On 22/07/2016 08:31, Michael Vostrikov wrote:
sticking the escaping types after the output makes it hard to spot what's
going on with anything other than a simple variable. e.g. <?*
$this->renderView($thing->getViewName(), 'html'), 'js' ?>
In Twig escapers and filters are also written after a variable, and this is
not confusing for many users.
{{ render(thing.viewName, 'html') | escape('js') | somefilter }}
Sure, but in Twig, Smarty, etc filters aren't just a special syntax for
doing escaping, they're a fundamental part of the language. In essence,
they're just a different way of writing a function call, a bit like
Sara's pipe operator, which incidentally would allow this:
<?= render($thing->viewName, 'html') |> escape($$, 'js') |>
somefilter($$) ?>
Because it's not obviously part of the <?* operator, someone might think
the escape parameter can be used elsewhere: <?php echo
'<blink>oops</blink>', 'html' ?> Operators don't normally have a list of
arguments.
Just a default variable, nothing complicated.
If they write echo like this, they will notice 'oopshtml' and then correct
this contstruction.
Binary operators have 2 arguments (add($a, $b), escape($string, $context)),
'for' has 3 arguments.
Binary operators have a left-hand operand and a right-hand operand;
unary operators have an operand immediately before or immediately after
their symbol. You don't write +$a, $b you write $a + $b. The only
exception is the ternary decision operator, $a ? $b : $c, which still
doesn't use a comma.
Functions, on the other hand, have a name, and a pair of brackets. So
+($a, $b) looks a bit like a function call with a funky name; that would
give us <?*( $foo, 'html') ?>.
I can see your logic in defining it this way, it just doesn't look like
anything else in the language, and that's a bad thing for people using
it properly.
And this is the reason why I want it to be a call of function with constant
name. This is very clear - <?* $str, $context ?> turns into
some_escape_function($str, $context).
The more you compare it to a function call, the less I understand how it
gains over just defining a function e() and writing <?= e( $foo, 'html') ?>
What happens if you mistype the argument? <?* $foo, 'hmtl' ?> Or with the
current proposal's use of '|', what if you get that syntax wrong? <?* $foo,
'html || js' *?> <?* $foo, 'html, js' ?>
Exception: Unknown context 'hmtl'.
Exception: Unknown context ''.
Exception: Unknown context 'html, js'.
If the handlers for these contexts are not set, of course.
But if these are run-time errors, how is the clever syntax helping
people get it right here? If you can pass a variable as the escaping
method, define arbitrary escaping functions, etc, you can't even write a
strict static analyser.
if you're mentioning the whole function name, you can just call it already
<?*html= $foo ?>
Do you mean the function autoloading? What is the difference with not-fq
name 'PHPEscaper' then?) And how to use an escaper like [$this, 'html'] ?
You've merged two unrelated lines from my e-mail here, so I'm not sure
what your question is. By the first line, I meant that if you write
"<?[$this, 'html'] $foo ?>" you might as well just write "<?=
$this->html($foo) ?>". The syntax has gained you nothing but a minimum
version of PHP and some head-scratching from new users.
JS escape only; not sure if this should encode as JSON, or just a JS safe
string; maybe <?*json= $foo ?> as well / instead...
This looks unclear for me - why I cannot use json for strings and what if
my variable sometimes is an array, sometimes a string?
'foo' is valid JSON - there is much hot air about the difference between
a "JSON value", a "JSON document", etc, but long story short, it is
perfectly fine to say <?= json_encode('hello world') ?>
On the other hand, if I have an array and ask for it to be HTML-escaped,
nothing iterates the array for me, it will just print "Array". So if I
ask for it to be "JS-escaped", why should it magically produce a JSON
array? Not to mention the fact that PHP "arrays" cannot be losslessly
represented as either an object or an array in JS (they have both
arbitrary keys and well-defined order, JS makes you choose one or the
other).
The biggest use case for this is people who *aren't* using a framework
... so customising the definitions is going to be the exception, not the
rule
They can setup their escapers once, this is not a problem, but the problem
is e.g. default flags for html escaping.
Customization is required.
Customizability is required, yes, but it absolutely should not be
mandatory. If people are using a framework already, *they will already
have a method of doing this*. This feature is really only useful for
people who are relying on absolutely minimum framework code, who want
something to work "out of the box".
If I have to write "register_escape_handler(function($string,
$mode='html') { .... })" I might as well just write "function e($string,
$mode='html') { .... }". There's not even a question of autoloading,
because nothing is going to autoload the procedural code that runs
"register_escape_handler" anyway.
If we make it too flexible, we're basically inventing a new templating
language
We cannot forbid a customization, so any custom escaper is a kind of new
templating language.
The operator must be simple for use. If someone wants to create new
templating language in his application, let he create. It will be in
application, not in PHP.
I think we're in agreement here - simplicity is key. :)
The trick with the magic class name and namespace aliasing is neat, but
feels likely to confuse a lot of users
Yes, I have to agree. Maybe more better way is to make it similar to
set_error_handler() - not for context as it is in RFC, but for 'escape'
callable.
Personally, I think having a separate handler registered for each
context argument, like streams, makes more sense. I don't see the use
case for customising how contexts are combined, passing variable
contexts around, or anything else that is gained by one callback with
two parameters.
Again, focusing on simplicity:
<?php
set_escape_handler('html', 'htmlspecialchars');
set_escape_handler('json', 'json_encode');
?>
<?*html*json= $foo ?>
becomes:
<?php echo htmlspecialchars(json_encode($foo)); ?>
And, as I say, the common escape handlers should be defined by default,
just like a whole bunch of stream types are.
Regards,
--
Rowan Collins
[IMSoP]
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php