XaminProject / handlebars.php

Handlebars processor for php
331 stars 134 forks source link

Args passed to helpers are a string? #142

Closed EGreg closed 8 years ago

EGreg commented 8 years ago

This is going back to the mismatch between EachHelper->execute expecting $args to be an array, but then it's actually a string, when passed from Template->_handlebarsStyleSection.

Therefore, all my handlers written in PHP are broken now. They are getting a string like this: "foo.bar" "baz" 5 instead of an array like this: array("foo.bar", "baz", 5)

is this intentional? In the tests each helper now calls this line before using the args: $parsedArgs = $template->parseArguments($arg);

but in the DocBlock you still have the vestigial type: array

everplays commented 8 years ago

@EGreg yeah, I can't remember exactly when* but we changed how helpers work. If you have upgraded from an early version, you need to use parseArguments.

* Check the history if you're interested.

EGreg commented 8 years ago

@everplays OK but parseArguments and parseNamedArguments doesn't seem to pick up literals like false or 1.2 on the right-hand side, only strings. How can I get it to parse the other values, like null which are available in javascript implementations, and use them like I was able to before?

everplays commented 8 years ago

@EGreg have you tried passing the result of those function to $context->get? Something like $context->get('false') should return what you're looking for.

EGreg commented 8 years ago

Yes, I tried of course. And it doesn't handle literals except strings. $context->get('false') returns null, for example. Try it.

I wrote a function that I call instead:

    /**
     * Call this in your helpers to parse the args into a useful array
     * @method parseArgs
     * @static
     * @param {Handlebars_Template} $template
     * @param {Handlebars_Context} $context
     * @param {string|array} $args
     * @return {array}
     */
    static function parseArgs($template, $context, $args)
    {
        if (is_array($args)) {
            return $args;
        }
        $parsed = array_merge(
            $template->parseArguments($args),
            $template->parseNamedArguments($args)
        );
        $results = array();
        foreach ($parsed as $k => $arg) {
            $result = $context->get($arg);
            if (!isset($result)) {
                $result = @json_decode($arg);
            }
            $results[$k] = $result;
        }
        return $results;
    }
everplays commented 8 years ago

@EGreg ok, glad that you figured it out.

One of the things that we wanted to work on but neither of us have found time to do is to parse and prepare all the parameters and pass it to helper. This way, regardless of what helper is going to do, all the parameters are ready to be used.

Please be my guest if you want to work on it.

EGreg commented 8 years ago

Well, I can submit a pull request, but at this point whoever is using the library would expect the helper to return $args as a string. If we go back to an array it would break for others just like it did for me. The Javascript implementation of helpers has a different convention, anyway. But I think if you want, you can use my function above and add it to the general Handlebars\Template class. It seems to be very convenient.

If the library wasn't already released, I'd say do $args = parseArgs($args) before sending them to the helper!

everplays commented 8 years ago

@EGreg right now, as you can see using helpers is not as convenient as JS implementation. Library should prepare the parameters and we can easily keep the backward compatibility by using reflection.

I am going to close this issue but if interested, what we talked about needs to be implemented.