views:

384

answers:

3

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?

A: 

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. :)

deceze
deceze, I find myself reading the CakePHP posts on SO just so I can find out something new. Happens every time you post. Thanks for the addt'l info, keep up the great work!
Travis Leleu
I'm actually learning a lot from the questions as well, it's a mutually beneficial relationship. :-3
deceze
A: 

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',
)
Matt Huggins
Thanks Matt, unfortunately I actually need the exact opposite of this.
nickf
Ahh, sorry. I misread the question.
Matt Huggins
+2  A: 

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()

nickf