CSqlDataProvider.php 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. <?php
  2. /**
  3. * CSqlDataProvider implements a data provider based on a plain SQL statement.
  4. *
  5. * CSqlDataProvider provides data in terms of arrays, each representing a row of query result.
  6. *
  7. * Like other data providers, CSqlDataProvider also supports sorting and pagination.
  8. * It does so by modifying the given {@link sql} statement with "ORDER BY" and "LIMIT"
  9. * clauses. You may configure the {@link sort} and {@link pagination} properties to
  10. * customize sorting and pagination behaviors.
  11. *
  12. * CSqlDataProvider may be used in the following way:
  13. * <pre>
  14. * $count=Yii::app()->db->createCommand('SELECT COUNT(*) FROM tbl_user')->queryScalar();
  15. * $sql='SELECT * FROM tbl_user';
  16. * $dataProvider=new CSqlDataProvider($sql, array(
  17. * 'totalItemCount'=>$count,
  18. * 'sort'=>array(
  19. * 'attributes'=>array(
  20. * 'id', 'username', 'email',
  21. * ),
  22. * ),
  23. * 'pagination'=>array(
  24. * 'pageSize'=>10,
  25. * ),
  26. * ));
  27. * // $dataProvider->getData() will return a list of arrays.
  28. * </pre>
  29. *
  30. * Note: if you want to use the pagination feature, you must configure the {@link totalItemCount} property
  31. * to be the total number of rows (without pagination). And if you want to use the sorting feature,
  32. * you must configure {@link sort} property so that the provider knows which columns can be sorted.
  33. *
  34. * @author Qiang Xue <qiang.xue@gmail.com>
  35. * @package system.web
  36. * @since 1.1.4
  37. */
  38. class CSqlDataProvider extends CDataProvider
  39. {
  40. /**
  41. * @var CDbConnection the database connection to be used in the queries.
  42. * Defaults to null, meaning using Yii::app()->db.
  43. */
  44. public $db;
  45. /**
  46. * @var string|CDbCommand the SQL statement to be used for fetching data rows.
  47. * Since version 1.1.13 this can also be an instance of {@link CDbCommand}.
  48. */
  49. public $sql;
  50. /**
  51. * @var array parameters (name=>value) to be bound to the SQL statement.
  52. */
  53. public $params=array();
  54. /**
  55. * @var string the name of key field. Defaults to 'id'.
  56. */
  57. public $keyField='id';
  58. /**
  59. * Constructor.
  60. * @param string|CDbCommand $sql the SQL statement to be used for fetching data rows. Since version 1.1.13 this can also be an instance of {@link CDbCommand}.
  61. * @param array $config configuration (name=>value) to be applied as the initial property values of this class.
  62. */
  63. public function __construct($sql,$config=array())
  64. {
  65. $this->sql=$sql;
  66. foreach($config as $key=>$value)
  67. $this->$key=$value;
  68. }
  69. /**
  70. * Fetches the data from the persistent data storage.
  71. * @return array list of data items
  72. */
  73. protected function fetchData()
  74. {
  75. if(!($this->sql instanceof CDbCommand))
  76. {
  77. $db=$this->db===null ? Yii::app()->db : $this->db;
  78. $command=$db->createCommand($this->sql);
  79. }
  80. else
  81. $command=clone $this->sql;
  82. if(($sort=$this->getSort())!==false)
  83. {
  84. $order=$sort->getOrderBy();
  85. if(!empty($order))
  86. {
  87. if(preg_match('/\s+order\s+by\s+[\w\s,\.]+$/i',$command->text))
  88. $command->text.=', '.$order;
  89. else
  90. $command->text.=' ORDER BY '.$order;
  91. }
  92. }
  93. if(($pagination=$this->getPagination())!==false)
  94. {
  95. $pagination->setItemCount($this->getTotalItemCount());
  96. $limit=$pagination->getLimit();
  97. $offset=$pagination->getOffset();
  98. $command->text=$command->getConnection()->getCommandBuilder()->applyLimit($command->text,$limit,$offset);
  99. }
  100. foreach($this->params as $name=>$value)
  101. $command->bindValue($name,$value);
  102. return $command->queryAll();
  103. }
  104. /**
  105. * Fetches the data item keys from the persistent data storage.
  106. * @return array list of data item keys.
  107. */
  108. protected function fetchKeys()
  109. {
  110. $keys=array();
  111. if($data=$this->getData())
  112. {
  113. if(is_object(reset($data)))
  114. foreach($data as $i=>$item)
  115. $keys[$i]=$item->{$this->keyField};
  116. else
  117. foreach($data as $i=>$item)
  118. $keys[$i]=$item[$this->keyField];
  119. }
  120. return $keys;
  121. }
  122. /**
  123. * Calculates the total number of data items.
  124. * This method is invoked when {@link getTotalItemCount()} is invoked
  125. * and {@link totalItemCount} is not set previously.
  126. * The default implementation simply returns 0.
  127. * You may override this method to return accurate total number of data items.
  128. * @return integer the total number of data items.
  129. */
  130. protected function calculateTotalItemCount()
  131. {
  132. return 0;
  133. }
  134. }