php 空字符串而不是空值 Eloquent

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17452923/
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-08-25 12:55:03  来源:igfitidea点击:

Empty string instead of null values Eloquent

phplaravellaravel-4

提问by Israel Ortu?o

I'm trying to create entities using mass-assignment Eloquent feature...

我正在尝试使用批量分配 Eloquent 功能创建实体...

$new = new Contact(Input::all());
$new->save();

The problem's that this way, every field's filled out with an empty string instead of nullvalues as I expected.

问题是这样,每个字段都填充了一个空字符串,而不是null我预期的值。

I'm currently developing the system and still some table columns're not defined, that's why using this method, to avoid adding every new field to $fillablearray and to a new Contact(array(...));...

我目前正在开发系统,但仍然没有定义一些表列,这就是为什么使用这种方法,以避免将每个新字段添加到$fillable数组和new Contact(array(...));...

Also I've around 20 fields in this table, so It'd be a bit ugly to have an array such as

另外我在这个表中有大约 20 个字段,所以有一个数组会有点难看,比如

$new = new Contact(array(
    'salutation' => Input::get('salutation'),
    'first_name' => Input::get('first_name'),
    'last_name'  => Input::get('last_name'),
    'company_id' => Input::get('company_id'),
    'city' => ...
    ...
));

Any tips of how to do this or fix?

有关如何执行此操作或修复的任何提示?

UpdateBy now I've sorted out this doing the array_filter in the App::before()filter.

更新到目前为止,我已经在App::before()过滤器中对 array_filter 进行了整理。

UpdateIn filter was a bit mess. I end up doing:

更新过滤器有点乱。我最终做了:

public static function allEmptyIdsToNull()
{
    $input = Input::all();

    $result = preg_grep_keys ( '/_id$/' , $input );

    $nulledResults = array_map(function($item) {
        if (empty($item))
            return null;

        return $item;
    }, $result);

    return array_merge($input, $nulledResults);
}

And in my functions.php.

在我的functions.php 中。

if ( ! function_exists('preg_grep_keys'))
{
    /**
    * This function gets does the same as preg_grep but applies the regex
    * to the array keys instead to the array values as this last does.
    * Returns an array containing only the keys that match the exp.
    * 
    * @author Daniel Klein
    * 
    * @param  string  $pattern
    * @param  array  $input
    * @param  integer $flags
    * @return array
    */
    function preg_grep_keys($pattern, array $input, $flags = 0) {
        return array_intersect_key($input, array_flip(preg_grep($pattern, array_keys($input), $flags)));
    }
}

By now only working with fields that ends with "_id". This is my biggest problem as if a relationship is not NULL, the database will throw an error as the foreign key "" cannot be found.

现在只处理以“_id”结尾的字段。这是我最大的问题,好像没有关系一样NULL,数据库将抛出错误,因为找不到外键“”。

Works perfect. Any comment?

工作完美。任何意见?

采纳答案by craig.tadlock

Use the model 'saving' event to look for empty models and explicitly set them to null. 'Project' is the name of my model in this example. Put this in a helper function and wire it up to all your models.

使用模型“保存”事件查找空模型并将它们显式设置为空。在这个例子中,'Project' 是我的模型的名称。把它放在一个辅助函数中并将它连接到你的所有模型。

Project::saving(function($model) {
    foreach ($model->toArray() as $name => $value) {
        if (empty($value)) {
            $model->{$name} = null;
        }
    }

    return true;
});

UPDATE FOR LARAVEL 5 (April 11 2016)

Laravel 5 更新(2016 年 4 月 11 日)

I also ended up creating an Http Middleware to cleanup the input data from the http request, in addition to cleaning up the data before it is sent to the database.

除了在将数据发送到数据库之前清理数据之外,我还最终创建了一个 Http 中间件来清理来自 http 请求的输入数据。

class InputCleanup
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        $input = $request->input();

        array_walk_recursive($input, function(&$value) {

            if (is_string($value)) {
                $value = StringHelper::trimNull($value);
            }
        });

        $request->replace($input);

        return $next($request);
    }
}

回答by Trip

I've looked for the answer to this myself, and the closest I can come up with is using Mutators (http://laravel.com/docs/eloquent#accessors-and-mutators).

我自己一直在寻找答案,我能想到的最接近的方法是使用 Mutators ( http://laravel.com/docs/eloquent#accessors-and-mutators)。

The same problem was solved by adding a (magic!) Mutator method for the foreign key field in the model:

通过为模型中的外键字段添加(神奇!)Mutator 方法解决了同样的问题:

public function setHeaderImageIdAttribute($value)
{
    $this->attributes['header_image_id'] = $value ?: null;
}

For a table with a lot of foreign keys, this can get kind of bulky, but it's the most "built-in" method I've found for handling this. The upside is that it's magic, so all you have to do is create the method and you're good to go.

对于有很多外键的表,这可能会变得有点笨重,但这是我发现的最“内置”的方法来处理这个问题。好处是它很神奇,所以你所要做的就是创建方法,你就可以开始了。

UPDATE -- Laravel 5.4 and above

更新——Laravel 5.4 及以上

As of Laravel 5.4, the \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::classmiddleware handles this when the request is received. In my example above, if the request contains an empty string value for 'header_image_id', this middleware automatically converts it to nullbefore I can assign it to my model.

从 Laravel 5.4 开始,\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class中间件会在收到请求时进行处理。在我上面的示例中,如果请求中包含一个空字符串值“header_image_id”,此中间件会自动将其转换为 ,null然后我才能将其分配给我的模型。

回答by Rubens Mariuzzo

Laravel 4

Laravel 4

If it is necessary you could remove any empty string in an array by filtering.

如果有必要,您可以通过过滤删除数组中的任何空字符串。

$input = array_filter(Input::all(), 'strlen');

Then if you have something like array('a' => 'a', 'b' => '')you will get: array('a' => 'a').

然后,如果你有类似的东西,array('a' => 'a', 'b' => '')你会得到:array('a' => 'a').

As far as I know, if a field is not specified in the array for mass-assignment, then Laravel Eloquent ORM will treat it like NULL.

据我所知,如果一个字段没有在数组中指定用于批量赋值,那么 Laravel Eloquent ORM 会将其视为NULL.



Laravel 5

Laravel 5

$input = array_filter(Request::all(), 'strlen');

or

或者

// If you inject the request.
$input = array_filter($request->all(), 'strlen');

回答by Konstantin ?uvakin

Probably more generic solution:

可能更通用的解决方案:

class EloquentBaseModel extends Eloquent {

    public static function boot()
    {
        parent::boot();

        static::saving(function($model)
        {
            if (count($model->forcedNullFields) > 0) {
                foreach ($model->toArray() as $fieldName => $fieldValue) {
                    if ( empty($fieldValue) && in_array($fieldName,$model->forcedNullFields)) {
                        $model->attributes[$fieldName] = null;
                    }
                }
            }

            return true;
        });

    }

}

The model where you needs to sanitize empty form fields should extends this class, then you should fill $forcedNullFields array with field names that required to be NULL in case of empty form fields:

您需要清理空表单字段的模型应该扩展此类,然后您应该使用字段名称填充 $forcedNullFields 数组,这些字段名称在空表单字段的情况下需要为 NULL:

class SomeModel extends EloquentBaseModel {
    protected $forcedNullFields = ['BirthDate','AnotherNullableField'];
}

And thats all, you should not repeat same code in mutators.

就是这样,你不应该在 mutator 中重复相同的代码。

回答by Vedmant

Another simple solution is to create base model class and extend models from it:

另一个简单的解决方案是创建基础模型类并从中扩展模型:

class Model extends \Illuminate\Database\Eloquent\Model
{
    /**
     * Set field to null if empty string
     *
     * @var array
     */
    protected $forcedNullFields = [];

    /**
     * Set a given attribute on the model.
     *
     * @param  string  $key
     * @param  mixed  $value
     * @return \Illuminate\Database\Eloquent\Model
     */
    public function setAttribute($key, $value)
    {
        if (in_array($key, $this->forcedNullFields) && $value === '') {
            $value = null;
        }

        return parent::setAttribute($key, $value);
    }
}

Then just fill required fields in $forcedNullFields for each model if needed.

然后,如果需要,只需为每个模型填写 $forcedNullFields 中的必填字段。

回答by Nico Kaag

For a form input, it's normal, and more logical to have empty values, rather then null values.

对于表单输入,有空值而不是空值是正常的,也更合乎逻辑。

If you really think the best way to do this, is to directly put the input into your database, than the solution to make empty values null would be something like this.

如果您真的认为最好的方法是直接将输入放入您的数据库中,那么将空值设为 null 的解决方案将是这样的。

$input = Input::all();
foreach ($input as &$value) {
    if (empty($value) { $value = null; }
}
$new = new Contact(Input::all());
$new->save();

Personally I don't approve with these kind of solutions, but it does work for some people.

我个人不赞成这些解决方案,但它确实适用于某些人。

回答by Half Crazed

In your Eloquent model, make sure $guardedis empty. You don't need to set $fillable.

在您的 Eloquent 模型中,确保$guarded为空。您无需设置$fillable.

Mass assignment isn't usually a good idea, but it's OK to do in some scenarios - you must determine when.

批量分配通常不是一个好主意,但在某些情况下可以这样做 - 您必须确定何时。

See: http://laravel.com/docs/eloquent#mass-assignment

请参阅:http: //laravel.com/docs/eloquent#mass-assignment