SyMfonAK - vyvíjame databázy pomocou frameworku Symfony

Databázy (Doctrine ORM)

Z SyMfonAK
Prejsť na: navigácia, hľadanie

Symfony dokumentácia → Databázy (Doctrine ORM)


originál návod

Inštalácia Doctrine

Inštalujeme ORM pack a MakerBundle

 composer require symfony/orm-pack
 composer require --dev symfony/maker-bundle

Konfigurácia databázy

Nastavujeme v systémovej premennej DATABASE_URL v súbore .env

# .env (or override DATABASE_URL in .env.local to avoid committing your changes)

# customize this line!
DATABASE_URL="mysql://db_user:db_password@127.0.0.1:3306/db_name"

# to use sqlite:
# DATABASE_URL="sqlite:///%kernel.project_dir%/var/app.db"

Teraz už vieme vytvoriť databázu:

 php bin/console doctrine:database:create


Podrobnejšie nastavenia vieme spraviť v súbore config/packages/doctrine.yaml


Nastavenie databázy na UTF8 Dôležité je nastaviť Symfony pre spojenie s databázou znakovou sadou utf8. Inak defaultne databázy používajú latin1 napríklad. Ak nastavujem databázu MySQL (MariaDB), tak typicky v my.cnf

# od verzie 5.5.3 je zavedené utf8mb4, čo odporúča toto nastavenie:
collation-server      = utf8mb4_unicode_ci # nahrádza doteraz používané utf8_unicode_ci
charakter-set-server  = utf8mb4            # nahrádza doteraz používané utf8 
<pre>

v Symfony nastavíme preto:

<pre>
# app/config/config.yml
doctrine:
    dbal:
        charset: utf8mb4
        default_table_options:
            charset: utf8mb4
            collate: utf8mb4_unicode_ci

Zoznam všetkých príkazov získame takto:

php bin/console list doctrine


Vytvorenie triedy pre entitu

Adresár Entity v src/ (sf3: v src/AppBundle) obsahuje súbory, napr. "Menotbl.php", tieto reprezentujú entity (entita ako tabuľka databázy). Súbory Menotbl.php sú objekty.

Pomocníkom je príkaz make:entity formou otázok a volieb nakoniec vytvorí entitu. Napríklad

 php bin/console make:entity

Class name of the entity to create or update:
> Product

 to stop adding fields):
> name

Field type (enter ? to see all types) [string]:
> string

Field length [255]:
> 255

Can this field be null in the database (nullable) (yes/no) [no]:
> no

 to stop adding fields):
> price

Field type (enter ? to see all types) [string]:
> integer

Can this field be null in the database (nullable) (yes/no) [no]:
> no

 to stop adding fields):
>
(press enter again to finish)


Column types:

   string: Type that maps a SQL VARCHAR to a PHP string.
   integer: Type that maps a SQL INT to a PHP integer.
   smallint: Type that maps a database SMALLINT to a PHP integer.
   bigint: Type that maps a database BIGINT to a PHP string.
   boolean: Type that maps a SQL boolean or equivalent (TINYINT) to a PHP boolean.
   decimal: Type that maps a SQL DECIMAL to a PHP string.
   date: Type that maps a SQL DATETIME to a PHP DateTime object.
   time: Type that maps a SQL TIME to a PHP DateTime object.
   datetime: Type that maps a SQL DATETIME/TIMESTAMP to a PHP DateTime object.
   datetimetz: Type that maps a SQL DATETIME/TIMESTAMP to a PHP DateTime object with timezone.
   text: Type that maps a SQL CLOB to a PHP string.
   object: Type that maps a SQL CLOB to a PHP object using serialize() and unserialize()
   array: Type that maps a SQL CLOB to a PHP array using serialize() and unserialize()
   simple_array: Type that maps a SQL CLOB to a PHP array using implode() and explode(), with a comma as delimiter. IMPORTANT Only use this type if you are sure that your values cannot contain a ”,”.
   json_array: Type that maps a SQL CLOB to a PHP array using json_encode() and json_decode()
   float: Type that maps a SQL Float (Double Precision) to a PHP double. IMPORTANT: Works only with locale settings that use decimal points as separator.
   guid: Type that maps a database GUID/UUID to a PHP string. Defaults to varchar but uses a specific type if the platform supports it.
   blob: Type that maps a SQL BLOB to a PHP resource stream



Pridanie viac položiek

Generovanie getterov a settterov, novší spôsob pomocou MakerBundle, v starších verziách SensioGeneratorBundle.

Príkazom make:entity


staršie ako sf3.4 príkazom $ php bin/console doctrine:generate:entities AppBundle/Entity/MenoEntity


založenie tabuliek (schémy) databázy

$ php bin/console doctrine:schema:update --force

To je ale nebezpečnejšie, než nechať si vygenerovať príkazom make:migration sql príkazy, ktoré si potom upravíme! Najmä ak viacero aplikácii používa rovnakú databázu, aby niektorá entita nezrušila pre ňu nedefinované položky.

Migration: založenie tabuliek (schémy) databázy

php bin/console make:migration

Týmto príkazom sa vytvorí súbor s SQL príkazmi v adresári src/Migrations. Tieto treba spustiť:

php bin/console doctrine:migrations:migrate

Súbor udržuje všetky potrebné príkazy pre update databázy. Treba ho spustiť aj na produkčnom, keď sa nasadzuje nová verzia. Sled SQL príkazov zabezpeční korektný update aj samotnej ostrej databázy.

Poznámka: Po zvýšení verzia na Symfony 5 som dostal chybové hlásenia, že DoctrineMigrations nie je platný adresár, preto som zmenil v config/doctrine_migrations.yaml nastavenie takto:

zakomentoval som riadok:

  1. namespace: DoctrineMigrations

a odkomentoval som riadok: dir_name: '%kernel.project_dir%/src/Migrations'

Migrations a pridávanie ďalších položiek

Ak je treba pridať ďalšie položky do tabuliek, opäť stačí spustiť príkaz

 php bin/console make:entity

Class name of the entity to create or update
> Product

 to stop adding fields):
> description

Field type (enter ? to see all types) [string]:
> text

Can this field be null in the database (nullable) (yes/no) [no]:
> no

 to stop adding fields):
>
(press enter again to finish)


V našom príklade pridá položku description a príslušné metódy getDescription() a setDescription().

// src/Entity/Product.php
// ...

class Product
{
    // ...

+     /**
+      * @ORM\Column(type="text")
+      */
+     private $description;

    // getDescription() & setDescription() were also added
}

Tieto zmeny treba zaznamenať aj do SQL príkazov súboru pre migráciu.

php bin/console make:migration

V súbore pribudne príkaz ALTER TABLE product ADD description LONGTEXT NOT NULL. V tomto nástroji je zabudovaná potrebná ingeligencia na logický sled. Udržuje ich vo vlastnej tabuľke.

Potom nasleduje vykonanie zmien:

php bin/console doctrine:migrations:migrate

Pri každej zmene schémy databázy vo vývoji treba spustiť tieto dva príkazy. Pri nasadení do ostrej prevádzky treba migračné súbory poslať tiež a tam aj spustiť.

V prípade že ručne pridáme nové položky a editujeme súbory Entít, vieme si uľahčiť prácu a dať si vygenerovať potrebné getters a setters metódy takto:

php bin/console make:entity --regenerate

Ak chceme obnoviť všetky metódy getters a setters použijeme parameter --overwrite.


Vloženie objektu do databázy

Necháme si vytvoriť potrebný kontrolér, uľahčíme si prácu aj v tomto bode prípravy.

php bin/console make:controller ProductController

V tomto novom kontroléri potom napíšeme funkciu na vytváranaie nových objektov do tabuľky databázy.

// src/Controller/ProductController.php
namespace App\Controller;

// ...
use App\Entity\Product;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\Response;

class ProductController extends AbstractController
{
    /**
     * @Route("/product", name="create_product")
     */
    public function createProduct(): Response
    {
        // you can fetch the EntityManager via $this->getDoctrine()
        // or you can add an argument to the action: createProduct(EntityManagerInterface $entityManager)
        $entityManager = $this->getDoctrine()->getManager();

        $product = new Product();
        $product->setName('Keyboard');
        $product->setPrice(1999);
        $product->setDescription('Ergonomic and stylish!');

        // tell Doctrine you want to (eventually) save the Product (no queries yet)
        $entityManager->persist($product);

        // actually executes the queries (i.e. the INSERT query)
        $entityManager->flush();

        return new Response('Saved new product with id '.$product->getId());
    }
}

Vysvetlenie:

Objekt $this->getDoctrine()->getManager() - entity manažér Doctrine je najdôležitejší pre prácu s databázou v Doctrine, je zodpovedný za ukladanie ale aj výber. S objektom $product pracujeme ako s bežným PHP objektom. Príkaz persist($product) pripraví potrebné, zatiaľ neukladá a nevykonáva sql príkazy. Tie vybaví až príkaz flush().

Ak sa objavia problémy Doctrine\ORM\ORMException, preštuduj Transactions and Concurrency.


Vyskúšame v prezerači. http://localhost:8000/product

Overíme príkazom konzoly:

php bin/console doctrine:query:sql 'SELECT * FROM product'

Pre užívateľov využívajúcich PowerShell:

php bin/console doctrine:query:sql "SELECT * FROM product"


Výber objektu z databázy

Získanie objektu z databázy je ľahké. Predpokladajme že sme pripravili smerovanie aby sme mohli zobraziť jednu parcelu podľa jej položky id.

public function zobrazAction($parcelaId)
{
    $parcela = $this->getDoctrine()
        ->getRepository(Parcely::class)
        ->find($parcelaId);

    if (!$parcela) {
        throw $this->createNotFoundException(
            'Nebola nájdená parcela zvolenej hodnoty id '.$parcelaId
        );
    }

    // ... vykonaj niečo, napríklad zobraz $parcela v templatu
}

Toto sa dá dosiahnuť aj bez jediného kódu využitím skratky pomocou @ParamConverter. Podrobnosti o tejto téme možno nájsť Param konverter.


Validácia objektu

Validácia Symfony využíva na vykonanie základných validácii metadáta Doctrine. Od verzie Symfony 4.3 je vykonávaná základná validácia automaticky.



Úprava existujúceho objektu v databáze

zmazanie objektu

Dotazy na objekty

DQL dotazy

Dotazy pomocou Doctrine Query Builder

Ukladanie vlastných dotazov repozitárov

Príkaz make:entity vytvorí nielen samotnú entitu ale aj repozitár. Príkaz vie aj znovu vytvoriť repozitár neskôr príkazom make:enity --regenerate.

Konfigurácia

Odkazy na typy polí

Relácie a asociácie

Ako pracovať s asociáciami/reláciami Doctrine

Myšlienky na záver

Naučte sa viac

Pozri aj