How to directly access JSON data as an object - laravel

I have a table where one of the columns has the data type "json". The column is called payment_data and inside of it I have a JSON object:
{"success":true,"status":0,"resposta":"OK","referencia":"44304425","entidade":"5555"}
I found an example online that I could call directly in Laravel, using this example:
{{ $order['payment_data->entidade']}}
But it doesn't work so I guess it is not right. Is there a helper available to get the information directly?

You have to override cast variable in your model:
protected $casts = [
'payment_data' => 'object'
];
Then you can use like this:
{{ $order->payment_data->entidade }}

You can use attribute casting on your model which would allow you to access the JSON data as an array.
For example, you can add the following to your your model class:
protected $casts = [
'payment_data' => 'array',
];
Then you should be able to access values inside the JSON value like this: $order->payment_data['entidade'].

try:
$order = new Order::find( 1 );
$json_data = json_decode( $order->payment_data );
echo $json_data->entidade;

If you have a json like this
{"success":true,"status":0,"resposta":"OK","referencia":"44304425","entidade":"5555"}
you can do like this to access the values
$json = {"success":true,"status":0,"resposta":"OK","referencia":"44304425","entidade":"5555"}
the you can access the values like this
$json = json_decode($json, true);
echo $json['entidade'];
I hope it helps some one,this how i solved my problem.

Related

store and update an array as json in mysql database laravel 9

I have values that I want to store in the database, I have declared the type as json and cast it as an array:
protected $casts = [
'favourites' => 'array'
];
however, I'm not sure how to add and update and read the values inside, any ideas?
controller function:
public function addtofav()
{
$id = request()->get('id');
$user = auth()->user();
json_decode($user->favourites,true);
array_push($user->favourites,$id);
dump('hello');
json_encode($user->favourites);
$user->save();
return response(['id'=> $id],200);
}
Quoting from the Laravel documenations:
adding the array cast to that attribute will automatically deserialize
the attribute to a PHP array when you access it on your Eloquent
model.
therefore, no need to make any encoding or decoding to your values before any update or create, just keep it as an array and Eloquent will take care of that, since you have the $cast array as below:
protected $casts = [
'options' => 'array',
];
Actually you should use many to many but if you want to use array, you don't encode or decode.
public function addtofav()
{
$id = request()->get('id');
$user = auth()->user();
$favourites = $user->favourites;
array_push($favourites,$id);
$user->favourites = $favourites
$user->save();
return response(['id'=> $id],200);
}

Encrypted Array Won't Save in Eloquent Model

I'm having an odd error with saving an encrypted array in Laravel. The model never updates even when save() is called.
There are no console or SQL errors.
When the encryption is disabled, there are no errors and the model updates successfully.
In a Controller, I'm calling the model like so:
$userData = UserData::where('user_id', $user_id)->first();
I then pull the array:
$encryptedData = $userData->app_data;
And I want to add to this array e.g.
$encryptedData['new'] = 'axy';
$encryptedData['time'] = time();
I then update the model and save it:
$userData->app_data = $encryptedData;
$userData->save();
However, here is where the problem starts. The model does not update. It remains as if nothing happens. Hence if I refresh(), I get the same data as if I had never added the two new entries. When I log it, it looks like this:
Array
(
[token] => xyz
[access_token] => abc
)
After the addition of two new entries:
Array
(
[token] => xyz
[access_token] => abc
[new] => 'axy'
[time] => 1234
)
And after the save() and refresh():
Array
(
[token] => xyz
[access_token] => abc
)
The model looks like this:
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Contracts\Encryption\DecryptException;
class UserData extends Model
{
protected $fillable = [
'user_id', 'app_data'
];
protected $casts = [
'user_id' => 'int',
'app_data' => 'array'
];
public function getAppDataAttribute($value)
{
try {
return decrypt($value);
}
catch (DecryptException $e) {
return $value;
}
}
public function setAppDataAttribute($value)
{
$this->attributes['app_data'] = encrypt($value);
}
}
Why are my additions to the array not being saved?
Edit: The strangeness continues
If I call:
UserData::where('id', $userData->id)->update(['app_data' => $encryptedData]);
Then the model does update and does not encrypt, HOWEVER, when I refresh and log the new 'app_data' field, it is returned as a JSON string and not an array as before. I need to cast/decode it to an array each time I want to use it.
Couple of things to look for.
1) The Laravel encrypter uses the app key. Make sure you have one in your .env file. If not, run php artisan key:generate
2) I assume the array is correctly formatted like this:
Array
(
'token' => 'xyz', // You have a = here and no commas after any other value
'access_token' => 'abc'
)
3) Depending on what you are storing this as, you can test by serializing the array before encrypting it:
$arr = serialize($encryptedData); // After you have added new data to the array
$userData->app_data = $arr;
$userData->save();
This is automatic in Laravel, but may give you a help hunting the bug. Test with your mutator using encryptString() and manually unserialize / decryptString() to see if any odd behavior by stepping through the values as they are mutated.

adding manul data to form requests in laravel

I have this fuction which is getting data from my form add create row in database
$project = Project::create($request->only(['title', 'report_type', 'user_id', 'body', 'attachment', 'projectclass', 'budget', 'deadline']));
now I want add another data into it but that data not coming from form it generates in controller,
'pnum' => mt_rand(1000, 9223372036854775807)
How can I add my pnum data to the function above?
Take request data into variable which will be of type array and add there your new element
$insertData = $request->only(['title', 'report_type', 'user_id', 'body', 'attachment', 'projectclass', 'budget', 'deadline']);
$insertData['pnum'] = mt_rand(1000, 9223372036854775807);
Now you can pass this variable to create method
$project = Project::create($insertData);
first keep all the the data of your request to the variable eg: $data
and then follow the following
$data= $request->all();
$data['pnum'] = mt_rand(1000, 9223372036854775807);
$project = Project::create($data);

How to change value of a request parameter in laravel

I need to change value of my request parameter like this:
$request->name = "My Value!";
I use this code but does not work:
$request->offsetSet('img', $img);
Try to:
$requestData = $request->all();
$requestData['img'] = $img;
Another way to do it:
$request->merge(['img' => $img]);
Thanks to #JoelHinz for this.
If you want to add or overwrite nested data:
$data['some']['thing'] = 'value';
$request->merge($data);
If you do not inject Request $request object, you can use the global request() helper or \Request:: facade instead of $request
Use merge():
$request->merge([
'user_id' => $modified_user_id_here,
]);
Simple! No need to transfer the entire $request->all() to another variable.
Read more about Laravel's merge() here:
https://laravel.com/docs/collections#method-merge
If you need to customize the request
$data = $request->all();
you can pass the name of the field and the value
$data['product_ref_code'] = 1650;
and finally pass the new request
$last = Product::create($data);
If you need to update a property in the request, I recommend you to use the replace method from Request class used by Laravel
$request->replace(['property to update' => $newValue]);
Use add
$request->request->add(['img' => $img]);
If you use custom requests for validation, for replace data for validation, or to set default data (for checkboxes or other) use override method prepareForValidation().
namespace App\Http\Requests\Admin\Category;
class CategoryRequest extends AbstractRequest
{
protected function prepareForValidation()
{
if ( ! $this->get('url')) {
$this->merge([
'url' => $this->get('name'),
]);
}
$this->merge([
'url' => \Str::slug($this->get('url')),
'active' => (int)$this->get('active'),
]);
}
}
I hope this information will be useful to somebody.
It work for me
$request = new Request();
$request->headers->set('content-type', 'application/json');
$request->initialize(['yourParam' => 2]);
check output
$queryParams = $request->query();
dd($queryParams['yourParam']); // 2
Great answers here but I needed to replace a value in a JSON request. After a little digging into the code, I came up with the following code. Let me know if I'm doing something dumb.
$json = $request->json()->all();
$json['field'] = 'new value';
$request->json()->replace($json);
Try that :
$request["name"] = "My New Value";
$request["img"] = $img;
It's worked in Laravel 8.
Also, make sure to update the model class.
Item
{
fillable=[
'img',
... // other attributes
];
}
in case of updating an item of object you can write the lines bellow
$Obj = $request->data;
$Obj['item'] = value;

Laravel testing, get JSON content

In Laravel's unit test, I can test a JSON API like that:
$this->post('/user', ['name' => 'Sally'])
->seeJson([
'created' => true,
]);
But what if I want to use the response. How can I get the JSON response (as an array) using $this->post()?
Proper way to get the content is:
$content = $this->get('/v1/users/1')->decodeResponseJson();
Currently, in 5.3 this is working...
$content = $this->get('/v1/users/1')->response->getContent();
However, it does break the chain since response returns the response and not the test runner. So, you should make your chainable assertions before fetching the response, like so...
$content = $this->get('/v1/users/1')->seeStatusCode(200)->response->getContent();
As at Laravel 8, this worked for me.
I was returning an automatically generated field (balance) after the POST request has created the entity.
The response was in the structure {"attributes":{"balance":12345}}
$response = $this->postJson('api/v1/authors', [
'firstName' => 'John',
'lastName' => 'Doe',
])->assertStatus(201);
$balance = $response->decodeResponseJson()['attributes']['balance'];
decodeResponseJson will pick the response and transform it to an array for manipulation.
Using getContent() returns json and you will have to use json_decode on the returned data to turn it into an array.
I like to use the json method when working with json, instead of ->get()
$data = $this->json('GET', $url)->seeStatusCode(200)->decodeResponseJson();
I hit a similar problem and could not get $this->getResponse()->getContent() working with the built in $this->get() method. I tried several variations with no success.
Instead I had to change the call to return the full http response and get the content out of that.
// Original (not working)
$content = $this->get('/v1/users/1')->getContent();
// New (working)
$content = $this->call('GET', '/v1/users/1')->getContent();
Simple way:
$this->getJson('api/threads')->content()
Just want to share, I have used the same in $this->json() like:
$response = $this->json('POST', '/order', $data)->response->getContent();
But I added one more line to use json response and decode otherwise decodeResponseJson() was not working for me.
$json = json_decode($response);
Found a better way:
$response = $this->json('POST', '/order', $data);
$responseData = $response->getOriginalContent(); // saves the response as an array
$responseData['value'] // you can now access the array values
This method returns the response json as an array.
You can just call:
$data = $response->json();
$response = $this->json('POST', '/products', $data);
$data = $response->getData();

Resources