Tartalomjegyzék

< Laravel API

Laravel API kezdés

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:

Szerkesszük a .env fájlt, írjuk bele milyen adatbázist használunk.

.env
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:

routes/api.php
<?php
 
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
 
/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider and all of them will
| be assigned to the "api" middleware group. Make something great!
|
*/
 
Route::middleware('auth:sanctum')->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:

routes/api.php
//...
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

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.

database/migrations/*create_employees_table.php
//...
 
    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:

routes/api.php
use App\Models\Employee;
 
//...
 
Route::get('/employees', function(){
    return Employee::all();
});

Ellenőrizzük Insomnia-ban:

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:

app/Models/Employee.php
//...
class Employee extends Model
{
    use HasFactory;
 
    protected $fillable = [
        'name',
        'city',
        'salary'
    ];
}

A routingban beállítunk egy dolgozót:

routes/api.php
//...
 
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 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:

app/Http/Controller/EmployeeController.php
//...
 
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:

routes/api.php
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:

app/Http/Controller/EmployeeController.php
//...
 
    public function store(Request $request)
    {
        return Employee::create($request->all());        
    }

Írjunk hozzá útválasztást:

routes/api.php
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

app/Http/Controller/EmployeeController.php
//...
 
    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

app/Http/Controller/EmployeeController.php
//...
 
    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

app/Http/Controller/EmployeeController.php
//...
 
    public function show($id)
    {
        return Employee::find($id);
    }

Írjunk hozzá útválasztást:

routes/api.php
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

app/Http/Controller/EmployeeController.php
//...
 
    public function update(Request $request, $id)
    {
        $employee = Employee::find($id);
        $employee->update($request->all());
        return $employee;
    }

Írjunk hozzá útválasztást:

routes/api.php
//...
Route::put('/employees/{id}', [EmployeeController::class, 'update']);

Ellenőrizzük API klienssel.

Dolgozó törlése

app/Http/Controller/EmployeeController.php
//...
 
    public function destroy($id)
    {
        return Employee::destroy($id);
    }

Írjunk hozzá útávlasztást:

routes/api.php
//...
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:

routes/api.php
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

app/Http/Controller/EmployeeController.php
//...
 
    public function search($name)
    {
        return Employee::where('name', 'like', '%'.$name.'%')->get();
    }

Routing szerkesztése:

routes/api.php
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:

routes/api.php
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
app/Http/Controllers/AuthController.php
<?php
 
namespace App\Http\Controllers;
 
use Illuminate\Http\Request;
 
use App\Models\User;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\facades\Auth;
 
class AuthController extends Controller
{
    public function register(Request $request) {
        $fields = $request->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:

Útválasztás

Route::post('/register', [AuthController::class, 'register']);
Route::post('/login', [AuthController::class, 'login']);

Kilépés

app/Http/Controllers/AuthController.php
//...
 
    public function logout(Request $request) {
        auth()->user()->tokens()->delete();
        return [
            'message' => 'Logged out'
        ];
    }

Útválasztás:

routes/api.php
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