Say Jack
Say Jack

Reputation: 61

Laravel - How to prevent row getting deleted when there is dependent field

I am a laravel beginner. In my laravel CRUD project, I have these migration table
GroupTable

class Group extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('group', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('group_code');
            $table->string('group_desc');
            $table->timestamps();
    });
}

CategoryTable

class Category extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('category', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('category_code');
            $table->string('category_desc');
            $table->timestamps();
        });
    }

ItemTable

class Item extends Migration
{
   /**
    * Run the migrations.
    *
    * @return void
    */
     public function up()
   {
       Schema::create('item', function (Blueprint $table) {
           $table->bigIncrements('id');
           $table->string('item_code');
           $table->string('item_desc');
           $table->string('item_picture');
           $table->string('item_cost');
           $table->string('item_price');
           $table->string('group_desc');
           $table->string('category_desc');
           $table->timestamps();
       });

      
   }

The group_desc and category_desc from ItemTable are foreign key from GroupTable and CategoryTable.

GroupController

 public function destroy($id)
    {
        Group::find($id)->delete();
        return response()->json(['success'=>'Group deleted successfully.']);
    }

CategoryController

public function destroy($id)
    {
        Category::find($id)->delete();
     
        return response()->json(['success'=>'Category deleted successfully.']);
    }

This is the ajax delete function in my view of group

  //Delete
   $('body').on('click', '.deleteRecord', function () {
     
     var id = $(this).data("id");
     if(confirm("Are you sure want to delete? "))
   
    {
      $.ajax({
         type: "DELETE",
         url: "{{ url('group/delete') }}" + '/' + id,
         success: function (data) {
             table.draw();
         },
         error: function (data) {
             console.log('Error:', data);
         }
     });
    }
 });

Before user want to delete the row on GroupTable or CategoryTable, how to display a message shows that the row are not allow to delete if ItemTable have data from GroupTable or CategoryTable?

Upvotes: 0

Views: 1167

Answers (2)

aphoe
aphoe

Reputation: 2726

If you follow Laravel's convention, things will be a lot easier to do. Might be longer at first but it gets better

(I am assuming you are using Laravel 8)

1: Table names are usually in plural forms, so your tables should be groups, categories and items

2: Next is to properly define foreign keys for groups and categories tables in items table like this

Schema::create('item', function (Blueprint $table) {
   //...
   $table->foreignId('group_id')->constrained();
   $table->foreignId('category_id')->constrained();
   //...
});

3: Define the respective relations in the 3 models

Group Model

namespace App\Models;
class Group extends Model
{
  //...
  public function items(){
    return $this->hasMany(Item::class);
  }
  //...
}

Category model

namespace App\Models;
class Category extends Model
{
  //...
  public function items(){
    return $this->hasMany(Item::class);
  }
  //...
}

Item Model

namespace App\Models;
class Item extends Model
{
  //...
  public function category(){
    return $this->belongsTo(Category::class);
  }
  
  public function group(){
    return $this->belongsTo(Group::class);
  }
  //...
}

All the above, while kind of long, will make your work easier later.

From here you can implement the following

GroupController

public function destroy($id)
{
    $group = Group::withCount('items')
      ->find($id);
     
    if($group->items_count < 1){
      $group->delete()
      return response()->json(['success'=>'Group deleted successfully.']);
    }
      
    return response()->json(['fail'=> 'Group has items, cannot be deleted.' ]);
}

CategoryController

public function destroy($id)
{
    $category = Category::withCount('items')
      ->find($id);
     
    if($category->items_count < 1){
      $category->delete()
      return response()->json(['success'=>'Category deleted successfully.']);
    }
      
    return response()->json(['fail'=> 'Category has items, cannot be deleted.' ]);
}

Upvotes: 0

Arul Anandhan
Arul Anandhan

Reputation: 7

If you are using the foreign key and if it is not a 'cascade' delete, then laravel won't allow you to delete the row when If the same Id used somewhere. for example,

$table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade'); //inside item table. (CASCADE delete).


$table->foreign('category_id')->references('id')->on('categories');// non-cascade

assume, If you are using cascade delete, and you are trying to delete the category which is used in the item table, this will delete the category and related item lists in item table.

If you are using non-cascade method, It won't allow you to delete the category when it is used in item table.

Upvotes: 1

Related Questions