All we need is an easy explanation of the problem, so here it is.
While using Laravel 5.1, I am trying to check every value before it is saved in the database using Eloquent ORM. My logic is, first trim the value, if the value is an empty string ""
, then to convert it to null
instead of just an empty string.
I was advised to create a Trait which will override the setAttribute method for that.
So here is what I have done
I have a new folder “app\Traits” inside of a file called TrimScalarValues.php
which contains the following code
<?php
namespace App\Traits;
trait TrimScalarValues
{
public function setAttribute($key, $value)
{
if (is_scalar($value)) {
$value = $this->emptyStringToNull(trim($value));
}
return $this->setAttribute($key, $value);
}
/**
* return null value if the string is empty otherwise it returns what every the value is
*
*/
private function emptyStringToNull($string)
{
//trim every value
$string = trim($string);
if ($string === ''){
return null;
}
return $string;
}
}
Finally I have a app\Models\Account.php
file which contains the following code
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use App\Models\industry;
use App\Traits\RecordSignature;
use App\Traits\TrimScalarValues;
class Account extends Model
{
use RecordSignature, TrimScalarValues;
/**
* The database table used by the model.
*
* @var string
*/
protected $table = 'accounts';
protected $primaryKey = 'account_id';
const CREATED_AT = 'created_on';
const UPDATED_AT = 'modified_on';
const REMOVED_AT = 'purged_on';
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = ['client_id','account_name', 'company_code', 'legal_name', 'created_by','modified_by','instrucations'];
/**
* The attributes excluded from the model's JSON form.
*
* @var array
*/
//protected $hidden = ['account_id', 'remember_token'];
protected $guarded = ['account_id'];
/**
* Get the industry record associated with the account.
*/
public function industry()
{
return $this->hasOne(industry, industry::primaryKey);
}
public function pk(){
return $this->primaryKey;
}
}
But every time I update a value, I get a white page with no error or logs.
When I modify the app\Models\Account.php
and change use RecordSignature, TrimScalarValues;
to use RecordSignature;
then I do not get a white page but obviously the values are not trimmed and converted to null.
What am I doing wrong here?
How to solve :
I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.
Method 1
You can’t call $this->setAttribute()
in your trait. Instead you want to call the “original” setAttribute
method by using parent::
:
public function setAttribute($key, $value)
{
if (is_scalar($value)) {
$value = $this->emptyStringToNull(trim($value));
}
return parent::setAttribute($key, $value);
}
Regarding the empty logs, have you checked the webserver log besides the one from the framework?
Method 2
I had the same problem and solved it by creating a middleware that filters empty input fields.
public function handle($request, Closure $next) {
$input = $request->all();
if ($input) {
array_walk_recursive($input, function (&$item) {
$item = trim($item);
$item = ($item == "") ? null : $item;
});
$request->merge($input);
}
return $next($request);
}
Don’t forget to add your custom middleware to Http/Kernel.php
Found this at Laracasts
Method 3
You might wanna take a look at this package:
https://packagist.org/packages/iatstuti/laravel-nullable-fields
“This create a trait and allows you to easily flag attributes that should be set as null when being persisted to the database.”
I know this post is old, and at that time this package maybe didn’t exist yet.
Method 4
You can use mutator in you model.
For the field account_name mutator should looks like this:
public function setAccountNameAttribute($account_name)
{
if(is_null($account_name))
{
$this->attributes['account_name'] = null;
}
else
{
$this->attributes['account_name'] = $account_name;
}
}
And everytime when you will update or insert the record using Eloquent, account_name will be passed through this mutator.
Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0