Laravel casting not working on double and decimal setting to zeros - laravel

I have 2 decimal(10,8) fields on mysql with this migration:
$table->decimal('lat', 10, 8)->nullable();
$table->decimal('lng', 10, 8)->nullable();
Via an API endpoint I find the latitude and longitude.
The API returns this:
$geo->lat = 46.0081326;
$geo->lng = 8.9761892;
BUT when setting my model field like so
$estate->lat = $geo->lat;
$estate->lng = $geo->lng;
in the DB the fields gets set to 46.00000000 and 8.00000000.
Because of this I tried setting the cast in the model like so
protected $casts = ['lat' => 'double', 'lng' => 'double'];
I also tried casting to specific decimal
protected $casts = ['lat' => 'decimal:8', 'lng' => 'decimal:8'];
But no luck. I still get 46.00000000 and 8.00000000 inside the DB.
I also tried removing Laravel casts and forcing the type like this
$estate->lat = (double) $geo->lat;
But I still get empty decimal points.
These are 2 new brand new columns but I tried checking if the App has some setLatAttribute() mutator but it does not.

Your database is holding the data type as a decimal (which is good!), but your application tries to read that decimal as a float.
You should be able to tell your application to continue reading the data as a decimal:
protected $casts = ['lat' => 'decimal:8'];
If you're relying on Laravel's $casts functionality, you shouldn't be forcing type anywhere else in your code, this can get you into all sorts of nasty problems that are incredibly hard to debug.

The problem was not related to the casting or typing but rather to the wrong class name.
I forgot to rename the Class name into the correct one (SmootherCommand in SmootherCommand.php) and this caused misbehaviour.

Related

Has laravel 7 model a way to get list of all columns?

Has laravel 7 model a way to get list of all columns ?
I found and tried method
with(new ModelName)->columns
but it returns empty string.
I do not mean $fillable var of a model.
Thanks!
If you just want a reliable way to pull the list of attributes from any given instance no matter the state, and assuming the table structure isn't changing often, the path of least resistance might be to set a defaults attributes array to ensure the attributes are always present.
e.g.
class Fish extends Model
{
protected $attributes = [
'uuid' => null,
'fin_count' => null,
'first_name' => null,
];
}
$fishie = app(\Fish::class);
will then result in an instance of Fish with uuid, fin_count, and first_name set. You can then use $fishie->attributes or $fishie->getAttributes() to load the full set.
Assuming the structure doesn't change a lot, setting the attributes on the model like this will save you a database query every time you want to reference the list. The flip side is that instances change from not having the attributes unless explicitly defined to always being present, which may have implications in the project.
Here's the documentation for default attributes:
https://laravel.com/docs/master/eloquent#default-attribute-values

Laravel does not show the highest value from the database

I has a code, which find max value in column:
$max_x = DB::table('bust_history')->max('bust_number');
But always the same value. Now the number 97.52 is displayed, from the field #30. But I have values also higher than this number, but the laravel does not want to display them. How can i fix this? For example, not highest value its 159.30, from fiend #550.
Your column in database probably is a string so because of that it consider it as string and not an integeror float and I think that's the cause of your problem. you have two ways in this case
First to change the bust_number to int or float (change your migration file etc)
Second is to cast it to integer in your model if you have a model for your bust_history table if so you just need to write
protected $casts = [
'bust_number' => 'integer'
];
in your model...

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']

Laravel treating decimal as string

Im trying to make the next eloquent query
$result = $result->where('money','>=',(float)$moneyFilter);
The money column in my database its DECIMAL(11,2), when I run the query it returns an empty array, when I go over php artisan tinker and see the column money, it's a string value "11.1".
I would like to filter the $result collection to have values over $moneyFilter.
Thanks
You need to define in your model which fields need to be cast to a primitive attribute.
protected $casts = ['my_decimal' => 'float'];
There is a really good explanation here:
https://mattstauffer.com/blog/laravel-5.0-eloquent-attribute-casting/
Also there is an explanation in the docs:
https://laravel.com/docs/5.5/eloquent-mutators#attribute-casting

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

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

Resources