首页 文章

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

提问于
浏览
166

我希望能够在加载时为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() 之类的东西不是一个选项

7 回答

  • 266

    last thing on the Laravel Eloquent doc page是:

    protected $appends = array('is_admin');
    

    这可以自动用于向模型添加新的访问器,而无需像修改 ::toArray() 之类的方法那样进行任何额外的工作 .

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

  • 13

    如果您将 getAvailability() 方法重命名为 getAvailableAttribute() ,则您的方法将变为 accessor ,并且您将能够在模型上使用 ->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 ....
        }
    }
    

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

  • 32

    问题是由于 ModeltoArray() 方法忽略了与基础表中的列没有直接关系的任何访问器 .

    正如泰勒奥特威尔提到here,"This is intentional and for performance reasons."但是有一种简单的方法可以达到这个目的:

    class EventSession extends Eloquent {
    
        protected $table = 'sessions';
        protected $appends = array('availability');
    
        public function getAvailabilityAttribute()
        {
            return $this->calculateAvailability();  
        }
    }
    

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

    Old answer (for Laravel versions < 4.08):

    我发现的最佳解决方案是覆盖 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);    
        }
    
    }
    

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

    class Book extends Eloquent {
    
        protected $table = 'books';
    
        public function toArray()
        {
            $array = parent::toArray();
            foreach ($this->getMutatedAttributes() as $key)
            {
                if ( ! array_key_exists($key, $array)) {
                    $array[$key] = $this->{$key};   
                }
            }
            return $array;
        }
    
        public function getUpperAttribute()
        {
            return strtoupper($this->title);    
        }
    
    }
    
  • 104

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

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

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

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

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

    并使用 is_paused 来获取或使用视图中的属性 .

  • 11

    我有一些类似的东西:我的模型中有一个属性图片,它包含文件在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);
    }
    
  • 1

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

相关问题