Vianoce v ITnetwork sú tu! Dobí si teraz kredity a získaj až 80 % extra kreditov na e-learningové kurzy ZADARMO. Zisti viac.
Hľadáme nové posily do ITnetwork tímu. Pozri sa na voľné pozície a pridaj sa k najagilnejšej firme na trhu - Viac informácií.

1. diel - Rezervačný systém v Symfony - Založenie projektu a prihlásenie

Zdravím všetky pokročilejšie programátorov v kurze tutoriálov pre PHP framework Symfony.

Budeme tu programovať rezervačný systém pre vozidlá. K dispozícii bude samozrejme základná bezpečnosť prihlásením emailom a heslom, užívateľské role (admin, bežný užívateľ), pridávanie vozidiel, ich úprava a mnoho ďalšieho.

Rezervácia vozidiel v Symfony - Rezervačný systém pre vozidlá v Symfony

Na väčšom projekte nás stretnú nové problémy, s ktorými sme sa ešte nestretli, a ukážeme si ich riešenie.

Správa užívateľov v Symfony - Rezervačný systém pre vozidlá v Symfony

Ak za sebou nemáte naše minulé lekcie a alebo práve začínate sa Symfony, odporúčam sa prvýkrát pozrieť na kurz Základy frameworku Symfony.

Príprava projektu

Najprv si pripravíme celý projekt. Keďže je vydaná Symfony verzia 5, založíme si projekt nad touto verziou. Začneme s požiadavkami pre túto verziu Symfony. Nainštalujeme si PHP verziu 7.2.5 a vyšší. Ďalej budeme potrebovať composer pre inštaláciu balíkov a samotného frameworku a samozrejme databázu.

Symfony projekt

Ak máme všetko pripravené, vytvoríme si pre projekt zložku a v nej zahájime inštalácii Symfony nasledujúcim príkazom:

composer create-project symfony/website-skeleton:^5 rezervace_vozidel

Teraz sa v aktuálnom adresári vytvorila zložka s projektom, ktorá má nasledujúcu štruktúru:

štruktúra projektu - Rezervačný systém pre vozidlá v Symfony

Po inštalácii sa môžeme uistiť, či spĺňame požiadavky príkazom:

symfony check:requirements

Ak ste zvyknutí využívať vlastné balík pre webový server (wamp / xampp), tak ho môžete využiť. Symfony však môže urobiť svoj vlastný webový server, ktorý nie je potrebné ďalej konfigurovať, ten prípadne spustíme príkazom:

symfony server:start

V príkazovom riadku sa dozvieme adresu s portom, ktorú navštívime vo webovom prehliadači. Tým sa zobrazí uvítacia homepage Symfony.

So zakladaním nového projektu by ste nemali mať problém, prípadne opäť odporučím najskôr prejsť základný kurz, konkrétne vytvorenie projektu v lekcii Inštalácia Symfony a IDE.

Databázy

Najprv povieme Symfony kde je naša databáza a ako sa k nej pripojí. Otvoríme si súbor .env v root priečinku projektu a nájdeme riadok:

DATABASE_URL=mysql://db_user:[email protected]:3306/db_name?serverVersion=5.7

Údaje na tomto riadku následne zmeníme na údaje nášho serveru. Nezabudnite uviesť verziu vášho databázového servera. V mojom prípade to bude užívateľ root a heslo kokos123, verzia MySQL 5.7:

DATABASE_URL=mysql://root:[email protected]:3306/itnetwork_tut?serverVersion=5.7

Ak používate databázu SQLite alebo PostgreSQL, URL je iná! Dočítate sa o tom o riadok vyššie v .env súbore.

Teraz si môžeme nechať vytvoriť databázu projektu pomocou príkazu:

php bin/console doctrine:database:create

Prihlásenie a užívatelia

Ďalším základným kameňom aplikácie sú užívatelia.

Entita User

Najprv si vytvoríme entitu User, ktorá bude reprezentovať užívateľa. Urobíme to pomocou príkazu:

php bin/console make:user

Vo vygenerovanom súboru src/Entity/User.php ešte pridáme užívateľovi vlastnosti $canReserve a $displayname. Súbor bude vyzerať takto:

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;

/**
 * @ORM\Entity(repositoryClass="App\Repository\UserRepository")
 */
class User implements UserInterface
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=180, unique=true)
     */
    private $email;

    /**
     * @ORM\Column(type="json")
     */
    private $roles = [];

    /**
     * @var string The hashed password
     * @ORM\Column(type="string")
     */
    private $password;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    private $displayname;

    /**
     * @ORM\Column(type="boolean")
     **/
    private $canReserve;


    public function getId(): ?int
    {
        return $this->id;
    }

    public function getEmail(): ?string
    {
        return $this->email;
    }

    public function setEmail(string $email): self
    {
        $this->email = $email;

        return $this;
    }


    /**
     * A visual identifier that represents this user.
     *
     * @see UserInterface
     */
    public function getUsername(): string
    {
        return (string) $this->email;
    }

    /**
     * @see UserInterface
     */
    public function getRoles(): array
    {
        $roles = $this->roles;
        // guarantee every user at least has ROLE_USER
        $roles[] = 'ROLE_USER';

        return array_unique($roles);
    }

    public function setRoles(array $roles): self
    {
        $this->roles = $roles;

        return $this;
    }

    /**
     * @see UserInterface
     */
    public function getPassword(): string
    {
        return (string) $this->password;
    }

    public function setPassword(string $password): self
    {
        $this->password = $password;

        return $this;
    }

    /**
     * @see UserInterface
     */
    public function getSalt()
    {
        // not needed when using the "bcrypt" algorithm in security.yaml
    }

    /**
     * @see UserInterface
     */
    public function eraseCredentials()
    {
        // If you store any temporary, sensitive data on the user, clear it here
        // $this->plainPassword = null;
    }

    public function getDisplayname(): ?string
    {
        return $this->displayname;
    }

    public function setDisplayname(?string $displayname): self
    {
        $this->displayname = $displayname;

        return $this;
    }

    public function getCanReserve(): ?bool
    {
        return $this->canReserve;
    }

    public function setCanReserve(bool $canReserve): self
    {
        $this->canReserve = $canReserve;

        return $this;
    }

}

Autentifikácia

Overovať užívateľa budeme pomocou emailu a hesla. Necháme si vytvoriť tiež LoginFormAuthenticator (/logout, LoginForm.php a SecurityController.php) cez príkaz:

php bin/console make:auth

Všetky naše nové súbory sú teda nasledujúce:

src/Entity/User.php
src/Repository/UserRepository.php
src/Security/LoginFormAuthenticator.php
templates/security/login.html.twig

config/packages/security.yaml

Symfony si automaticky nakonfiguroval súbory config/packages/doctrine.yaml a config/packages/security.yaml, ktoré sme mu zadali do príkazového riadku. Avšak nikto nemá zatiaľ prístup k prihláseniu na adrese /login. Na koniec súboru security.yaml teda pridáme riadok, ktorý nám zabezpečí, že budú mať všetci prístup k prihlásenie:

access_control:
    - { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }

Migrácia

Teraz máme adresu /login "funkčná". Nebudeme sa ale môcť prihlásiť, pretože nemáme zatiaľ žiadne užívateľa a hlavne sme nespravili migráciu databázy. Síce teda máme entitu, ale v databáze reálne tabuľka s užívateľmi ešte nie je. Pre migráciu spustíme tieto dva príkazy:

php bin/console make:migration
php bin/console doctrine:migrations:migrate

Testovanie

Aby sme projekt vyvíjali trochu na úrovni, testovať užívateľa (vytvárať "umelé entity") budeme pomocou fixtures, ktoré využijeme aj v budúcnosti (napr. Pre rezervácie). Nainštalujeme si ich pomocou:

composer require --dev doctrine/doctrine-fixtures-bundle

a potom vytvoríme novú fixture:

php bin/console make:fixtures

FIXTURE nazveme UserFixture, bude mať na starosti používateľa. Súbor src/DataFixtures/UserFixture.php upravíme do nasledujúcej podoby:

<?php

namespace App\DataFixtures;

use App\Entity\User;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;

class UserFixture extends Fixture
{
    public const USER_USER_REFERENCE = 'user-user';
    public const USER_ADMIN_REFERENCE = 'user-admin';

    private $encoder;

    public function __construct(UserPasswordEncoderInterface $encoder)
    {
        $this->encoder = $encoder;
    }

    public function load(ObjectManager $manager)
    {
        $user1 = new User();
        $user1->setPassword($this->encoder->encodePassword($user1, "kokos1"));
        $user1->setCanReserve(0); // otestujeme aj to, že admin bude ignorovať túto vlastnosť
        $user1->setDisplayname("Admin");
        $user1->setEmail("[email protected]");
        $user1->setRoles(["ROLE_ADMIN"]);

        $user2 = new User();
        $user2->setPassword($this->encoder->encodePassword($user2, "kokos1"));
        $user2->setCanReserve(0);
        $user2->setDisplayname("Test");
        $user2->setEmail("[email protected]");
        $user2->setRoles(["ROLE_USER"]);

        // vďaka tomuto sa potom dostaneme k týmto užívateľom z iných FIXTURE
        $this->addReference(self::USER_ADMIN_REFERENCE, $user1);
        $this->addReference(self::USER_USER_REFERENCE, $user2);

        $manager->persist($user1);
        $manager->persist($user2);

        $manager->flush();
    }
}

FIXTURE vytvorí v databáze 2 testovacie užívateľa. Určite ste si všimli, že jeden je administrátor a druhý len bežný užívateľ. To aby sme si mohli overiť, že funkcia aplikácie pre administrátora fungujú a zároveň nie sú dostupné pre bežného užívateľa. To je koniec koncov veľmi dôležité!

Nakoniec spustíme a potvrdíme príkaz pre nahranie používateľov do databázy:

php bin/console doctrine:fixtures:load

Záver

Teraz sa môžeme prihlásiť na adrese /login:) Vyhodí nám to chybu "TODO: provide a valid redirect inside". Zatiaľ sa nemáme kam prihlásiť, preto budeme myslieť do budúcnosti a odkážeme na budúce route /myBooking v metóde onAuthenticationSuccess v súbore src/Security/LoginFormAuthenticator.php nasledovne:

public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
{
    if ($targetPath = $this->getTargetPath($request->getSession(), $providerKey)) {
        return new RedirectResponse($targetPath);
    }

    // TODO: redirect after authentication For example : return new RedirectResponse($this->urlGenerator->generate('some_route'));
    return new RedirectResponse($this->urlGenerator->generate("myBooking"));
}

Tu ukončíme dnešnú lekciu.

V ďalšej lekcii, Rezervačný systém v Symfony - Entity, repozitára, kontrolery , si vytvoríme entity rezervácie, vozidlá, kontrolér a upravíme repozitár pre rezervácie.


 

Stiahnuť

Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami

Stiahnuté 227x (13.76 MB)

 

Všetky články v sekcii
Rezervačný systém pre vozidlá v Symfony
Preskočiť článok
(neodporúčame)
Rezervačný systém v Symfony - Entity, repozitára, kontrolery
Článok pre vás napísal Samuel Hél
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
Autor se věnuje hlavně programování, nejvíce z oblasti webových technologií, dělá občasné video edity ze svých dovolených. Má rád memes, svou gf a elektroniku
Aktivity