Getting info from json column in laravel 5.5 - php

I have json column where i save my orders data in it, code below is sample of that data:
[{"id":27,"name":"new product","price":7246,"quantity":"1","attributes":[],"conditions":[]}]
with code above if i have such loop in my edit page i'm able to get orders info:
#foreach($order->product_data as $data)
{{ $data['quantity'] }}
#endforeach
until here everything is good, but the problem when comes that my order has attributes "attributes":[], then i get this error:
Invalid argument supplied for foreach()
and my data in json column is like:
"[{\"id\":29,\"name\":\"effewf\",\"price\":24524,\"quantity\":\"1\",\"attributes\":[{\"attr\":{\"label\":\"Red\",\"price\":\"5000.00\"}},{\"attr\":{\"label\":\"22\\\"\",\"price\":\"900000.00\"}}],\"conditions\":[]}]"
as you see this order has 2 attributes. (can be more or less).
additional
this is how i get those data in order model:
protected $casts = [
'product_data' => 'array',
];
any idea why i get that error and how i can get my attributes data no matter if my order has attribute or not?
UPDATE
if i open edit page of order without attribute and dd the result will be like:
array:6 [▼
"id" => 27
"name" => "new product"
"price" => 7246
"quantity" => "1"
"attributes" => []
"conditions" => []
]
if load the same on order with attributes get the error above.

You should only allow to print data if exists and having the format we are expecting ,please add necessary conditions to your code like below which may prevent from getting the errors
Assuming the array you have in post is data you need to print.
#if($order->product_data) // check product_data value or not , also add key exists if needed
#if(is_array($order->product_data)) // check for product_data is array or not
#foreach($order->product_data as $data)
{{ $data['quantity'] // if array }}
{{ $data->quantity // if object }}
#if($data->attributes)
#foreach($data->attributes as $attribute) // loop through attributes
{{ $attribute->nameOfTheProperty // if object }}
#endforeach
#endif
#endforeach
#endif
#endif
But better to handle the data in controller if possible
update:
you need to convert your data into array, as your attribute property will be blank array if not having value otherwise it will be stdObject.
so your code should be : ($order->product_data should be an array if not then convert it to an array)
#if($order->product_data)
#if(is_array($order->product_data)) // assuming array
#foreach($order->product_data as $data)
{{ $data['quantity'] // if array }}
#if(count($data['attributes']) > 0) // **checked for blank array**
#foreach($data->attributes as $attribute) // loop through attributes
{{ $attribute['attr']['label'] }}
{{ $attribute['attr']['price'] }}
#endforeach
#endif
#endforeach
#endif
#endif

Tried with your sample data, and that executed without any error.
$json = "[{\"id\":29,\"name\":\"effewf\",\"price\":24524,\"quantity\":\"1\",\"attributes\":[{\"attr\":{\"label\":\"Red\",\"price\":\"5000.00\"}},{\"attr\":{\"label\":\"22\\\"\",\"price\":\"900000.00\"}}],\"conditions\":[]}]";
$jsonAsArray = json_decode($json, true);
foreach ($jsonAsArray as $data) {
echo $data['quantity'] . "\n";
if (! empty($data['attributes']) ) {
if (is_array($data['attributes'])) {
foreach ($data['attributes'] as $attribute) {
echo $attribute['attr']['label'] . ' ' . $attribute['attr']['price'] . "\n";
}
}
}
}
Outputs:
1
Red 5000.00
22" 900000.00
In your case, the product_data is not cast as an array.
You could try Defining An Accessor in your Order model, and remove the cast property of product_data
public function getProductDataAttribute($value)
{
return json_decode($value, TRUE);
}
Or Manually decode the json in your loop
#foreach (json_decode($order->product_data, TRUE) as $data)
{{ $data['quantity'] }}
#if (! empty($data['attributes']))
#foreach ($data['attributes'] as $attribute)
{{ $attribute['attr']['label'] }} {{ $attribute['attr']['price'] }}
#endforeach
#endif
#endforeach

This is how I did mine (category is a json column in the DB):
<div class="category">
<ul class="list-group">
#foreach ( json_decode( $code->category ) as $category)
<li class="list-group-item d-flex justify-content-between align-items-center">
<span class="badge badge-secondary badge-pill">{{$category}}</span>
</li>
#endforeach
</ul>
</div>
You just have to json_decode your json column to get an array and iterate over it. that's it, cheers.

Related

Trying to get property 'prd_name' of non-object while trying to show results with for loop

I want to retrieve some data from the DB with for loop, So at the Controller, I have added this:
$foundOrder = Cart::select('crt_content')->whereCrtId($cart->crt_id)->latest()->first();
$foundOrder = json_decode($foundOrder->crt_content);
if ($foundOrder != null) {
foreach ($foundOrder as $key => $value) {
$prds[] = [
Product::with('uploaded')->wherePrdId($value->id)->select('*')->first(),
$value->quantity,
$value->price
];
}
} else {
$prds = [];
}
So $prds is an array and if I do {{ dd($prds) }}, I get this:
So at the Blade, I tried this:
#for($i=0;$i<=count($prds);$i++)
{{ $prds[$i]->prd_name }}
{{ $prds[$i]->prd_sale_price }}
#endfor
But it returns this error:
Trying to get property 'prd_name' of non-object
So what is wrong here ? As you can see in the picture, I'm getting all the existing products with their attributes (such as prd_id, prd_name, prd_sale_price).
You are storing Product object, quantity and price in your $prds array. And you have array inside array. Use below code
Using foreach loop
#foreach($prds as $data)
// in data 0 index will your product object,1 will be quantity and 2 will be price
{{ $data[0]->prd_name }} // prd_name from product object
{{ $data[0]->prd_sale_price }}
#endforeach
// using for loop
#for($i=0;$i<count($prds);$i++)
{{ $prds[$i][0]->prd_name }}
{{ $prds[$i][0]->prd_sale_price }}
#endfor
Your $prds is an array with each element have below structure:
[
product,
quantity,
price
];
So if you loop through it and want to get attributes of a product, you need to get it from $prds[$i][0], for example: $prds[$i][0]->prd_name.
Update: You need to loop from index 0 to count($prds) - 1:
#for($i = 0; $i <= count($prds) - 1; $i++)

How to echo array elements in laravel

I want to echo arry elemnts in view
followings are my code (controller)
$next_d_dts= \DB::table('tb_billing_cycle')->select('next_due_bill_date')->where('customer_id',$row->customer_id)->get();
return view('invoice.view')->with('next_d_dts',$next_d_dts);
I can print it using print function, eg:
print_r($next_d_dts);
Output:
Array ( [0] => stdClass Object ( [next_due_bill_date] => 2019-03-28 ) [1] => stdClass Object ( [next_due_bill_date] => 2020-02-28 ) )
You need to iterate over the collection of objects:
#foreach ($next_d_dts as $object)
{{ $object->name }}
#endforeach
If you just want to see its contents but not stop the script:
{{ var_dump($next_d_dts) }}
You've also asked how to iterate without Blade:
foreach ($next_d_dts as $object) {
echo $object->name;
}
#foreach($next_d_dts as $value)
{{$value['next_due_bill_date']}}
#endforeach
you should used foreach loop in laravel like this
#foreach ($next_d_dts as $value)
<p>Some text here{{ $value->id }}</p>
#endforeach
for more information read Laravel Manual blade template
Also you can used
dd($next_d_dts) //The dd function dumps the given variables and ends execution of the script
You can convert it into array using toArray() and iterate over it
$next_d_dts= \DB::table('tb_billing_cycle')->select('next_due_bill_date')->where('customer_id',$row->customer_id)->get()->toArray();
In view
#foreach($next_d_dts as $value)
{{ $value['column_name'] }}
#endforeach
Or
print_r($next_d_dts)
#foreach($array as $item)
{{$item}}
#endforeach
Simple.
you need to use Blade Loops syntax invoice.view.blade.php
#foreach($next_d_dts as $next )
{{ $next }}
#endforeach

Parse object of array in laravel

I got the following from controller :
{"cat_id":17,"course":"Maths",
"subcat_info":[{"subcat_id":43,"title":"Test","cat_id":17}]}
Now I want to fetch the title of (title:test) from subcat_info.
I tried following foreach in blade view (result is blank)
#foreach($cats as $cat)
{{ $cat->subcat_info[0]->title }}
#end
How to get title from this?
Try this
$json = '{
"cat_id":17,
"course":"Maths",
"subcat_info":[{
"subcat_id":43,
"title":"Test",
"cat_id":17
}]
}';
$array = json_decode($json,true);
echo $array['subcat_info'][0]['title'];
Output
Test
#foreach($cats as $cat)
{{ $cat->course }} // if you like to print the "title" of the category
#foreach($cat->subcat_info as $subcat)
{{ $subcat->title }}
#endforeach
#endforeach

Combine multiple column for to do a foreach

I have 5 columns in my database. Here are the names of the columns:
promo1
promo2
promo3
promo4
promo5
I would like to combine these columns to be able to make a foreach in my view.
I tried this:
$promos = Building::select('promo1', 'promo2', 'promo3', 'promo4', 'promo5')->where('id', $card->id)->get()->toArray();
and in my view :
#foreach($promos as $promo)
<span>{{ $promo['promo1'] }}</span>
#endforeach
But I have only one result for my foreach. Instead of 5. And I can only select one by one ($ promo ['promo1'], $ promo ['promo2']) so doing a foreach would not help
Is there a way to do that? thank you very much
When you're using get() method, you're getting a collection. Use the find() method to get an object instead of collection:
$promos = Building::select('promo1', 'promo2', 'promo3', 'promo4', 'promo5')->find($card->id)->toArray();
Then you'll be able to iterate over promos:
#foreach ($promos as $promo)
<span>{{ $promo }}</span>
#endforeach
First get the building object
$building = Building::select('promo1', 'promo2', 'promo3', 'promo4', 'promo5')->findOrFail($card->id);
then loop through the promos
#foreach ($building->getAttributes() as $key => $value)
<span>{{ $key }} : {{ $value }}</span>
#endforeach
note: using the $key here is optional

perplexing check box behavior

I have a edit form with some checkboxes that I am trying to make checked when the associated many to many relationship is established.
Distributors belong to many beers
Beers belong to many distributors
in my controller I have:
$breweries = Brewery::lists('name', 'id');
$all_dist = Distributor::all();
$beer = Beer::find($id);
$distributions = [];
foreach ($beer->distributors as $distributor)
{
$distributions[$distributor->id] = BeerDistribution::where('beer_id', '=', $beer->id)
->where('distributor_id', '=', $distributor->id)->first()->price;
}
return View::make('beers.edit', ['beer' => $beer, 'distributors' => $all_dist, 'distributions' => $distributions, 'breweries' => $breweries, 'styles' => $styles]);
and I in my edit form I have:
{{ Form::model($beer, ['route' => ['beers.update', $beer->id], 'method' => 'PATCH']) }}
#foreach ($distributors as $distributor)
<?php $carried = in_array($distributor->id, array_keys($distributions)) ? true : false ?>
{{ Form::checkbox('distributors[]', $distributor->id, $carried); }}
{{ Form::label($distributor->name) }}
{{ Form::label('price' . $distributor->id, 'Retail:') }}
<?php $price = $carried ? $distributions[$distributor->id] : null ?>
{{ Form::text('price' . $distributor->id, $price ) }}
#endforeach
{{ Form::submit('Save') }}
{{ Form::close() }}
Basically I am passing an associated array of each distributor_id => price. This array also tells me which distributors the beer already belongs to so that I can mark those checked off in my edit form.
Here's where things get wonky. When I load this form, all the checkboxes will be checked no matter what. If I change my controller loop to this:
foreach ($beer->distributors()->lists('distributor_id') as $distributor_id)
Then I can do create my array.
Why does calling $beer->distributors in the controller would result in all the checkboxes being checked?
The problem is with the last argument : $carried
{{ Form::checkbox('distributors[]', $distributor->id, [ "checked" => $carried ]); }}
Pass the last parameter as array, and tell it exactly which attribute to modify and the attribute value.

Categories