Felhasználói eszközök

Eszközök a webhelyen


oktatas:web:back-end_framework:laravel:laravel_rest_api_drink_pelda

< Laravel

Laravel REST API Drink példa

Szükséges szoftverek

Windowson

  • PHP
  • XAMP
  • Composer
  • Visual Studio Code vagy más szerkesztő program
  • Insomnia vagy Postman

Linuxon

  • PHP
  • Composer
  • Mariadb szerver
  • Visual Studio Code vagy más szerkesztő program
  • Insomnia vagy Postman

Linuxon szükséges csomagok

apt install php phpunit php-bcmath php-mbstring php-xml curl php-curl php-mysql

Ez a példaprojekt egy RestApi alkalmazást mutat be amely egy italraktár adatbázis nyilvántartását kezeli. A projekt Laravel 10 verzióval készült.

Adatbázis

drinks ( id, drink, amount, type_id, package_id )

types ( id, type )

packages ( id, package )

Projekt létrehozás

composer create-project laravel/laravel Drink

Migrációs állományok

Az adatbázisnak üresen léteznie kell, az adattáblákat a megfelelő mezőkkel a migrációs állományok fogják létrehozni.

drinks

php artisan make:migration create_drinks_table

A drinks táblában tároljuk az italokat.

public function up(): void {
  Schema::create('drinks', function (Blueprint $table) {
    $table->id();
    $table->string( "drink" );
    $table->integer( "amount" );
    $table->foreignId( "type_id" );
    $table->foreignId( "packages_id" );
    $table->timestamps();
    });
}

types

php artisan make:migration create_types_table

A types táblában tároljuk az italok típusait ( Bor, Sör, üdítő, …stb )

public function up(): void {
  Schema::create('types', function (Blueprint $table) {
    $table->id();
    $table->string( "type" );
   });
}

packages

php artisan make:migration create_packages_table

A packages táblában tároljuk az italok kiszereléseit ( Üveges, Hordós, …stb )

public function up(): void {
  Schema::create('packages', function (Blueprint $table) {
    $table->id();
    $table->string( "package" );
   });
}

Adattáblák létrehozása:

php artisan migrate

Modellek

Az adattáblákhoz tartozó modellek fogják kezelni az adatmozgást az alkalmazás és az adatbázis között. Fel kell venni az írható mezők listáját és szükség szerint ignorálni kell a timestamps mezőt. A model nevének meg kell egyeznie az adattábla nevével de egyes számban.

Drink

php artisan make:model Drink
class Drink extends Model {
 
    use HasFactory;
 
    protected $fillable = [
        "drink",
        "amount",
        "type_id",
        "package_id"
    ];
 
    public function type() {
 
        return $this->belongsTo( Type::class );
    }
 
    public function package() {
 
        return $this->belongsTo( Package::class );
    }
}

Type

php artisan make:model Type
class Type extends Model {
 
    use HasFactory;
 
    protected $fillable = [
        "type"
    ];
 
    public $timestamps = false;
 
    public function drink() {
 
        return $this->hasMany( Drink::class );
    }
}

Package

php artisan make:model Package
class Package extends Model {
 
    use HasFactory;
 
    protected $fillable = [
        "package"
    ];
 
    public $timestamps = false;
 
    public function drink() {
 
        return $this-hasMany( Drink::class );
    }
}

Resources osztályok

A resources osztályok állítják össze a válaszban küldött adathalmazt. Ezeket az adatokat mi adjuk meg, mit szeretnénk látni a kimeneten. A resources osztályok neve megegyezik a model nevével.

php artisan make:resource Drink

Töltsük fela toArray() metódus tömbjét az adathalmazzal.

DrinkResource

public function toArray(Request $request): array {
 
    return [
        "id" => $this->id,
        "drink" => $this->drink,
        "amount" => $this->amount,
        "type" => $this->type->type,
        "package" => $this->package->package
    ];
}

TypeResource

php artisan make:resource Type
public function toArray(Request $request): array {
 
    return [
       "type" => $this->type
    ];
}

PackageResource

php artisan make:resource Package
public function toArray(Request $request): array {
 
   return [
        "package" => $this->package
    ];
}

Kontrollerek

A kontrollerek metódusaiban történik a vezérlés, a végpontok ezekre a metódusokra mutatnak. A vezérlő osztályoknak érdemes külön könyvtárat létrehozni. Ezt könyvtárat a php artisan automatikusan létrehozza, ha nem létezik. A válaszok küldését mivel majdnem minden művelet visszatér valamilyen eredménnyel érdemes külön osztályba szervezni a kódismétlés kiküszöbölése végett.

ResponseController

php artisan make:controller Api/ResponseController

Két metódust tartalmaz, a sikeres és a hibás művletek eredményét adja vissza.

Sikeres művelet

public function sendResponse( $data, $message ) {
 
    $response = [
        "sucess" => true,
        "data" => $data,
        "message" => $message
    ];
 
    return response()->json( $response, 200 );
}

Hibás művelet

public function sendError( $error, $errorMessages = [], $code = 404 ) {
 
    $response = [
        "success" => false,
        "message" => $error
    ];
 
    if( !empty( $errorMessages )) {
 
        $response[ "data" ] = $errorMessages;
    }
 
    return response()->json( $response, $code );
}

DrinkController

php artisan make:controller Api/DrinkController

A DrinkControllert származtassuk a ResponseControllertől. A ResponseControllert és a modelt fel kell venni útvonalra. Kérjük le a drinks tábla adatait.

use App\Http\Controllers\Api\ResponseController;
use App\Models\Drink;
class DrinkController extends ResponseController {
 
    public function getDrinks() {
 
        $drinks = Drink::all();
 
        return $this->sendResponse( $drinks, "Adatok betöltve" );
    }
}

Teszteljük Insomnia vagy Postman programban. Ez a metódus minden adatot visszaad a táblából, de az idegen tábláknak csak az id idegen kulcsai látszanak. Kapcsoljuk hozzá a két másik táblát és nézzük meg az eredményt.

public function getDrinks() {
 
    $drinks = Drink::with( "type", "package" )->get();
 
    return $this->sendResponse( $drinks, "Adatok betöltve" );
}

Egy ital lekérése

Most használjuk a létrehozott resources osztályt az adatok megjelenítésére. Az osztályt be kell emelni a kontrollerbe. Mivel a model és a resorces osztály neve megegyezik ezért el kell látnunk aliasszal, hogy a hivatkozás egyértelmű legyen.

use App\Http\Resorces\Drink as DrinkResource;
public function getOneDrink( $id ){
 
    $drink = Drink::with( "type", "package" )->find( $id );
 
    if( is_null( $drink )){
 
        return $this->sendError( "Nincs ilyen ital" );
    }
 
    return $this->sendResponse( new DrinkResource( $drink ), "Ital kiválasztva" );
 
}

Ital hozzáadása

Itt szükség van a kapott ital típusának és a kiszerelésének az azonosítójára. Ezeket egy másik adattáblából kell lekérni, ezt az adott adattábla saját kontrollere fogja szolgáltatni. A beérkező adatokat validálni kell. A validálást a saját request osztály végzi. Ezt fel kell venni útvonalra.

use App\Http\Requests\DrinkAddChecker;
public function addDrink( DrinkAddChecker $request ) {
 
    $request->validated();
    $input = $request->all();
 
    $drink = new Drink;
    $drink->drink = $input["drink"];
    $drink->amount = $input["amount"];
    $drink->type_id = ( new TypeController )->getTypeId( $input[ "type" ]);;
    $drink->package_id = ( new PackageController )->getPackageId( $input[ "package" ]);
 
    $drink->save();
 
    return $this->sendResponse( new DrinkResource( $drink ), "Ital kiírva" );;
    }

Italok frissítése

Az adatokat itt is validálni kell, a szükséges azonosítokat az adattábla saját kontrollere szolgáltatja.

public function updateDrink( DrinkAddChecker $request, $id ) {
 
    $request->validated();
    $input = $request->all();
 
    $drink = Drink::find( $id );
    $drink->drink = $input[ "drink" ];
    $drink->amount = $input[ "amount" ];
    $drink->type_id = ( new TypeController )->getTypeId( $input[ "type" ]);
    $drink->package_id = ( new PackageController )->getPackageId( $input[ "package" ]);
 
    $drink->update();
 
    return $this->sendResponse( new DrinkResource( $drink ), "Ital frissítve" );
}

Ital törlése

public function deleteDrink( $id ) {
 
    $drink = Drink::find( $id );
    $drink->delete();
 
    return $this->sendResponse( new DrinkResource( $drink ), "Ital törölve" );
}

TypeController

Ez a vezérlő felelős a types tábla adatkezeléséért a megfelelő metódusokon keresztül. Az osztály szintén a ResponseControllertől öröklődik és be kell emelni a szükséges más osztályokat is.

use App\Models\Type;
use App\Http\Controllers\api\ResponseController as ResponseController;
use App\Http\Resources\Type as TypeResource;
use App\Http\Requests\TypeAddChecker;

Típusok lekérése

public function getTypes() {
 
    $types = Type::all();
 
    return $this->sendResponse( $types, "Típusok betöltve" );
}

Új típus felvétele

Az adatot itt is validálni kell, ezt a saját validáló osztály végzi.

public function addType( TypeAddChecker $request ) {
 
    $request->validated();
    $input = $request->all();
 
    $type = Type::create( $input );
 
    return $this->sendResponse( new TypeResource( $type ), "Sikeres kiírás" );
}

Típus frissítése

public function updateType( TypeAddChecker $request, $id ) {
 
    $request->validated();
    $input = $request->all();
 
    $type = Type::find( $id );
    $type->type = $input[ "type" ];
    $type->update();
 
    return $this->sendResponse( new TypeResource( $type ), "Típus frissítve" );
}

Típus törlése

public function deleteType( $id ) {
 
    $type = Type::find( $id );
    if( is_null( $type )) {
 
        return $this->sendError( "Nincs ilyen típus" );
 
    }else {
 
        $type->delete();
        return $this->sendResponse( new TypeResource( $type ), "Típus törölve" );
 
    }
}

Típus azonosító lekérése

public function getTypeId( $typeName ) {
 
    $type = Type::where( "type", $typeName )->first();
    $id = $type->id;
 
    return $id;
}

PackageController

Ez a vezérlő felelős a kiszerelések adatkezeléséért. Örökölni kell a ResponseControllert és ide is be kell emelni a szükséges osztályokat.

use App\Models\Package;
use App\Http\Controllers\api\ResponseController as ResponseController;
use App\Http\Resources\Package as PackageResource;
use App\Http\Requests\PackageAddChecker;

Kiszerelések lekérése

public function getPackages() {
 
    $packages = Package::all();
 
    return $this->sendResponse( $packages, "Kiszerelések betöltve" );
}

Új kiszerelés felvétele

public function addPackage( PackageAddChecker $request ) {
 
    $request->validated();
 
    $input = $request->all();
    $package = Package::create( $input );
 
    return $this->sendResponse( new PackageResource( $package ), "Sikeres kiírás" );
}

Kiszerelés frissítése

public function updatePackage( PackageAddChecker $request, $id ) {
 
    $request->validated();
    $input = $request->all();
 
    $package = Package::find( $id );    
    $package->package = $input[ "package" ];
    $package->update();
 
    return $this->sendResponse( new PackageResource( $package ), "Kiszerelés frissítve" );
}

Kiszerelés törlése

public function deletePackage( $id ) {
 
    $package = Package::find( $id );
    if( is_null( $quantity )) {
 
       return $this->sendError( "Nincs ilyen kiszerelés" );
 
    }else {
 
       $package->delete();
       return $this->sendResponse( new PackageResource( $package ), "Kiszerelés törölve" );
 
    }
}

Kiszerelés azonosító lekérése

public function getPackageId( $packageName ) {
 
    $package = Package::where( "package", $packageName )->first();
    $id = $package->id;
 
    return $id;
}

Request osztályok

Ezek az osztályok felelősek a beérkező adat ellenőrzéséért. A rules() metódus ellenőrzi az adatokat, a messages() metódus a saját hibaüzenetet generálja és a failedValidation() metódus a hibaüzenetet küldi. Be kell emelni két külső osztályt.

use Illuminate\Http\Exceptions\HttpResponseException;
use Illuminate\Contracts\Validation\Validator;

DrinkAddChecker

php artisan make:request DrinkAddChecker
public function rules(): array {
 
    return [
        "drink" => "required",
        "amount" => "required",
        "type" => "required",
        "package" => "required"
    ];
}
public function messages() {
 
    return [
        "drink.required" => "Név elvárt",
        "amount.required" => "Mennyiség elvárt",
        "type.required" => "Típus elvárt",
        "packages.required" => "Kiszerelés elvárt",
    ];
}
public function failedValidation( Validator $validator ) {
 
    throw new HttpResponseException( response()->json([
        "success" => false,
        "message" => "Adatbeviteli hiba",
        "data" => $validator->errors()
    ]));
}

TypeAddChecker

php artisan make:request TypeAddChecker
public function rules(): array {
 
    return [
        "type" => "required"
    ];
}
public function messages() {
 
    return [
        "type.required" => "Név elvárt"
    ];
}
public function failedValidation( Validator $validator ) {
 
    throw new HttpResponseException( response()->json([
        "success" => false,
        "message" => "Adatbeviteli hiba",
        "data" => $validator->errors()
    ]));
}

PackageAddChecker

php artisan make:request PackageAddChecker
public function rules(): array {
 
    return [
        "package" => "required"
    ];
}
public function messages() {
 
    return [
        "package.required" => "Kiszerelés elvárt"
    ];
}
public function failedValidation( Validator $validator ) {
 
    throw new HttpResponseException( response()->json([
        "success" => false,
        "message" => "Adatbeviteli hiba",
        "data" => $validator->errors()
    ]));
}

UserRegisterChecker

php artisan make:request UserRegisterChecker

Ez az osztály végzi a bevitt adatok ellenőrzését a megfelelő szabályokon keresztül. A rules() metódus a szabályokat tartalmazza, a messages() metódus a saját hibaüzeneteket és a failedValidation() metódus küldi a hibaüzeneteket. Emeljük be a szükséges osztályokat

use Illuminate\Http\Exceptions\HttpResponseException;
use Illuminate\Contracts\Validation\Validator;
public function rules(): array {
 
    return [
        "name" => "required",
        "email" => "required",
        "password" => "required",
        "confirm_password" => "required|same:password"
    ];
}
public function messages() {
 
    return [
        "name.required" => "Név kötelező",
        "email.required" => "Email kötelező",
        "password.required" => "Jelszó kötelező",
        "confirm_password.same" => "Nem egyező jelszó"
    ];
}
public function failedValidation( Validator $validator ) {
 
    throw new HttpResponseException( response()->json([
        "success" => false,
        "message" => "Adatbeviteli hiba",
        "data" => $validator->errors()
    ]));
}

UserLoginChecker

php artisan make:request UserLoginChecker

Ez az osztály végzi a bejelentkezés adatainak az ellenőrzését, ide is be kell emelni a szükséges osztályokat.

use Illuminate\Http\Exceptions\HttpResponseException;
use Illuminate\Contracts\Validation\Validator;
public function rules(): array {
 
    return [
        "name" => "required",
        "password" => "required"
    ];
}
public function messages() {
 
    return [
        "name.required" => "Név kötelező",
        "password.required" => "Jelszó kötelező"
    ];
}
public function failedValidation( Validator $validator ) {
 
    throw new HttpResponseException( response()->json([        
        "success" => false,
        "message" => "Adatbeviteli hiba",
        "data" => $validator->errors()
    ]));
}

Útvonalak

Az útvonalakat az App\routes\api.php állományban rögzítsük. Az állományban fel kell venni útvonalra a kontrollereket.

use App\Http\Controllers\DrinkController;
use App\Http\Controllers\api\TypeController;
use App\Http\Controllers\api\QuantityController;
use App\Http\Controllers\api\AuthController;

Italok

//Italok lekérése
    Route::get( "/drinks", [ DrinkController::class, "getDrinks" ]);
//Egy ital lekérése
    Route::get( "/oneDrink/{id}", [ DrinkController::class, "getOneDrink" ]);
//Új ital felvétele
    Route::post( "/addDrink", [ DrinkController::class, "addDrink" ]);
//Ital frissítése
    Route::put( "/updatedrink/{id}", [ DrinkController::class, "updateDrink" ]);
//Ital törlése==
    Route::delete( "/deleteDrink/{id}", [ DrinkController::class, "deleteDrink" ]);

Típusok

//Típusok lekérése
    Route::get( "/types", [ TypeController::class, "getTypes" ]);
//Új típus felvétele
    Route::post( "/addtype", [ TypeController::class, "addType" ]);
//Típus frissítése
    Route::put( "/updatetype/{id}", [ TypeController::class, "updateType" ]);
//Típus törlése
    Route::delete( "/deletetype/{id}", [ TypeController::class, "deleteType" ]);

Kiszerelések

//Kiszerelések lekérése
    Route::get( "/packages", [ PackageController::class, "getPackages" ]);
//Új kiszerelés felvétele
    Route::post( "/addpackage", [ PackageController::class, "addPackage" ]);
//Kiszerelés frissítése
    Route::put( "/updatepackage/{id}", [ PackageController::class, "updatePackage" ]);
//Kiszerelés törlése
    Route::delete( "/deletepackage/{id}", [ PackageController::class, "deletePackage" ]);

Azonosítás

A felhasználók kezeléséhez szükség van sanctum csomagra

composer require laravel/sanctum

A sanctum kiszolgáló beállítása:

php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"

A Kernel.php állományban engedélyezni kell a csoportos middleware api szekciójában a Sanctum használatát. Vegyük ki a kommentet a megfelelő sor elől.

protected $middlewareGroups = [
    'web' => [
        \App\Http\Middleware\EncryptCookies::class,
        \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
        \Illuminate\Session\Middleware\StartSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
        \App\Http\Middleware\VerifyCsrfToken::class,
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
    ],
 
    'api'=>   
        //\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
        \Illuminate\Routing\Middleware\ThrottleRequests::class.':api',
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
    ],
];

A felhasználók kezelése szintén adatbázisból történik, az ehhez szükséges adat táblák, a users és a personal_access_tokens a migráció során automatikusan létrejönnek. Szintén automatikusan létrejön a User model is, ebben a szükséges három mező: name, email, password. Ha User modelben nem találjuk, emeljük be a HasApiTokens osztályt.

use Laravel\Sanctum\HasApiTokens

A users táblát ki kell egészíteni két új mezővel amelyben a bejelentkezések számát és az esetleges kitiltás lejárati idejét tároljuk.

php artisan make:migration add_banned_data_to_users_table
public function up(): void {
 
    Schema::table('users', function (Blueprint $table) {
        $table->timestamp( "login_attempts" )->default( 0 );
        $table->timestamp( "banned_time" )->nullable()->default( null );
    });
}

UserController

Ez a vezérlő felelős a felhasználók regisztrációjáért, a bejelentkezésekért és a kijelentkezésekért. Négy metódusa van a register(), a logIn(), a logOut() és az isValidUser(). A kontrollert örököltessük a ResponseControllertől és emeljük be, illetve a még szükséges osztályokat is.

use App\Http\Controllers\Api\ResponseController as ResponseController;
use Illuminate\Support\Facades\Auth;
use App\Models\User;
use App\Http\Requests\UserRegisterChecker;
use App\Http\Requests\UserLoginChecker;
use Carbon\Carbon;

Az adatokat itt is validálni kell, ezt a saját ellenőrző osztály végzi.

public function register( UserRegisterChecker $request ) {
 
    $request->validated();
 
    $input = $request->all();
    $input[ "password" ] = bcrypt( $input[ "password" ]);
    $user = User::create( $input );
    $success[ "name" ] = $user->name;
 
    return $this->sendResponse( $success, "Sikeres regisztrácio" );
}

Ellenőrizni kell, hogy a bejelentkezni próbáló felhasználó létezik-e. Ha létezik meghívja a login() metódust, ha nem létezik hibaüzenetet ad.

public function isValidUser( UserLoginChecker $request ) {
 
    $count = User::where( "name", $request->name )->count();
    if( $count != 0 ) {
 
        $data = $this->login( $request );
        return $data;
 
    }else {
 
        return $this->sendError( "Azonosítási hiba", [ "Nincs ilyen felhasználó" ] );
    }
}

Most következik a felhasználó ellenőrzése, a felhasználónév jelszó páros. Ha a felhasználó háromszor hibásan adja meg a jelszavát, egy percre tíltásba kerül és hibaüzenetet kap. A felhasználó nevét és a tiltás idejének lejáratát emailben elküldjük egy adott címre. Sikeres bejelentkezés esetén generálni kell egy tokent ami a personal_access_tokens táblában tárolódik és nullázni kell a hibás bejelentkezés számlálókat. A hibás próbálkozások számlálását és rögzítését a BanningTimeController végzi.

public function login( UserLoginChecker $request ) {
 
    $bannedTime = null;
    $request->validated();
 
    if(( Auth::attempt([ "name" => $request->name, "password" => $request->password ]))) {
 
        $bannedTime = ( new BanningTimeController )->getUserBannedTime( $request->name );
 
        if( $bannedTime > Carbon::now( "Europe/Budapest" ) ) {
 
            return $this->sendError( "Túl sok próbálkozás", [ 
                "nextlogin" => $bannedTime
             ], 429 );
        }
 
        ( new BanningTimeController )->resetBannedData( $request->name );
        $authUser = Auth::user();
        $success[ "token" ] = $authUser->createToken( $authUser->name."Token" )->plainTextToken;
        $success[ "name" ] = $authUser->name;
 
        return $this->sendResponse( $success, "Sikeres bejelentkezés" );
 
    }else {
 
        $loginCounter = ( new BanningTimeController )->getLoginAttempts( $request->name );
        if( $loginCounter < 3 ) {
 
            ( new BanningTimeController )->setLoginAttempts( $request->name );
            return $this->sendError( "Sikertelen azonosítás", [ "error" => "Hibás felhasználónév vagy jelszó" ]);
 
        }else if( $loginCounter == 3 &&  is_null( $bannedTime )) {
 
            $bannedTime = ( new BanningTimeController )->setUserBannedTime( $request->name );
            $allert = ( new AllertController )->sendEmail( $request->name, $bannedTime );
            return $this->sendError( "Sikertelen azonosítás", [ "error" => "Túl sok próbálkozás" ]);
        }
    }
}

Kijelentkezéskor a tokent törölni kell.

public function logOut( Request $request ){
    auth("sanctum")->user()->currentAccessToken()->delete();
 
    return response()->json("Sikeres kijelentkezés");
}

BanningTimeController

Ennek a vezérlőnek a feladata kezelni a hibás bejelentkezések rögzítését és a kitiltás időintervallumának a beállítását. Emeljük be a szükséges osztályokat.

use Carbon\Carbon;
use App\Models\User;
class BanningTimeController extends Controller {
 
    public function getUserBannedTime( $name ) {
 
        $user = User::where( "name", $name )->first();
 
        return $user->banned_time;
    }
 
    public function getLoginAttempts( $name ) {
 
        $user = User::where( "name", $name )->first();
        $loginAttempts = $user->login_attempts;
 
        return $loginAttempts;
    }
 
    public function setLoginAttempts( $name ) {
 
        User::where( "name", $name )->increment( "login_attempts" );
    }
 
    public function setUserBannedTime( $name ) {
 
        $user = User::where( "name", $name )->first();
        $banned_time = Carbon::now( "Europe/Budapest" )->addSeconds( 60 );
        $user->banned_time = $banned_time;
        $user->save();
 
        return $banned_time;
    }
 
    public function resetBannedData( $name ) {
 
        $user = User::where( "name", $name )->first();
        $user->login_attempts = 0;
        $user->banned_time = null;
 
        $user->save();
    }
}

Email küldése

Két osztályra és egy nézetre van szükség, ezeket generáljuk le.

php artisan make:controller Api\AllertController
php artisan make:mail AllertMail

A resources\views könyvtárban hozzuk létre a mail.blade.php állományt. Az .env állományban állítsuk be az email küldéséhez szükséges adatokat. A példában gmail fiókot használunk.

MAIL_MAILER=smtp
MAIL_HOST=smtp.gmail.com
MAIL_PORT=587
MAIL_USERNAME=a_sajat_fiokod@gmail.com
MAIL_PASSWORD=a_titkos_jelszo
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS="drink@laravel.com" //Ez az emailcím fog megjelenni a levélben.
MAIL_FROM_NAME="Drink projekt"  // Ez a név fog megjelenni a levében.

AllertController

Ennek a vezérlőnek a feladata összeállítani az email tartalmát és itt adhatjuk meg a címzettet. Emeljük be a szükséges osztályokat.

use App\Mail\AllertMail;
use Illuminate\Support\Facades\Mail;
class AllertController extends Controller {
 
    public function sendEmail( $user, $time ) {
 
        $content = [
            "title" => "Felhasználó blokkolva",
            "user" => $user,
            "time" => $time
        ];
 
        Mail::to( "a_sajat_email_cimed@gmail.com" )->send( new AllertMail( $content ));
 
        return false;
    }
}

AllertMail

A konstruktorban vegyük át az összeállított adatokat. Az envelop() metódusban adhatjuk meg az email tárgyát. A content() metódusban hivatkozunk a nézetre amiben a levél kinézete van. Az attachments() metódusban van lehetőség állomány csatolására.

class AllertMail extends Mailable {
 
    use Queueable, SerializesModels;
 
    public $content;
    public function __construct( $content ) {
 
        $this->content = $content;
    }
 
    public function envelope(): Envelope
    {
        return new Envelope(
            subject: 'Allert Mail',
        );
    }
 
    public function content(): Content
    {
        return new Content(
            view: 'mail',
        );
    }
 
    public function attachments(): array
    {
        return [];
    }
}

Mail nézet

Ebben a nézetben kerül összeállításra a levél kinézete, ide emeljük be a küldeni kívánt adatokat és írhatunk hozzá további szöveget.

<h1>{{ $content[ "title" ] }}</h1><br>
<h3>Idő: {{ $content[ "time" ] }}</h3><br>
<p><h3>{{ $content[ "user" ] }}</h3>
    1 percre kitiltva túl sok sikertlen próbálkozás miatt.
</p>

Védett útvonalak

A felhaszálóknak csak bejelentkezés után engedünk végrehajtani bizonyos műveleteket. Az ezekre mutató végpontokat védetté kell tenni, a middleware csomagon keresztül a Sanctum ellenőrzi jogosultságokat. Ezt a generált tokennel igazolhatjuk. A routes/api állományban állítsuk be a védett útvonalakat, vegyük fel a middleware group csoportba. Azokat az útvonalakat amelyeket nem kívánunk védeni, hagyjuk kívül.

Route::group([ "middleware" => [ "auth:sanctum" ]], function() {
    Route::post( "/logout", [ AuthController::class, "logOut" ]);
    Route::post( "/addDrink", [ DrinkController::class, "addDrink" ]);
    Route::put( "/updatedrink/{id}", [ DrinkController::class, "updateDrink" ]);
    Route::delete( "/deletedrink/{id}", [ DrinkController::class, "deleteDrink" ]);
    Route::post( "/addtype", [ TypeController::class, "addType" ]);
    Route::put( "/updatetype/{id}", [ TypeController::class, "updateType" ]);
    Route::delete( "/deletetype/{id}", [ TypeController::class, "deleteType" ]);
    Route::post( "/addpackage", [ PackageController::class, "addPackage" ]);
    Route::put( "updatepackage/{id}", [ PackageController::class, "updatePackage" ]);
    Route::delete( "/deletepackage/{id}", [ PackageController::class, "deletePackage" ]);
});
 
Route::post( "/register", [ AuthController::class, "register" ])->middleware( "throttle:100,43200" );;
Route::post( "/login", [ AuthController::class, "isValidUser" ])->middleware( "throttle:100,43200" );
Route::get( "/drinks", [ DrinkController::class, "getDrinks" ]);
Route::get( "/oneDrink/{id}", [ DrinkController::class, "getOneDrink" ]);
Route::get( "/types", [ TypeController::class, "getTypes" ]);
Route::get( "/quantities", [ QuantityController::class, "getQuantities" ]);
oktatas/web/back-end_framework/laravel/laravel_rest_api_drink_pelda.txt · Utolsó módosítás: 2024/02/11 19:14 szerkesztette: resahh