Closed literal closed 13 years ago
are you looking for...
{{ macros.blah([ 'key': 'value', ... ]) }}
?
Hashes are already supported:
{{ form.input(['name': 'foo', 'style': 'color: red']) }}
Um, sorry, my bad.
I didn't get that because it is not mentioned under "Literals" in "Twig for Template Designers". But I see now, that the [foo: bar]
syntax is used in two examples.
I probably missed that also because it was not what I expected. I saw "[...]", thought "all right, that's arrays, where are the hashes?". Arrays and hashes are different concepts and I see it as one of the fundamental design weaknesses of PHP not to make a clear distinction between them. (Just imagine how much easier those built-in PHP array_* functions could be if you didn't have to remember how they act on hashes and how on real arrays - or even worse, a mix of both).
So I think it's a pity that Twig mimics this PHP flaw. But I understand it's probably too late to change the syntax from [foo: bar]
to {foo: bar}
...
No, it's not too late. As Twig 1.0 is not released yet, we can still change things like that if that makes sense.
So, that's something we can still discuss. The reasoning behind the decision is to ease the learning curve for web designers who don't know any programming language. For them, it's better to have one unified construct like PHP has. On the other hand, supporting a more standard syntax like JSON can also make sense.
Well I disagree with the PHP-style "unified construct" being easier.
If you follow my basic statement that arrays and hases are different structures for different use cases, you might also see that there is a certain WTF-factor to arrays sometimes having explicit keys and sometimes not.
Arrays store an arbitrary number of similar things. You'd normally loop over the elements and not care for the keys. A non-programmer-Twig-user might not even be aware there are keys and fortunately doesn't have to.
Hashes/collections/dictionaries have named elements with different meanings. You'd normally access them directly by their keys. And if you loop, you'd actually use the keys in some way.
In my view it's not easy but instead confusing to have different concepts share the same notation.
And by the way all other programming languages I have used besides PHP either make a clear distinction between arrays and hashes (Python, Ruby, Javascript etc.) or have no native hash constructs (like Java were you use e.g. a java.util.HashMap object).
Another point:
The typical template desiner I have in mind (and which I have met many times) has had contact with one programming language: JavaScript. He/she might not have a concept of OOP, prototype based inheritance or even functions, but uses frameworks and other off-the-shelf stuff like TinyMCE . Mostly he/she copies and adapts examples from tutorials, forums etc. which requires a basic knowledge of JS syntax. Thus [foo, bar]
and {foo: bar, boom: baz}
are familiar.
Personally I think if it's a PHP template engine, then stick to the syntax provided by the underlying language?
Having worked on and with both sides of site creation - design and development - I would say any designer who is capable of writing javascript stands out above 90% of other designers as it is, and it shouldn't be too hard for them to understand that they just use [ square brackets ]
for server stuff, instead of { curly braces }
.
Of course, if support for curly was added while keeping square as it is then, whatever, I just don't think it would be wise to remove square bracket combined arrays + hashes since it's a staple of PHP (whether anyone thinks it's for better or for worse, it just is).
A quick suggestion: what about allowing both {} and [] in the parser? Which would mean that all the following expressions would be valid:
[foo, bar]
{foo, bar}
[foo: bar]
{foo: bar}
[foo: bar, bar]
{foo: bar, bar}
+1 for only allowing hashes which makes more sense even for a designer or frontender since they most likely already know some javascript.
I'm not sure I understand. You don't want support for "simple" arrays?
when i see [] i assume its like a array() with numeric keys and {} here keys have meaning if that makes sense :)
I do agree with supporting both the square and curly brackets syntaxes! I think it will be definitely a more flexible syntax because every developer can select its own conventions based on its preferences and habits.
Every "there is more than one way to do it"-descision also has negative aspects:
Let's assume the docs use one style in the examples and the alternative style is only mentioned in some more formal reference part or a footnote.
Now if some template designer who is not aware of the alternative syntax edits a Twig template that someone else wrote using the alternative style. What is s/he going to think? "Is it an error?", "What does it mean?". "Is {foo: bar} the same as [foo: bar] or is there a subtle difference?" (e.g. like between single an double quotes in PHP) It would make the template designer feel unsure about his/her understanding of Twig.
Only having one way to do something is valuable, and adding redundant ways of doing things, should be avoided unless there is going to be a deprecation over time imo. Either {}
or []
should work, but not both. The points that literal raised are very valid, confusion and documentation bloat are real concerns for me.
ok, we need to make a decision here. If I understand all arguments, we basically have two choices:
Which one do we want?
I prefer the first choice... By Changing we could break all the templates that we've already written... Furthermore I prefer a syntax closer to PHP, because we're using PHP and not JS...
I vote for the first choice. I have a question - Is possible to pass hash in hash? such as css have key 'color' and 'padding', value of 'padding' is hash with key 'top' and 'bottom'. {{ css(['color': 'blue', 'padding': ['top': 10px, 'bottom': 5px]]) }}
if we choose the second choice, it will be {{ css({'color': 'blue', 'padding': {'top': 10px, 'bottom': 5px}}) }}
I do not care if new syntax will break the old template that I've written. If it make good performance, easy for designer and clean code (easy to read).
Yes it should be possible to do that...
I votes for the [] as it is now to keep it simple and as immamino said we are using php anyways.
@henrikbjorn ... Lmammino :P
I'm for the [] construct. It's not confusing because PHP programmers know how arrays work in PHP and don't care how they work in other languages. And from my small 7 years experience with web development (3 of them with php) the programmer that writes the models and the controllers is also the one that writes the logic of the view. Small or large firms.. same stuff. And interface designers/developers only play around with html and javascript. Please stop thinking for those guys and think for the one that actually use this template engine and it's us the php programmers.
@Imammino hard to write on an iPad.
I think that switching to {}
would make the Twig templates look more like other templates, and provide some consistency with other languages like javascript, python, and ruby. I don't really but into the argument, that php developers will be confused by {}
. I don't think you can be a front end web developer and avoid Javascript, also you don't declare arrays in php with []
either. While I'm not happy about having to change all my existing templates when this feature comes, I think separating hashes and arrays makes sense even if PHP decided to conflate the two concepts.
But the underlying language is still PHP and not javascript and not python. If you want that kind of syntax why arent you all using Python? :)
But PHP doesn't use []
to construct arrays either. So its just as disconnected from the underlying language in either case.
But there is an RFC for adding the [] array shortcut into core.
Just one little thing, everyone mentions we're using php so [] makes more sense, which is not even true, but assuming it would be. What about using foo.bar? How is that close to PHP?
The template engine is written in PHP, but templates are not PHP. Much like PHP is written in C and yet we use classes and such, who cares about the underlying implementation's language. The fact is, using dot for properties/method access instead of concatenation makes the Twig syntax look almost 100% like JS already. Aside from the filter, if we changed to the second proposal ([] = array, {} = hash), Twig would look like JS, which imo is a big win for a typically frontend-oriented technology.
That being said, if we support {} for hashes, I think we need to revisit the syntax, atm I think Twig forces you to quote the keys, while JS does not take quotes, but JSON takes double quotes. I'd go for no quotes. Which means you can't define a hash with a variable key, unless we also allow stuff like {% set foo[var] = val %}
- I'm not sure if this is possible atm, but I don't think so?
@henrikbjorn: having an RFC doesn't mean it's gonna happen.
@Seldaek i know that having an RFC dosent mean it will happen. And i dont think i will.
+1 for [] - 1 for {}
If we are going to look at inconsistensies in the templating language also, we should look at the {% block %}
tag which takes one parameter that is not a quoted string.
Well, I think we should look at inconsistencies, and fix them before it's too late.
There should be a decision in here, this is a change that should be made asap. Later it will never be made, as "many programs rely on it" (call-time pass by reference is deprecated for decades, but it still isn't removed from PHP).
I definitely approve of the variant with different syntaxes for arrays and hashes. There are basically two reasons:
'foo'
and one index '0'
(yes this is not a numerical key!), but I can imagine that many others, especially frontend-developers, who have only worked with JavaScript, can not. It simply doesn't make sense to intermix arrays and hashes.[]
and {}
are well known to JavaScript developers (and many other people, as these are the typical modern syntaxes for arrays and hashes). From this it follows, that both a frontend-designer (who probably knows JavaScript) and the backend-programmer (who probably has worked with JavaScript at least some time earlier or knows JSON) know that syntax. The syntax ['foo': 'bar', 'bar']
on the other hand is unknown to either of them.After thinking about the issue for quite a long time now, and based on all the arguments from this thread, I have finally implemented the [] and {} syntax.
https://github.com/fabpot/Twig/commit/4505200d9f5481839738421eed0bde3ae546e0a7
Twig's datatype support looks strangely incomplete to me.
So far Twig supports literals for null, booleans, numbers, strings and (scalar/true) arrays.
While it is possible to access hashes (or associative arrays if you want to stick to the ugly PHP type system and terminology) as
foo.bar
orfoo[bar]
or through afor key, value in foo
loop, there is no way to create them.Now, why would one want hash literals? Mere symmetry (if you can use, you should also be able to create it) might not be strong enough a motive.
The real use in my view are hash arguments for calling filters, macros or methods of objects in the template context.
Look at this example from Twig documentation:
What if you also wanted to also allow for id, class, style, onmouseover, onmouseout etc.? The parameter signature of the macro would become excessive and you might end up with macro calls like this:
...and the input tag generator is only a very simplistic example. Think of macros/filters/methods for more complex HTML constructs.
The above example would be so much easier if one could do it like this:
Or think of another common use case, a macro/filter to dynamically create a query string for a link URL. If hash literals existed, it could be as easy as this:
[Note: The strange looking comments are necessary to avoid unwanted whitespace inside the result.]
... and it would be called like this:
I feel hash literals are a really essential feature and although my request comes in rather late I propose to schedule it for the 1.0 release.
I'd recommend JSON notation for hash literals as shown in the examples above. Array literals are written in JSON notation already (
[foo, bar, ...]
), and many template designers will be familiar with the{foo: bar, boom: baz, ... }
syntax from JavaScript.I haven't taken too deep a look into the Twig source code yet, but I assume it shouldn't be very hard to implement hash literals.