使用Eloquent ORM自定义方法链接?

时间:2017-02-11 23:23:55

标签: php laravel eloquent

这是我目前的查询:

$cars = Cars::with('brand')->get();

$cars->map(function($cars){

    $cars->fullName = $cars->brand->brand." ".$cars->name;
    //other manipulation...
    return $cars;
});

我想在模型中操作我的集合,以便我可以运行$cars = Cars::with('brand')->getWithBrand();

之类的东西

我该怎么做呢,所以每次运行查询时都不必编写地图函数?

1 个答案:

答案 0 :(得分:1)

在您的特定示例中,您根本不需要使用map来修改Collection。您可以使用Eloquent accessor在模型上定义数据库中不存在的属性。在您的示例中,您将在Cars模型上定义以下方法:

public function getFullNameAttribute($value)
{
    // make sure brand exists first
    if ($this->brand) {
        return $this->brand->brand.' '.$this->name;
    }

    // default if brand doesn't exist
    return $this->name;
}

通过在Model上定义该函数,只要您尝试使用full_name属性,就会调用该函数,如下面的代码所示:

$car = Cars::with('brand')->first();

// this will echo the result of the getFullNameAttribute method
echo $car->full_name;

修改

如果您还希望此新属性自动显示在toArray()toJson()输出中,则可以将该属性添加到$appends Cars属性中模型:

class Cars extends Model
{
    protected $appends = ['full_name'];

    public function getFullNameAttribute($value)
    {
        // make sure brand exists first
        if ($this->brand) {
            return $this->brand->brand.' '.$this->name;
        }

        // default if brand doesn't exist
        return $this->name;
    }
}

但请注意,您的自定义属性取决于相关对象。因此,如果您在没有急切加载toArray()关系的汽车集合上做了一些意外调用toJson()__toString()brand等的事情,这将导致N + 1查询问题。

例如:

// Bad: N+1 issue because each printed Car will execute a
// separate query to get its brand to output full_name.
echo Cars::get();

// Good: No N+1 issue because all brands are already loaded.
echo Cars::with('brand')->get();