IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Lekce 1 - Rezervační systém v Symfony - Založení projektu a přihlášení

Zdravím všechny pokročilejší programátory v kurzu tutoriálů pro PHP framework Symfony.

Budeme zde programovat rezervační systém pro vozidla. K dispozici bude samozřejmě základní bezpečnost přihlášením emailem a heslem, uživatelské role (admin, běžný uživatel), přidávání vozidel, jejich úprava a mnoho dalšího.

Rezervace vozidel v Symfony - Rezervační systém pro vozidla v Symfony

Na větším projektu nás potkají nové problémy, se kterými jsme se ještě nesetkali, a ukážeme si jejich řešení.

Správa uživatelů v Symfony - Rezervační systém pro vozidla v Symfony

Pokud za sebou nemáte naše minulé lekce a nebo právě začínáte se Symfony, doporučuji se prvně podívat na kurz Základy frameworku Symfony.

Příprava projektu

Nejprve si připravíme celý projekt. Jelikož je vydána Symfony verze 5, založíme si projekt nad touto verzí. Začneme s požadavky pro tuto verzi Symfony. Nainstalujeme si PHP verzi 7.2.5 a vyšší. Dále budeme potřebovat composer pro instalaci balíků a samotného frameworku a samozřejmě databázi.

Pozor, dodržuj přesné verze komponent! Pokročilé projekty jako tento jsou složené z komponent. Možná by tě napadlo použít nejnovější verzi nějaké komponenty, co zrovna včera vyšla. Projekt ti pak ale bez odborné úpravy pravděpodobně nebude fungovat! U verzí komponent neplatí jako např. u aktualizace Windows, že chceme každý den používat tu nejnovější. Neustálé aktualizace všeho by totiž vyžadovaly každodenní a komplexní změny kódu projektu a reálně se tak neprovádějí. Ze stejného důvodu i my aktualizujeme kurzy v pravidelných intervalech a nové verze k sobě pak sladíme tak, aby vše fungovalo.

Symfony CLI

Symfony CLI (nebo příkazový řádek Symfony) nám pomůže například vytvořením vestavěného serveru. Na instalaci Symfony CLI je třeba nástroj Scoop. Scoop nainstalujeme tak, že zapneme Powershell v OS Windows a vložíme následující příkaz:

iwr -useb get.scoop.sh | iex

Následně spustíme v příkazovém řádku příkaz:

scoop install symfony-cli

Nyní máme Symfony CLI nainstalované :) Všechny příkazy, co zde uvedu a budou začínat slovem symfony, využije se Symfony CLI.

Ostatní OS

Na OS Linux nebo MacOS je popsána instalace v dokumentaci Symfony CLI.

Symfony projekt

Pokud máme vše připraveno, vytvoříme si pro projekt složku a v ní zahájíme instalaci Symfony následujícím příkazem:

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

Nyní se v aktuálním adresáři vytvořila složka rezervace_vozidel s projektem, která má následující strukturu:

Struktura projektu - Rezervační systém pro vozidla v Symfony

Instalace určitých verzí může být někdy problém, proto jsem nahrál tuto základní složku pod článek.

Pokud používáme Symfony CLI, můžeme použít následující příkaz a ujistit se, zda splňujeme požadavky:

symfony check:requirements

Požadavky splňuje pouze právě použitý PC, kde příkaz proběhl. Pokud budete projekt někde nahrávat, je vhodné se ujistit i tam.

Jestli jste zvyklí využívat vlastní balík pro webový server (wamp/xampp), tak ho můžete využít. Symfony však může udělat svůj vlastní webový server, který není třeba dále konfigurovat, ten případně spustíme příkazem:

symfony server:start

V příkazovém řádku se dozvíme adresu s portem, kterou navštívíme ve webovém prohlížeči. Tím se zobrazí uvítací homepage Symfony.

Se zakládáním nového projektu byste neměli mít problém, případně opět doporučím nejdříve projít základní kurz, konkrétně vytvoření projektu v lekci Instalace Symfony a IDE.

Databáze

Databázový server je třeba mít už nainstalovaný a spuštěný. Nejprve řekneme Symfony, kde je naše databáze a jak se k ní připojí. Otevřeme si soubor .env v root složce projektu a najdeme řádek:

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

Údaje na tomto řádku následně změníme na údaje našeho serveru. Nezapomeňte uvést verzi vašeho databázového serveru. V mém případě to bude uživatel root a heslo kokos123, verze MySQL 5.7:

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

Pokud používáte databázi SQLite nebo PostgreSQL, URL je jiná! Dočtete se o tom o řádek výše v .env souboru.

Nyní si můžeme nechat vytvořit databázi projektu pomocí příkazu:

php bin/console doctrine:database:create

Přihlášení a uživatelé

Dalším základním kamenem aplikace jsou uživatelé.

Entita User

Nejprve si vytvoříme entitu User, která bude reprezentovat uživatele. Uděláme to pomocí příkazu:

php bin/console make:user

Ve vygenerovaném souboru src/Entity/User.php ještě přidáme uživateli vlastnosti $canReserve a $displayname. Soubor bude vypadat 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;
    }

}

Autentifikace

Ověřovat uživatele budeme pomocí emailu a hesla. Necháme si vytvořit také LoginFormAuthenticator (/logout, LoginForm.php a SecurityController.php) přes příkaz:

php bin/console make:auth

Všechny naše nové soubory jsou tedy následující:

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 soubory config/packages/doctrine.yaml a config/packages/security.yaml, které jsme mu zadali do příkazového řádku. Avšak nikdo nemá zatím přístup k přihlášení na adrese /login. Na konec souboru security.yaml tedy přidáme řádek, který nám zajistí, že budou mít všichni přístup k přihlášení:

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

Migrace

Teď máme adresu /login "funkční". Nebudeme se ale moci přihlásit, protože nemáme zatím žádné uživatele a hlavně jsme neprovedli migraci databáze. Sice tedy máme entitu, ale v databázi reálně tabulka s uživateli ještě není. Pro migraci spustíme tyto dva příkazy:

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

Testování

Abychom projekt vyvíjeli trochu na úrovni, testovat uživatele (vytvářet "umělé entity") budeme pomocí fixtures, které využijeme i v budoucnu (např. pro rezervace). Nainstalujeme si je pomocí:

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

a poté vytvoříme novou fixture:

php bin/console make:fixtures

Fixturu nazveme UserFixture, bude mít na starosti uživatele. Soubor src/DataFixtures/UserFixture.php upravíme do následující 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 i to, že admin bude ignorovat tuto vlastnost
        $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"]);

        // díky tomuto se pak dostaneme k těmto uživatelům z jiných fixtur
        $this->addReference(self::USER_ADMIN_REFERENCE, $user1);
        $this->addReference(self::USER_USER_REFERENCE, $user2);

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

        $manager->flush();
    }
}

Fixtura vytvoří v databázi 2 testovací uživatele. Určitě jste si všimli, že jeden je administrátor a druhý jen běžný uživatel. To abychom si mohli ověřit, že funkce aplikace pro administrátora fungují a zároveň nejsou dostupné pro běžného uživatele. To je konec konců velmi důležité!

Nakonec spustíme a potvrdíme příkaz pro nahrání uživatelů do databáze:

php bin/console doctrine:fixtures:load

Závěr

Nyní se můžeme přihlásit na adrese /login :) Vyhodí nám to chybu "TODO: provide a valid redirect inside". Zatím se nemáme kam přihlásit, proto budeme myslet do budoucna a odkážeme na budoucí routu /myBooking v metodě onAuthenticationSuccess v souboru src/Security/LoginFormAuthenticator.php následovně:

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"));
}

Tady ukončíme dnešní lekci.

V další lekci, Rezervační systém v Symfony - Entity, repositáře, kontrolery, si vytvoříme entity rezervace, vozidla, kontroler a upravíme repositář pro rezervace.


 

Měl jsi s čímkoli problém? Zdrojový kód vzorové aplikace je ke stažení každých pár lekcí. Zatím pokračuj dál, a pak si svou aplikaci porovnej se vzorem a snadno oprav.

Stáhnout

Stažením následujícího souboru souhlasíš s licenčními podmínkami

Staženo 180x (13.76 MB)

 

Všechny články v sekci
Rezervační systém pro vozidla v Symfony
Přeskočit článek
(nedoporučujeme)
Rezervační systém v Symfony - Entity, repositáře, kontrolery
Článek pro vás napsal Samuel Hél
Avatar
Uživatelské hodnocení:
9 hlasů
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