Doctrine

Met Doctrine kan je databases en tabellen maken en hiermee communiceren. Het is reuze makkelijk om een tabel te maken en te beheren binnen Symfony. Daarnaast is het systeem slim: het houdt de wijzigingen netjes bij en voert veranderingen door waar nodig.

Maak een SQL-database aan

Je hebt vast wel een schema gemaakt nu van hoe je tabellen aan elkaar geknoopt worden, en nu moet je een lege SQL-database aanmaken. Weet je niet hoe je dit moet doen, dan is er wat werk aan de winkel.

  • Installeer eerst een sql-server op je computer, hoe je dit moet doen is afhankelijk van je besturingssysteem. In sommige Linux distributies zit deze overigens al ingebouwd.
  • De bekendste SQL beheerdersomgeving is PhpAdmin, maar ik persoonlijk vind Adminer beter.
  • Zorg dat je je SQL wachtwoord bij de hand hebt.
  • Je hoeft geen lege database aan te maken, dit doet Symfony voor je.

Installatie

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

Wijzig het .env bestand. Zoek de volgende regel en pas deze aan:

DATABASE_URL=mysql://sql_inlog_naam:sql_wachtwoord@127.0.0.1:3306/database_naam

Maak een Database aan

php bin/console doctrine:database:create

Maak een Entity aan

Met dit commando doe je eigenlijk niks anders dan de tabel met bijbehorende velden aanmaken. Doe je wat fout, geen nood want je kan alles naderhand nog veranderen.

php bin/console make:entity
  • Het veld 'id' wordt automatisch aangemaakt (AUTO INCREMENT). Je hoeft dit dus niet apart aan te maken.
  • Bekijk de Entity in src/Entity, je kan hier nog zaken in veranderen als je wilt.
  • Als je dit gedaan hebt is je tabel nog niet 'echt' aangemaakt, volg hiervoor de volgende stappen.

Maak de tabel

php bin/console make:migration

In scr/Migrations is nu een php-bestand aangemaakt met daarin de sql-commandos. Leuk om eens even naar te kijken, en dan ben je gelijk blij dat Symfony je dit uit handen neemt!

php bin/console doctrine:migrations:migrate

Nu is de tabel daadwerkelijk gemaakt. Klaar!

Hoe wijzig je tabellen?

Natuurlijk komt het voor dat je tabellen moet wijzigen. Er moet altijd wel een keer ergens 'een veldje bij of af', of je moet een koppeling aanbrengen tussen twee velden. Hier komt Symfony pas echt goed uit de verf want Symfony is 'slim', hij brengt de wijzigingen aan waar nodig.

  1. Maak eventuele wijzigingen in: scr/Entity/NaamEntity.php. Er is nu nog niks gewijzigd in de SQL database zelf.
  2. Voer hierna uit: php bin/console make:migration. Je maakt de benodigde PHP en SQL code hiermee aan. Nog wat vergeten? Geen probleem, rommel weer wat in je Entity en voer het hiervoor genoemde commando gewoon weer uit.
  3. Voer hierna uit: php bin/console doctrine:migrations:migrate. Nu zijn de wijzigen 'in het echt' doorgevoerd.
  4. Controleer de Doctrine status met: php bin/console doctrine:migrations:status

Overzicht

.env
  • src
    • Entity
    • Migrations

Gegevens plaatsen in een tabel

Gegevens plaatsen in een tabel zal natuurlijk meestal gaan via een Formulier (apart behandeld) maar hieronder wordt gedemonstreerd hoe je direct gegevens kan plaatsen. Deze code kan je dan weer uitbreiden. Het voorbeeld gaat uit van een klasse Werknemer die je hebt aangemaakt via Doctrine. Deze klasse bevindt zich dan in Entity/Werknemer.php.

Plaats onderstaande code maar eens in je Controller:

/**
 * @Route ("/genereer",name="werknemer_maken")
 */
public function genereer()
{
    $werknemer = new Werknemer();
    $werknemer->setWerknemerNaam("Piet Janssen");
    $werknemer->setWerknemerLoonschaal(8);

    //Aanroepen 'entity-manager'
    $em = $this->getDoctrine()->getManager();

     //Gegevens in tabel plaatsen
    $em->persist($werknemer);
    $em->flush();

    //Even checken op het scherm wat er gebeurt is en stoppen
    dump($werknemer);
    die;
}

Gegevens uit de tabel ophalen

Gegevens uit de tabel ophalen is zo gebeurt, het schermwerk gebeurt natuurlijk door Twig. Plaats onderstaande code in je controller:

/**
 * @Route ("",name="werknemers_tonen")
 */
public function index()
{
    //Activeer de 'entity manager' voor het vuile werk
    $em      = $this->getDoctrine()->getManager();

    //Haal nu alle records op
    $werknemers = $em->getRepository(Werknemer::class)->findAll();

    //En toon alles op het scherm met Twig!
    return $this->render('werknemer/toonalles.html.twig', [
        'werknemers' => $werknemers
    ]);
}

En om het op je scherm te toveren vogel je met Twig iets zoals:

<table>
    <thead>
        <tr>
            <th>Werknemer Naam</th>
            <th>Loonschaal</th>
        </tr>
    </thead>
    <tbody>
    {% for werknemer in werknemers %}
        <tr>
            <td>{{ werknemer.werknemersNaam }}</td>
            <td>{{ werknemer.werknemersLoonschaal }}</td>
        </tr>
    {% endfor %}
    </tbody>
</table>

En hier een voorbeeld van hoe je gegevens van slechts 1 record opvraagt. Je ziet dat er met de Route een id variabele wordt meegegeven.

/**
 * @Route ("/show/{id}",name="show_werknemer")
 */
public function show_werknemer($id)
{
    $em     = $this->getDoctrine()->getManager();
    $werknemer = $em->getRepository(Werknemer::class)->find($id);
    return $this->render('werknemer/show_werknemer.html.twig', [
        'werknemer' => $werknemer,
    ]);
}

Hier is natuurlijk nog niet alles mee gezegd, maar meer zaken zoals invoervelden en buttons worden behandeld bij Twig en Formulieren.

Relaties tussen Entities

Het hele doel van relaties is voorkomen dat je gegevens dubbel opslaat. Hoe doe je dit nu in Symfony?

Je moet altijd eerst de Entities aanmaken, anders heb je niks om aan elkaar te knopen.

  1. Ga naar scr/Entity en open de Entity waar je wat wilt veranderen. Haal hier het veld weg wat je wilt veranderen. Je gaat dit veld zo weer toevoegen aan de Entity, maar maakt er een koppelingsveld van. Sla de wijzigingen op.
  2. Typ in de terminal:
    php bin/console make:entity
  3. Geef de naam van de Entity, je krijgt vervolgens de melding dat deze al bestaat en dat je velden kan gaan toevoegen.
  4. Geef de naam van het koppelingsveld op maar zonder _id. Heb je dus een veld race wat met een nummer verwijst naar een andere tabel dan zal Symfony hier automatisch race_id van maken. Symfony zal achter elk koppelingsveld _id zetten overigens.
  5. Als er wordt gevraagd naar het field type typ dan in relation (dit wordt meestal al zelf aangevuld door Symfony).
  6. Kies nu het type relatie, dit zal vaak ManyToOne zijn. Symfony geeft bij elk type relatie wat voorbeelden, bestudeer deze.
  7. Geef de naam van de Klasse waaraan dit veld gekoppeld gaat worden. Dit moet een bestaande Klasse zijn, en deze wordt ook al vanzelf aangevuld door Symfony. Een teken dat je goed bezig bent!
  8. Nullable: meestal no, maar gebruik gerust yes als je het niet zeker weet.
  9. Je krijgt dan een vraag: Do you want to add a new property...: meestal yes antwoorden. Dit zorgt ervoor dat de relatie 'van twee kanten' is te benaderen. Dus bv vrouw ---> kinderen maar ook kinderen ---> vrouw.
  10. Je bent nu klaar, stop nu door op Enter te drukken.
  11. Voer nu de wijzigingen door:
    php bin/console make:migration
    Controleer de php code in migrations. Je zal zien dat Symfony bij sommige velden netjes _id heeft toegevoegd.
  12. Tevreden? Voer dan de wijzigingen door in de database met:
    php bin/console doctrine:migrations:migrate

Klaar! Je doet met Doctrine eigenlijk niks anders dan gecontroleerd tabellen aanmaken. Soms wat lastig, maar dat is SQL ook als je het zonder Symfony doet. Bovendien gebeurt het hier gecontroleerd, want Symfony kijkt over je schouder mee!

CRUD generator

Het is natuurlijk de bedoeling dat Symfony je werk uit handen neemt, en je kan met het volgende commando al heel wat voorwerk doen. Het kijkt naar een Entity en genereert automatisch alles wat nodig is om een een Tabel uit te lijsten en te bewerken (create/read/update/delete).

bin/console make:crud NaamEntity

Vervolgens krijg je netjes een lijst van welke bestanden Symfony voor je heeft gemaakt, het enige wat jij moet doen is deze zodanig bewerken dat ze geschikt zijn voor je website. Reuze makkelijk toch?

Een bestaande database importeren in Symfony

Natuurlijk komt het voor dat er al een database met tabellen met gegevens is, en dat je deze in je Symfony project moet importeren.

Voordat je begint, zorg ervoor dat de connectie met de sql-server correct is ingesteld in het .env bestand. Hier staat vermeld hoe je dat moet doen. Let op dat de tabellen altijd minimaal een primary key hebben.

We beginnen met om Symfony te vragen om van de bestaande tabellen allemaal Entities te maken in scr/Entity

php bin/console doctrine:mapping:import "App\Entity" annotation --path=src/Entity

Je krijgt netjes melding van de entities die aangemaakt zijn. Echter, de getters en setters zijn nog niet aangemaakt. We doen dit als volgt:

php bin/console make:entity --regenerate App

En je krijg weer netjes een melding dat de boel aangepast is.

Een Repository genereren voor een Entity

Als je al wat gevorderd bent in Symfony zal je ook graag een Repository willen aanmaken voor een Entity. Zorg er dan voor dat onderstaande regel in je Entity staat voordat je bovenstaande regel uitvoert:

/**
 * @ORM\Entity(repositoryClass="App\Repository\MijnKlasseRepository")
 */
class MijnKlasse
{
...
}

Database importeren met relationele tabellen

En hoe zit het met gerelateerde tabellen dan? Als je de correcte relaties al hebt aangemaak in sql dan zal Symfony deze netjes meenemen. Heb je dit niet gedaan dan moet je de Entities aanpassen.