Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Templating systems produce output based on a template and a set of data. PHP produces output based on imperative code that can do anything. While you can certainly adhere to your templates only consuming data (ie some kind of view model), it's actually awkward to do, as PHP files don't take parameters, so you need to use a convention of having your "template" files provide functions and call them, but functions are global so you now need to name them uniquely to avoid collisions. If templates are meant to be pluggable, this is much more difficult because you have two templates that are supposed to be interchangeable, with identifiers for calling them that are different[1]. There are a lot of properties of template systems that PHP does not actually have.

[1] It's so much worse than this... You can use some horrible hacks like undefining a well-known function that each template implements, but this would only work one level deep without also adding a mechanism for "calling" a template, and at that point you are making a template system on top of PHP.



> as PHP files don't take parameters

$_SERVER, $_POST, $_GET.

The rest is not the PHP3 I recognize to be honest, let alone the modern stuff. Remember include() literally just included the code right there, inline, so you could include in functions and gain the function's scope:

    function render($data) {
        switch ($data['foo']) {
            case 'bar': include('bar.inc'); break;
            case 'baz': include('baz.inc'); break;
        }
    }
That's your template router with all the template's data pre-loaded in the template's scope, be it ever so filthy.


All of those variables are global, there's no way to establish an interface between the caller and the callee without using functions. You could certainly have a shared understanding of what variables have been injected into a global, but this is awkward, and requires you to do cleanup after each template instantiation to avoid leaking values between templates, which can cause subtle bugs.

> Remember include() literally just included the code right there, inline, so you could include in functions and gain the function's scope:

I've talked about this approach elsewhere in thread, it is not nestable without building a way to "call" templates on top of require/include, and when you do that you'll need to undefined the render function to do it as well, which creates additional complexity. At that point, the original premise of just using raw PHP isn't very true, because you are now building a framework or templating system around it.

Also, you have to contend with the magic "render" function not being globally defined by something. It's messy.


> there's no way to establish an interface between the caller and the callee without using functions

Um. Can you give me an example to pad that out a bit?

> and requires you to do cleanup after each template instantiation to avoid leaking values between templates

In my render() example, isn't that "reaching the end of the function"? (Edit: Wait, you're only talking about the superglobals, right?)


> Um. Can you give me an example to pad that out a bit?

Your example of using a render() function is already an example of this. You can parameterize render() to provide data to the template from the caller without utilizing untyped globals, and without having to clean the globals up after the template has rendered.

> Wait, you're only talking about the superglobals, right?

Yes. Globals are globals. PHP's super global distinction isn't really relevant to whether you are tainting the execution environment when you pass data to a script.

The point is, as I elaborate elsewhere, PHP is very awkward to use as a proper templating system.


>functions are global so you now need to name them uniquely to avoid collisions

I hear this here, and elsewhere I hear that PHP has evolved into a decent language. Both can't be true.


The discussion thread here may underrepresent OOP PHP. Large software in PHP usually uses namespaces instead of declaring functions at the top-level scope. And most projects except for legacy ones lean towards objects and classes over plain functions.

Namespaces allow non-global functions without a wrapping class already, IIRC. Looking up though, there seem to be special cases (legacy behavior, making everything at the top level global) when using namespaced files with include() statemtents, if I read the docs correctly.

Dumping pure functions as static members into wrapper classes was not uncommon when I used PHP.

But primarily, a lot of code was heavy on dependency injection and inversion of control, Symfony being the leader of this coding style maybe.

TFA also seems to be about class-oriented programming, but not the heavy design-pattern style mentioned above.

The linked TUI CLI parser looks like a nice and lean PHP OOP example.


Function names are scoped to the current namespace. This means that for local closures it is usually better to define functions as variables

$closure = function(){};

instead of

function closure(){}


Its not true at all.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: