A quick tutorial on CakePHP Set class (Part 1)

March 4, 2008 – 12:56 am
Table of Content [Hide]

Test data

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
$data = array( 
    1 => array('Post' => array( 
            'id' => 1, 'post_comment_count' => 2, 
            'name' => 'My first title', 'body' => 'My first body' 
        ), 
        'PostComment' => array( 
            array( 
                'id' => 1, 'post_id' => 1, 'is_active' => 1, 
                'name' => 'My first comment', 'body' => 'My first comment'), 
            array( 
                'id' => 2, 'post_id' => 2, 'is_active' => 1, 
                'name' => 'My second comment', 'body' => 'My second comment'), 
            array( 
                'id' => 3, 'post_id' => 2, 'is_active' => 1, 
                'name' => 'My third comment', 'body' => 'My third comment') 
        ) 
    ), 
    2 => array('Post' => array( 
            'id' => 2, 'post_comment_count' => 1, 
            'name' => 'My second title', 'body' => 'My second title' 
        ), 
        'PostComment' => array( 
            array( 
                'id' => 4, 'post_id' => 2, 'is_active' => 
                1, 'name' => 'My fourth comment', 'body' => 'My fourth comment' 
            ) 
        ) 
    ), 
    3 => array('Post' => array( 
            'id' => 3, 'post_comment_count' => 0, 
            'name' => 'My third title', 'body' => 'My third title' 
        ), 
        'PostComment' => array(                   
 
        ) 
    ) 
);                   
 
$dataExtra = array( 
    4 => array('Post' => array( 
            'id' => 4, 'post_comment_count' => 1, 
            'name' => 'My fourth title', 'body' => 'My fourth title' 
        ), 
        'PostComment' => array( 
            array( 
                'id' => 5, 'post_id' => 4, 'is_active' => 1, 
                'name' => 'My fifth comment', 'bdoy' => 'My fifth comment' 
            ) 
        ) 
    ) 
);

Set::merge

PHP doc blcok

This function can be thought of as a hybrid between PHP's array_merge and 
array_merge_recursive. The difference to the two is that if an array key 
contains another array then the function behaves recursive (unlike array_merge) 
but does not do if for keys containing strings (unlike array_merge_recursive). 
See the unit test for more information.         

Note: This function will work with an unlimited amount of arguments and 
typecasts non-array parameters into arrays.

A bit like array_merge_recursive. Merge joins two arrays on their keys.
If we want to add the $extraData array into the $dat most people would probably think, hey, lets merge them using Set::merge… but.. no, dont, unless you know what your doing.

1
pr(Set::merge($data, $dataExtra));

The above cod will only produce the ‘expected’(?) result because I have added the numeric key 4 in the $extraData array (Line 40). If I had, as I did the first time around, just let php auto-increment the keys for me, both $datad and $extraData would contain the numeric index key 0, and since Set::merge works on keys, $extraData’s Fourth post would overwrite $data’s First post where they had anything in common (id, name, post_comment_count, body and everything in the first PostComment (My first comment)).

In case I had let php handle the index keys, I would have to use Set::insert to append the fourth comment to the list.

A better use of Set::merge is in CAKE/libs/model/model.php where is automagic merges ‘actsAs’ from your current model (PostComment) and your AppModel, so you automagic inherit the global behaviors from AppModel:

384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
// model.php 
if (is_subclass_of($this, 'AppModel')) { 
    $appVars = get_class_vars('AppModel'); 
    $merge = array();             
 
    if ($this->actsAs !== null || $this->actsAs !== false) { 
        $merge[] = 'actsAs'; 
    }             
 
    foreach ($merge as $var) { 
        if (isset($appVars[$var]) && !empty($appVars[$var]) && is_array($this->{$var})) { 
            $this->{$var} = Set::merge($appVars[$var], $this->{$var}); 
        } 
    } 
}

A funny thing is that Set::merge is still rarely used in the core code yet. Probably because array_merge (or am()) is faster for simple operations like just merging two simple 1 level arrays like a config array.

Set::filter

PHP doc blcok

Filters empty elements out of a route array, excluding '0'.

This method is not recursive. So doing

1
2
< ?php 
pr(Set::filter($data, true));

wont change anything in the array sinc no elements in first level is empty.



1
2
3
4
5
6
7
8
9
pr(Set::filter($data[3], true));      
 
array('Post' => array( 
    'id' => 3, 
    'post_comment_count' => 0, 
    'name' => 'My third title', 
    'body' => 'My third title' 
    ) 
);

We will notice that the PostComment array is gone, since its empty

Set::pushDiff

PHP doc blcok

Pushes the differences in $array2 onto the end of $array

That sounds simple enough, and it really is.

1
pr(Set::pushDiff($data, $dataExtra));

just pushes the $dataExtra on the end of $data, since they have nothing in common. Again, this method operates on the array keys when comparing arrays.

Set::map

PHP doc block

Maps the contents of the Set object to an object hierarchy. 
Maintains numeric keys as arrays of objects

That sounds very fancy, and it is! A lot of people migrating to CakePHP from Symfony (PHPDoctrine, Propel) will probably be confused at first that all model data in CakePHP is arrays, and not objects like other frameworks. This method attemps to 'fix' this issue by converting a model data array to a set of objects (StdClass). StdClass is a build-in dummy class in PHP, and it doesnt really do anything but contain data, no methods or fancy magic there.

1
2
3
4
5
6
7
8
9
< ?php 
// Convert to objects 
$map = Set::map($data); 
// id of first post (Object style) 
echo $map[0]->id; 
// name of first comment to first post (Object style) 
echo $map[0]->PostComment[0]->name; 
// name of first comment to first post (array style) 
echo $map[0]['PostComment'][0]['name']; // WONT WORK, Cannot access StdClass as an array

As you can see above, its important to decide what method you want to use, Object or Array style, since they cannot be mixed.
Also, the return from Set::map is a mix of arrays and StdClass, thats why I can access $map[0] as array, but not access $map[0]['name'].

Set::numeric

PHP doc blcok

Checks to see if all the values in the array are numeric

Not much to say on this one, because it doesnt do more or less than the name implies.

1
2
3
4
5
6
7
8
// false 
var_dump(Set::numeric($data)); 
// false 
var_dump(Set::numeric($data[1])); 
// false 
var_dump(Set::numeric($data[1]['PostComment'])); 
// true 
var_dump(Set::numeric(array(1,2,3)));

-------

Thats it for now, next time I will look at:

Set::enum, Set::format, Set::extract, Set::insert, Set::remove, Set::check, Set::diff, Set::isEqual, Set::contains, Set::countDim, Set::normalize, Set::combine and Set::reverse.

Look forward to it

Tags: , ,

  1. 6 Responses to “A quick tutorial on CakePHP Set class (Part 1)”

  2. Great, thanks for doing this! Looking forward to seeing the rest of the functions explained too.

    By Sean on Mar 4, 2008

  3. Great Stuff I look forward to the next piece thx

    By Sam S on Jul 17, 2008

  4. Thank you very much for the useful blog posts. One little detail I thought I’d point out is that the example code here seems to have > encoded as > but there’s a space before the ; and so it’s not displaying as > but rather as &gt ; which makes copy and paste pretty much impossible. Not really a big deal, as I’m just using this information to learn from, but it would be easier to read if these characters were displayed as intended. :)

    By Silver Knight on Jun 6, 2009

  5. I’m new to cakePHP, I would like to build a facebook application with cakePHP framework. Is this the best option available to build facebook Apps for Pages?

    By Sandy Gordon on Sep 23, 2010

  6. Nice, but in the code snippet I don’t see the arrows but the html codings (e.g. & gt; )

    By marco on Oct 2, 2010

  1. 1 Trackback(s)

  2. Mar 23, 2008: playing with nested array (i hate it) at Stay hungry, Stay foolish

Post a Comment