Comments (15)
@zordius my apologies. This comment I wrote is incorrect. The way this is working is consistent with the documentation.
My question now, is why does input work this way for helpers, but differently for hbhelpers? Why not have a consistent input methodology across both? I think both ways are valid, but it's just odd that they work differently.
from lightncandy.
Ya, in my original design, the helpers interface is different with handlebars' style. Because:
- In handlebars.js, one registerHelper() handles both 'single helper' and 'block helper' .
- In handlebars.js, custom helper function need to take care of different input parameter numbers , and take care of last parameter (options) . It also need to take care of 'calling inner block renderer' .
- The most important thing: there is no standard way for custom helper function to know it is be used as 'single custom helper' or as 'block custom helper' (My little trick is to check options.fn ....if it is there, then the custom helper is be executed as block custom helper)
So, I don't like the way of handlebars.js do it and decide to make something different. My idea is: let lightncandy handle inputs, and let custom helper in easy life.....So, I designed helpers and blockhelpers in another way.
If I am writing a custom helper: test
, the helpers
way can give me all inputs in one time no matter it is named argument or not. In handlebars.js , I need to get none named arguments from 1st to n-1 arguments, and all named input from last arguments.hash. Then, I may need to put similar statements in all my custom helper functions to handle these:
function test () { // do not declare any params here, then I can handle Variable-length argument lists
$arg_list = func_get_args(); // in javascript it is arguments
$options = array_pop($arg_list); // in javascript options = arguments.pop();
$all_named_args = $options['hash'];
$all_nonamed_args = $arg_list;
if (isset($options['fn'])) {
// Do block custom helper things ....
} else {
// Do custom helper things ....
}
}
And then, support handlebars' style is another story happened later.......the target of hbhelpers is to simulate handlebars.js behaviors , even when I still think it is not good. That's why helpers
is different with hbhelpers
.
helpers
: If you do not care about "the interface should be same with handlebars.js" , and you think the input of custom helpers should be simple , you should use this.hbhelpers
: If you use handlebars.js, and you like to port your old custom helper javascript to PHP, you can use this to reduce code conversion issues.blockhelpers
: it only let custom helper to change context or skip the block. I do the design in this way and try to make people think about: prevent to do too many things in custom helper, you maybe put too many logic in template......it should be logicless. But, if you do not think so, you can still usehbhelpers
to do heavy works in block custom helper.
from lightncandy.
I found a bad thing in my helpers design....
- If people always use {{test a b c}} , then I can use test($a, $b, $c) .
- If someone use {{test a b name=c}} , then I will change to use test($input) and $input will be Array(0=>a , 1=>b , name=>c) .
This still make custom helper code not consist in one way. Current design is only good for:
- A: people always {{test a b c}} and function test ($a, $b, $c)
- B: people always {{test a=0 b=2 c=3) and function test ($input)
If someone mix usage A and B, then he will run into trouble. I will think about this and find a better way to prevent the problem. Any suggestion?
from lightncandy.
If I had to choose, I would prefer the mechanism that is in place for hbhelpers to be applied uniformly.
So, you can use {{test a a="1" b="1"}} and:
- "a" will be the "a" value from the context
- $options will implicitly always be the last argument
- $options contains a hash of "a" and "b" parameters
$helper = function ($a, $options) {
echo $a;
print_r($options['hash']);
};
this reduces the amount of effort inside each helper to organize/gather the input because it is neat and tidy. I think the ability to mix the two styles together is very powerful, and certainly superior to the other PHP handlebars implementations.
Ultimately, it is up to you. Ultimately, I'd don't see too much distinction between helpers and hbhelpers. I think that the user could use a hbhelper in a simple way, or they can take advantage of more complex capabilities of it. If the user uses a hbhelper as a helper, there is no harm
from lightncandy.
The problem is, if you create a helper as
$helper = function ($a, $options) {
echo $a;
print_r($options['hash']);
};
Then all helper user should apply 1 none named argument like:
- {{helper "test" a=b c=d}}
- {{helper a}}
- {{helper a.b c="xxx"}}
If any template write in this way:
- {{helper a b}} (options will be 3rd param)
- {{helper a=b c=d}} (options will be 1st param)
Then the helper function will boooooooooom. That's the problem I talk about: when the number of input parameters is not consist , the helper function can not work correctly. This happened in both hbhelpers
and helpers
.
If I change the design of helpers
to 'always use hash format' , then all helpers
developer can use this style:
helper = function ($hash) {
// $hash[0] or $hash['name'] ....use isset() to check.
}
Hmm, still not good enough............Maybe in this way:
helper = function ($params) {
// $params = Array('named' => {...} , 'no_named' => [...] )
}
Then the number of params can be get by count($params['no_named'])
.....I feel this is better then original helpers
design, maybe I will add a option flag for this.
from lightncandy.
How about this:
// {{my_helper 1 2 3 a="4" b="5" c="6"}}
function my_helper($args, $options) {
// $args = array(1,2,3);
// $options = array("a"=>4, "$b"=>5, "c"=>6);
}
Then we can just check for empty($args)
to see if no arguments provided. And we got a nice $options
array containing the named params.
from lightncandy.
good approach!
from lightncandy.
I like this approach as well.
Would it be same / similar for both helpers, hbhelpers and blockhelpers?
from lightncandy.
I think it would be a good idea to make it consistent, it would avoid bugs and confusion. Everything should have the same API so we can just use it whilst feeling intuitive.
One thing I didn't think was about the $options['fn']
and $options['inverse']
block callbacks. Should these be included in the $options
array, reserving properties such as inverse
and fn
? No. Passing a third $block
parameter which contains the block callbacks would make more sense.
Something like this:
function my_helper($args, $options, $block) {
// $args = array(1,2,3);
// $options = array("a"=>4, "$b"=>5, "c"=>6);
// $block = array("fn"=>function, "inverse"=>function);
}
Three arguments is manageable, after that it becomes a hassle to remember. Also the order of the arguments is easy to remember. This would also have the added benefit of getting rid of the helpers separation, instead of having helpers, hbhelpers and blockhelpers, we would just have a common helper concept, which would simplify internals a lot.
Also, how would we know if it's a block helper? Easy as cake:
function my_helper($args, $options, $block) {
if (isset($block)) {
// It's a block helper
} else {
// Not a block helper
}
}
If helper is called as a normal helper, like {{myhelper 1 2 3}}
, then $block
would be set to null
, thus infering that there's no block. Semantic win.
If there's a block, like {{#myhelper 1 2 3}}...{{/myhelper}}
, then $block
would be an array populated with fn
and optionally inverse
. The latter being only specified if there's an {{else}}
block, null
otherwise.
Bacon!
from lightncandy.
I 100% support this comment. I really didn't see the benefit of differentiating between types of helpers.
Also, I would add that I don't think its necessary to implement this w/ a config flag, that in-general, helper support is so new in Lightncandy that breaking backwards compatibility is not a big deal IMHO.
@zordius when can you do this? ;)
from lightncandy.
@zordius any update? I'm migrating many helpers to this platform at the moment
from lightncandy.
I like new design and will do it on helpers
, but can not decide to use it or not on hbhelper
<= (it's supposed to be same with handlebars ) . More inputs are welcome, I will go helpers
first today.
from lightncandy.
New testing version and document in this branch: https://github.com/zordius/lightncandy/tree/helper_interface_change
, please try it, thanks. ( helpers and blockhelpers are changed now , hbhelper still not be changed )
from lightncandy.
Thanks for the implementation
from lightncandy.
#58 already merged into master, so close this, thanks.
from lightncandy.
Related Issues (20)
- Tests still pass even if phpunit fails HOT 1
- Size in README.md out of date HOT 5
- Render-time partials cannot access @partial-block.
- Class instance method as helper function
- Array value passed to helper as null within #each HOT 2
- Raw block working until the end of template
- Possible to access parsed variables?
- Valid use for Lightncandy::prepare() HOT 6
- Nested Helpers Unavailable When Rendered
- The problem in PHP8 HOT 7
- Bad indentation in case of nested partials
- Different behaviour than Javascript when modifying context in helper HOT 1
- Hi...broken forum link
- Opencart 1.5.6 Integration
- SafeString fails with FLAG_EXTHELPER | FLAG_BESTPERFORMANCE
- Custom condition helper over payload array with conditions
- Subexpression with a string where zero spaces occur before parenthesis breaks Parser
- Custom Block Helper with blockParams
- PHP Warning: Undefined array key when trying to access unavailable key from parent context
- Possible bug with `$context['flags']['debug']`? HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from lightncandy.