Hlavné vydania - major releases, boli doteraz vydávané každých 6 mesiacov. Teda každý polrok. A to bolo príliš často. Občas sa zdalo, že len čo ste dobojovali s prechodom na novú verziu, už tu bola ďalšia.
Od teraz budú nové vydania (major) vydávané raz ročne.
Laravel 9 môžeme očakávať v septembri tohto roku.
Viac si môžete prečítať priamo v blogposte Laravel: New Release Schedule
Zalezi od nastavenia, ci tam mas transakcie a rollbacky, alebo migrujes hore dole a tiez kedy sa do tych tabuliek pozeras. Kazdy test by mal zacinat cerstvou DB a byt nezavisly na inych testoch. Ak sa pozeras do DB pri transakcnom spracovani, tam commit nejde nikdy, takze v tabulkach data neuvidis.
Idealne je na testy pouzit SQLite :in_memory:, obcas ale mozes narazit na problem, ze SQLite nepodporuje uplne celu mnozinu (My)SQL dotazov. Ak je testovanie kriticke a testov bude vela - rychlost bude dolezita, je dobre to prisposobit uz v ramci aplikacie a zjednodusit si robotu. Inak potom druha pouzitelna moznost zo skusenosti je in-memory engine MySQL(MariaDB) a transakcie.
Ahoj, jak se řeší, když potřebuji testovat, zda se vložil správný počet záznamů do databáze? Dohledával jsem to, ale nemohu nic kloudného najít, resp. vše se to řeší obezličkami typu mockery (kde jestli jsem správně pochopil, tak to jen simuluji). Čekal bych normální řešení, kdy se vkládají data do databáze a z ní je poté kontroluji, když už se při testech dělají migrace.
Nejde na to pouzit assertEquals
?
// insert 25 users
$this->assertEquals(25, $users->count());
Co viem, tak priamo nad DB Laravel ponuka len existencne asserty, teda assertDatabaseHas
a assertDatabaseMissing
...
Je to tym, ze Laravel defaultne pouziva kodovanie utf8mb4
a v MySQL v. < 5.7.7 a MariaDB < 10.2.2 sa tam tieto kluce nezmestia.
Jednoduchy fix je zavolat v boot
metode v AppServiceProvider
toto:
Schema::defaultStringLength(191);
cim sa zabezpeci nastavenie pozadovanej dlzky indexov.
Viac info tu: https://laravel.com/docs/7.x/migrations#creating-indexes (Index Lengths & MySQL / MariaDB)
Ahoj @iko95
ano, funguje to spravne. Mail::to()
robi presne to, co o sebe hovori ze robi. Teda vezme vsetkych prijemcov a hodi ich do hlavicky to
. Pokial chces poslat kazdy email individualne, vyuzi na to slucky, alebo nad kolekciou ->each()
. Eventualne mozes pouzit Bcc.
Po 6 mesiacoch od vypustenia Laravel 7, je tu ďalší major release - Laravel 8.
Prináša opäť mnoho zaujímavých vychytávok, ktoré predovšetkým zjednodušujú prácu, šetria čas, upratujú framework (hlavne pre väčšie projekty) a zavádzajú nové štandardy.
Súčasťou "osmičky" je aj Laravel Jetstream, ktorý prináša kompletnú tvár pre vašu novú aplikáciu. Obsahuje napríklad Profile Management, vďaka ktorému si môžu užívatelia zmeniť meno a e-mail, alebo nahrať profilový obrázok (avatar). Patrí sem aj zmena hesla, pokročilé zabezpečenie účtov pomocou dvojprvkovej autentifikácie, omverenie e-mailu a zmazanie účtu. Teda základ, ktorý Laravel ponúkal už dlhšie, bol opäť rozšírený, a framework vám tak dokáže ušetriť ďalší čas pri štarte.
Jetstream navyše prináša podporu API, tímov a podporu pre Livewire a Inertia - podľa výberu.
Ak ste v predchádzajúcich vydaniach používali konvenciu s adresárom Models pre modely, Laravel 8 vám vyšiel naproti. V osmičke sú totiž modely umiestňované do adresára Models automaticky, out of the box.
V novom vydaní môžete využiť factory ako triedu s rozšírenou podporou pre vzťahy medzi modelmi, takže opäť celkom zásadné zlepšenie a zjednodušenie práce.
use App\Models\User;
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
User::factory()
->times(50)
->hasPosts(1)
->create();
}
Za mňa dlho očakávané vylepšenie. Laravel 8 umožňuje "spojiť" viacero migrácii do jedného celku - schémy.
php artisan schema:dump
// Dump the current database schema and prune all existing migrations...
php artisan schema:dump --prune
Po prevedení príkazu sa vytvorí schéma, ktorá sa vykoná ako prvá a až po nej nasledujú nevykonané migrácie. Dumpovanie schém funguje pre MySQL, PostgreSQL, a SQLite databázy.
Nemenej zaujímavé sú aj ďalšie vylepšenia a novinky:
Viac informácií nájdete (ako vždy) priamo v release notes.
Ahoj, podarilo sa ti na to prist/vyriesit to?
Ahoj.
Nie je to sposobene frameworkom a nejedna sa o chybu. Toto spravanie naozaj zodpoveda specifikacii MySQL, pokial nie je uvedeny default. Riesenim je pouzit default
.
In a CREATE TABLE statement, the first TIMESTAMP column can be declared in any of the following ways:
Kompletne info: http://download.nust.na/pub6/mysql/doc/refman/5.4/en/timestamp.html
Od včera je k dispozícii nový major realease, Laravel 7.x
Obsahuje veľa zaujímavých noviniek, a o mnohých z nich si povieme viac v samostatných postoch.
Na úvod niekoľko základných informácii k podpore minulých a súčasných verzií.
K staršiemu LTS vydaniu (Laravel 5.5) bude vydávané bezpečnostné záplaty do konca augusta tohto roka. K účasnému LTS (Laravel 6) budú vychádzať bezpečnostné záplaty do 3. septembra 2022 a opravy chýb do 3. septembra 2021.
Čo je vo verzii 7 nové?
CastsAttributes
, vďaka ktorému môžete definovať ako sa majú dátové typy transformovať v oboch smeroch - pri ukladaní do databázy a pri výbere z databázy. Slúžia k tomu metódy get
(transformácia z databázovej hodnoty na daný typ) a set
(transformácia z typu na hodnotu ukladanú do databázy).<x-tag></x-tag>
. Blade komponentyIlluminate\Support\Str
. Ponúka však širšie možnosti manipulácie s reťazcami, viď. Fluent StringsgetRouteKeyName
. Ide tak o ďalšie zjednodušenie a zefektívnenie syntaxe pri zvýšení prehľadnosti - key name je priamo súčasťou definície routes.Viac informácií k novému Laravel 7.x nájdete v L7 Release notes
Registracia cez Twitter aj priama registracia (email&pass) by uz mali fungovat.
Ahoj, právě jsem se pokoušel zaregistrovat, tak reportuji bugy.
Registrace emailem, uživatelským jménem a heslem vyhodila po timeoutu Whooops. Registrace twitterem mne přesměrovala na 404. Registrace githubem nakonec zafungovala ;)
Docela dlouho očekávám vznik nějaké CZ/SK Laravel komunity, taky jsem si říkal, že zkusím něco vytvořit, ale konečně to vypadá, že už není potřeba ;-) Dobrý počin kontaktovat Taylora. Pokud budete chtít vývoj tohoto webu dělat komunitně, rád čas od času přidám pomocnou ruku.
Tak to aby som sa na to zajtra pozrel! Diky za report.
Moja povodna myslienka bola drzat to ako public repo na githube, ale pokial by som na tom robil sam, tak to uplne nedava zmysel. Za predpokladu ze by sa nasli dalsi dobrovolnici, ktori by realne prispeli do codebase, by som do toho siel. Kludne email na info at domena... :)
Nastavit pre mysql uzivatela nativne (stary sposob prihlasovania) heslo
alter user 'username'@'localhost' identified with mysql_native_password by 'password';
pripadne pouzit starsiu verziu mysql, alebo mariadb
Pri prijímaní vstupu a následnom ukladaní hodnôt sa často stretneme s potrebou validovať unikátnosť hodnoty v rámci databázovej tabuľky. Laravel preto obsahuje jednoduché pravidlo unique
, ktoré funguje nasledovne:
'code' => 'string|unique:vouchers'
V uvedenom príklade musí byť kód voucheru reťazec znakov a musí byť unikátny v rámci tabuľky vouchers.
Ak prijímate hodnotu pod iným kľúčom ako je názov stĺpca v tabuľke, môžete uviesť názov stĺpca explicitne:
'promo_code' => 'string|unique:vouchers,code'
Pri validácii sa teraz bude kontrolovať stĺpec code aj napriek tomu, že validujeme pole s názvom promo_code.
Toto je základné využitie unique, ktoré nájdete zdokumentované v oficiálnej dokumentácii. Okrem toho existujú aj menej zdokumentované, resp. nezdokumentované možnosti validácie, ktoré sa však môžu veľmi často hodiť.
Často potrebujeme pri update operáciach vynechať z validácie riadok, ktorý upravujeme. Inými slovami, chceme povoliť prepísanie hodnoty ktorá už existuje rovnakou hodnotou, pokiaľ ide o rovnaký riadok tabuľky, ktorý upravujeme.
'code' => 'string|unique:vouchers,code,' . $voucher->id . ',id',
Tento zápis hovorí, že chceme aby bola hodnota code unikátna v rámci tabuľky vouchers v stĺpci code, ale výnimkou je riadok, ktorý ma id uvedeného vouchera. To znamená, že update rovnakou hodnotou prebehne bez validačnej chyby.
Častým prípadom je aj validácia unikátnosti dvojice hodnôt. Dva vouchery teda môžu mať rovnaký kód, ale nesmú sa viazať na rovnaký obchod.
'voucher' => [
'string',
Rule::unique('vouchers')->where(function ($query) {
return $query->where('code', $this->voucher)
->where('store_id', $this->store_id);
}),
]
V callback funkcii hľadáme v tabuľke dvojicu hodnôt code a _storeid. Validácia skončí chybou len vtedy, pokiaľ v tabuľke voucher takáto kombinácia hodnôt už existuje.
Vše funkční.
Nějak hapruje stránka se zapomenutým heslem.
Opravil som to - obnovenie hesla by teraz malo fungovat v poriadku.
Skus a daj prosim vediet ci vsetko ok.
Dakujem
dik za heads up, pozriem sa na to.
Řeším zapeklitý problém (pro mě). Laravel používám jako (json) API. Mám dva objekty : Client, Project. vazbz jsou : "client has many projects" a "project belongs to client".
A potřebuju aby mi v api byl vrácen u klienta i seznam projektů A u projektu client.
Řešil jsem to pomocí protected $appdends
ale ...
Tam je ten háček.
Zacykli se to. Klient má projekty a projekty mají klienta kterej má projekty...
ukázka :
client : {
name: 'klientA',
projects : [{
name: 'prejktA',
client: {
name: 'klientA',
projects : [{
name: 'prejktA',
client: {
name: 'klientA',
....
}
}]
}
}]
}
Jak se tohle má řešit "správně" ? Mám snad mapovat v kontroleru kolekci a otrocky každý model ručně ?
Jednoznacna a jedina spravna odpoved asi neexistuje. Moznosti je niekolko.
S tym cyklenim je to problem, ktory ModelResource sam o sebe neriesi (cyklit sa ti to bude rovnako aj ked pouzijes Resources).
Osobne preferujem, ak je odpoved na akykolvek API call vratena ako Resource, pretoze Resource wrapper (rozdelenie do casti data, links, meta, ...) je prijemnym standardom.
Do akej hlbky potrebujes mat tie vztahy obsiahnute vo vyslednom objekte? Staci ak Client
bude mat Project
, ktory uz nebude obsahovat klientov?
Celkom elegantne riesenie je pouzit Eager load v modeli a nasledne v Resource na vztah podmienku whenLoaded
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ť:
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.
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:
Ak chcete využiť Stripe pre váš projekt postavený na Laraveli, dávam do pozornosti oficiálny package Cashier.
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.
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.
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.
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:
Knižnica ponúka aj pomerne široké možnosti konfigurácie.
Viac informácií nájdete priamo na githube projektu: xml-string-streamer
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();
createProgressBar()
vytvorí inštanciu progress baru. Ako parameter definujete celkový počet krokov, ktoré sa budú vykonávať.advance()
zakaždým, keď vykonáte jeden krokfinish()
. 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
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!
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.
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.
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.
Zdravim, @misko95.
Aky setup pouzivas pre lokalny vyvoj? Server bezi priamo u teba, alebo vo VM?
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
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...
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
});
}
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é...
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.
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“.
Vytváranie fasád je veľmi jednoduché:
Vytvoríte samotnú fasádu
class Meta extends Facade {
protected static function getFacadeAccessor()
{
return 'meta';
}
}
Vytvoríte ServiceProvider
class MetaServiceProvider extends ServiceProvider {
public function register()
{
$this->app->bind('meta', 'App\Meta\Meta');
}
}
Implementujete samotnú triedu (V tomto prípade App\Meta\Meta). Všetky verejné metódy bude vďaka tomu možné volať „staticky“.
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 :).
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.
version()
.
mix.sass('resources/assets/sass/app.scss', 'public/css').version();
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é.
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();
}
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
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.
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.
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
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ť.
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ť.
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
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');
}
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?'
]);
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ť
Kompletný prehľad, detaily a použitie nájdete v dokumentácii.
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.
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 - 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' width='100%' height='180' frameborder='0' scrolling='no' seamless='true' style='width:100%; height:180px;'></iframe>
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.
<iframe src='https://share.transistor.fm/e/8061adf9' width='100%' height='180' frameborder='0' scrolling='no' seamless='true' style='width:100%; height:180px;'></iframe>
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.
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 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.
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.
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.
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.
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.
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.
Včera vyšiel nový release, 5.7.22. Nový patch obsahuje jednu opravu chyby a niekoľko úprav. Konkrétne:
Fixed TestResponse::assertJsonValidationErrors() when there are no errors (#27190)
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)
<iframe src='https://share.transistor.fm/e/57a1e430' width='100%' height='180' frameborder='0' scrolling='no' seamless='true' style='width:100%; height:180px;'></iframe>
Ď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.
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.
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->subject = 'Example Thread';
$thread->save();
V prípade Data Mapper by základ vyzeral podobne:
$thread = new Thread;
$thread->subject = 'Example Thread';
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.
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).
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
Blueprint::removeColumn()
(#27115, #27122)ModelMakeCommand::handle()
should always return bool
value (#27156)TestResponse::assertSessionDoesntHaveErrors()
when there is no errors (#27145)403.blade.php
error page (4a08120)Changed
get_called_class()
to static::class
(#27146)NoMatchingExpectationException
from PendingCommand
(#27158)Zdroj: https://github.com/laravel/framework/blob/5.7/CHANGELOG-5.7.md#v5721-2019-01-15
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('test', function () {
return 'Môj prvý výstup';
});
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('test', function () {
return view('test');
});
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:
<!DOCTYPE html>
<html>
<head>
<title>Hello World!</title>
</head>
<body>
<h1>Hello World!</h1>
</body>
</html>
Na endpointe /test
prehliadač zobrazí nadpis prvej úrovne „Hello World!“
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.
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:
<!DOCTYPE html>
<html>
<head>
<title>@yield('title')</title>
</head>
<body>
@yield('content')
</body>
</html>
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:
<!-- pages/home.blade.php -->
@extends('overall')
@section('title', 'Hello World!')
@section('content')
<h1>Hello World!</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
@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('home', function () {
return view('pages.home');
});
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.
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('home', function () {
return view('pages.home', ['name' => 'John']);
});
V súbore šablóny vypíšeme premennú $name
@extends('overall')
@section('title', “Hello {$name}“)
@section('content')
<h1>Hello {{ $name }}!</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
@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.
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('view.name', ['some' => 'data'])
Rovnako ako pri funkcii view
, aj tu je druhý parameter – pole predávaných dát nepovinné.
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.
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ť.
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('/forum', 'ThreadController@index');
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:
<?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()->take(10)->get();
return view('thread.index', compact('threads'));
}
}
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('/forum', 'IndexController');
Trieda controllera by v tomto prípade obsahovala obsahovala implementáciu metódy __invoke
public function __invoke()
{
$threads = Thread::latest()->take(10)->get();
return view('thread.index', compact('threads'));
}
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
.
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
.
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
.
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('test', function () {
return 'Môj prvý výstup';
});
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('dashboard', 'DashboardController@index');
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í).
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('/thread/{slug}', function ($slug) {
return $slug;
});
resp.
Route::get('/thread/{slug}', 'ThreadController@show');
Parametrov môže byť viac.
Route::get('/{user}/{slug}', 'ThreadController@show');
Parametre môžu byť nepovinné
Route::get('/thread/{slug?}', 'ThreadController@show');
Parametre je možné obmedziť regulárnym výrazom
Route::get('/thread/{slug}', 'ThreadController@show')->where('slug' => '[a-z-]+');
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('/thread/{slug}', 'ThreadController@show')->name('thread.show');
Na generovanie URL z pomenovanej routy nám poslúži funkcia route
route('thread.show', ['slug' => 'hello-world']);
// 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.
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.
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.
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.
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.
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.