Repository.php 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. <?php
  2. namespace app\framework\Repository;
  3. use app\common\models\BaseModel;
  4. use app\framework\Repository\Source\Cache;
  5. use app\framework\Repository\Source\Eloquent;
  6. use app\framework\Repository\Source\Local;
  7. /**
  8. * Class Repository
  9. * @package app\framework\Repository
  10. */
  11. abstract class Repository
  12. {
  13. /**
  14. * @var []
  15. */
  16. static $instances = [];
  17. /**
  18. * @var array
  19. */
  20. private $source;
  21. protected $modelName;
  22. /**
  23. * @var BaseModel
  24. */
  25. protected $model;
  26. protected $cacheTime;
  27. protected $excludeFields = [];
  28. protected $only = [];
  29. private function getKeyName()
  30. {
  31. return $this->getModel()->getKeyName();
  32. }
  33. protected function getModel()
  34. {
  35. if (!isset($this->model)) {
  36. $this->model = new $this->modelName;
  37. }
  38. return $this->model;
  39. }
  40. protected function _getSource()
  41. {
  42. $model = $this->getModel();
  43. $source = [
  44. new Local($model),
  45. new Cache($model, $this->cacheTime),
  46. new Eloquent($model, $this->excludeFields),
  47. ];
  48. return $source;
  49. }
  50. private function getSource()
  51. {
  52. if (!isset($this->source)) {
  53. $this->source = $this->_getSource();
  54. }
  55. return $this->source;
  56. }
  57. protected function findManyBy($key,$ids)
  58. {
  59. $data = new Collection();
  60. // 记录每层被穿透的数据
  61. $missedSourcesIds = [];
  62. // 逐层向上查找
  63. foreach ($this->getSource() as $source) {
  64. /**
  65. * @var RepositorySourceInterface $source
  66. */
  67. $data = $source->findMany($key,$ids);
  68. $findIds = array_column($data, $key) ?: [];
  69. $missedIds = array_diff($ids, $findIds);
  70. if (!count($missedIds)) {
  71. // 全部找到,终止循环
  72. break;
  73. }
  74. // 记录没找到的
  75. $missedSourcesIds[] = [
  76. 'source' => $source,
  77. 'ids' => $missedIds,
  78. ];
  79. }
  80. // 保存数据到被穿透的层
  81. if ($missedSourcesIds) {
  82. // 每个穿透的层
  83. foreach ($missedSourcesIds as $missedSourceItemIds) {
  84. // 这层被穿透的数据
  85. $missedData = [];
  86. foreach ($data as $item) {
  87. // 根据id匹配对应的数据
  88. if (in_array($item[$key], $missedSourceItemIds['ids'])) {
  89. $missedData[] = $item;
  90. }
  91. }
  92. /**
  93. * @var RepositorySourceInterface $missedSource
  94. */
  95. $missedSourceItemIds['source']->saveMany($missedData);
  96. }
  97. }
  98. return new Collection($data);
  99. }
  100. /**
  101. *
  102. * @param $ids
  103. * @return Collection
  104. */
  105. protected function findMany($ids)
  106. {
  107. return $this->findManyBy($this->getKeyName(),$ids);
  108. }
  109. /**
  110. * @param $id
  111. * @return null
  112. */
  113. protected function find($id)
  114. {
  115. $data = null;
  116. $missedSources = [];
  117. // 逐层向上查找
  118. foreach ($this->getSource() as $source) {
  119. /**
  120. * @var RepositorySourceInterface $source
  121. */
  122. $data = $source->find($id);
  123. if (isset($data)) {
  124. break;
  125. }
  126. $missedSources[] = $source;
  127. }
  128. // 保存到被穿透的层
  129. if ($missedSources) {
  130. foreach ($missedSources as $missedSource) {
  131. /**
  132. * @var RepositorySourceInterface $missedSource
  133. */
  134. $missedSource->save($id, $data);
  135. }
  136. }
  137. return $data;
  138. }
  139. /**
  140. * @return null
  141. */
  142. protected function all()
  143. {
  144. $data = new Collection();
  145. $missedSources = [];
  146. // 逐层向上查找
  147. foreach ($this->getSource() as $source) {
  148. /**
  149. * @var RepositorySourceInterface $source
  150. */
  151. $data = $source->all();
  152. if (isset($data)) {
  153. break;
  154. }
  155. $missedSources[] = $source;
  156. }
  157. // 保存到被穿透的层
  158. if ($missedSources) {
  159. foreach ($missedSources as $missedSource) {
  160. /**
  161. * @var RepositorySourceInterface $missedSource
  162. */
  163. $missedSource->saveAll($data);
  164. }
  165. }
  166. return new Collection($data);
  167. }
  168. protected function flush()
  169. {
  170. foreach ($this->getSource() as $source) {
  171. $source->flush();
  172. }
  173. \app\common\helpers\Cache::forget('load_option');
  174. }
  175. public function __call($name, $arguments)
  176. {
  177. if (!self::$instances[static::class]) {
  178. self::$instances[static::class] = $this;
  179. }
  180. if (method_exists($this, $name)) {
  181. return self::$instance['static::class']->{$name}(...$arguments);
  182. }
  183. }
  184. public static function __callStatic($name, $arguments)
  185. {
  186. if (!self::$instances[static::class]) {
  187. self::$instances[static::class] = new static();
  188. }
  189. return self::$instances[static::class]->{$name}(...$arguments);
  190. }
  191. }