CDbStatePersister.php 4.39 KB
Newer Older
JULIO JARAMILLO's avatar
JULIO JARAMILLO committed
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 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
<?php
/**
 * CDbStatePersister class file.
 *
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @link http://www.yiiframework.com/
 * @copyright 2008-2013 Yii Software LLC
 * @license http://www.yiiframework.com/license/
 * @package system.base
 * @since 1.1.17
 */

/**
 * CDbStatePersister implements a database persistent data storage.
 *
 * It can be used to keep data available through multiple requests and sessions.
 *
 * By default, CDbStatePersister stores data in a table named 'state'.
 * You may change the location by setting the {@link stateTableName} property.
 *
 * To retrieve the data from CDbStatePersister, call {@link load()}. To save the data,
 * call {@link save()}.
 *
 * Comparison among state persister, session and cache is as follows:
 * <ul>
 * <li>session: data persisting within a single user session.</li>
 * <li>state persister: data persisting through all requests/sessions (e.g. hit counter).</li>
 * <li>cache: volatile and fast storage. It may be used as storage medium for session or state persister.</li>
 * </ul>
 *
 * @package system.base
 * @since 1.1.17
 */
class CDbStatePersister extends CApplicationComponent implements IStatePersister
{
	/**
	 * @var string the database table name storing the state data. Make sure the table
	 * exists or database user is granted to CREATE tables.
	 */
	public $stateTableName='state';
	/**
	 * @var string connection ID
	 */
	public $dbComponent='db';
	/**
	 * @var CDbConnection instance
	 */
	public $db;
	/**
	 * @var string Column name for value-field
	 */
	public $valueField='value';
	/**
	 * @var string Column name for key-field
	 */
	public $keyField='key';


	/**
	 * Initializes the component.
	 * This method overrides the parent implementation by making sure {@link stateFile}
	 * contains valid value.
	 */
	public function init()
	{
		parent::init();
		if($this->stateTableName===null)
			throw new CException(Yii::t('yii', 'stateTableName param cannot be null.'));
		$this->db=Yii::app()->getComponent($this->dbComponent);
		if($this->db===null)
			throw new CException(Yii::t('yii', '\'{db}\' component doesn\'t exist.',array(
				'{db}'=>$this->dbComponent
			)));
		if(!($this->db instanceof CDbConnection))
			throw new CException(Yii::t ('yii', '\'{db}\' component is not a valid CDbConnection instance.',array(
				'{db}'=>$this->dbComponent
			)));
		if($this->db->schema->getTable($this->stateTableName,true)===null)
			$this->createTable();
	}

	/**
	 * Loads state data from persistent storage.
	 * @return mixed state data. Null if no state data available.
	 */
	public function load()
	{
		$command=$this->db->createCommand();
		$command=$command->select($this->valueField)->from($this->stateTableName);
		$command=$command->where($this->db->quoteColumnName($this->keyField).'=:key',array(
			':key'=>Yii::app()->name
		));
		$state=$command->queryScalar();
		if(false!==$state)
			return unserialize($state);
		else
			return null;
	}

	/**
	 * Saves application state in persistent storage.
	 * @param mixed $state state data (must be serializable).
	 * @return int
	 */
	public function save($state)
	{
		$command=$this->db->createCommand();
		if(false===$this->exists())
			return $command->insert($this->stateTableName,array(
				$this->keyField=>Yii::app()->name,
				$this->valueField=>serialize($state)
			));
		else
			return $command->update($this->stateTableName,array($this->valueField=>serialize($state)),
				$this->db->quoteColumnName($this->keyField).'=:key',
				array(':key'=>Yii::app()->name)
		);
	}

	/**
	 * @return mixed
	 */
	public function exists()
	{
		$command=$this->db->createCommand();
		$command=$command->select($this->keyField)->from($this->stateTableName);
		$command=$command->where($this->db->quoteColumnName($this->keyField).'=:key',array(
			':key'=>Yii::app()->name
		));
		return $command->queryScalar();
	}

	/**
	 * Creates state persister table
	 * @throws CException
	 */
	protected function createTable()
	{
		try
		{
			$command=$this->db->createCommand();
			$command->createTable($this->stateTableName,array(
				$this->keyField=>'string NOT NULL',
				$this->valueField=>'text NOT NULL',
				'PRIMARY KEY ('.$this->db->quoteColumnName($this->keyField).')'
			));
		}
		catch (CDbException $e)
		{
			throw new CException(Yii::t('yii','Can\'t create state persister table. Check CREATE privilege for \'{db}\' connection user or create table manually with SQL: {sql}.',array('{db}'=>$this->dbComponent,'{sql}'=>$command->text ) ) );
		}
	}
}