xvital

xvital

@xvital
Praha, CZ

Web & Laravel enthusiast

Sep 12, 2019

Stripe už aj na Slovensku! Od 12.9.2019

xvital vytvoril tému Stripe už aj na Slovensku! Od 12.9.2019

Dnes predobedom mnohým z nás dorazil dlho očakávaný email s takýmto úvodom:

Hello,

A while back, you registered on stripe.com/global to be notified when Stripe became available in Slovakia. 

Great news: we’re happy to tell you that you can now create a Stripe account in Slovakia! Check out our blog for more details or register for your account using the button below.

Vďaka Stripe je možné prijímať platby kartou (Visa, Mastercard alebo AmericanExpress) vo viac ako 135 menách, s plným prístupom do prehľadného unifikovaného administračného rozhrania, ktoré Stripe ponúka.

Produkty, ktoré je možné využívať:

  • Stripe Connect (Standard aj Custom Connect)
  • Stripe Billing pre opakované platby (subscriptions), napríklad pre Saas
  • Stripe Radar
  • lokálne spôsoby platby dostupné kdekoľvek v Európe

Stripe a ceny transakcií

Pre európske platobné karty platí cena 1,4% + 0,25€ Pre platobné karty vydané mimo EU je cena 2,9% + 0.25€ *V prípade, že je potrebný prevod z inej meny, Stripe si za takúto transakciu účtuje ešte 1% navyše.

Služba okamžitého vyplatenia (Instant payout) je dostupná za poplatok 1% z transakcie.

Stripe a podpora slovenského jazyka

V tomto smere si zatiaľ budeme musieť vystačiť s angličtinou. Podpora, rozhranie a dokumentácia budú zatiaľ dostupné v angličtine.

Táto správa asi poteší množstvo prevádzkovateľov online biznisov a to hneď z niekoľkých dôvodov:

  • cena (pre porovnanie, GoPay si za transakciu berie 2,2% + 0,11€)
  • možnosti implementácie a prispôsobenia
  • prepracovaný dashboard
  • detailná a veľmi kvalitne spracovaná dokumentácia

Ak chcete využiť Stripe pre váš projekt postavený na Laraveli, dávam do pozornosti oficiálny package Cashier.

Sep 4, 2019

Laravel 6 je vonku

xvital vytvoril tému Laravel 6 je vonku

Team okolo Laravelu včera s malým sklzom vypustil do sveta novú verziu frameworku - 6.0.

Okrem sémantického verzovania, spomenutého aj v krátkej správe tu na webe, prichádza v6 s kompatibilitou pre Laravel Vapor a mnohými ďalšími vylepšeniami ale aj úplne novými funkciami.

Zásadnou správou je fakt, že Laravel 6.0je LTS verziou, ktorá bude oficiálne podporovaná do 3.9.2021, resp. 2022 (bugy/bezpečnosť).

Verzia 6.0 nie je prelomovou verziou, a plynule nadväzuje na vylepšenia verzie 5.8. Viac informácií nájdete v oficiálnych release notes.

Zároveň dávam do pozornosti upgrade guide, ktorý obsahuje len minimum zásadných zmien, ktoré sa dotknutú naozaj každého 5.8 projektu.

Upgradu sa netreba báť, naozaj nejde o zásadnú zmenu.

Aug 21, 2019

Nový web ako predzvesť príchodu verzie 6.0 (laravel.com)

xvital vytvoril tému Nový web ako predzvesť príchodu verzie 6.0 (laravel.com)

Avizovaný web v novom šate vrátane nového loga je online! Pozrieť si ho môžete priamo na oficiálnej doméne projektu - laravel.com.

Web pôsobí prijemným, čistým dojmom. Dokumentácia je dobre čitateľná, aj ked chvíľu asi potrvá, kým si na zmenu osobne zvyknem. Každopádne, podľa mňa krok správnym smerom, a oceňujem hlavne fixed sidebar v rámci doku. Veľmi praktická vec, čo mi na starom webe chýbalo.

Svoje názory, postrehy a komentáre k novému webu môžete písať sem do diskusie.

Jul 26, 2019

Laravel v6 už v auguste 2019

xvital vytvoril tému Laravel v6 už v auguste 2019

Dnes len stručne, pretože detaily zatiaľ nepoznáme.

Každopádne, Taylor Otwell na svojej laravelovskej konferencii Laracon (NY) oznámil, že nová verzia Laravelu pôjde na svetlo sveta už v auguste tohto roka. Laravel v rámci releasu verzie 6.0 príde s novým brandingom aj webom. Okrem toho budú ďalšie vydania nasledovať pravidlá sémantického verzovania.

Noviniek bude samozrejme omnoho viac, na tie si však budeme musieť počkať do skončenia Laraconu.

Jul 17, 2019

Spracovanie veľkých XML súborov

xvital vytvoril tému Spracovanie veľkých XML súborov

Nie je to síce priamo Laravel, ale tento tip na knižnicu by sa mohol hodiť mnohým z vás, ktorý sa dostanete do styku s väčšími XML dokumentami. Jej implementácia/použitie je veľmi jednoduché.

Nedávno som dostal za úlohu spracovať asi stovku produktových XML feedov. Drvivú väčšinu z nich nemal problém Simple XML spracovať, pretože neboli tak rozsiahle, aby sa nevošli do pamäte. Niekoľko feedov však obsahovalo 100k+ záznamov a to už pretekalo.

Na spracovanie som využil XML String Streamer, ktorý prechádza XML dokument postupne, po jednotlivých uzloch stromu nastavenej úrovne. Do pamäte sa vďaka tomu načítava práve jeden uzol, takže pamäťové nároky sú úplne minimálne.

Príklad z dokumentácie.

XML

<?xml version="1.0" encoding="UTF-8"?>
<gigantic>
    <customer>
        <firstName>Jane</firstName>
        <lastName>Doe</lastName>
    </customer>
    ...
</gigantic>

Vytvorenie Streamera a parsovanie dokumentu po uzloch

$streamer = Prewk\XmlStringStreamer::createStringWalkerParser("gigantic.xml");

while ($node = $streamer->getNode()) {
    $simpleXmlNode = simplexml_load_string($node);
    echo (string)$simpleXmlNode->firstName;
}

K dispozícii sú dva parsery (StringWalker, UniqueNode) a tri možnosti, ako získať dáta:

  1. Stream/File pre čítanie súborov z disku
  2. Stream/Stdin pre čítanie zo štandardného konzolového vstupu STDIN
  3. Stream/Guzzle pre stream prostredníctvom HTTP pomocou knižnice Guzzle.

Knižnica ponúka aj pomerne široké možnosti konfigurácie.

Viac informácií nájdete priamo na githube projektu: xml-string-streamer

Jul 15, 2019

Artisan: Progress bar

xvital vytvoril tému Artisan: Progress bar

Pozrime sa na okrajovú záležitosť pre fajnšmekrov, ktorá sa môže hodiť práve vám.

V mnohých projektoch som si všimol, že na zobrazenie aktuálneho stavu vykonávania určitej operácie sa používa vypisovanie na štandardný výstup do konzoly. Je to klasické riešenie, ktoré funguje dobre. Pri rozsiahlejších operáciach však môže dochádzať ku generovaniu neprimerane dlhých výstupov a tým pádom "špineniu" konzoly.

Laravel ponúka veľmi elegantnú možnosť, ako takú situáciu riešiť pomocou progress baru. Riešenie je požičané zo Symfony a funguje naozaj perfektne.

$posts = App\Posts::all();

$bar = $this->output->createProgressBar(count($posts));

foreach ($posts as $post) {
    $this->updatePost($post);

    $bar->advance();
}

$bar->finish();
  1. createProgressBar() vytvorí inštanciu progress baru. Ako parameter definujete celkový počet krokov, ktoré sa budú vykonávať.
  2. V tele cyklu zavoláte advance() zakaždým, keď vykonáte jeden krok
  3. Na záver zavoláte finish(). Zabezpečí, že progress bar bude na 100%.

Poznámka: v prípade, že chcete inkementovať progress bar o viac krokov naraz, stačí metóde advance parametrom predať počet krokov.

Viac infomrácií k progress barom nájdete v dokumentácii Laravelu alebo Symfony

Jul 14, 2019

Hydratácia - "oživovanie" polí

xvital vytvoril tému Hydratácia - "oživovanie" polí

Je pravdepodobné, že s nasledovnou situáciou ste sa už stretli. Chcete vybrať dáta z databázy pokročilejším dotazom, no výber sa snažíte krkolomne napasovať na možnosti Eloquentu len preto, aby sa vám dáta vrátili ako kolekcia objektov a vy ste na nich mohli ďalej aplikovať fancy features, ktoré Eloquent ponúka.

To však nie je vôbec nutné. Napríklad jednoduchý MATCH AGAINST nad fulltextovým indexom za vás Eloquent pripraviť nedokáže.

$dry_posts = DB::table('posts')
   ->selectRaw('*, MATCH (title) AGAINST (?) AS reltitle, MATCH (excerpt) AGAINST (?) AS relexcerpt', [$query, $query])
   ->whereRaw('MATCH (title, excerpt) AGAINST (?)', [$query])
   ->orderByRaw('(reltitle * 1.3)+(relexcerpt) DESC')
   ->take(5)
   ->get();

Výsledkom takého raw selectu je kolekcia obsahujúca pole výsledkov, vrátených databázou. Položky poľa obsahujú všetky dáta jednotlivých záznamov, ale je to pole. Žiadne pekné metódy si na jednotlivé položky poľa nezavoláte.

Ak však vrátené pole hydratujete:

$posts = Post::hydrate($dry_posts->toArray());

// $posts->each(function ($post)) {
//    echo $post->comments()->first();
// }

Výsledkom bude kolekcia Eloquent objektov a môžete s nimi ďalej pracovať úplne rovnako, ako keby ste ich dostali z Post::where(...)->get().

Poznámka: Nezabudnite, že metóda hydrate príjma v argumente pole!

Jun 19, 2019

Ako sa dostanem k uloženým cookies?

xvital odpovedal v téme Ako sa dostanem k uloženým cookies?

A ako pracujes s cookie Ty?

Tipujem, ze cookie len vyrobis, ale neodosles ju v ramci odpovede. Dolezite je uvedomit si zakladnu vec - cookie sa ukladaju v prehlidaci navstevnika/uzivatela. V runtime nemozes ulozit cookie do prehliadaca navstevnika. Cookie potrebujes vyrobit A nasledne poslat s HTTP odpovedou. Jedine to je cesta ako susienku zapisat.

Samotna metoda Cookies::make() sa postara o vytvorenie cookie, ale tu este musis odoslat. Na to mozes pouzit bud

return response('Hello World')->cookie($cookie);

alebo cookie vyrobis a odlozis na odoslanie s najblizsou odpovedou

Cookie::queue('name', 'value', $minutes);

Metoda Cookie::queue() prijma v argumente aj instanciu cookie vytvorenu Cookie::make()

Cookie::queue(Cookie::make('name', 'value', $minutes));

K takto vytvorenym cookies potom pristupujes v ramci aktualneho requestu ako $request->cookie('name'), alebo pouzijes fasadu Cookie tak ako to pravdepodobne robis teraz, pomocou Cookie::get('my_cookie').

Tiez si treba uvedomit, ze ak posles cookie v odpovedi, tak dostupna v requeste bude az v najblizsom HTTP cykle, teda v dalsej poziadavke, ktora ti pride.

Snad to pomoze.

Jun 15, 2019

Laravel 5.8.22: Eager loading pre polymorfické vzťahy

xvital vytvoril tému Laravel 5.8.22: Eager loading pre polymorfické vzťahy

Dávnejšie som sa rozhodol, že nedáva zmysel publikovať (kopírovať) release notes pre každý nový patch, ktorý výjde.

Laravel 5.8.22 však prináša zaujímavú a celkom široko použiteľnú možnosť prednačítať polymorfické vzťahy modelov. Doteraz to bolo možné len pre vzťahy typu 1:1, 1:N a N:M.

Od verzie 5.8.22 môžete využiť aj túto možnosť

$comments = Comment::query()
    ->with(['commentable' => function (MorphTo $morphTo) {
        $morphTo->morphWith([Post::class => ['user']]);
    }])
    ->get();

Okrem toho samozrejme pribudlo aj niekoľko ďalších vecí a fixov. Kompletný changelog pre v.5.8.22 je na githube.

May 24, 2019

Nefunguje artisan storage:link

xvital odpovedal v téme Nefunguje artisan storage:link

V tom pripade musis vytvarat link v Homestead.

Takze, prihlas sa ssh-ckom do Homestead, odtial pusti artisan storage:link a malo by to fungovat.

Nefunguje artisan storage:link

xvital odpovedal v téme Nefunguje artisan storage:link

Zdravim, @misko95.

Aky setup pouzivas pre lokalny vyvoj? Server bezi priamo u teba, alebo vo VM?

May 7, 2019

Validácia hesiel podľa doporučení NIST

xvital vytvoril tému Validácia hesiel podľa doporučení NIST

Balík obsahuje validačné pravidlá podľa odporúčaní Národného inštitútu pre štandardy a technológie (NIST Special Publication 800-63B section 5).

Okrem dĺžky hesla (viac ako 8 znakov) sa testuje použitie základných slovníkových slov (102 tisíc slov), použitie hesiel z v minulosti uniknutých a prelomených databáz, podobnosť s užívateľským menom a pod.

Pokiaľ je Vaša aplikácia kritická, toto je jedna z možností ako zlepšiť zabezpečenie vaších užívateľov.

Viac informácií nájdete na Githube: https://github.com/langleyfoxall/laravel-nist-password-rules

May 6, 2019

Kaskádové mazání relací se soubory.

xvital dal hlas Kaskádové mazání relací se soubory.

Zdravím, řeším problém který bych chtěl vyřešit nějak "pěkně". Zadání je jednoduché. Při smazání kategorie se musí smazat i články a obrázky patřící článkům.

Tohle mi funguje dobře ale už ne při relaci.

class Post extends Model {

    protected static function boot()
    {
        static::delete(function ($post) {

            // zde kod pro mazani souboru atd...

Kaskádové mazání relací se soubory.

xvital odpovedal v téme Kaskádové mazání relací se soubory.

Mozno ide len o preklep, ale event delete by mal byt bud deleting alebo deleted (delete neexistuje). Skuste miesto static::delete pouzit self::deleting, alebo self::deleted, podla potreby.

Mazanie by teda vyzeralo nasledovne

protected static function boot()
{
   self::deleting(function ($product) {
      // mazanie
   });
}
May 2, 2019

Laravel fasády (Facades)

xvital vytvoril tému Laravel fasády (Facades)

Pravdepodobne ste v minulosti narazili na rôzne vyjadrenia a názory, ktoré hanili Laravel kvôli používaniu Facades s tým, že ide o tzv. statické peklo. Niet sa čomu čudovať – ak venujete päť minút rýchlemu štúdiu akéhokoľvek Laravel projektu, narazíte na množstvo „staticky“ volaných metód. A statické metódy sú zlé...

Ako Fasády v skutočnosti fungujú?

Nemusíte sa báť, žiadne statické metódy v triedach Fasád v skutočnosti neexistujú. Ide o dobre premyslený koncept, ktorý využíva jednoduchosť a praktickosť volania statických metód – využíva teda tradičný koncept volania statickej metódy Class::method(), no súčasne volá metódu nad inštanciou triedy z IoC kontajnera. Reálne preto tento koncept neohrozuje testovateľnosť a nejde o triedy, ktoré by obsahovali množstvo statických metód.

Ako je to možné?

Odpoveďou na otázku, ako môže Laravel zavolať na oko staticky volanú metódu nad inštanciou triedy je celkom jednoduchá: Magic metóda __callStatic() v PHP. __callStatic() je špeciálna metóda (tzv. Magic metódy), ktorá je zavolaná vždy, ak sa na triedu volá nedostupná statická metóda. > __callStatic() is triggered when invoking inaccessible methods in a static context. A to je presne miesto, kde Laravel implementuje logiku spracovania takéhoto volania.

Pozrime sa teda, ako vyzerá metóda __callStatic() abstraktnej triedy Facade:

/**
     * Handle dynamic, static calls to the object.
     *
     * @param  string  $method
     * @param  array   $args
     * @return mixed
     *
     * @throws \RuntimeException
     */
    public static function __callStatic($method, $args)
    {
        $instance = static::getFacadeRoot();

        if (! $instance) {
            throw new RuntimeException('A facade root has not been set.');
        }

        return $instance->$method(...$args);
    }

V skutočnosti Laravel vytiahne inštanciu a zavolá na ňu metódu, ktorú sme volali „staticky“.

Ako vytvárať fasády

Vytváranie fasád je veľmi jednoduché:

  1. Vytvoríte samotnú fasádu

    class Meta extends Facade {
    
    protected static function getFacadeAccessor()
    {
        return 'meta';
    }
    }
  2. Vytvoríte ServiceProvider

    class MetaServiceProvider extends ServiceProvider {
    
    public function register()
    {
        $this->app->bind('meta', 'App\Meta\Meta');
    }
    }
  3. Implementujete samotnú triedu (V tomto prípade App\Meta\Meta). Všetky verejné metódy bude vďaka tomu možné volať „staticky“.

Prečo používať fasády?

Najväčšou devízou fasád je jednoduchosť ich použitia. Menej práce, rovnaká testovateľnosť, prehľadnejší, jednoduchší kód, v ktorom idete priamo na vec. Na príklade môžete vidiet, že implementácia fasád je naozaj jednoduchá a rýchla. Aké jednoduche je ich používanie, už pravdepodobne dobre viete :).

Apr 12, 2019

TIP: Ako zneplatniť staré CSS/JS súbory pomocou Laravel Mix

xvital vytvoril tému TIP: Ako zneplatniť staré CSS/JS súbory pomocou Laravel Mix

V rámci projektu ste previedli úpravy, ktoré sa týkajú CSS alebo JS externých súborov, ktoré na webe linkujete. Úpravy ste nasadili do produkcie, ale štýly celkom nesedia. Pre vás jednoduchá situácia – pomôže premazať cache prehliadača a všetko je v poriadku. Ako však invalidovať linkované súbory u vaších návštevníkov a donútiť ich prehliadače načítať nové?

Najčastejšie v podobnej situácii asi zvyknete pridať za názov súboru niečo ako ?v=1.1 alebo podobne. Buď staticky – natvrdo za názov súboru niečo v rámci query stringu dopíšete, aby sa zmenil jeho názov, čo donúti prehliadač nanovo súbor načítať, alebo dynamicky - napr. timestamp.

<link rel="stylesheet" type="text/css" href="{{ asset('css/app.css') }}?v=1.1" />

Laravel Mix však ponúka omnoho jednoduchšie a dynamickejšie riešenie, vďaka ktorému sa viac nebudete musieť o verzovanie linkovaných súborov starať. Ak teda kompilujete vaše scss/less/sass/js súbory pomocou Laravel Mix, je to veľmii jednoduché. Celé riešenie spočíva v dvoch krokoch.

  1. V rámci receptu na kompiláciu použijete navyše funkciu version().
    mix.sass('resources/assets/sass/app.scss', 'public/css').version();
  2. V linku generujeme názov súboru miesto helperu asset() helperom mix() - ten sa postará o to, aby bola za názov súboru pridaná aktuálna verzia súboru.
    <link rel="stylesheet" type="text/css" href="{{ mix('css/app.css') }}" />

To je všetko. Novo vygenerované súbory budú automaticky invalidovať staré.

Verzovanie len pre produkciu

Vďaka Mixu môžete generovať novú verziu len v kompilácii pre produkciu (cli príkaz npm run production). Ak teda používate npm watcher (npm run watch), nemusí sa generovať nová verzia pri každej úprave. Stačí na to jednoduchá podmienka v mix súbore:

mix.sass('resources/assets/sass/app.scss', 'public/css');

if (mix.inProduction()) {
    mix.version();
}
Feb 26, 2019

Laravel 5.8 je vonku

xvital vytvoril tému Laravel 5.8 je vonku

Dnes bol oficiálne vydaný nový minor release, Laravel 5.8.

Prináša ďalšie vylepšenia a opravy chýb.

Pribudol nový vzťah HasOneThrough, automaticá detekcia Model Policies, Cache podla štandardu PSR-16 a mnoho iného.

Opravy chýb budú zabezpečené do 26. augusta 2019 (6 mesiacov), bezpečnostné opravy do 26. februára 2020 (12 mesiacov)

Zoznam noviniek nájdete na stránke https://laravel.com/docs/5.8/releases#laravel-5.8

Upgrade Guide

Feb 5, 2019

Resource štandardy, ktoré sa oplatí dodržiavať

xvital vytvoril tému Resource štandardy, ktoré sa oplatí dodržiavať

Už vieme ako definovať route a príslušný controller. Je ideálny čas na to, podchytiť best practice v routovaní a spracovaní požiadavok.

Resourceful?

Resource (prostriedok, zdroj) je v našom prípade niečo, nad čím operujeme. Teda konkrétny model. Pri návrhu aplikácie sa typicky zamýšľame nad tým, aké akcie budeme nad daným modelom vykonávať (čo s ním bude možné v rámci aplikácie robiť). Ak je controller resourceful, znamená to, že obsahuje všetky nižšie spomenuté akcie.

HTTP verbs

Protokol HTTP obsahuje niekoľko metód, ako odosielať požiadavku. Ide o slovesá, ktoré (veľmi trefne) popisujú, akú akciu ideme nad resourcom vykonať. Ide o týchto 5 metód/akcií: GET, POST, PUT, PATCH, DELETE.

GET získanie resourcu (R) zo servera
POST odoslanie R na server
PUT zmena R (ako celok, doslova zámena za iný, zmazanie starého a nahranie nového)
PATCH zmena R (jeho časti)
DELETE zmazanie R

Route akcie

Ak by sme chceli nad modelom vykonávať všetky akcie, môžeme ich definovať explicitne takto:

Route::get('/articles', 'ArticleController@index');
Route::post('/articles', 'ArticleController@store');
Route::put('/articles/{article}', 'ArticleController@update');
Route::patch('/articles/{article}', 'ArticleController@update');
Route::delete('/article/{article}', 'ArticleController@destroy');

Laravel však ponúka omnoho jednoduchšiu cestu s rovnakým výsledkom:

Route::resource('articles', 'ArticleController');

Ak chcete využiť len niektoré akcie, metódami only a except môžete definíciu obmedziť

// only
Route::resource('photos', 'PhotoController')->only([
    'index', 'show'
]);

// except
Route::resource('articles', 'ArticleController')->except([
    'create', 'store', 'update', 'destroy'
]);

Úplne najväčší kanón je definícia viacerých resource-ov naraz:

Route::resources([
    'articles' => 'ArticleController',
    'comments' => 'CommentController'
]);

V controlleri ArticleController zas nemusíte pracne definovať metódy pre jednotlivé akcie. Ak použijete pri vytváraní controlleru prepínač -r

php artisan make:controller ArticleController -r

vygenerovaný controller bude tzv. resourceful – bude obsahovať všetky metódy, ktoré potrebujete. Stačí len implementovať.

Prečo dodržiavť štandardy?

Ide o dôležitý štandard hlavne v prípade, že aplikácia mení majiteľa, mení sa tím, alebo prichádza nová posila. Pri použití štandardných URI a akcií controllera je veľmi jednoduche s aplikáciou (v tomto ohľade) ďalej pracovať a nie je potrebné skúmať aké názvoslovie zvolil kolega pred vami.

Ak teda chcete priniesť aplikáciou jej majiteľovi čo najvyššiu hodnotu, je aj budúca udržateľnosť aplikácie jedným z bodov, na ktorý by ste mali pri návrhu myslieť.

Jan 29, 2019

Eloquent ORM

xvital vytvoril tému Eloquent ORM

Eloquent (plynulý, ladný, dokonalý) je ORM, ktoré je súčasťou Laravelu. Tak ako hovorí samotný názov, ide o veľmi príjemné a prirodzené rozhranie pre prácu s objektami a interakcie s databázou. V jednoduchých aplikáciach tak priamo s SQL nemusíte prísť vôbec do kontaktu.

Dnes sa bližšie pozrieme na

  1. vytváranie objektov
  2. ukladanie objektov do databázy
  3. vzťahy medzi modelmi
  4. základné operácie na objektoch a ich vzťahoch

Prerekvizity

V tomto bode by ste mali mať nainštalovaný Laravel a nakonfigurovaný prístup k databáze. Pre účely ukážky práce s modelmi a vzťahmi poslúži ako príklad jednoduchá aplikácia - blog, ktorá bude obsahovať dva modely: User a Post.

Eloquent model

Je na vás aký workflow si zvolíte, prvým krokom však väčšinou bude vytvorenie modelov. Výhodou je, že Laravel v základe obsahuje jednoduchý model User a kompletnú implementáciu autentifikácie. Keďže aplikácia už model User obsahuje, vytvárať budeme už len model Post:

php artisan make:model Post -m

Použil som prepínač -m, aby mi artisan pripravil migráciu pre tabuľku posts.

Model created successfully.
Created Migration: 2019_01_29_085958_create_posts_table

V migrácii pripravíme požadovanú štruktúru tabuľky

<?php

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

class CreatePostsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->increments('id');
            $table->timestamps();

            /* Nazov clanku */
            $table->string('subject');
            /* Obsah clanku */
            $table->text('body');

            /**
             * Tabulka users je v dobe vykonavania tejto migracie uz vytvorena
             * mozeme na nu odkazovat v cudzom kluci
             */
            $table->integer('user_id')->unsigned();
            $table->foreign('user_id')->references('id')->on('users');
        });
    }

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

V tomto bode máme vytvorené tabuľky a môžeme sa pozrieť na model User, ktorý zatiaľ neobsahuje žiadne vzťahy, len niekoľko vlastných premenných, ktoré definujú prístup a viditeľnosť k atribútom modelu (o týchto premenných sa dozviete ďalej v článku).

Vzťah s modelom Post definujeme ako 1:N (1 užívateľ môže vytvoriť N článkov). V modeli User teda implementujeme metódu posts ako vzťah hasMany, nasledovne:

public function posts()
    {
        return $this->hasMany('App\Post');
    }

Model Post obsahuje zatiaľ prázdnu triedu Post, ktorú nám vygeneroval artisan. Sem pridáme vzťah s modelom User. Ide o opačnú stranu vzťahu 1:N, použijeme metódu belongsTo.

public function user() 
    {
        return $this->belongsTo('App\User');
    }

Vytváranie nových objektov

Na vytvorenie objektov môžeme použiť explicitný prístup: vytvoriť model, nastaviť atribúty na požadované hodnoty a nakoniec model uložiť (perzistovať ho do databázy).

$post = new Post;

$post->subject = 'Hello World!';
$post->body = 'How are you?';

$post->save();

Eloquent však na vytváranie objektov poskytuje jedoduchšiu metódu create, vďaka ktorej vytvoríte nový objekt rýchlejšie, predaním poľa s parametrami

Post::create([
      'subject' = 'Hello World!',
      'body' = 'How are you?'
]);

Používanie vzťahov medzi modelmi

Jedna z predností Active Record je práve jednoduchosť používania vzťahov. Ak chceme získať autora článku a máme k dispozícii článok

$author = $post->user;

Ak chceme zoznam článkov, ktoré napísal daný autor

$posts = $user->posts;

Tak jednoduchý môže byť prístup ku vzťahovým modelom.

Niekedy však potrebujete tento výber obmedziť/filtrovať. Volanie metódy vzťahu vracia Query Builder objekt (v tomto prípade HasMany), ktorý môžete zreťaziť s ďalšími metódami Query Buildera a samotný SQL dotaz vykonať až na konci volaním get(). Vtedy dôjde k spojeniu s databázou a vykonaniu samotnému dotazu.

// volanie vztahu a filtrovanie pouzitim where
dd($user->posts()->where('subject', 'like', '%hello%')->latest());

// vysledkom je objekt typu HasMany
HasMany {#209 ▼
  #foreignKey: "posts.user_id"
  #localKey: "id"
  #query: Builder {#206 ▶}
  #parent: User {#212 ▶}
  #related: Post {#201 ▶}
}

// to iste co vyssie, ale ukoncene volanim metody get()
dd($user->posts()->where('subject', 'like', '%hello%')->latest()->get());

// vysledkom je zoradena kolekcia objektov, ktore zodpovedaju splnaju klauzulu where
Collection {#213 ▼
  #items: array:3 [▼
    0 => Post {#214 ▶}
    1 => Post {#218 ▶}
    2 => Post {#219 ▶}
  ]
}

Eloquent obsahuje implementáciu rôznych vzťahov, ktoré budete pri vývoji aplikácií potrebovať

  • one to one
  • one to many
  • many to many
  • has many through
  • polymorfné vzťahy

Kompletný prehľad, detaily a použitie nájdete v dokumentácii.

Prednačítanie vzťahov (Eager loading)

V úvodných, jednoduchých príkladoch som využil prístup ku vzťahovým modelom cez dynamické atribúty. Veľmi praktické a jednoduché. Je však potrebné uvedomiť si, ako to celé funguje. Ak pristupujeme ku vzťahu ako k dynamickému atribútu objektu na ktorom vzťah voláme, SQL dotaz sa vykoná v danej chvíli. Ak použijete vzťah ako dynamický atribút druhýkrát, opäť sa vykoná rovnaký SQL dotaz. V určitých situáciach teda môžete zbytočne pristupovať do databázy niekoľkokrát a vyberať pri tom rovnaké dáta. Laravel preto ponúka možnosť tzv. eager loadingu, čo znamená že vzťah, resp. vzdialený objekt sa prednačíta a stane sa súčasťou vybraného objektu. Pre prístup k dátam vzdialeného objektu už nebude potrebné dotazovať sa do databázy.

Fillable, guarded a hidden atribúty modelov

V triede modelu môžete obmedziť hromadné vyplňovanie atribútov. Slúžia na to špeciálne premenné $fillable a $guarded. Guarded – je zoznam chránených atribútov, ktoré bude Laravel za vás strážiť, aby sa nevypĺňali hromadne (napríklad pri použití metódy create). Všetky atribúty, ktoré nebudú definované v tomto zozname, bude možné vypĺňat hromadne. Fillable – je má inverznú funkciu ako guarded – atribúty vymenované v zozname sa budú dať hromadne vypĺňať, u ostatných to možné nebude. Zoznamy definujete ako pole atribútov. Používajte podľa potreby buď guarded, alebo fillable. Ak chcete, aby niektoré atribúty modelu neboli obsiahnuté v dátach, ktoré vám Eloquent vráti, definujte ich v premennej $hidden. Podobne ako u vyššie uvedených, definujete skryté atribúty ako pole atribútov. Vhodné hlavne pre atribúty, ktoré môžu predstavovať bezpečnostné riziko.

Ako vždy, detailné informácie a hlavne mnoho ďalších funkcií a možností, ktoré ponúka Eloquent, nájdete v dokumentácii pre ORM Eloquent.

Laravel Snippet #3

xvital vytvoril tému Laravel Snippet #3

Laravel Snippet - týždenný sumár Taylora Otwella, na čom pracoval Laravel team v uplynulom týždni je tu opäť.

<iframe src='https://share.transistor.fm/e/ac3cc392&#039; width='100%' height='180' frameborder='0' scrolling='no' seamless='true' style='width:100%; height:180px;'></iframe>

Snippet #3 Highlight: Prístup k migráciam, rollback a metóda down()

Taylor hovorí o tom, že v produkčnom prostredí ešte asi nikdy nepoužil rollback. Podobne ako väčšina Laravel vývojárov, využíva len dopredný prístup a v prípade potreby migruje všetky migrácie od začiatku príkazom php artisan migrate:fresh. V prípade že potrebuje štruktúru databázy upraviť, vytvorí k tomu novú migráciu. Podobný prístup som spomenul v článku o Databáze a migráciach.

Laravel Snippet #2

xvital vytvoril tému Laravel Snippet #2

<iframe src='https://share.transistor.fm/e/8061adf9&#039; width='100%' height='180' frameborder='0' scrolling='no' seamless='true' style='width:100%; height:180px;'></iframe>

Highlight tohto Snippetu: Je Lumen mŕtvy?

Lumen nie je mŕtvy. Je to mikroframework, kde (už z definície) nepribúda množstvo nových funkcií rýchlym tempom, ako to môžeme vidieť v klasických frameworkoch. Na pohľad sa teda môže zdať, že Lumen sa nevyvíja a Laravel team mu nevenuje pozornosť, v skutočnosti však Lumen ide svojou cestou a málo aktivity neznamená, že by bol na odpis.

Jan 26, 2019

Databáza a migrácie

xvital vytvoril tému Databáza a migrácie

Keď už vieme ako Laravel zabezpečuje perzistenciu modelov v databáze, môžeme prejsť na samotnú databázu a jej konfiguráciu. V tomto článku sa pozrieme na konfiguráciu a používanie databáz v Laraveli.

Konfigurácia

Konfigurácia a nastavenia v Laraveli vo všeobecnosti majú dve úrovne. Adresár config obsahuje jednotlivé konfiguračné súbory pre rôzne časti aplikácie a služby, resp. balíčky. Potom je tu .env súbor, kam môžete vytiahnuť niektoré premenné, ktoré majú byť závislé na prostredí. .env súbor by sa pri deploymente nemal distribuovať. Vďaka tomu bude konfigurácia zodpovedať danému prostrediu, bez potreby meniť hodnoty pri opakovanom deploymente (úpravy/oprava chýb).

Najčastejšie zrejme budete využívať databázu MySQL (MariaDB). Konfigurácia je v rámci novej inštalácie Laravelu pripravená na použitie MySQL, takže stači v súbore .env nastaviť správne údaje pre pripojenie k databáze.

Ak chcete zmeniť prednastavený typ spojenia, stačí otvoriť súbor config/database.php a upraviť hodnotu default podľa potreby. Pripojenia spravujete v tom istom súbore, o niečo nižšie, pod kľúčom connections.

Ak ste zadali správne údaje, môžete vyskúšať spustiť migráciu (pomocou php artisan migrate) a uvidíte, či zbehnú vstavané migrácie v poriadku.

Migrácie

Veľmi efektívne a využiteľné rozhranie pre prácu so štruktúrou databázy vám dávajú v Laraveli migrácie. Ide o zaujímavý koncept, ktorý pripomína verzovanie v svn alebo git.

Ako to funguje?

V databáze je pre účely migrácií vytvorená veľmi jednoduchá servisná tabuľka migrations, ktorá obsahuje záznamy o tom, ktoré migrácie už boli vykonané. Každý zásah do štruktúry tabuliek sa potom robí v rámci novej migrácie. Databáza prejde vykonaním migrácie do nového stavu. Vďaka tomu môžete robiť zásahy aj do produkčnej databázy bez toho, aby ste museli dáta exportovať, (v extrémnom prípade upravovať) a znova importovať do upravenej databázy. Stačí správne napísať migráciu.

Nikde však nie je striktne uvedené, ako pristupovať k migráciam. Môžete vytvárať migrácie pri vytváraní modelov s prepínačom -m a mať tak oddelené migrácie pre jednotlivé tabuľky modelov. Osobne využívam skôr prístup, kedy sa v rámci jedného cyklu od návrhu až po deployment snažím udržiavať všetky úpravy na úrovni databázy v jedinej migrácii. Získam tak výhodu nižšieho počtu migračných súborov, lepší prehľad a lepšiu kontrolu nad migráciami – pri každom deploymente sa vykoná maximálne jedna. Záleží však aj od konkrétnej situácie, a niekedy dáva väčší zmysel oddeliť jednotlivé úpravy/vytváranie podľa logických celkov a nemiešať všetko dohromady. Vyberte si akýkoľvek prístup, ktorý vyhovuje vám, konkrétnemu projektu a vášmu workflow.

Vytváranie migrácii

Novú migráciu vytvoríte príkazom

php artisan make:migration nazov_migracie

Pre urýchlenie a zjednodušenie práce s vygenerovanými súbormi migrácii môžete využiť prepínače --create a --table, ktoré hovoria o tom, ktorej tabuľky sa bude migrácia týkať. Pripravený súbor tak bude obsahovať viac informácií - menej práce s úpravou.

Štruktúra súborov

Trieda migrácie obsahuje dve metódy: up a down. V metóde up hovoríme, čo sa má vykonať pri vykonávaní migrácie (napr. vytváranie tabuliek, pridávanie nových stĺpcov, zmena názvov stĺpcov a pod.) a v metóde down by sme mali tieto akcie zas vziať späť. V ideálnom prípade sa databáza po vykonaní migrácie a jej rollbacku dostane znova do pôvodného stavu. V reálnom svete väčšina vývojárov metódu down vôbec nevyužíva, resp. v nej len v prípade vytvárania tabuliek v rámci migrácie prevádzajú ich drop. Taylor Otwell sa k tejto problematike vyjadril v Laravel Snippet #3.

Všetky potrebné funkcie pre vytváranie tabuliek, stĺpcov, úpravy, vytváranie FK, indexov a množstvo ďalších vecí nájdete priamo v dokumentácii. Ak by ste s potrebovali pomôcť s konkrétnou vecou, stačí sa ozvať tu na fóre.

Prístup k dátam

Priamočiary prístup k dátam na vyššej úrovni zabezpečuje ORM Eloquent, ktorý mapuje stĺpce tabuliek modelov na atribúty modelov v PHP. Viac o Eloquente a Active Record implementácii som napísal v staršom blogu. Tejto téme sa ešte budem venovať v článku o Eloquente.

Druhý prístup (nižšej úrovne) ponúka Query Builder a fasáda DB. Ak potrebujete vo vašej aplikácii pristupovať k dátam zložitejšími dotazmi, Query Builder je rozhranie, ktoré hľadáte. Na stránkach dokumentácie pre Query Builder nájdete (takmer) nekonečné množstvo užitočných funkcií, ktoré zabezpečujú konvenčný prístup k databáze. Ak by vám ani toto nestačilo, je vám k dispozícii metóda raw na čisté SQL dotazovanie. Dohromady je k dispozícii veľmi silný nástroj, ktorý zaručene pokryje všetky vaše potreby.

Jan 23, 2019

Laravel 5.7.22

xvital vytvoril tému Laravel 5.7.22

Včera vyšiel nový release, 5.7.22. Nový patch obsahuje jednu opravu chyby a niekoľko úprav. Konkrétne:

Fixed

Fixed TestResponse::assertJsonValidationErrors() when there are no errors (#27190)

Changed

Allowed TestResponse::assertJsonMissingValidationErrors() to be called without an argument (#27176) Updated vue preset's vue-stubs for laravel-mix 4 compatibility (#27229) Updated preset to use @babel/preset-react (#27235) Used config to resolve the database value during tests. (#27240)

Jan 20, 2019

Taylor Otwell: Laravel Snippet #1

xvital vytvoril tému Taylor Otwell: Laravel Snippet #1

<iframe src='https://share.transistor.fm/e/57a1e430&#039; width='100%' height='180' frameborder='0' scrolling='no' seamless='true' style='width:100%; height:180px;'></iframe>

Jan 19, 2019

Laravel a Active Record

xvital vytvoril tému Laravel a Active Record

Ďalším dielom základov v Laraveli by logicky mala byť databáza alebo ORM Eloquent. Predtým, než sa pozrieme na to, ako Laravel pracuje s databázou si však povedzme niečo o tom, ako Laravel pracuje s dátami na úrovni modelov a ako zabezpečuje perzistenciu modelov v databáze.

ORM – mapovanie objektov do relačnej databázy

Existencia modelov je ohraničená PHP runtimeom, sú teda, len dočasné. Na to, aby sme dáta modelov zachovali, potrebujeme modely uložiť tzv. perzistentne. Ako úložisko sa vo webových aplikáciach najčastejšie využívajú relačné databázy. Prístupov k mapovaniu objektov do databázy je však viacero. Dva, v rámci webových frameworkov najčastejšie používané, sú Active Record a Data Mapper.

Active Record vs. Data Mapper

Zatiaľ čo v rámci Data Mapper prístupu definujete prepojenie dát s databázou explicitne, Active Record implicitne mapuje stĺpce tabuľky 1:1 na atribúty modelu.

V AR typicky využívame pri práci s modelmi workflow:

$thread = new Thread;
$thread-&gt;subject = &#039;Example Thread&#039;;

$thread-&gt;save();

V prípade Data Mapper by základ vyzeral podobne:

$thread = new Thread;
$thread-&gt;subject = &#039;Example Thread&#039;;

ThreadMapper::persist($thread);

Model Thread však nemá informácie o štruktúre databázy a je len obyčajným PHP objektom, preto na uloženie potrebujeme zavolať službu, ktorá model do databázy uloží. Výhodou je, že je len objektom a sám sa nezaoberá svojou perzistenciou. To za neho rieši príslušný, oddelený mapper v inej vrstve, ktorý má na starosti mapovanie atribútov modelu do tabuľky.

Active Record túto vrstvu neobsahuje, vďaka čomu môže byť vývoj omnoho jednoduchší a rýchlejší. Na druhej strane to predurčuje využitie vzoru na určitý typ aplikácií; Je excelentný pre domény, ktoré neobsahujú zložitú biznis logiku a predovšetkým tie, kde je práca s dátami skutočne priamočiara – CRUD.

Čím viac logiky pri vyberaní/zapisovaní dát do databázy potrebujete, tým menej výhodný tento model bude – spoznáte to napríklad podľa neštandardne dlhých tried modelov.

Eloquent ORM = Active Record

Laravel vo svojom ORM Eloquent implementuje vzor Active Record. Dobrou správou pre tých, ktorí nad Laravelom uvažujú je, že veľa webov si s CRUD operáciami do veľkej miery vystačí, pretože fungujú ako rozhranie na vytváranie/zobrazovanie obsahu.

Pre tie ostatné je na mieste zamyslieť sa pred návrhom nad tým, či ísť cestou priamych queries v Laraveli a obchádzať tak ORM Eloquent, alebo sa viac oplatí siahnuť po inom ORM (alebo aj celom frameworku) implementujúcom vzor Data Mapper a definovať mapovanie podľa potrieb aplikácie v oddelenej vrstve (DM).

Jan 16, 2019

Laravel 5.7.21

xvital vytvoril tému Laravel 5.7.21

Zhruba týždeň po vydaní patchu 5.7.20 včera vyšiel ďalší - 5.7.21. Pozrime sa bližšie na to, čo sa opravovalo.

Fixed

  • Fixed Blueprint::removeColumn() (#27115, #27122)
  • Fixed allowing of null broadcast connection driver (#27135)
  • Fixed ModelMakeCommand::handle() should always return bool value (#27156)
  • Fixed TestResponse::assertSessionDoesntHaveErrors() when there is no errors (#27145)
  • Fixed default message in localization twice in 403.blade.php error page (4a08120)

Changed

  • Replaced get_called_class() to static::class (#27146)
  • Re-throw NoMatchingExpectationException from PendingCommand (#27158)

Zdroj: https://github.com/laravel/framework/blob/5.7/CHANGELOG-5.7.md#v5721-2019-01-15

Generovanie výstupu a Laravel Blade šablóny

xvital vytvoril tému Generovanie výstupu a Laravel Blade šablóny

Pozrime sa bližšie na to, ako v Laraveli oddelíme generovanie a formátovanie výstupu od logiky aplikácie. V článku o routingu som uviedol príklad, ako môžeme vygenerovať výstup priamo z route súboru web.php. Vyzeral približne takto:

Route::get(&#039;test&#039;, function () {
    return &#039;Môj prvý výstup&#039;;
});

V reálnej aplikácii však budeme generovať zložitejší, štruktúrovaný výstup v HTML. Posielať ho na výstup takýmto spôsobom by bolo veľmi nepraktické, preto využijeme oddelené súbory - šablóny. V Laraveli sú súbory šablón organizované v adresári resources/views a tu bude hľadať naše šablóny aj pomocná funkcia (helper) view. Namiesto vyššie uvedeného príkladu použijeme:

Route::get(&#039;test&#039;, function () {
    return view(&#039;test&#039;);
});

V adresári resources/views vytvoríme súbor test.blade.php (súbory šablón majú koncovku .blade.php). Do príkladu pridám aj základnú HTML štruktúru:

&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;title&gt;Hello World!&lt;/title&gt;
&lt;/head&gt;

&lt;body&gt;

    &lt;h1&gt;Hello World!&lt;/h1&gt;

&lt;/body&gt;
&lt;/html&gt;

Na endpointe /test prehliadač zobrazí nadpis prvej úrovne „Hello World!“

Blade a šablónovanie

Už vieme, ako generovať výstup definovaný v oddelenom súbore. Samo o sebe by nám to však veľmi nepomohlo, pokiaľ by sme museli každé zobrazenie (view) webu definovať ako samostatný nezávislý súbor – množstvo kódu by sa opakovalo a úpravy by boli doslova nočnou morou. Vo vytváraní štruktúry šablón nám pomôže prepracovaný šablonovací engine Blade. Blade je veľmi výkonný nástroj na šablónovanie, ktorý prináša veľké možnosti s minimálnou, resp. žiadnou réžiou navyše vďaka tomu, že šablóny sa prekladajú do PHP a udržiavajú sa medzi úpravami v cache. V Blade šablónach je možné používať aj čisté PHP.

Skladanie šablón

Aby sme zabránili opakovaniu rovnakého kódu v zobrazeniach, opakujúce sa časti môžeme združiť do základnej šablóny, ktorá nám poslúži ako základ, ktorý budeme rozširovať vo vnorených šablónach. Základnú šablónu nazvem napríklad overall.blade.php. V našom prípade by mohla vyzerať napríklad takto:

&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;title&gt;@yield(&#039;title&#039;)&lt;/title&gt;
&lt;/head&gt;

&lt;body&gt;

    @yield(&#039;content&#039;)

&lt;/body&gt;
&lt;/html&gt;

Povedzme, že chceme vytvoriť uvítaciu stránku s nadpisom a krátkym textom. Šablóna nižšej úrovne pages/home.blade.php bude vyzerať napríklad takto:

&lt;!-- pages/home.blade.php --&gt;

@extends(&#039;overall&#039;)

@section(&#039;title&#039;, &#039;Hello World!&#039;)

@section(&#039;content&#039;)
    &lt;h1&gt;Hello World!&lt;/h1&gt;
        &lt;p&gt;Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.&lt;/p&gt;
@endsection

Blade syntax je veľmi jasná a väčšina direktív funguje presne tak, ako by ste čakali. Direktíva @extends definuje šablónu, ktorú rozširujeme, @section definuje jednotlivé sekcie rodičovskej šablóny. Pre vygenerovanie kompletného zobrazenia použijeme šablónu najnižšej úrovne – v tomto prípade home.blade.php:

Route::get(&#039;home&#039;, function () {
    return view(&#039;pages.home&#039;);
});

Všimnite si . Zápis. Dá sa použiť aj klasický zápis pomocou lomítka (forward slash), je však lepšie zvyknúť si na zápis s bodkami, je to totiž štandard, ktorý Laravel využíva aj mimo Blade súborov.

Posielanie dát do šablón

Druhým parametrom funkcie view() je nepovinné pole s predávanými dátami. Kľúče tohto poľa budú v šablóne dostupné ako premenné rovnakého názvu. Ak by sme teda chceli posunúť našej uvítacej šablóne nejaké dáta, môžeme to urobiť takto:

Route::get(&#039;home&#039;, function () {
    return view(&#039;pages.home&#039;, [&#039;name&#039; =&gt; &#039;John&#039;]);
});

V súbore šablóny vypíšeme premennú $name

@extends(&#039;overall&#039;)

@section(&#039;title&#039;, “Hello {$name}“)

@section(&#039;content&#039;)
    &lt;h1&gt;Hello {{ $name }}!&lt;/h1&gt;
        &lt;p&gt;Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.&lt;/p&gt;
@endsection

Syntax {{ }} zabezpečuje výpis a ide v podstate o volanie PHP funkcie echo. Táto syntax sa používa na tzv. bezpečný výpis. Je zabezpečená proti XSS útokom tým, že vstup prechádza PHP funkciou htmlspecialchars. Ak potrebujete vypísať neescapovaný obsah, môžete použiť syntax {!! $var !!}, ale rozhodne týmto spôsobom nevypisujte dáta od užívateľa. Mohli by ste sa stať zraniteľný XSS útokom. Syntax základných kontrolných štruktúr nájdete v dokumentácii.

Vkladanie šablón

Na vloženie obsahu inej šablóny môžeme použiť Blade direktívu @include, ktorá má niekoľko variánt – viď dokumentácia @include. Základná syntax @include

@include(&#039;view.name&#039;, [&#039;some&#039; =&gt; &#039;data&#039;])

Rovnako ako pri funkcii view, aj tu je druhý parameter – pole predávaných dát nepovinné.

Záver

V článku sme prešli základmi šablónovania a oddeľovania zobrazení od logiky aplikácie. Blade šablóny sú veľmi silným nástrojom na generovanie a formátovanie výstupu aplikácie s priamočiarou, jednoduchou syntaxou. Všetky detaily nájdete v dokumentácii na oficiálnych stránkach. Zaujímavosti a menej bežné direktívy si ukážeme v niektorom z ďalších článkov.

Jan 14, 2019

Controllery – ich význam a základy používania

xvital vytvoril tému Controllery – ich význam a základy používania

V tomto blogu nadviažem na posledný článok o routingu. Controllery s routami dosť úzko súvisia.

Controller je základným kameňom každej, aspoň trochu rozsiahlejšej aplikácie. Primárnou úlohou controllerov je oddeliť logiku spracovania požiadavky od zvyšku aplikácie. Bez tejto abstrakcie by boli naše route súbory obrovské, pretože by obsahovali celú logiku spracovania požiadaviek.

Ako sa však dostane požiadavka do controllera? Vďaka routeru. V route file sme zadefinovali, ktorý controller má spracovať požiadavku smerovanú na daný endpoint aplikácie. Laravel sa postará, aby naša požiadavka dorazila do príslušného controllera a tam ju môžeme spracovať.

Definícia route a controllera

Pripomeňme si, ako vyzerá základná definícia cesty v route súbore, ktorá zabezpečí spracovanie GET požiadavky zaslanej na endpoint forum, controllerom ThreadController – konkrétne jeho akciou (metódou) index:

Route::get(&#039;/forum&#039;, &#039;ThreadController@index&#039;);

Súbor controllera je možné vytvoriť v app/Http/Controllers, omnoho jednoduchšie je však použiť vstavaný artisan príkaz

php artisan make:controller ThreadController

ThreadController by mohol v tomto prípade po implementácii metódy index vyzerať napríklad takto:

&lt;?php

namespace App\Http\Controllers;

use App\Thread;
use App\Http\Controllers\Controller;

class ThreadController extends Controller
{
    /**
     * Zobrazenie zoznamu 10 najnovsich tem fora.
     *
     * @param  int  $id
     * @return View
     */
    public function index()
    {
        $threads = Thread::latest()-&gt;take(10)-&gt;get();

        return view(&#039;thread.index&#039;, compact(&#039;threads&#039;));
    }
}

Jednoúčelový controller (controller s jedinou akciou)

Menej bežná je definícia controllera s jedinou akciou. V určitých prípadoch však môže prísť táto možnosť vhod. Namiesto definície jednotlivých akcií zadefinujete jedinú metódu __invoke v triede controllera.

Route by potom vyzeral napríklad takto

Route::get(&#039;/forum&#039;, &#039;IndexController&#039;);

Trieda controllera by v tomto prípade obsahovala obsahovala implementáciu metódy __invoke

public function __invoke()
{
    $threads = Thread::latest()-&gt;take(10)-&gt;get();

    return view(&#039;thread.index&#039;, compact(&#039;threads&#039;));
}

Pri použití jednoúčelového controllera môžete využívať všetky ostatné možnosti (predávanie parametrov, explicitná definícia konštruktora, …). artisan podporuje aj vytváranie jednoúčelových controllerov, stačí použiť prepínač --invokable.

Štandardné akcie controllerov

Dobrým zvykom je používať štandardné akcie controllerov vždy, pokiaľ to je možné. Je to štandard, ktorý zabezpečí, že váš kód bude ľahšie pochopiteľný a rýchlejšie čitateľný. Preto rozhodne odporúčam dodržiavať. Prehľadnú tabuľku nájdete priamo v dokumentácii.

Pre vytvorenie resource controlleru (obsahuje všetky uvedené akcie), môžete použiť pri vytváraní controlleru prepínač --resource. Ak chcete do jednotlivých metód automaticky vložiť aj triedu modelu na ktorý sa controller vzťahuje (type-hinting), použite pri vytváraní controlleru prepínač --model=NazovModelu.

Jan 12, 2019

Základy routovania v Laraveli

xvital vytvoril tému Základy routovania v Laraveli

Routing je fundamentom každého webovo orientovaného MVC frameworku, no nie je špecifikom MVC - routing sa používa aj inde. Router prichádza ako prvý do kontaktu s požiadavkou. Obsahuje logiku spracovania, alebo jej ďalšieho presmerovania. V rámci rozdelenia zodpovednosti v modeli MVC je logika spracovania požiadavky oddelená do tzv. controllerov, ktoré preberajú zodpovednosť za spracovanie.

Dlhú dobu Laravel v defaulte obsahoval jediný súbor routes.php, kde boli definované všetky routy na jednom mieste. Od verzie 5.3 však bol tento súbor premiestnený do samostatného adresára routes v koreňovom adresári projektu a rozdelený do viacerých súborov. Na routy v súbore routes/web.php sa aplikuje middleware web (stavy, CSRF), zatiaľ čo na routy v súbore routes/api.php sú bezstavové a aplikuje sa na ne middleware api.

Route definície

Najjednoduchšia možnosť ako zadefinovať route a poslať do prehliadača dáta je použitie callbacku priamo v route súbore. V tomto prípade sa stáva Router zároveň controllerom, keďže zodpovednosť za spracovanie požiadavky neposúva na dedikovaný controller.

Route::get(&#039;test&#039;, function () {
    return &#039;Môj prvý výstup&#039;;
});

Táto metóda routingu môže poslúžiť napríklad pri ladení aplikácie, oveľa častejšie však pre aplikácie bežného rozsahu v MVC využijete nasledujúcu metódu, kde ako callback uvediete dedikovaný controller a jeho metódu, ktorá bude požiadavku spracovávať

Route::get(&#039;dashboard&#039;, &#039;DashboardController@index&#039;);

Fasáda Route umožňuje definíciu všetkých dostupných HTTP metód (get, post, put, patch, delete, options). Keďže HTML formuláre do verzie HTML 4, resp. XHTML 1 podporujú len metódy GET a POST, na využívanie ďalších metód potrebujeme vo formulároch definovat skryté pole (tzv. form method spoofing, o ktorom si povieme viac v článku a pokročilom routovaní).

Parametrické URI

V aplikáciach často potrebujeme definovať parametrické URI, teda URI s premennými segmentami. Na definíciu parametrov použijeme zložené zátvorky {}.

Route::get(&#039;/thread/{slug}&#039;, function ($slug) {
    return $slug;
});

resp.

Route::get(&#039;/thread/{slug}&#039;, &#039;ThreadController@show&#039;);

Parametrov môže byť viac.

Route::get(&#039;/{user}/{slug}&#039;, &#039;ThreadController@show&#039;);

Parametre môžu byť nepovinné

Route::get(&#039;/thread/{slug?}&#039;, &#039;ThreadController@show&#039;);

Parametre je možné obmedziť regulárnym výrazom

Route::get(&#039;/thread/{slug}&#039;, &#039;ThreadController@show&#039;)-&gt;where(&#039;slug&#039; =&gt; &#039;[a-z-]+&#039;);

Veľmi praktická možnosť je dať niektorým routam (podľa použitia) názov. Práca s nimi je potom rýchlejšia, jednoduchšia a prehľadnejšia.

Route::get(&#039;/thread/{slug}&#039;, &#039;ThreadController@show&#039;)-&gt;name(&#039;thread.show&#039;);

Na generovanie URL z pomenovanej routy nám poslúži funkcia route

route(&#039;thread.show&#039;, [&#039;slug&#039; =&gt; &#039;hello-world&#039;]);
// thread/hello-world

Routovanie v Laraveli je pomerne jednoduchá záležitosť. V tomto blogu som zhrnul základné možnosti, ktoré využijete najčastejšie. Užitočných možností je však omnoho viac. Pre lepší prehľad odporúčam prejsť dokumentáciu routingu.

Ďalší blog o controlleroch vám predstaví základné princípy oddelenia logiky spracovania požiadavky do samostatných súborov.

Jan 11, 2019

Laravel - inštalácia a základná konfigurácia

xvital vytvoril tému Laravel - inštalácia a základná konfigurácia

Inštalácia samotného frameworku je rýchla a nenáročná. Pred tým než sa do inštalácie pustíte sa však uistite, že vaše vývojové prostredie spĺňa všetky požiadavky. Serverové požiadavky podľa verzie frameworku nájdete v dokumentácii.

Podmienkou pre inštaláciu je mať nainštalovaný Composer (správca závislostí).

Stačí zavolať príkaz

composer global require laravel/installer

Po pridaní globálneho vendor adresára do $PATH (premennej prostredia) môžete používať na vytvorenie nového projektu jednoduché volanie laravel new nazov-projektu Toto volanie vytvorí nový Laravel projekt a nainštaluje všetky preddefinované závislosti.

Vývojové prostredie, lokálny server

Možností ako pracovať lokálne je niekoľko. PHP CLI od verzie 5.4.0 disponuje vstavaným webserverom, ktorý je pre potreby vývoja webu plne dostačujúci. Pozor však na obmedzenia (webserver napríklad využíva pri spracovaní požiadavok jediný jednovláknový proces) a vstavaný webserver používajte len na vývoj a testovacie účely. Na spustenie servera môžete použiť artisan príkaz

php artisan serve

Ak chcete používať o niečo robustnejšie riešenie, môžete skúsiť Valet (osobne sa mi osvedčil najviac), alebo virtuálny Homestead, ktorý je však už trochu tažším kalibrom a na môj vkus spotrebuje priveľa pamäte.

Konfigurácia

Konfiguračné súbory sa nachádzajú v adresári config. Niekoľko konštánt je už vytiahnutých do .env súboru nachadzjúceho sa v koreňovom adresári projektu, kde je možné konfigurovať konštanty v závislosti od prostredia – čo je mimochodom veľmi praktická vec. Odporúčam všetky konfiguračné konštanty, ktoré sú závislé od použitého prostredia (testovanie, produkcia, …) nastavovať v tomto súbore a mať ich tak na jednom mieste.

V rámci konfigurácie skontrolujte práva adresárov storage a bootstrap/cache. Webový server by mal byť schopný do uvedených adresárov zapisovať. Aplikačný kľúč by mal byť vygenerovaný vo vašom .env súbore. Ak tam z nejakého dôvodu nie je, použite príkaz

php artisan key:generate

Tento kľúč je veľmi dôležitý z bezpečnostného hľadiska. Používa sa na šifrovanie session a ďalších kritických dát.

Webserver

Dôležité je nakonfigurovať web root vášho web servera do adresára public, kde sa nachádza front controller. Ak bude web server hľadať súbor index.php v koreňovom adresári projektu, aplikácia pochopiteľne nebude fungovať.

V prípade, že používate Apache, uistite sa, že máte povolény mod_rewrite. Ak máte problém s defaultným .htaccess súborom, skúste alternatívu z dokumentácie.

Všetko pripravené?

Ak inštalácia prebehla v poriadku a vy ste správne nakonfigurovali web server, mali by ste vidieť defaultnú bielu stránku s odkazmi na dokumentáciu a pod.

Ak sa vám táto stránka zobrazuje, gratulujem. Zvládli ste inštaláciu a môžete sa pustiť do vývoja aplikácie.

V prípade, že sa objavila chyba, skontrolujte vyššie uvedené body, alebo napíšte na fórum.

V ďalšom blogu si povieme viac o routingu v Laraveli.