Skip to content

Commit

Permalink
Added identity map for Yii
Browse files Browse the repository at this point in the history
  • Loading branch information
phpnode committed Sep 20, 2011
1 parent 2648b09 commit 64ebf0e
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 0 deletions.
72 changes: 72 additions & 0 deletions identitymap/AActiveRecord.php
@@ -0,0 +1,72 @@
<?php

abstract class AActiveRecord extends CActiveRecord {
/**
* The identity map
* @var AIdentityMap
*/
private $_identityMap;

/**
* Creates an active record with the given attributes.
* This method is internally used by the find methods.
* @param array $attributes attribute values (column name=>column value)
* @param boolean $callAfterFind whether to call {@link afterFind} after the record is populated.
* This parameter is added in version 1.0.3.
* @return CActiveRecord the newly created active record. The class of the object is the same as the model class.
* Null is returned if the input data is false.
*/
public function populateRecord($attributes,$callAfterFind=true)
{
if($attributes!==false)
{
$identityMap = $this->getIdentityMap();
if (!$identityMap->enabled) {
return parent::populateRecord($attributes,$callAfterFind);
}
$pk = $this->getMetaData()->tableSchema->primaryKey;
$key = $identityMap->getKey($pk, $attributes);

if (!$identityMap->contains($key)) {
$identityMap->add($key, parent::populateRecord($attributes,$callAfterFind));
}
else {
Yii::log("Loading ".get_class($identityMap->itemAt($key))."#$key from identity map");
}
return $identityMap->itemAt($key);
}
else
return null;
}

/**
* Gets the identity map for this model class
* @return AIdentityMap the identity map
*/
public function getIdentityMap() {
$class = get_class($this);
if ($this !== $class::model()) {
return $class::model()->getIdentityMap();
}
if ($this->_identityMap === null) {
$this->_identityMap = new AIdentityMap;
}
return $this->_identityMap;
}
/**
* Sets the identity map for this model class
* @param AIdentityMap|array $identityMap the identity map
*/
public function setIdentityMap($identityMap) {
$class = get_class($this);
if ($this !== $class::model()) {
return $class::model()->setIdentityMap($identityMap);
}
if (!($identityMap instanceof AIdentityMap)) {
$identityMap = new AIdentityMap($identityMap);
}
$this->_identityMap = $identityMap;
}


}
41 changes: 41 additions & 0 deletions identitymap/AIdentityMap.php
@@ -0,0 +1,41 @@
<?php
/**
* Ensures that each model gets loaded only once by keeping every loaded model in a map.
*
* @author Charles Pick
* @package packages.identityMap
*/
class AIdentityMap extends CTypedMap {
/**
* Constructor, sets the type for the map
*/
public function __construct() {
parent::__construct("CActiveRecord");
}

/**
* Whether the map is enabled or not
* @var boolean
*/
public $enabled = true;
/**
* Gets a key to use to store models with the given attributes
* @param string|array $pk the name of the primary key attribute(s)
* @param array $attributes the attributes that contain the keys
* @return string the key key to use when storing and retrieving models with these attributes
*/
public function getKey($pk, array $attributes) {
if (is_array($pk)) {
$limit = count($pk);
$key = array();
for($i = 0; $i < $limit; $i++) {
$key[] = $attributes[$pk[$i]];
}
$pk = implode(":",$key);
}
else {
$pk = $attributes[$pk];
}
return $pk;
}
}

0 comments on commit 64ebf0e

Please sign in to comment.