Get formatted date at Eloquent results - laravel

Considering that the model is
class Cota extends Model
{
protected $fillable = ['status','user_id','produto_id','numero','arquivo','updated_at'];
protected $dates = [
'updated_at',
];
//protected $dateFormat = 'd/m/Y';
}
And considering the query:
$cotas = DB::table('cotas')->join('produtos','produtos.id','=','cotas.produto_id')->join('users','users.id','=','cotas.user_id')->select('cotas.id','produtos.titulo as produto','cotas.numero','cotas.arquivo','users.name','cotas.status','cotas.updated_at','produtos.valor')->get();
When I get only one instance, like:
$cota = Cota::find(6517);
I can do this:
$cota->updated_at->format('d/m/Y');
But in the query above, the results come always with the traditionl date format used by Mysql.
How do I get the results with the ('d/m/Y') format? I have to use a raw query? Is that the only way?
Thanks!

You can always user DB::raw in Select statement.
$cotas = DB::table('cotas')
->join('produtos','produtos.id','=','cotas.produto_id')
->join('users','users.id','=','cotas.user_id')
->select([
'cotas.id',
'produtos.titulo as produto',
'cotas.numero',
'cotas.arquivo',
'users.name',
'cotas.status',
DB::raw('DATE_FORMAT(cotas.updated_at, "%d/%m/%Y"') as updated_at,
'produtos.valor'
])
->get();
// Or Else You can always loop over your collection when displaying data / using that data.

You can use date casting like so
protected $casts = [
'updated_at' => 'datetime:d/m/Y',
];
This is only useful when the model is serialized to an array or JSON according to the docs.

Related

Right way to save timestamps to database in laravel?

As part of a standard laravel application with a vuejs and axios front-end, when I try to save an ISO8601 value to the action_at field, I get an exception.
class Thing extends Model {
protected $table = 'things';
// timestamp columns in postgres
protected $dates = ['action_at', 'created_at', 'updated_at'];
protected $fillable = ['action_at'];
}
class ThingController extends Controller {
public function store(Request $request) {
$data = $request->validate([
'action_at' => 'nullable',
]);
// throws \Carbon\Exceptions\InvalidFormatException(code: 0): Unexpected data found.
$thing = Thing::create($data);
}
}
My primary requirement is that the database saves exactly what time the client thinks it saved. If another process decides to act on the "action_at" column, it should not be a few hours off because of timezones.
I can change the laravel code or I can pick a different time format to send to Laravel. What's the correct laravel way to solve this?
The default created_at and updated_at should work fine.
You should always set your timezone in your config/app.php to UTC
Add a timezone column or whichever you prefer in your users table
Do the time-offsets in your frontend or api response
Here's a sample code to do the time offset in backend
$foo = new Foo;
$foo->created_at->setTimezone('America/Los_Angeles');
or frontend using momentjs
moment(1650037709).utcOffset(60).format('YYYY-MM-DD HH:mm')
or using moment-timezone
moment(1650037709).tz('America/Los_Angeles').format('YYYY-MM-DD HH:mm')
class Thing extends Model {
protected $table = 'things';
// timestamp columns in postgres
protected $dates = ['action_at', 'created_at', 'updated_at'];
protected $fillable = ['action_at'];
}
class ThingController extends Controller {
public function store(Request $request) {
$data = $request->validate([
'action_at' => 'nullable',
]);
// convert ISO8601 value, if not null
if ($data['action_at'] ?? null && is_string($data['action_at'])) {
// note that if the user passes something not in IS08601
// it is possible that Carbon will accept it
// but it might not be what the user expected.
$action_at = \Carbon\Carbon::parse($data['action_at'])
// default value from config files: 'UTC'
->setTimezone(config('app.timezone'));
// Postgres timestamp column format
$data['action_at'] = $action_at->format('Y-m-d H:i:s');
}
$thing = Thing::create($data);
}
}
Other tips: don't use the postgres timestamptz column if you want to use it with protected $dates, laravel doesn't know how to give it to carbon the way postgres returns the extra timezone data.
See the carbon docs for other things you can do with the $action_at instance of \Carbon\Carbon, such as making sure the date is not too far in the future or too far in the past. https://carbon.nesbot.com/docs/

How do I "json_decode" a single column data after fetch from database in Laravel?

I am saving an array in one column of my database using json_encode as follows and it works:
$service->description = $request->service_description;
$service->image = json_encode($url);
$service->duration = $request->service_delivery_time;
When I fetch the data I get a string. I am fetching using $service = Service::findOrFail($id);. I can decode the individual column as done below and pass it to the view.
$service = Service::findOrFail($id);
$images = json_decode($service->image);
return view('services.show',['service'=>$service , 'images'=>$images]);
What I am asking is, can I decode the images in one query?
Well this is a single query, json_decode runs after the SQL query returned your desired result.
What you can do is add a $casts property to your Service model so Laravel encodes/decodes it automatically for you, then you don't need to store these values with json_encode, just do $service->image = $url, and when you run findOrFail, the image property will already be a decoded json.
protected $casts = [
'image' => 'array',
];
Here's the documentation
You can use $cast or Accessor
1: $cast:
protected $casts = [
'image' => 'array'];
2: Accessor:
public function getImageAttribute()
{
return json_decode($this->attributes['image']);
}

Laravel insert into database request()->all() and addition

In laravel if i want to insert all the form input and i want to add text in one of the column why cant i use this code?
Example
$B2 = new B2;
$B2::create([
request()->all(),
$B2->column9 = "aaaa",
]);
The inserted database only insert column9, the other column is Null.
Because create() accepts an array as the only parameter:
public static function create(array $attributes = [])
You can do this:
$data = request()->all();
$data['column9'] = 'aaaa';
B2::create($data);
When ever you use request all you must first make sure that you have either fillable fields in your model or guarded = to an empty array so for example:
class B2 extends Model
{
protected $table = 'db_table';
protected $fillable = [
'email',
'name',
];
}
or you can use
protected $guarded = [];
// PLEASE BE CAREFUL WHEN USING GUARDED AS A POSE TO FILLABLE AS IT OPENS YOU TO SECURITY ISSUES AND SHOULD ONLY REALLY BE USED IN TEST ENVIRONMENTS UNLESS YOU REALLY KNOW WHAT YOU ARE DOING!
As for your create method you should make sure its an associative array like this:
$B2::create([
$B2->column9 => "aaaa",
]);
Or you could do something like:
$data = $request->except('_token');
$B2::create($data);
You'll have to merge the array.
$B2::create(array_merge(request()->all(), ['column9' => 'text']));
When you are adding to a database in that was it is called mass assignment. Laravel Automatically protects against this so you need to add the firld names to a fillable attribute in your model
protected $fillable = ['field1', 'column9'] //etc
https://laravel.com/docs/5.4/eloquent#mass-assignment
You also need to make sure you pass an array to the create method
$my_array = $request->all()
$my_array['column9'] = 'aaaa';
$B2::create(
$my_array
);

Distinct values with pluck

I'm trying to retrieve data from database and bind them to a html select tag, and to bind them i need to use pluck so i get the field i want to show in a array(key => value), because of FORM::select. The normal pluck gets all the results, while i want to use distinct. My model is Room and it looks like:
class Room extends Eloquent
{
public $timestamps = false;
protected $casts = [
'price' => 'float',
'floor' => 'int',
'size' => 'float'
];
protected $fillable = [
'capacity',
'description',
'price',
'floor',
'size',
'type',
'photo_name'
];
}
While my function I'm using in the controller look like:
public function getRooms()
{
$roomType = Room::pluck('type','type');
$roomFloor = Room::pluck('floor','floor');
return view('roomgrid')->with('type',$roomType)->with('floor',$roomFloor);
}
And my view contains this piece of code to get floors:
{{FORM::select('floor', $floor, null,['class'=>'basic'])}}
Like this i get duplicated floors, that i don't want. Is there any way so i can get distinct floors and pluck them? Thanks in advance.
Why not use groupBy()?
$roomType = Room::groupBy('type')->pluck('type','type');
Room::unique('floor')->pluck('floor', 'floor');
distinct can do the trick:
Room::query()->distinct()->pluck('type');
Which will be translated into the following SQL:
SELECT DISTINCT type FROM rooms
2019 Update
You don't need to use 2 arguments with pluck()
simply do:
$roomType = Room::groupBy('type')->pluck('type');
of course for getting it into array:
$roomType = Room::groupBy('type')->pluck('type')->toArray();
Sometimes I use the result for whereIn clause, its useful for that.
you can do this
$roomType = Room::pluck('type')->unique();
$roomFloor = Room::pluck('floor')->unique();
You can use KeyBy or pluck with same key-Value pair to pick Distinct Values.
PHP array can only have unique keys.From this Idea we can get Unique models based on Array key.
Room::keyBy('floor')->pluck('floor');
or
Room::pluck('floor', 'floor');

how to print model query in laravel

i am new in laravel and have to save the record in table , i am using this code to insert the value
$model->studentRollId = $value1;
$model->resident_permit_number = $value2;
$model->save()
i am not getting any error but record not inserting in the table , so can anyone please tell me how can i print the executed query by the $model->save(), i tried DB::getQueryLog() but its not shiwing the query log so i can fin what is the issue . thanks in advance
Use ->toSql(), after your $model->save(), just do a dd($model->toSql())
Edit: Have you do a \DB::enableQueryLog();?
\DB::enableQueryLog();
$model->studentRollId = $value1;
$model->resident_permit_number = $value2;
$model->save()
dd(\DB::getQueryLog());
Try This
$model->studentRollId = $value1;
$model->resident_permit_number = $value2;
$data = $model->toSql();
dd($data);
Do you have studentRollId and resident_permit_number in the $fillable array?
Go to the $model and check if you have something like this:
protected $fillable = [
'studentRollId',
'resident_permit_number'
];
Another solution would be to insert data in raw like this:
DB::table('table_name')->insert([
'studentRollId' => $value1,
'resident_permit_number' => $value2
]);
Hope it helps.
Have you mentioned the column names in $fillable in you model. In laravel to insert a data in table you have to mentioned the columns names in $fillable method.
e.g.
Suppose you have users table and for that table you have User model.
In User.php add following method
protected $fillable = [
'list of columns'
];

Resources