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