Laravel 4 中的通用访问器和修改器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22482310/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 09:12:42  来源:igfitidea点击:

Universal accessors and mutators in Laravel 4

phplaravel

提问by tprsn

I know it's possible to define accessors and mutators for individual fields, like so:

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

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

But is it possible to define a fallback method that will be used for allattribute gets and sets?

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

The reason being that I want to convert any empty values to null values on the fly, to keep my database clean and allow nullable fields to be null instead of an empty string (if there's a better way to do this let me know!)

原因是我想即时将任何空值转换为空值,以保持我的数据库干净并允许可空字段为空而不是空字符串(如果有更好的方法来做到这一点,请告诉我!)

I'm looking for something like

我正在寻找类似的东西

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

UPDATE:

更新:

Thanks to Chris Goosey I've found a solution that works for me. I extended the Eloquent model method setAttribute, and I set the value to the column default if it's empty. That's usually null, zero or an empty string in my databases so works for me!

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

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);
}

回答by Chris Goosey

Best way is probably to extend the Eloquent class overwriting the setAttribute and getAttribute methods.

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

For all your models to inherit these overwritten methods you would want to create a class that extends eloquent e.g.

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

<?php 

class BaseModel extends eloquent {

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

    public function getAttribute($key) {
        // Do Stuff
    }
}

and then all your models should extend from this new class, e.g.

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

<?php

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

It is also worth mentioning your new methods should have all the functionality of the old method plus your new functionality, this is what the getAttribute() looks like (Illuminate\Database\Eloquent line 2212):

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

and the setAttribute in the same file looks like this (line 2338):

并且同一文件中的 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;
}

Hope this helps!

希望这可以帮助!