由于某些特殊原因,我在模型中使用了append属性,现在当我想对自定义属性进行where
查询时,例如“ category ”,我遇到了一个错误这意味着eloquent找不到具有“ category ”名称的列!
要解决这个问题,我想如果我将查询结果放入临时表中,我可以做我想做的事情!
有人有任何想法吗?如果它对我有用,我如何将结果传送到临时表?
答案 0 :(得分:1)
您将无法使用Model访问者的动态字段限制数据库查询,因为该字段显然不存在于数据库中。
但是,Collection对象具有相当强大的过滤功能,因此您可以在查询数据库后使用动态字段过滤Collection结果。这不像在从数据库中检索结果之前过滤掉结果那样高效,但是您可能会遇到性能不那么重要或者代码清洁/维护成本超过性能成本的情况。
举个例子,给出以下模型:
class Book extends Model
{
public function getCategoryAttribute()
{
if ($this->targetAge < 13) {
return 'child';
}
if ($this->targetAge < 18) {
return 'teen';
}
return 'adult';
}
}
以下查询无效,因为表中实际不存在category
字段:
$childrenBooks = Book::where('category', 'child')->get(); // error: no category field
但是,以下方法可行,因为您在从数据库返回的模型集合上调用where()
,并且模型可以访问动态字段:
$childrenBooks = Book::get()->where('category', 'child');
在这种情况下的问题是,虽然它确实有效,但它将从数据库中获取所有书籍并为每个书籍创建一个Model实例,然后筛选完整的Collection。但是,好处是您不必复制访问器方法中的逻辑。在这里,您需要权衡利弊,并确定在您的情况下这是否可以接受。
中间选项是创建一个模型范围方法,这样您的访问者逻辑只能在一个地方重复(如果它可以复制查询):
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);
}
}
然后您可以像这样使用此查询范围:
$childrenBooks = Book::category('child')->get();
这里的好处是逻辑适用于实际查询,因此记录在从数据库返回之前是有限的。主要问题是现在你的“类别”逻辑是重复的,一次是在一个访问器中,一次是在一个范围内。此外,这只有在您可以将访问者逻辑转换为可由数据库查询处理的内容时才有效。
答案 1 :(得分:0)
您可以使用原始语句创建临时表。这篇文章相当深入:
https://laracasts.com/discuss/channels/laravel/how-to-implement-temporary-table