开发者

CakePHP function to convert dotted arrays to multidimensional

In CakePHP, it seems like a lot of functions can开发者_如何学编程 take their arguments as nested, multidimensional arrays, or as dotted strings:

$this->MyModel->contain(array(
    'Something', 'Something.Else', 'Something.Else.Entirely'
));
$this->MyModel->contain(array(
    'Something' => array(
        'Else' => 'Entirely'
    )
));

Therefore, I figure there must be a function somewhere in the core to switch from dotted to nested associative, but I can't find it for the life of me. Any ideas?


I've actually figured my own way to get this working leveraging the built-in Set functions.

Given:

$input = array (
    'Post.id' => 1,
    'Post.title' => 'Some post title.',
    'Post.Tag.0.id' => 4,
    'Post.Tag.0.name' => 'cakephp',
    'Post.Tag.1.id' => 7,
    'Post.Tag.1.name' => 'mysql',
);

This code will put that into a nested associative array.

$output = array();
foreach ($input as $key => $value) {
    $output = Set::insert($output, $key, $value);
}

Here's the docs for Set::insert()


What you're looking for is Set::flatten(). It's not documented in the CakePHP manual, but take a look at the API definition.

It works something like this (the result might not be exact, this is from my head):

$array = array(
    'Post' => array(
        'id' => 1,
        'title' => 'Some post title.',
        'Tag' => array(
            0 => array(
                'id' => 4,
                'name' => 'cakephp',
            ),
            1 => array(
                'id' => 7,
                'name' => 'mysql',
            ),
        ),
    );
);

$array = Set::flatten($array);
var_dump($array);

Your $array variable will now look like this:

Array (
    'Post.id' => 1,
    'Post.title' => 'Some post title.',
    'Post.Tag.0.id' => 4,
    'Post.Tag.0.name' => 'cakephp',
    'Post.Tag.1.id' => 7,
    'Post.Tag.1.name' => 'mysql',
)


It's just a convention throughout Cake, but each part does its own, customized parsing. If you look at the function ContainableBehavior::containments() in cake/libs/model/behaviors/containable.php, you'll see a lot of preg_matching and explode('.')ing going on. At least in the case of Containable, the verbose array('name' => array(...)) syntax seems to be the canonical syntax, but it can be abbreviated with the dot syntax, which will just be expanded. I'd guess that the expanding itself is just too varied among different parts to be easily summarized in a central function.

That, or they just haven't gotten to it yet. :)


Great question, I was just searching for the same thing. Apparently it's coming in Cake 2.2.

The new Hash class (a new, improved version of the Set class) has an expand() function which does this. You can view the code on Github if you need to use it in the meantime:

https://github.com/cakephp/cakephp/blob/2.2/lib/Cake/Utility/Hash.php

...However the solution nickf posted works great, too. :-)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜