How to work with JSON coming from api-platform - json

I've installed the api-platform demo on a server and I did a client app (working with Symfony 3.3) and I want to display the response in a classic view (Twig).
Everything's working fine : I can request and retrieve the response.
But here's where i'm stuck : when I dump the response in my view I got this
{"#context":"\/contexts\/Book","#id":"\/books","#type":"hydra:Collection","hydra:member":[{"#id":"\/books\/1","#type":"Book","id":1,"isbn":"9783161484100","title":"1st Book","description":"This is my first book synopsis","author":"Hemingroad","publicationDate":"2018-02-16T14:15:58+00:00","reviews":[]}],"hydra:totalItems":1}
Here's my controller's method :
//...
use GuzzleHttp\Client;
public function newAction(Request $request)
{
//initialize client API
$client = new Client([
'base_uri' => 'http://my.apidomain.com/',
'timeout' => 2.0,
]);
//request to API
$dataBooks = $client->request('GET', 'books', ['auth' => ['login', 'p#$$w0rd']]);
$listBooks = $dataBooks->getBody()->getContents();
return $this->render('book/new.html.twig', array(
'listBooks' => $listBooks
));
}
I've also tried to json_decode and using JMSSerializer on $listBooks.
I got a beautiful object but I still cant access the JSON attribute's like ISBN, title by doing something like
{% for book in listBooks %}
{{ dump(book.title) }}
<!-- .... -->
{% endfor %}
Here's what I got when I json_decode $listBooks :
{{ dump(listBooks) }}
I got an error when I try to access every field like this
{{ dump(listBooks.#id) }}
{{ dump(listBooks['hydra:member']) }}
....
Am I missing something ?
Thanks

$dataBooks->getBody()->getContents(); returns a string, as described in Guzzle's documentation, so you need to use json_decode.
$listBooks = json_decode($listBooks); returns an object. In Twig you can use the dot notation to access methods and properties of an object, e.g. {{ listBooks.myProp }}. But because hydra:member includes a special character (:), you need to use Twig's attribute function, as described in Twig's documentation:
{{ attribute(listBooks, 'hydra:member') }}
Another approach is to do $listBooks = json_decode($listBooks, true); so that you get an associative array instead of an object. Then you can use the bracket notation in Twig:
{{ listBooks['hydra:member'] }}
I would prefer this second approach, because in my opinion {{ listBooks['hydra:member'] }} is much clearer and cleaner than {{ attribute(listBooks, 'hydra:member') }}.

Related

json_decode () breaking when called directly in the Laravel Blade template - (expects string, object given)

I have a Laravel Results model that returns some data from a database to a blade view from a 'results' table. One of the columns is called properties which is of a json datatype and it stores data similar to the following:
{
"clubs": [
{
"id": 1741008,
"name": "BanterburyFC",
"wins": "0"
},
{
"id": 17844730,
"name": "es ticazzi",
"wins": "1"
}
]
}
The index controller gets the results from the getResults() function which returns an array of values such as match_id, home_team_goals, away_team_goals & properties - the properties (which is of a json datatype in the MySQL database is looped through on the frontend & I do the json_decode directly in the blade template, however it gives me the following error.
htmlspecialchars() expects parameter 1 to be string, object given (View: /Users/myname/Projects/myapp/resources/views/dashboard.blade.php)
Weirdly when I run the json_decode() on the same data in the controller before I pass this into the view it works fine and creates an object as expected. However for some reason when I attempt to run the json_decode directly inside the blade view it returns the Error Exception above.
What's wrong?
Controller logic
public function index()
{
$user = auth()->user();
$data = [ 'results' => Result::getResults($user->properties) ];
// var_dumping so I can check the data before it is passed to the blade view
var_dump($data['results'][0]->properties); // returns string - looks fine & this doesn't return any errors
var_dump(json_decode($data['results'][0]->properties)); // returns object - looks fine & this doesn't return any errors either
return view('dashboard', $data);
}
Blade view/template
#foreach ($results as $result)
{{ json_decode($result->properties) }} <!-- the line causing the problem -->
{{ json_decode($result->properties, true) }} <!-- this also fails -->
#endforeach
Using PHP 8.x & Laravel 8.x
In the Laravel blade {{}} is equal to echo so it accept string not an object. It uses htmlspecialchars internally for XSS protection against injection. So when you are trying to do {{ json_decode($result->properties) }}, it is throughing the error. Instead you can use #php ... #endphp directives.
#foreach ($results as $result)
#php $p = json_decode($result->properties); #endphp
#endforeach

Object values not being passed

I am using Laravel 5.6 and having an issue passing data to my blade file.
BlogController:
namespace App\Http\Controllers;
use App\Mail\Practice;
use App\Mail\Mailable;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use App\Post;
use Session;
class BlogController extends Controller
{
public function getSingle($slug){
// Fetch from the DB based on Slug --first stops after one, get pulls everything
$post = Post::where('slug', '=', $slug)->first();
print_r($slug);
// return the view and pass in the post object
return view('blog.single')->withPost($post);
}
}
single.blade.php:
#extends('main')
#section('title', "| $post->title")
#section('content')
<div class="row">
<div class="col-md-8 col-md-offset-2">
<h1>{{ $post->title}}</h1>
<p>{{ $post->body }}</p>
</div>
#stop
I verified the name and spelling in the DB (MySQL.) If I dd($slug) or print_r($slug) the results are correct.
However, if I do the same but use $title or $body it returns the error
Trying to get property of non-object (View: /Users/jesseburger/myproject/resources/views/blog/single.blade.php)
I have been able to verify its pulling an empty array by using print_r($post) but can't figure out why.
print_r($post) yields:
Illuminate\Database\Eloquent\Collection Object ( [items:protected] => Array ( ) )
Current route:
Route::get('blog/{slug}', [
'as' => 'blog.single',
'uses' => 'BlogController#getSingle'
])->where('slug', '[\w\d\-\_]+');
Your return statement is incorrect, you need to change this line:
return view('blog.single')->withPost($post);
To this, it should resolve your issue.
return view('blog.single')->with('post', $post);
First you are debugging your slug not your post. Try to debug your post to see if it was found. You are getting that error because the post doesn't exist at all. Abort if it doesn't exist.
if(!$post){
abort(404);
}

Access a single element of the array within twig

I'm using symfony2 and twig in my view. I'm sending an array to the view which has been created using from a mysql query, not using the symfony entity framework:
$claims_summary_table = $statement->fetchAll();
I can dump this in the view...
{{ dump(claims_summary_table) }}
array:1 [▼
0 => array:11 [▼
"claim_status" => "Open"
"claim_id" => "101"
"claim_reference" => "BALLINGM"
"loss_date_from" => "2015-06-02"
"loss_catastrophe_name" => "Fire"
"loss_value" => "2000.00"
"total_payments" => "300.00"
"total_reserve" => "2000.00"
"claim_file_closed" => null
"last_seen_date" => "2016-04-20 11:20:25"
"last_seen_by" => "2"
]
]
but I just want to access one element, I just want to access "Open".
I have tried {{ claims_summary_table.claim_status }}
The only way I can access the single element is if I use a { for.....}.
How can I just get one element?
If you need to access the first element of the sub-array you can use the following.
{{ claims_summary_table[0][0]. claim_status }}
and
{{ claims_summary_table[0][0]. claim_id }}
Otherwise you need to iterate and looking for the record with the claim_stauts open
You can access the values by array key, in your case:
{{ claims_summary_table[0]. claim_status }}

Laravel: How do I parse this json data in view blade?

Currently this is my view
{{ $leads }}
And this is the output
{"error":false,"member":[{"id":"1","firstName":"first","lastName":"last","phoneNumber":"0987654321","email":"email#yahoo.com","owner":{
"id":"10","firstName":"first","lastName":"last"}}]}
I wanted to display something like this
Member ID: 1
Firstname: First
Lastname: Last
Phone: 0987654321
Owner ID: 10
Firstname: First
Lastname: Last
It's pretty easy.
First of all send to the view decoded variable (see Laravel Views):
view('your-view')->with('leads', json_decode($leads, true));
Then just use common blade constructions (see Laravel Templating):
#foreach($leads['member'] as $member)
Member ID: {{ $member['id'] }}
Firstname: {{ $member['firstName'] }}
Lastname: {{ $member['lastName'] }}
Phone: {{ $member['phoneNumber'] }}
Owner ID: {{ $member['owner']['id'] }}
Firstname: {{ $member['owner']['firstName'] }}
Lastname: {{ $member['owner']['lastName'] }}
#endforeach
it seems you can use #json($leads) since laravel 5.5
https://laravel.com/docs/5.5/blade
For such case, you can do like this
#foreach (json_decode($leads->member) as $member)
{{ $genre }}
#endforeach
You can use json decode then you get php array,and use that value as your own way
<?php
$leads = json_decode($leads, true);
dd($leads);
The catch all for me is taking an object, encoding it, and then passing the string into a javascript script tag. To do this you have to do some replacements.
First replace every \ with a double slash \\ and then every quote" with a \".
$payload = json_encode($payload);
$payload = preg_replace("_\\\_", "\\\\\\", $payload);
$payload = preg_replace("/\"/", "\\\"", $payload);
return View::make('pages.javascript')
->with('payload', $payload)
Then in the blade template
#if(isset($payload))
<script>
window.__payload = JSON.parse("{!!$payload!!}");
</script>
#endif
This basically allows you to take an object on the php side, and then have an object on the javascript side.
in controller just convert json data to object using json_decode php function like this
$member = json_decode($json_string);
and pass to view in view
return view('page',compact('$member'))
in view blade
Member ID: {{$member->member[0]->id}}
Firstname: {{$member->member[0]->firstname}}
Lastname: {{$member->member[0]->lastname}}
Phone: {{$member->member[0]->phone}}
Owner ID: {{$member->owner[0]->id}}
Firstname: {{$member->owner[0]->firstname}}
Lastname: {{$member->owner[0]->lastname}}
Example if you have array format like this:
$member = [
[ "firs_name" => "Monica",
"last_name" => "Dev",
"sex" => "F"
],
[ "firs_name" => "Blake",
"last_name" => "Devante",
"sex" => "M"
],
[ "firs_name" => "Johnny",
"last_name" => "Merritt",
"sex" => "M"
]
]
You can use #json Blade directive for Laravel 5.5 to 9.x
<script>
var app = #json($member);
</script>
From Laravel 8.x to latest version you can use Illuminate\Support\Js::from method directive.
<script>
var app = {{ Illuminate\Support\Js::from($member) }};
</script>
And for short with Js facade
<script>
var app = {{ Js::from($array) }};
</script>
Reference:
https://laravel.com/docs/blade
If your data is coming from a model you can do:
App\Http\Controller\SomeController
public function index(MyModel $model)
{
return view('index', [
'data' => $model->all()->toJson(),
]);
}
index.blade.php
#push('footer-scripts')
<script>
(function(global){
var data = {!! $data !!};
console.log(data);
// [{..}]
})(window);
</script>
#endpush
Just Remove $ in to compact method ,
return view('page',compact('member'))

Symfony2 doctrine2 array data is available and works in Twig file but rendered blank page

I'm getting datas from MySQL database but not display in rendered TWIG file. in TWIG file, I execute Twig's dump() function It works, all datas displayed but TWIG is empty.
$em = $this->getDoctrine()->getEntityManager();
$yorumlar = $em->getRepository('SiteSiteBundle:Yorum')->find($id);
if (!$yorumlar) {
throw $this->createNotFoundException($id . ' nolu Yorum bulunamadı!');
}
return $this->render('SiteSiteBundle:Default:liste.html.twig', array(
'yorumlar' => $yorumlar
));
Just acces to your propertie. Using var_dumpt, print_r or any dump function in a managed entity could crash or marke verry slow you php server because it will try to dump you entity doctrine and all his dependancies maybe the container...
{{ yorumlar.yourPorpertie }}