Skip to content

Commit f0624a1

Browse files
Md. Touhidur RahmanMd. Touhidur Rahman
authored andcommitted
initial commit
0 parents  commit f0624a1

28 files changed

+2133
-0
lines changed

.gitattributes

Whitespace-only changes.

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
.DS_Store
2+
/vendor
3+
/build
4+
composer.lock
5+
.phpunit.result.cache

.travis.yml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
language: php
2+
3+
php:
4+
- 7.3
5+
- 7.4
6+
- 8.0
7+
8+
env:
9+
matrix:
10+
- COMPOSER_FLAGS="--prefer-lowest"
11+
- COMPOSER_FLAGS=""
12+
13+
before_script:
14+
- travis_retry composer update ${COMPOSER_FLAGS}
15+
16+
script:
17+
- vendor/bin/phpunit

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Changelog
2+
All notable changes to this project will be documented in this file.
3+
4+
## [Unreleased]
5+
6+
7+
## [1.0.0] - 2021-08-21
8+
- Initial release

LICENSE.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) Touhidur Rahman Abir
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 318 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,318 @@
1+
# Laravel Model UUID
2+
3+
A simple package to use **Repository Pattern** approach for laravel models .
4+
5+
## Repository pattern
6+
Repositories are classes or components that encapsulate the logic required to access data sources. They centralize common data access functionality, providing better maintainability and decoupling the infrastructure or technology used to access databases from the domain model layer. [Microsoft](https://docs.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/infrastructure-persistence-layer-design)
7+
8+
## Installation
9+
10+
Require the package using composer:
11+
12+
```bash
13+
composer require touhidurabir/laravel-model-repository
14+
```
15+
16+
To publish the config file:
17+
```bash
18+
php artisan vendor:publish --provider="Touhidurabir\ModelRepository\ModelRepositoryServiceProvider" --tag=config
19+
```
20+
21+
## Command and Configuration
22+
23+
To use this package, you need to have repository class bound to laravel model class . This package includes a command that make it easy to to create repository classes from command line . to create a new repository class, run the following command
24+
25+
```bash
26+
php artisan make:repository UserRepository --model=User
27+
```
28+
29+
The above command will create a new repository **UserRepository** class in **App\Repositories** path . the **--model** option to define which laravel model class to target for this repositoty class . The content of **UserRepository** will look like
30+
31+
```php
32+
namespace App\Repositories;
33+
34+
use Touhidurabir\ModelRepository\BaseRepository;
35+
use App\Models\User;
36+
37+
class UserRepository extends BaseRepository {
38+
39+
/**
40+
* Constructor to bind model to repo
41+
*
42+
* @param object<App\Models\User> $user
43+
* @return void
44+
*/
45+
public function __construct(User $user) {
46+
47+
$this->model = $user;
48+
49+
$this->modelClass = get_class($user);
50+
}
51+
52+
}
53+
```
54+
55+
This package by default assume all **models** are located in path **App\Models** and use the path **App\Repositories** to store the **repository** classes. But also possible to provide custom repositories class path and different model class path . for example
56+
57+
```bash
58+
php artisan make:reposity App\\SomeOtherPath\\UserRepository --model=App\\OtherModelPath\\User
59+
```
60+
The above command will try to store the repository class to path **App\SomeOtherPath** and will create a directory named **SomeOtherPath** if not already exists. Will also try to resolve model path/namespace from **App\OtherModelPath** .
61+
62+
Check the **config** file after publishing at the **config/model-repository.php** to see the default settings configurations .
63+
64+
## Usage
65+
66+
The best way to use the repository classes via **Dependency Injection** through the **controller** classes . for example :
67+
68+
```php
69+
namespace App\Http\Controllers;
70+
71+
use App\Http\Controllers\Controller;
72+
use App\Repositories\UserRepository;
73+
74+
class UserController extends Controller {
75+
76+
/**
77+
* The resource repository instance
78+
*
79+
* @var mixed<object{\App\Repositories\UserRepository}|null>
80+
*/
81+
protected $userRepository;
82+
83+
/**
84+
* create a new controller instance
85+
*
86+
* @param \App\Repositories\UserRepository $userRepository
87+
* @return void
88+
*/
89+
public function __construct(UserRepository $userRepository) {
90+
91+
$this->userRepository = $userRepository;
92+
}
93+
}
94+
```
95+
96+
And in that way one can already get a fully qualified user repository class . Also to manually initiated :
97+
98+
```php
99+
namespace App\Http\Controllers;
100+
101+
use App\Models\User;
102+
use App\Http\Controllers\Controller;
103+
use App\Repositories\UserRepository;
104+
...
105+
106+
$userRepository = new UserRepository(new User);
107+
```
108+
109+
Or through static constructor
110+
```php
111+
$userRepository = UserRepository::withModel(new User);
112+
```
113+
114+
The repository class will have following features/abilities .
115+
116+
### Create
117+
118+
To create a new model record, just call the **create** method on repositoty class and pass the data attributes as :
119+
120+
```php
121+
$this->userRepository->create([
122+
...
123+
]);
124+
```
125+
126+
### Update
127+
128+
To update a existing model record, call the **update** method of the repository class . the **update** method will require 2 params , the data attributes and the model redored primary key value or an exiting model instance .
129+
130+
To update with primary key for user with primary key of id with value 10
131+
132+
```php
133+
$primaryKeyValue = 10;
134+
135+
$this->userRepository->update([
136+
...
137+
], $primaryKeyValue);
138+
```
139+
or To update the already retrived model record :
140+
141+
```php
142+
$user; // the already retrived model record instance
143+
144+
$this->userRepository->update([
145+
...
146+
], $user);
147+
```
148+
149+
### Find
150+
151+
To find a model record, use the **find** method of the repository class
152+
153+
```php
154+
$this->userRepository->find(1); // find the id(primary key) of 1
155+
$this->userRepository->find([1,2,3]); // find the id(primary key) of 1,2 and 3
156+
```
157+
158+
The **find** method can also work with array where it will use those as **AND WHERE** query and return the first record that match
159+
160+
```php
161+
$this->userRepository->find(['email' => 'somemail@mail.test']);
162+
```
163+
164+
By passing the optional relations array as the second argument to **find** method will load the relations along with model record
165+
166+
```php
167+
$this->userRepository->find(1, ['profile']); // find the id(primary key) of 1
168+
$this->userRepository->find([1,2,3], ['profile']); // find the id(primary key) of 1,2 and 3
169+
```
170+
171+
The thrid agument is a optional boolen which is by default set to **false** . By setting it to **true**, it will thorw the **\Illuminate\Database\Eloquent\ModelNotFoundException** when a model record not found .
172+
173+
```php
174+
$this->userRepository->find(1, ['profile'], true); // find the id(primary key) of 1
175+
$this->userRepository->find([1,2,3], [], true); // find the id(primary key) of 1,2 and 3
176+
```
177+
178+
### All Records
179+
180+
To get back all records, use the **all** method of repository class
181+
182+
```php
183+
$this->userRepository->all();
184+
```
185+
186+
### Delete
187+
188+
To Delete a model record, use the **delete** method of repository class
189+
190+
```php
191+
$this->userRepository->delete(1);
192+
```
193+
194+
The **delete** method can wrok with model instance or the same kind of argument passed to the repository class **find** method .
195+
196+
```php
197+
$this->userRepository->delete($user); // delete the alredt retrived $user model instance
198+
$this->userRepository->delete(1); // delete user id of 1
199+
$this->userRepository->delete([1,2,3]); // delete user id of 1,2 and 3
200+
$this->userRepository->delete(['email' => 'somemail@mail.test']); // delete user with email of somemail@mail.test
201+
```
202+
203+
The **delete** method also check for the **SoftDelete** feature , that is if the model is using the **Illuminate\Database\Eloquent\SoftDeletes** trait, the it will do the soft delete of given model records.
204+
205+
### Force Delete
206+
207+
To Force Delete a model record, use the **forceDelete** method of repository class
208+
209+
```php
210+
$this->userRepository->forceDelete(1);
211+
```
212+
213+
The **delete** method can wrok with model instance or the same kind of argument passed to the repository class **find** method .
214+
215+
```php
216+
$this->userRepository->forceDelete($user); // delete the alredt retrived $user model instance
217+
$this->userRepository->forceDelete(1); // delete user id of 1
218+
$this->userRepository->forceDelete([1,2,3]); // delete user id of 1,2 and 3
219+
$this->userRepository->forceDelete(['email' => 'somemail@mail.test']); // delete user with email of somemail@mail.test
220+
```
221+
222+
The **delete** method also check for the **SoftDelete** feature, that is regardless of the model is using the **Illuminate\Database\Eloquent\SoftDeletes** trait, the it will remove those records from DB.
223+
224+
### Restore
225+
226+
To Restore a model record that has soft deleted, use the **forceDelete** method of repository class
227+
228+
```php
229+
$this->userRepository->restore(1);
230+
```
231+
232+
The **restore** will only works for those models that use the **SoftDeletes** feature . It try to use the restore on the model that do not have **SoftDeletes** implemented, it will throw an exception.
233+
234+
The **restore** method can wrok with model instance or array of model primary keys .
235+
236+
```php
237+
$this->userRepository->restore($user); // restore the already retrived $user model instance
238+
$this->userRepository->restore(1); // restore user id of 1
239+
$this->userRepository->restore([1,2,3]); // restore user id of 1,2 and 3test
240+
```
241+
242+
## Other Features
243+
244+
### Get Model
245+
246+
As this package does not handle all of the features of Eloquent and if any other Eloquent method need to use to build complex query, we need the model instance . to get the model instance
247+
248+
```php
249+
$this->userRepository->getModel();
250+
```
251+
252+
Also to set/update the model later
253+
254+
```php
255+
$this->userRepository->setModel(new User);
256+
$this->userRepository->setModel($user);
257+
```
258+
259+
### Model Sanitizer
260+
261+
The BaseRepository class includes a model sanitizer that will automatically sanitize passed array attributes on model record create/update . Here sanatize means it will remove any element from the data array to match with the model table schema while at the same time respecting model **$fillable** and **$hidden** properties .
262+
263+
The implementation of these methods are as such
264+
265+
```php
266+
/**
267+
* Sanitize data list to model fillables
268+
*
269+
* @param array $data
270+
* @return array
271+
*/
272+
public function sanitizeToModelFillable(array $data) {
273+
274+
$classModel = $this->model->getModel();
275+
$fillable = $classModel->getFillable();
276+
277+
$fillables = ! empty($fillable)
278+
? $fillable
279+
: array_diff(
280+
array_diff(
281+
Schema::getColumnListing($classModel->getTable()),
282+
$classModel->getGuarded()
283+
),
284+
$classModel->getHidden()
285+
);
286+
287+
return array_intersect_key($data, array_flip($fillables));
288+
}
289+
```
290+
291+
So even if extra details passed, it will be ignored or some columns passed that in the **$fillable** or **$hidden** list.
292+
293+
```php
294+
$user = $this->userRepository->create([
295+
'name' => 'User Name',
296+
'email' => 'somemail@mail.test',
297+
'password' => Hash::make('password'),
298+
'date_of_birth' => '1990-12-08' // This date_of_birth column not present in users table
299+
]);
300+
```
301+
302+
The above code will run without any issue while a simple model create method will throw exception .
303+
304+
```php
305+
$user = $this->userRepository->create($request->validated());
306+
307+
$profile = $this->profileRepository->create($request->validated());
308+
```
309+
310+
This become very useful when in one single controller method do need to push data to multiple model table
311+
312+
## Contributing
313+
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
314+
315+
Please make sure to update tests as appropriate.
316+
317+
## License
318+
[MIT](./LICENSE.md)

0 commit comments

Comments
 (0)