API REST en Laravel en 100 l铆neas de c贸digo

inb4: copie y pegue de la documentaci贸n


La gu铆a se enfoca en el despliegue r谩pido de un conjunto m铆nimo para el desarrollo completo de API de acuerdo con las mejores pr谩cticas, tomado de la documentaci贸n de Laravel 5.7, reunido en un solo lugar. Escrib铆 para m铆 y mis colegas como una hoja de trucos, espero que sea 煤til para otra persona.


Preestablecido


Ponemos un marco


composer create-project --prefer-dist laravel/laravel scaffold-api


Eliminar componentes innecesarios de la interfaz de usuario (vuejs, reaccionar)


php artisan preset none


Configurar conexi贸n de base de datos


Vaya a la carpeta, edite el archivo .env:


 DB_CONNECTION=mysql DB_HOST=localhost DB_PORT=3306 DB_DATABASE=api-authentification DB_USERNAME=root DB_PASSWORD= 

Comenzando a generar


Ejecutamos en la consola
php artisan make:model Game -mrc


Obtenemos el modelo, la migraci贸n y el controlador:


 Model created successfully. Factory created successfully. Created Migration: 2019_02_27_105610_create_games_table Controller created successfully. 

Crear columnas en la tabla de la base de datos.


Corregimos la migraci贸n agregando columnas a la tabla. Tipos m谩s utilizados:


  • increments('id')
  • string('title')
  • text('description')
  • tinyInteger('complexity')
  • boolean('isActive')
  • softDeletes()

Para campos opcionales, no olvide agregar el valor predeterminado con ->default()


Aplicar migraciones ejecutando php artisan migrate


Generamos reglas de validaci贸n.


Ejecutando php artisan make:request GameRequest


Abra la App/Http/Requests/GameRequest.php .
En el m茅todo authorize() , establezca return true hasta que agreguemos autorizaci贸n.
La matriz que se devuelve en el m茅todo rules() describe las reglas para todas las columnas que enumeramos en la migraci贸n. Reglas disponibles aqu铆


Para minimizar el c贸digo, usamos la construcci贸n del interruptor para diferentes verbos http, en lugar de hacer StoreGameRequest, UpdateGameRequest, etc.


 public function rules(Request $request) { $rules = [ 'title' => 'required|string|unique:games,title', 'description' => '', 'complexity' => 'required|min:1|max:10', 'minPlayers' => 'required|min:1|max:10', 'maxPlayers' => 'required|min:1|max:10', 'isActive' => 'required|boolean' ]; switch ($this->getMethod()) { case 'POST': return $rules; case 'PUT': return [ 'game_id' => 'required|integer|exists:games,id', // .   : unique:games,id,' . $this->route('game'), 'title' => [ 'required', Rule::unique('games')->ignore($this->title, 'title') //  ,     ] ] + $rules; //      // case 'PATCH': case 'DELETE': return [ 'game_id' => 'required|integer|exists:games,id' ]; } } 

Opciones de descripci贸n de error personalizado


Si necesita sus propios textos de error, redefinimos el m茅todo de mensajes (), que devuelve una matriz con traducciones de cada regla:


 public function messages() { return [ 'date.required' => 'A date is required', 'date.date_format' => 'A date must be in format: Ym-d', 'date.unique' => 'This date is already taken', 'date.after_or_equal' => 'A date must be after or equal today', 'date.exists' => 'This date doesn\'t exists', ]; } 

Para garantizar que no solo los par谩metros pasados 鈥嬧媏n el cuerpo de la solicitud, sino tambi茅n los par谩metros pasados 鈥嬧媏n la URL est茅n disponibles en las reglas de validaci贸n, redefinimos el m茅todo all (que generalmente se usa en el controlador en forma de $ request-> all ()):


 public function all($keys = null) { // return $this->all(); $data = parent::all($keys); switch ($this->getMethod()) { // case 'PUT': // case 'PATCH': case 'DELETE': $data['date'] = $this->route('day'); } return $data; } 

Configuramos el controlador y describimos la l贸gica del negocio.


Abra Http\Controllers\GameController . Eliminamos los m茅todos generados create(), edit() destinados a representar formularios (ya que tenemos una API REST, no son necesarios).


Reemplace el use Illuminate\Http\Request; est谩ndar use Illuminate\Http\Request; , en nuestro use App\Http\Requests\GameRequest;


A continuaci贸n, edite los m茅todos:


 public function index() { return Game::all(); } 

 public function store(GameRequest $request) { $day = Game::create($request->validated()); return $day; } 

 public function show(Game $game) { return $game = Game::findOrFail($game); } 

 public function update(GameRequest $request, $id) { $game = Game::findOrFail($id); $game->fill($request->except(['game_id'])); $game->save(); return response()->json($game); } 

 public function destroy(GameRequest $request, $id) { $game = Game::findOrFail($id); if($game->delete()) return response(null, 204); } 

Si hay mucha l贸gica, entonces es mejor colocarla en una capa separada Servicio / Repositorio


Personaliza el modelo


Abra el modelo de la aplicaci贸n / Http / Game.php y agregue las propiedades:


 protected $fillable = ['title', 'description', 'complexity', 'minPlayers', 'maxPlayers', 'isActive']; protected $hidden = ['created_at', 'updated_at', 'deleted_at']; 

Configurar middleware


Para que nuestra aplicaci贸n siempre devuelva json independientemente de los encabezados pasados, creamos middleware:


 php artisan make:middleware ForceJsonResponse 

y agregue el c贸digo:


 public function handle($request, Closure $next) { $request->headers->set('Accept', 'application/json'); return $next($request); } 

Registre este middleware en la app/Http/Kernel.php :


 ... 'api' => [ 'throttle:60,1', 'bindings', \App\Http\Middleware\ForceJsonResponse::class, ], 

Configuramos enrutamiento


Abra routes/api.php y agregue:


 use Http\Controllers\GameController; Route::apiResource('/games', 'GameController'); 

El m茅todo est谩tico Route :: apiResource, a diferencia del m茅todo de recursos, excluye los m茅todos de edici贸n y creaci贸n, dejando solo indexar, mostrar, almacenar, actualizar, destruir.


Lo mismo se puede lograr con un registro m谩s obvio:


 Route::resource('/games', 'GameController')->only([ 'index', 'show', 'store', 'update', 'destroy' ]); 

Ahora, puede mirar los caminos con la php artisan route:list comando de php artisan route:list y usarlo.


隆REST API est谩 lista!


Ep铆logo

Ep铆logo


Si necesita autorizaci贸n, lo har谩 el Pasaporte Laravel est谩ndar.


Configurar la autorizaci贸n del pasaporte Laravel


 composer require laravel/passport php artisan make:auth php artisan passport:install php artisan migrate 

Agregue el Laravel\Passport\HasApiTokens al modelo App\User y llame a Passport::routesmethod en la app/AuthServiceProvider boot app/AuthServiceProvider :


 public function boot() { $this->registerPolicies(); Passport::routes(); } 

En el config/auth.php cambie el controlador a pasaporte:


 'api' => [ 'driver' => 'passport', 'provider' => 'users', ], 

Cree un controlador para la autorizaci贸n 'php artisan make: controller Api / AuthController.php`


Agrega el c贸digo all铆


 use App\User; use Illuminate\Support\Facades\Validator; 

 public function register (Request $request) { $validator = Validator::make($request->all(), [ 'name' => 'required|string|max:255', 'email' => 'required|string|email|max:255|unique:users', 'password' => 'required|string|min:6|confirmed', ]); if ($validator->fails()) { return response(['errors'=>$validator->errors()->all()], 422); } $request['password']=Hash::make($request['password']); $user = User::create($request->toArray()); $token = $user->createToken('Laravel Password Grant Client')->accessToken; $response = ['token' => $token]; return response($response, 200); } public function login (Request $request) { $user = User::where('email', $request->email)->first(); if ($user) { if (Hash::check($request->password, $user->password)) { $token = $user->createToken('Laravel Password Grant Client')->accessToken; $response = ['token' => $token]; return response($response, 200); } else { $response = "Password missmatch"; return response($response, 422); } } else { $response = 'User does not exist'; return response($response, 422); } } public function logout (Request $request) { $token = $request->user()->token(); $token->revoke(); $response = 'You have been succesfully logged out!'; return response($response, 200); } 

Despu茅s de eso, puede usar los m茅todos api/register, api/login, api/logout para la autorizaci贸n y bloquear el acceso a la api. Para hacer esto, necesitamos envolver el enrutamiento de nuestros controladores REST en middleware:


 Route::middleware('auth:api')->group(function () { ... Route::get('/logout', 'Api\AuthController@logout')->name('logout'); }); 

Ep铆logo

Ep铆logo:


Todav铆a habr铆a que hacer pruebas funcionales y generaci贸n de documentaci贸n en swagger, pero esto est谩 un poco m谩s all谩 del alcance del tutorial de andamios, as铆 que m谩s sobre eso en otro momento


Source: https://habr.com/ru/post/441946/


All Articles