Laravel eloquent updateOrCreate(), do something only if create? - php

I use in my laravel 5.5 app Model::updateOrCreate(), it works, but by 1 parameter I wish to do something only if entry is creating and not updating model, is this possible?

The updateOrCreate returns a model instance where you can check for recent creation
An example could be the following pseudo code
$model = Model::updateOrCreate($data);
if($model->wasRecentlyCreated) {
// Do logic only when the model was created
}

Related

Manipulate request data using backpack 4.1

I'd like to change a data before saving I have a date where I don't need seconds only minutes, and I want the seconds to be 00 all the time. I tried Laravel's prepareForValidation() method in my request class, but it turned out it does not affect value stored in database. I also tried backpack's modifyField() but I couldn't find a way to modify value before store or update.
What's the best way to perform this? Using Laravel7 and Backpack 4.1
I don't know if there's a specific backpack way of doing it, but you can use a mutator on your model to modify the value before it gets saved to the database.
In your case, if your fieldname is "date_time" you could do something like:
class MyModel extends Model {
setDateTimeAttribute ($value) {
$value = Carbon::parse($value)->second(0);
$this->attributes['date_time'] = $value;
}
}
This has the benefit that the mutation will occur every time your date_time attribute is updated - whether you update it through your Backpack Crud or from some other method.
References:
Laravel Mutators: https://laravel.com/docs/7.x/eloquent-mutators#defining-a-mutator
Modifying Dates with Carbon: https://carbon.nesbot.com/docs/#api-settersfluent

Does a one-to-one relationship in Laravel always need first()?

I have a one-to-one relationship between User and UserSettings models,
But (after $user = auth()->user()) when I try $user->settings()->something it throws an Undefined property error.
It's gone when I use $user->settings()->first()->something...
My question is, is this how it's supposed to work? or am I doing something wrong?
You cannot directly run $user->settings()->something.
Because when you call $user->settings(), it just return Illuminate\Database\Eloquent\Relations\HasOne object.
So it is not the model's object, you need to take the model's object and call its attribute like this.
$user->settings()->first()->something;
Dynamic Properties
Since you have one-to-one relationship between User and UserSettings.
If you have a one-to-one relationship in your User model:
public function settings()
{
return $this->hasOne('App\Models\UserSettings', 'user_id', 'id');
}
According to Laravel doc
Once the relationship is defined, we may retrieve the related record using Eloquent's dynamic properties. Dynamic properties allow you to access relationship methods as if they were properties defined on the model:
Eloquent will automatically load the relationship for you, and is even smart enough to know whether to call the get (for one-to-many relationships) or first (for one-to-one relationships) method. It will then be accessible via a dynamic property by the same name as the relation.
So you can use eloquent's dynamic properties like this:
$user->settings->something; // settings is the dynamic property of $user.
This code will give you a result of collection.
$user->settings;
So calling 'something' is not available or it will return you of null, unless you get the specific index of it.
$user->settings()->something
while this one works because you used first() to get the first data of collection and accessed the properties of it .
$user->settings()->first()->something
The first method returns the first element in the collection that passes a given truth test
see docs here laravel docs
If you want to get the user settings itself simply do this:
$user->settings
Then you can get the fields of the settings doing this:
$user->settings->something
When you do this $user->settings() you can chain query after that. E.g.
$user->settings()->where('something', 'hello')->first()
That's why the output of $user->settings and $user->settings()->first() are the same.
Auth only gives you user info;
Try the following code:
$user = User::find(auth()->user()->id);//and then
$user->settings->something;

wasRecentlyCreated and wasChanged are not working

I am trying to use wasChanged and wasRecentlyCreated of models in laravel project but both of them are false in the below code
$saved=$project->accessInfo()->updateOrCreate(['type'=>$request->type],['value'=>$data]);
dd($project->accessInfo[0]->wasChanged(),$project->accessInfo[0]->wasRecentlyCreated,$project->wasRecentlyCreated,$project->wasChanged());
//here is my relation in Project model
public function accessInfo()
{
return $this->hasMany('Modules\Project\Models\ProjectAccessInfo', 'project_id');
}
also below code returns error
dd($project->accessInfo->wasChanged(),$project->accessInfo()->wasRecentlyCreated)
//No such method or attribute in both cases
//Call to undefined method Illuminate\\Database\\Eloquent\\Relations\\HasMany::wasChanged()
Thanks in advance for your help.
getChanges - Get the attributes that were changed.
getDirty - Get the attributes that have been changed since last sync.
When you want to know if the model has been edited since it was queried from the database, or isn't saved at all, then you use the ->isDirty() function.

Accessing Eloquent Relationship Automatically when loaded

I am working on a project which requires me to get all the list of all information from a table --Just like in a blog, i used the all() method to do this but when i try to get the method i declared in my Model i get an error, saying
the collection instance does not exists
But when i use The
Model::find($id)->relationship()->name;
it works fine. Is there any way to load all relationship with the all() function in laravel.
Thanks for your help..
When you perform Model::find($id)->relationship(); you are actually accesing to the Dynamic relationships Properties
You need to convert it into a collection using Model::find($id)->relationship()->get();
Then you can perform any collection method to get the result you want. After doing this you can access to its attributes like this:
$model_varible = Model::find($id)->relationship()->get();
$model_variable = $model_variable->find($id)->name;
Let me know if this works for you.
You should use relationship without brackets to access the model:
Model::find($id)->relationship->name;
And use "with()" to populate the relationships:
Model::where('published', 1)->with('relationship')

how can do a multiple has() /orHas() in laravel 5.4 orm

First of all I should say I want to Use laravel ORM not query builder and not the Raw sql methods. so here is my question.
I have a model called bots that has belongTo(User::class) relation and 6 hasMany(TextPost::class) - hasMany(PhotoPost::class) and so on. I want to get bots that has at least one record in any of the hasMany(...) relations. so if a bot has a record in TextPost it should be returned and if a bot has no post in none of the hasMany(...) relations it should not be returned.
so far I have something like this in my User model
public function broadCasters()
{
return $this->bots->has('text_post')->orHas('photo_post')->orHas('media_post')->orHas('video_post')->orHas('audio_post')->orHas('document_post');
}
but its not going to work and says Call to a member function orHas() on boolean
so I wanted to change it to something like this:
public function broadCasters(){
return $this->bots->where(function($query){
return $query->has('TextPost')->orHas('PhotoPost') ...;
});
}
but this is not gonna work either and says Missing argument 2 for Illuminate\Support\Collection::where(). what should I do?
I use laravel 5.4. bu I saw this Question whereHas on multiple relationships - laravel 5.4 and its pretty close to what I want but no answers yet!!
also this question is another of my questions too, Combining AND/OR eloquent query in Laravel
but its not working either.
AND NOW THIS IS EXACTLY WHAT I WANT BUT NOT WORKING, I THINK BECAUSE ITS FOR LARAVEL 4 AND I USE LARAVEL 5.4
Laravel eloquent multiple has and where clause
enter code hereIf you user $this->bots, the result will be laravel collection array. You need to use $this->bots() like this :
public function broadCasters(){
return $this->bots()->where(function($query){
return $query->has('TextPost')->orHas('PhotoPost') ...;
})->get();
}

Categories