Delete all of relationship with static::deleting model - laravel

I've tried using event handler for delete the relation but it can't work for delete relation of relation. Event hasMany Person and Person hasMany File
class Event
public static function boot() {
parent::boot();
static::deleting(function($model) { // before delete() method call this
$model->person()->delete();
});
}
}
class Person
public static function boot() {
parent::boot();
static::deleting(function($model) { // before delete() method call this
$model->files()->delete();
});
}
}
So when I delete event, it can delete person but it doesn't delete the files row. What should I do?

You should call it one by one to call boot method on each model instance. So, get the instances and then delete them one by one.
class Event
public static function boot() {
parent::boot();
static::deleting(function($model) { // before delete() method call this
foreach($model->person as $person){
$person->delete();
}
});
}
}
class Person
public static function boot() {
parent::boot();
static::deleting(function($model) { // before delete() method call this
foreach($model->files as $file){
$file->delete();
}
});
}
}

Related

Laravel Observer not triggered on UpdateorCreate

I have Model Model1 where I want to update a particular column rank on saved.
protected static function boot()
{
parent::boot();
static::saved(function ($model) {
$service = new Service();
$service->updateRank($model->id);
});
}
I put a log inside the saved. but it is not called
You should use method booted.
protected static function booted()
{
static::saved(function ($model) {
$service = new Service();
$service->updateRank($model->id);
});
}

Fetch the data of parent model into static::saving() boot function

I want to use data from the parent model to run the saving() function in the child model
Previously, I inserted a computed data to the table in model "Loan" but now I need to insert it into a child model "InterestAmount"
Loan.php
use Illuminate\Database\Eloquent\Model;
class Loan extends Model
{
protected $fillable ['amount','interest','status','duration','member_id','loan_type_id','interest_type_id','loan_payment_type_id'];
//protected $appends = 'interest_amount
protected static function boot()
{
parent::boot();
static::saving(function($model) {
$model->interest_amount = ($model->amount/100 )* $model->interest;
});
}
public function interest_amount()
{
return $this->hasMany(InterestAmount::class,'loan_id','id');
}
}
I want to remove the saving function from Loan.php and use as below.
Interest.php
use Illuminate\Database\Eloquent\Model;
class InterestAmount extends Model
{
public function loan()
{
$this->belongsTo(Loan::class,'loan_id','id');
}
protected static function boot()
{
parent::boot();
static::saving(function($model) {
$model->interest_amount = ($model->amount/100 )* $model->interest;
});
}
}
How do I fetch "amount" and "interest" in this function?
The $model variable inside InterestAmount model refers to an InterestAmount object :
static::saving(function($model){
$model->interest_amount = ($model->loan->amount/100 )* $model->loan->interest;
});
Then you need to get the related loan using your relationship method loan() then get the properties amount/interest.
NOTE: As #namelivia's comment says you're missing the return in the loan() method:
public function loan()
{
return $this->belongsTo(Loan::class,'loan_id','id');
}

How to implement event/listeners with repository pattern in laravel 5.4

I can't make listeners trigger action update, create or delete when I user patter repository.
Addionally I have added my code in order to help my to solve my problem.
TicketController.php
namespace App\Http\Organizer\Controllers;
use App\Http\Controllers\Controller;
use App\Http\Events\Contracts\IEvent;
use App\Entities\Event;
class TicketController extends Controller
{
protected $IEvent;
public function __construct( IEvent $IEvent )
{
$this->IEvent = $IEvent;
}
public function checkFutbolType ($activityId)
{
// I need to listen this action here
$event = $this->IEvent->update(21927, ['title'=>'new title']);
}
}
My RepoEvent.php:
<?php
namespace App\Http\Events\Repositories;
use App\Http\Events\Contracts\IEvent
;
class RepoEvent implements IEvent
{
protected $model;
public function __construct($model)
{
$this->model = $model;
}
public function update($activityId, $params)
{
return $this->model->where('id', $activityId)->update($params);
}
}
My AppServiceProvider.php
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\Entities\Event;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
//event: creating
Event::creating(function (Event $event) {
return $event->creatingEvent();
});
//event: saving
Event::saving(function (Event $event) {
return $event->savingEvent();
});
//event: updating
Event::updating(function (Event $event) {
return $event->updatingEvent();
});
}
}
My interface IEvent.php:
<?php
namespace App\Http\Events\Contracts;
interface IEvent
{
public function update($activityId, $params);
}
My ServicesOrchestration.php:
<?php
namespace App\Http\Administration\Providers;
use App\Entities\Event;
use App\Http\Administration\Repositories\RepoEvent;
use Illuminate\Support\ServiceProvider;
class ServicesOrchestration extends ServiceProvider
{
public function boot()
{
}
public function register()
{
$this->app->bind('App\Http\Administration\Contracts\IEvent', function () {
return new RepoEvent(new Event());
});
}
}
My model Event.php
<?php
namespace App\Entities;
use Illuminate\Database\Eloquent\Model;
class Event extends Model
{
public function creatingUser() {
\Log::info('creating event');
}
public function savingUser() {
\Log::info('saving event');
}
public function updatingUser() {
\Log::info('updating event');
}
}
thanks in advance.thanks in advance.thanks in advance.thanks in advance.thanks in advance.thanks in advance
Here's the relevant snipped from the docs (scroll to mass updates):
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.
For your code to work you need to first retrieve the actual model instance like below:
public function update($activityId, $params)
{
$instance = $this->model->find($activityId);
$instance->fill($params);
$instance->save();
}
This will have an additional cost of doing two queries instead of one and only being able to update a single model at a time.
A sidenote: You're passing a model instance to the repository but what you actually want is to pass a query builder instance:
$this->app->bind('App\Http\Administration\Contracts\IEvent', function () {
return new RepoEvent(Event::query());
});

eloquent events, can I use them in model class?

I am reading up on laravel softdelete and restore cascade here: Laravel 5: cascade soft delete
where a user said:
You should use Eloquent events for this.
Offers::deleted(function($offer) {
$offer->services()->delete();
});
Offers::restored(function($offer) {
$offer->services()->withTrashed()->restore();
});
He did not mention where to place this code, I am interested in listening for eloquent deleted and restored events. Where can I put this code? Can I listen for it in the model class? If not where to place it?
I think...
<?php
class Attribute extends Model implements Transformable
{
//....
protected static function boot() {
parent::boot();
static::deleting(function($model) {
foreach ($model->attributeValue()->get() as $attributeValue) {
$attributeValue->delete();
}
});
}
Or example:
class BaseModel extends Model
{
public static function boot()
{
static::creating(function ($model) {
// blah blah
});
static::updating(function ($model) {
// bleh bleh
});
static::deleting(function ($model) {
// bluh bluh
});
parent::boot();
}
}

Laravel Eloquent ORM - removing rows and all the child relationship, with event deleting

I have three models that relate to each other one to many:
Country
class Country extends Model
{
protected $fillable=['name','sort'];
public $timestamps=false;
public function region(){
return $this->hasMany('App\Models\Region');
}
}
Region
class Region extends Model
{
protected $fillable=['country_id','name','sort'];
public $timestamps=false;
public function country()
{
return $this->belongsTo('App\Models\Country');
}
public function city()
{
return $this->hasMany('App\Models\City');
}
}
City
class City extends Model
{
protected $table='cities';
protected $fillable=['region_id','name','sort'];
public $timestamps=false;
public function region()
{
return $this->belongsTo('App\Models\Region');
}
}
When we remove the country automatically, remove all child item relationship, that is, removed and regions and city this country
I am doing so:
Model Country
public static function boot() {
parent::boot();
static::deleting(function($country) {
//remove related rows region and city
// need an alternative variation of this code
$country->region()->city()->delete();//not working
$country->region()->delete();
return true;
});
}
}
OR
Model Region
public static function boot() {
parent::boot();
// this event do not working, when delete a parent(country)
static::deleting(function($region) {
dd($region);
//remove related rows city
$region->city()->delete();
return true;
});
}
}
options with cascading deletes database, please do not offer
UPDATE
I found the answer
use closure for query builder, to remove related models
Model Country
public static function boot() {
parent::boot();
static::deleting(function($country) {
//remove related rows region and city
$country->region->each(function($region) {
$region->city()->delete();
});
$country->region()->delete();//
return true;
});
}
Laravel Eloquent ORM - Removing rows and all the inner relationships
Just a quick recap:
$model->related_model will return the related model.
$model->related_model() will return the relation object.
You can do either $model->related_model->delete() or $model->related_model()->get()->delete() to access the delete() method on the model.
Another way of handling the deletion of related (or sub) models is to use foreign key constraints when you write your migrations, check https://laravel.com/docs/master/migrations#foreign-key-constraints
I think you can do this in the delete function of the parent object:
public function destroy_parent($id)
{
$parent = PARENT::find($id);
foreach ($parent->childs as $child){
$child->delete();
}
$parent->delete();
return redirect(...);
}

Resources