Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Danny971's avatar

Why cant I delete product from my db

I have a table in the db for category this table has three columns (id,category_name ,product_name)

my goal is to delete a product upon request

i get the following error

Undefined property: stdClass::$id

here is my code 

Controller Code

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use App\Models\category;
use Illuminate\Support\Facades\Notification;


 public function deleteProductCategory($product_category_id)  {
        $category = category:: find($product_category_id);

       if($category) {
        $category ->delete();
        session()->flash('notification', ['type' => 'success', 'message' => 'Product deleted successfully']);
       } else {
        session()->flash('notification', ['type' => 'error', 'message' => 'Product not found']);
       }
        return redirect() -> back();

    }


here is the route

Route::delete('/delete-product/{product_category_id}', [CategoryController::class, ' deleteProductCategory']) ->name('deleteProduct');

here is the HTML


                            @foreach(explode(',', $category->products) as $product)
                                <li class="list-group-item d-flex justify-content-between align-items-center">{{ $product }}
                <div class="btn-group">

                            <form  method="POST" action="{{ route('deleteProduct', ['product_category_id' => $category->id]) }}">
                            @csrf
                            @method('DELETE')
                            <a href="{{ route('deleteProduct',['product_category_id' => $category ->id])}}" onclick="event.preventDefault(); if(confirm('Are you sure you want to delete this item?')) { document.getElementById('delete-form-{{ $product->id }}').submit(); }" class="delete">
                                <i class="bi bi-trash text-white mr-4"></i> Delete
                            </a>
                        </form>

                        <a href="#" class="edit" data-toggle="modal"  data-target="">
                        <i class="bi bi-pencil-fill bluepen"></i>
                         </a>
                </div>
                                </li>
                                
                            @endforeach
0 likes
32 replies
Ben Taylor's avatar

Not sure if it's the reason, but you have a space here which you should remove

$category ->delete();

And here

return redirect() -> back();

Why do you have an anchor tag in your delete form?

You should investigate route model binding. Half the code in your controller would be instantly removed.

Danny971's avatar

@Ben Taylor I think its in the Html can't see where I went wrong

tykus's avatar

@Danny971 there is nothing id related in the deleteProductCategory method; so it is likely that the issue is elsewhere.

How do you get the data for the view?

Danny971's avatar

@tykus

public function fetchCategoryAndProductData() {

    // pulling from the database via the model for category and products



   $categoryAndProducts = DB::select("
    SELECT category_name, GROUP_CONCAT(product_name) AS products
    FROM category
     GROUP BY category_name
    ");
    // Pass the data to the view
return view('categories', ['categoryAndProducts' => $categoryAndProducts]);
} 
tykus's avatar

@Danny971 why are you working so much against Laravel's conventions??? Your approach to fetching the categories and associated product is, frankly, ridiculous. The upshot of your approach is this nonsense:

@foreach(explode(',', $category->products) as $product)

So that you are aware, you are using the Query Builder to fetch the Category and Product data. This means that you will get a Collection of stdClass objects not Category model instances. And, you do not select either the Category or Product id column, hence the error message.

Just do the right thing, and define a relationship between Category and Product models:

// Category
public function products()
{
    return $this->hasMany(Product::class);
}

Then the Controller action can look like this:

public function fetchCategoryAndProductData()
{
    $categoryAndProducts = Category::with('products')->get();
    return view('categories', ['categoryAndProducts' => $categoryAndProducts]);
} 

Finally, in the view template:

@foreach($category->products as $product)
    <!-- form -->

The rest of your markup is nonsense; sort that out!

Danny971's avatar

@tykus you suggesting I should have a table for category and one for products. what I did was just have a single table category and have three column id,category, product

tykus's avatar

@Danny971 oh my life! If you wanted to change the name of a Category, how many records would need changing???? The First Normal Form (1NF) would suggest your approach is not optimal.

Danny971's avatar

@tykus am confused. what is the best approach do you suggest. should I keep it as having product and category under the same table or death habe a table. I did this to move quicker

Snapey's avatar

cant really tell what you are trying to do

  • delete category
  • remove product from category
  • delete product

Give your form a submit button not an a tag

Models are classes so should always start uppercase

Why dont you have a pivot table betweek category and products

Show the full error

Danny971's avatar

@Snapey I'm trying delete a product from category so therefore it will delete a row because I have one table for categories and products. the the product I'm trying to delete will also be delete with the category name in the row.

Snapey's avatar

@Danny971 Well we cannot guess at the business requirements, but a common pattern would be

Category has information relevant to describing and displaying category only

Product has information related to the product only

a pivot table of categories_products contains a linking table joining a product instance and a category instance.

This is a hasMany relationship. You should do so research into many to many arrangements because it is too much to describe in a forum answer.

Danny971's avatar

@Snapey category has the name of products category such baaby items, bedroom items and the products column contain the name of the item such is crib,blanket ect which pertain to the category name

Danny971's avatar

so I should have two tables rather than one for both category and and products. I thought of this earlier on but I was a bit too lazy 😅 🙃 to implement it that way

Snapey's avatar

A many to many relationship allows a category to have many products and a product to be in many categories.

A simpler approach is a products table with a category_id foreign key meaning that a product belongs to a single category. Its a simpler approach but comes with its own restrictions.

Danny971's avatar

@Snapey I have another question. I don't feel it's necessary to start a new discussion on laracast. so here goes

I have an application on compute engine. I use wget to get phpmy admin on there to manage my db. I sucessfully open it by http:// ip-address/phpmyadmin . but lately when i try this it wont work

Danny971's avatar

@Snapey


Now I have a table for Category and one for Products

it's a one to many relationship (one category can have many products) this is the way it's specified in the requirements

here is my my table structure looks like

category table

id int not null primary key
category_name varchar(200) not null


products table 

id 
category_id
product_name
created_at
updated_at
FOREIGN KEY (category_id) REFERENCES category(id)


MY html 

 <div class="basic-form">
                                    <form>
                                    

                                        <div class="form-row">
                                            <div class="col-sm-7">
                                                <input type="text" class="form-control" placeholder="Enter Catgory Name" id="categoryName">
                                            </div>
                                            <div class="col mt-2 mt-sm-0">
                                                <input type="number" class="form-control" placeholder="Number of Items" id="numberOfItems">
                                            </div>
                                            
                                        </div>
                                        <br>
                                        <div id="dynamicFields"></div>
                                         <br>
                                        <button type="button" class="btn btn-primary" id="saveChanges">Save Changes</button>
                                    </form>
                                </div>

here is my js code 


<!-- dynimacally create required input fields for product -->
<script>
    document.getElementById('numberOfItems').addEventListener('input', function() {
        var numberOfItems = parseInt(this.value);
        var dynamicFieldsContainer = document.getElementById('dynamicFields');
        dynamicFieldsContainer.innerHTML = '';

        for (var i = 0; i < numberOfItems; i++) {
            var inputField = document.createElement('input');
            inputField.type = 'text';
            inputField.className = 'form-control';
            inputField.placeholder = 'Item ' + (i + 1);
            inputField.id = 'item'+ i; // unique ID 
            dynamicFieldsContainer.appendChild(inputField);

            var lineBreak = document.createElement('br');
            dynamicFieldsContainer.appendChild(lineBreak);
        }
    }); 
</script>

<!-- js script to save data for category name and it products --> 

<script>
document.getElementById('saveChanges').addEventListener('click', function() {
    var categoryName = document.getElementById('categoryName').value;
    var numberOfItems = parseInt(document.getElementById('numberOfItems').value);
    var itemNames = [];

    
    for (var i = 0; i < numberOfItems; i++) {
        var itemInput = document.getElementById('item' + i);
        if(itemInput) {
        itemNames.push(itemInput.value);
        }
    }

    // Send data to controller using Ajax
    $.ajax({
        url: '{{ route("saveCategoryAndProductData") }}',
        type: 'POST',
        data: {
            _token: '{{ csrf_token() }}',
            categoryName: categoryName,
            itemNames: JSON.stringify(itemNames)
        },
        success: function(response) {
           
            /// dont forget to pass back and add a notification 

            setTimeout(function() {
                location.reload();
            }, 1000);
        },
        error: function(xhr, status, error) {
            console.error(error);
        }
    });
});
    </script>   


controller

 public function saveCategoryAndProductData(Request $request)
    {
        $categoryName = $request->categoryName;
        $itemNames = json_decode($request->itemNames);
    
        try {
            // Create the category
            $category = Category::create(['category_name' => $categoryName]);
    
            // Ensure $itemNames is an array
            if (!is_array($itemNames)) {
                $itemNames = [];
            }
    
            // Save products and associate them with the created category
            $products = [];
            foreach ($itemNames as $itemName) {
                $products[] = [
                    'product_name' => trim($itemName),
                    'category_id' => $category->id,
                    'created_at' => now(),
                    'updated_at' => now(),
                ];
            }
    
            // Save all products in one go
            if (!empty($products)) {
                Product::insert($products);
            }
    
            return response()->json(['message' => 'Data saved successfully']);
        } catch (\Exception $e) {
            // Handle exceptions during data saving
            return response()->json(['message' => 'Error saving data: ' . $e->getMessage()], 500);
        }
    }
Danny971's avatar

so when I delete I will just delete the product

Snapey's avatar

@Danny971 Start with the basics. Try the 30 days to learn laravel video course (free)

Snapey's avatar

@Danny971 save items like


            if (!is_array($itemNames)) {
                $itemNames = [];
            }
    
            // Save products and associate them with the created category
            foreach ($itemNames as $itemName) {
                 $category->products()->create([
                     'product_name' => trim($itemName),
                 ]);
            }

See how cleaner this looks. It uses the fact that you should have a hasMany relationship on the Category model to say create a new Product and associate it with the category

jlrdw's avatar

@danny971 In my opinion some of the lessons from here would help you. Like laravel in 30 days.

tykus's avatar

@Danny971 your Response status code will not be ok because you return a redirect (3xx status code).

Otherwise, if you want more help, please format your code correctly by wrapping it within triple backticks

```
// your code
```
tykus's avatar
tykus
Best Answer
Level 104

@Danny971 it is not a JS issue; your happy path results in a redirect:

return redirect() -> back();

which means a 3xx status code, whereas your JavaScript is checking for a 2xx here:

if (response.ok) {
colbyalbo's avatar

@Danny971 The exception message is telling you that the post method is DELETE, and the route you are sending it to only takes GET method requests. May not solve your issue but check to make sure you are submitting to a route that is setup to handle DELETE request methods

!--
Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException: The DELETE method is not supported for route categories. Supported methods: GET, HEAD.

Please or to participate in this conversation.