Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question about template variables #4

Closed
skyosev opened this issue Mar 5, 2015 · 5 comments
Closed

Question about template variables #4

skyosev opened this issue Mar 5, 2015 · 5 comments
Assignees
Labels

Comments

@skyosev
Copy link

skyosev commented Mar 5, 2015

Hi again!

I'm curious about the need to use $this->my_var while accessing data in templates. Is there any particular reason (performance, escaping etc.) for not using locally scoped variables like $my_var ? Plates does allow it AFAIK.

I didn't dig into Foil that much, so my question could sound improper.

Regards,
Stoyan

@gmazzap gmazzap self-assigned this Mar 5, 2015
@gmazzap
Copy link
Contributor

gmazzap commented Mar 5, 2015

Your question is not improper, and thanks again for your interest.

Reason are:

  • avoid notices when a variable is undefined. Inside a template, the usage of $my_var produces a notice if it not defined. $this->my_var doesn't. So a secure use of scoped var is:

    isset($my_var) ? $my_var : ''
    

    that is more typing than $this->my_var. Actually, the benefit of less typing in scoped var, just vanished.

  • Autoescape. Foil supports autoescape for variables. Sure it is not as powerful as it is in compiled languages (unless you use arraization), but I feel that something is better than nothing. More on the topic.

If you are intersted in a more in depth comparison with Plates features I did a blog post.

@gmazzap gmazzap closed this as completed Mar 5, 2015
@skyosev
Copy link
Author

skyosev commented Mar 5, 2015

I see. Thanks for your explanation.

While I agree with your points, I have some concerns about the 'On Plates data access' section.

Having worked countless hours with native php templates, I made the following observations:

  • variables in the templates are meant to be there, i.e. I had very few situations where I would use a variable that is not set and echo empty string instead. Most of the cases (well.. my cases) all of the variables are set through the controller (on traditional MVC architecture). I barely used isset control structures like your example above.
  • actually getting notices for undefined variables is sometimes useful. Especially in development mode, where you could just forget to assign a variable to the template or miswrite its name. Foil could benefit from a 'strict_variables' option, like Twig.

About autoescaping - I guess there is no difference for the end user between escaping a variable on demand, when accessing it from the template with $this->my_var, and escaping all of the variables that are passed to the render function, thus providing escaped scoped vars to the template. Do you see room for an option like 'use_scoped_variables', that would allow to access the template variables without 'this' ?

@gmazzap
Copy link
Contributor

gmazzap commented Mar 5, 2015

variables in the templates are meant to be there

I've worked countless hours with templates engines, not native php one, but in this regard there is no difference between native or compiled, and I encountered a lot of occasions where variables may be there or not, expecially when data comes from external sources, like API, file parsing...

Moreover, if you know that undefined variables equals empty string, you can use undefined variable by design.

Let's assume that by design a page may has or may not a subtitle. Page template in Plates will probably contain:

<?= isset($subtile) ? $subtile : '' ?>

or a more verbose if statement. In Foil you just <?= $this->subtile ?> obtaining same effect.

An alternative would be always assign subtile var to page, but in that case the control structure is moved from template code to data generation code (controller or whatever), that is sure better, but no need for it is even better IMO.

actually getting notices for undefined variables is sometimes useful

I'm pretty agree that 'strict_variables' would by a nice addition I'm going to add myself an issue for it.

I guess there is no difference for the end user between escaping a variable on demand...

Plates documentation itself encourages people to do $this->e('var_name').
You can do exactly the same in Foil, but you can also to $this->var_name (so less typing) when autoescape is turned on.

If we agree that unescaped output is bad (and I agree) Foil gives an easier access to escaped data while unescaped data must be accessed intentionally with $this->raw(). Plates does the countrary: unescaped data is easily accessed, while escaped data must be required. I feel this is bad and I can say recently even the Laravel Blade do the same thing moving from unescaped-by-default to escaped-by-default.

Do you see room for an option like 'use_scoped_variables'

Yes, I do. Generally speacking I write open source code for things that I like to have but I can't find. This means the default behavior of my code reflects my preferences. But I don't see reason why I have to force people on my preferences.
I have to say that option will destroy the autoescape thing. So I can allow it only if autoescape is off (there is already an option for that).
If you want to add this feature and do a PR it will be merged. If you have no time for that, add a specific issue, I'll handle it when I can. (for the name I feel we can make it less verbose as 'scoped_variables').

@skyosev
Copy link
Author

skyosev commented Mar 5, 2015

Thanks for the detailed explanation.

My experience with templates is 95% connected with html markup, that's why in my cases $subtitle would be wrapped by span (div, paragraph etc.) and I would use conditional structure to omit this markup regardless of how I access $subtitle. I see this is not valid for the cases you mention (API, file parsing), so I am biased here.

Another attempt to explain my view about autoescaping.

$engine->render('a-template', $template_variables_array);

Why can't the template engine just escape and then extract $template_variables_array before including the template file, so all of the $template_variables_array items would appear as escaped scoped variables in the template ? The original unescaped $template_variables_array can be kept in order to be able to access the raw variables with $this->raw('my_var');. Does this makes sense or I miss the point ?

I didn't mean to question your purposes for creating Foil, just discussing my views on the topic. I will think about a PR.

@gmazzap
Copy link
Contributor

gmazzap commented Mar 5, 2015

Why can't the template engine just escape and then extract $template_variables_array before including the template file, so all of the $template_variables_array items would appear as escaped scoped variables in the template

This is the biggest issue with autoescape in native PHP templates.

Variables passed to templates are not always strings. Strings can be easily escaped. Array can as well, by recursively parse them.

Problem are objects. While you can get object properties using get_object_vars() this fails if object implement __get() overloading method.

Example:

class Post {
    private $data;

    public function __construct(array $data) {
        $this->data = $data;
    }

    public function __get($var) {
        return isset($this->data[$var]) ? $this->data[$var] : '';
    }
}

$post = new Post(array('foo' => 'Bar'));
echo $post['foo'];   // echo 'Bar'

If the $post object is passed to templates, there is no way to autoescape post properties.

This problem does not exists for compiled template engines, because they first echo the value (in a sandboxed environment), then escape the echoed value.

The point of arraize Foil method is to convert all objects to array, so they don't suffer of this issue and can be easily autoescaped.

If the scoped_variable option is added to Foil, maybe, besides true / false values for it is possible to add support for "arraize" value: when used, if autoescape is true Foil passes template variable to arraize() before extract them...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants