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 null
values as I expected.
问题就是这样,每个字段都填充了一个空字符串而不是我期望的空值。
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 $fillable
array and to a new Contact(array(...));
...
我正在开发系统,但仍然没有定义一些表格列,这就是为什么使用这种方法,以避免将每个新字段添加到$ fillable数组和新的Contact(数组(...)); ...
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?
有关如何执行此操作或修复的任何提示?
Update By now I've sorted out this doing the array_filter in the App::before()
filter.
更新到现在为止,我已经在App :: before()过滤器中完成了这个做array_filter。
Update In 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?
工作完美。任何意见?
7 个解决方案
#1
10
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.
使用模型“save”事件查找空模型并将其显式设置为null。 '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 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);
}
}
#2
58
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:
通过为模型中的外键字段添加(magic!)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.
对于一个有很多外键的表,这可能会变得笨重,但它是我发现处理它的最“内置”方法。好处是它很神奇,所以你所要做的就是创造方法并且你很高兴。
#3
19
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')
.
然后,如果你有类似数组('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
$input = array_filter(Request::all(), 'strlen');
or
要么
// If you inject the request.
$input = array_filter($request->all(), 'strlen');
#4
11
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.
这就是全部,你不应该在mutators中重复相同的代码。
#5
1
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.
我个人不赞成使用这些解决方案,但它确实适用于某些人。
#6
0
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中的必填字段。
#7
-2
In your Eloquent model, make sure $guarded
is 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
#1
10
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.
使用模型“save”事件查找空模型并将其显式设置为null。 '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 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);
}
}
#2
58
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:
通过为模型中的外键字段添加(magic!)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.
对于一个有很多外键的表,这可能会变得笨重,但它是我发现处理它的最“内置”方法。好处是它很神奇,所以你所要做的就是创造方法并且你很高兴。
#3
19
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')
.
然后,如果你有类似数组('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
$input = array_filter(Request::all(), 'strlen');
or
要么
// If you inject the request.
$input = array_filter($request->all(), 'strlen');
#4
11
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.
这就是全部,你不应该在mutators中重复相同的代码。
#5
1
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.
我个人不赞成使用这些解决方案,但它确实适用于某些人。
#6
0
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中的必填字段。
#7
-2
In your Eloquent model, make sure $guarded
is 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