Diskuze: Laravel metódy naprieč celou stránkou

PHP PHP Laravel metódy naprieč celou stránkou American English version English version

Avatar
Mego
Člen
Avatar
Mego:

Ahojte. Ako iste viete, väčšina webstránok (webaplikácií) má nejakú jednotnú hlavičku a jednotnú pätičku.

Momentálne to u mňa funguje dajme tomu tak, že o každú podstránku sa stará daný vlastný controller. Problém nastáva tam, že potrebujem niektoré funkcie mať dostupné naprieč celou stránkou, napríklad vyťahujem do footera celkový počet užívateľov a tak podobne. Ako sa niečo také rieši? Header a footer includujem do každého view, kde controller odosiela data na zobrazenie. Asi som to napísal tak, že z toho nikto nič nepochopi. Takže háda príklad ozrejmi:

Mám stránku localhost/project. Keďže nemám homestead a podobné veselosti, na route "/" pristúpim cez adresu localhost/pro­ject/public. V routes.php mám nastavené, že o routu "/" sa má starať WelcomeContro­ller@index. Tento WelcomeController si volá funkcie z WelcomeModel-u a posiela ich do view -> welcome.blade.php . Vo welcome.blade.php mám includy na header.blade.php a footer.blade.php.

Tu nastáva problém. Funkcie WelcomeControllera využívajú aj header a fotoer (napr. na renderovanie údajov prihláseného užívateľa a pod., na zobrazovanie štatistík). Sú však umiestnené vo WelcomeControlleri. To znamená, že keď teraz prídem na iný controller, nazvyme ho EshopController@in­dex, tak mi view vyhodí error, pretože includovaný header očakáva, že dostane data z funkcií WelcomeControllera. Lenže WelcomeController sa v tomto prípade nepoužíva....

napadá ma teda, ako niečo také riešiť? Urobiť si nejaký GeneralModel, ktorý by obsahoval všetky funkcie potrebné pre celú stránku a následne ho includovať do každého controllera a tam ho volať? Na includovanie by sa použilo napr.
use App\EshopModel;
use App\GeneralModel;

Je niečo také reálne? Resp. ako sa vôbec riešia takéto problémy?

Odpovědět 5. května 13:17
Radšej 15 minút skôr, ako 15 sekúnd neskoro...
Avatar
shaman
Člen
Avatar
Odpovídá na Mego
shaman:

Ja by som na tvojom mieste rozsiril kazdy controller o nejaky zakladny kontroller, napr: BaseController

class WelcomeController extends BaseController {

    public function __construct()
    {
        parent::__construct();
    }
...

a potom v samotnom BaseControlleri by som riesil veci co pojdu na kazdu stranku. Samozrejme vsetky controlleri budu musiet byt rozsirene o tento BaseController, aj tvoj EshopController.

Nahoru Odpovědět  +1 5. května 13:28
try {...} catch (Exception ignored) { echo " ¯\_(ツ)_/¯ "; }
Avatar
Mego
Člen
Avatar
Mego:

Jasne, to by nebol až taký problém... ale tak či tak budem musieť rovnake metódy volať v každom controlleri, či ne? A je toto best practise?

Nahoru Odpovědět 5. května 13:34
Radšej 15 minút skôr, ako 15 sekúnd neskoro...
Avatar
shaman
Člen
Avatar
Odpovídá na Mego
shaman:

Vsak tie "rovnake metody" si daj to konstruktoru BaseControllera, tak sa ti sami zavolaju. Napr:

class BaseController {

    public function __construct()
    {
        $rovnake = new Rovnake();

        $this->value = $rovnake->metody();

        View::share('value', $this->value);

        View::share('title', "Page");

    }

WTF su best practices? Prosim, posli mi link.

Nahoru Odpovědět  +1 5. května 14:03
try {...} catch (Exception ignored) { echo " ¯\_(ツ)_/¯ "; }
Avatar
Matúš Petrofčík
Šéfredaktor
Avatar
Odpovídá na Mego
Matúš Petrofčík:

Zrob jak si shaman radí.

Jednoducho si urobíš nejaký BaseController, z ktorého bude každý tvoj konkrétnejší kontroler dediť, a tak budeš mať opakujúcu sa funkciu (dáta pre header, footer) na jednom mieste. Ak musí v Laraveli kontroler niečo dediť z frameworku, tak to stačí v BaseController-u.

Nahoru Odpovědět  ±0 5. května 14:34
obsah kocky = r^2 ... a preto vlak drnká
Avatar
mayo505
Redaktor
Avatar
Odpovídá na Mego
mayo505:

Ako aj to čo píše Shaman je riešienie aj keď sa mi úplne nepáči, pretože čo ak by mal rôzne pätičky a rôzne footre na rôznych stránkach a musel by to šialene dediť. Napríklad chcem typ hlavičky čislo 1 a typ pätičky číslo 3. To by tak jednoducho nevyriešil kvôli viacnásobnej dedičnosti. Aj keď je mi jasné, že vo väčšine prípadov toto problém nebude, iba som chcel poukázať na nedostatok tohto riešenia.

Laravel má na toto vec, ktorá sa volá View Composer, ktorý sa zavolá pri vykresľovaní určitého pohľadu. Môžeš ho teda naviazať priamo na header.blade.php (aspoň dúfam a ak nie tak na všetky view, ktoré ho includujú). Viac info tu https://laravel.com/docs/5.1/views#…, malo by to byť z tade jasné, ak nie poradím viac

 
Nahoru Odpovědět 5. května 14:37
Avatar
mayo505
Redaktor
Avatar
Odpovídá na shaman
mayo505:

https://translate.google.sk/#… :D

neexistuje jeden link kde by si to mal všetko vypísané

 
Nahoru Odpovědět  +1 5. května 14:38
Avatar
Matúš Petrofčík
Šéfredaktor
Avatar
Odpovídá na mayo505
Matúš Petrofčík:

Mego napísal presne čo chce, a shaman-ove riešenie to rieši.

Ak potrebuješ v niektorom z view-ov inú hlavičku, tak si jednoducho prepíšeš v danom kontroleri metódu (v tomto prípade konštruktor), prípadne vygeneruješ extra dáta čo by nahradili tie "defaultné" (kľudne do inej premennej). Chápem že sa snažíš poukázať na univerzálne riešenie.

edit: za čo mám ten mínus a šaman nie? :D

Editováno 5. května 16:13
Nahoru Odpovědět  +1 5. května 16:12
obsah kocky = r^2 ... a preto vlak drnká
Avatar
mayo505
Redaktor
Avatar
Odpovídá na Matúš Petrofčík
mayo505:

áno rieši, ale zároveň sa mego pýtal aj na best practices tak preto som odpovedal tým štýlom. Ďalší problém toho riešenia je ak v jednej metóde v controlleru to chceš a v druhej nie. To by si to najprv musel "zrušiť" v konštruktore a následne "aktivovať" v tej metóde a to už by bol duplikovaný kód. A povedal by som, že toto sa bude veľmi často (hlavne v laraveli) stávať. Napríklad metóda create zobrazí formulár a metóda store uloží a presmeruje. V metode create ti to treba ale v store je úplne zbytočne. Čiže zbytočne by sa vykonával kód v tom konštruktore, ktorý pravdepodobne bude pristupovať k databáze. Samozrejme, všetko sa dá vyriešiť ale celé mi to pripadá také "hacky".

Opäť vravím dá sa to aj tak aj tak ale mego sa pýtal na best practise a tou je v laraveli view composer, ktorý bol urobený špeciálne na tieto prípady.

To mínus je preto lebo shaman ponúkol riešenie ale ty si ho už priamo nabádal aby ho použil, navyše mojim komentárom som reagoval aj na shamana, tvoj som si všimol až keď som ho mal dopísaný ... ale neber to prosím nejako zle :)

 
Nahoru Odpovědět 5. května 16:36
Avatar
Matúš Petrofčík
Šéfredaktor
Avatar
Odpovídá na mayo505
Matúš Petrofčík:

problém toho riešenia je ak v jednej metóde v controlleru to chceš a v druhej nie.

Asi viem čo máš na mysli. Napr. že na get request (zobrazenie stránky) sa spúšťa metóda create, a na post request (spracovanie formuláru) sa spúšťa metóda store. Pri post requeste je možno zbytočné v konštruktore vykonávať kód pre získanie dát do hlavičky/pätičky, to dáva zmysel napr. ak sa stránka pri chybe nezobrazuje ale presmeruje (tak ako v tunajšom php tutoriáli, tam sa zobrazí a z $_POST sa predvyplňa do šablóny).

Ono asi záleží aj na návrhu aplikácie. Ten laraverácky view composer nepoznám, bez neho by som vytvoril ten BaseController, ktorý by mohol mať metódu na získanie dát pre hlavičku/pätičku, a všetky metódy kde to treba by si tú metódu volali (1 riadok by sa opakoval, čo už). Stále sa mám čo učiť.

K mínusku: Čím ďalej tým viac si uvedomujem rozdiel medzi "ja by som to urobil tak..." a "urob to tak..." :) určite to neberiem zle a ani sa nehnevám.

Editováno 5. května 16:57
Nahoru Odpovědět  +1 5. května 16:55
obsah kocky = r^2 ... a preto vlak drnká
Avatar
mayo505
Redaktor
Avatar
mayo505:

áno presne tak som to myslel :)

prípadne možno by sa dal použiť trait, čím by vlastne "vložil" tie metódy na získavanie dát pre hlavičku do controlleru, bez použitia dedičnosti. Aj keď tam by bol potom problém s dependency injection, ale ako vravíš, záleží na návrhu :)

 
Nahoru Odpovědět  +1 5. května 17:18
Avatar
shaman
Člen
Avatar
Odpovídá na mayo505
shaman:

Dalo by sa to rozsirit jednoducho s kontrolou metody

class BaseController {

    public function __construct()
    {
        if ($request->isMethod('get')) {

                $rovnake = new Rovnake();

                $this->value = $rovnake->metody();

                View::share('value', $this->value);

                View::share('title', "Page");
        }

    }

Dalsia moznost je zadefinovat "rovnake metody" v BaseControlleri a potom ich volat len tam kde chces:

class BaseController {

    public function __construct()
    {
    }

    public function rovnakeMetody()
    {
        // tutok nieco zrobit treba spolocne pre header a footer
    }

        public function ineMetody()
        {
                // nieco ine pre post requesty
        }
}

a potom v EshopControlleri volas:

class EshopController extends BaseController
{
        public function index() {
                $this->rovnakeMetody();
        }

        public function store() {
                $this->ineMetody();
        }
}

Ked tak pozeram View composer, tak to vlastne riesi tiez. Prave ma napadlo, ze spravit middleware na get funkcie je dalsie riesenie. Ako vidime, rieseni je vela a kazde je vhodne pre urcite pripady. Preto nerad pocuvam best practices.

Pre mna hadat sa o best practices je ako hadat sa ze 5x3 = 3 + 3 + 3 + 3 + 3 ale nie 5 + 5 + 5.

Nahoru Odpovědět  +1 5. května 18:24
try {...} catch (Exception ignored) { echo " ¯\_(ツ)_/¯ "; }
Avatar
Mego
Člen
Avatar
Odpovídá na shaman
Mego:

WTF? Čo je middleware?

Nahoru Odpovědět  -1 5. května 18:33
Radšej 15 minút skôr, ako 15 sekúnd neskoro...
Avatar
shaman
Člen
Avatar
Odpovídá na Mego
shaman:

MIddleware: Celu tvoju aplikaciu si predstav ako cibulu. Ked uzivatel pride k tvojej cibuli a pyta sa GET /jadrocibule , tak prechadza cez jednotlive vrstvy cibule az pride do stredu, kde je uz tvoj kontroler. Middleware su vsetky tie vrstvy medzi tym ako tvoja aplikacia zacne spracovavat route a tym kym sa spusti tvoj samotny kontroller. Middleware by som prelozil ako software uprostred.

Napriklad samotna authentifikacia je tiez middleware. Pred tym ako sa spusti kontroller, sa musi overit ci dany uzivatel ma spravny token a ci je teda authentifikovany. Middleware mozes pridat aj viac a vzdy sa spustaju v tom poradi ako ich zadefinujes. Dokonca mozes nastavit middleware aby sa vykonal az po cinnosti kontrollera.

Napriklad toto:

Route::get('admin/profile', ['middleware' => 'auth', function () {
    //
}]);

kontroller pre admin/profile sa spusti az po tom ako auth zbehne.

Kazdy middleware ma vo vnutri $next, cim vola v poradi dalsiu vrstvu cibule a vracia $response pre dalsie middleware alebo kontroller. Pre tvoj pripad by handle() metoda middlewaru vyzerala asi takto

public function handle($request, Closure $next)
    {
        if($request->isMethod('get')) {
                // zavolaj nejake "rovnake metody"
        }
        $response = $next($request);
        return $response;
    }

a tento middleware si zakvacis na vsetky route ktore chces. Ja neviem ci som ti middleware trochu vysvetlil, ale skus sa pozriet na dokumentaciu. https://laravel.com/…2/middleware

Nahoru Odpovědět 5. května 22:27
try {...} catch (Exception ignored) { echo " ¯\_(ツ)_/¯ "; }
Avatar
mayo505
Redaktor
Avatar
mayo505:

Mego odporúčam ti prečítať si celú dokumentáciu, middleware je jedna zo základných súčastí frameworku, v dokumentácii je dokonca v kategórii "The Basics". Očividne máš podstatné nedostatky v znalosti ako funguje framework. Dokumentáciu prečítaš max. za deň a dozvieš sa veľa vecí (samozrejme mimo iného čo je to middleware a čo je to view composer). Navyše to nie je úplne nudné čítanie, je to iné ako čítať dokumentáciu k mobilu, ktorý si dostal.

Shaman best practices majú svoj význam a ja som sa snažil poukázať prečo je jedno riešenie lepšie než druhé a teda je "better practice". Keď používaš príklad s číslami tak keď počítam na papiery 25 * 14, tak si čísla napíšem pod seba a vynásobím ich podľa známej techniky a nebudem počítať 25 + 25 + 25 + 25 + 25 + 25 + 25 + 25 + 25 + 25 + 25 + 25 + 25 + 25. Napríklad z tých dvoch riešení čo si napísal je prvé úplna blbosť (prepáč, že to tak napíšem). To druhé sa povedzme dá, ale išlo mu práve o to aby nemusel opakovať stále to isté (a to aj keď by sa jednalo len o jeden riadok).

 
Nahoru Odpovědět 5. května 22:43
Avatar
shaman
Člen
Avatar
Odpovídá na mayo505
shaman:

Mayo, tvoje riesenie je jedno z rieseni. To ci je better practice alebo best practice nebudem rozhodovat, kazdy nech si spravi usudok a rozhodnutie sam. Poukazali sme tu 3 sposoby ako sa da jeho problem riesit. A ked nestaci, tak pridam riesenie cez Eventy. A netlac na nikoho ze ten View Composer je best practice a jedine spravne riesenie, lebo ti dam minusko takisto ako si ho ty dal Matusovi Petrofcikovi. ;)

Tie pocty dvoch cisel je len priklad poukazujuci nad nezmyselnostou hadania sa ktora metoda je lepsia. Dufam ze si nemyslis naozaj ze to pocitam 5 + 5 + 5?

Nahoru Odpovědět 5. května 23:10
try {...} catch (Exception ignored) { echo " ¯\_(ツ)_/¯ "; }
Avatar
mayo505
Redaktor
Avatar
Odpovídá na shaman
mayo505:

V mojom poslednom komentári som nikde nenapísal čo má použiť. Reagoval som na tvoj komentár kde si vlastne povedal, že akési best practices nemajú význam (nie úplne ale v podstate) a s tým nesúhlasím. Iba som povedal, že všeobecne existujú veci, ktoré sú lepšie a ktoré sú horšie. To, že sa dá niečo urobiť 10 spôsobmi neznamená, že 10 spôsobov je dobrých. Áno je dobré vedieť o 10 spôsoboch ale je aj dobré povedať aké sú ich nedostatky, lebo nie každý to vie sám uvážiť.

Iba tak pomimo ale hodí sa mi k tomuto jeden výrok Juvala Lowyho, ktorý je síce high level softvérový architect, ale to nijako nevadí.

For the beginner architect, there are many options for doing pretty much anything. But for the Master architect, there are only a few [1].

Toto teraz nepíšem nijako osobne (a to hlavne ten citát, v žiadnom prípade sa neoznačujem za toho "master"). Ešte raz zopakujem čo som chcel vyjadriť, lebo niekedy si ľudia domyslia aj to čo som povedať nechcel, netýka sa to teraz tohto vlákna ale všeobecne: Nie všetky riešenie sú na rovnakej úrovni jedno môže byť lepšie jedno horšie. Potom sú riešenia, ktoré sú vo väčšine prípadov lepšie ako druhé a teda má sa význam baviť o best practices.

Dufam ze si nemyslis naozaj ze to pocitam 5 + 5 + 5?

O to mi práve ide, počítaš to ako 5*3, lebo je to lepšie, je to lepšia metóda. Ak sa ma niekto spýta ako násobiť tak mu poviem, že tým klasickým spôsobom, lebo je to "best practise".

[1] zdroj: http://www.oreilly.com/pub/e/3281

Editováno 5. května 23:43
 
Nahoru Odpovědět 5. května 23:42
Avatar
shaman
Člen
Avatar
Odpovídá na mayo505
shaman:

Vdaka za link, urcite si to pozriem cez vikend. Ten citat som uz niekde videl a suhlasim s nim. Ale este pred zaciatocnikom architektom je zaciatocnik programator a ten ani nevie ake moznosti ma. Az clovek ktory vie o svojich moznostiach moze premyslat ktora moznost je better alebo best.

Nahoru Odpovědět  +1 6. května 1:09
try {...} catch (Exception ignored) { echo " ¯\_(ツ)_/¯ "; }
Avatar
mayo505
Redaktor
Avatar
Odpovídá na shaman
mayo505:

s tým súhlasím :)

inak ak by ťa zaujímalo od neho viac tak má celkom zaujímavé videá o architektúre idesign, ktorú vytvoril https://www.youtube.com/playlist?…

 
Nahoru Odpovědět 6. května 11:55
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 19 zpráv z 19.