|
9 | 9 |
|
10 | 10 | Implementation of Repository pattern for Laravel (on top of Eloquent)
|
11 | 11 |
|
12 |
| -## Laravel 5.5 |
| 12 | +## Laravel 5.5+ |
13 | 13 |
|
14 | 14 | Install the ```saritasa/laravel-repositories``` package:
|
15 | 15 |
|
16 | 16 | ```bash
|
17 | 17 | $ composer require saritasa/laravel-repositories
|
18 | 18 | ```
|
19 | 19 | ## Configuration
|
20 |
| -### Publish file |
21 |
| -To publish configuration file you can run next command: |
| 20 | +- Publish configuration file: |
| 21 | + |
22 | 22 | ```bash
|
23 | 23 | php artisan vendor:publish --tag=laravel_repositories
|
24 | 24 | ```
|
25 |
| -It will copy file laravel_repositories.php in config directory. |
26 |
| -### Register custom repositories implementaion |
27 |
| -To register your own IRepository impelementaion you can put it into configuration file, like: |
| 25 | + |
| 26 | +- Register custom repositories implementation: |
28 | 27 | ```php
|
29 | 28 | return [
|
30 |
| - 'bindings' => [\App\Models\User::class => \App\Repositories\UserRepository::class,], |
| 29 | + 'bindings' => [ |
| 30 | + \App\Models\User::class => \App\Repositories\UserRepository::class, |
| 31 | + ], |
31 | 32 | ];
|
32 | 33 | ```
|
33 |
| -NOTE: Just remember that default IRepositoryFactory implementation can work only with classes extended from Repository. If you want change this behavior you should add your own implementation. |
34 |
| -## Available classes |
35 |
| - |
36 |
| -### RepositoryFactory |
37 |
| -Base iRepositoryFactory implementation. You can register IRepository implementation to some model. In when you will be getting repository for this model - you will receive this registered object. |
38 |
| - |
39 |
| -**Example** |
40 |
| -```php |
41 |
| - $repositoryFactory = app(IRepositoryFactory::class); |
42 |
| - $repositoryFactory->register(User::class, Repository::class);``` |
43 |
| -*Your repository must implement IRepository contract and receive string $modelClass in constructor.* |
44 |
| - |
45 |
| -### Repository |
46 |
| -Repository class implements **IRepository** interface. Contains helper methods to build query for SQL-like storages. |
47 |
| -Has protected method to join tables by Eloquent model relation name. |
48 |
| -Supported relations are: **BelongsToMany**, **HasOne**, **HasMany**, **BelongsTo** |
49 |
| -Nested relations supported. |
50 |
| - |
51 |
| -**Example** |
52 |
| - |
53 |
| -For method |
54 |
| - |
55 |
| -```php |
56 |
| -public function getUsersList(): Collection |
57 |
| -{ |
58 |
| - $query = $this->query(); |
59 |
| - $this->joinRelation($query, ['role', 'profile', 'cars', 'profile.phones']); |
60 |
| - return $query;} |
| 34 | +*Note: Your custom repository must implement `IRepository` contract.* |
| 35 | + |
| 36 | +## Getting repository inside your code |
| 37 | +To get specific repository in your code you can just build with DI container repositories factory and then |
| 38 | +build needed for your repository in this factory. |
| 39 | + **Example:** |
| 40 | +```php |
| 41 | + $repositoryFactory = app(\Saritasa\LaravelRepositories\Repositories\IRepositoryFactory::class); |
| 42 | + $userRepository = $repositoryFactory->getRepository(\App\Models\User::class); |
| 43 | +``` |
| 44 | +## Filtering results with repository |
| 45 | +Methods findWhere/getWhere/getWith/getPage/getCursorPage/count/ can receive criteria as params |
| 46 | +Here the examples of available syntax: |
| 47 | +- Criterion without operator: |
| 48 | +```php |
| 49 | + $criteria = [ |
| 50 | + 'field1' => 'value1', |
| 51 | + 'field2' => 1, |
| 52 | + ]; |
61 | 53 | ```
|
62 |
| - |
63 |
| -result query will be |
64 |
| - |
65 |
| -```SQL |
66 |
| -SELECT * |
67 |
| -FROM "users" |
68 |
| - LEFT JOIN "roles" ON "users"."role_id" = "roles"."id" LEFT JOIN "profiles" ON "profiles"."user_id" = "users"."id" LEFT JOIN "cars" ON "cars"."user_id" = "users"."id" LEFT JOIN "phones" ON "phones"."profile_id" = "profiles"."id"``` |
69 |
| -**Repository** has **getWith()** method that allows to retrieve list of entities with |
| 54 | +*In this case `=` operator and `and` boolean between them will be used.* |
| 55 | +**Example:** `... 'field1 = 'value1' and 'field2' = 1 ...` |
| 56 | +- Criterion with operator: |
| 57 | +```php |
| 58 | + $criteria = [ |
| 59 | + ['field1', '<>', 'value1'], |
| 60 | + ['field2', '>', 1, 'or'], |
| 61 | + ['field3', 'in', [1, 2]], |
| 62 | + ['field4', 'not in', new \Illuminate\Support\Collection([1, 2])], |
| 63 | + ]; |
| 64 | +``` |
| 65 | +**`Important:` arrays and collection can be used only with `in` and `not in` operators.** |
| 66 | +*Note: As 4th parameter you can pass boolean `or`/`and` (`and` uses by default). |
| 67 | +But you should remember that boolean used between current and previous criterion* |
| 68 | +**Example:** `... 'field1 <> 'value1' or 'field2' > 1 and 'field3' in (1, 2) and 'field4' not in (1, 2) ...` |
| 69 | +- Criterion as DTO: |
| 70 | +```php |
| 71 | + $criteria = [ |
| 72 | + new Criterion([ |
| 73 | + Criterion::OPERATOR => '<>', |
| 74 | + Criterion::VALUE => 'value1', |
| 75 | + Criterion::ATTRIBUTE => 'field1', |
| 76 | + ]), |
| 77 | + new Criterion([ |
| 78 | + Criterion::OPERATOR => '>', |
| 79 | + Criterion::VALUE => 1, |
| 80 | + Criterion::ATTRIBUTE => 'field2', |
| 81 | + Criterion::BOOLEAN => 'or', |
| 82 | + ]), |
| 83 | + new Criterion([ |
| 84 | + Criterion::OPERATOR => 'in', |
| 85 | + Criterion::VALUE => [1, 2], |
| 86 | + Criterion::ATTRIBUTE => 'field3', |
| 87 | + ]), |
| 88 | + new Criterion([ |
| 89 | + Criterion::OPERATOR => 'not in', |
| 90 | + Criterion::VALUE => [1, 2], |
| 91 | + Criterion::ATTRIBUTE => 'field4', |
| 92 | + ]), |
| 93 | + ]; |
| 94 | +``` |
| 95 | +Result will be the same as in previous example. |
| 96 | +- Nested criteria: |
| 97 | +You can group different conditions that gives flexibility in getting data from repository |
| 98 | +```php |
| 99 | + $criteria = [ |
| 100 | + [ |
| 101 | + ['field1', '<>', 'value1'], |
| 102 | + ['field2', '>', 1, 'or'], |
| 103 | + ], |
| 104 | + [ |
| 105 | + ['field3', 'in', [1, 2]], |
| 106 | + ['field4', 'not in', [1, 2], |
| 107 | + 'boolean' => 'or', |
| 108 | + ], |
| 109 | + ]; |
| 110 | +``` |
| 111 | +*Note: you can add nesting level in any depth what you want. To use `or` condition between one group |
| 112 | +and other(group and non-group condition) you can pass 'boolean' parameter in the same level as other conditions.* |
| 113 | + |
| 114 | +**Example:**`... ('field1 <> 'value1' or 'field2' > 1) or ('field3' in (1, 2) and 'field4' not in (1, 2)) ...` |
| 115 | +## Preload model relations |
| 116 | +Method **getWith()** method allows to retrieve list of entities with |
70 | 117 | eager loaded related models and related models counts. Also allows to filter this list by given criteria
|
71 | 118 | and sort in requested order.
|
72 | 119 |
|
73 | 120 | **Example**:
|
74 | 121 | ```php
|
75 |
| -$usersRepository->getWith(['role', 'supervisors'], ['phones'], [['age', '>', 21]], $sortOptions) |
76 |
| - |
77 |
| -// Retrieves list of users which age greater than 21. // Each user will be retrieved with pre-loaded role and supervisors models. |
78 |
| -// List of users will be ordered by requested sort options (SortOptions::class object) |
| 122 | +$usersRepository->getWith( |
| 123 | + ['role', 'supervisors'], |
| 124 | + ['phones'], |
| 125 | + [], |
| 126 | + new Saritasa\LaravelRepositories\DTO\SortOptions('name', 'DESC') |
| 127 | +); |
79 | 128 | ```
|
| 129 | +- Each user will be retrieved with pre-loaded role and supervisors models. |
| 130 | +- Each user will be retrieved with pre-loaded phones relation count. |
| 131 | +- List of users will be ordered by requested sort options. |
80 | 132 |
|
81 |
| -### SortOptions |
82 |
| -DTO that allows to pass sort options to repository. Contains sort order field |
83 |
| -and sort order direction that should be one of **OrderDirections** enum value. |
84 |
| - |
85 |
| -## Exceptions |
| 133 | +## Exceptions |
86 | 134 | ### Repository Exception
|
87 |
| -Base exception for repository layer. |
| 135 | +Base exception for repository layer. |
| 136 | +### Repository register exception |
| 137 | +Throws when can not register custom repository. |
88 | 138 | ### Model not found Exception
|
89 | 139 | Throws in case when some model not exists in storage.
|
90 |
| - |
91 |
| -**Example**: |
92 |
| -```php |
93 |
| -function findWhere(array $fieldValues) { |
94 |
| - if (!count($fieldValues)) { new RepositoryException($this, "No search criteria provided"); } // ...} |
95 |
| -``` |
96 |
| - |
| 140 | +### Bad Criteria Exception |
| 141 | +Throws when provided criteria has incorrect format at least in one criterion inside. |
| 142 | + |
97 | 143 | ## Contributing
|
98 | 144 |
|
99 | 145 | 1. Create fork, checkout it
|
|
0 commit comments