Override boot function when insert function calling in Laravel - php

I have override boot function inside the laravel model, code structure something like this:
class modelName extends Model
{
protected static function boot(){
parent::boot();
self::creating(function ($model){
//Do Some Stuff
});
}
This is working fine when I'm calling create a function, like this:
modelName::create($tmpArray);
But it's not working when I want to use insert function:
modelName::insert($tmpArray);
Now I want to call boot function when insert function called, I've two-dimensional array; in that case, I've only insert function to save data in a single row.

Events are only called when using the Eloquent functions to save/update/delete records.
If you want events to be triggered when saving multiple records, you could try to use Model::createMany($arrayOfObjects). However, checking the source code for this function, it will actually run a separate query for each record that's in the array. So if you got a whole lot, you might need to think of a different route.

creating is event of eloquent model.
insert() is not method of eloquent model, its method of db queries.
try to use eloquent method instead of db query.
see laravel doc for eloquent methods
see Db queries method

for two two-dimensional array can use eloquent method of createMany or saveMany
difference between save and create is that save accepts a full Eloquent model instance while create accepts a plain PHP array.
you can refer laravel docs Inserting & Updating Related Models

Related

Call a Model method using Laravel Relationship

I'm currently trying to use Laravel Relationships to access my achievements Model using User model, I use this relationship code:
public function achievements()
{
return $this->hasMany('App\Models\User\Achievement');
}
I can easily make some eloquent queries, however I can't access any method that I created there, I can't access this method:
class Achievement extends Model
{
public function achievementsAvailableToClaim(): int
{
// Not an eloquent query
}
}
Using the following code:
Auth::user()->achievements()->achievementsAvailableToClaim();
I believe that I am using this Laravel function in the wrong way, because of that I tried something else without using relationship:
public function achievements()
{
return new \App\Models\User\Achievement;
}
But that would have a performance problem, because would I be creating a new class instance every time I use the achievements function inside user model?
What would be the right way of what I'm trying to do?
it's not working because your eloquent relationship is a hasMany so it return a collection. you can not call the related model function from a collection.
you can var dump it on tinker to understand more what i mean.
You can use laravel scopes.Like local scopes allow you to define common sets of constraints that you may easily re-use throughout your application.
In your case you use this like, Define scope in model:
public function scopeAchievementsAvailableToClaim()
{
return $query->where('achivement_avilable', true);
}
And you can use this like :
Auth::user()->achievements()->achievementsAvailableToClaim();

Pass variable to laravel model boot

I use laravel 5.8 for my application. I have variables call "lot" and when I delete one, I want to perform other actions.
So I use deleting function on my model, everything works OK.
But know I have a function on my controller to delete many "lots" and I want actions to be perform only when all "lots" have been delete and not on every "lots" delete.
So I wonder if there is a way to achieve this ? Maybe we can pass a variable to boot functions to trigger or not the function ?
My model looks like this :
protected static function boot()
{
parent::boot();
static::deleted(function($modele) {
Etage::doesntHave('lots')->delete();
}
}
Model events are been designed to work for single models.
You should use Laravel Events instead, not tied to Models.
In EventServiceProvider.php register a new Event/Listener in the $listens array, like
LotsDeleted::class => PerformOtherAction::class
Create those classes with php artisan event:generate
Then, when you have finished deleting all your Lot objects, trigger the event with
event(new LotsDeleted());
The handle() function of your listener will be called and you can perform other actions.

Laravel model event won't fire

I'm using ajax to update my model User, the ajax part works fine since the data is updated successfully in the database, inside my controller action the update performed by :
$user->update($data);
The part that doesn't work:
I've used boots method updated inside my model like :
class User extends BaseModel
{
...
public static function boot()
{
parent::boot();
self::updated(function($model){
Log::info("updated");
dd($model);
});
}
}
The event was never reached I'm not sure why.
Problem:
I'm trying to perform an action after the model update but the event doesn't fire.
Here's what the manual states with update()
When issuing a mass update via Eloquent, the saved and updated model events will not be fired for the updated models. This is because the models are never actually retrieved when issuing a mass update.
You need to use save to trigger events. Something like:
$user->fill($data);
$user->save();
This of course is assuming that $user is a model and not a query builder instance.
You are accessing the function statically:
instead try using
self::updated(function($model){
Log::info("updated");
dd($model);
});

how to run custom code after every $model->save() function in yii2

I want to execute my custom code after or before every $model->save() in Yii2.
I want to perform this globally like using components, etc.
I want to create a user activity log to store how many times a user insert or update any rows in database table, so for this I want to run some code when ever data inserted or update in tables.
Any help or suggestion will appreciated.
As #patryk mentioned ActiveRecord has beforeSave and afterSave methods.
I use something like the following to store a created date for new records (and updated date when existing records are updated). The code in the example is, of course, trivial but it allows you to use any arbitrary code you need, see the layout and how to split code for 'new' records and existing.
This overridden method can be added to any model class which extends ActiveRecord to allow the parent beforeSave to be called correctly also.
/**
* #inheritdoc
*/
public function beforeSave($insert)
{
if ($insert) {
// This is a new instance of modelClass, run your 'insert' code here.
$this->created_date = time();
}
// Anything else will be run any time a model is saved.
$this->updated_date = time();
return parent::beforeSave($insert);
}
edited to add:
if the code to be run is the same for each model you could create a trait and use the trait in each model to allow you to change the behaviour in one place. Or create a custom ActiveRecord class to override the beforeSave method for each subclass.
Create new class(MyActiveRecord) which extends \yii\db\ActiveRecord
Use extends MyActiveRecord to all your project models
Ex:
class MyActiveRecord extends \yii\db\ActiveRecord
{
public function afterSave($insert, $changedAttributes){
//This will called after every model saved
return parent::beforeSave($insert,$changedAttributes);
}
}
In your project other models
class Customer extends app\models\MyActiveRecord
{
}
Yii2 ActiveRecord class has beforeSave and afterSave methods. https://github.com/yiisoft/yii2/blob/master/framework/db/BaseActiveRecord.php#L926
But maybe it would be better to do such operation on database triggers?

laravel's model gets request info from controller

I have a problem with code using Laravel. I define an attribute in a model to get a list. It takes a lot of time. I use this model in a controller. Follow the code:
protected $appends=["consume_info"];
public function getConsumeInfoAttribute(){
//query a lot of information from mysql
}
I'm wondering if there is an attribute in Controller or Model to avoid a query with mysql in model.
Is there a setting to tell Laravel when to load this appended attribute or not?
Why not just remove the consume_info from $appends array. You will get the $model->consumer_info and that too only when you need this.

Categories