Laravel 4中的通用存取器和变换器

tpr*_*rsn 10 php laravel

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

public function setSomeAttribute($value) {
    // set the attribute
}
public function getSomeAttribute() {
    // return the attribute}
}
Run Code Online (Sandbox Code Playgroud)

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

原因是我想动态地将任何空值转换为空值,以保持我的数据库清洁并允许可空字段为空而不是空字符串(如果有更好的方法,请告诉我!)

我正在寻找类似的东西

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

更新:

感谢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);
}
Run Code Online (Sandbox Code Playgroud)

小智 11

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

对于所有模型继承这些重写方法,您可能希望创建一个扩展雄辩的类,例如

<?php 

class BaseModel extends eloquent {

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

    public function getAttribute($key) {
        // Do Stuff
    }
}
Run Code Online (Sandbox Code Playgroud)

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

<?php

class User extends BaseModel {
    protected $table = 'users';
}
Run Code Online (Sandbox Code Playgroud)

还值得一提的是,您的新方法应该具有旧方法的所有功能以及您的新功能,这就是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);
    }
}
Run Code Online (Sandbox Code Playgroud)

并且同一文件中的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;
}
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助!