空字符串而不是空值Eloquent

Isr*_*uño 30 php laravel laravel-4

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

$new = new Contact(Input::all());
$new->save();
Run Code Online (Sandbox Code Playgroud)

问题是这样,每个字段用空字符串填充而不是null我预期的值.

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

此外,我在这个表中有大约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' => ...
    ...
));
Run Code Online (Sandbox Code Playgroud)

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

更新到现在为止,我已经整理了App::before()过滤器中的array_filter .

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

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

在我的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)));
    }
}
Run Code Online (Sandbox Code Playgroud)

现在只处理以"_id"结尾的字段.这是我最大的问题,如果关系不是NULL,数据库将抛出错误,因为无法找到外键"".

工作完美.任何意见?

Tri*_*rip 61

我自己已经找到了答案,而我最接近的就是使用Mutators(http://laravel.com/docs/eloquent#accessors-and-mutators).

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

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

对于一个包含大量外键的表,这可能会变得笨重,但它是我发现处理这个问题的最"内置"方法.好处是它很神奇,所以你所要做的就是创造方法,你很高兴.

  • 这是适当的Laravel解决方案.这就是Eloquent中存在Accessors和Mutators的原因.它还可以更准确地控制设置为"null"的内容,而不是像接受的答案那样将"将所有内容设置为空". (10认同)
  • 这个答案+1.这绝对是分配null键的正确方法.使您可以更好地控制各个列.如果您必须更改列默认值或类似的内容,这也将是有益的. (5认同)

Rub*_*zzo 19

Laravel 4

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

$input = array_filter(Input::all(), 'strlen');
Run Code Online (Sandbox Code Playgroud)

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

据我所知,如果数组中没有为质量分配指定一个字段,那么Laravel Eloquent ORM会将其视为NULL.


Laravel 5

$input = array_filter(Request::all(), 'strlen');
Run Code Online (Sandbox Code Playgroud)

要么

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

  • 你是对的@JasonLewis但是...使用`array_filter`本身将过滤掉所有*falsy*值.如果你有一个'0`作为一个字符串值,它将被过滤掉,也许这不是预期的结果. (6认同)
  • 请注意,这不适用于更新操作,因为将忽略用户重置的字段,并保留以前的值.在这种情况下,可以使用类似的方法:``$ input = array_map(function($ e){return $ e?:null;},Input :: all());``` (5认同)

Kon*_*kin 11

可能更通用的解决方案:

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

    }

}
Run Code Online (Sandbox Code Playgroud)

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

class SomeModel extends EloquentBaseModel {
    protected $forcedNullFields = ['BirthDate','AnotherNullableField'];
}
Run Code Online (Sandbox Code Playgroud)

这就是全部,你不应该在mutators中重复相同的代码.


cra*_*ock 10

使用模型"save"事件查找空模型并将其显式设置为null."Project"是此示例中我的模型的名称.将它放在辅助功能中并将其连接到所有型号.

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

    return true;
});
Run Code Online (Sandbox Code Playgroud)

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

除了在将数据发送到数据库之前清理数据之外,我还最终创建了一个Http Middleware来清除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);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 使用此代码一段时间之后..小心它.它有一个有趣的副作用.它会在每次更新时将值设置为null.这可能会产生意想不到的后果.检查值是否已从其原始状态更改可能会很好. (3认同)