Laravel 5.8 query from column containing json data - php

I have a column that contains a json array, but I am having difficulty outputting them as individual items.
ListingController#show
public function show(Listing $listing)
{
$services = collect($listing->services_offered);
return view('listings.listing', compact('banner', 'listing', 'services'));
}
listing.blade.php
#foreach($services as $service)
<li>{{$service}}</li>
#endforeach
Output

In your Listing model you can cast the json array into a PHP array like this:
protected $casts = [
'services_offered' => 'array',
];
Then you can wrap that into a collection as you already do and list them on the view.

You need to convert the JSON string to actual JSON array.
$services = collect(json_decode($listing->services_offered, true));
or you can create an accessor in your model
public function getServicesOfferedAttribute($value)
{
return json_decode($value);
}

Related

Create array key inside foreach loop in laravel

I'm fetching data from database, inside foreach loop i have to add one array index list_array
$list = Lists::where('name',$request->name)->get();
$Data=[];
foreach($list as $key => $list_row)
{
$list_row['list_array'][]=$list_row['data_1'];
$list_row['list_array'][]=$list_row['data_2'];
$Data[]=$list_row;
}
It should be of array type but when i declare it as array it is not working,
message: "Indirect modification of overloaded property
App\Models\Lists
Any solution to create list_array as an array index inside foreach loop. Thanks
You are not dealing with an array, you are dealing with an App/Models/Lists model. What you probably instead want to do is adding a custom attribute to the model. This happens one step before.
// your model
class Lists
{
protected $appends = ['list_array'];
public function getListArrayAttribute()
{
$data = [
// your array data from where ever
];
return $data;
}
}
You then can access (without adding it when you want to access the data) the new attribute from within the model, like so:
// where you access your data
$lists = Lists::where('name', 'whatever')->get();
foreach($lists as $list) {
dd($lists->list_array)
}
You can read more about the so called Accessors here:
https://laravel.com/docs/8.x/eloquent-mutators#defining-an-accessor (Laravel 8)
https://laravel.com/docs/9.x/eloquent-mutators#defining-an-accessor (Laravel 9)
I hope I got the intention of your question right. From your question it's not very clear what data you want to add and where it is coming from. There might be other and better ways too.
Edit:
Based on the comment from #user3653474 the Accessor function could look like this.
public function getListArrayAttribute()
{
$data = [
$this->data_1,
$this->data_2,
];
return $data;
}
data_1 and data_2 are the column names in the table of the same model.

How can I make laravel casting array on the model?

I try like this
Data type of votes_detail in database is json
My model like this :
<?php
class Store extends Model{
protected $fillable = [ ...,'votes_detail',...];
protected $casts = [
'votes_detail' => 'array',
];
}
My controller like this :
$store = Store::find($id)
$votes_detail = $store->votes_detail;
dd($votes_detail);
The result of dd($votes_detail) is :
{"1": "1", "5": "2"}
Why the result is still json?
The result should be an array
Whereas I've set the array in cast model
How can I solve this problem?
You could use Laravel accessors. In you model define a method called exactly getVotesDetailAttribute($details):
public function getVotesDetailAttribute($details)
{
return json_decode($details, true);
}
then when you will call $store->votes_detail you will get the expected result.
After that you can use mutators to convert an array back to JSON when it is saved back in the DB. Define the method setVotesDetailAttribute($value) as follows:
public function setVotesDetailsAttribute($value)
{
$this->attributes['votes_detail'] = json_encode($value);
}
You can easily do it by converting your data to the array by using toArray() function. So it should be like
$store = Store::find($id)->toArray();
//$store contain a array.
$votes_detail = $store['votes_detail'];
make it dd($votes_detail) and get your desire result.
I think you are storing array data after json_encode() to a column which is not defined as json() in the migration like:
$table->text('votes_detail');
or
$table->integer('votes_detail');
And seems you have defined votes_detail as string, number or something else.
This is the reason behind your problem. So, define column type as json in migration like:
$table->json('votes_detail');
And then refresh your migration, your casting in the model will work and you will get your desired array.

Perform action on Laravel model once it has been filled with data

So I have a model that has a json field as an attribute. When it is retrieved, I'd like to convert that field into an array so I can do some other things with it.
For example, if the json has data like this {name:bob,email:sue} in a parameter called json, when the model object is built, I'd like it to something like this:
public function setJsonAttribute($value)
{
$this->attributes['json'] = $value;
$jsonInfo = json_decode($value, true);
$this->name = $jsonInfo['email'];
$this->email = $jsonInfo['name'];
}
This is an example of an attempt I did with a mutator, but it's not optimal. Is there any way to do this kind of thing automatically once the model has been loaded with data from the database?
Laravel 5.4
Eloquent includes a feature called array casting which converts a field from JSON to an array property on retrieval and converts the array back to a JSON string on saving.
You can enable this by adding a $casts property to your Model with the field name as the key and array as the value:
protected $casts = [
'options' => 'array',
];
https://laravel.com/docs/5.4/eloquent-mutators#array-and-json-casting
If you had options as {name:bob,email:sue} in the database, you would then access them as $model->options['name'] and $model->options['email'].

JSON string in MySQL to json response

I have a JSON formatted string stored in a column (meta_data) in a mysql database, stored in the table it looks something like this for example:
{"Format":"JPEG","Geometry":"3216x2136","size":{"width":3216,"height":2136}}
Now if I use the following:
$meta_data = DB::query->get();
return $meta_data;
I get:
[
{
"meta_data": "{\"Format\":\"JPEG\",\"Geometry\":\"3216x2136\",\"size\":{\"width\":3216,\"height\":2136}
}
]
I also get the same result if I use:
$meta_data = json_decode(DB::query->get());
return $meta_data;
Similarly, using response()->json($meta_data); returns it as a string.
It seems to me that it needs to go the next step down but I haven't been able to get anything close to what I'm after, which is ideally:
[
{
"meta_data":
{
"Format":"JPEG",
"Geometry":"3216x2136",
"size":
{
"width":3216,
"height":2136
}
}
}
]
DB::query->get() will return an array of stdClass objects (assuming query is just shorthand for your query conditions). You will need to loop through the array and convert the meta_data field of each entry to a json object manually.
$records = DB::query->get();
foreach ($records as $record) {
$record->meta_data = json_decode($record->meta_data);
}
return $records;
Another option would be to create a Model for the table, and then add the meta_data field to the $casts property to automatically cast it to json.
Model:
class Attachment extends Model
{
protected $casts = [
'meta_data' => 'json',
];
}
Controller:
// assume "query" is shorthand for your query conditions
$records = Attachment::query->get();
return $records;

Yii2 ArrayHelper::toArray doesn't work recursively

Yii2 ArrayHelper's helper method toArray doesn't convert nested objects.
Here is my test code.
public function actionTest()
{
$product = \common\models\Product::find()
->where(['id' => 5779])
->with('firstImage')
->one();
$product = \yii\helpers\ArrayHelper::toArray($product);
print_r($product);
}
Recursive property is enabled by default.
public static array toArray ( $object, $properties = [], $recursive =
true)
So this piece of code should work correctly but it doesn't.
Action returns one level array without firstImage object.
What I'm doing wrong here?
PS:
Code was simplified for test purposes. I know that in this certain situation one can simply use asArray() method to get AR record in array.
You should use this instead :
$product = \common\models\Product::find()
->where(['id' => 5779])
->with('firstImage')
->asArray()
->one();
Read more about Retrieving Data in Arrays.
If your really want to use toArray(), and since a relation is not really an attribute or property, you should simply use the second parameter, e.g. :
$product = \yii\helpers\ArrayHelper::toArray($product, [
'common\models\Product' => [
// add needed properties here
// ...
'firstImage',
],
]);
Or, if you are using REST, you could override extraFields() in your model :
public function extraFields()
{
return ['firstImage'];
}
Read more about REST fields.

Categories