【问题标题】:Add a custom attribute to a Laravel / Eloquent model on load?在加载时向 Laravel / Eloquent 模型添加自定义属性?
【发布时间】:2013-06-18 10:27:29
【问题描述】:

我希望能够在加载 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' 不是基础表中的字段。
  • $sessions 作为 API 的一部分作为 JSON 对象返回,因此不能在模板中调用 $session->available() 之类的东西

【问题讨论】:

    标签: php orm laravel eloquent


    【解决方案1】:

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

    <?php
    ...
    
    class Movie extends Model{
    
        protected $appends = ['cover'];
    
        //define accessor
        public function getCoverAttribute()
        {
            return json_decode($this->InJson)->cover;
        }
    
    

    【讨论】:

      【解决方案2】:

      在我的订阅模型中,我需要知道订阅是否已暂停。 这是我的做法

      public function getIsPausedAttribute() {
          $isPaused = false;
          if (!$this->is_active) {
              $isPaused = true;
          }
      }
      

      然后在视图模板中,我可以使用 $subscription-&gt;is_paused 得到结果。

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

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

      【讨论】:

        【解决方案3】:

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

        //Add extra attribute
        protected $attributes = ['picture_data'];
        
        //Make it available in the json response
        protected $appends = ['picture_data'];
        
        //implement the attribute
        public function getPictureDataAttribute()
        {
            $file = Storage::get($this->picture);
            $type = Storage::mimeType($this->picture);
            return "data:" . $type . ";base64," . base64_encode($file);
        }
        

        【讨论】:

          【解决方案4】:

          假设您的用户表中有 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;
          

          【讨论】:

          • 你是怎么从 getFullNameAttribute 变成 full_name 的?
          • @natghi Laravel 将去掉“get”和“Attribute”,留下“FullName”。然后它将它转换为snake_case,因此是full_name
          【解决方案5】:

          last thing on the Laravel Eloquent doc page 是:

          protected $appends = array('is_admin');
          

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

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

          【讨论】:

          【解决方案6】:

          如果您将 getAvailability() 方法重命名为 getAvailableAttribute(),您的方法将成为 访问器,您将能够直接在模型上使用 -&gt;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 ....
              }
          }
          

          我没有测试它,但在你当前的设置中尝试应该很简单。

          【讨论】:

          • 这可以使-&gt;available$session 对象上可用,但由于$sessions 直接转换为JSON 字符串(它是API 的一部分),所以没有'没有机会使用它。
          • 我不确定我是否理解你的东西是如何工作的。如果EventSession::all() 从 API 返回一个 JSON 对象,那么你并没有真正使用 Laravel 模型,对吧?抱歉,我对您如何实现模型感到困惑。
          • EventSession 是一个标准的 Eloquent 对象 (class EventSession extends Eloquent)。 ::all() 只是一个例子。 EventSession::find(170071) 将是另一个。这些在整个 SessionController (SessionController extends \BaseController) 的各个点被调用,这些点将通过诸如“/sessions/170071”之类的 URL 调用。
          • 我认为关键可能在于 Eloquent 的内置对象到发生的 JSON 转换。即使您向模型添加了自定义属性(例如 public $available),转换对象时也不会显示。
          • 自 2013 年 10 月 8 日 Laravel 4.0.8 发布后可用。请参阅官方文档:laravel.com/docs/eloquent#converting-to-arrays-or-json(查找 protected $appends = array('is_admin');
          【解决方案7】:

          问题是由于ModeltoArray() 方法忽略了与基础表中的列不直接相关的任何访问器。

          正如 Taylor Otwell 提到的 here,“这是出于性能考虑。”但是有一种简单的方法可以实现这一点:

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

          只要您添加了适当的访问器,$appends 属性中列出的任何属性都将自动包含在模型的数组或 JSON 形式中。

          旧答案(适用于 Laravel 版本

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

          【讨论】:

          • 今天的最佳问答。我正在研究如何实现这一目标的不同实现,就在 laravel.io 上发布问题之前,我发现了这个!耶!!!
          • 有没有办法在某些情况下不将它们添加到 json 中?
          • 通过关系调用模型时,这些海关属性似乎没有出现。 (例如:Models\Company::with('people'))。有什么想法吗?
          • @JordiPuigdellívol 在 Laravel 5 中,您可以使用 protected $hidden = [] 添加要排除的列/访问器。
          • 晚安,先生。我想知道我的案例here 是否可以通过这种解决方案实现。亲爱的先生,我可以向您寻求帮助吗?
          【解决方案8】:

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

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

          【讨论】:

            【解决方案9】:

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

            【讨论】:

              猜你喜欢
              • 2015-09-23
              • 1970-01-01
              • 2015-12-01
              • 2020-11-23
              • 1970-01-01
              • 2015-11-15
              • 2011-02-18
              • 2023-03-09
              • 2017-03-31
              相关资源
              最近更新 更多