0
votes

I am new to pivot tables and laravel and I'm having a hard time updating a certain column of my pivot table. I tried searching online but nothing seems to work. I'm trying to update the status column of the selected user. Note as an admin i can view the customers profile and update their information. Here's what i have:

customers table

id | name | budget

products table

id | name | price

customer_product pivot table

product_id | customer_id | qty | status

Product model

public function customers()
{
    return $this->belongstoMany('App\Customer', 'product_customer')
    ->withPivot('status','qty');

}  

Customer Model

public function products()
{
    return $this->belongsToMany('App\Product', product_customer)
    ->where('status', '=', '1')
    ->withPivot('qty', 'status');
}

Controller
This is where i'm having trouble with, after the updateExistingPivot it requires an $id, how can i place the $id of the current customer profile that i am currently viewing or am i understanding it the wrong way. The code runs but it doesn't do anything. It doesn't update the status column. I want to be able to change status from 1 to 0.

public function updateProductStatus($id)
 {
  Product::find($id)->customers()->updateExistingPivot($id, array('status' => 0), false);
 }  

public function getCustomerProfile($id)
{
  $customers = Customer::find($id);
  foreach ($customers->products as $product) 
  {
    $product->pivot->product_customer;
  } 
  $products = Product::lists('name');
  return view('admin.customer-profile', ['customers' => $customers], compact('products') );
}  

public function index()
{
  $customers = DB::table('customers')
  ->select('name')
  ->get();
  return view('admin.index', compact('customers'));
}  

Route

Route::put('updateProductStatus/{id}', ['as' => 'updateProductStatus',
        'uses' => 'AdminController@updateProductStatus']);
Route::get('getCustomerProfile/{id}', ['as' => 'getCustomerProfile',
        'uses' => 'AdminController@getCustomerProfile']);

Blade

<table class="table">
        <thead>
         <tr>   
          <th>Name</th>
            <th>Qty</th>
            <th>Status</th>                                         
         </tr>
        </thead>
            @foreach($customers->products as $product)
            <tbody>
             <tr>
              <td>{{$product->name}}</td>
              <td>{{$product->pivot->qty}}</td>
              <td>{!!Form::open(array('route'=>['updateProductStatus', $product->pivot->status], 'method'=>'PUT'))!!}
              {!!Form::button('Update', ['class'=>'btn btn-danger', 'type'=>'submit'])!!}
              {!!Form::close()!!}<td>
              </tr>
              </tbody>
            @endforeach
</table>

main.blade.php

<table id="datable_1" class="table table-hover display  pb-30" >
  <thead>
   <tr>
    <th>Name</th>
    <th>Action</th>
   </tr>
  </thead>
   @foreach($customers as $customer)
    <tbody>
     <tr>
      <td>{{$customer->name}}</td>
       <td>{!!Form::open(array('route'=>['deleteCustomerProfile', $customer->id], 'method'=>'DELETE'))!!}
           {{ link_to_route('getCustomerProfile', 'Edit', [$customer->id] , ['class' => 'btn btn-primary'])}}|
           {!!Form::button('Delete', ['class'=>'btn btn-danger', 'type'=>'submit'])!!}
           {!!Form::close()!!}
           </td>
          </tr>
         </tbody>
        @endforeach
       </table>

URL of the blade above

/admin/getCustomerProfile/1

Error

Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException thrown with message ""

Stacktrace:
#19 Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException in G:\xampp\htdocs\theshop\vendor\laravel\framework\src\Illuminate\Routing\RouteCollection.php:218
#18 Illuminate\Routing\RouteCollection:methodNotAllowed in G:\xampp\htdocs\theshop\vendor\laravel\framework\src\Illuminate\Routing\RouteCollection.php:205
#17 Illuminate\Routing\RouteCollection:getRouteForMethods in G:\xampp\htdocs\theshop\vendor\laravel\framework\src\Illuminate\Routing\RouteCollection.php:158
#16 Illuminate\Routing\RouteCollection:match in G:\xampp\htdocs\theshop\vendor\laravel\framework\src\Illuminate\Routing\Router.php:821
#15 Illuminate\Routing\Router:findRoute in G:\xampp\htdocs\theshop\vendor\laravel\framework\src\Illuminate\Routing\Router.php:691
#14 Illuminate\Routing\Router:dispatchToRoute in G:\xampp\htdocs\theshop\vendor\laravel\framework\src\Illuminate\Routing\Router.php:675
#13 Illuminate\Routing\Router:dispatch in G:\xampp\htdocs\theshop\vendor\laravel\framework\src\Illuminate\Foundation\Http\Kernel.php:246
#12 Illuminate\Foundation\Http\Kernel:Illuminate\Foundation\Http\{closure} in G:\xampp\htdocs\theshop\vendor\laravel\framework\src\Illuminate\Routing\Pipeline.php:52
#11 call_user_func in G:\xampp\htdocs\theshop\vendor\laravel\framework\src\Illuminate\Routing\Pipeline.php:52
#10 Illuminate\Routing\Pipeline:Illuminate\Routing\{closure} in G:\xampp\htdocs\theshop\vendor\laravel\framework\src\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode.php:44
#9 Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode:handle in G:\xampp\htdocs\theshop\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php:136
#8 call_user_func_array in G:\xampp\htdocs\theshop\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php:136
#7 Illuminate\Pipeline\Pipeline:Illuminate\Pipeline\{closure} in G:\xampp\htdocs\theshop\vendor\laravel\framework\src\Illuminate\Routing\Pipeline.php:32
#6 call_user_func in G:\xampp\htdocs\theshop\vendor\laravel\framework\src\Illuminate\Routing\Pipeline.php:32
#5 Illuminate\Routing\Pipeline:Illuminate\Routing\{closure} in G:\xampp\htdocs\theshop\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php:103
#4 call_user_func in G:\xampp\htdocs\theshop\vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php:103
#3 Illuminate\Pipeline\Pipeline:then in G:\xampp\htdocs\theshop\vendor\laravel\framework\src\Illuminate\Foundation\Http\Kernel.php:132
#2 Illuminate\Foundation\Http\Kernel:sendRequestThroughRouter in G:\xampp\htdocs\theshop\vendor\laravel\framework\src\Illuminate\Foundation\Http\Kernel.php:99
#1 Illuminate\Foundation\Http\Kernel:handle in G:\xampp\htdocs\theshop\public\index.php:54
#0 require_once in G:\xampp\htdocs\theshop\server.php:21
2
Are you viewing the products for a single customer or for multiple customers in your blade.php file? - Nikola Gavric
@NikolaGavric oh im viewing only the product for a single costumer. - jesse rodriguez
When you say product, you mean multiple products for a single customer? - Nikola Gavric
@NikolaGavric yes a single costumer can have multiple products. Sorry i'll edit my post, i'll post the blade where it displayed all the costumers and ill include the route for viewing costumer profile. - jesse rodriguez
No need, I've updated my answer, note that the $customer in the blade.php file should be of type \App\Customer - Nikola Gavric

2 Answers

0
votes

I will post a full explanation and solution..

You are strongly encouraged to change the method name belongstoMany to belongsToMany, but this is optional thanks to @amphetamachine check the comments for an explanation why.

public function customers()
{
    return $this->belongsToMany('App\Customer', 'customer_product')
               ->withPivot('status', 'qty');

}

Your controller code

use App\Customer;
use App\Product;
...
...
public function updateProductStatus(Customer $customer, Product $product)
{
  $pivotProduct = $customer->products()->wherePivot('product_id', $product->id);
  $pivotProduct->updateExistingPivot($customer->id, array('status' => $pivotProduct->pivot->status == 0 ? 1:0));
}

public function getCostumerProfile(Customer $customer)
{
  return view('admin.costumer-profile', ['customer' => $customer]);
}

public function index()
{
  $customers = Customer::all();
  return view('admin.index', ['customers' => $customers]);
}

Your routes file now includes those 2 parameters you are receiving and they are customer and product and thanks to Route Model Binding they will be auto-resolved to their respective objects

Route::put('updateProductStatus/{customer}/{product}', ['as' => 'updateProductStatus',
    'uses' => 'AdminController@updateProductStatus']);

Route::get('getCostumerProfile/{customer}', ['as' => 'getCostumerProfile',
    'uses' => 'AdminController@getCostumerProfile']);

Your blade file should first iterate through all of the customers and for each of the customer it will iterate through all of his/her products and show them in a table, consider that you can change the design of the table

<table class="table">
      <thead>
         <tr>   
            <th>Name</th>
            <th>Qty</th>
            <th>Status</th>                                         
         </tr>
      </thead>
      <tbody>
      @if($customer->products()->count() > 0)
      @foreach($customer->products as $product)
         <tr>
            <td>{{$product->name}}</td>
            <td>{{$product->pivot->qty}}</td>
            <td>{!!Form::open(array('route' => ['updateProductStatus', ['customer' => $customer, 'product' => $product]], 'method'=>'PUT'))!!}
            {!!Form::button('Update', ['class'=>'btn btn-danger', 'type'=>'submit'])!!}
            {!!Form::close()!!}<td>
         </tr>
      @endforeach
      @else
         <tr>
            <td colspan="3">No products found for this customer.</td>
         </tr>
      @endif
      </tbody>
</table>

And finally your main.blade.php should look like this

<table id="datable_1" class="table table-hover display  pb-30" >
   <thead>
     <tr>
        <th>Name</th>
        <th>Action</th>
     </tr>
  </thead>
  @foreach($customers as $customer)
  <tbody>
      <tr>
        <td>{{$customer->name}}</td>
        <td>{!!Form::open(array('route'=>['deleteCostumerProfile', $customer->id], 'method'=>'DELETE'))!!}
        {{ link_to_route('getCostumerProfile', 'Edit', ['customer' => $customer->id] , ['class' => 'btn btn-primary'])}}|
        {!!Form::button('Delete', ['class'=>'btn btn-danger', 'type'=>'submit'])!!}
        {!!Form::close()!!}
        </td>
      </tr>
  </tbody>
  @endforeach
</table>
0
votes

I had trouble with the updateExistingPivot() function because it updates the status for all the rows with the same customer id. So instead i just used DB update. Here's my solution

public function updateProductStatus($id)
{
 DB::table('customer_product')
 ->where('product_id', $id)
 ->update(['status' => 0]);
 return redirect()->back();
}

and in my blade i just changed

{!!Form::open(array('route'=>['updateProductStatus', $product->pivot->status], 'method'=>'PUT'))!!}

into

{!!Form::open(array('route'=>['updateProductStatus', $product->pivot->product_id], 'method'=>'PUT'))!!}