Store True as 1 False as 0 using Laravel + Eloquent + Mysql - laravel

I have a value of true or false coming from an ajax post to the back end (laravel) and I want to store it as 1 or 0 in the mysql database. This is basically a checkbox or radio that I reach into the DOM and grab the value. I believe I should be able to add a mutator:
protected $casts = [
'active' => 'boolean',
];
This does pull the 1 and convert it to true, however it does not store true as 1.
The documentation does not say the cast will be performed both directions for boolean, however it does say the cast works both directions for array
Once the cast is defined, you may access the options attribute and it will automatically be deserialized from JSON into a PHP array. When you set the value of the options attribute, the given array will automatically be serialized back into JSON for storage:
I could convert to integer on the client, I guess I would prefer to do it on the back end. Any other thoughts? I will need this conversion on many tables. I am using laravel 5.2

I believe you only need to be sure that your database column type is either boolean or tinyint.
Edit:
However, you can use a Mutator function in you model in order to convert it to int, like the following:
public function setActiveAttribute($value)
{
$this->attributes['active'] = (int) $value;
}

Related

Eloquent Collection query - 'WHERE' clause with $value parameter without invoked accessor

I have used some accessors for Model attributes.
And as my knowledge about Accessor in Laravel, it can use to create a virtual attribute based on another attribute value or modify the return value of the existing attribute.
So I create an Accessor with the public method getStatusAttribute to convert the status from integer to string value. For example, my Model has an attribute named is 'status'. In DB, this column is stored with integers like 0,1,2,...
In this method, the return value is a string based on the current status attribute value.
public function getStatusAttribute(int $value): string
{
$statuses = [
1 => 'New',
2 => 'Pending',
3 => 'Canceled'
];
return $statuses[$value];
}
Everything work fined when I retrieve attribute value from the model object entity.
But when I want to retrieve an Eloquent Collection with a specific 'status' attribute value, the $value parameter in the 'where' method expects a string value that is returned from the accessor method, not is an integer value which stored in a database. So the $value parameter would be 'New' or 'Pending' or 'Canceled' instead of 1,2,3.
I want to retrieve a collection that contains an Eloquent Model Object so that I won't use an Illuminate\Support\Facades\DB.
I know I still can retrieve the exact collection with the $value parameter as a string, but I was just wondering if we have another way to skip the accessor in the query of Eloquent Collection?
Please see an example below for more detail about what I expect.
For example, some records in the database look like the below, and the model was named 'DemoModel' :
id
status
1
1
2
3
3
1
4
3
5
2
public function getCanceledEntities($entityId)
{
$canceledEntities = DemoModel::all()->where('status', '=', 3);
if($canceledEntities->isNotEmpty()) {
return $canceledEntities;
}
}
Without an accessor, this query will return a collection containing two entities with id [ 2, 4 ].
But with an accessor (as defined in the model), it can't find a matched entity because the WHERE clause expects that the 3rd parameter is 'Canceled' instead of 3.
My alternative method is to use a string 'Canceled' in the 'where' clause. However, I still want to use the value stored in a database for the query, and I think maybe the framework has another way to write an Eloquent Collection query without invoking an accessor.
Any suggestions are always welcome.

Retrieve Value from Field in Laravel Cast Array

I have a table named settings, in it, there are several columns, id,company_id, key, value.
In my Laravel model for Setting, I have the following cast:
protected $casts = [
'value' => 'array',
];
But when I go to retrieve data that has been stored, I can't.
For example, I have a record with the following value: "{\"default_remit_address\":\"2395\"}"
And when I go to retrieve the record in a Blade, it does pull it up correctly, but I'm not sure how to grab a specific value from the value field (like default_remit_address).
If I print the return "{{$settings->value}}" directly in the Blade, this is what I get:
{"default_remit_address":"2395"}
So how can I go one level deeper?
As this json object is being cast to an Array, you can just use regular array syntax to access it's contents.
$default_remit_address = Settings::find(1)->value['default_remit_address'];
or in your blade template
{{ $settings->value['default_remit_address'] }}

Laravel Array to string conversion error while updating database

I want to update a totcosty field in the User table but it is throwing this error everytime and it is not updating the field
this is the function for execution:
public static function cost(){
$user = User::find($user_id);
$total = Helper::totcost();
// dd($tot_amt);
$user->totcosty = $total;
$user->save();
}
array to string means you are sending an array to the database but db will not accept it you have to explode() the array before sending it to db...
Hope it will help!
If you really want to store an array in some table field, then better declare it as a JSON field. For this, your DB should have support for JSON type columns.
See here how to do this.
Once this is done, you can save arrays in that column, you can assign an array value to the model property and laravel will convert it to JSON while saving and also it will be converted to array while retrieving.

laravel get data without applying casts

I am doing
Model::get()->toArray()
to get all the data from my table but the model has a cast on the dates.
protected $casts = ['date' => 'datetime:D, M d Y'];
I want to be able to get all the data without applying the cast and just the original datetime format. Is there a way to control when the cast is applied.
Laravel 7+
As Sam mentioned for Laravel 7+ you can use:
$model->getRawOriginal('created_at')
You can get all attributes as they are, by using
Model::get()->transform(function ($item) {
return $item->getOriginal();
}))->toArray();
Also can use getOriginal() as
$model->getOriginal('created_at')
on any model to get the original value whenever it's needed.
Note : getOriginal() will include all the $hidden attributes of the model.
getOriginal('date') and getRawOriginal('date') return the unmodified values !
If you want to get the current value without cast, you can use getAttributes()['date']

Eloquent Collections Where Condition

I want to get alternative products pictures.
dd($alternativeProduct->pictures);
When die and dump i get this result.
I need to get only the picture which is main. If main equals to 1. It is main picture.
When I write
dd($alternativeProduct->pictures->where('main', 1))
I got an empty array.
Here is my relation with Product and Picture relation
public function pictures(){
return $this->hasMany('App\Models\ProductPicture');
}
What can i do ?
The where method in a collection has three parameters: $key, $value and $strict, the last one defaults to true if not passed when calling the method. When $strict is true the comparison is done via === which does not do type coercion, meaning "1" === 1 is false.
From your dump data, I can see that "main" => "1" which means it's a string and you're passing an integer 1 to the where method, resulting in what I described above as a false condition and returning an empty result set. You can fix that by disabling strict comparison:
$alternativeProduct->pictures->where('main', 1, false);
// or the equivalent helper whereLoose
$alternativeProduct->pictures->whereLoose('main', 1);
Or passing a string as the value:
$alternativeProduct->pictures->where('main', "1");
That being said, if that's the only place you're using that collection in that request's context, I suggest that you filter the results at the database level, not after they are fetched, like so:
$alternativeProduct->pictures()->where('main', 1)->get();
Accessing the relations as a method ->pictures(), instead of as a property ->pictures, will return a Query Builder instance that allows you to add conditions to the database query and only fetch the actual items you need from the database, instead of fetching them all and filtering them out afterwards.
You may want to use whereLoose instead:
dd($alternativeProduct->pictures->whereLoose('main', 1))
From the Laravel docs:
The where method uses strict comparisons when checking item values. Use the whereLoose method to filter using "loose" comparisons.

Resources