在加载时将自定义属性添加到Laravel / Eloquent模型?

时间:2013-06-21 10:13:21

标签: php orm laravel eloquent

我希望能够在加载时为Laravel / Eloquent模型添加自定义属性/属性,类似于使用RedBean's $model->open()方法实现的方式。

例如,目前,在我的控制器中,我有:

public function index()
{
    $sessions = EventSession::all();
    foreach ($sessions as $i => $session) {
        $sessions[$i]->available = $session->getAvailability();
    }
    return $sessions;
}

能够省略循环并且已经设置和填充'available'属性会很好。

我尝试使用文档中描述的一些模型事件在对象加载时附加此属性,但到目前为止没有成功。

注意:

  • 'available'不是基础表中的字段。
  • $sessions作为API的一部分作为JSON对象返回,因此在模板中调用类似$session->available()的内容不是一个选项

9 个答案:

答案 0 :(得分:281)

问题是由于Model的{​​{1}}方法忽略了与基础表中的列没有直接关系的任何访问器这一事实。

正如泰勒奥特威尔所提到的here,“这是故意的,也是出于表现的原因。”但是,有一种简单的方法可以实现这一目标:

toArray()

$ appends属性中列出的任何属性都将自动包含在模型的数组或JSON格式中,前提是您已添加了相应的访问者。

旧答案(适用于Laravel版本< 4.08):

我发现的最佳解决方案是覆盖class EventSession extends Eloquent { protected $table = 'sessions'; protected $appends = array('availability'); public function getAvailabilityAttribute() { return $this->calculateAvailability(); } } 方法,并明确设置属性:

toArray()

或者,如果您有许多自定义访问器,请循环遍历它们并应用它们:

class Book extends Eloquent {

    protected $table = 'books';

    public function toArray()
    {
        $array = parent::toArray();
        $array['upper'] = $this->upper;
        return $array;
    }

    public function getUpperAttribute()
    {
        return strtoupper($this->title);    
    }

}

答案 1 :(得分:112)

last thing on the Laravel Eloquent doc page是:

protected $appends = array('is_admin');

可以自动使用它来为模型添加新的访问器,而无需修改::toArray()等方法。

只需创建getFooBarAttribute(...)访问者并将foo_bar添加到$appends数组即可。

答案 2 :(得分:35)

如果您将getAvailability()方法重命名为getAvailableAttribute(),您的方法将变为访问者,并且您将能够使用->available直接在您的模型上阅读

文档:https://laravel.com/docs/5.4/eloquent-mutators#accessors-and-mutators

编辑:由于您的属性是“虚拟”,因此默认情况下它不会包含在您对象的JSON表示中。

但我发现了这个:Custom model accessors not processed when ->toJson() called?

为了强制在数组中返回属性,请将其作为$ attributes数组的键添加。

class User extends Eloquent {
    protected $attributes = array(
        'ZipCode' => '',
    );

    public function getZipCodeAttribute()
    {
        return ....
    }
}

我没有对它进行测试,但对于您尝试当前的设置应该是非常简单的。

答案 3 :(得分:16)

步骤1:在$appends中定义属性
步骤2:为该属性定义访问器。
示例:

<?php
...

class Movie extends Model{

    protected $appends = ['cover'];

    //define accessor
    public function getCoverAttribute()
    {
        return json_decode($this->InJson)->cover;
    }

答案 4 :(得分:13)

您可以在模型中使用setAttribute函数添加自定义属性

答案 5 :(得分:12)

我有类似的东西: 我的模型中有一个属性图片,它包含Storage文件夹中文件的位置。 图像必须返回base64编码

//Add extra attribute
protected $attributes = ['pictureData'];

//Make it available in the json response
protected $appends = ['pictureData'];

//implement the attribute
public function getPictureDataAttribute()
{
    $file = Storage::get($this->picture);
    $type = Storage::mimeType($this->picture);
    return "data:" . $type . ";base64," . base64_encode($file);
}

答案 6 :(得分:5)

假设您的用户表中有2个名为first_name和last_name的列,并且您想检索全名。您可以使用以下代码实现:

class User extends Eloquent {


    public function getFullNameAttribute()
    {
        return $this->first_name.' '.$this->last_name;
    }
}

现在您可以获得全名:

$user = User::find(1);
$user->full_name;

答案 7 :(得分:1)

在我的情况下,创建一个空列并设置其访问器工作正常。 我的访问者从dob列填充用户的年龄。 toArray()函数也有效。

public function getAgeAttribute()
{
  return Carbon::createFromFormat('Y-m-d', $this->attributes['dateofbirth'])->age;
}

答案 8 :(得分:0)

在我的订阅模式中,我需要知道订阅是否已暂停。 我是这样做的     public function getIsPausedAttribute() { $isPaused = false; if (!$this->is_active) { $isPaused = true; } }

然后在视图模板中,我可以使用 $subscription->is_paused获得结果。

getIsPausedAttribute是设置自定义属性的格式

并使用is_paused在视图中获取或使用该属性。