Lestah's avatar
Level 11

How did it end as an array?

here's my controller


public function addAttributes(Request $request, $id=null)
    {
        $productDetails = Product::with('attributes')->where(['id' => $id])->first();
        $productDetails = json_decode(json_encode($productDetails));
        echo "<pre>"; print_r($productDetails); die;
    }

it gives me this


stdClass Object
(
    [id] => 3
    [category_id] => 2
    [product_name] => valenciaga
    [product_code] => 4
    [product_color] => black
    [description] => quality shoes running shoes
    [price] => 200
    [image] => 87910.jpeg
    [created_at] => 2019-02-20 11:51:18
    [updated_at] => 2019-02-20 11:52:28
    [attributes] => Array
        (
            [0] => stdClass Object
                (
                    [id] => 1
                    [product_id] => 3
                    [sku] => rt-1
                    [size] => small
                    [price] => 200
                    [stock] => 5
                    [created_at] => 2019-02-20 16:16:51
                    [updated_at] => 2019-02-20 16:16:51
                )

            [1] => stdClass Object
                (
                    [id] => 2
                    [product_id] => 3
                    [sku] => rt-2
                    [size] => medium
                    [price] => 300
                    [stock] => 10
                    [created_at] => 2019-02-20 16:16:51
                    [updated_at] => 2019-02-20 16:16:51
                )

now here my view page


@foreach($productDetails['attributes'] as $attribute)
                <tr class="gradeX">
                  <td>{{ $attribute->id }}</td>
                  <td>{{ $attribute->sku }}</td>
                  <td>{{ $attribute->size }}</td>
                  <td>{{ $attribute->price }}</td>
                  <td>{{ $attribute->stock }}</td>
                  <a rel="{{ $attribute->id }}" rel1="delete-product" href="javascript:"  class="btn btn-danger btn-mini deleteRecord">Delete</a>
                </tr>
                @endforeach


now i got an error like this

2/2) ErrorException Trying to get property of non-object

should i use


<td>{{ $attribute['id'] }}</td>


to view my data?

0 likes
17 replies
jlrdw's avatar

That's what json_decode does and yes.

Why

json_decode(json_encode($productDetails));
jlrdw's avatar
return view('whatever.something', compact('productDetails'));

Or if returning ajax:

return Response::json($productDetails);

You should really find and view a good youtube video on returning ajax response if new to this.

Lestah's avatar
Level 11

return view('admin.products.add_attributes', compact('productDetails'));

tried this one does not work :C

Cronix's avatar
Cronix
Best Answer
Level 67
    public function addAttributes(Request $request, $id=null)
    {
        $productDetails = Product::with('attributes')->where(['id' => $id])->firstOrFail();

        return view('admin.products.add_attributes', compact('productDetails'));
    }
@foreach($productDetails->attributes as $attribute)
    {{ $attribute->id }}
@endforeach

You also better be sure you get a result first. You're assuming you are but never check. For instance, if the $id doesn't exist you will get errors for trying to use a property on an object that doesn't exist. You should basically always use firstOrFail() instead of just first(). That way you will get an appropriate 404 page not found error instead if the $id didn't exist. https://laravel.com/docs/5.7/eloquent#retrieving-single-models

Lestah's avatar
Level 11

@CRONIX - (1/1) ErrorException Argument 1 passed to Illuminate\Database\Grammar::columnize() must be of the type array, string given, called in C:\xampp\htdocs\online-shop\vendor\laravel\framework\src\Illuminate\Database\Query\Grammars\Grammar.php on line 131 and defined

this the error i came up.. I'm still trying to search on laravel documentation

Cronix's avatar

That shouldn't be caused by anything I suggested or showed. The only difference between your query and mine was using firstOrFail() instead of first().

What is $id? What is your route?

Troubleshoot it.

  1. dd($id); - is $id what you expect? If not, why?
  2. remove the relationship from the query and dd() the result immediately. Then hit the route again. Does that work? If so,
  3. Add back in the relationship

etc. Simplify it and add back complexity until it breaks. Then you can pinpoint the actual problem. Are you doing something in the view that is performing an additional query, such as you didn't eager load something? The problem could be coming from multiple places. You need to narrow it down more.

Cronix's avatar

@uniels Great observation! I don't think it messes the query itself up (since with('attributes') was used and produced results), but it definitely could in the view when accessing it as a property, like $model->attributes.

Snapey's avatar

and when you want to analyse the data returned, instead of this

        $productDetails = json_decode(json_encode($productDetails));
        echo "<pre>"; print_r($productDetails); die;

just do

    dd($productDetails);
Lestah's avatar
Level 11

@CRONIX - i got a product_view.blade.php which have a datatable of product ID, category ID, Category Name and so on.. the table contains add edit delete view on the add button i got


<a href="{{ url('/admin/add-attributes/'.$product->id) }}" class="btn btn-success btn-mini">Add</a>


that's why i have a route on my web.php


Route::match(['get', 'post'], '/admin/add-attributes/{id}','ProductsController@addAttributes');


so it will go to my controller addAttributes

when i dd($id); it gives me the product_id that i click on the table which is correct thats what i expect

i tried this removed the relationship


$productDetails = Product::where(['id' => $id])->first();
dd($productDetails);

it gives me this

Product {#241 ▼
  #connection: "mysql"
  #table: null
  #primaryKey: "id"
  #keyType: "int"
  +incrementing: true
  #with: []
  #withCount: []
  #perPage: 15
  +exists: true
  +wasRecentlyCreated: false
  #attributes: array:10 [▶]
  #original: array:10 [▶]
  #casts: []
  #dates: []
  #dateFormat: null
  #appends: []
  #events: []
  #observables: []
  #relations: []
  #touches: []
  +timestamps: true
  #hidden: []
  #visible: []
  #fillable: []
  #guarded: array:1 [▶]
}


i trink I have to troubleshoot more

Cronix's avatar

At what point do you get the actual error? Is it the controller, or the view?

Try eliminating the view first by "dump and die (dd())" the variable before it gets to the view. You should use dd() instead of echo "<pre>"; print_r($productDetails); die;. It does a better job and is only 2 chars.

    public function addAttributes(Request $request, $id=null)
    {
        $productDetails = Product::with('attributes')->where(['id' => $id])->firstOrFail();
        dd($productDetails);
        return view('admin.products.add_attributes', compact('productDetails'));
    }

Can you expand the attributes section of the output and see the correct data for that model (click triangle next to "attributes" from the dd())? Can you do the same for the relations property and see the individual attribute objects? If so, the problem is in the view.

What you showed above... you need to click on the "attributes" to see the data for that model...it's there. It says there are 10 elements in it.

Snapey's avatar

yes,open up attributes to check the model data, and when you put the relationship back there will be a relations element to explore also

Lestah's avatar
Level 11

@CRONIX - hey guys @cronix @snapey thanks for ur help I just solved it what i did is just this on my products controller i query this


$productDetails = Product::with('attributes')->where('id', $id)->first();
and do test like what you advc


and then on my view page i did this like what @cronix suggested


@foreach($productDetails->attributes as $attribute)


and it now displays i just need a couple hours of sleep to figure that one out haha thanks a lot

Cronix's avatar

@lestah You're welcome. I'd still highly advise you to use firstOrFail() instead of first() in this case.

To see why, go to the url with an id that doesn't exist, like

http://yoursite.com/admin/add-attributes/20000

Your app will blow up and get undefined property errors, because you don't ever check wither the ID exists. You assume you will always get a result, and then use the result in the view. A user should never see your errors.

If you use firstOrFail(), you'd get a 404 error when the $id doesn't exist, which is appropriate. It can't find the thing you're telling it to find - 404 - not found.

Lestah's avatar
Level 11

@CRONIX - I'ma use it always now since its your recommendation... 2000 id yeah i think i wouldn't get a product that much

Cronix's avatar

You can't assume people will only be clicking on links you provide. Some will mess with the url to try to hack in. Some will mess with it using their browser dev tools and change form inputs and stuff. Never trust any user supplied data, that includes get requests (the id is user supplied data - anyone can change the number in the url) and all data entered in forms. It all needs to be verified and validated before processing, or you will get owned. Security first. Always.

Please or to participate in this conversation.