Nette 2.1dev – jak správně a čistě dostat do komponenty přístup do db

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

Zdravim.

Používám komponentu Login pro vykreslení přihlašovacího formuláře a přihlášení uživatele.
Ovšem nevím jak dostat do komponenty přístup do databáze.

namespace Component;

use Nette;
use Nette\Application\UI\Form;

class Login extends Nette\Application\UI\Control
{

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

    protected function createComponentLoginForm()
    {
        $form = new Form();
        $form->addText( 'nick', 'Nick:', 26, 20 );
        $form->addPassword( 'password', 'Heslo:', 26 );
        $form->addSubmit( 'login', 'Přihlásit se' );
        $form->onSuccess[] = $this->loginFormSubmitted;
        return $form;
    }

    public function loginFormSubmitted( Form $form )
    {
        //TODO - jak se dostanu k databazi?
    }

    public function render()
    {
        $this->template->setFile( __DIR__ . '/Login.latte' );
        $this->template->render();
    }
}

Je správné řešení si předávat v konstruktoru službu poskytující přístup k tabulce s uživateli ($this->userRepository)?
Nebo mi doporučíte lepší řešení?

Šaman
Člen | 2666
+
0
-

Jsou dvě čisté možnosti, obě jsou DI.

  • Jedna možnost je konstruktor injection a ano, je to čistý a doporučovaný způsob.
  • Pokud bys z nějakých důvodů nechtěl použít konstruktor, tak použij setter injection. Napiš si setter a pokud chceš, aby se závislost předávala automaticky, pojmenuj ho inject*. Inject metody se ve verzi 2.1 zavolají automaticky ihned po vytvoření instance kontejnerem.
  • Pokud bys náhodou někdy vytvářel instanci ručně, tak bys musel ručně také předat závislosti, ať už do konstruktoru, nebo pomocí té metody.
batko
Člen | 219
+
0
-

prečti tohle: před týdnem jsem založil vlákno a je tam vše

https://forum.nette.org/…vrh-aplikace

motorcb
Člen | 552
+
0
-

Šaman:

Díky za info.
konstruktor injection nevyužiji, protože je to komponenta tu musím inicializovat.
Nehledě na to, že kdybych chtěl v budoucnu v této komponentě přistupovat i k jiným repository, musel bych upravit všechny metody kde se volá komponenta Login:
Asi neexistuje možnost nadefinovat komponentu automaticky aby si přes DI natahla požadované závislosti,co?

protected function createComponentLogin()
{
    return new Component\Login( TADY_BYCH_MUSEL_PREDAVAT_ZAVISLOSTI );
}

Jak bych měl použít ten setter injection?

Díky

Šaman
Člen | 2666
+
0
-

Ten problém je docela dopodrobna rozebrán na fóru
Aktuální stav a ukázkové řešení je tady

Cílem je minimalizovat volání operátoru new a nechat většinu instancování a řešení závislostí na kontejneru. Pak nemusíš přepisovat nic, jen ten jeden konstruktor. O ostatní se postará aplikační kontejner a jeho správa závislostí.

// Mimochodem v té druhé ukázce je i příklad setter injection, v tomto případě do presenteru (tam totiž může být s použitím konstruktoru problém). Jedná se o tu metodu injectShowBasketFactory. Je jedno, jak se bude jmenovat, ale musí začínat na inject* (aby ji automaticky zpracoval autowiring) a musí být uveden typ požadovaného parametru (zde třída ShowBasketFactory), podle které se dohledá odpovídající služba v kontejneru a předá se.

Editoval Šaman (13. 6. 2013 20:54)