[[oktatas:web:back-end_framework:laravel:laravel_rest_api|< Laravel API]]
====== Laravel API kezdés ======
* **Szerző:** Sallai András
* Copyright (c) Sallai András, 2021, 2023
* Licenc: [[https://creativecommons.org/licenses/by-sa/4.0/|CC Attribution-Share Alike 4.0 International]]
* Web: https://szit.hu
===== Projekt =====
Hozzuk létre a projektet:
composer create-project laravel/laravel emp
Lépjünk be könyvtárba, majd indítsuk el a szervert:
cd emp
php artisan serve
===== Adatbázis =====
Használhatunk többféle adatbázis, itt most SQLite-t fogunk használni.
A database könyvtárban **hozzuk létre** az SQLite adatbázist, **database.sqlite** néven,
egy üres fájl formájában:
* database/database.sqlite
**Szerkesszük** a **.env** fájlt, írjuk bele milyen adatbázist használunk.
DB_CONNECTION=sqlite
A MySQL-ra vonatkozó beállításokat tegyük megjegyzésbe.
===== Routes =====
A routes vagy magyarul útválasztásban határozzuk meg, milyen végpontokat érhetünk el, és a végpontokat elérve, mi kell történjen.
Szerkesszük a routes/api.php fájlt:
get('/user', function (Request $request) {
return $request->user();
});
A két use kezdetű sor lehetővé teszik hogy használjuk a Request és a Route osztályokat.
A Route::middleware() függvényhívással kezdődő sor egy útválasztási bejegyzés.
Töröljük, vagy tegyük megjegyzésbe.
Vegyünk fel egy saját útválasztó bejegyzést, GET metódussal:
//...
Route::get('/employees', function(){
return 'employees';
});
A /employees végpontot határoztuk meg és egy névtelen függvényben, az 'employees' szóval térünk vissza.
==== Ellenőrzés ====
Használjuk egy HTTP klienst a teszteléshez. Lehet egy böngésző, az Insomnia, vagy a curl parancssoros program.
Készítsünk egy GET kérést a következő címre:
http://localhost:8000/api/employees
Ügyeljünk arra, hogy fusson a szerver. Ha valamiért leállítottuk, akkor nem kapunk eredményt.
==== Gyakorlat ====
* Készítsünk legalább három másik végpontot, GET metódussal, különféle üzenetekkel.
===== Dolgozók modell és tábla =====
Hozzuk létre a dolgozók táblát gyártó PHP osztályt:
php artisan make:model Employee --migration
A --migration kapcsoló, létrehozza a migrációs fájlokat,
amiből leképezhető az adatbázis tábla. A Laravel alapértelmezetten tartalmaz
néhány migrációs táblát, ezek szükségesek a működéshez.
A migrációs fájlok a **database/migrations** könyvtárban vannak.
Szerkesszük a database/migrations/*create_employees_table.php fájlt.
A * helyén az aktuális dátum szerepel.
//...
public function up()
{
Schema::create('employees', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('city');
$table->decimal('salary', 5, 2);
$table->timestamps();
});
}
//...
Ezt követően a táblák elkészíthetők
Hozzuk létre a táblákat:
php artisan migrate
További lehetőségek a migrációs fájlokban:
$table->increments('id');
$table->boolean('done');
$table->tinyInteger('status')->default('1');
==== Tábla frissítése ====
Ha szeretnénk javítani a migrációs állományt, szükség van a migráció újabb futtatására. Ez a :refresh utótaggal tehetjük meg.
Ez a művelet törli a tábla tartalmát.
php artisan migrate:refresh
===== Útválasztás javítása =====
Vegyük használatba az útválasztóban az Employee osztályt:
use App\Models\Employee;
//...
Route::get('/employees', function(){
return Employee::all();
});
Ellenőrizzük Insomnia-ban:
* Metódus: GET
* URL: http://localhost:8000/api/employees
A tábla üres, de 200-s kódot kell kapjunk.
===== A post metódus =====
Szeretnénk új dolgozót felvenni. Ehhez engedélyezzük a **name**, **city** és **salary** mezők
megadását:
//...
class Employee extends Model
{
use HasFactory;
protected $fillable = [
'name',
'city',
'salary'
];
}
A routingban beállítunk egy dolgozót:
//...
Route::post('/employees', function(){
return Employee::create([
'name' => 'Rágó Ferenc',
'city' => 'Szolnok',
'salary' => 2873000
]);
});
Ellenőrizzük egy POST kéréssel az Insomnia-ban.
Nézzük meg az adatbázisban az új dolgozót.
Így most, mindig ezt a felhasználót fogja felvenni.
A következő fejezetben megoldjuk, hogy a bejövő
HTTP kérésből vegyük a dolgozó adatait.
===== A dolgozó kontroller =====
Hozzunk létre egy Employee nevű kontrollert:
php artisan make:controller EmployeeController --resource --api
Kapcsolók:
* A --resource hatására létrejönnek az alapértelmezett metódusok.
* A --api hatására nem jön létre create és edit metódus.
A create és edit metódusok nem szükségesek REST API készítése során.
Szerkesszük az EmployeeController.php fájlt. Szükség van az Employee modellre, vegyük azt használatba:
//...
use App\Models\Employee;
Az index függvényben kérjük le az összes dolgozó adatait:
public function index()
{
return Employee::all();
}
Állítsuk be az útválasztás:
use App\Http\Controllers\EmployeeController;
//...
Route::get('/employees', [EmployeeController::class, 'index']);
A [EmployeeController::class, 'index'], azt jelenti, az EmployeeController osztályon belül
szeretnénk az index metódust hívni, ha valaki a /employees végpontra hivatkozik.
Ellenőrizzük API klienssel.
Ha szeretnénk dolgozót tárolni egy store() nevű metódust hozunk létre.
Írjuk meg a store függvényt:
//...
public function store(Request $request)
{
return Employee::create($request->all());
}
Írjunk hozzá útválasztást:
use App\Http\Controllers\EmployeeController;
//...
Route::get('/products', [EmployeeController::class, 'index']);
Route::post('/employees', [EmployeeController::class, 'store']);
Teszteljük API klienssel.
JSON tartalmat küldünk. Insomnia esetén figyeljük meg a "Header" fülön, hogy
beállításra kerül a "Content-Type" "application/json" fejléc adat.
==== Válaszkód küldése ====
//...
public function store(Request $request)
{
$employees = Employee::create($request->all());
return response($employees, 201);
}
A sikeres létrehozást 201-s válaszkóddal jelezzük.
==== Validáció beállítása ====
//...
public function store(Request $request)
{
$request->validate([
'name' => 'required',
'salary' => 'required'
]);
$employees = Employee::create($request->all());
return response($employees, 201);
}
===== Egyetlen dolgozó lekérdezése =====
//...
public function show($id)
{
return Employee::find($id);
}
Írjunk hozzá útválasztást:
Route::get('/products/{id}', [EmployeeController::class, 'show']);
A végpont után írt {id} az show() metódusban elérhető paraméterként a kontrollerben.
===== Dolgozó módosítása =====
//...
public function update(Request $request, $id)
{
$employee = Employee::find($id);
$employee->update($request->all());
return $employee;
}
Írjunk hozzá útválasztást:
//...
Route::put('/employees/{id}', [EmployeeController::class, 'update']);
Ellenőrizzük API klienssel.
===== Dolgozó törlése =====
//...
public function destroy($id)
{
return Employee::destroy($id);
}
Írjunk hozzá útávlasztást:
//...
Route::delete('/employees/{id}', [EmployeeController::class, 'destroy']);
Ellenőrizzük API klienssel.
Siker esetén 1-el tér vissza.
===== Összes erőforrás =====
Az összes CRUD műveletet egyetlen útválasztó bejegyzéssel megoldhatjuk:
use App\Http\Controllers\EmployeeController;
//...
Route::resource('/employees', EmployeeController::class);
/*
Route::get('/products', [EmployeeController::class, 'index']);
Route::post('/employees', [EmployeeController::class, 'store']);
Route::get('/products/{id}', [EmployeeController::class, 'show']);
Route::put('/employees/{id}', [EmployeeController::class, 'update']);
Route::delete('/employees/{id}', [EmployeeController::class, 'destroy']);
*/
Ellenőrizzük, milyen router információk vannak:
php artisan route:list
Ellenőrizzük API klienssel. Cím:
http://localhost:8000/api/employees/2
===== Keresés =====
//...
public function search($name)
{
return Employee::where('name', 'like', '%'.$name.'%')->get();
}
Routing szerkesztése:
use App\Http\Controllers\EmployeeController;
//...
Route::get('/employees/search/{name}', [EmployeeController::class, 'search']);
Ellenőrizzük API klienssel.
Például:
http://localhost:8000/api/employees/search/László
===== Sanctum =====
A csomagok (package) között található a Sanctum:
* https://laravel.com/docs/8.x/sanctum
use App\Http\Controllers\EmployeeController;
//...
Route::resource('/employees', EmployeeController::class);
// Route::get('/employees/search/{name}', [EmployeeController::class, 'search']);
// Route::get('/employees', [EmployeeController::class, 'index']);
// Route::post('/employees', [EmployeeController::class, 'store']);
Route::group(['middleware' => ['auth:sanctum']], function () {
Route::get('/employees/search/{name}', [EmployeeController::class, 'search']);
});
Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
return $request->user();
});
Ellenőrizzük:
http://localhost:8000/api/employees/search/László
A következő hibát kapjuk:
Route [login] not defined.
Állítsuk be fejlécben -> "Header" fülön:
Accept application/json
A következő választ kapjuk:
{
"message": "Unauthenticated."
}
==== Auth kontroller ====
php artisan make:controller AuthController
validate([
'name' => 'required|string',
'email' => 'required|string|unique:users,email',
'password' => 'required|string|confirmed'
]);
$user = User::create([
'name' => $fields['name'],
'email' => $fields['email'],
'password' => bcrypt($fields['password'])
]);
$token = $user->createToken('sajatToken')->plainTextToken;
$response = [
'user' => $user,
'token' => $token
];
return response($response, 201);
}
public function login(Request $request) {
if( Auth::attempt([ "name" => $request->name, "password" => $request->password ])) {
$authUser = Auth::user();
$success[ "token" ] = $authUser->createToken( "myapptoken" )->plainTextToken;
$success[ "name" ] = $authUser->name;
return response( $success);
}else {
return response( "Hiba! A bejelentkezés sikertelen", [ "error" => "Hibás adatok" ]);
}
}
public function logout( Request $request ) {
auth( "sanctum" )->user()->currentAccessToken()->delete();
return response()->json('Kijelentkezve');
}
}
Az AuthController tartalmát, akár be is másolhatjuk, de van egy hivatkozás User osztályra, ezért ne felejtsük el használatba vennei:
use App\Models\User;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\facades\Auth;
//...
Regisztrációnál a jelszó elkérhető kétszer:
$validator = Validator::make( $request->all() , [
"name" => "required",
"email" => "required",
"password" => "required",
"confirm_password" => "required|same:password",
]);
==== Regisztráció ====
Az api számára is fel kell vennünk felhasználókat az azonosításhoz.
Használhatunk hozzá egy REST API klienst, például Insomnia.
Fejléc:
Accept application/json
Ezt küldjük:
{
"name": "mari",
"email": "mair@zold.lan",
"password": "titok",
"password_confirmation": "titok"
}
Eredmény:
{
"user": {
"name": "mari",
"email": "mari@zold.lan",
"updated_at": "2021-11-24T19:57:43.000000Z",
"created_at": "2021-11-24T19:57:43.000000Z",
"id": 3
},
"token": "3|7eBr5iAUPgqQz3lxIFgC72Yh3ERO76g1MyuHNOGD"
}
==== Keresés azonosítással ====
Insomnia-ban:
* Auth fül
* Kiválasztjuk: Bearer
* Token: 3|7eBr5iAUPgqQz3lxIFgC72Yh3ERO76g1MyuHNOGD
* [Send]
==== Útválasztás ====
Route::post('/register', [AuthController::class, 'register']);
Route::post('/login', [AuthController::class, 'login']);
===== Kilépés =====
//...
public function logout(Request $request) {
auth()->user()->tokens()->delete();
return [
'message' => 'Logged out'
];
}
Útválasztás:
Route::group(['middleware' => ['auth:sanctum']], function () {
Route::get('/employees/search/{name}', [EmployeeController::class, 'search']);
Route::post('/logout', [AuthController::class, 'logout']);
});
Teszteléshez:
http://localhost:8000/api/logout