laravel get data without applying casts - laravel

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

Related

How to get distinct dates from a datetime field

I have this field valid_upto which is a datetime, so if I do:
$dates = Game::where('week', $this->week)
->distinct('valid_upto')
->pluck('valid_upto');
It returns an array like:
["2022-09-08 19:20:00",
"2022-09-11 12:00:00",
"2022-09-11 15:25:00",
"2022-09-11 19:20:00",
"2022-09-12 19:15:00",]
But I only want the date part, like:
["2022-09-08",
"2022-09-11",
"2022-09-12",]
is there a way to do it directly in Laravel's ORM? I don't want to use a rawSelect or similar, I know I could apply DATE('valid_upto') as d in mySQL and Postgres, but I really like to use "general" approaches.
This would work:
foreach ($dates as $i => $d) $dates[$i]=explode(" ", $dates[$i])[0]
$dates = $dates->unique()
But I think its an horrible solution
Something I would like to do, instead of using that foreach, applying a lambda (like in Python) to the Collection and then use the distinct. But I don't know if Laravel has lambdas.
In Laravel you can use Mutators and Casters to determine how certain columns are formatted when you access them. Laravel applies the casting when the model is serialized to json or to an array. So your query could become:
$dates = Game::where('week', $this->week)
->distinct('valid_upto')
->get('valid_upto')
->toArray();
And if you apply a caster on your Game model like so:
protected $casts = [
'valid_upto' => 'datetime:Y-m-d',
];
that should get you a collection of the dates you want in the format you want.

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 casting not working on double and decimal setting to zeros

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.

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

How to select specific columns in laravel eloquent

lets say I have 7 columns in table, and I want to select only two of them, something like this
SELECT `name`,`surname` FROM `table` WHERE `id` = '1';
In laravel eloquent model it may looks like this
Table::where('id', 1)->get();
but I guess this expression will select ALL columns where id equals 1, and I want only two columns(name, surname). how to select only two columns?
You can do it like this:
Table::select('name','surname')->where('id', 1)->get();
Table::where('id', 1)->get(['name','surname']);
You can also use find() like this:
ModelName::find($id, ['name', 'surname']);
The $id variable can be an array in case you need to retrieve multiple instances of the model.
By using all() method we can select particular columns from table like as shown below.
ModelName::all('column1', 'column2', 'column3');
Note: Laravel 5.4
You first need to create a Model, that represent that Table and then use the below Eloquent way to fetch the data of only 2 fields.
Model::where('id', 1)
->pluck('name', 'surname')
->all();
Also Model::all(['id'])->toArray() it will only fetch id as array.
Get value of one column:
Table_Name::find($id)->column_name;
you can use this method with where clause:
Table_Name::where('id',$id)->first()->column_name;
or use this method for bypass PhpStorm "Method where not found in App\Models":
Table_Name::query()->where('id','=',$id)->first()->column_name;
in query builder:
DB::table('table_names')->find($id)->column_name;
with where cluase:
DB::table('table_names')->where('id',$id)->first()->column_name;
or
DB::table('table_names')->where('id',$id)->first('column_name');
last method result is array
You can use get() as well as all()
ModelName::where('a', 1)->get(['column1','column2']);
From laravel 5.3 only using get() method you can get specific columns of your table:
YouModelName::get(['id', 'name']);
Or from laravel 5.4 you can also use all() method for getting the fields of your choice:
YourModelName::all('id', 'name');
with both of above method get() or all() you can also use where() but syntax is different for both:
Model::all()
YourModelName::all('id', 'name')->where('id',1);
Model::get()
YourModelName::where('id',1)->get(['id', 'name']);
To get the result of specific column from table,we have to specify the column name.
Use following code : -
$result = DB::Table('table_name')->select('column1','column2')->where('id',1)->get();
for example -
$result = DB::Table('Student')->select('subject','class')->where('id',1)->get();
use App\Table;
// ...
Table::where('id',1)->get('name','surname');
if no where
Table::all('name','surname');
If you want to get a single value from Database
Model::where('id', 1)->value('name');
Also you can use pluck.
Model::where('id',1)->pluck('column1', 'column2');
You can use Table::select ('name', 'surname')->where ('id', 1)->get ().
Keep in mind that when selecting for only certain fields, you will have to make another query if you end up accessing those other fields later in the request (that may be obvious, just wanted to include that caveat). Including the id field is usually a good idea so laravel knows how to write back any updates you do to the model instance.
You can get it like
`PostModel::where('post_status', 'publish')->get(['title', 'content', 'slug', 'image_url']`)
link
you can also used findOrFail() method here it's good to used
if the exception is not caught, a 404 HTTP response is automatically sent back to the user. It is not necessary to write explicit checks to return 404 responses when using these method not give a 500 error..
ModelName::findOrFail($id, ['firstName', 'lastName']);
While most common approach is to use Model::select,
it can cause rendering out all attributes defined with accessor methods within model classes. So if you define attribute in your model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* Get the user's first name.
*
* #param string $value
* #return string
*/
public function getFirstNameAttribute($value)
{
return ucfirst($value);
}
}
And then use:
TableName::select('username')->where('id', 1)->get();
It will output collection with both first_name and username, rather than only username.
Better use pluck(), solo or optionally in combination with select - if you want specific columns.
TableName::select('username')->where('id', 1)->pluck('username');
or
TableName::where('id', 1)->pluck('username'); //that would return collection consisting of only username values
Also, optionally, use ->toArray() to convert collection object into array.
If you want to get single row and from the that row single column, one line code to get the value of the specific column is to use find() method alongside specifying of the column that you want to retrieve it.
Here is sample code:
ModelName::find($id_of_the_record, ['column_name'])->toArray()['column_name'];
If you need to get one column calling pluck directly on a model is the most performant way to retrieve a single column from all models in Laravel.
Calling get or all before pluck will read all models into memory before plucking the value.
Users::pluck('email');
->get() much like ->all() (and ->first() etc..) can take the fields you want to bring back as parameters;
->get/all(['column1','column2'])
Would bring back the collection but only with column1 and column2
You can use the below query:
Table('table')->select('name','surname')->where('id',1)->get();
If you wanted to get the value of a single column like 'name', you could also use the following:
Table::where('id', 1)->first(['name'])->name;
For getting multiple columns (returns collection) :
Model::select('name','surname')->where('id', 1)->get();
If you want to get columns as array use the below code:
Model::select('name','surname')->where('id', 1)->get()->toArray();
If you want to get a single column try this:
Model::where('id', 1)->first(['column_name'])->column_name;

Resources