using observers to delete all relations in Laravel - laravel

My tables structure is :
Shopsidname
Productsidnameshop_id
Product_tagsidlabelvalueproduct_id
Problem is: I want to delete products and product tags on deleting shop
I made two Observers and registered both :
ShopObserver
ProductObserver
ShopObserver :
public function deleting(Shop $shop)
{
$shop->products()->delete();
}
ProductObserver :
public function deleting(Product $product)
{
$product->tags()->delete();
}
But I have following error :
"SQLSTATE[23000]: Integrity constraint violation: 1451 Cannot delete or update a parent row: a foreign key constraint fails (`tabadolha`.`product_tags`, CONSTRAINT `product_tags_product_id_foreign` FOREIGN KEY (`product_id`) REFERENCES `products` (`id`)) (SQL: delete from `products` where `products`.`shop_id` = 26 and `products`.`shop_id` is not null)"
I don't want to use nullOnDelete on my database. I want to delete it by observer.
Any way?

The problem is that your second observer of tags should be fired FIRST, and you can't specify the order of observers in Laravel.
What I would to is delete the tags in the same ShopObserver, before deleting the products, and not create a separate ProductObserver.
Something like:
$shop->products->each(function($product) {
$products->tags()->delete();
});
$shop->products()->delete();
Please test, not sure about the syntax, typed it with phone from my memory :)

Related

Laravel - How to delete child row when parent was deleted?

I have 4 tables as below:
class Job extend Model
{
public function candidates()
{
return $this->hasMany(App\Models\Candidate::class);
}
}
=========================================================
class Candidate extend Model
{
public function skills()
{
return $this->belongsToMany(App\Models\Skill::class);
}
public function job()
{
return $this->belongsTo(\App\Models\Job::class);
}
}
So, when I delete a job. I want to delete all candidates who apply to this job also. But, When I delete I got this message
SQLSTATE[23000]: Integrity constraint violation: 1451 Cannot delete or update a parent row: a foreign key constraint fails (`evaluation_db`.`candidate_skill`, CONSTRAINT `candidate_skills_candidate_id_foreign` FOREIGN KEY (`candidate_id`) REFERENCES `candidates` (`id`)) (SQL: delete from `candidates` where `candidates`.`job_id` = 39 and `candidates`.`job_id` is not null)
I think, it because of skills relation inside candidate class. Could any one help me out? I really appreciate with your help.
Thank you!
You need to define the behaviour in your migration.
Doc : https://laravel.com/docs/8.x/migrations#foreign-key-constraints
$table->foreignId('user_id')
->constrained()
->onUpdate('cascade')
->onDelete('cascade');
Delete child row when parent delete (DeleteWithRelation)
Delete all customers (children) when deleting company (parent)
$companyDetails = Company::find($companyId);
if (!$companyDetails) {
return "Company Not Found.";
}
$companyDetails->customers()->delete();
$companyDetails->delete();

Using sync with many to many relationship in laravel: PostgreSQL Pivot table doesn't update

I'm getting this error whenever i try to sync an array of inputs to a pivot table:
Illuminate\Database\QueryException
SQLSTATE[23503]: Foreign key violation: 7 ERROR: insert or update on table "items_option_parcel"
violates foreign key constraint "items_option_id_fk_2971521" DETAIL: Key (items_option_id)=(0) is not present in table "items_options". (SQL: insert into "items_option_parcel" ("items_option_id", "parcel_id") values (0, 168))
here is a line of my controller:
$parcel->parcel_options()->sync($request->input('parcel_options', []));
function in the first model:
public function parcelOptionsParcels()
{
return $this->belongsToMany(Parcel::class);
}
function in the 2nd model:
public function parcel_options()
{
return $this->belongsToMany(ItemsOption::class);
}
I found out the issue, i checked my pluck() function, i forgot to pluck the items options ID with their SKUs, that's why every time it says a 0 id is not present in the table because it wasn't getting fetched at all.
I changed this:
$parcel_options = ItemsOption::all()>pluck('item_option_sku')>prepend(trans('global.pleaseSelect'), '');
to this
$parcel_options =
ItemsOption::all()->pluck('item_option_sku','id')->prepend(trans('global.pleaseSelect'), '');

laravel 5.4 how to handle query exception with custom exception

whenever I try to delete an artist with the related song in the child table.
it returns this error.
QueryException in Connection.php line 647:
SQLSTATE[23000]: Integrity constraint violation: 1451 Cannot delete or update a parent row: a foreign key constraint fails (`laravel`.`artist_song`, CONSTRAINT `artist_song_artist_id_foreign` FOREIGN KEY (`artist_id`) REFERENCES `artists` (`id`)) (SQL: delete from `artists` where `id` = 1)
this is what I want. to protect the parent table, but what I want is to make the end user see a message saying like this "yOU CAN NOT DELETE AN ARTIST WITH RELATED SONGS PLEASE DELETE ALL SONGS OF THIS ARTIST, FIRST'. so how can I catch this with the custom exception?
I don't think you need to rely here on database exception. When someone chooses deleting artist you should verify whether artist has any songs and if yes, you should then redirect with message.
Assuming you have in Artist model relationship defined like this:
public function songs()
{
return $this->hasMany(Song::class);
}
in controller you could use code like this:
public function destroy($artistId)
{
$artist = Artist::findOrFail($artistId);
if ($artist->songs()->count()) {
return redirect()->back()->with('message','You cannot delete ...');
}
$artist->delete();
return redirect()->route('artists.index');
}

Foreign key constraint fails on nullable field

I have a table organizations. This table has a primary id (int 10, unsigned, AUTO_INCREMENT).
In the table organizations, I also have a foreign key to the iself: main_organization_id. This has the following attributes: (int 10, unsigned, nullable, empty:TRUE, default:NULL).
Whenever I create a new organization:
$organization = Organization::create($request->all());
Without a main_organization_id in my request, it fails with the following error:
SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or
update a child row: a foreign key constraint fails
(myDB.organizations, CONSTRAINT
organizations_main_organization_id_foreign FOREIGN KEY
(main_organization_id) REFERENCES organizations (id)) (SQL:
insert into organizations (main_organization_id) values
())
But why does this fail? The field is nullable, does that mean I have to implicitly set main_organization_id to null in the request?
My $fillable:
protected $fillable = [
'main_organization_id',
];
My migration:
Schema::table('organizations', function (Blueprint $table) {
$table->integer('main_organization_id')->unsigned()->nullable();
$table->foreign('main_organization_id')->references('id')->on('organizations');
});**strong text**
I want to prevent code like this: $request['main_organization_id'] = null; before creating my new row. Is this possible?
Thank you for reading.
Yes, you should specify the field value while creating an Organization, you should do it like this:
$organization = Organization::create(array_merge([
'main_organization_id' => null,
], request()->all()));
Hope this helps!

cannot add foreign key constraint Laravel 5.1

I first created all the tables without their foreign keys, I then added the foreign keys for each table, starting with the first table, i got this error:
SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint (SQL
: alter table `accounts` add constraint accounts_client_id_foreign foreign
key (`client_id`) references `clients` (`id`))
Here's my code:
public function up()
{
Schema::create('accounts', function(Blueprint $table)
{
$table->engine = 'InnoDB';
$table->bigInteger('id');
$table->integer('client_id')->unsigned();
$table->foreign('client_id')->references('id')->on('clients');
$table->integer('emp_id')->unsigned();
$table->foreign('emp_id')->references('id')->on('employees');
$table->string('type');
$table->timestamps();
});
}
I tried without $table->engine='innoDB'; but same error
Plus, i tried to separate the foreign keys:
Schema::table('accounts', function($table) {
$table->foreign('client_id')->references('id')->on('clients');
$table->foreign('emp_id')->references('id')->on('employees');
});
I got this error:
Base table or view already exists: 1050 Table 'accounts' already exists
So when I deleted and re-migrate i get the first error
So whats happening?
I've got same error, it feels like bug to me. What I did is created different migrations for foreign keys. So, first you create table with fields, then (in next by date migration) you add foreign keys.
Then I rolled back all migrations and reruned them with php artisan migrate. It worked for me, I hope it'll also work for you.
I foresee you created the related table("clients") specifying the primary key/id as this
$table->bigInteger('id');
or
$table->integer('id');
which will cause problem in the sense that your foreign key constraint
is being specified as
$table->integer('client_id')->unsigned();
whiles the primary key/id does not have the unsigned() constraint assigned to it.
So change the primary key of the related table to
$table->bigInteger('id')->unsigned();
or
$table->integer('id')->unsigned();
And if you are using bigInteger for the primary key try and make the foerign key also bigInteger. Don't forget to use unsigned() for both (the primary key and the foreign key).

Resources