Symfony 6 współpraca z bazą danych: tworzenie tabeli i wypełnienie jej randomowymi danymi

Symfony to nowoczesny, elastyczny i skalowalny framework PHP, który ułatwia tworzenie zaawansowanych aplikacji internetowych. W ramach tego artykułu omówimy jak efektywnie współpracować z bazą danych, korzystając z Doctrine ORM oraz wzorca projektowego Model-View-Controller (MVC) w kontekście Symfony.

Doctrine to potężne narzędzie do mapowania obiektowo-relacyjnego (ORM), które umożliwia łatwą i wydajną interakcję z bazą danych, niezależnie od używanego silnika. Dzięki Doctrine programiści mogą pracować z obiektami domenowymi, zamiast bezpośrednio z tabelami i zapytaniami SQL, co przekłada się na większą czytelność oraz łatwiejsze utrzymanie kodu.

Wzorzec MVC (Model-View-Controller) to popularny wzorzec architektury aplikacji, który pomaga oddzielić logikę biznesową, dane oraz prezentację, ułatwiając zarządzanie i rozwijanie projektu. W Symfony, modele reprezentują dane, kontrolery obsługują logikę aplikacji, a widoki są odpowiedzialne za prezentację informacji.

W niniejszym artykule przedstawimy, jak zintegrować Doctrine ORM z Symfony, aby pobierać modele z bazy danych i wyświetlać je w widokach, zgodnie z zasadami wzorca MVC. Krok po kroku omówimy konfigurację, tworzenie modeli, kontrolerów i widoków, a także pokażemy, jak wykorzystać funkcje Symfony do ułatwienia pracy z bazą danych.

Instalacja Symfony

Rozpoczynamy od stworzenia nowego projektu Symfony poprzez wykorzystanie narzędzia Composer.

Za pomocą menedżera zależności Composer tworzymy nowy projekt Symfony oparty na szkielecie (skeleton) w wersji 6.2. Umieszczamy projekt w katalogu o nazwie „ORMSynfony”. Szkic (skeleton) to lekka struktura projektu, która zawiera minimalny zestaw zależności niezbędnych do uruchomienia aplikacji Symfony.

composer create-project symfony/skeleton:"6.2.*" ORMSynfony

Następnie przechodzimy do katalogu nowo utworzonego projektu „ORMSynfony” za pomocą polecenia „cd”, aby kontynuować konfigurację.

cd ORMSynfony

Instalujemy pakiet „webapp” za pomocą Composer. Pakiet „webapp” dostarcza zestaw podstawowych zależności, które są niezbędne do stworzenia aplikacji internetowej opartej na frameworku Symfony, takich jak routing, obsługa żądań HTTP oraz system szablonów Twig.

composer require webapp

Instalujemy pakiet „symfony/apache-pack”. Ten pakiet zawiera konfigurację dla serwera Apache, która jest niezbędna do prawidłowego działania aplikacji Symfony na tym serwerze. Apache to popularny serwer WWW, często używany w połączeniu z aplikacjami PHP.

composer require symfony/apache-pack

Konfiguracja VirtualHost na Apache

Aby skonfigurować Virtual Host na serwerze Apache dla naszej aplikacji Symfony, dodaj poniższy kod do konfiguracji swojego apache, zastępując podane ścieżki poprawnymi ścieżkami z Twojego systemu. Dzięki temu serwer będzie mógł poprawnie obsługiwać naszą aplikację.

<VirtualHost *:80>
    ServerName ormsynfony.localhost
    ServerAlias www.ormsynfony.localhost

    DocumentRoot "/ścieżka/do/projektu/ORMSynfony/public"
    DirectoryIndex index.php

    <Directory "/ścieżka/do/projektu/ORMSynfony/public">
        AllowOverride None
        Require all granted
        Allow from All

        FallbackResource /index.php
    </Directory>

    ErrorLog "/var/log/apache2/ormsynfony_error.log"
    CustomLog "/var/log/apache2/ormsynfony_access.log" combined
</VirtualHost>

Uruchom ponownie Apache i przejdź na stronę http://ormsymfony.localhost Powinieneś ujżeć następującą stronę:

Uruchomiona aplikacja Symfony na serwerze Apache.

Strona, którą widzisz, to domyślna strona powitalna generowana przez Symfony dla nowo utworzonych projektów. Strona wyświetla się, gdy jeszcze nie skonfigurowałeś żadnej ścieżki URL dla strony głównej i włączony jest tryb debugowania (debug mode). Ta strona służy jako punkt wyjścia dla rozwoju Twojej aplikacji, więc możesz teraz zacząć tworzyć własne kontrolery, widoki i ścieżki URL, aby zbudować aplikację zgodnie z Twoimi wymaganiami. W ramach tego artykułu kontynuujemy rozwój aplikacji, integrując Doctrine ORM i współpracując z bazą danych.

Konfiguracja bazy danych

Teraz musisz skonfigurować połączenie z bazą danych. W projekcie Symfony, konfiguracja bazy danych znajduje się w pliku .env. Otwórz plik .env w katalogu głównym projektu i znajdź sekcję zaczynającą się od DATABASE_URL. Domyślnie, konfiguracja będzie wyglądać mniej więcej tak:

DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=8&charset=utf8mb4"

Zaktualizuj wartość DATABASE_URL zgodnie z ustawieniami Twojej bazy danych. Zmień db_user, db_password, 127.0.0.1:3306 oraz db_name na odpowiednie wartości. Jeśli używasz innego silnika bazy danych niż MySQL, musisz także zmienić protokół na początku linii (np. postgresql:// dla PostgreSQL).

W swoim projekcie używam bazy MariaDB z pakietu XAMPP, więc moja konfiguracja jest następująca:

DATABASE_URL="mysql://root@127.0.0.1:3306/ormsymfony?serverVersion=mariadb-10.4.27"

Utwórz bazę danych, jeśli jeszcze nie istnieje. W terminalu, będąc w katalogu projektu, wykonaj polecenie:

php bin/console doctrine:database:create

To utworzy bazę danych zgodnie z konfiguracją podaną w pliku .env.

Po wykonaniu tych kroków, Twoja aplikacja Symfony współpracuje z bazą danych.

Utworzenie bazy danych przez Symfony.

Tworzenie encji

Teraz musimy stworzyć encję. Encja to klasa PHP reprezentująca tabelę w bazie danych, a jej atrybuty odpowiadają kolumnom tej tabeli. Doctrine używa encji do mapowania obiektów w aplikacji na rekordy w bazie danych, co pozwala na łatwiejszą i bardziej obiektową pracę z danymi.

W terminalu, będąc w katalogu projektu, wykonaj polecenie:

php bin/console make:entity

Kiedy konsola poprosi Cię o wprowadzenie nazwy encji, wpisz Person i naciśnij Enter.

Teraz zostaniesz poproszony o dodanie pól do encji Person. Dla każdego pola wykonaj następujące kroki:
Podaj nazwę pola: wprowadź name i naciśnij Enter.
Podaj typ pola: wprowadź string i naciśnij Enter.
Określ długość maksymalną (opcjonalnie): możesz zostawić wartość domyślną (255) lub wprowadzić inną wartość, a następnie naciśnij Enter.
Zdecyduj, czy pole może być puste (NULL): wpisz no i naciśnij Enter.

Powtórz krok 3 dla pozostałych pól:
Pole surname: typ string, maksymalna długość 255, nie może być puste (NULL).
Pole age: typ integer, nie może być puste (NULL).
Pole email: typ string, maksymalna długość 255, nie może być puste (NULL).

Gdy zakończysz dodawanie pól, naciśnij Enter, aby wyjść z trybu dodawania pól.

Po wykonaniu powyższych kroków, konsola utworzy nową encję o nazwie Person w katalogu src/Entity twojego projektu. Klasa Person będzie zawierać atrybuty name, surname, age i email wraz z ich getterami i setterami.

Gettery i Settery

Gettery i settery to metody dostępu (accessor methods) używane w programowaniu obiektowym do kontrolowania dostępu do atrybutów klas. Zapewniają one bezpieczny i kontrolowany sposób na odczytywanie i modyfikowanie wartości atrybutów obiektów.

Gettery (metody pobierające) służą do odczytywania wartości atrybutów obiektu. Pozwalają one uzyskać dostęp do wartości prywatnych lub chronionych atrybutów w sposób kontrolowany, bez udostępniania bezpośredniego dostępu do tych atrybutów. Gettery zazwyczaj zaczynają się od słowa „get” lub „is” (dla wartości logicznych) i nie przyjmują żadnych argumentów. Zwracają wartość odpowiedniego atrybutu obiektu.

Settery (metody ustawiające) modyfikują wartości atrybutów obiektu. Umożliwiają kontrolowanie sposobu, w jaki wartości atrybutów są ustawiane, np. walidując dane wejściowe lub wykonując dodatkowe operacje związane z modyfikacją atrybutu. Settery zazwyczaj zaczynają się od słowa „set” i przyjmują jeden argument – nową wartość atrybutu, który należy ustawić.

Gettery i settery zapewniają enkapsulację, jedną z podstawowych zasad programowania obiektowego. Enkapsulacja polega na ukrywaniu szczegółów implementacji i stanu obiektu, udostępniając jedynie wybrane metody dostępu do tego stanu. Dzięki enkapsulacji, można zmieniać implementację klasy bez wpływu na pozostałą część kodu, która korzysta z tej klasy, co ułatwia utrzymanie i rozwój aplikacji.

Zawartośc pliku src/Entity/Person.php jest następująca:

<?php

namespace App\Entity;

use App\Repository\PersonRepository;
use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity(repositoryClass: PersonRepository::class)]
class Person
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    private ?int $id = null;

    #[ORM\Column(length: 255)]
    private ?string $name = null;

    #[ORM\Column(length: 255)]
    private ?string $surname = null;

    #[ORM\Column]
    private ?int $age = null;

    #[ORM\Column(length: 255)]
    private ?string $email = null;

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

    public function getName(): ?string
    {
        return $this->name;
    }

    public function setName(string $name): self
    {
        $this->name = $name;

        return $this;
    }

    public function getSurname(): ?string
    {
        return $this->surname;
    }

    public function setSurname(string $surname): self
    {
        $this->surname = $surname;

        return $this;
    }

    public function getAge(): ?int
    {
        return $this->age;
    }

    public function setAge(int $age): self
    {
        $this->age = $age;

        return $this;
    }

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

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

        return $this;
    }
}

Migracje bazodanowe

Gdy mamy już plik encji należy przeprowadzić migracje bazodanową. Migracje pozwalają na utrzymanie i ewolucję schematu bazy danych w trakcie rozwoju aplikacji. Umożliwiają one generowanie skryptów SQL, które wprowadzają zmiany w strukturze bazy danych, zgodnie z zaktualizowanymi encjami w kodzie. Aby utworzyć migrację wykonaj polecenie, które porówna obecny stan encji w projekcie z obecnym schematem bazy danych, a następnie wygeneruje nowy plik migracji z wymaganymi instrukcjami SQL:

php bin/console make:migration

Po wykonaniu polecenia w katalogu migrations zostanie utworzony nowy plik migracji, na przykład Version20230318194730.php. Plik ten zawiera klasę z metodami up() oraz down(), które służą do wprowadzania i cofania zmian w schemacie bazy danych.

tworzenie pliku z migracją.

Przejrzyj wygenerowany plik migracji i upewnij się, że zawiera poprawne instrukcje SQL, które odpowiadają zmianom wprowadzonym w encjach. Po utworzeniu migracji musisz ją wykonać, aby wprowadzić zmiany w schemacie bazy danych. Wykonaj polecenie:

php bin/console doctrine:migrations:migrate

Po zatwierdzeniu wykonania migracji, Doctrine zastosuje zmiany opisane w pliku migracji do bazy danych. W ten sposób struktura bazy danych zostanie zaktualizowana zgodnie z aktualnym stanem encji w aplikacji.

Wykonanie migracji.

Tworzenie kontrolera

Kolejnym krokiem jest stworzenie kontrolera. Kontroler jest odpowiedzialny za przetwarzanie żądań HTTP, zarządzanie danymi oraz przygotowanie odpowiedzi HTTP lub renderowanie widoków. Aby utworzyć kontroler, wykonaj następujące polecenie:

php bin/console make:controller PersonController

W wyniku wykonania tego polecenia zostaną utworzone:

Plik kontrolera PersonController.php w katalogu src/Controller. Ten plik zawiera klasę PersonController, która dziedziczy po klasie AbstractController z Symfony. W klasie PersonController będziesz dodawać metody (akcje) obsługujące różne operacje związane z encją Person, takie jak wyświetlanie listy osób, dodawanie, edycja czy usuwanie osób.

Plik szablonu Twig person/index.html.twig w katalogu templates. Ten plik będzie służył jako domyślny widok dla kontrolera. Możesz go modyfikować, aby dopasować go do potrzeb swojej aplikacji.

Tworzenie kontrolera w Symfony.

W tym kroku skorzystamy z generatora losowych danych, aby stworzyć przykładowe rekordy Person w bazie danych. Wykorzystamy do tego bibliotekę Faker. Aby korzystać z Faker, musisz go zainstalować za pomocą menedżera pakietów Composer. Otwórz terminal w katalogu projektu i wykonaj polecenie:

composer require fakerphp/faker

W pliku src/Controller/PersonController.php, dodaj następującą metodę generateRandomPersons():

    #[Route('/generate-random-persons', name: 'app_generate_random_persons')]
    public function generateRandomPersons(EntityManagerInterface $entityManager): Response
    {

        $existingPeople = $entityManager->getRepository(Person::class)->findAll();
        foreach ($existingPeople as $existingPerson) {
            $entityManager->remove($existingPerson);
        }
        $entityManager->flush();


        $faker = Factory::create();
        $people = [];

        for ($i = 0; $i < 10; $i++) {
            $person = new Person();
            $person->setName($faker->firstName())
                ->setSurname($faker->lastName())
                ->setAge($faker->numberBetween(18, 100))
                ->setEmail($faker->safeEmail());

            $entityManager->persist($person);
            $people[] = $person;
        }

        $entityManager->flush();

        return $this->render('person/random_people.html.twig', [
            'people' => $people,
        ]);
    }

Metoda generateRandomPersons() wykonuje następujące działania:
Pobiera wszystkie istniejące rekordy Person z bazy danych i usuwa je.
Tworzy 100 losowych rekordów Person za pomocą biblioteki Faker i zapisuje je w bazie danych.
Renderuje widok person/random_people.html.twig z listą wygenerowanych rekordów Person.

W powyższym kodzie usuwane są istniejące rekordy z tabeli następującym kodem:

$existingPeople = $entityManager->getRepository(Person::class)->findAll();
        foreach ($existingPeople as $existingPerson) {
            $entityManager->remove($existingPerson);
        }
        $entityManager->flush();

Można kod uprościć poprzez użycie metody truncate zamiast pobierania i usuwania każdego rekordu oddzielnie. Metoda truncate usuwa wszystkie rekordy z tabeli, co jest szybsze niż iteracyjne usuwanie każdego rekordu osobno. Kod wygląda następująco:

$entityManager->getConnection()->executeStatement('TRUNCATE TABLE person');

Tworzenie widoku

Stwórz plik random_people.html.twig w katalogu templates/person i umieść w nim poniższy kod:

{% extends 'base.html.twig' %}

{% block body %}
    <h1>Random People</h1>
    <table>
        <thead>
        <tr>
            <th>Name</th>
            <th>Surname</th>
            <th>Age</th>
            <th>Email</th>
        </tr>
        </thead>
        <tbody>
        {% for person in people %}
            <tr>
                <td>{{ person.getName() }}</td>
                <td>{{ person.getSurname() }}</td>
                <td>{{ person.getAge() }}</td>
                <td>{{ person.getEmail() }}</td>
            </tr>
        {% endfor %}
        </tbody>
    </table>
{% endblock %}

W przeglądarce przejdź pod adres: http://ormsynfony.localhost/generate-random-persons

Jeśli wszystko będzie ok, powinna wyświetlić się podobna do poniższej strona:

Utworzenie 100 randomowych rekordów w bazie danych.

W tym artykule omówiliśmy podstawowe kroki związane z tworzeniem aplikacji MVC w Symfony, konfiguracją bazy danych oraz współpracą z Doctrine ORM. Przedstawiliśmy również sposób generowania losowych danych za pomocą biblioteki Faker.

W kolejnym artykule będziemy kontynuować rozwój naszej aplikacji, dodając funkcje dodawania, wyświetlania, edycji i usuwania rekordów encji Person.

Leave a Comment

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *


Scroll to Top