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. :-)
精彩评论