Php 空字符串而不是空值

Php 空字符串而不是空值,php,laravel,laravel-4,Php,Laravel,Laravel 4,我正在尝试创建实体使用质量分配雄辩的功能 $new = new Contact(Input::all()); $new->save(); 问题在于,通过这种方式,每个字段都用空字符串填充,而不是像我预期的那样用null值填充 我目前正在开发该系统,但仍有一些表列未定义,这就是为什么使用此方法,以避免将每个新字段添加到$filleble数组和新联系人(数组(…) 另外,我在这个表中有大约20个字段,所以使用这样的数组会有点难看 $new = new Contact(array( '

我正在尝试创建实体使用质量分配雄辩的功能

$new = new Contact(Input::all());
$new->save();
问题在于,通过这种方式,每个字段都用空字符串填充,而不是像我预期的那样用
null
值填充

我目前正在开发该系统,但仍有一些表列未定义,这就是为什么使用此方法,以避免将每个新字段添加到
$filleble
数组和
新联系人(数组(…)

另外,我在这个表中有大约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' => ...
    ...
));
有没有关于如何进行此操作或修复的提示

更新现在,我已经在
App::before()
过滤器中通过数组过滤器解决了这个问题

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

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);
}
在myfunctions.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)));
    }
}
现在只处理以“\u id”结尾的字段。这是我最大的问题,因为如果关系不是
NULL
,数据库将抛出错误,因为找不到外键“”


工作完美。有什么评论吗?

在您的雄辩模型中,确保
$guarded
为空。您不需要设置
$filleble

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


请参阅:

对于表单输入,使用空值而不是空值是正常的,更符合逻辑

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

$input = Input::all();
foreach ($input as &$value) {
    if (empty($value) { $value = null; }
}
$new = new Contact(Input::all());
$new->save();
就我个人而言,我不赞成这种解决方案,但它确实对某些人有效。

Laravel 4 如果有必要,可以通过筛选删除数组中的任何空字符串

然后,如果您有类似于
array('a'=>'a','b'=>'')
的内容,您将得到:
array('a'=>'a')

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


拉维尔5号 或


我自己也在寻找这个问题的答案,我能想到的最接近的方法就是使用突变子()

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

public function setHeaderImageIdAttribute($value)
{
    $this->attributes['header_image_id'] = $value ?: null;
}
对于一个有很多外键的表,这可能会有点笨重,但这是我找到的处理这个问题的最“内置”的方法。好的一面是它很神奇,所以你所要做的就是创建这个方法,然后你就可以开始了

更新——Laravel 5.4及以上版本


从Laravel 5.4开始,
\illumb\Foundation\Http\Middleware\ConvertEmptyStringsToull::class
中间件在收到请求时处理此问题。在我上面的示例中,如果请求包含“header\u image\u id”的空字符串值,则该中间件会自动将其转换为
null
,然后我才能将其分配给我的模型。

使用模型“saving”事件查找空模型,并显式将其设置为nullProject'是本例中我的模型的名称。将其放入一个助手函数中,并将其连接到所有模型

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

    return true;
});
LARAVEL 5的更新(2016年4月11日)

我还创建了一个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);
    }
}

可能是更通用的解决方案:

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

    }

}
需要清理空表单字段的模型应扩展此类,然后应使用字段名填充$forcedNullFields数组,如果表单字段为空,则字段名必须为NULL:

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

总之,您不应该在mutators中重复相同的代码。

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

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

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

我在进行批量分配时没有问题,只是在每个空表单字段将其值设置为
而不是
NULL
发布时是否存在这些字段?如果是,它们是空的吗?表列的迁移和/或默认值是什么样子的?当我发布时字段存在,这就是为什么我得到的是空值而不是
NULL
。主要问题已经提到below@RobW,OP只想清除那些发布的空值;将它们设置为
null
。如果它是您想要的空行,为什么不直接调用
Model::create(array())
?只需将空字符串直接存储到数据库中即可。毕竟,我不认为您会呈现空值…我也不接受空值,因为我正在处理ImnoDB、关系和约束。因此,如果FK不是
null
,则需要查找外部ID,即使它是
,这显然不存在于外部表中,并引发MySQL错误,例如
无法添加或更新子行:外键约束失败
@RubensMariuzzo您可能希望在数据库中使用空值是有原因的。例如我在数据库中存储一个带有序列化数据对象的字符串,如果数据尚未生成,则该值为null;如果数据已经生成,但没有要存储的数据,则该值为空字符串。Israel Ortuño:我实际上会写出所有字段,只是因为我认为最好将您得到的所有输入都“白名单”,这样您就永远不会处理您不想处理的数据。我已经尝试过这样做。。。但是仍然得到一个空字段作为
Input::get()
返回字段值(空),而不是
null
。尝试使用Input::get('sallation',null),我认为应该可以解决这个问题。这样,您也可以设置其他默认值,而无需执行if和else语句<代码>联系人::创建(Input::all())
ftw。我不是用这种方法获取空值吗?我认为它做的事情和做
$new=newcontact(Input::all())做的事情是一样的好主意。。。我一直在想
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;
        });

    }

}
class SomeModel extends EloquentBaseModel {
    protected $forcedNullFields = ['BirthDate','AnotherNullableField'];
}
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);
    }
}