I'm working in Symfony and tried to pass a variable called $services into my twig template. Naturally, I would also refer to the variable in twig with the same name.
$services = new ArrayCollection(); // Some array
$this->render('template.html.twig', [
'services' => $services
]);
For some reason however, services always is a boolean value of true. This is instead of the ArrayCollection I am trying to pass into it.
I've checked my twig configuration for anything that could be assigning itself as a global variable but everything checks out, and I can't seem to find any documentation about services being a reserved keyword.
FWIW, I renamed the twig variable name from services to foo for sanity checking and the $services variable behaves as expected, so it's definitely got something to do with assigning a variable to the word services in twig.
I'm currently running Twig 2.14.3
Apart from checking if there are any global variables set, are there any other avenues for trying to find why and where this variable would be defined?
After a few hours of troubleshooting, it seems like a pretty dumb answer.
I checked:
Global variables in my twig.yaml configuration
Made sure that any custom twig extensions weren't bound to service
Checked that any bound services weren't creating any functions with the name service
Made sure that I wasn't setting service in any of my templates up to my base template
It seemed like a whole lotta nothing, then I started turning to some 3rd party bundles that have some twig templates registered.
It turns out a bundle had a template with {% set services = ... %} written inside it, which was included in my base template.
+1 to #yivi for brining debug:twig to my attention, as it was incredibly useful knowing what is bound to twig. It was this info that made me aware of any namespaces that bundles had bound themselves to and gave some extra places to start looking.
Related
I need to generate with Simplesamlphp library an AuthnRequest with the following Extensions tag
<samlp:Extensions xmlns:spid="https://spid.gov.it/saml-extensions">
<spid:Purpose>PX</spid:Purpose>
</samlp:Extensions>
In Simplesamlphp's documentation is explained how to generate an Extensions' child with namespace,
but it's not clear if it's possible to add a namespace to Extensions tag itself.
Any suggestion/clarification?
I've been working for some weeks to update our version of simplesamlphp, we provide SPID, CIE, SPID eIDAS, ...
My company was using a version of the library from 2010 when I came here, after many many struggles I managed to update SPID completely and I'm almost done with CIE (and then there's the rest!).
Hope I can help you a bit for all I suffered.
To fix this issue I did this:
added these rows inside vendor/simplesamlphp/saml2/src/SAML2/XML/md/EntityDescriptor.php to declare these namespaces globally (one for SPID and one for CIE)
if($this->getIncludeSPIDns() === true){ //[EC] 14-03-'22
$e->setAttribute ( 'xmlns:spid', 'https://spid.gov.it/saml-extensions' );
}
if($this->getIncludeCIEns() === true){ //[EC] 14-03-'22
$e->setAttribute ( 'xmlns:cie', 'https://www.cartaidentita.interno.gov.it/saml-extensions' );
}
I had to modify some files and declare these properties and their getters inside the EntityDescriptor class, because I wanted them to be dinamic:
(config/authsources.php)
'IncludeCIEns' => true, //Se impostato aggiunge il namespace (globalmente)
To add the Extensions block I did this:
I declared these properties inside the contacts property on config/authsources.php
I marked these new properties as valid (so SAML would "pick them up") inside
lib/SimpleSAML/Utils/Config/Metadata.php
I read these values on
lib/SimpleSAML/Metadata/SAMLBuilder.php
(this is the addContact function)
I add the Extensions block and his children inside
vendor/simplesamlphp/saml2/src/SAML2/XML/md/ContactPerson.php
Quick edit: I'm working with simplesamlphp 1.18.8 from 2020-09-02
P.S.: I wanted to provide code, I resorted to screenshots because of stackoverflow, what a waste of time just to post an answer. It was always saying my code wasn't indented properly (even if it was...), couldn't post my answer like it was, I resorted to enclosing it in pre tags (because the code sample wasn't working), it wasn't enough for this fancy site, had to convert them to screenshot...
For instance in the Timber Documentation we have lots of examples like the following:
{% for item in menu.items %}
{{ post.author.name }}
Now the "item" and the "menu" etc. are all predefined, and nowhere defined by a user in the files (otherwise by my understanding Timber and TWIG would not make much sense).
What I do not understand is where I can find out a list these. In the Docs of Timber, there are a bunch of examples, then when I compare them to the Timber Starter Theme for Wordpress, I see a bunch of them, which aren't even mentioned in the documentations.
Where do I find a list of all available items?
What is the logic behind these items?
Don’t feel dumb, because you’re not! We’ve all been there. I had the same questions, when I started out with Timber. We’re trying to improve the documentation constantly, so questions like these help us to find out what we can do better 👍.
Whenever you see a variable in Twig, it can actually come from a couple of different places:
Variables from the global context
There’s a filter that most of us use to make a variable globally available whenever you set up your context through Timber::get_context(). When you see {% for item in menu.items %}, then it’s probably from the section of the docs about «Setting up a menu globally». I have to admit that we explain the filter through this example only, which is not ideal. But we’re changing this. In the next version of Timber, we try to explain the global context better (make sure to only read the section about the global context, because the part about «Template Contexts» describes functionality that is not available yet.)
Variables from the template
Consider the following example:
$context = Timber::get_context();
$context['post'] = new Timber\Post();
Timber::render( 'single.twig', $context );
Here you set up your context through Timber::get_context(). When you use Timber::get_context(), you’ll get a bunch of variables that make sense globally, but not for every template.
The $context variable is an array, holding all the variables you want to pass to your Twig template, in this case single.twig. When can add our own variables, like in the example above, where we add post that hold a Timber\Post object of the currently displayed post.
Variables from Timber’s classes
In the template, when you see {{ post.author.name }}, then author can be different things:
A property of the Timber\Post object that holds a value. These are all the variables that you’d see when you do {{ dump(post) }}.
A method of the Timber\Post object, that will be excecuted. This might be confusing at first, because in PHP, you always need to add braces to call a function, but in Twig, you don’t need to. When you call $post->author() in PHP, you would use post.author in Twig. To see a list of all the methods that are available for Timber\Post, you need to look into the Reference section for Timber\Post in the docs.
So if you would write the example {{ post.author.name }} in PHP, it would look like this:
$post->author()->name()
So author is a method of Timber\Post, which returns a Timber\User object. The Timber\User object has a method called name, which returns «the human-friendly name of the user».
But! When you just look at {{ post.author.name }}, it could also be a multi-dimensional array that you defined yourself:
$context['post'] = array(
'author' => array(
'name' => 'Tom Riddle',
),
);
You wouldn’t know that just from looking at it in Twig.
Variables from the Twig syntax
When you see {% for item in menu.items %}, then you’re looping over the variable menu.items. The variable menu probably comes from the global context (a Timber\Menu object), and items is a property of this object. The item variable is a new variable that is created to access the current loop item in the for loop. In this example, it’s the current menu item. You can choose any name for item you want.
Variables from includes
You can pass down a variable in Twig through the include statement. For example, if you defined post through your template file and wanted to use a different name in the template that you include, you could use it like this:
{% include 'teaser.twig' with { teaser: post } %}
Coming back to your specific questions:
Where do I find a list of all available items?
What is the logic behind these items?
I’m afraid there isn’t a definitive list, because what a variable is can be very dynamic. It’s mostly a combination of the global context, variables you set from the template, methods and properties from Timber’s classes as well as variables you define yourself in Twig.
If you have more question, add the to this answer as comments and I can update this answer accordingly.
I’ve been building an application with Kohana 3.3, and recently switched development from Coda 2 — a text editor — to PhpStorm 6 — an IDE.
PhpStorm 6 has been very handy in pointing out potential code smells; it prompted me to move from attaching data to views with the __set($key, $value) magic method to instead using the bind($key, $value) method.
Another thing that PhpStorm 6 is complaining about, is that I’m declaring fields dynamically.
I have subclassed Controller_Template, and I’m attaching my view to my template like this:
public function action_index() {
# Create the view
$view = View::factory('project/list');
# Attach the view to the template
$this->template->content = $view;
}
Apparently, content is declared dynamically. I’ve been checking up the class heirarchy, and I can't find the content property declared anywhere (hence why it’s dynamic, I suppose). Is this a code smell? Is dynamic declaration bad? Can I explicitly declare the content property somewhere?
As it is, the code works. I just want to understand why PhpStorm is giving me a notice, and whether or not I’m going about things the right way.
The advantage and disadvantage of PHP is dynamic typing. Its convenient in some cases, but irritating in another. You shown here irritating example. You know, that the $view is object which inherit from View (for example), so you know which functions you can use. If you don't mess anything, there will be View type object always.
Phpstorm don't have this information and thats why you see warning. He wants you also to be careful with this code but in this case you cannot do nothing. You cannot also cast $view to View like in Java:
$this->template->content = (View)$view; //impossible :(
$view and $this->template->content are dynamic typing variables and you cannot change it. Just take care to not assign another type to your variable and everything should work fine.
I wanted to add some info to the answer Kasyx is giving. Everything he says is correct but there is an alternative to set variables in kohana if you hate dynamic typing or like some clarity in what your views are doing. (Template is just another view ;) )
You can also set variables in views with the set() function (docs) eg:
$view->set('foo', 'my value');
Ok, the subject makes no sense so Ill try to better describe it here.
Zend Frame work in use here. And I have run into a problem passing variables to my views, well the views included into the "top.phtml" that make up the template. What I am trying to do is implement a breadcrumb concept. The bread crumb file is included into the top.phtml before the content view file. So the breadcrumb variable isn't defined as far as the breadcrumb file is concerned.
I can print_r my array of settings for the breadcrumbs within the controllers view, no problem so it is working I know that much, just anything above that view in particular in the order of things can't get the variable. So I guess what I am looking to have answered is is there a means off passing a variable to the overall scheme of things similar in concept to
$this->view->variable_name = blah;
where something as high as the top.phtml can pick it up for use?
You may be looking for Placeholders.
Example:
Setting a placeholder value from a controller:
$this->view->placeholder('some_placeholder_name')->set('blah');
Setting a placeholder value from a view
$this->placeholder('some_placeholder_name')->set('blah');
Retrieving the placeholder value in a view script or layout:
$value = $this->placeholder('some_placeholder_name');
Placeholder content is rendered towards the end of your application execution so the value set in your controller should be available in your top level top.phtml view script.
I think this will work:
$this->layout()->breadcrumbs = ...
And then print $this->layout()->breadcrumbs in your top.phtml.
Zend Layout
After sending hours trying to get placeholder() to work with partialLoop(), I finally gave up and hacked a fix to pass vars to a partial:
$vars = (array) $this->getVars();
foreach ($this->rows as $row) {
$partialVars = array(
'row' => $row,
'vars' => $vars,
);
echo $this->partial('row.phtml', $partialVars);
}
ugly, but it worked.
+1 for everyone for giving me a clue, however none of the above worked well in my favor. However between them all, they lead me towards finding my answer which is
Zend_Registry
In my Controller I built my array and passed it to Zend_Registry like
$breadArray = array(
array("icon"=>"i_robot", "href"=>"systems/"),
array("href"=>"metrics","text"=>"Metrics")
);
Zend_Registry::set('breaded_crumbs', $breadArray);
Then in my breadcrumb.phtml which is loaded before the content and view I used
print_r(Zend_Registry::get('breaded_crumbs'));
to see if it was working, and it gave me the array's so I for anyone in the future looking to extend a variable outside of the view itself, the registry seems to be the way to go. I tried placeholder and layout, both gave me errors about not being something or another, and when I got them to work in part I wasn't getting what I was expecting.
In PhpStorm, if I create an object, then I have all auto complete on that object working fine:
$object = new MyClass();
$object->getNa...
Will auto complete to
$object->getName();
So far so good, but if I get returned an object through the first method, then the auto complete will not work on that.
$car->getDriver()->getNam...
Will show an empty list.
The getDriver method has its PHPDoc #return tag set to 'Driver' though and in some other IDEs, this therefore works to get the correct auto complete.
Wondering if there's a setting that I missed somewhere or if PhpStorm doesn't offer this kind of advanced auto complete yet?
The function getDriver() needs appropriate type-hints for the return value (function's docblock):
* #return classOrInterfaceName
This is normally enough to have a IDE "go deeper". I'm pretty sure Phpstorm supports that, but I'm not a Phpstorm user.
Take care the file with the interface/class is within the project or referenced to it.
As a work around you can assign the return value to a variable and type-hint that variable. Might not be that comfortable but can help.
Please ensure that only one definition of class Driver exists across all your project files. This is crucial for current versions of PhpStorm
see http://youtrack.jetbrains.net/issue/WI-2202 and http://youtrack.jetbrains.net/issue/WI-2760