Render object as context in twig template - php

How to render an object instead of array, like we usually do?
echo $twig->render('index.html', array('name' => 'Fabien'));
The render() function does not accept an object.
Is there any way to render the object directly?.
And I do not mean an "objectToArray" solution.

The second parameter of the method render take an array for transport data to the view, so you simply put your object as value of the array with a specified key. Something like this:
$object = new People()
$object->setName('Fabien');
echo $twig->render('index.html', array('obj' => $object));
And use in the template as
{{ obj.name }}
Hope this help

Related

Laravel, only first element of array passed to route is readable

From a blade template I want to pass an array with a variable amount of values to a route, as described in the answer here.
However when I do this I can only ever access the first value in the array I pass to the route.
This is how I call the route in the blade template:
{{ route('stats.downloads', ['stat_kind' => 'files_size', 'group_by' => 'week', 'start' => '2020-11-01', 'end' => '2020-11-10']) }}
this is my route from web.php:
Route::get('stats/downloads', 'StatsController#view_stats_downloads')->name('stats.downloads');
and my controller:
public function view_stats_downloads(Request $request){
// get the input parameters
$group_by = $request->get('group_by');
$stat_kind = $request->get('stat_kind');
$company = $request->get('group_by');
$user = $request->get('user');
$start = $request->get('start');
$end = $request->get('end');
...
The problem is, that I can only ever access the first value of the array I pass to the controller (stat_kind in this case). It doesn't natter in which order I call the get() function either.
What can I do to fix this?
I'm running laravel 5
Try changing the curly braces, {{ }}, to {!! !!} where you are calling the route helper.
The & is being encoded to & so only the first query string parameter that you are sending does not have a & in front of it so it is named correctly. The others are named with the amp;, the part after the & in the encoded ampersand.

Twig - Sandbox security policy won't work

I have been trying to get this to work for a while now and can't find much docs on it. Or any use cases where the sandbox policy has been used outside of the Symfony framework.
I'm using Twig as a stand-alone package, so can't use any Symfony pseudo-code.
I have strict mode enabled so the sandbox affects all templates. Most templates render fine except this one which makes a call to a class. However I don't know how to allow it through.
Class:
class GetThings {
public function doStuff() {
return array(
'id' => '...',
'data' => '...'
);
}
}
...
Twig:
$allowedTags = ['if', 'else', 'elseif', 'endif', 'for', 'endfor'];
$allowedFilters = ['upper', 'escape'];
$allowedMethods = [
'GetThings' => array('doStuff') // Possibly this may be wrong?
];
$allowedProperties = [
'GetThings' => array('id', 'data') // Or this is wrong? But not sure the correct way.
];
$allowedFunctions = ['range'];
$policy = new Twig_Sandbox_SecurityPolicy($allowedTags, $allowedFilters, $allowedMethods, $allowedProperties, $allowedFunctions);
$sandbox = new Twig_Extension_Sandbox($policy, true);
...
Template:
{% for i in info %}
{{ i.id }} <- Code that raises securityPolicy exception.
{{ i.data }} <- Code that raises securityPolicy exception.
{% endfor %}
I believe it may be related to the allowed methods or properties, but I wasn't able to find any working examples of these in use. I've tried the full namespaces too, nothing.
EDIT:
So I looked into this error a bit deeper and found the exception stack-trace, for some reason it thinks my class is StdClass rather than GetThings? Not sure why. Any ideas?
Twig_Sandbox_SecurityNotAllowedPropertyError: Calling "id" property on a "stdClass" object is not allowed.
To instantiate the class I simply do the following:
public function index() {
$data = new GetThings();
// echo get_class($data); // returns GetThings as expected...
return $twig->render('index.twig', [
'info' => $data->doStuff()
]);
}
If I do 'StdClass' => array('id', 'data') for the allowed properties, the page works fine. But I feel this is not working as intended, as StdClass could be anything? And GetThings should work, no?
EDIT:
I think I figured it out. So my allowed properties allows 'GetThings' => [id, data] which is fine. doStuff() returns a \PDO array of objects, using the \PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_OBJ option which causes PDO to convert all returned values into StdClass objects.
Is there any way around this? I want to keep that option, but still want to reference the policy as 'GetThings' => [...] rather than 'StdClass' => [...]
It works as intended:
{% for i in info %}
{{ i.id }} <- Code that raises securityPolicy exception.
{{ i.data }} <- Code that raises securityPolicy exception.
{% endfor %}
Here i is not a GetThings instance. It's whatever you instantiated as value for the id and data key:
return array(
'id' => '...',
'data' => '...'
);
Twig for tag will iterate over the info variable, which happens to be a keyed array. So the loop will iterate over the values of the array - in your case '...' and '...' which I guess are stdClass instances.

How to Insert values in a Twig template and use the plain text as a string?

I want to be able to send html email. I created the template with twig and I have some variables in it {{ name }} {{ date }} and so on.
What I want to do now is to pass variables from my php script into the template and to use the new html file with the injected values as a string which I am going to mail().
How could I achieve this ?
I tried
$emailText = $this->container['view']->render('user/mailTemplate.html', array('name' => $username, 'date'=>$currentdate));
But I get 'Message: Argument 1 passed to Slim\Views\Twig::render()
must implement interface Psr\Http\Message\ResponseInterface '
Using the Slim Framework Twig View component gives you the fetchFromString() method:
$rendered = $this->view->fetchFromString(
$template_string,
array('fname' => 'John',
'lname' => 'Doe')
);
Or use ->fetch() to load the template from a file (if it is in the template directory).

Laravel - Breadcrumbs module : pass array of arguments

I am using this module .
I defined my Breadcrumbs, and now I'm trying to render in my blade template by doing the following :
{!! Breadcrumbs::render($breadcrumbs) !!}
The value of $breadcrumbs being "controlled" by my controller.
The problem is that I would like to be able to pass an array of arguments to this render() method, and not only simple strings. Indeed, here are some Breadcrumbs I declared :
Breadcrumbs::register('home', function($breadcrumbs)
{
$breadcrumbs->push('Home', route('home'));
});
/* .... etc .... */
Breadcrumbs::register('style', function($breadcrumbs, $style_name, $style_slug)
{
$breadcrumbs->parent('styles');
$breadcrumbs->push($style_name, route('style', $style_slug));
});
In this situation, I need to be able to pass an array of arguments to the render() method, which will be sent by the Controller to the View.
I tried the following :
{!! call_user_func_array(Breadcrumbs::render, $breadcrumbs) !!}}
But I get the following error :
Undefined class constant 'render'
This module has a renderArray() method. Next time, I'll read the documentation till the end :)

Print a variable that contains html and twig on a twig template

I have a variable suppose that is:
$menustr; this variable contains code html and some twig parts for example:
$menustr .= '<li><a href="{{ path("'. $actual['direccion'] .'") }}" >'. $actual['nombre'] .'</a></li>';
I need that the browser take the code html and the part of twig that in this momen is the
"{{ path(~~~~~) }}"
I make a return where i send the variable called "$menustr" and after use the expresion "raw" for the html code but this dont make effective the twig code.
This is te return:
return $this->render('::menu.html.twig', array('menu' => $menustr));
and here is the template content:
{{ menu | raw }}
Twig can't render strings containing twig. There is not something like an eval function in Twig1..
What you can do is moving the path logic to the PHP stuff. The router service can generate urls, just like the path twig function does. If you are in a controller which extends the base Controller, you can simply use generateUrl:
$menuString .= '<li>'. $actual['nombre'] .'</li>';
return $this->render('::menu.html.twig', array(
'menu' => $menuString,
));
Also, when using menu's in Symfony, I recommend to take a look at the KnpMenuBundle.
EDIT: 1. As pointed by #PepaMartinec there is a function which can do this and it is called template_from_string
You can render Twig template stored in a varible using the template_from_string function.
Check this bundle: https://github.com/LaKrue/TwigstringBundle
This Bundle adds the possibility to render strings instead of files with the Symfony2 native Twig templating engine:
$vars = array('var'=>'x');
// render example string
$vars['test'] = $this->get('twigstring')->render('v {{ var }} {% if var is defined %} y {% endif %} z', $vars);
// output
v x y z
In your case i would be:
return $this->render('::menu.html.twig', array(
'menu' => $this->get('twigstring')->render($menustr, $vars)
));

Categories