BF Summer sales
Pouze tento týden sleva až 80 % na HTML & CSS a JavaScript
80 % bodů zdarma na online výuku díky naší Letní akci!

Lekce 6 - Jednoduchý redakční systém v Laravel - Migrace

V minulé lekci, Jednoduchý redakční systém v Laravel - Struktura projektu, jsme si popsali strukturu Laravel aplikace a vytvořili si nový projekt.

V dnešním PHP tutoriálu si vysvětlíme, co jsou to migrace a vytvoříme si také svoji vlastní.

Databáze

Údaje k připojení k databázi jsme si nastavili v minulé lekci. O samotné připojení se však starat nemusíme - to za nás řeší framework na pozadí. Pro práci s databází budeme používat Eloquent ORM, kdy každá databázová tabulka má vlastní model (třídu) a skrz tento model pracujeme s danou tabulkou. Jak se ale spravuje databázová struktura v Laravel frameworku?

Generování databázové struktury

Představme si situaci, kdy pracujeme s někým na našem projektu a následně potřebujeme změnit sloupeček v databázové tabulce. Jak tohoto elegantně dosáhnout? Jedním z řešení je sdílet MySQL kód této změny s dalšími vývojáři dané aplikace. To je však velice neefektivní a nespolehlivé. Při nahrávání změn na produkční server se může na některé části MySQL kódu zapomenout a to by způsobilo nefunkčnost aplikace. Jenže takováto situace nesmí nastat u reálné aplikace, zákazník by asi nebyl moc spokojený :) Z tohoto a dalších důvodů vznikly migrace.

Migrace jsou něco jako verze databáze. Modifikujeme skrz ně databázovou strukturu pomocí PHP kódu přes builder nebo spouštěním MySQL příkazů. Výhodou migrací je, že se vykonají pouze jednou. Navíc se v nich můžeme vracet zpět, což se hodí, pokud uděláme nějakou chybu při vývoji.

Migrace najdeme ve složce database/migrations/ a pokud si tuto složku nyní otevřeme, zjistíme, že již obsahuje 2 soubory. Jeden nám vygeneruje tabulku uživatelů a druhý tabulku pro neúspěšné úlohy běžící na pozadí (tzv. jobs). Vysvětleme si migrace na souboru 2014_10_12_000000_create_users_table.php, jehož obsah je následující:

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('email')->unique();
            $table->timestamp('email_verified_at')->nullable();
            $table->string('password');
            $table->rememberToken();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('users');
    }
}

Každá migrace se skládá ze dvou metod: up() a down():

  • Metoda up() slouží ke změně databázové tabulky (například přidání nového sloupečku nebo klíče).
  • Metoda down() je přesným opakem metody up(). Bude zavolaná v případě, kdy chceme změny vrátit zpátky.
Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!

Pro správu databázové struktury přes migrace používáme builder Schema. Tomu poté předáme jako parametr instanci třídy Blueprint zastupující tabulku.

Proč vlastně Laravel již v základu obsahuje tyto 2 migrace? Jak už jsem psal v úvodní lekci, Laravel je optimalizovaný pro reálné webové aplikace a kvůli tomu také obsahuje nejčastěji používané tabulky. Tím důležitějším důvodem (platí hlavně pro migraci uživatelů) je však to, že si můžeme nechat vygenerovat celou část registrace a přihlašování uživatelů. To je však předmětem až dalších lekcí.

Vytváření modelu článku

Nejdříve bychom měli začít vytvářením tabulky pro budoucí model článku. Migrace si můžeme nechat vygenerovat spolu s Eloquent modely, podíváme se jaké k tomu máme možnosti. Na to použijeme v terminálu Artisan příkaz help:

php artisan help make:model

Po vložení příkazu uvidíme následující výstup:

Výstup Artisan příkazu help pro tvorbu modelů v PHP frameworku Laravel

Jak si můžeme všimnout, máme na výběr mnoho možností. Popisovat si je všechny pro nás zatím nemá význam. Většinu z nich se naučíme používat postupně. Nás budou nyní zajímat tyto dvě možnosti:

  • --resource - Vytvoří CRUD kontroler využívající instance modelu. To je kontroler pro operace k přidání, zobrazení, editaci a odstranění dané položky, v našem případě článku.
  • --migration - Vygeneruje migraci pro vytvoření tabulky modelu. Tím pro položku vytvoříme i databázovou tabulku.

Vložíme tedy následující příkaz pro vytvoření modelu článku s těmito možnostmi:

php artisan make:model --resource --migration Article

Migraci a kontroler lze vytvořit i zvlášť. Zápis výše je pouze zkrácením následujících příkazů:

php artisan make:model Article
php artisan make:migration --create=articles create_articles_table
php artisan make:controller --model=Article ArticleController

Výstup příkazu při úspěchu vypadá následovně:

Výstup Artisan příkazu pro tvorbu modelů v PHP frameworku Laravel

Jak lze vidět na obrázku výše, vygenerovaly se nám tři požadované soubory. Nejdříve začneme už zmíněnou migrací pro vytvoření tabulky článků.

Migrace tabulky článků

Určitě se shodneme na tom, že každý článek musí mít své ID, podle kterého ho budeme identifikovat např. při jeho editaci. Zároveň ale naše tabulka bude obsahovat sloupce created_at a updated_at definující časy vytvoření a poslední úpravy. Tyto sloupečky, spolu s id, jsou již jako výchozí zahrnuty v každé vygenerované tabulce. My si nyní navíc přidáme titulek, (unikátní) URL, obsah a popisek článku.

Migrační soubor pro vytvoření tabulky článků s názvem ..._create_articles_table.php, který najdeme ve složce database/migrations/, tedy upravíme do následující podoby:

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateArticlesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('articles', function (Blueprint $table) {
            $table->id();
            $table->string('title');
            $table->string('url')->unique();
            $table->string('description');
            $table->text('content');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('articles');
    }
}

Migrační soubory se pro vás můžou lišit datem v jejich názvu. Toho lze však využít v případě, kdy bychom chtěli, aby se některá z migrací provedla dřív. Pozměnili bychom pouze toto datum v jméně souboru.

Nyní spustíme migraci přes příkaz php artisan migrate, jehož výsledkem bude vytvoření migrační databázové tabulky, která si uchovává všechny spuštěné migrace. Dále se samozřejmě vytvoří i tabulky uživatelů, resetovaných hesel, článků a neúspěšných úloh:

Spuštění první migrace v PHP frameworku Laravel

Výstup se může lišit na základě data vytvoření daných migrací, které je reflektované v jejich názvu a které může být popřípadě upraveno. Proto se migrace s články provede dříve než migrace s tabulkou pro neúspěšné úlohy.

Model článku

Přesuneme se k modelu. Ten najdeme hned ve složce app/ s názvem Article.php. Nyní obsahuje pouze vytváření třídy Article dědící z Model. Možná vás to překvapí, ale již v této fázi je model naprosto funkční. Všechny metody, které budeme potřebovat pro práci s databází (vyhledávání, vytváření, upravování), obsahuje Model, jenž definuje právě Eloquent ORM.

Tabulku, se kterou má daný model pracovat, specifikovat nemusíme. Názvy modelů se totiž odvíjí od názvu tabulek, kdy tabulka je v množném čísle názvu dané entity a model v jednotném, protože zastupuje právě jeden řádek databázové tabulky. Pokud bychom toto z nějakého důvodu nedodržovali a chtěli jiný název tabulky, můžeme tento název definovat skrz proměnnou $table:

/**
 * The table associated with the model.
 *
 * @var string
 */
protected $table = 'articles';

Kontroler článku

Nyní se podíváme na vygenerovaný kontroler článku ve složce app/Http/Controllers/ s názvem ArticleController.php. Ten obsahuje již CRUD metody pro akce výpisu článků, vytvoření nového, editaci a odstranění:

<?php

namespace App\Http\Controllers;

use App\Article;
use Illuminate\Http\Request;
use Illuminate\Http\Response;

class ArticleController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return Response
     */
    public function index()
    {
        //
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return Response
     */
    public function create()
    {
        //
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  Request $request
     * @return Response
     */
    public function store(Request $request)
    {
        //
    }

    /**
     * Display the specified resource.
     *
     * @param  Article $article
     * @return Response
     */
    public function show(Article $article)
    {
        //
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  Article $article
     * @return Response
     */
    public function edit(Article $article)
    {
        //
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  Request $request
     * @param  Article $article
     * @return Response
     */
    public function update(Request $request, Article $article)
    {
        //
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  Article $article
     * @return Response
     */
    public function destroy(Article $article)
    {
        //
    }
}

Typicky se tyto metody používají následovně:

  • index() - Zobrazení seznamu článků (můžeme využít pro administraci)
  • create() - Zobrazení formuláře pro vytvoření článku
  • store() - Vytvoření článku z předávaných hodnot formuláře
  • show() - Zobrazení samotného článku
  • edit() - Zobrazení formuláře pro editaci článku
  • update() - Upravení databázového záznamu s článkem
  • destroy() - Odstranění článku z databáze

Využívání CRUD kontrolerů extrémně ulehčuje práci, jelikož jejich routování je daleko jednodušší a zároveň nám to přidává další možnosti v rámci práce s daným kontrolerem.

V další lekci, Jednoduchý redakční systém v Laravel - Výpis článku, si zobrazíme náš první článek. Navíc si budete moci stáhnout zdrojové kódy v případě, že jste měli s čímkoli problém :)


 

Předchozí článek
Jednoduchý redakční systém v Laravel - Struktura projektu
Všechny články v sekci
Laravel framework pro PHP
Článek pro vás napsal Jan Lupčík
Avatar
Jak se ti líbí článek?
10 hlasů
Autor se primárně věnuje vývoji webových stránek a aplikacích v PHP (speciálně ve frameworku Laravel) a je jedním z vývojářů komunitní modifikace TruckersMP.
Aktivity (16)

 

 

Komentáře

Avatar
Jaroslav Patrný:14. února 3:51

Ahoj, po spuštění php artisan migrate místo vytvoření tabulek vyhozena výjimka "Illuminate\Da­tabase\QueryEx­ception ..." Dosud bylo všechno O.K., co jsem udělal blbě?

 
Odpovědět
14. února 3:51
Avatar
Jan Lupčík
Super redaktor
Avatar
Odpovídá na Jaroslav Patrný
Jan Lupčík:14. února 9:02

Ahoj, jak už z chyby vyplývá, připojení k databázi bylo neúspěšné, tj. uvedené údaje v konfiguračním souboru projektu .env nejsou správné. Zkontroluj si je, spusť příkaz php artisan config:clear a nech migrace opět proběhnout.

Odpovědět
14. února 9:02
TruckersMP vývojář
Avatar
Jaroslav Patrný:17. února 5:59

Ahoj, kde může být chyba v konfiguračním souboru? Našel jsem také chyby v kompilaci frontendových souborů (viz 2. screenshot), ale ty by s tím neměly souviset.

 
Odpovědět
17. února 5:59
Avatar
Jaroslav Patrný:17. února 6:07

Když spustím příkaz npm run dev

 
Odpovědět
17. února 6:07
Avatar
Odpovídá na Jan Lupčík
Jaroslav Patrný:19. února 1:23

Ahoj, chybu v konfiguraci jsem už odstranil, ale stále přetrvávají chyby při kompilaci frontendu po spuštění příkazu

npn run dev

(viz log). Mám Win7 SP1 64bit, Node 12.16.1-x64.

 
Odpovědět
19. února 1:23
Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!
Avatar
jakubhoral
Člen
Avatar
jakubhoral:7. března 16:08

Ahoj, mám problém s příkazem: php artisan migrate. Vyhazuje mi chybu viz obr.Přijde mi, že se nejde připojit k databázi proto, že žádná neběží. Jak tu databázi na základě nastavení toho .env souboru spustím?
Projekt spouštím variantou: php artisan serve. Ten ale nespoučtí mysql server.

 
Odpovědět
7. března 16:08
Avatar
Odpovídá na jakubhoral
Martin Kašpar:7. března 17:15

Databázi pomocí .env ani php artisan serve nespustíš. Příkaz php artisan serve je vlastně totéž jako php -S 127.0.0.1:8000 -t /cesta_k_projektu/ - spouští webový miniserver s php. Oproti tomu je MySQL, SMTP nebo třeba Redis externím zdrojem, na který se Laravel (PHP) připojuje. Pro vývoj s databází si musíš alespoň lokální MySQL nainstalovat a rozchodit samostatně.

Pokud by Ti v tom bránila technická omezení nebo něco jiného, pak je alternativní možností pro menší databázi nebo lokální vývoj použít SQLite - samozřejmě za cenu nevýhod jako je menší výkon a složitější převod dat mezi rozdílnými databázovými systémy na testu a produkci. Stačí vytvořit místní sqlite3 databázový soubor a překonfigurovat Laravel pro jeho použití. Laravel je v ohledu použitelných databázových systémů dost flexibilní.

 
Odpovědět
7. března 17:15
Avatar
jakubhoral
Člen
Avatar
Odpovídá na Martin Kašpar
jakubhoral:7. března 18:36

Ok, zkoušel neúspěšně rozjet přes MAMP a XAMPP a nakonec pomohl Homestead.

 
Odpovědět
7. března 18:36
Avatar
Jan Štěch
Super redaktor
Avatar
Jan Štěch:15. června 14:38

Jak přesně vytváří Laravel názvy tabulek podle názvů modelů? Přidá k ni prostě vždycky "s", aby vytvořil množné číslo a automaticky předpokládá, že jsme model pojmenovali anglicky, nebo má i ošetřenou složitější tvorbu množných čísel (ať už u slov končících třeba na "s": moss - mosses, nebo i u nepravidelných slov: fish - fish [lepší příklady mě nenapadají]).

 
Odpovědět
15. června 14:38
Avatar
Jan Lupčík
Super redaktor
Avatar
Odpovídá na Jan Štěch
Jan Lupčík:15. června 18:53

Ahoj, ano, samotný framework má na to svojí metodu. Každopádně jak je zmíněno v článku, pokud by nastal nějaký případ, ve kterém se název modelu a databázové tabulky neshoduje, můžeš definovat tento název přes třídní proměnnou $table.

Odpovědět
15. června 18:53
TruckersMP vývojář
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 10 zpráv z 10.