I'm using Laravel basic authentication but I am really struggling to use the Auth object in the views.
There are good examples using Blade, but I am using Twig (twig bridge) and cannot solve this.
I can vardump(Auth::user()->name) in my controller in regular php but how do I get the same in the twig file (my view file)?
How do I do something like;
{% if auth.guest %}
Or;
{{ Auth.user().name }}
I've tried so many different ways but just get nothing.
This has to do with the way twig works, accessing static variables /classes or static methods on classes is impossible without adding a function to the Twig Environment.
You can register a function like so:
$twig = new Twig_Environment($loader);
$twig->addFunction('staticCall', new Twig_Function_Function('staticCall'));
function staticCall($class, $function, $args = array())
{
if (class_exists($class) && method_exists($class, $function))
return call_user_func_array(array($class, $function), $args);
return null;
}
Then i think you should be able to do:
{% if staticCall('Auth', 'guest') %}
Hi there stranger, why don't you login?
{% endif %}
I took the code from this answer: twig template engine, using a static function or variable
Related
Over a template I do a render method:
{{ render(controller('AppBundle:Widgets:myCapsWidget'),{'somestring':someString}) }}
Over the controller I have the following method:
public function myCapsWidgetAction($somestring)
{
return new Response(strtoupper($somestring));
}
I also looked over theese links:
symfony twig render controller argument array
https://knpuniversity.com/screencast/symfony2-ep3/render-controller
But still cannot find any light to my path.
If I read the first link you gave us, you should use:
{{ render(controller('AppBundle:Widgets:myCapsWidget',{'somestring':someString})) }}
I'm starting a project using Phalcon framework with Volt as a template engine. I have some experience with Symfony/Twig.
I read documentation and tried searching all over the internet but can't find a satisfying way to accomplish what I want (I find ugly the solution described here: How do I create common template with header and footer for phalcon projects with Volt Engine; it's not using Volt per se for the navigation.)
So the story is pretty easy: my base template consists of 4 parts: navigation, header, content and footer. I use partials to include the common areas in the base template like the navigation, header and the footer, works fine with "static data".
Now the question is: how do I get to dynamically generate the navigation menu with items coming from the database? The template will have common areas that have to come from DB also in the header, footer and a sidebar. Having to fetch that in all Controller actions sounds like overkill and not very DRY (maybe do it on the init part? but will have to be done in every controller. Maybe in an abstract controller, I dunno.)
What is the best way to accomplish this in Phalcon/Volt? In Symfony/Twig you can call from the view a controller action, so you can have like a LayoutController that renders partials from a page.
Thanks!
Here are few variants:
1) Your controllers can extend a BaseController and in it's initialize() method you can assign those variables to the view.
class BaseController extends \Phalcon\Mvc\Controller
{
public function initialize()
{
// Common Variables
$this->view->assetsSuffix = $this->config->debug ? '' : '.min';
}
2) Create a custom Volt function which loads the data.
// In your Volt service:
$compiler->addFunction('getMenu', function($resolvedArgs, $exprArgs){
return 'Helpers\CommonFunctions::getMenu(' . $resolvedArgs . ')';
})
// Helper file and function
public static function getMenu()
{
return \Models\Menu::find();
}
// Volt usage
{% set menuItems = getMenu() %}
{% for item in menuItems %}
{% endfor %}
3) Use the models to query the DB directly from the template. However this is not yet supported with Volt (not sure if it is added in latest version, have to confirm).
<?php $menuItems = \Models\Menu::find(); ?>
{% for item in menuItems %}
{% endfor %}
4) Ajax/Javascript, but this is really dependant on your application. Something like Angular approach, but I will not get into details with this varaiant.
I want to set a layout like main.htm for all of my twig files in yii 2, but it loads the folder that controller call first, so I can not call my layout with extends.
in SiteController
public function actionIndex()
{
return $this->render('index.htm');
}
This code calls views/site/index.htm
In my index.htm
{% extends "main.html" %}
So if I put the main.html in site folder, there is no problem, but I want to put it in the layout folder and can be called every controller views .. How can I do that ??
views
->site
->index.html
->layouts
->main.html
For example in symfony we can call like this
{% extends '::base.html.twig' %}
But in Yii2 I can not found a way to do this ....
I have done this with hardcoded the file viewRenderer.php. This is not the way I like it because a composer update the changes are gone away...
Now the function init is like this the loader is null here. I have added loader for my layouts.
$this->twig = new \Twig_Environment(null, array_merge([
'cache' => Yii::getAlias($this->cachePath),
'charset' => Yii::$app->charset,
], $this->options));
After adding a loader ..
$this->loader = new \Twig_Loader_Filesystem($_SERVER["DOCUMENT_ROOT"].'\views\layouts');
And last thing is render function in ViewRenderer.php
public function render($view, $file, $params)
{
$this->twig->addGlobal('this', $view);
//$this->twig->setLoader(new TwigSimpleFileLoader(dirname($file)));
$this->loader->addPath(dirname($file));
return $this->twig->render(pathinfo($file, PATHINFO_BASENAME), $params);
}
I want it without hardcoded changes in the core file of yii2-twig ....
Have you tried using a full path here {% extends "main.html" %}. Something like {% extends "\layouts\main.html" %}
Or even {% extends "#app/views/layouts/main.html" %}
I have not used twig with yii, but it is worth a shot.
In php I can use in my template:
use My\WebBundle\Classes\Util;
How can I put the same in Twig tempate?
Thanks.
You can't create objects in twig template, but you can pass them in twig template from controller:
public function postsAction() {
return $this->render('AcmeBlogBundle:User:posts.html.twig', array(
'util' => new My\WebBundle\Classes\Util(),
));
}
And in twig template can use it:
{{ util.anyProperty }}
You don't want PHP in your twig template. All you need to do is tell twig what variables you use. It's part of the MVC.
http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller
How can i create a link to the current in my template?
I want to create a language switcher which should link to the current page in varios languages, so all parameters should be the same exept for the locale.
I end up rolling my own function for this. I though at first it was included somewhere in FrameworkBundle but did not find anything about it. Here the steps I took.
At first, I created a Twig extension function that would output the same route as the one the user is visiting currently (parameters and query string included). I left this step to you. You can look at this link from a good tutorial on Symfony2 for the description of how to create a Twig extension if you don't know how already. I could help you with it if you need it.
Next step is to create the function itself that will switch the locale of the current route. This function will need the Request and Router objects as dependencies. In my personal case, I put this function in a dedicated service named RoutingHelper service. This service is then used by my Twig extension function. Here the service definition I added to the dependency container:
acme.helper.routing:
class: Application\AcmeBundle\Helper\RoutingHelper
scope: "request"
arguments:
request: "#request"
router: "#router"
And the constructor of my service:
protected $request;
protected $router;
public function __construct($request, $router)
{
$this->request = $request;
$this->router = $router;
}
The $locale parameter is new locale would like to switch to. Here the function:
public function localizeCurrentRoute($locale)
{
$attributes = $this->request->attributes->all();
$query = $this->request->query->all();
$route = $attributes['_route'];
# This will add query parameters to attributes and filter out attributes starting with _
$attributes = array_merge($query, $this->filterPrivateKeys($attributes));
$attributes['_locale'] = $locale;
return $this->router->generate($route, $attributes);
}
Essentially, it does what others have put so far but it also handles parameters and query string. The method filterPrivateKeys will remove private attribute from the route attributes. Those attributes are the one starting with an underscore and should not be passed back to the route generator. Here its defintion:
private function filterPrivateKeys($attributes)
{
$filteredAttributes = array();
foreach ($attributes as $key => $value) {
if (!empty($key) && $key[0] != '_') {
$filteredAttributes[$key] = $value;
}
}
return $filteredAttributes;
}
In the end, I'm able to this in my Twig view to create links to switch locales:
{% block language_bar %}
English
Français
{% endblock %}
Edit:
Here my twig extension service definition:
acme.twig.extension:
class: Application\AcmeBundle\Twig\Extension\AcmeExtension
arguments:
container: "#service_container"
tags:
- { name: twig.extension }
And in the twig extension function I have this call: $routingHelper = $this->container->get('acme.helper.routing');
This should solve the scope widening exception happening because the twig extension is not in the request scope.
Update:
It is now possible with Symfony 2.1 to have a locale switcher in an easier way than before. Indeed, the 2.1 version of Symfony introduced a new parameter for routes that make it more easy to do a locale switcher. Here the code, all in twig
{% set route_params = app.request.attributes.get('_route_params') %}
{# merge the query string params if you want to keep them when switching the locale #}
{% set route_params = route_params|merge(app.request.query.all) %}
{# merge the additional params you want to change #}
{% set route_params = route_params|merge({'_locale': 'fr'}) %}
{{ path(app.request.attributes.get('_route'), route_params) }}
It is still a few lines of twig code, but could be included in a Twig block for easier reuse. Credits to stof, from the Symfony community, for the code above.
Hope this is what you are looking for.
Regards,
Matt
Current page
Similar question: language switching without changing the current page
English