Putting eloquent results in another table to doing where queries in Laravel 5.4
由于某些特殊原因,我在模型中使用了附加属性,现在当我要对自定义属性进行
要解决此问题,我想如果将查询结果放入临时表中,我可以做我想做的事情!
有人对此有任何想法吗?如果对我有用,如何将结果传输到临时表?
您将无法使用模型访问器的动态字段来限制数据库查询,因为该字段在数据库中显然不存在。
但是,Collection对象具有相当强大的过滤功能,因此您可以在查询数据库之后使用动态字段来过滤Collection结果。这不像在从数据库中检索结果之前过滤掉结果那样有表现力,但是您可能会遇到这样的情况:性能不是那么关键,或者代码的清洁/维护成本超过了性能成本。
作为示例,给定以下模型:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | class Book extends Model { public function getCategoryAttribute() { if ($this->targetAge < 13) { return 'child'; } if ($this->targetAge < 18) { return 'teen'; } return 'adult'; } } |
以下查询将不起作用,因为表中实际上不存在
1 | $childrenBooks = Book::where('category', 'child')->get(); // error: no category field |
但是,以下操作将起作用,因为您正在从数据库返回的模型集合上调用
1 | $childrenBooks = Book::get()->where('category', 'child'); |
在这种情况下的问题是,尽管它确实起作用,但是它将从数据库中获取所有书籍,并为每个书籍创建一个Model实例,然后通过该完整Collection进行过滤。但是,这样做的好处是您不必在访问器方法中重复逻辑。在这里,您需要权衡利弊,并确定在您的情况下这是否可以接受。
一个中间选项是创建一个Model作用域方法,以便您的访问器逻辑仅在一个地方重复(如果可以为查询重复):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | class Book extends Model { public function getCategoryAttribute() { if ($this->targetAge < 13) { return 'child'; } if ($this->targetAge < 18) { return 'teen'; } return 'adult'; } public function scopeCategory($query, $category) { if ($category == 'child') { return $query->where('target_age', '<', 13); } if ($category == 'teen') { return $query->where(function ($query) { return $query ->where('target_age', '>=', 13) ->where('target_age', '<', 18); }); } return $query->where('target_age', '>=', 18); } } |
然后您可以像下面这样使用此查询范围:
1 | $childrenBooks = Book::category('child')->get(); |
这里的好处是该逻辑适用于实际查询,因此在从数据库返回记录之前限制了记录。主要的问题是,现在一次在访问器中一次在作用域中重复了您的"类别"逻辑。此外,仅当您可以将访问器逻辑转换为可由数据库查询处理的内容时,此方法才有效。
您可以使用原始语句创建临时表。这篇文章对它进行了相当深入的介绍:
https://laracasts.com/discuss/channels/laravel/how-to-implement-temporary-table