【问题标题】:Universal accessors and mutators in Laravel 4Laravel 4 中的通用访问器和修改器
【发布时间】:2014-04-24 07:23:09
【问题描述】:

我知道可以为单个字段定义访问器和修改器,如下所示:

public function setSomeAttribute($value) {
    // set the attribute
}
public function getSomeAttribute() {
    // return the attribute}
}

但是是否可以定义一个用于所有属性获取和设置的后备方法?

原因是我想即时将任何空值转换为空值,以保持数据库清洁并允许可空字段为空而不是空字符串(如果有更好的方法可以让我知道!)

我正在寻找类似的东西

public function setAttribute($property,$value) {
    $this->$property = empty($value) ? null : $value;
}

更新:

感谢 Chris Goosey,我找到了适合我的解决方案。我扩展了 Eloquent 模型方法 setAttribute,如果它为空,我将值设置为列默认值。在我的数据库中,这通常是 null、零或空字符串,所以对我有用!

public function setAttribute($key, $value)
{
    // Convert empty values to their default values (e.g. null, zero)
    if(empty($value) && $this->getSchema()->hasColumn($key)) {
        $value = $this->getSchema()->getColumn($key)->getDefault();
    }
    parent::setAttribute($key,$value);
}

【问题讨论】:

    标签: php laravel


    【解决方案1】:

    最好的方法可能是扩展 Eloquent 类,覆盖 setAttribute 和 getAttribute 方法。

    为了让您的所有模型都继承这些被覆盖的方法,您可能需要创建一个扩展 eloquent 的类,例如

    <?php 
    
    class BaseModel extends eloquent {
    
        public function setAttribute($property,$value) {
            $this->$property = empty($value) ? null : $value;
        }
    
        public function getAttribute($key) {
            // Do Stuff
        }
    }
    

    然后你的所有模型都应该从这个新类扩展,例如

    <?php
    
    class User extends BaseModel {
        protected $table = 'users';
    }
    

    还值得一提的是,您的新方法应该具有旧方法的所有功能以及您的新功能,这就是 getAttribute() 的样子(Illuminate\Database\Eloquent line 2212):

    /**
     * Get an attribute from the model.
     *
     * @param  string  $key
     * @return mixed
     */
    public function getAttribute($key)
    {
        $inAttributes = array_key_exists($key, $this->attributes);
    
        // If the key references an attribute, we can just go ahead and return the
        // plain attribute value from the model. This allows every attribute to
        // be dynamically accessed through the _get method without accessors.
        if ($inAttributes || $this->hasGetMutator($key))
        {
            return $this->getAttributeValue($key);
        }
    
        // If the key already exists in the relationships array, it just means the
        // relationship has already been loaded, so we'll just return it out of
        // here because there is no need to query within the relations twice.
        if (array_key_exists($key, $this->relations))
        {
            return $this->relations[$key];
        }
    
        // If the "attribute" exists as a method on the model, we will just assume
        // it is a relationship and will load and return results from the query
        // and hydrate the relationship's value on the "relationships" array.
        $camelKey = camel_case($key);
    
        if (method_exists($this, $camelKey))
        {
            return $this->getRelationshipFromMethod($key, $camelKey);
        }
    }
    

    并且同一个文件中的 setAttribute 看起来像这样(第 2338 行):

    /**
     * Set a given attribute on the model.
     *
     * @param  string  $key
     * @param  mixed   $value
     * @return void
     */
    public function setAttribute($key, $value)
    {
        // First we will check for the presence of a mutator for the set operation
        // which simply lets the developers tweak the attribute as it is set on
        // the model, such as "json_encoding" an listing of data for storage.
        if ($this->hasSetMutator($key))
        {
            $method = 'set'.studly_case($key).'Attribute';
    
            return $this->{$method}($value);
        }
    
        // If an attribute is listed as a "date", we'll convert it from a DateTime
        // instance into a form proper for storage on the database tables using
        // the connection grammar's date format. We will auto set the values.
        elseif (in_array($key, $this->getDates()))
        {
            if ($value)
            {
                $value = $this->fromDateTime($value);
            }
        }
    
        $this->attributes[$key] = $value;
    }
    

    希望这会有所帮助!

    【讨论】:

    • 太棒了!这正是我要找的,谢谢!我已经用我的最终代码更新了我的问题。
    • 看起来这会覆盖各个模型中的任何更具体的 setAttributes。反正有这个吗?
    • 如果各个模型具有 setAttribute() 或 getAttribute() 函数,它们将覆盖 BaseModel 中的任何此类函数。是什么让您认为 BaseModel 覆盖了单个模型?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-20
    相关资源
    最近更新 更多