Can not format datetime in laravel 7.2.2 - laravel

i am currently working in laravel 7.2.2 and I am trying to format following datetime in to 'M d Y' .
"created_at": "2020-03-23T12:17:29.000000Z",
Previously, in laravel 6, datetime formats are like this: 2019-12-02 20:01:00.
but now, date format is changed, and appearing like above: 2020-03-23T12:17:29.000000Z.
In laravel 6 i used to format my datetime as following code:
foreach ($posts as $post) {
$createdAt = Carbon::parse($post['created_at']);
$post['created_at'] = $createdAt->format('M d Y');
}
But it gives me same output as above 2020-03-23T12:17:29.000000Z .
So, how can i format my datetime in laravel 7.
Any help?

This was a breaking change introduced in Laravel 7.0. You can still format it the way you want.
You can override the serializeDate method on your model:
/**
* Prepare a date for array / JSON serialization.
*
* #param \DateTimeInterface $date
* #return string
*/
protected function serializeDate(DateTimeInterface $date)
{
return $date->format('M d Y');
}
See the docs in the upgrade guide for more information.
HTH

You can use Eloquent resources to transform the data from your model to what the API should respond with. That way you won't need to touch the data and how the data is saved in your model.
It could look like something like this, given that your column names are the same:
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Http\Request;
class Post extends JsonResource
{
public function toArray(Request $request)
{
return [
'id' => $this->id,
'title' => $this->title,
'text' => $this->text,
'created_at' => $this->created_at->format('M d Y'),
'updated_at' => $this->updated_at->format('M d Y'),
];
}
}

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/

Get formatted date at Eloquent results

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.

Dynamic search function Photo album

I am trying to create a dynamic serch function to my PhotoAlbumn project. So I have installed Nicolaslopezj Searchable. However it does not work propertly as yet.
Error
Illuminate\Database\Eloquent\RelationNotFoundException
Call to undefined relationship [albums] on model [App\Photo]
Model
use Illuminate\Database\Eloquent\Model;
use Nicolaslopezj\Searchable\SearchableTrait;
class Photo extends Model{
use SearchableTrait;
protected $searchable = [
/**
* Columns and their priority in search results.
* Columns with higher values are more important.
* Columns with equal values have equal importance.
*
* #var array
*/
'columns' => [
'albums.name' => 10,
'photos.title' => 10,
'photos.info' => 10,
'albums.title' => 5,
],
'joins' => [
'albums' => ['photos.id','albums.id'],
],
];
protected $fillable = array('photo','title','info','album_id');
public function album(){
return $this->belongsTo('App\Album');
}
PhotoController
public function search(Request $request){
$query = $request->input('query');
$result = Photo::search($query)
->with('albums')
->get();
return view('search.results')->with('result', $result);
}
This relationship worked prior to using Nicolaslopezj Searchable.
You have an extra s in your relationship.
Replace
$result = Photo::search($query)
->with('albums')
->get();
by
$result = Photo::search($query)
->with('album')
->get();

Entity saving to database wrong date format codeigniter 4

My entity looks like this:
class Request extends Entity
{
protected $casts = [
'id' => 'integer',
'added_at' => 'datetime',
'deadline' => 'datetime',
'completed' => 'integer'
];
}
When saving, the model generates the date fields in 'Y/m/d' format for the sql query, hovewer my database can not parse this. How can I force it to generate dates in 'Y-m-d' format when calling $myModel->insert($myEntity) ?
Entities has the option of setters. It performs the validation or conversion in your case whenever you perform save an entity. Lets say you want to change the form of deadline in that case you have to set the Setter for your deadline as follow :
public function setDeadline(string $dateString)
{
$this->attributes['deadline'] = $dateString;
return $this;
}
In the following line : $this->attributes['deadline'] = $dateString; You will use some library like Carbon to format the $dateString and then reassign your variable deadline. Reference link :
https://codeigniter4.github.io/userguide/models/entities.html

Laravel merge a relation

How can I merge my Laravel code to have only one collection? I have the following
$users = User::with(['messages'=> function($query) {
$query->select('sender');
}])->with(['files' => function($query) {
$query->select('size');
}])->get(['name']);
I expect my results to be
[
{
"name": "user 1",
"sender": "user 3",
"size": "3 MB"
}
]
You wrote messages and files as plural mean its a OneToMany, mean messages and files should retrieve a collection of object
Anyway if its for an API (as i see you want to return json) you could use the laravel ressources (https://laravel.com/docs/5.7/eloquent-resources) and prepare your object
return [
'name' => $this->name,
'sender' => $this->messages->sender,
'size' => $this->files->size
]
When you are using with() relation, the resultant collection will have the relative collections inside it.
In your case :
user_collection
- userdata
.
.
- file_collection
- message_collection
Now, there are few ways you can do it :
1. Have a join query :
$users = User::join('messages', 'messaged.user_id', '=', 'users.id')
->join('files', 'files.user_id', '=', 'users.id')
->select('users.name', 'files.size', 'messages.sender')
->get();
2. Format data using resources :
Resources are a kind of mapper or modifier which will return the response in format you like. It standardises the response the way you want it.
You can create app\Http\Resources\UserResource.php:
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class User extends JsonResource
{
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function toArray($request)
{
return [
'size' => $this->files->size,
'sender' => $this->messages->sender,
'name' => $this->name
];
}
}
And then inside controller :
return new UserResource(User::find(1));
The advantage is that if you want messages to look certain way, you can nest the Resource classes. The documentation has detailed examples.

Resources