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

I make heavy use of a similar thing in PHP. I have a function "lookup" which lets me say:

    lookup($foo, array('bar', 'baz' 15, 'quux'))
This is equivalent to any of the following:

    $foo->bar->baz[15]->quux
    $foo->bar->baz[15]['quux']
    $foo->bar['baz'][15]->quux
    $foo->bar['baz'][15]['quux']
    $foo['bar']->baz[15->quux
    ... and so on
It's useful in Drupal when the required data is often at the end of a long chain of objects-containing-arrays-containing-objects-....

I've been a bit naughty with its types for the sake of convenience: if a non-array is given as the second argument, it's wrapped as a singleton array, ie.

    lookup(array('foo' => 'bar'), 'foo') === 'bar'
Also if any of the components aren't found, it returns NULL, ie.

    lookup(array('foo' => NULL), 'foo') === lookup(array(), 'foo')
It would be theoretically better to return an empty array on error and a singleton array on success, since they can be distinguished, but in practice that's so far down the list of problems with PHP that it's not worth the effort of adding such wrappers at the moment.

A really nice thing about this function is that it curries nicely:

    $find_in_foo = partially_apply('lookup', $foo)

    $get_blah = partially_apply(flip('lookup'), 'blah')

    $find_in_foo('x') === lookup($foo, 'x')

    $get_blah($foo) === lookup($foo, 'blah')
Actually, my argument-flipping function is already curried, so I can just say:

    $get_blah = flip('lookup', $foo)
This currying is great for filtering, mapping, etc.


Hi, Drupal dev here. Got to the point yesterday afternoon where I'm going to have to implement exactly what you've already done in order to put out some reasonable JSON from a node_load_multiple call. Don't suppose you have this function in a gist anywhere, do you? Please?


Here's the definition and a few tests.

https://gist.github.com/Warbo/9d8425fcdd7c026c795a

The SimpleTest test class probably doesn't work as-is, since it is originally derived from our own class hierarchy, but shouldn't be too hard to fix.


Convenience-wise, you could also make a "varargs" version with `func_get_args()`, e.g:

    f($structure, 'bar','baz', 15, 'quux');


Which version of Drupal? D7 has https://api.drupal.org/api/drupal/includes%21common.inc/func... which does exactly that.


Indeed I haven't seen that before. Still, it doesn't support objects like mine does :)


Another implementation of this pattern is available as a component from the Symfony2 ecosystem[1]. It is flexible, well-tested, and can be easily used standalone either from Github[2] or through composer[3]

[1] http://symfony.com/doc/current/components/property_access/in...

[2] https://github.com/symfony/PropertyAccess

[3] https://packagist.org/packages/symfony/property-access


Have you seen guzzle's implementation of this? It's pretty useful and something I'd love to see split out of guzzle and made its own library.

https://github.com/guzzle/guzzle/blob/master/src/functions.p... is the actual code, although it's pulled into the guzzle collection: https://github.com/guzzle/guzzle/blob/master/src/Collection....


That smells to me: the path argument given to "get_path" is a string of components, separated by "/". The first thing get_path does is split the path apart at "/".

Why doesn't it just take an array? That way, it would be a simple reduction:

    function get_path($data, $path) {
      return array_reduce(
        $path,
        function($result, $index) {
          return (is_array($result) && isset($result[$index]))? $result[$index] : NULL;
        },
        $data);
    }
Unfortunately PHP's function namespace is separate from its value namespace. We can't define "get_path" using a couple of combinators :(

Also, requiring 'strings without slashes' is a pretty bad idea in PHP in particular, since it's meant for Web programming. This means a) we tend to have / in strings due to URLs and b) someone will inevitably pass user input as one of these components, which would allow a very limited form of code injection attack.




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

Search: