API Rest con Laravel 12
Creación de un API Rest en Laravel 12 usando Sanctum
Build Secure PHP REST API in Laravel with Sanctum Auth
Código en GitHub de REST API in Laravel with Sanctum (usa Laravel 8)
Laravel 10 REST API Authentication using Sanctum
Montaje de ficheros en el VPS:
sshfs usuario@alumno.me:/home/usuario/notesApp/ servidor -p 22 cd servidor code .
Conectarse por ssh:
ssh usuario@alumno.me
Situarse en la carpeta del proyecto:
cd ~/notesApp
Instalar Sanctum, si no se ha configurado la opción api en la creación del proyecto (opciones de instalación en Laravel 11):
php artisan install:api
(php artisan migrate)
Modificar el fichero app/Models/User.php para añadirle use HasApiTokens:
<?php namespace App\Models; use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; use Laravel\Fortify\TwoFactorAuthenticatable; use Laravel\Jetstream\HasProfilePhoto; use Laravel\Sanctum\HasApiTokens; use App\Models\Note; use Illuminate\Database\Eloquent\Relations\HasMany; class User extends Authenticatable implements MustVerifyEmail { use HasApiTokens; /** @use HasFactory<\Database\Factories\UserFactory> */ use HasFactory; use HasProfilePhoto; use Notifiable; use TwoFactorAuthenticatable; /** * The attributes that are mass assignable. * * @var array<int, string> */ protected $fillable = [ 'name', 'email', 'password', 'email_verified_at', ]; /** * The attributes that should be hidden for serialization. * * @var array<int, string> */ protected $hidden = [ 'password', 'remember_token', 'two_factor_recovery_codes', 'two_factor_secret', ]; /** * The accessors to append to the model's array form. * * @var array<int, string> */ protected $appends = [ 'profile_photo_url', ]; /** * Get the attributes that should be cast. * * @return array<string, string> */ protected function casts(): array { return [ 'email_verified_at' => 'datetime', 'password' => 'hashed', ]; } public function notes(): HasMany { return $this->hasMany(Note::class); } }
Crear los recursos del API
php artisan make:resource Note
Modificar el fichero
nano app/Http/Resources/Note.php
poner este contenido en el fichero app/Http/Resources/Note.php:
<?php namespace App\Http\Resources; use Illuminate\Http\Request; use Illuminate\Http\Resources\Json\JsonResource; class Note extends JsonResource { /** * Transform the resource into an array. * * @return array<string, mixed> */ public function toArray(Request $request): array { return [ 'id' => $this->id, 'title' => $this->title, 'description' => $this->description, 'created_at' => $this->created_at->format('d/m/Y'), 'updated_at' => $this->updated_at->format('d/m/Y'), ]; } }
Crear los controladores
Crear el fichero app/Http/Controllers/Api/BaseController.php
cd ~/notesApp mkdir app/Http/Controllers/Api nano app/Http/Controllers/Api/BaseController.php
poner este contenido en el fichero BaseController.php
<?php namespace App\Http\Controllers\Api; use Illuminate\Http\Request; use App\Http\Controllers\Controller as Controller; class BaseController extends Controller { /** * success response method. * * @return \Illuminate\Http\Response */ public function sendResponse($result, $message, $code = 200) { $response = [ 'success' => true, 'data' => $result, 'message' => $message, ]; return response()->json($response, $code); } /** * return error response. * * @return \Illuminate\Http\Response */ public function sendError($error, $errorMessages = [], $code = 200) { $response = [ 'success' => false, 'message' => $error, ]; if(!empty($errorMessages)){ $response['info'] = $errorMessages; } return response()->json($response, $code); } }
Crear el fichero app/Http/Controllers/Api/AuthController.php
nano app/Http/Controllers/Api/AuthController.php
poner este contenido en el fichero AuthController.php
<?php namespace App\Http\Controllers\Api; use Illuminate\Http\Request; use App\Http\Controllers\Api\BaseController as BaseController; use Illuminate\Support\Facades\Auth; use Validator; use App\Models\User; class AuthController extends BaseController { public function login(Request $request) { if (Auth::attempt(['email' => $request->email, 'password' => $request->password])){ $authUser = Auth::user(); $result['token'] = $authUser->createToken('MyAuthApp')->plainTextToken; $result['name'] = $authUser->name; return $this->sendResponse($result, 'User signed in'); } else { return $this->sendError('Unauthorised.', ['error'=>'incorrect Email/Password']); } } public function register(Request $request) { $validator = Validator::make($request->all(), [ 'name' => 'required', 'email' => 'required|email', 'password' => 'required', 'confirm_password' => 'required|same:password', ]); if ($validator->fails()){ return $this->sendError('Error validation', $validator->errors()); } try { $input = $request->all(); $input['password'] = bcrypt($input['password']); $user = User::create($input); $result['token'] = $user->createToken('MyAuthApp')->plainTextToken; $result['name'] = $user->name; return $this->sendResponse($result, 'User created successfully.'); } catch (\Exception $e) { return $this->sendError('Registration Error' , $e->getMessage()); } } public function logout(Request $request) { // Get user who requested the logout $user = request()->user(); //or Auth::user() // Revoke current user token $user->tokens()->where('id', $user->currentAccessToken()->id)->delete(); $success['name'] = $user->name; // return response()->json(['message' => 'User successfully signed out']); return $this->sendResponse($success, 'User successfully signed out.'); } }
Duración del token:
How does Laravel sanctum expire tokens?
Configuración en el fichero config/sanctum.php
/* |-------------------------------------------------------------------------- | Expiration Minutes |-------------------------------------------------------------------------- | | This value controls the number of minutes until an issued token will be | considered expired. If this value is null, personal access tokens do | not expire. This won't tweak the lifetime of first-party sessions. | */ //'expiration' => null, //'expiration' => 60 * 24 * 7, 'expiration' => 60,
TODO:
– validar el email cuando un usuario se registra a través del API
(enviar un email de validación al registrarse, la validación posterior se haría desde el navegador)
API
Using HTTP Methods for RESTful Services
Crear el fichero de rutas routes/api.php
nano routes/api.php
poner este contenido en el fichero api.php:
<?php use Illuminate\Http\Request; use Illuminate\Support\Facades\Route; use App\Http\Controllers\Api\AuthController; use App\Http\Controllers\Api\NoteController; use App\Http\Controllers\Api\MailController; /* |-------------------------------------------------------------------------- | API Routes |-------------------------------------------------------------------------- */ Route::post('login', [AuthController::class, 'login']); Route::post('register', [AuthController::class, 'register']); Route::middleware('auth:sanctum')->group( function () { Route::resource('note', NoteController::class); Route::post('logout', [AuthController::class, 'logout']); // Route::post('email', [MailController::class, 'sendEmail']); }); Route::post('email', [MailController::class, 'sendEmail']); Route::middleware('auth:sanctum')->get('/user', function (Request $request) { return $request->user(); });
Crear el fichero app/Http/Controllers/Api/TasskController.php y añadir las operaciones CRUD en el API
nano app/Http/Controllers/Api/NoteController.php
poner este contenido en el fichero NoteController.php:
<?php namespace App\Http\Controllers\Api; use Illuminate\Http\Request; use App\Http\Controllers\Api\BaseController as BaseController; use Validator; use App\Models\Note; use App\Http\Resources\Note as NoteResource; class NoteController extends BaseController { public function index() { $notes = Note::where('user_id', auth()->user()->id) ->get(); return $this->sendResponse(NoteResource::collection($notes), 'Notes fetched.'); } public function store(Request $request) { $input = $request->all(); $validator = Validator::make($input, [ 'title' => 'required|max:255', 'description' => 'required' ]); if ($validator->fails()){ return $this->sendError($validator->errors()); } $note = new Note(); $note->title = $request->title; $note->description = $request->description; $note->user_id = auth()->user()->id; $note->save(); return $this->sendResponse(new NoteResource($note), 'Note created.'); } public function show($id) { $note = Note::find($id); if (is_null($note)) { return $this->sendError('Note does not exist.'); } return $this->sendResponse(new NoteResource($note), 'Note fetched.'); } public function update(Request $request, Note $note) { $input = $request->all(); $validator = Validator::make($input, [ 'title' => 'required|max:255', 'description' => 'required' ]); if($validator->fails()){ return $this->sendError($validator->errors()); } $note->title = $input['title']; //$note->title = $request->title; $note->description = $input['description']; //$note->description = $request->description; $note->save(); return $this->sendResponse(new NoteResource($note), 'Note updated.'); } public function destroy($id) { $note = Note::find($id); if (is_null($note)) { return $this->sendError('Note does not exist.', 'Note NOT deleted.'); } else { $note->delete(); return $this->sendResponse([], 'Note deleted.'); } } }
Crear el controlador para enviar emails
nano app/Http/Controllers/Api/MailController.php
poner este contenido en el fichero app/Http/Controllers/Api/MailController.php:
<?php namespace App\Http\Controllers\Api; use Illuminate\Http\Request; use Illuminate\Support\Facades\Mail; use App\Http\Controllers\Api\BaseController as BaseController; use App\Mail\NewEmail; use App\Mail\SendMailable; use Validator; use Exception; class MailController extends BaseController { public function sendEmail(Request $request) { $validator = Validator::make($request->all(), [ 'to' => 'required|email', 'subject' => 'required', 'message' => 'required', ]); if ($validator->fails()) return $this->sendError('Error validation', $validator->errors()->getMessages(), 400); else try { $to = $request->input('to'); $subject = $request->input('subject'); $message = $request->input('message'); Mail::to($to) ->send(new SendMailable($subject, $message)); return $this->sendResponse('', 'Email sent Successfully', 200); } catch (Exception $exception) { // $status = 554; return $this->sendError('', 'Email has not been sent. Error: ' . $exception->getMessage(), 500); } } }
Crear la clase SendMailable
php artisan make:mail SendMailable
poner este contenido en app/Mail/SendMailable.php
<?php namespace App\Mail; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Mail\Mailable; use Illuminate\Mail\Mailables\Content; use Illuminate\Mail\Mailables\Envelope; use Illuminate\Queue\SerializesModels; class SendMailable extends Mailable { use Queueable, SerializesModels; public $subject; public $message; public function __construct($subject, $message) { $this->subject = $subject; $this->message = $message; } public function build() { return $this->view('emails.send') //->from($this->from) //->cc($address, $name) //->bcc($address, $name) //->replyTo($address, $name) ->subject($this->subject) ->with([ 'body' => $this->message ]); } }
Crear la carpeta resources/views/emails
cd ~/notesApp mkdir resources/views/emails
Crear el fichero resources/views/emails/send.blade.php
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Email from our platform</title> <style> /* Inline styles for simplicity, consider using CSS classes for larger templates */ body { font-family: Arial, sans-serif; margin: 0; padding: 0; } .container { max-width: 600px; margin: 0 auto; padding: 20px; background-color: #f1f1f1; } .logo { text-align: center; margin-bottom: 20px; } .logo img { max-width: 200px; } .message { padding: 20px; background-color: #ffffff; } .message p { margin-bottom: 10px; } .footer { text-align: center; margin-top: 20px; } </style> </head> <body> <h3>Email desde la app</h3> <div class="container"> <div class="message"> <p>{{ $body }},</p> <p>Regards</p> </div> </div> </body> </html>
Código
Más información.
Laravel 11 REST API Authentication using Sanctum Tutorial
Laravel Email: A Complete Guide to Setup, and Automation
Sending Email in Laravel: A Comprehensive Guide
Deja una respuesta
Lo siento, debes estar conectado para publicar un comentario.