Skip to content

Commit 8acfd5c

Browse files
committed
init
1 parent 4b60f51 commit 8acfd5c

35 files changed

+1642
-3651
lines changed

Readme.md

Lines changed: 286 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,80 +1,322 @@
1-
## Installation
1+
# Laravel API tool kit and best API practices
2+
3+
Laravel api tool kit is a set of tools that will help you to build a fast and well-organized API using laravel best practices.
4+
5+
## Contents
6+
7+
[Installation](#installation)
8+
9+
[Api Generator module](#api-generator-module)
10+
11+
[Api response](#api-response)
12+
13+
[Filters](#filters)
14+
15+
[comment]: <> ([Out of the box permissions]&#40;#out-of-the-box-permissions&#41;)
16+
17+
[Actions](#actions)
18+
19+
[Media Helper](#media-helper)
20+
21+
[Enum](#enum)
22+
23+
[General tips](#general-tips)
24+
25+
26+
### **Installation**
27+
28+
```
29+
composer require essa/api-tool-kit
230
```
3-
composer require essa/api_generator:dev-master
31+
to publish config
32+
```
33+
php artisan vendor:publish --provider="essa\APIToolKit\APIToolKitServiceProvider" --tag="config"
434
```
535

36+
use exception handler to standardize the error response
637

38+
```php
739

8-
### Exceptions:
40+
namespace App\Exceptions;
941

10-
`App\Providers\Handler.php`:
42+
use essa\APIToolKit\Exceptions\Handler;
43+
use essa\APIToolKit\Exceptions\Handler as APIHandler;
1144

12-
```php
45+
class Handler extends ExceptionHandler
46+
{
47+
}
1348

49+
```
1450

51+
use API Response Trait in Controller
1552

16-
use Throwable;
17-
use essa\APIGenerator\Http\ApiResponse;
18-
use Illuminate\Database\QueryException;
19-
use Illuminate\Validation\ValidationException;
20-
use Illuminate\Auth\Access\AuthorizationException;
21-
use Illuminate\Database\Eloquent\ModelNotFoundException;
53+
`App\Http\Controllers\Controller.php`:
2254

23-
class Handler extends ExceptionHandler
55+
```php
56+
use essa\APIToolKit\Http\ApiResponse;
57+
58+
class Controller extends BaseController
2459
{
2560
use ApiResponse;
26-
27-
/**
28-
* Render an exception into an HTTP response.
29-
*
30-
* @param \Illuminate\Http\Request $request
31-
* @param \Throwable $exception
32-
* @return \Illuminate\Http\JsonResponse|\Illuminate\Http\Response|\Symfony\Component\HttpFoundation\Response
33-
* @throws \Throwable
34-
*/
35-
public function render($request, Throwable $exception)
36-
{
37-
if ($exception instanceof ValidationException) {
38-
return $this->ResponseValidationError($exception);
39-
}
61+
}
62+
```
63+
check : [API response](#api-response)
64+
65+
[🔝 Back to contents](#contents)
66+
67+
### **API Generator module**
4068

41-
if ($exception instanceof QueryException || $exception instanceof ModelNotFoundException) {
42-
return $this->responseNotFound("Record not found!", $exception->getMessage());
43-
}
69+
#### Usage :
4470

45-
if ($exception instanceof AuthorizationException) {
46-
return $this->responseUnauthorized();
47-
}
71+
```
72+
php artisan api:generate Car
73+
```
74+
75+
if you write the command it will ask you if you want to generate all default options which you can select in config/api-tool-kit file if you decide not to change the default option and decide to select all option it will generate the following files :
76+
```
77+
-app/Models/Car.php
78+
-app/Http/Controllers/API/CarController.php
79+
-app/Http/Resources/CarResource.php
80+
-app/Http/Requests/Car/CreateCarRequest.php
81+
-app/Http/Requests/Car/UpdateCarRequest.php
82+
-app/Filters/CarFilters.php
83+
-database/seeds/CarSeeder.php
84+
-database/factories/CarFactory.php
85+
-Tests/Feature/CarTest.php
86+
-database/migrations/x_x_x_x_create_cars_table.php
87+
```
88+
and will create api.php in routes file and will add the routes to it
89+
90+
if you choose not to select all options it will ask you which files you want to generate
91+
92+
[🔝 Back to contents](#contents)
93+
94+
### **API Response**
95+
96+
it is used to format your response to standard format and status codes
97+
for success responses, it will be
4898

49-
return parent::render($request, $exception);
99+
```json
100+
{
101+
"message": "your message",
102+
"data": "your date"
103+
}
104+
```
105+
for errors responses
106+
107+
```json
108+
{
109+
"errors": [
110+
{
111+
"status": 403,
112+
"title": "unauthenticated!",
113+
"detail": "Unauthenticated."
50114
}
115+
]
51116
}
117+
```
118+
119+
usage:
120+
you can use the trait inside the class you want to return the response form
52121

122+
and use it like this
53123

124+
```php
125+
$this->responseSuccess('car created successfully' , $car);
54126
```
55-
56-
### Controller:
127+
Available Methods
128+
```php
57129

58-
`App\Http\Controllers\Controller.php`:
130+
responseSuccess($message , $data) // returns a 200 HTTP status code
131+
responseCreated($message,$data) // returns a 201 HTTP status code
132+
responseDeleted() // returns empty response with a 204 HTTP status code
133+
responseNotFound($details,$message) // returns a 404 HTTP status code
134+
responseBadRequest($details,$message) // returns a 400 HTTP status code
135+
responseUnAuthorized($details,$message) // returns a 403 HTTP status code
136+
responseConflictError($details,$message) // returns a 409 HTTP status code
137+
responseUnprocessable($details,$message) // returns a 422 HTTP status code
138+
responseUnAuthenticated ($details,$message) // returns a 401 HTTP status code
139+
responseWithCustomError($title, $details, $status_code) //send custom error
140+
```
141+
[🔝 Back to contents](#contents)
142+
143+
### **Filters**
144+
145+
usage:
146+
147+
to create a filter class:
148+
```
149+
php artisan make:action CarFilters
150+
```
151+
to set default filters to the Car model , in Car model you will add
152+
```php
153+
protected $default_filters = CarFilters::class;
154+
```
155+
to use it
156+
157+
```php
158+
Car::useFilters()->get();
159+
```
160+
if you want to override the default filters
59161

60162
```php
61-
use essa\APIGenerator\Http\ApiResponse;
163+
Car::useFilters(SpecialCaseCarFilters::class)->get();
164+
```
165+
options in Filter class
62166

63-
class Controller extends BaseController
167+
```php
168+
//to add the attributes to filter by =>> /cars?color=red&model_id=1
169+
protected array $allowedFilters = ['color' , 'model_id'];
170+
//to add the attributes to filter by =>> desc : ?sorts=created_at asc : ?sorts=-created_at
171+
protected array $allowedSorts = ['created_at'];
172+
//allowed relationships to be loaded
173+
protected array $allowedIncludes = ['model'];
174+
//column that will be included in search =>> ?search=tesla
175+
protected array $columnSearch = ['name','descriptions'];
176+
//relation that will be included in search =>> ?search=ahmed
177+
protected array $relationSearch = [
178+
'user' => ['first_name', 'last_name']
179+
];
180+
```
181+
182+
to create a custom query you will just create a new function in the class and add your query
183+
example filter by year:
184+
```php
185+
public function year($term)
186+
{
187+
$this->builder->whereYear('created_At', $term);
188+
}
189+
```
190+
filter by relationship :
191+
```php
192+
public function option($term)
193+
{
194+
$this->builder->whereHas('options', fn($query) => $query->where('option_id', $term));
195+
}
196+
```
197+
198+
199+
[🔝 Back to contents](#contents)
200+
201+
### **Actions**
202+
action is a laravel implementation of command design pattern where can add the business logic in https://en.wikipedia.org/wiki/Command_pattern
203+
204+
usage:
205+
206+
```
207+
php artisan make:action CreateCar
208+
```
209+
210+
```php
211+
<?php
212+
namespace App\Actions;
213+
214+
class CreateCar
64215
{
65-
use ApiResponse;
216+
public function execute(array $data)
217+
{
218+
//add business logic to create a car
219+
}
66220
}
67221
```
68222

223+
The best practice to use the action class is to use dependency injection
224+
you have many options
225+
1-use laravel app class
226+
```php
227+
app(CreateCar::class)->execute($data);
228+
```
229+
2-inject it in class construct
69230

231+
```php
232+
private $create_car_action ;
233+
public function __construct(CreateCar $create_car_action)
234+
{
235+
$this->create_car_action=$create_car_action;
236+
}
237+
238+
public function doSomething()
239+
{
240+
$this->create_car_action->execute($data);
241+
}
242+
```
243+
3-use it in laravel controller function
70244

71-
## Usage
245+
```php
246+
public function doSomething(CreateCar $create_car_action)
247+
{
248+
$create_car_action->execute($data);
249+
}
250+
```
251+
[🔝 Back to contents](#contents)
252+
253+
254+
### **Media Helper**
255+
256+
it is used to upload and delete an image
257+
258+
```php
259+
// to upload image
260+
$image_path = MediaHelper::uploadImage($file ,$path);
261+
//to delete an image
262+
MediaHelper::deleteImage($path); //to delete image
263+
```
264+
Available Methods
265+
266+
[🔝 Back to contents](#contents)
267+
268+
### **Enum
269+
bad practice :
270+
if I have two types of users admin and student instead of hard coding the name of user type every time using it you can simply use the enum class
271+
272+
usage :
273+
```
274+
php artisan make:enum UserTypes
275+
```
276+
it will generate classes like this
277+
```php
278+
namespace App\Enums;
72279

73-
Create component
280+
class UserTypes extends Enum
281+
{
282+
public const ADMIN = 'admin';
283+
public const STUDENT = 'student';
284+
}
285+
```
286+
methods:
287+
```php
288+
getAll() //get all types
289+
isValid($value) //to check if this value exist in the enum
290+
toArray() //to get all enums as key and value
74291
```
75-
php artisan make:module Admin
292+
293+
[🔝 Back to contents](#contents)
294+
295+
### **General Tips**
296+
297+
### **throw error instead of return json response**
298+
299+
A class and a method should have only one responsibility.
300+
301+
Bad:
302+
303+
```php
304+
public function index()
305+
{
306+
if (auth()->user()->not_active ) {
307+
$this->responseUnAuthorized('you cant preform this action'');
308+
}
309+
}
76310
```
311+
good
77312

313+
```php
314+
public function index()
315+
{
316+
if (auth()->user()->not_active ) {
317+
throw new AuthorizationException('you cant preform this action'');
318+
}
319+
}
78320
```
79-
php artisan make:module Admin --with-image
80-
```
321+
322+
[🔝 Back to contents](#contents)

0 commit comments

Comments
 (0)