Emre Sasi
Emre Sasi

Reputation: 29

When deleting data from the pivot table, also to delete from the main table

I want to ask a question. I am developing a project in Laravel 8. I have 3 tables products (id, name), urls (id, page_id, request_id) and product_url (product_id, url_id, site_id). When a product or url is deleted, I can delete it from the product_url table. There is no problem, but when I delete a data from the product table, I want to delete all the urls connected to that product from the product_url table, but it did not work, although I gave it onDelete ('cascade') in the product_url table. :( is there an easy way to achieve this?

Products migration:

Schema::create('products', function (Blueprint $table) {
        $table->id();
        $table->string('name');
        $table->timestamps();
    });

Urls migration:

Schema::create('urls', function (Blueprint $table) {
        $table->id();
        $table->text('page_url');
        $table->text('request_url')->nullable();
        $table->timestamps();

    });

Product_Url Pivot migration:

Schema::create('product_url', function (Blueprint $table) {

        $table->foreignId('product_id')->constrained();
        $table->foreignId('url_id')->constrained()->cascadeOnDelete();
        $table->unsignedBigInteger('site_id');

    });

Product Model:

use HasFactory;

protected $fillable  = ['name'];
protected $hidden = ['created_at','updated_at'];

public function url()
{
    return $this->belongsToMany(Url::class)
    ->withPivot('site_id');
}

public function sites()
{
    return $this->belongsToMany(Site::class, 'product_url')
    ->withPivot('product_id','url_id');
}

Urls Model:

use HasFactory;
protected $fillable  = ['page_url','request_url'];
protected $hidden = ['created_at','updated_at'];

public function products()
{
    return $this->belongsToMany(Product::class)
    ->withPivot('site_id');
}

public function sites()
{
    return $this->belongsToMany(Site::class, 'product_url')
    ->withPivot('product_id','url_id');
}

public function urls()
{
    return $this->belongsToMany(self::class)
    ->withPivot('url_id');
}

Products Controller:

public function destroy($id)
{
    $product = Product::find($id);
    $product->url()->detach();
    $product->delete();
    return redirect()->route('product.index');

}

Urls Controller:

 public function destroy($id)
{

    $Url = Url::find($id);
    $Url->products()->detach();
    $Url->delete();
    return redirect()->route('url.index');

}

Upvotes: 2

Views: 694

Answers (2)

MrEduar
MrEduar

Reputation: 1961

To remove a many-to-many relationship record, use the detach method. The detach method will delete the appropriate record out of the intermediate table; however, both models will remain in the database:

//Detach a single url from product
$product->urls()->detach($urlId);

//Detach All urls from the product
$product->urls()->detach();

For convenience, detach also accept arrays of IDs as input:

$product->urls()->detach([1, 2, 3]);

And then you can delete your product model and related model.

 /**
 * Remove the specified resource from storage.
 *
 * @param  \App\Models\Product  $product
 * @return \Illuminate\Http\Response
 */
public function destroy(Product $product)
{
    $product->url()->detach();
    $product->url()->delete();
    $product->delete();
    
    return redirect()
        ->route('product.index')
        ->withSuccess('Product başarılı şekilde silindi.');

}

Upvotes: 0

Emre Sasi
Emre Sasi

Reputation: 29

solved the problem. I added the url to the ProductController destroy method with with, then I deleted the relation table first with $ product->url()->delete(), then I cleared the pivot table and deleted the product from the product table.

public function destroy($id)
{
    $product = Product::with('url')->find($id) ?? abort(404,'Product Bulunamadı');
    $product->url()->delete();
    $product->url()->detach();
    $product->delete();
    return redirect()->route('product.index')->withSuccess('Product başarılı şekilde silindi.');

}

Upvotes: -1

Related Questions