CDataProviderIterator.php 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. <?php
  2. /**
  3. * CDataProviderIterator class file.
  4. *
  5. * @author Charles Pick <charles.pick@gmail.com>
  6. * @link http://www.yiiframework.com/
  7. * @copyright 2008-2013 Yii Software LLC
  8. * @license http://www.yiiframework.com/license/
  9. */
  10. /**
  11. * CDataProviderIterator allows iteration over large data sets without holding the entire set in memory.
  12. *
  13. * CDataProviderIterator iterates over the results of a data provider, starting at the first page
  14. * of results and ending at the last page. It is usually only suited for use with {@link CActiveDataProvider}.
  15. *
  16. * For example, the following code will iterate over all registered users (active record class User) without
  17. * running out of memory, even if there are millions of users in the database.
  18. * <pre>
  19. * $dataProvider = new CActiveDataProvider("User");
  20. * $iterator = new CDataProviderIterator($dataProvider);
  21. * foreach($iterator as $user) {
  22. * echo $user->name."\n";
  23. * }
  24. * </pre>
  25. *
  26. * @property CDataProvider $dataProvider the data provider to iterate over
  27. * @property integer $totalItemCount the total number of items in the iterator
  28. *
  29. * @author Charles Pick <charles.pick@gmail.com>
  30. * @author Carsten Brandt <mail@cebe.cc>
  31. * @package system.web
  32. * @since 1.1.13
  33. */
  34. class CDataProviderIterator extends CComponent implements Iterator, Countable
  35. {
  36. private $_dataProvider;
  37. private $_currentIndex=-1;
  38. private $_currentPage=0;
  39. private $_totalItemCount=-1;
  40. private $_items;
  41. /**
  42. * Constructor.
  43. * @param CDataProvider $dataProvider the data provider to iterate over
  44. * @param integer $pageSize pageSize to use for iteration. This is the number of objects loaded into memory at the same time.
  45. */
  46. public function __construct(CDataProvider $dataProvider, $pageSize=null)
  47. {
  48. $this->_dataProvider=$dataProvider;
  49. $this->_totalItemCount=$dataProvider->getTotalItemCount();
  50. if(($pagination=$this->_dataProvider->getPagination())===false)
  51. $this->_dataProvider->setPagination($pagination=new CPagination());
  52. if($pageSize!==null)
  53. $pagination->setPageSize($pageSize);
  54. }
  55. /**
  56. * Returns the data provider to iterate over
  57. * @return CDataProvider the data provider to iterate over
  58. */
  59. public function getDataProvider()
  60. {
  61. return $this->_dataProvider;
  62. }
  63. /**
  64. * Gets the total number of items to iterate over
  65. * @return integer the total number of items to iterate over
  66. */
  67. public function getTotalItemCount()
  68. {
  69. return $this->_totalItemCount;
  70. }
  71. /**
  72. * Loads a page of items
  73. * @return array the items from the next page of results
  74. */
  75. protected function loadPage()
  76. {
  77. $this->_dataProvider->getPagination()->setCurrentPage($this->_currentPage);
  78. return $this->_items=$this->dataProvider->getData(true);
  79. }
  80. /**
  81. * Gets the current item in the list.
  82. * This method is required by the Iterator interface.
  83. * @return mixed the current item in the list
  84. */
  85. public function current()
  86. {
  87. return $this->_items[$this->_currentIndex];
  88. }
  89. /**
  90. * Gets the key of the current item.
  91. * This method is required by the Iterator interface.
  92. * @return integer the key of the current item
  93. */
  94. public function key()
  95. {
  96. $pageSize=$this->_dataProvider->getPagination()->getPageSize();
  97. return $this->_currentPage*$pageSize+$this->_currentIndex;
  98. }
  99. /**
  100. * Moves the pointer to the next item in the list.
  101. * This method is required by the Iterator interface.
  102. */
  103. public function next()
  104. {
  105. $pageSize=$this->_dataProvider->getPagination()->getPageSize();
  106. $this->_currentIndex++;
  107. if($this->_currentIndex >= $pageSize)
  108. {
  109. $this->_currentPage++;
  110. $this->_currentIndex=0;
  111. $this->loadPage();
  112. }
  113. }
  114. /**
  115. * Rewinds the iterator to the start of the list.
  116. * This method is required by the Iterator interface.
  117. */
  118. public function rewind()
  119. {
  120. $this->_currentIndex=0;
  121. $this->_currentPage=0;
  122. $this->loadPage();
  123. }
  124. /**
  125. * Checks if the current position is valid or not.
  126. * This method is required by the Iterator interface.
  127. * @return boolean true if this index is valid
  128. */
  129. public function valid()
  130. {
  131. return $this->key() < $this->_totalItemCount;
  132. }
  133. /**
  134. * Gets the total number of items in the dataProvider.
  135. * This method is required by the Countable interface.
  136. * @return integer the total number of items
  137. */
  138. public function count()
  139. {
  140. return $this->_totalItemCount;
  141. }
  142. }