1<?php 2/** 3 * CDbStatePersister class file. 4 * 5 * @author Qiang Xue <qiang.xue@gmail.com> 6 * @link http://www.yiiframework.com/ 7 * @copyright 2008-2013 Yii Software LLC 8 * @license http://www.yiiframework.com/license/ 9 * @package system.base 10 * @since 1.1.17 11 */ 12 13/** 14 * CDbStatePersister implements a database persistent data storage. 15 * 16 * It can be used to keep data available through multiple requests and sessions. 17 * 18 * By default, CDbStatePersister stores data in a table named 'state'. 19 * You may change the location by setting the {@link stateTableName} property. 20 * 21 * To retrieve the data from CDbStatePersister, call {@link load()}. To save the data, 22 * call {@link save()}. 23 * 24 * Comparison among state persister, session and cache is as follows: 25 * <ul> 26 * <li>session: data persisting within a single user session.</li> 27 * <li>state persister: data persisting through all requests/sessions (e.g. hit counter).</li> 28 * <li>cache: volatile and fast storage. It may be used as storage medium for session or state persister.</li> 29 * </ul> 30 * 31 * @package system.base 32 * @since 1.1.17 33 */ 34class CDbStatePersister extends CApplicationComponent implements IStatePersister 35{ 36 /** 37 * @var string the database table name storing the state data. Make sure the table 38 * exists or database user is granted to CREATE tables. 39 */ 40 public $stateTableName='state'; 41 /** 42 * @var string connection ID 43 */ 44 public $dbComponent='db'; 45 /** 46 * @var CDbConnection instance 47 */ 48 public $db; 49 /** 50 * @var string Column name for value-field 51 */ 52 public $valueField='value'; 53 /** 54 * @var string Column name for key-field 55 */ 56 public $keyField='key'; 57 58 59 /** 60 * Initializes the component. 61 * This method overrides the parent implementation by making sure {@link stateFile} 62 * contains valid value. 63 */ 64 public function init() 65 { 66 parent::init(); 67 if($this->stateTableName===null) 68 throw new CException(Yii::t('yii', 'stateTableName param cannot be null.')); 69 $this->db=Yii::app()->getComponent($this->dbComponent); 70 if($this->db===null) 71 throw new CException(Yii::t('yii', '\'{db}\' component doesn\'t exist.',array( 72 '{db}'=>$this->dbComponent 73 ))); 74 if(!($this->db instanceof CDbConnection)) 75 throw new CException(Yii::t ('yii', '\'{db}\' component is not a valid CDbConnection instance.',array( 76 '{db}'=>$this->dbComponent 77 ))); 78 if($this->db->schema->getTable($this->stateTableName,true)===null) 79 $this->createTable(); 80 } 81 82 /** 83 * Loads state data from persistent storage. 84 * @return mixed state data. Null if no state data available. 85 */ 86 public function load() 87 { 88 $command=$this->db->createCommand(); 89 $command=$command->select($this->valueField)->from($this->stateTableName); 90 $command=$command->where($this->db->quoteColumnName($this->keyField).'=:key',array( 91 ':key'=>Yii::app()->name 92 )); 93 $state=$command->queryScalar(); 94 if(false!==$state) 95 return unserialize($state); 96 else 97 return null; 98 } 99 100 /** 101 * Saves application state in persistent storage. 102 * @param mixed $state state data (must be serializable). 103 * @return int 104 */ 105 public function save($state) 106 { 107 $command=$this->db->createCommand(); 108 if(false===$this->exists()) 109 return $command->insert($this->stateTableName,array( 110 $this->keyField=>Yii::app()->name, 111 $this->valueField=>serialize($state) 112 )); 113 else 114 return $command->update($this->stateTableName,array($this->valueField=>serialize($state)), 115 $this->db->quoteColumnName($this->keyField).'=:key', 116 array(':key'=>Yii::app()->name) 117 ); 118 } 119 120 /** 121 * @return mixed 122 */ 123 public function exists() 124 { 125 $command=$this->db->createCommand(); 126 $command=$command->select($this->keyField)->from($this->stateTableName); 127 $command=$command->where($this->db->quoteColumnName($this->keyField).'=:key',array( 128 ':key'=>Yii::app()->name 129 )); 130 return $command->queryScalar(); 131 } 132 133 /** 134 * Creates state persister table 135 * @throws CException 136 */ 137 protected function createTable() 138 { 139 try 140 { 141 $command=$this->db->createCommand(); 142 $command->createTable($this->stateTableName,array( 143 $this->keyField=>'string NOT NULL', 144 $this->valueField=>'text NOT NULL', 145 'PRIMARY KEY ('.$this->db->quoteColumnName($this->keyField).')' 146 )); 147 } 148 catch (CDbException $e) 149 { 150 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 ) ) ); 151 } 152 } 153} 154