A "filter" is just a function - the difference is just global state indicating the current "default" function, which I think is a very bad idea.
Just alias function calls as closures: $html = function ($str) { return htmlspecialchars($str); }; // "default filter" $attr = function ($str) { ... } // "attribute filter" Then call them: <?= $html($foo) ?> <?= $attr($attr) ?> IMO, this is much clearer and simpler (and more flexible) than hiding a function name in global state. Incidentally, that's what Aura HTML does: https://github.com/auraphp/Aura.Html Rather than inventing a new concept (filters) why not leverage a well-known quantity like functions? If they could autoload, that would be a more explicit, natural and still pretty convenient way to accomplish the same thing. Hmm. Here's a thought. You can already mix use-statements, right? I mean, you can "use" either class/interface name or a namespace name. At the time when PHP encounters the use-statement, it doesn't actually decide what you imported, it just creates a file-wide alias for a name. That's why you can have a class and namespace with the same name and "use" them both with one use-statement. What if that worked for functions too? use MyNamespace\fun; fun(); // -> MyNamespace\fun() This makes it convenient to import and call namespaced functions. Okay, but to the real problem, autoloading functions... what if spl_autoload_register() was triggered for missing functions as well as for missing classes? I know, I know - BC break, but think about it... with Composer there's no problem? it'll just attempt to autoload "MyNamespace/fun.php" and give up. If you were to follow that naming convention, it would probably just work without any modifications at all. What's funny is that spl_autoload_register() documentation page doesn't in fact even say that it's for classes, hehehe ;-) Okay, so I'm only half serious - It would probably be cleaner to add a dedicated spl_autoload_func_register() or something? On Mon, Jun 20, 2016 at 6:07 PM, Larry Garfield <la...@garfieldtech.com> wrote: > On 06/20/2016 10:24 AM, Rasmus Schultz wrote: >>> >>> <ul> >>> <?php foreach ( $things as $thing ) { ?> >>> <li><a href="/things/<?= $thing['name'] ?>" onclick="show_popup('<?= >>> $thing['name'] ?>');"><?= $thing['name'] ?></a> >>> <?php } ?> >>> </ul> >>> >>> There are three different escape mechanism needed there; if there is a >>> shorthand for one, do you think it will be more likely or less that >>> people >>> will get the other two right? >> >> I have to agree with that - assigning special syntax to one kind of >> escape-function gives that function an elevated status, which could >> easily encourage neglect and oversight. >> >> I do wish that we had an obvious, consistently-named set of >> web-related escape/encode functions for use in plain PHP templates, >> like html(), attr(), js(), etc... having to type and read >> htmlspecialchars() and json_encode() while you're trying to visually >> parse a template is really inconvenient. >> >> That's all it is though, inconvenience. Nice to have, not must have. >> >> I'd be much more interested in a general solution to the problem of >> being unable to (or at least strongly demotivated from) using actual >> namespaced functions in this and many other cases - that's a missing >> feature and a more general problem, whereas in my opinion an operator >> or shorter function-names are just a work-around... >> >> (and please, nobody say "use a template engine" - I *am* using a >> template engine, it's called PHP!) > > > In many of the PHP template engines, there are multiple "filters" available > with a specific syntax, and a way to add more. You have to specify which > one you want, because only you know the context. > > Twig (and possibly others?) lets you set a default escaper that can be > overridden case by case as needed, including by a "none" option. > > Rather than try to make print statements themselves into a more secure > template layer (Sorry, Rasmus, that ship has long since sailed, even Drupal > gave up on PHPTemplate), perhaps it would be more useful to look at the > needs of the various template engines (Twig, Smarty, Blade, etc.) and see > what the language can/should do to make it easier for those engines to be > made secure. That same underlying tooling, then, can be exposed in a way > that those still using PHP itself as a template engine can leverage it more > easily. > > I'm not 100% certain what that would look like. My initial thought (which > is potentially a terrible idea), is some sort of callable registration, akin > to stream wrappers or autoloaders, where you could do something vaguely like > this: > > register_escaper('html', function($var) { return htmlentities($var, > ENT_QUOTES | ENT_HTML5); }); > register_escaper('html_attrib', function($var) { ... }); > register_escaper('raw', function($var) { return $var;}); > > set_default_escaper('html'); // I dislike a global flag like this, but it > works for this demonstration. > > <?php > print $foo; // no escaping, because BC. > printe $foo; // Run through html escaper > printe($foo, 'html_attrib'); // Run through html_attrib escaper > ?> > > <?= $foo; ?> // No escaping > <?~ $foo ?> // Run through html escaper > <?~html_attrib $foo ?> // Run through html_attrib escaper > > And then Twig, Smarty, etc. can also leverage the registered escapers, and > add their own as appropriate. > > That's off-the-cuff syntax that may be terrible, but the goal here is to > better enable template engines (whether thick ones like Twig or thin ones > like *.view.php) to do security better, rather than trying to Solve It For > All The Things(tm), which for security is a very dangerous dead-end > approach. > > --Larry Garfield > > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php > -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php