Call another observer method in current model observer - laravel

In laravel I want to call another observers deleting method in my current model observer. Is that possible?
for example lets say I have observers for product and category, So I want to call productobservers deleting method in categoryobservers deleting loop.
public function deleting(Category $Category)
{
DB::transaction(function () use($Category) {
$Category->products->each(function ($products) {
//call product observer deleting function
});
});
}

You can set your event in this array like this
class User extends Authenticatable
{
protected $dispatchesEvents = [
'saved' => UserSaved::class,
'deleted' => UserDeleted::class,
];
}
and create listener for those events

Related

fire event on pivot sync in Laravel

i have a pivot model
class UserRoles extends Pivot
{
protected $table="user_roles";
}
i am using syncWithoutDetaching to update the pivot table
$user->roles()
->syncWithoutDetaching(
[ $roleId => [ 'is_active' => $value]]
);
the relation roles() is already using the pivot model class and i created an observer in order to detect the updated event on the pivot model
class UserRolesObserver
{
public function created()
{
Log::info("event fired");
}
public function updated()
{
Log::info("event fired");
}
public function saved()
{
Log::info("event fired");
}
the observer's updated event isn't being fired even when the update is done
Pivot tables do not fire events. You would need to utilize a package like this one to fire pivot events: https://github.com/GeneaLabs/laravel-pivot-events.
Once you install that package you can utilize pivotAttaching and pivotAttached methods on the Observer.

How to update one to many polymorphic relationship?

How to update multiple records in One to many polymorphic relationship?
I want to update the fields as a group, but how?
Skill Model:
class Skill extends Model
{
use HasFactory;
protected $fillable = ['title', 'percentage'];
/**
* Get the owning skillable model.
*/
public function skillable(): MorphTo
{
return $this->morphTo();
}
}
User Model:
class User extends Model
{
use HasFactory;
/**
* Get all of the skill's user.
* #return MorphMany
*/
public function skills(): MorphMany
{
return $this->morphMany(Skill::class, 'skillable');
}
}
There are a number of ways to do so:
$user->skills->each(function ($skill) {
$skill->update([...]);
});
$user->skills->each(fn($skill) => $skill->update([...]));
$user->skills->each->update([...]);
$user->skills()->update([...]);
I recommend the first three approaches. Because if there are any model events, those will be fired. Model events won't be fired in the fourth one.
Specifically to your problem, you might want to do something like this in the controller:
public function update()
{
$skills = collect(request('skill_titles'))
->zip(request('skill_percentages'))
->map(function ($pair) {
return [
'title' => $pair[0],
'percentage' => $pair[1],
]
});
$skills->each(function ($skill) use ($user) {
$user->skills()->where('title', $skill['title'])
->update($skill['percentage']);
});
}
you can use update method
// make sure you have the desired attributes in fillable array property in your model class
$model->related_model->update([inputs]);
if you write the relationship methods "related_method" in model class correctly you can use them as properties of your model and access their attributes or update them.

How to detect update event in model in Laravel 8

Good day to all
The situation is as follows
In the controller, in the update method, I try to update the object
There is an image in the fields of this object
Wrote a trait to process this field and load an image
In the model itself, I called the update method, which just determines the event of updating the object
The problem lies in the following image in the specified directory is loaded and the entry itself in the database does not change
Here is my code
Controller
Model
Trait
There is extra code in the model
public function update(Request $request, MainHeader $mainHeader): RedirectResponse
{
$mainHeader->update([
'language_id' => $request->language_id,
'brandLogoImage' => $request->file('brandLogoImage'),
'homeTitle' => $request->homeTitle,
'ourProjectsTitle' => $request->ourProjectsTitle,
'contactTitle' => $request->contactTitle,
'feedbackTitle' => $request->feedbackTitle,
]);
return redirect()->route('admin.header.index')->with('success', 'Данные успешно обновлены');
}
public function setBrandLogoImageAttribute($value): string
{
return $this->uploadImage('brandLogoImage', $value);
}
public function update(array $attributes = [], array $options = [])
{
$this->uploadImage('brandLogoImage', $attributes['brandLogoImage']);
$this->setBrandLogoImageAttribute($attributes['brandLogoImage']);
return parent::update($attributes, $options); // TODO: Change the autogenerated stub
}
protected function uploadImage(string $attr, $value): string
{
$uploadDir = public_path('uploads/');
$imageDir = public_path('uploads/image/');
if (!file_exists($uploadDir)){
mkdir($uploadDir);
}
if (!file_exists($imageDir)){
mkdir($imageDir);
}
if (!file_exists(public_path("uploads/image/$this->table/"))){
mkdir(public_path("uploads/image/$this->table/"));
}
$imageName = Str::random(12) . '.png';
Image::make($value)->save(public_path("uploads/image/$this->table/$imageName") , 100);
return $this->attributes[$attr] = (string) "uploads/image/$this->table/$imageName";
}
if you call the update methode in your model then you are overriding the default update() of the model class , its not listening to the event it simply runs your code before parent:: , so you need to make sure that the changes you are making does not get overwitten by the parent call .
regarding your question on how to detect update , if you want to perform anything before update than i advise you to use eloquent events or use observers , Observers listen to various events regarding your model like updating or updated .. but i think if its only for updating event than you should use event using closure
for example :
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* The "booted" method of the model.
*
* #return void
*/
protected static function booted()
{
static::updating(function ($user) {
// do what you want
});
}
}
If your pupose

How to fix error Method Illuminate\Database\Query\Builder::attach does not exist. Attaching multiple items

I'm trying to attach "items model" to "events model.
Item Model:
public function events()
{
return $this->belongsToMany('App\Event', 'event_item');
}
Event Model
public function items()
{
return $this->belongsToMany('App\Item', 'event_item');
}
User Model
public function items()
{
return $this->hasMany('App\Item', 'user_id');
}
EventsController
public function store(Request $request)
{
// Get user
$user = $request->user();
// Create event
$event = Event::create(array_merge($request->all(), ['user_id' => $user->id]));
// Attach items to event
$user->items()->attach($event->id);
}
My user has multiple items. All user items need to be attached to events on store function.
I get this error Method Illuminate\Database\Query\Builder::attach does not exist.
I was able to figure this out, easy mistake actually. I want to attach items to events but in my original question I have users attaching to items.
Changed this:
// Attach items to event
$user->items()->attach($event->id);
To this:
// Attach items to event
$event->items()->attach($user->items);
Works as expected now.
User Model:
return $this->hasMany('App\Item', 'item_id');
Your User model items function has to return a BelongsToMany relationship in order to use attach().
User Model:
public function items() {
return $this->belongsToMany('App\Item');
}

How to create custom model events laravel 5.1?

I want to create a custom model event in laravel 5.1.
For e.x. when an Articles category is updated i want to make an event and listen to it.
$article = Article::find($id);
$article->category_id = $request->input('category_id');
// fire an event here
You should use Eloquent Events (do not confuse with Laravel Events).
public function boot()
{
Article::updated(function ($user) {
// do some stuff here
});
}
You would want to look into Observers to make this more reusable and single-responsible, though a starting point would be something alike:
public function boot()
{
self::updated(function ($model) {
if (array_key_exists('category_id', $model->getDirty())) {
// Log things here
}
});
}
Laravel will populate a 'dirty' array which contains modified fields. You can detect when a certain field has changed using this.
You also have:
$model->getOriginal('field_name') // for this field value (originally)
$model->getOriginal() // for all original field values
You can use Attribute Events to fire an event when the category_id attribute changes:
class Article extends Model
{
protected $dispatchesEvents = [
'category_id:*' => ArticleCategoryChanged::class,
];
}

Resources