Why does Laravel array cast sort the elements, and can it be avoided? - laravel

I have a JSON field in a database which is populated using the array cast on an Eloquent model.
Before saving the field, Laravel sorts the elements by their key. Presumably this happens during serialisation.
Why does it do this? And is there a way to prevent it?

If you do not need to implement search by field, you can use the text type instead of the json type. Just before saving, you will need to execute json_encode, either yourself or implement a mutator.

I've never encountered this behavior before, but perhaps you can try using an accessor and a mutator to accomplish what you want. Let's say your database column is meta. You can use Laravel's special setAttribute and getAttribute methods in your model.
A mutator
For example, to json_encode data as it's about to be saved to your database it would be:
public function setMetaAttribute($value)
{
$this->attributes['meta'] = json_encode($value);
}
An accessor
To json_decode data as it's being retrieved it would be:
public function getMetaAttribute($value)
{
return json_decode($value, true);
}
The rule of thumb is take get or set and append your column name with first letters uppercased and removing any underscores, and appending Attribute to the method name. E.g. active_users column becomes getActiveUsersAttribute and so on.
Try that and see if it does any funky sorting.

Sometimes MySQL changes the order of keys when a JSON field is used.
The basic solution is to use a TEXT field to store json.
See Mysql 5.7 native json support - control keys order in json_insert function

Related

Can Laravel model validate the field data types(int,float,..etc) while inserting data?

My problem is that I'm using noSql for my database and Laravel for the backend.
I know that we can validate the data types in the request but this validates only the incoming request after that we might calculate or re-arrange the data type of a field and insert it. I want to prevent this insertion by checking the data types. Is there a way to implement this validation in model like fillable [] or casts [].
You could setup an Observer on that model and in the Observer's 'updating' method you could perform any type formatting or cleanup required.
Or if it's a real edge case you could call the Validator facade to define the keys/rules to check for and then pass your changed object to it? If Validator->fails() you could loop through Validator->errors() and apply corrections as needed.

When to use request in Laravel?

I am reading an article casting created_at to a string as it will return as an object by default. When to make request exactly? I know that the request can be used to transform one format to another. But when exactly? Any rules like when you create a data column you must use it? Things like that?
Using created_at as a string is not a best practice. Laravel Eloquent will automatically extract them from DB and cast them to Carbon instance, so you can transform it with a string (with ->format()) whenever you want.
Plus, having a Carbon object, you have access to lots of methods to handle your date, like comparison, extraction of single data (like day, month, hours...), so it doesn't make sense to cast it to a string, imho.

How to get columns of a model instance in Laravel?

Can I extract a specific column for a model instance in Laravel instead of using query methods statically? more clearly, instead of writing the code below:
MyModel::select('columnName')->where('id', $model->id)->first();
can we write?
$model->select('columnName');
Well, when you grab it from a model class, it is a Eloquent Object, and it has all attributes from the database.
But if you are talking about serializing that into an array or JSON everytime, then you need to modify your $visible array ;
if you wanna transform it for a specific case, then you need to do :
MyModel::select('columnName')->where('id', $model->id)->first()->pluck('columnName');

Laravel5: refresh method for eloquent models?

I create a model and save it, using the save() methods, and I do not fill all properties. Mysql will set the assigned default values of the columns.
But the values are not filled after, just the primary keys.
Isn't there a something like "refresh()" method which updates my model instance with the actual data?
Yes. There's a fresh method on the model that does exactly that.
You shouldn't need this. You should add the default values to the $attributes array so that you always have the default values automatically.

What does mutators and accessors do in Doctrine?

In this document, it explains how to use mutators and accessors in Doctrine, but does not explain what they are.
Could anyone explain what mutators and accessors do and what they are?
Thanks in advance.
You can use mutators and accessors to implement additional behavior for your models' fields. Basically they transform the value from one form into another. For example if you look at Doctrine's docs they specify a md5Password mutator. Mutator means that Doctrine will call the specified mutator method whenever you set the value for the field. So whenever you do:
$user->password = 'foobar';
Doctrine will call the md5Password() of the model, hence transforming 'foobar' into md5('foobar'). In a nutshell this ensures that the password is always hashed on software-level.
Accessor is the opposite of mutator; it'll be called when the field is being read instead of being set (eg. when a row is read from the database).

Resources