上QQ阅读APP看书,第一时间看更新
Using Yii core collections
Yii has a set of collection classes used mainly for internal purposes which are not described in the Definitive Guide, but are still very useful for applications:
- Lists:
CList
,CTypedList
- Maps:
CMap
,CAttributeCollection
- Queue:
CQueue
- Stack:
CStack
How to do it…
All collections implement SPL IteratorAggregate
, Traversable
, and Countable
. Lists and maps also implement SPL ArrayAccess
. It allows using collections like a standard PHP construct. The following is a snippet from the CList
API:
- The following is the snippet from
CList
API:// append at the end $list[]=$item; // $index must be between 0 and $list->Count $list[$index]=$item; // remove the item at $index unset($list[$index]); // if the list has an item at $index if(isset($list[$index])) // traverse each item in the list foreach($list as $index=>$item) // returns the number of items in the list $n=count($list);
CList
is an integer-indexed collection. Compared to the native PHP array, it adds stricter checks, can be used in OO fashion, and allows to make a collection read-only:$list = new CList(); $list->add('python'); $list->add('php'); $list->add('java') if($list->contains('php')) $list->remove('java'); $anotherList = new CList(array('python', 'ruby')); $list->mergeWith($anotherList); $list->setReadOnly(true); print_r($list->toArray());
- There is another list collection named
CTypedList
that ensures that the list contains only items of a certain type:$typedList = new CTypedList('Post'); $typedList->add(new Post()); $typedList->add(new Comment());
As we are trying to add a comment to a posts list, the preceding code will give you the following exception:
CTypedList<Post> can only hold objects of Post class.
CMap
allows using every value, integer or not, as a key. Just like inCList
, it can also be used in the native PHP style, has almost the same set of OO-methods, and allows making a collection read only:$map = new CMap(); $map->add('php', array('facebook', 'wikipedia', 'wordpress', 'drupal')); $map->add('ruby', array('basecamp', 'twitter')); print_r($map->getKeys());
- There is also one handy static method named
CMap::mergeArray
that can be used to recursively merge two associative arrays while replacing scalar values:$apps1 = array( 'apps' => array( 'task tracking', 'bug tracking', ), 'is_new' => false ); $apps2 = array( 'apps' => array( 'blog', 'task tracking', ), 'todo' => array( 'buy milk', ), 'is_new' => true ); $apps = CMap::mergeArray($apps1, $apps2); CVarDumper::dump($apps, 10, true);
The result of the preceding code is as follows:
array ( 'apps' => array ( '0' => 'task tracking' '1' => 'bug tracking' '2' => 'blog' '3' => 'task tracking' ) 'is_new' => true 'todo' => array ( '0' => 'buy milk' ) )
CAttributeCollection
includes allCMap
functionality and can work with data just like properties:$col = new CAttributeCollection(); // $col->add('name','Alexander'); $col->name='Alexander'; // echo $col->itemAt('name'); echo $col->name;
CQueue
andCStack
implement a queue and a stack respectively. A stack works as LIFO: last in, first out, and the queue is FIFO: first in, first out. Same as list and map collections these can be used in native PHP style and have OO style methods:$queue = new CQueue(); // add some tasks $queue->enqueue(new Task('buy milk')); $queue->enqueue(new Task('feed a cat')); $queue->enqueue(new Task('write yii cookbook')); // complete a task (remove from queue and return it) echo 'Done with '.$queue->dequeue(); echo count($queue).' items left.'; // return next item without removing it echo 'Next one is '.$queue->peek(); foreach($queue as $task) print_r($task); $garage = new CStack(); // getting some cars into the garage $garage->push(new Car('Ferrari')); $garage->push(new Car('Porsche')); $garage->push(new Car('Kamaz')); // Ferrari and Porsche can't get out // since there is… echo $garage->peek(); // Kamaz! // we need to get Kamaz out first $garage->pop(); $porsche = $garage->pop(); $porsche->drive();