├── .gitignore
├── README.md
├── composer.json
├── src
├── AbstractMongoArRepository.php
├── AbstractSqlArRepository.php
├── Exceptions
│ └── RepositoryException.php
├── Interfaces
│ └── iRepository.php
└── Traits
│ ├── MongoArRepositoryTrait.php
│ └── SqlArRepositoryTrait.php
└── tests
└── .gitignore
/.gitignore:
--------------------------------------------------------------------------------
1 | vendor
2 | index.php
3 | composer.lock
4 | .idea
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Yii2 Repository Pattern implementation
2 | ======================================
3 | Yii2 Repository Pattern implementation in Yii2
4 |
5 | you can read more about repository patterns here :
6 | http://deviq.com/repository-pattern/
7 | http://martinfowler.com/eaaCatalog/repository.html
8 | http://shawnmc.cool/the-repository-pattern
9 | http://stackoverflow.com/questions/16176990/proper-repository-pattern-design-in-php
10 |
11 | ## Table of Contents
12 |
13 | - Installation
14 | - Composer
15 | - Methods
16 | - RepositoryInterface
17 |
18 | - Usage
19 | - Create a Model
20 | - Create a Repository
21 | - Attach your Repository to container
22 | - Repository Sample Usage
23 |
24 |
25 | ## Installation
26 |
27 | ### Composer
28 | The preferred way to install this extension is through [composer](http://getcomposer.org/download/).
29 |
30 | Either run
31 |
32 | ```
33 | composer require --prefer-dist mhndev/yii2-repository "1.*"
34 | ```
35 |
36 | or add
37 |
38 | ```
39 | "mhndev/yii2-repository": "1.*"
40 | ```
41 |
42 | to the require section of your `composer.json` file.
43 |
44 |
45 | ## Methods
46 |
47 | ### mhndev\yii2Repository\Interfaces\iRepository
48 |
49 | ```php
50 | public function with(array $with = []);
51 |
52 | public function columns(array $columns = ['*']);
53 |
54 | public function limit($limit = 10);
55 |
56 | public function orderBy($orderBy, $sort = 'DESC');
57 |
58 | public function create(array $data);
59 |
60 | public function createMany(array $data);
61 |
62 | public function findOneById($id, $returnArray = false);
63 |
64 | public function findOneBy($key, $value, $operation = '=', $returnArray = false);
65 |
66 | public function findManyBy($key, $value, $operation = '=', $withPagination = true, $returnArray = false);
67 |
68 | public function findManyByIds(array $ids, $withPagination = true, $returnArray = false);
69 |
70 | public function findAll($withPagination = true, $returnArray = false);
71 |
72 | public function findManyByCriteria(array $criteria = [], $withPagination = true, $with = [], $returnArray = false);
73 |
74 | public function updateOneById($id, array $data = []);
75 |
76 | public function updateOneBy($key, $value, array $data = []);
77 |
78 | public function updateOneByCriteria(array $criteria, array $data = []);
79 |
80 | public function updateManyBy($key, $value, array $data = [], $operation = '=');
81 |
82 | public function updateManyByCriteria(array $criteria = [], array $data = []);
83 |
84 | public function updateManyByIds(array $ids, array $data = []);
85 |
86 | public function deleteOneById($id);
87 |
88 | public function allExist(array $ids);
89 |
90 | public function deleteOneBy($key, $value, $operation = '=');
91 |
92 | public function deleteOneByCriteria(array $criteria = []);
93 |
94 | public function deleteManyBy($key, $value, $operation = '=');
95 |
96 | public function deleteManyByCriteria(array $criteria = []);
97 |
98 | public function searchByCriteria();
99 |
100 | public function deleteManyByIds(array $ids);
101 |
102 | public function inc($id, $field, $count = 1);
103 |
104 | public function dec($id, $field, $count = 1);
105 | ```
106 |
107 | ## Usage
108 |
109 | ### Create a Model
110 |
111 | create your ActiveRecord Model :
112 |
113 | ```php
114 | namespace app\models;
115 |
116 |
117 | use yii\db\ActiveRecord;
118 |
119 | /**
120 | * Class City
121 | * @package app\models
122 | */
123 | class Post extends ActiveRecord
124 | {
125 |
126 | /**
127 | * @return string
128 | */
129 | public static function tableName()
130 | {
131 | return 'posts';
132 |
133 | }
134 |
135 | /**
136 | * @return array
137 | */
138 | public function rules()
139 | {
140 | return [
141 |
142 | [['title'], 'required'],
143 |
144 | ];
145 | }
146 |
147 |
148 | }
149 |
150 | ```
151 |
152 | ### Create a Repository Interface
153 | ```php
154 | namespace app\repositories\interfaces;
155 | use mhndev\yii2Repository\Interfaces\iRepository;
156 |
157 | interface iPostRepository extends iRepository
158 | {
159 |
160 | }
161 |
162 | ```
163 | ### Create a Repository class
164 |
165 | ```php
166 | namespace app\repositories;
167 |
168 | use app\repositories\interfaces\iPostRepository;
169 | use mhndev\yii2Repository\AbstractSqlArRepository;
170 |
171 | class PostRepository extends AbstractSqlArRepository implements iPostRepository
172 | {
173 |
174 | }
175 |
176 | ```
177 |
178 | or
179 |
180 | ### create a Repository as a Yii component
181 |
182 | ```php
183 | class PostRepository extends Component implements iPostRepository
184 | {
185 |
186 | const PRIMARY_KEY = 'id';
187 |
188 | const APPLICATION_KEY = 'id';
189 |
190 |
191 | use SqlArRepositoryTrait {
192 | init as repositoryInit;
193 | }
194 |
195 |
196 | public function init()
197 | {
198 | parent::init();
199 |
200 | $this->repositoryInit();
201 | }
202 | }
203 |
204 |
205 | ```
206 |
207 | this approach is useful when toy have a class which is already extending a class
208 | and can't extend AbstractRepository class just like yii components
209 | by using traits you can use this classes as yii component.
210 |
211 |
212 |
213 | if your model is using sql as it's data source and your model actually is extending yii\db\ActiveRecord
214 | your repository should extend mhndev\yii2Repository\AbstractSqlArRepository.
215 |
216 | and if your data source is mongodb and your model actually is extending yii\mongodb\ActiveRecord
217 | your repository should extend mhndev\yii2Repository\AbstractMongoArRepository.
218 |
219 |
220 | and consider your application can use power of both sql and document-based databses (mongo)
221 | ### Attach your Repository to container
222 | ```php
223 |
224 | Yii::$container->set(\app\repositories\interfaces\iPostRepository::class, [
225 | 'class' => \app\repositories\PostRepository::class
226 | ]);
227 |
228 |
229 | Yii::$container->set('postRepository', function($container, $params, $config){
230 | return new \app\repositories\PostRepository(new \app\models\Post());
231 | });
232 |
233 |
234 | ```
235 | if you are coding in a module you can put above code in your module bootstrap file.
236 | and also you can don't use container and create repository object every where you want like this :
237 |
238 | ```php
239 | $postRepository = new \app\repositories\PostRepository(new \app\models\Post());
240 |
241 | ```
242 |
243 | ### Repository Sample Usage
244 |
245 | sample usage which I show by using a controller.
246 |
247 | ```php
248 | namespace app\controllers;
249 |
250 | use app\repositories\interfaces\iPostRepository;
251 | use Yii;
252 | use yii\web\Controller;
253 | use yii\web\Response;
254 |
255 | /**
256 | * PostController
257 | */
258 | class PostController extends Controller
259 | {
260 |
261 | /**
262 | * @var iPostRepository
263 | */
264 | protected $postRepository;
265 |
266 |
267 | /**
268 | * @var bool
269 | */
270 | public $enableCsrfValidation = false;
271 |
272 |
273 | /**
274 | * init
275 | */
276 | public function init()
277 | {
278 | parent::init();
279 | $this->postRepository = Yii::$container->get('postRepository');
280 |
281 | Yii::$app->response->format = Response::FORMAT_JSON;
282 | }
283 |
284 | /**
285 | * @return array
286 | */
287 | public function verbs()
288 | {
289 | return [
290 | 'create' => ['POST'],
291 | 'delete' => ['DELETE'],
292 | 'update' => ['PUT'],
293 | 'index' => ['GET'],
294 | 'show' => ['GET'],
295 | 'delete-multiple' => ['DELETE']
296 | ];
297 | }
298 |
299 |
300 | /**
301 | * @return mixed
302 | */
303 | public function actionCreate()
304 | {
305 | $data = Yii::$app->request->post();
306 |
307 | $post = $this->postRepository->create($data);
308 |
309 | return $post;
310 | }
311 |
312 |
313 | /**
314 | * @param $id
315 | */
316 | public function actionDelete($id)
317 | {
318 | $this->postRepository->deleteOneById($id);
319 | }
320 |
321 | /**
322 | * @param $id
323 | * @return bool
324 | */
325 | public function actionUpdate($id)
326 | {
327 | $data = Yii::$app->request->post();
328 |
329 | $post = $this->postRepository->updateOneById($id, $data);
330 |
331 | return $post;
332 | }
333 |
334 |
335 | /**
336 | * @return mixed
337 | */
338 | public function actionIndex()
339 | {
340 | return $this->postRepository->searchByCriteria();
341 | }
342 |
343 |
344 | /**
345 | * @param $id
346 | * @return mixed
347 | */
348 | public function actionShow($id)
349 | {
350 | return $this->postRepository->findOneById($id);
351 | }
352 |
353 |
354 | /**
355 | *
356 | */
357 | public function actionDeleteMultiple()
358 | {
359 | $ids = Yii::$app->request->post()['ids'];
360 |
361 | $deletedCount = $this->postRepository->deleteManyByIds($ids);
362 | }
363 |
364 |
365 | }
366 |
367 | ```
368 |
369 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mhndev/yii2-repository",
3 | "description": "repository implementation in Yii2",
4 | "type": "library",
5 | "keywords": ["yii2","repository pattern","design pattern"],
6 | "license": "MIT",
7 | "authors": [
8 | {
9 | "name": "majid abdolhosseini",
10 | "email": "majid8911303@gmail.com"
11 | }
12 | ],
13 | "require": {
14 | "yiisoft/yii2": "*"
15 | },
16 |
17 | "suggest": {
18 | "yiisoft/yii2-mongodb": "needed if you want to use mongodb as your dbms instead of relational dbms"
19 | },
20 |
21 |
22 | "autoload": {
23 | "psr-4": {
24 | "mhndev\\yii2Repository\\": "src/"
25 | }
26 | },
27 |
28 | "minimum-stability": "stable"
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/src/AbstractMongoArRepository.php:
--------------------------------------------------------------------------------
1 | findManyBy('title','title5','like');
17 | *
18 | * $posts = $postRepository->findManyBy('title','title5');
19 | *
20 | * $posts = $postRepository->findManyByIds([1,2,3]);
21 | *
22 | * $posts = $postRepository->findManyWhereIn('text',['text1','text2']);
23 | *
24 | * $posts = $postRepository->findManyByCriteria([
25 | * ['like', 'title','title'] , ['=','text','text1']
26 | * ]);
27 | *
28 | * $posts = $postRepository->findOneById(2);
29 | *
30 | * $postRepository->updateOneById(2, ['title'=>'new new']);
31 | *
32 | * $postRepository->updateManyByIds([1,2,3], ['title'=>'new new new']);
33 | *
34 | * $postRepository->updateManyBy('title','salam', ['text'=>'sssssssssss'], 'like');
35 | *
36 | * $postRepository->updateManyByCriteria([['like','title','salam'],['like','text','text2']], ['text'=>'salam']);
37 | *
38 | * $postRepository->deleteManyByIds([2,3]);
39 | *
40 | * $postRepository->deleteManyBy('title','title5','like');
41 | *
42 | * $posts = $postRepository->findManyWhereIn('title',['salam','salam2'], false);
43 | *
44 | * Class AbstractMongoArRepository
45 | * @package mhndev\yii2Repository
46 | */
47 | class AbstractMongoArRepository implements iRepository
48 | {
49 |
50 | const PRIMARY_KEY = '_id';
51 |
52 | const APPLICATION_KEY = 'id';
53 |
54 | use MongoArRepositoryTrait;
55 |
56 | /**
57 | * AbstractMongoRepository constructor.
58 | * @param ActiveRecord $model
59 | */
60 | public function __construct(ActiveRecord $model)
61 | {
62 | $this->model = $model;
63 |
64 | $this->initRepositoryParams();
65 | }
66 |
67 |
68 | }
69 |
--------------------------------------------------------------------------------
/src/AbstractSqlArRepository.php:
--------------------------------------------------------------------------------
1 | findManyBy('title','title5','like');
18 | *
19 | * $posts = $postRepository->findManyBy('title','title5');
20 | *
21 | * $posts = $postRepository->findManyByIds([1,2,3]);
22 | *
23 | * $posts = $postRepository->findManyWhereIn('text',['text1','text2']);
24 | *
25 | * $posts = $postRepository->findManyByCriteria([
26 | * ['like', 'title','title'] , ['=','text','text1']
27 | * ]);
28 | *
29 | * $posts = $postRepository->findOneById(2);
30 | *
31 | * $postRepository->updateOneById(2, ['title'=>'new new']);
32 | *
33 | * $postRepository->updateManyByIds([1,2,3], ['title'=>'new new new']);
34 | *
35 | * $postRepository->updateManyBy('title','salam', ['text'=>'sssssssssss'], 'like');
36 | *
37 | * $postRepository->updateManyByCriteria([['like','title','salam'],['like','text','text2']], ['text'=>'salam']);
38 | *
39 | * $postRepository->deleteManyByIds([2,3]);
40 | *
41 | * $postRepository->deleteManyBy('title','title5','like');
42 | *
43 | * $posts = $postRepository->findManyWhereIn('title',['salam','salam2'], false);
44 | *
45 | * Class AbstractSqlArRepository
46 | * @package mhndev\yii2Repository
47 | */
48 | class AbstractSqlArRepository implements iRepository
49 | {
50 |
51 | const PRIMARY_KEY = 'id';
52 |
53 | const APPLICATION_KEY = 'id';
54 |
55 |
56 | use SqlArRepositoryTrait;
57 |
58 | /**
59 | * AbstractMongoRepository constructor.
60 | * @param ActiveRecord $model
61 | */
62 | public function __construct(ActiveRecord $model)
63 | {
64 | $this->model = $model;
65 |
66 | $this->initRepositoryParams();
67 | }
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/src/Exceptions/RepositoryException.php:
--------------------------------------------------------------------------------
1 | findManyBy('title','title5','like');
22 | *
23 | * $posts = $postRepository->findManyBy('title','title5');
24 | *
25 | * $posts = $postRepository->findManyByIds([1,2,3]);
26 | *
27 | * $posts = $postRepository->findManyWhereIn('text',['text1','text2']);
28 | *
29 | * $posts = $postRepository->findManyByCriteria([
30 | * ['like', 'title','title'] , ['=','text','text1']
31 | * ]);
32 | *
33 | * $posts = $postRepository->findOneById(2);
34 | *
35 | * $postRepository->updateOneById(2, ['title'=>'new new']);
36 | *
37 | * $postRepository->updateManyByIds([1,2,3], ['title'=>'new new new']);
38 | *
39 | * $postRepository->updateManyBy('title','salam', ['text'=>'sssssssssss'], 'like');
40 | *
41 | *
42 | * $postRepository->updateManyByCriteria([['like','title','salam'],['like','text','text2']], ['text'=>'salam']);
43 | *
44 | * $postRepository->deleteManyByIds([2,3]);
45 | *
46 | * $postRepository->deleteManyBy('title','title5','like');
47 | *
48 | * $posts = $postRepository->findManyWhereIn('title',['salam','salam2'], false);
49 | *
50 | *
51 | *
52 | * trait MongoArRepositoryTrait
53 | * @package mhndev\yii2Repository
54 | */
55 | trait MongoArRepositoryTrait
56 | {
57 | /**
58 | * @var ActiveRecord
59 | */
60 | protected $model;
61 |
62 |
63 | /**
64 | * @var string
65 | */
66 | public $modelClass;
67 |
68 | /**
69 | * @var array $data
70 | * query parameters (sort, filters, pagination)
71 | */
72 | protected $data;
73 |
74 | /**
75 | * @var array
76 | */
77 | protected $with = [];
78 |
79 | /**
80 | * @var array
81 | */
82 | protected $columns = ['*'];
83 |
84 | /**
85 | * @var string
86 | */
87 | protected $orderBy;
88 |
89 | /**
90 | * @var int
91 | */
92 | protected $limit = 10;
93 |
94 | /**
95 | * @var int
96 | */
97 | protected $offset = 0;
98 |
99 |
100 | /**
101 | * @var Query
102 | */
103 | protected $query;
104 |
105 |
106 | /**
107 | * @var Connection
108 | */
109 | protected $connection;
110 |
111 |
112 |
113 | /**
114 | * @throws RepositoryException
115 | */
116 | public function init()
117 | {
118 | if($this->model){
119 | return;
120 | }
121 |
122 | if(empty($this->modelClass)){
123 | throw new RepositoryException('what the f ...');
124 | }
125 |
126 | $this->model = new $this->modelClass;
127 |
128 | $this->initRepositoryParams();
129 | }
130 |
131 |
132 | /**
133 | * @return $this
134 | */
135 | protected function initRepositoryParams()
136 | {
137 | $this->columns();
138 | $this->orderBy(self::PRIMARY_KEY, self::desc);
139 |
140 | $this->connection = Yii::$app->mongodb;
141 | $this->query = $this->model->find();
142 |
143 | return $this;
144 | }
145 |
146 | /**
147 | * @param $returnArray
148 | * @param $columns
149 | * @param $with
150 | */
151 | protected function initFetch($returnArray, $columns, $with)
152 | {
153 | foreach ($with as $relation){
154 | $this->query = $this->query->with($relation);
155 | }
156 |
157 |
158 | if($columns != ['*']){
159 | $this->query->select($columns);
160 | }
161 |
162 | if($returnArray){
163 | $this->query->asArray();
164 | }
165 | }
166 |
167 |
168 |
169 | /**
170 | * @return ActiveRecord
171 | */
172 | protected function makeQuery()
173 | {
174 | return $this->model;
175 | }
176 |
177 |
178 | /**
179 | * @param array $with
180 | * @return $this
181 | * @throws RepositoryException
182 | */
183 | public function with(array $with = [])
184 | {
185 | if (is_array($with) === false) {
186 | throw new RepositoryException;
187 | }
188 |
189 | $this->with = $with;
190 |
191 | return $this;
192 | }
193 |
194 | /**
195 | * @param array $columns
196 | * @return $this
197 | * @throws RepositoryException
198 | */
199 | public function columns(array $columns = ['*'])
200 | {
201 | if (is_array($columns) === false) {
202 | throw new RepositoryException;
203 | }
204 |
205 | else{
206 | $this->columns = $columns;
207 | }
208 |
209 | return $this;
210 | }
211 |
212 |
213 | /**
214 | * @param int $offset
215 | * @return $this
216 | * @throws RepositoryException
217 | */
218 | public function offset($offset = 0)
219 | {
220 | if (!is_numeric($offset) || $offset < 0) {
221 | throw new RepositoryException;
222 | }
223 |
224 | $this->offset = $offset;
225 |
226 | return $this;
227 | }
228 |
229 |
230 | /**
231 | * @param int $limit
232 | * @return $this
233 | * @throws RepositoryException
234 | */
235 | public function limit($limit = 10)
236 | {
237 | if (!is_numeric($limit) || $limit < 1) {
238 | throw new RepositoryException;
239 | }
240 |
241 | $this->limit = $limit;
242 |
243 | return $this;
244 | }
245 |
246 | /**
247 | * @param $orderBy
248 | * @param string $sort
249 | * @return $this
250 | * @throws RepositoryException
251 | */
252 | public function orderBy($orderBy, $sort = 'DESC')
253 | {
254 | if(! is_array($orderBy)){
255 | if ($orderBy === null)
256 | return $this;
257 |
258 |
259 | if (!in_array(strtoupper($sort), ['DESC', 'ASC'])) {
260 | throw new RepositoryException;
261 | }
262 |
263 | $this->orderBy = [$orderBy .' '. $sort];
264 | }
265 |
266 | else{
267 |
268 | foreach ($orderBy as $field => $method){
269 | if (!in_array(strtoupper($method), ['DESC', 'ASC'])) {
270 | throw new RepositoryException;
271 | }
272 | }
273 |
274 | $this->orderBy = $orderBy;
275 | }
276 |
277 |
278 | return $this;
279 | }
280 |
281 | /**
282 | * @param array $data
283 | * @return mixed
284 | */
285 | public function create(array $data)
286 | {
287 | foreach($data as $key => $value){
288 | $this->model->{$key} = $value;
289 | }
290 |
291 | if($this->model->save()){
292 | return $this->formatEntity($this->model);
293 | }else{
294 | return $this->model->errors;
295 | }
296 | }
297 |
298 |
299 | /**
300 | * @param array $data
301 | * @return mixed|void
302 | * @throws RepositoryException
303 | */
304 | public function createMany(array $data)
305 | {
306 | if(depth($data) < 2){
307 | throw new RepositoryException;
308 | }
309 |
310 | /** @var ActiveRecord $modelClassName */
311 | $modelClassName = get_class($this->model);
312 |
313 | foreach ($data as $record){
314 | /** @var ActiveRecord $model */
315 | $model = new $modelClassName;
316 |
317 | foreach($record as $key => $value){
318 | $model->{$key} = $value;
319 | }
320 |
321 | if(!$model->validate()){
322 | break;
323 | }
324 |
325 | }
326 |
327 | $this->connection->createCommand()
328 | ->batchInsert($modelClassName::collectionName(), $modelClassName->attributes(), $data)->execute();
329 | }
330 |
331 |
332 |
333 |
334 | /**
335 | * @param $id
336 | * @param bool $returnArray
337 | * @return mixed
338 | */
339 | public function findOneById($id, $returnArray = false)
340 | {
341 | $this->initFetch($returnArray, $this->columns, $this->with);
342 |
343 | $entity = $this->query->where([self::PRIMARY_KEY=>$id])->one();
344 |
345 | return $this->formatEntityObject($entity);
346 | }
347 |
348 |
349 | /**
350 | * @param $entity
351 | * @return mixed
352 | */
353 | protected function formatEntityObject($entity)
354 | {
355 | $primaryKey = self::PRIMARY_KEY;
356 | $appKey = self::APPLICATION_KEY;
357 |
358 | if(!empty($entity->{$primaryKey}) ){
359 |
360 | if($entity->{$primaryKey} instanceof ObjectID){
361 | $entity->{$primaryKey} = $entity->{$primaryKey}->__toString();
362 | }
363 |
364 | $entity->{$appKey} = $entity->{$primaryKey};
365 | unset($entity->{$primaryKey});
366 | }
367 |
368 | return $entity;
369 | }
370 |
371 |
372 | /**
373 | * @param $entity
374 | * @return mixed
375 | */
376 | protected function formatEntityArray($entity)
377 | {
378 | if(in_array(self::APPLICATION_KEY, $this->model->attributes())){
379 |
380 |
381 | $entity[self::APPLICATION_KEY] = $entity[self::PRIMARY_KEY];
382 |
383 | if($entity[self::PRIMARY_KEY] instanceof ObjectID){
384 | $entity[self::APPLICATION_KEY] = $entity[self::PRIMARY_KEY]->__toString();
385 | }
386 |
387 | }
388 |
389 | unset($entity[self::PRIMARY_KEY]);
390 |
391 | return $entity;
392 | }
393 |
394 |
395 | /**
396 | * @param $entity
397 | * @return mixed
398 | */
399 | public function formatEntity($entity)
400 | {
401 | if(is_array($entity)){
402 | $model = $this->formatEntityArray($entity);
403 | }else{
404 | $model = $this->formatEntityObject($entity);
405 | }
406 |
407 | return $model;
408 | }
409 |
410 | /**
411 | * @param array $entities
412 | * @return array
413 | */
414 | protected function formatEntities(array $entities)
415 | {
416 | $result = [];
417 |
418 | foreach ($entities as $entity){
419 | if(!in_array(self::APPLICATION_KEY, $this->model->attributes())){
420 |
421 | unset($entity->{self::PRIMARY_KEY});
422 | }
423 | $model = $this->formatEntity($entity);
424 |
425 | $result[] = $model;
426 | }
427 |
428 | return $result;
429 | }
430 |
431 |
432 | /**
433 | * @param $key
434 | * @param $value
435 | * @param string $operation
436 | * @param bool $returnArray
437 | * @return mixed
438 | */
439 | public function findOneBy($key, $value, $operation = '=', $returnArray = false)
440 | {
441 | $this->initFetch($returnArray, $this->columns, $this->with);
442 | $condition = ($operation == '=') ? [$key => $value] : [$operation, $key ,$value];
443 |
444 | return $this->query->where($condition)->one();
445 | }
446 |
447 |
448 | /**
449 | * @param $key
450 | * @param $value
451 | * @param string $operation
452 | * @param bool $withPagination
453 | * @param bool $returnArray
454 | * @return mixed
455 | */
456 | public function findManyBy($key, $value, $operation = '=', $withPagination = true, $returnArray = false)
457 | {
458 | $this->initFetch($returnArray, $this->columns, $this->with);
459 |
460 | $this->query = $this->query->where([$operation, $key , $value])->orderBy($this->orderBy);
461 |
462 | return $withPagination ? $this->paginate() : $this->formatEntity($this->query->all() );
463 | }
464 |
465 | /**
466 | * @param array $ids
467 | * @param bool $withPagination
468 | * @param bool $returnArray
469 | * @return mixed
470 | */
471 | public function findManyByIds(array $ids, $withPagination = true, $returnArray = false)
472 | {
473 | $this->initFetch($returnArray, $this->columns, $this->with);
474 |
475 | $this->query = $this->query->where([self::PRIMARY_KEY=>$ids])->orderBy($this->orderBy);
476 |
477 | return $withPagination ? $this->paginate() : $this->formatEntities($this->query->all() );
478 | }
479 |
480 |
481 | /**
482 | * @param $field
483 | * @param array $values
484 | * @param bool $withPagination
485 | * @param bool $returnArray
486 | * @return array
487 | */
488 | public function findManyWhereIn($field, array $values, $withPagination = true, $returnArray = false)
489 | {
490 | $this->initFetch($returnArray, $this->columns, $this->with);
491 |
492 | $this->query = $this->query->where([$field => $values])->orderBy($this->orderBy);
493 |
494 | return $withPagination ? $this->paginate() : $this->formatEntities($this->query->all() );
495 | }
496 |
497 |
498 |
499 | /**
500 | * @param bool $withPagination
501 | * @param bool $returnArray
502 | * @return mixed
503 | */
504 | public function findAll($withPagination = true, $returnArray = false)
505 | {
506 | $this->initFetch($returnArray, $this->columns, $this->with);
507 |
508 | $this->query = $this->query->orderBy($this->orderBy);
509 |
510 | return $withPagination ? $this->paginate() : $this->formatEntities($this->query->all() );
511 | }
512 |
513 |
514 | /**
515 | * @return array
516 | */
517 | protected function paginate()
518 | {
519 | $response = [];
520 |
521 | $count = $this->query->count();
522 |
523 | $perPage = !empty($_GET['perPage']) ? $_GET['perPage'] : $this->limit;
524 | $currentPage = !empty($_GET['page']) ? $_GET['page'] : 1;
525 | $pagination = new Pagination(['totalCount' => $count,'pageSize' => $perPage ]);
526 |
527 | $result = $this->query
528 | ->offset($pagination->offset)
529 | ->limit($pagination->limit)
530 | ->all();
531 |
532 | $response['items'] = $this->formatEntities($result);
533 | $response['_meta']['totalCount'] = $count;
534 | $response['_meta']['pageCount'] = $pagination->pageCount;
535 | $response['_meta']['currentPage'] = $currentPage;
536 | $response['_meta']['perPage'] = $pagination->limit;
537 |
538 | $response['_links'] = $pagination->getLinks();
539 |
540 | return $response;
541 | }
542 |
543 |
544 | /**
545 | * @param array $criteria
546 | * @param bool $withPagination
547 | * @param array $with
548 | * @param bool $returnArray
549 | * @return mixed
550 | */
551 | public function findManyByCriteria(array $criteria = [], $withPagination = true, $with = [], $returnArray = false)
552 | {
553 | $mainCriteria = [];
554 |
555 | if(depth($criteria) > 1){
556 |
557 | if(count($criteria) > 1 ){
558 | array_unshift($mainCriteria, 'and');
559 | }
560 |
561 | foreach ($criteria as $condition){
562 | if($condition[0] == '='){
563 | array_push($mainCriteria, [$condition[1] => $condition[2]]);
564 | }
565 | else{
566 | array_push($mainCriteria, $condition);
567 | }
568 | }
569 |
570 | }else{
571 | if($criteria[0] == '='){
572 | array_push($mainCriteria, [$criteria[1] => $criteria[2]]);
573 | }else{
574 | $mainCriteria = $criteria;
575 | }
576 | }
577 |
578 |
579 | if(count($mainCriteria) == 1 && depth($mainCriteria) > 1){
580 | $mainCriteria = $mainCriteria[0];
581 | }
582 |
583 | $this->initFetch($returnArray, $this->columns, $this->with);
584 |
585 |
586 | $this->query = $this->query->where($mainCriteria)->orderBy($this->orderBy);
587 |
588 | return $withPagination ? $this->paginate() : $this->formatEntities($this->query->all() );
589 | }
590 |
591 |
592 | /**
593 | * @param ActiveRecord $entity
594 | * @param array $data
595 | * @return ActiveRecord
596 | */
597 | protected function updateEntity(ActiveRecord $entity, array $data)
598 | {
599 | $entity->setAttributes($data);
600 | $entity->save();
601 |
602 | return $entity;
603 | }
604 |
605 |
606 |
607 | /**
608 | * @param $id
609 | * @param array $data
610 | * @return boolean
611 | */
612 | public function updateOneById($id, array $data = [])
613 | {
614 | $entity = $this->makeQuery()->findOne([self::PRIMARY_KEY=>$id]);
615 |
616 | return $this->updateEntity($entity, $data);
617 | }
618 |
619 | /**
620 | * @param $key
621 | * @param $value
622 | * @param array $data
623 | * @return boolean
624 | */
625 | public function updateOneBy($key, $value, array $data = [])
626 | {
627 | if($key == self::APPLICATION_KEY){
628 | $key = self::PRIMARY_KEY;
629 | }
630 |
631 | $entity = $this->makeQuery()->findOne([ $key => $value ]);
632 |
633 | return $this->updateEntity($entity, $data);
634 | }
635 |
636 | /**
637 | * @param array $criteria
638 | * @param array $data
639 | * @return boolean
640 | */
641 | public function updateOneByCriteria(array $criteria, array $data = [])
642 | {
643 | $entity = $this->model->findOne($criteria);
644 |
645 | return $this->updateEntity($entity, $data);
646 | }
647 |
648 | /**
649 | * @param $key
650 | * @param $value
651 | * @param array $data
652 | * @param string $operation
653 | * @return bool
654 | */
655 | public function updateManyBy($key, $value, array $data = [], $operation = '=')
656 | {
657 | if($key == self::APPLICATION_KEY){
658 | $key = self::PRIMARY_KEY;
659 | }
660 |
661 | return $this->model->updateAll($data, [$operation, $key, $value]);
662 | }
663 |
664 | /**
665 | * @param array $criteria
666 | * @param array $data
667 | * @return boolean
668 | */
669 | public function updateManyByCriteria(array $criteria = [], array $data = [])
670 | {
671 | if(depth($criteria) > 1)
672 | array_unshift($criteria, 'and');
673 |
674 | return $this->model->updateAll($data, $criteria);
675 | }
676 |
677 | /**
678 | * @param array $ids
679 | * @param array $data
680 | * @return bool
681 | */
682 | public function updateManyByIds(array $ids, array $data = [])
683 | {
684 | return $this->model->updateAll($data, ['in', self::PRIMARY_KEY, $ids]);
685 | }
686 |
687 | /**
688 | * @param $id
689 | * @return boolean
690 | */
691 | public function deleteOneById($id)
692 | {
693 | $entity = $this->model->findOne([self::PRIMARY_KEY=>$id]);
694 |
695 | return $entity->delete();
696 | }
697 |
698 | /**
699 | * @param array $ids
700 | * @return bool
701 | */
702 | public function allExist(array $ids)
703 | {
704 | // TODO: Implement allExist() method.
705 | }
706 |
707 | /**
708 | * @param $key
709 | * @param $value
710 | * @param string $operation
711 | * @return bool
712 | */
713 | public function deleteOneBy($key, $value, $operation = '=')
714 | {
715 | if($key == self::APPLICATION_KEY){
716 | $key = self::PRIMARY_KEY;
717 | }
718 |
719 | $condition = ($operation == '=') ? [$key => $value] : [$operation, $key ,$value];
720 |
721 | $entity = $this->model->findOne([$condition]);
722 |
723 | return $entity->delete();
724 | }
725 |
726 | /**
727 | * @param array $criteria
728 | * @return boolean
729 | */
730 | public function deleteOneByCriteria(array $criteria = [])
731 | {
732 | $entity = $this->model->findOne($criteria);
733 |
734 | return $entity->delete();
735 | }
736 |
737 | /**
738 | * @param $key
739 | * @param $value
740 | * @param string $operation
741 | * @return bool
742 | */
743 | public function deleteManyBy($key, $value, $operation = '=')
744 | {
745 | if($key == self::APPLICATION_KEY){
746 | $key = self::PRIMARY_KEY;
747 | }
748 |
749 | return $this->model->deleteAll([$operation, $key, $value]);
750 | }
751 |
752 | /**
753 | * @param array $criteria
754 | * @return boolean
755 | */
756 | public function deleteManyByCriteria(array $criteria = [])
757 | {
758 | if(depth($criteria) > 1)
759 | array_unshift($criteria, 'and');
760 |
761 | return $this->model->deleteAll($criteria);
762 | }
763 |
764 | /**
765 | * @return mixed
766 | * @throws RepositoryException
767 | */
768 | public function searchByCriteria()
769 | {
770 | $search = !empty($_GET['search']) ? explode(',',$_GET['search']) : null;
771 |
772 | if(!empty($_GET['fields'])){
773 | $fields = explode(',',$_GET['fields']);
774 | $this->columns($fields);
775 | }
776 |
777 | if(!empty($perPage)){
778 | $this->limit($perPage);
779 | }
780 |
781 | if(!empty($_GET['with'])){
782 | $with = explode(',',$_GET['with']);
783 | $this->with($with);
784 | }
785 |
786 | if(!empty($search)){
787 | $criteria = [];
788 | foreach ($search as $string){
789 | $components = explode(':', $string);
790 |
791 | if( empty($components[0]) || empty($components[1]) || empty($components[2]) ){
792 | throw new RepositoryException('search parameters are not specified correctly.');
793 | }
794 |
795 | if($components[0] == self::APPLICATION_KEY){
796 | $components[0] = self::PRIMARY_KEY;
797 | }
798 |
799 | array_push($criteria ,[$components[1],$components[0],$components[2]]);
800 | }
801 |
802 | return $this->findManyByCriteria($criteria);
803 |
804 | }else{
805 | return $this->findAll();
806 | }
807 |
808 | }
809 |
810 | /**
811 | * @param array $ids
812 | * @return mixed
813 | */
814 | public function deleteManyByIds(array $ids)
815 | {
816 | return $this->model->deleteAll(['in', self::PRIMARY_KEY, $ids]);
817 | }
818 |
819 | /**
820 | * @param $id
821 | * @param $field
822 | * @param int $count
823 | */
824 | public function inc($id, $field, $count = 1)
825 | {
826 | /** @var \yii\db\ActiveRecord $entity */
827 | $entity = $this->query->one([self::PRIMARY_KEY=>$id]);
828 |
829 | $entity->updateCounters([$field => $count]);
830 | }
831 |
832 | /**
833 | * @param $id
834 | * @param $field
835 | * @param $count
836 | */
837 | public function dec($id, $field, $count = 1)
838 | {
839 | /** @var ActiveRecord $entity */
840 | $entity = $this->query->one([self::PRIMARY_KEY=>$id]);
841 |
842 | $entity->updateCounters([$field => $count]);
843 | }
844 | }
845 |
--------------------------------------------------------------------------------
/src/Traits/SqlArRepositoryTrait.php:
--------------------------------------------------------------------------------
1 | findManyBy('title','title5','like');
21 | *
22 | * $posts = $postRepository->findManyBy('title','title5');
23 | *
24 | * $posts = $postRepository->findManyByIds([1,2,3]);
25 | *
26 | * $posts = $postRepository->findManyWhereIn('text',['text1','text2']);
27 | *
28 | * $posts = $postRepository->findManyByCriteria([
29 | * ['like', 'title','title'] , ['=','text','text1']
30 | * ]);
31 | *
32 | * $posts = $postRepository->findOneById(2);
33 | *
34 | * $postRepository->updateOneById(2, ['title'=>'new new']);
35 | *
36 | * $postRepository->updateManyByIds([1,2,3], ['title'=>'new new new']);
37 | *
38 | * $postRepository->updateManyBy('title','salam', ['text'=>'sssssssssss'], 'like');
39 | *
40 | *
41 | * $postRepository->updateManyByCriteria([['like','title','salam'],['like','text','text2']], ['text'=>'salam']);
42 | *
43 | * $postRepository->deleteManyByIds([2,3]);
44 | *
45 | * $postRepository->deleteManyBy('title','title5','like');
46 | *
47 | * $posts = $postRepository->findManyWhereIn('title',['salam','salam2'], false);
48 | *
49 | * trait SqlArRepositoryTrait
50 | * @package mhndev\yii2Repository
51 | */
52 | trait SqlArRepositoryTrait
53 | {
54 | /**
55 | * @var Connection
56 | */
57 | protected $connection;
58 |
59 |
60 | /**
61 | * @var string
62 | */
63 | public $modelClass;
64 |
65 | /**
66 | * @var ActiveRecord
67 | */
68 | protected $model;
69 |
70 | /**
71 | * @var Query
72 | */
73 | protected $query;
74 |
75 | /**
76 | * @var array $data
77 | * query parameters (sort, filters, pagination)
78 | */
79 | protected $data;
80 |
81 | /**
82 | * @var array
83 | */
84 | protected $with = [];
85 |
86 | /**
87 | * @var array
88 | */
89 | protected $columns = ['*'];
90 |
91 | /**
92 | * @var array|string
93 | */
94 | protected $orderBy = [self::PRIMARY_KEY => self::desc];
95 |
96 | /**
97 | * @var int
98 | */
99 | protected $limit = 10;
100 |
101 | /**
102 | * @var int
103 | */
104 | protected $offset = 0;
105 |
106 |
107 | /**
108 | * @throws RepositoryException
109 | */
110 | public function init()
111 | {
112 | if($this->model){
113 | return;
114 | }
115 |
116 | if(empty($this->modelClass)){
117 | throw new RepositoryException('what the f ...');
118 | }
119 |
120 | $this->model = new $this->modelClass;
121 |
122 | $this->columns();
123 |
124 | $this->orderBy(self::PRIMARY_KEY, self::desc);
125 |
126 | $this->connection = \Yii::$app->db;
127 | $this->query = $this->model->find();
128 | }
129 |
130 |
131 | /**
132 | * @return $this
133 | */
134 | protected function initRepositoryParams()
135 | {
136 | $this->columns();
137 | $this->orderBy(self::PRIMARY_KEY, self::desc);
138 |
139 | $this->connection = Yii::$app->db;
140 | $this->query = $this->model->find();
141 |
142 | return $this;
143 | }
144 |
145 | /**
146 | * @param array $with
147 | * @return $this
148 | * @throws RepositoryException
149 | */
150 | public function with(array $with = [])
151 | {
152 | if (is_array($with) === false) {
153 | throw new RepositoryException;
154 | }
155 |
156 | $this->with = $with;
157 |
158 | return $this;
159 | }
160 |
161 | /**
162 | * @param array $columns
163 | * @return $this
164 | * @throws RepositoryException
165 | */
166 | public function columns(array $columns = ['*'])
167 | {
168 | if (is_array($columns) === false) {
169 | throw new RepositoryException;
170 | }
171 |
172 | $this->columns = $columns;
173 |
174 | return $this;
175 | }
176 |
177 |
178 | /**
179 | * @param int $offset
180 | * @return $this
181 | * @throws RepositoryException
182 | */
183 | public function offset($offset = 0)
184 | {
185 | if (!is_numeric($offset) || $offset < 0) {
186 | throw new RepositoryException;
187 | }
188 |
189 | $this->offset = $offset;
190 |
191 | return $this;
192 | }
193 |
194 |
195 | /**
196 | * @param int $limit
197 | * @return $this
198 | * @throws RepositoryException
199 | */
200 | public function limit($limit = 10)
201 | {
202 | if (!is_numeric($limit) || $limit < 1) {
203 | throw new RepositoryException;
204 | }
205 |
206 | $this->limit = $limit;
207 |
208 | return $this;
209 | }
210 |
211 | /**
212 | * @param $orderBy
213 | * @param string $sort
214 | * @return $this
215 | * @throws RepositoryException
216 | */
217 | public function orderBy($orderBy, $sort = 'DESC')
218 | {
219 | if(! is_array($orderBy)){
220 | if ($orderBy === null)
221 | return $this;
222 |
223 |
224 | if (!in_array(strtoupper($sort), ['DESC', 'ASC'])) {
225 | throw new RepositoryException;
226 | }
227 |
228 | $this->orderBy = [$orderBy => 'SORT_'.$sort];
229 | }
230 |
231 | else{
232 |
233 | foreach ($orderBy as $field => $method){
234 | if (!in_array(strtoupper($method), ['DESC', 'ASC'])) {
235 | throw new RepositoryException;
236 | }
237 | }
238 |
239 | $this->orderBy = $orderBy;
240 | }
241 |
242 |
243 | return $this;
244 | }
245 |
246 | /**
247 | * @param array $data
248 | * @return mixed
249 | */
250 | public function create(array $data)
251 | {
252 | $this->model->setAttributes($data);
253 | $this->model->save();
254 |
255 | return $this->model;
256 | }
257 |
258 |
259 | /**
260 | * @param array $data
261 | * @return mixed|void
262 | * @throws RepositoryException
263 | */
264 | public function createMany(array $data)
265 | {
266 | if(depth($data) < 2){
267 | throw new RepositoryException;
268 | }
269 |
270 | $modelClassName = get_class($this->model);
271 |
272 | foreach ($data as $record){
273 | /** @var ActiveRecord $model */
274 | $model = new $modelClassName;
275 |
276 | foreach($record as $key => $value){
277 | $model->{$key} = $value;
278 | }
279 |
280 | if(!$model->validate()){
281 | break;
282 | }
283 |
284 | }
285 |
286 | $this->connection->createCommand()
287 | ->batchInsert($modelClassName::tableName(), $modelClassName->attributes(), $data)->execute();
288 | }
289 |
290 |
291 | /**
292 | * @param $id
293 | * @param bool $returnArray
294 | * @return mixed
295 | */
296 | public function findOneById($id, $returnArray = false)
297 | {
298 | foreach ($this->with as $relation){
299 | $this->query = $this->query->with($relation);
300 | }
301 |
302 | $this->initFetch($returnArray, $this->columns);
303 | return $this->query->where([self::PRIMARY_KEY=>$id])->limit(1)->one();
304 | }
305 |
306 | /**
307 | * @param $key
308 | * @param $value
309 | * @param string $operation
310 | * @param bool $returnArray
311 | * @return mixed
312 | */
313 | public function findOneBy($key, $value, $operation = '=', $returnArray = false)
314 | {
315 | foreach ($this->with as $relation){
316 | $this->query = $this->query->with($relation);
317 | }
318 | $this->initFetch($returnArray, $this->columns);
319 |
320 | return $this->query->where([$operation, $key ,$value])->limit(1)->one();
321 | }
322 |
323 | /**
324 | * @param $key
325 | * @param $value
326 | * @param string $operation
327 | * @param bool $withPagination
328 | * @param bool $returnArray
329 | * @return mixed
330 | */
331 | public function findManyBy($key, $value, $operation = '=', $withPagination = true, $returnArray = false)
332 | {
333 | foreach ($this->with as $relation){
334 | $this->query = $this->query->with($relation);
335 | }
336 |
337 | $this->initFetch($returnArray, $this->columns);
338 | $this->query = $this->query->where([$operation, $key , $value])->orderBy($this->orderBy);
339 |
340 | return $withPagination ? $this->paginate() : $this->query->all();
341 | }
342 |
343 | /**
344 | * @param array $ids
345 | * @param bool $withPagination
346 | * @param bool $returnArray
347 | * @return mixed
348 | */
349 | public function findManyByIds(array $ids, $withPagination = true, $returnArray = false)
350 | {
351 | foreach ($this->with as $relation){
352 | $this->query = $this->query->with($relation);
353 | }
354 |
355 | $this->initFetch($returnArray, $this->columns);
356 | $this->query = $this->query->where([self::PRIMARY_KEY=>$ids])->orderBy($this->orderBy);
357 |
358 | return $withPagination ? $this->paginate() : $this->query->all();
359 | }
360 |
361 |
362 | /**
363 | * @param $field
364 | * @param array $values
365 | * @param bool $withPagination
366 | * @param bool $returnArray
367 | * @return array
368 | */
369 | public function findManyWhereIn($field, array $values, $withPagination = true, $returnArray = false)
370 | {
371 | foreach ($this->with as $relation){
372 | $this->query = $this->query->with($relation);
373 | }
374 |
375 | $this->initFetch($returnArray, $this->columns);
376 | $this->query = $this->query->where([$field => $values])->orderBy($this->orderBy);
377 |
378 | return $withPagination ? $this->paginate() : $this->query->all();
379 | }
380 |
381 |
382 | /**
383 | * @param int $perPage
384 | * @return array
385 | */
386 | protected function paginate($perPage = 10)
387 | {
388 | $response = [];
389 |
390 | $count = $this->query->count();
391 |
392 | $pagination = new Pagination(['totalCount' => $count,'pageSize' => $perPage ]);
393 |
394 |
395 | $result = $this->query
396 | ->offset($pagination->offset)
397 | ->limit($pagination->limit)
398 | ->all();
399 |
400 | $response['items'] = $result;
401 | $response['_meta']['totalCount'] = $count;
402 | $response['_meta']['pageCount'] = floor($count / $pagination->limit )+ 1;
403 | $response['_meta']['currentPage'] = !empty($_GET['page']) ? $_GET['page'] : 1;
404 | $response['_meta']['perPage'] = $pagination->limit;
405 |
406 | $response['_links'] = $pagination->getLinks();
407 |
408 | return $response;
409 | }
410 |
411 |
412 | /**
413 | * @param $returnArray
414 | * @param $columns
415 | */
416 | protected function initFetch($returnArray, $columns)
417 | {
418 | if($columns != ['*']){
419 | $this->query->select($columns);
420 | }
421 |
422 | if($returnArray){
423 | $this->query->asArray();
424 | }
425 | }
426 |
427 | /**
428 | * @param bool $withPagination
429 | * @param bool $returnArray
430 | * @return mixed
431 | */
432 | public function findAll($withPagination = true, $returnArray = false)
433 | {
434 | foreach ($this->with as $relation){
435 | $this->query = $this->query->with($relation);
436 | }
437 |
438 | $this->initFetch($returnArray, $this->columns);
439 |
440 | $this->query = $this->query->orderBy($this->orderBy);
441 |
442 | return $withPagination ? $this->paginate() : $this->query->all();
443 | }
444 |
445 | /**
446 | * @param array $criteria
447 | * @param bool $withPagination
448 | * @param array $with
449 | * @param bool $returnArray
450 | * @return mixed
451 | */
452 | public function findManyByCriteria(array $criteria = [], $withPagination = true, $with = [], $returnArray = false)
453 | {
454 | if(depth($criteria) > 1)
455 | array_unshift($criteria, 'and');
456 |
457 | foreach ($this->with as $relation){
458 | $this->query = $this->query->with($relation);
459 | }
460 |
461 | $this->initFetch($returnArray, $this->columns);
462 | $this->query = $this->query->where($criteria)->orderBy($this->orderBy);
463 |
464 |
465 | return $withPagination ? $this->paginate() : $this->query->all();
466 | }
467 |
468 | /**
469 | * @param $id
470 | * @param $field
471 | * @param int $count
472 | */
473 | public function inc($id, $field, $count = 1)
474 | {
475 | $entity = $this->query->where([self::PRIMARY_KEY=>$id])->one();
476 |
477 | $entity->updateCounters([$field => $count]);
478 | }
479 |
480 | /**
481 | * @param $id
482 | * @param $field
483 | * @param int $count
484 | */
485 | public function dec($id, $field, $count = -1)
486 | {
487 | $entity = $this->query->where([self::PRIMARY_KEY=>$id])->one();
488 |
489 | $entity->updateCounters([$field => $count]);
490 | }
491 |
492 | /**
493 | * @param ActiveRecord $entity
494 | * @param array $data
495 | * @return ActiveRecord
496 | */
497 | protected function updateEntity(ActiveRecord $entity, array $data)
498 | {
499 | $entity->setAttributes($data);
500 | $entity->save();
501 |
502 | return $entity;
503 | }
504 |
505 | /**
506 | * @param $id
507 | * @param array $data
508 | * @return mixed
509 | */
510 | public function updateOneById($id, array $data = [])
511 | {
512 | $entity = $this->query->where([self::PRIMARY_KEY=>$id])->limit(1)->one();
513 |
514 | return $this->updateEntity($entity, $data);
515 |
516 | }
517 |
518 | /**
519 | * @param $key
520 | * @param $value
521 | * @param array $data
522 | * @return mixed
523 | */
524 | public function updateOneBy($key, $value, array $data = [])
525 | {
526 | $entity = $this->query->where([ $key => $value ])->limit(1)->one();
527 |
528 | return $this->updateEntity($entity, $data);
529 |
530 | }
531 |
532 | /**
533 | * @param array $criteria
534 | * @param array $data
535 | * @return mixed
536 | */
537 | public function updateOneByCriteria(array $criteria, array $data = [])
538 | {
539 | $entity = $this->query->where($criteria)->one();
540 |
541 | return $this->updateEntity($entity, $data);
542 | }
543 |
544 |
545 | /**
546 | * @param $key
547 | * @param $value
548 | * @param array $data
549 | * @param string $operation
550 | * @return int number of records updated
551 | */
552 | public function updateManyBy($key, $value, array $data = [], $operation = '=')
553 | {
554 | return $this->model->updateAll($data, [$operation, $key, $value]);
555 | }
556 |
557 | /**
558 | * @param array $criteria
559 | * @param array $data
560 | * @return int number of records updated
561 | */
562 | public function updateManyByCriteria(array $criteria = [], array $data = [])
563 | {
564 | if(depth($criteria) > 1)
565 | array_unshift($criteria, 'and');
566 |
567 | return $this->model->updateAll($data, $criteria);
568 | }
569 |
570 | /**
571 | * @param array $ids
572 | * @param array $data
573 | * @return int number of records updated
574 | */
575 | public function updateManyByIds(array $ids, array $data = [])
576 | {
577 | return $this->model->updateAll($data, ['in', self::PRIMARY_KEY, $ids]);
578 | }
579 |
580 |
581 | /**
582 | * @param array $ids
583 | * @return bool
584 | */
585 | public function allExist(array $ids)
586 | {
587 | // TODO: Implement allExist() method.
588 | }
589 |
590 | /**
591 | * @param $id
592 | * @return boolean|integer number of rows deleted
593 | */
594 | public function deleteOneById($id)
595 | {
596 | $entity = $this->model->findOne([self::PRIMARY_KEY=>$id]);
597 |
598 | return $entity->delete();
599 | }
600 |
601 |
602 | /**
603 | * @param $key
604 | * @param $value
605 | * @param string $operation
606 | * @return bool|int number of rows deleted
607 | */
608 | public function deleteOneBy($key, $value, $operation = '=')
609 | {
610 | $entity = $this->model->findOne([$operation, $key, $value]);
611 |
612 | return $entity->delete();
613 | }
614 |
615 | /**
616 | * @param array $criteria
617 | * @return boolean|integer number of rows deleted
618 | */
619 | public function deleteOneByCriteria(array $criteria = [])
620 | {
621 | $entity = $this->model->findOne($criteria);
622 |
623 | return $entity->delete();
624 | }
625 |
626 | /**
627 | * @param $key
628 | * @param $value
629 | * @param string $operation
630 | * @return bool|int number of rows deleted
631 | */
632 | public function deleteManyBy($key, $value, $operation = '=')
633 | {
634 | return $this->model->deleteAll([$operation, $key, $value]);
635 | }
636 |
637 | /**
638 | * @param array $criteria
639 | * @return boolean|integer number of rows deleted
640 | */
641 | public function deleteManyByCriteria(array $criteria = [])
642 | {
643 | if(depth($criteria) > 1)
644 | array_unshift($criteria, 'and');
645 |
646 | return $this->model->deleteAll($criteria);
647 | }
648 |
649 |
650 |
651 | /**
652 | * @param array $ids
653 | * @return boolean|integer number of rows deleted
654 | */
655 | public function deleteManyByIds(array $ids)
656 | {
657 | return $this->model->deleteAll(['in', self::PRIMARY_KEY, $ids]);
658 | }
659 |
660 |
661 | /**
662 | * @return mixed
663 | */
664 | public function searchByCriteria()
665 | {
666 | $search = !empty($_GET['search']) ? explode(',',$_GET['search']) : null;
667 |
668 | if(!empty($_GET['fields'])){
669 | $fields = explode(',',$_GET['fields']);
670 | $this->columns($fields);
671 | }
672 |
673 | if(!empty($perPage)){
674 | $this->limit($perPage);
675 | }
676 |
677 | if(!empty($_GET['with'])){
678 | $with = explode(',',$_GET['with']);
679 | $this->with($with);
680 | }
681 |
682 |
683 | if(!empty($_GET['perPage'])){
684 | $this->limit($_GET['perPage']);
685 | }
686 |
687 | if(!empty($_GET['page'])){
688 | $this->offset($_GET['page'] * $this->limit);
689 | }
690 |
691 |
692 | if(!empty($search)){
693 | $criteria = [];
694 | foreach ($search as $string){
695 | $components = explode(':', $string);
696 |
697 | array_push($criteria ,[$components[1],$components[0],$components[2]]);
698 | }
699 |
700 | return $this->findManyByCriteria($criteria);
701 |
702 | }else{
703 | return $this->findAll();
704 | }
705 |
706 | }
707 |
708 |
709 | }
710 |
--------------------------------------------------------------------------------
/tests/.gitignore:
--------------------------------------------------------------------------------
1 | !.gitignore
--------------------------------------------------------------------------------