Nove Inject a DIC továrničky, presentre a modely

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
duskohu
Člen | 778
+
0
-

V poslednej dobe pribudol sposob ako injectovat tovarnicky presentery a modeli, mam v tom trosku bordel co a ako pouzivat, tak by som sa chcel spytat ci som to spravne pochopil:

1. Inject sluzby do Presenteru:
neon:

services:
    Users

presenter:

/** @var Users */
private $users;
/**
 * injectUsers
 * @param Users
 */
public function injectUsers(Users $users) {
    $this->users = $users;
}

2. Inject Komponenty do presenteru + inject do Komponenty

neon:

services:
    Users

factories:
    editUsers:
        create: EditUsersControl(%params%)
        implement: IEditUsersControlFactory
        parameters: [params]

komponenta:

class EditUsersControl extends BaseControl {

    /** @Users */
    private $users;

    /** @array */
    private $params;

    public function __construct($params = array(), Users $users) {
        $this->params = $params;
        $this->users = $users;
    }
}

interface IEditUsersControlFactory
{
    /** @return EditUsersControl */
    function create($params);
}

presenter:

class UserPresenter extends \BasePresenter {
    /**
     * @var IEditUsersControlFactory
     */
    private $editUsersFactory;

    private $params = array();

    /**
     * @param IeditUsersControlFactory $editUsersFactory
     */
    public function injectEditUsersFactory(\IEditUsersControlFactory $editUsersFactory)
    {
        $this->editUsersFactory = $editUsersFactory;
    }

    //a napriklad v render:
    public function renderDefault() {
        $editUsers = $this->editUsersFactory->create($this->params);
        $editUsers->metoda();
    }
}

ale pokial v komponente pouzijem nieco ako:

$url = $this->presenter->link("this", $linkParams);

tak mi to zacne nadavat ze komponenta nieje pripojena k presentru
takze asi by bolo vhodnejsie ist cez tovarnicku a nedavat to do render

/**
 * @return EditUsersControl
 */
protected function createComponentEditUsers()
{
    return $this->editUsersFactory->create($this->params);
}

3. Do modelu tak pouzijem toto:
https://pla.nette.org/…cy-injection

4. co ak budem chciet nejaku triedu ktora nebude komponenta ani model takze Extension a na to pouzijem toto:
http://filip-prochazka.com/…te-framework

Filip Procházka
Moderator | 4668
+
0
-

1. Inject sluzby do Presenteru:
neon:

Ten zápis je maličko jinak

services:
	users: Users

Jinak to máš správně.


2. Inject Komponenty do presenteru + inject do Komponenty

neon:

Opět drobná chybka

services:
	users: Users

komponenta:

class EditUsersControl extends BaseControl {

musíš volat parent::__construct();

public function __construct($params = array(), Users $users)
{
	parent::__construct()
	$this->params = $params;
	$this->users = $users;
}

presenter:

class UserPresenter extends \BasePresenter

Tohle máš taky dobře jen napůl. Komponentu musíš vždy prohnat přes továrničku v presenteru, tak ja píšeš níže

protected function createComponentEditUsers()
{
    return $this->editUsersFactory->create($this->params);
}

Další věc je – nepoužívej vlastnost $params, používá ji PresenterComponent a mohl by jsi tím něco rozbít. Nevím co si tam předáváš, ale pojmenuj to jinak :)


3. Do modelu tak pouzijem toto:
https://pla.nette.org/…cy-injection

Když chceš něco předat do modelu, tak použiješ úplně klasicky konstruktor. Tenhle článek by měl obsahovat důrazné upozornění že je velice zastaralý! – Jé hele, on ho obsahuje ;)


4. co ak budem chciet nejaku triedu ktora nebude komponenta ani model takze Extension a na to pouzijem toto:
http://filip-prochazka.com/…te-framework

Jak jsi se dostal k tomuhle v kontextu ostatním věcí moc nechápu, ale budiž :) Extension je třída, která nahrazuje části konfigu. Nejčastěji ji využiješ, když chceš vytvořit nějakou část systému, kterou budeš chtít mít i v dalším projektu.

duskohu
Člen | 778
+
0
-

Dakujem za postreh, dost pomohlo minimalne ma clovek aspon prehlad.

4. co ak budem chciet nejaku triedu ktora nebude komponenta ani model takze Extension a na to pouzijem toto:
http://filip-prochazka.com/…te-framework

Jak jsi se dostal k tomuhle v kontextu ostatním věcí moc nechápu, ale budiž :) Extension je třída, která nahrazuje části konfigu. Nejčastěji ji využiješ, když chceš vytvořit nějakou část systému, kterou budeš chtít mít i v dalším projektu.

No v kontextu to nema nic spolocne, ale napadlo ma to spomenut, lebo som si chcel vytvorit nejaky objekt napr. Mailer, alebo Logger, cokolvek, ale nechcem to mat ako model, ale ani ako komponentu a chcem ju pouzivat aj v dalsich projektoch, a nevedel som aky je najvhodnejsi sposob realizacie. Len zaregistrovat, nakonfogurovat, predat do komponenty, presenteru, kdekolvek a pouzivat.

duskohu
Člen | 778
+
0
-

Este ma napadla jedna poznamka, Pises ze Komponentu musíš vždy prohnat přes továrničku v presenteru,
A potom ako by si definoval toto? https://doc.nette.org/…tion/factory#…
Tam to nerobis. Viem ze to neni potreba kedze je to znovupouzitelna factory, ale potom sa mi nejako straca rozdiel medzi niecim takym a komponentou. Nie je to tak ze na zaciatku je aj control aj nejaka trieda ktoru chcem znovu pouzit (to je vlastne aj komponenta) je factory a ked chcem z toho komponentu tak to prezeniem tovarnickou? Tym padom by som nemal robit NameControl, ale NameFactory. Na pociatku je vsetko factory.

bazo
Člen | 620
+
0
-

na pociatku nie je vsetko factory. su len komponenty, ktore vytvaras v tovarnickach v prezenteri. to o com pise hosiplan je len presunutie konfiguracie z createComponent metody prezenteru rovno do configu.

zmysel toho interfacu pre tovarnicku je iba lazy vytvaranie tej komponenty.

Filip Procházka
Moderator | 4668
+
0
-

duskohu napsal(a):

Este ma napadla jedna poznamka, Pises ze Komponentu musíš vždy prohnat přes továrničku v presenteru,
A potom ako by si definoval toto? https://doc.nette.org/…tion/factory#…
Tam to nerobis.

Vždyť si vytvářím Mail\Message, to není komponenta.

duskohu
Člen | 778
+
0
-

Super, dakujem za vycerpavajuce odpovede. Uz zacinam mat v tom jasno :-)

duskohu
Člen | 778
+
0
-

Este pridam k comu sa toto tema vstahuje:
Inject a DIC továrničky
https://doc.nette.org/…tion/factory#…
alebo:
https://doc.nette.org/…tion/factory?…
Diskusia k clanku
https://forum.nette.org/…c-tovarnicky#…

duskohu
Člen | 778
+
0
-

Neviem preco, ale nejako sa mi zacali divne spravat persistentni parametre, predpokladam preto lebo pri vytvarani instancie komponenta este nepozna ich hodnotu, takze v konstructore ich nastavenie mat nemozem, ale mam aj dalsi problem, tvar url mi urobi 2 krat jedna hodnota je pre presenter a druha pre komponentu ale komponenta si ich aj tak neprecita.

?column=surname&sort=desc&order-column=surname&order-sort=asc
// a ma to byt takto
?order-column=surname&order-sort=asc
class OrderControl extends BaseControl {

    /** @persistent */
    public $column;

    /** @persistent */
    public $sort;

    /**
     * @param string $column
     * @param string $sort
     */
    public function __construct($column = NULL, $sort = NULL) {
        parent::__construct();
        if ($column == NULL) {
            new \Nette\InvalidArgumentException("Parameter column is empty");
        }
        if ($sort == NULL) {
            new \Nette\InvalidArgumentException("Parameter sort is empty");
        }
        if ($this->column == NULL) {
            $this->column = $column;
        }
        if ($this->sort == NULL) {
            $this->sort = $sort;
        }
    }

    /**
     * sortLink
     * @param string $column
     * @param string|NULL $title
     * @param array $attributes
     * @return Nette\Utils\Html
     */
    public function sortLink($column, $title = NULL, $attributes = array()) {
        if ($title == NULL) {
            $title = $column;
        }
        $linkParams['column'] = $column;

        if ($column == $this->column) {
            $linkParams['sort'] = $this->sort == "asc" ? "desc" : "asc";
            $attributes["class"] = "sort-$this->sort";
        } else {
            $linkParams['sort'] = "asc";
        }
        $url = $this->presenter->link("this", $linkParams);
        $link = Html::el('a', $attributes)->href($url)->setText($title);
        return $link;
    }

}

/**
 * IOrderControlFactory
 */
interface IOrderControlFactory {

    /** @return OrderControl */
    function create($column, $sort);
}

neon:

factories:
    order:
        create: OrderControl(%column%, %sort%)
        implement: IOrderControlFactory
        parameters: [column, sort]

presenter:

/**
 * @var IOrderControlFactory
 */
private $orderFactory;

/**
 * @param IOrderControlFactory $orderFactory
 */
public function injectOrderFactory(\IOrderControlFactory $orderFactory)
{
    $this->orderFactory = $orderFactory;
}

/**
 * @return OrderControl
 */
protected function createComponentOrder()
{
    return $this->orderFactory->create("surname","asc");
}

presenter render
tu si ziskam udaje z komponenty z persistentnich parametrov

$orderData = array($order->column . " " . strtoupper($order->sort));

a pouzijem v sablone:

<th width="250">{$presenter['order']->sortLink("surname", "Meno")}</th>
<th width="250">{$presenter['order']->sortLink("email", "E-mail")}</th>
<th>{$presenter['order']->sortLink("active", "Stav")}</th>
bazo
Člen | 620
+
0
-

ved tu si ich vzdy prepises na default return $this->orderFactory->create(„surname“,„asc“);

a potom ich uz nikde nemenis.

a cely ten tvoj kod je nejaky divny.

aha, takze sortLink ti tvori odkaz pre presenter preto to mas v url dvakrat. neviem preco si pouzil taky obskurny pristup ale ok.

duskohu
Člen | 778
+
0
-

Aha to som si nevsimol, dakujem, a preco obskurny pristup? Vsak poslem komponente defaultne hodnoty, v sablone len vlozim metodu na generovanie linku a v presentru si nacitam data podla ktorych mam radit. Nijak inak ma to nenapadlo. Ako by si to riesil? Necham si rad poradit :-)

Editoval duskohu (23. 11. 2012 16:04)

bazo
Člen | 620
+
0
-

ja myslim hlavne tu metodu sortLink, ved tu linku dokazes zapisat aj v sablone. potom ti tam chyba handler na ten odkaz. a este si v konstruktore zakazdym prepises tie sortovacie hodnoty

duskohu
Člen | 778
+
0
-

Sortovacie hodnoty si prepisem len ked su persistentne hodnoty NULL, to znamena ked nemam v url ziadnu hodnotu pre sort a column, takze nastavim defaultne tie co poslem, Linka sa generuje na zaklade persistentneho parametra, podla toho ci nejaky existuje, ci je asc/desc alebo aky je stlpec podla ktoreho ma sortovat, tak vsetko to som nechcel zapisovat v sablone, a naco mi je handler?

bazo
Člen | 620
+
0
-

naco ti je link ked ho nikde nehandlujes? potom je vladtne cely ten kontrol zbytocny

duskohu
Člen | 778
+
0
-

komponenta si sama nastavi hodnoty perzistentneho parametra na zaklade URL, kokil v url niesu tak nastavi tie co som jej ja poslal. takze si udrzuje stav. A potom v presentri si ich proste vytiadnem z komponenty, ziadny handle nepotrebujem.

public function renderDefault() {
	$order = $this['order'];
	$orderData = array($order->column . " " . strtoupper($order->sort));
	$this->model->order(implode(",", $orderData));
}