Eloquent set updated_at value with creating. Ho can fix it? - laravel

In Eloquent when instantiating the model established by the two timestamps - created_at and updated_at with the same values. But according to the logic when you create a label should be established whether the created and the label is updated the next time you upgrade. How to fix it?
Eloquent 5.2, created_at and updated_at in db is integer (protected $dateFormat = 'U')
UPDATE - when I use the method, the properties created_at and updated_at is still updated at the same time. That is the first action - the creation, are set equal. The second action - update. Again, both fields are updated and they have the same value.

This is how Laravel does things sometimes, not letting the updated_at null is also a way to avoid problems with not null constraints. But you can fix that for you, if you please. You probably will be able to do something like this:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model as Eloquent;
class BaseModel extends Eloquent
{
public function save(array $options = [])
{
$saved = parent::save($options);
if ($this->wasRecentlyCreated) {
$this->updated_at = null;
parent::save($options);
}
return $saved;
}
}
And use this BaseModel in all your models

Related

laravel current timestamp in migration with carbon

I want to display created_at as a timestamp like this :
created_at : 1625501162
so this is my created_at column in migration:
$table->string('created_at')->Carbon::now()->timestamp;
Now I want this field to be created automatically when a new record is created and record the current time. so when i change the line to this :
$table->string('created_at')->useCurrent(Carbon::now()->timestamp);
gives me this error :
Method call is provided 1 parameters, but the method signature uses 0 parameters
so how can i fix this problem?
What other ways do you suggest for timestamp created_at and store it automatically?
If you want your column to be a timestamp you should use timestamp() instead of string(). useCurrent() doesn't take a parameter. Change
$table->string('created_at')->useCurrent(Carbon::now()->timestamp);
to
$table->timestamp('created_at')->useCurrent();
https://laravel.com/docs/8.x/migrations#column-method-timestamp
https://laravel.com/docs/8.x/migrations#column-modifiers
Edit: to always get a timestamp instead of a date you can use
protected $casts = ['created_at' => 'timestamp'];
in your Model.
Instead of string you may use timestamp() in your migration.
$table->timestamp('created_at')->useCurrent();
Also you may use casting inside model to always get expected format when receiving model.
class Something extends Model {
protected $cast = [
'created_at' => 'timestamp'
];
}
A simpler way is to configure the date format of the model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Flight extends Model
{
/**
* The storage format of the model's date columns.
*
* #var string
*/
protected $dateFormat = 'U';
}
No need to put a default value in the migration. everytime created_at, updated_at and deleted_at(if you use soft delete) is to be updated/filled, it will be in a unix timestamp format
Migration should be an integer
$table->integer('created_at')->nullable(); //you can omit this nullable
$table->integer('updated_at')->nullable(); //you can omit this nullable
// if you use softDelete trait
$table->integer('deleted_at')->nullable();
This is an example of a column createdAt. When a new record is created, it defaults to the date in UNIX format.
$table->integer('createdAt')->default(DB::raw('extract(epoch from now())'));

Adding two created_at on one insert

I want to add another created_at column on the database columns for reference.
I want to have a created_at and created_at1 at the same time.
This is what I have in my Model:
const CREATED_AT = 'created_at1';
protected $dates = [created_at, created_at1];
But I'm receiving this error: Field 'created_at' doesn't have a default value.
You do not need to add casting to the created_at since Laravel has already done it for you.
You need to add inside the string like
protected $dates = ['created_at1']
If you want to set the created_at1 when a new model is created, you can add Model Events.
Inside your model,
protected static function boot(){
parent::boot();
static::creating(function($model){
$model->created_at1 = Carbon::now();
});
}
Inside controller
$model = Model::create([
...
]);
Now it will set created_at and created_at1
For the insert, you have to manually save the value to the created_at1 because it will not reflect the model event.
Model::insert([
...
'created_at1' => Carbon::now()
]);
You might not be passing value to created_at column while inserting data. Please do check. If this is not the case please do provide more information on your problem.

Why is Laravel eloquent returning empty

This is my model
namespace App\Models\Invitation;
use App\Models\Model;
class SendtoType extends Model
{
}
When i get data from SendtoType it return empty or null but i sure sendto_types table has datas
$types = SendtoType::all();
dd($types); // return empty collection
$types = SendtoType::find(1);
dd($types);// null
It's happend after i run php artisan command:reset_table sendto_types command.
I cleared cache but it's not working.
Thank you everyone, i found my mistake:
i set timestamp for table's deleted_at column but forgot to set not null so it also filled deleted_at column when i add data.
That's why eloquent clause return empty.
So silly mistake!
You can add protected $table = 'sendto_types'; inside your model class with actual table name in your database.
class SendtoType extends Model
{
protected $table = 'sendto_types';
}
Command command:reset_table is not a built in command, so you'd need to look at your source code to see what it does, but by the name of it, I would assume the command empties your table.
In this case, your table is empty, so your query will not return any results.

Laravel 5 > touch pivot table (Many-to-Many)

Why is the updated_at field in my pivot table not updating giving the following setup?
Model
class Conversation extends Model {
public function users()
{
return $this->belongsToMany('App\User')->withTimestamps();
}
}
Controller
$conversation = Conversation::find($id);
$conversation->users()->touch();
The last line should - as far as I understand the whole thing - also update the pivots table updated_at field, shouldn´t it?
But it isn´t. Right now I have to do it manualy via a DB query.
I think the best way to do this is:
$conversation->users()->updateExistingPivot(
$conversation->users()->get(),
['updated_at' => date('Y-m-d H:i:s')]
);
It works for me (Laravel 5.7).

Conditional association on query

I have two models:
class Table extends Eloquent {
protected $table = 'tables';
public function sessions() {
return $this->hasMany('Sessions');
}
}
class Sessions extends \Eloquent {
protected $table = 'sessions';
public function table() {
return $this->belongsTo('Table');
}
}
(I call it Sessions instead of Session because Laravel was having trouble confusing classes).
Table refers to an actual diner table and a session is just someone or some group using it.
So, I come to the table, seat down, start a session, eat, pay, close session and leave. You then come and sit on the very same table, which corresponds to a new session.
Now, this is how I'm querying my table:
$table = Table::where('id', '=', $id)->with('sessions')->first();
However, my table comes with all it's related sessions. How should I go about querying:
-Returns table + single session if the table has a session which is open(Session.closed_at = '0000-00-00 00:00:00').
-Returns table only with no associated records if it has no open sessions.
How should I go about building this very same query in my Controller and in my model(such as Table::getWithSessions($id)).
Thanks.
Addendum:
Soon I will have a quite more complex relationship:
A table has many sessions(which only one matters, the active one), which has many cards(each person may get their individual cards), which can have many orders. Order are a join between a card and a item, which points to an product or many of them(for example, a kit with several different beers).
I would appreciate any insight on how to build this kind of relationship with eloquent and get all playing nicely(such as being able to query for the tables and get all orders for all cards related to the current session).
You can filter the models to eager load by using a closure in with() to define your conditions. Also you can use find() instead of where('id',... ->first():
$table = Table::with(['sessions' => function($q){
$q->where('closed_at', '0000-00-00 00:00:00');
}])->find($id);
Note that because the normally relationship returns a collection, it will still return one. So when accessing the session you need to use: $table->sessions->first() to get the current one.
To get tables without an open session, simply use whereDoesntHave:
$tables = Table::whereDoesntHave('sessions', function($q){
$q->where('closed_at', '0000-00-00 00:00:00');
})->get();
Edit
For a call like Table::getWithSessions($id) you have two options.
1. static method
Create a static method like this:
public static function getWithSessions($id){
return static::with(['sessions' => function($q){
$q->where('closed_at', '0000-00-00 00:00:00');
}])->find($id);
}
2. Use scopes
With a scope you can do something like:
Table::withOpenSessions()->find($id);
This is the scope method:
public function scopeWithOpenSessions($query){
return $query->with(['sessions' => function($q){
$q->where('closed_at', '0000-00-00 00:00:00');
}]);
}

Resources