Tvorba tovarnicky na komponentu

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

Prosim o radu snazim se vytvorit samostatnou komponentu kterou muzu pouzit opakovane na ruznych mistech potrebuji vni pracovat s db pridavat mazat atd takze tam potrebuji pripojeni k db absolutne jednoducha a primitivni vec! a je to pro me uz treti den absolutne neprekonatelny problem! procet jsem uplne vse od quiqstartu dokumentaci az po fora a DI nechapu! takze sem se snazil postupovat standartne, komponenta funguje bez problemu mam pro ni vytvorenou specialni sablonu kterou bezproblemu nacte kdyz tu komponentu zavolam pres {control …} ale v momente kdyz potrebuji pracovat s db nemam pripojeni a nejsem schopen ho v te komponente vytvorit ani ho tam predat!
V presenteru mi pripojeni v pohode funguje ale v komponente kterou vytvarim jako instanci v danem presenteru uz ne!
Kdyz se snazim vytvori interface a factory coz uz vubec nechapu proc a kcemu to je? a sluzbu v konfigu tak mi to zas neni schopno nacis sablonu ze pry „Interface function App\kontaktformFactory::render() cannot contain body“ prosim je nejaka jednoducha cesta jek ziskat pripojeni k db tam kde ho potrebuji napr. v te samostatne komponente? Moc diky za rady a prosim neodkazovat na quiqstart dokumentaci a podobne… procet se to xkrat ale proste mi to ztoho neni jasne!!je to delane pro odborniky ne pro zacatecniky!diky za pochopeni! pouzivam nette 2.1

Editoval marcelxy (5. 1. 2014 15:01)

Šaman
Člen | 2666
+
0
-

Huh, to bude na dýl. Je to trochu komplexní téma.

  1. Pro úplný začátek si můžeš vytáhnout databázi z presenteru (připojená komponenta má k němu přístup přes $this->presenter). Je to ale špatně a budeš to muset zrefaktorovat! Musíš ale někde začít a pokud tu komponentu rozchodíš takto, tak je na čem stavét dál.
  2. Vytvoříš si tovární třídu, která si injectuje databázi a jiné závislosti a umí vytvořit a nakonfigurovat konkrétní instance tvé komponenty.
  3. Tohle jde zautomatizovat pomocí generovaných továren. Ty se ale mezi verzemi @dev a @final trochu změnily, tak si jdu zaktualizovat příklad a někam ho nasdílím.

P.S. Připojená komponenta znamená, že presenter nemáš k dispozici už v konstruktoru, ale nejdříve v metodě attach(). V render() už je připojená určitě.

Editoval Šaman (4. 1. 2014 9:53)

marcelxy
Člen | 70
+
0
-

Aha

1. tak sem postupoval, ze jsem se v komponente snazil vytvorit pripojeni jak v presenteru

private $conect;

   public function __construct(\Nette\Database\Context $conect)
   {
       $this->conect = $conect;
   }

a pak uz jen $this->conect->table(‚kontakty‘)->insert($values);

coz v presenteru normalne funguje ale v komponente uz ne, hlasi
to „__construct() must be an instance of Nette\Database\Context, none given“ z cehoz mi plyne ze mu musim predat to pripojeni k db ale nevim jak? kdyz tu instanci te komponenty vytvarim v presenteru kde mi pripojeni k db funguje tak jak jsem uved na zacatku! takze v presenteru jsem mel!

 public function createComponentContaktForm()
{
   	 $frmkot = new kontaktform(a tady si myslim ze bych mel predat pripojeni k db?);
	 return $frmkot;
}

ale nevim jak ,ale asi to neni ani spravne ten system je tvoren asi jinak a to pres DI coz nechapu!

2. pak mi nekdo na foru poradil ze mam jit pres interface a factory coz taky dost dobre nechapu!
takze jsem prejmenova z class mjetrida na

namespace App;

interface FooFactory
{

tady jsem dal kod te me komponenty stejne jako driv ve class{...}
    /**
    * @return Foo
    */
    public function create();
}

a v presenteru ji pak volam pres

public $fooFactory;

    public function createComponentFoo()
    {
        $foo = $this->fooFactory->create();

        return $foo;
    }
}

a to mi vyhazuje ze
"Interface function App\kontaktformFactory::render() cannot contain body“ z cehoz mi plyne ze tento postup nemuze pracovat s sablonou? kterou ovsem ta komponeta potrebuje!
takze to delam asi taky spatne?
Takze ted nevim kde co pridat nebo ubrat?

A uz vubec nechapu kdyz v dokumentaci se pise ze
"Narovinu: Dependency Injection (DI) není nic tajemného nebo nepochopitelného. Celé se dá shrnout do jedné sobecké věty: „nic nesháněj, ať se postará někdo jiný.“ Nic víc, nic míň.

tak musim byt asi menecenej! ze tri dny nejsem schopen se hnout z mista a to pripojeni k db te komponente predat nebo ji v ni vytvorit! i kdyz samostatna kom. mi bez pripojeni k db. normalne funguje!

Editoval marcelxy (4. 1. 2014 10:54)

Jan Tvrdík
Nette guru | 2595
+
0
-

A uz vubec nechapu kdyz v dokumentaci se pise ze "Narovinu: Dependency Injection (DI) není nic tajemného nebo nepochopitelného. Celé se dá shrnout do jedné sobecké věty: „nic nesháněj, ať se postará někdo jiný.“ Nic víc, nic míň.

tak musim byt asi menecenej! ze tri dny nejsem schopen se hnout z mista a to pripojeni k db te komponente predat nebo ji v ni vytvorit!

Problém je, že na řádku $frmkot = new kontaktform(...); jsi porušil to pravidlo, že nemáš nic shánět. Ty sháníš připojení k databázi a divíš se, že ten koncept dobře nefunguje, když nerespektuješ jeho pravidla.

Navíc „Interface function App\kontaktformFactory::render() cannot contain body“ znační, že máš nedostatky v základech PHP, konkrétně v tom k čemu slouží a jak fungují rozhraní.

marcelxy
Člen | 70
+
0
-

Jo to mas asi pravdu ucim se postupne!ale jsem strasne rad ze odpovidas ty! poslouchal jsem tvou prednasku o komponentach v planette asi 20× je super!!!!! ale tu cast kde prave resis to pripojeni k db jako samostatnou vrstvu kterou sis vytvoril doma tak to sem proste nepochopil jak si to tam presne dostal to pripojeni k db a v tom mam ten problem!!!ale jinak mas samozdrejme pravdu nedostatky mam jeste velke jsem zacatecnik ale myslim si ze bych ten prooblem mel umet prekonat ze svymi znalostmi!!

marcelxy
Člen | 70
+
0
-

No ja to pripojeni neshanim ja kdyz ho tam nadam coz byl muj puvodni zamer protoze jsem si myslel ze si ho injektuje sam, tak mi tvrdi
„__construct() must be an instance of Nette\Database\Context, none given“ to znamena presne co? ze po me chce to pripojeni?
myslel jsem si ze bych mu ho mohl nejak predat!ale to asi nejde! ze?

Jan Tvrdík
Nette guru | 2595
+
0
-

„__construct() must be an instance of Nette\Database\Context, none given“ to znamena presne co?

Absenci tvých základů PHP. Je to standardní chybová hláška PHP, která tě informuje, že nerespektuješ typehint konstruktoru.

Jiří Nápravník
Člen | 710
+
0
-

Doproučuji opravdu ten článek, co poslal Honza.

Či-li pak zjistíš, že by to mělo být nějak takhle.

interface:

namespace App;

interface FooFactory
{
    /**
    * @return Foo
    */
    public function create();
}

žádné tělo, jen prostě definuješ předpis, jak to má vypadat.

Samotná komponenta:

namespace App;

class Foo
{
	private $connect;

	public function __construct(\Nette\Database\Context $connect)
	{
		$this->connect = $connect;
	}
}

do config.neon:

services:
	- App\FooFactory

No a ted ot musíš dostat do presenteru. V 2.1 je nejlepší asi takto:

class NejakyPresenter extends BasePresenter
{
	/**
	* @var \App\FooFactory
	* @inject
	*/
	public $fooFactory;

	public function createComponentFoo()
	{
		$foo = $this->fooFactory->create();
		return $foo;
	}
}

tím se ti předá samo připojení k databázi, protože to pozná nette podle toho rozhraní co jsi uvedl v konstruktoru komponenty.

Editoval Jan Tvrdík (4. 1. 2014 14:45)

marcelxy
Člen | 70
+
0
-

Je panove ja vam vsem moc dekuji za trpelivost! ja to konecne rozjel! Ja vim ze me znalosti jsou chatrne ale ja vubec netusil ze ty „komentare“ jsou pro beh celeho systemu nepostradatelne!!! Ja uz jsem to chtel vzdat kdyz sem si najednou vsimnul ze ty komentare neboli anotace ovlivnuji colou funkcnost! pak kdyz jsem je tam vsechny spravne vlozil najednou se to rozjelo! ale bez nich to nejede!! to kdybych vedel tak si usetrim 3 dny trhani vlasu!!
Prosim o posledni vec jestli nekde se o vyznamu a pouziti tech anotaci pise podrobne? krome jednoho odstavce sem k tomu nic moc nenasel potrebuji to dostudovat!! Diky za odpoved a vsem za trpelivost.

Myiyk
Člen | 321
+
0
-

Nějaké info o anotacích podrobně jsem neviděl. V nette jsem viděl jen anotace @inject a @var <typ>. Další anotace jsou pro dokumentaci (@var je taky dokumentační, ale nette ho používá).

Základní anotace na wikipedii https://en.wikipedia.org/wiki/PHPDoc#Tags

David Matějka
Moderator | 6445
+
+1
-

@marcelxy: z hlavy me napada par anotaci, co nette vyuziva a mohou ovlivnovat chod programu:
@inject anotace pro doplnovani zavislosti – co ma doplnit hleda v anotaci @var
@return u generovanych tovarnicek
@persistent anotace u persistentnich parametru
@persistent anotace u persistentnich komponent
@User(loggedIn) v presenterech pro autorizaci, v doc nevim, kde to je, v kodu zde
@method pro magicke metody

Editoval matej21 (5. 1. 2014 0:13)

marcelxy
Člen | 70
+
0
-

Aha tak dik ja si tu 3 dny rvu vlasy jak udelat DI inject na databazi a nakonec se dozvim ze mam problem v anotaci no to je vyborne! bez te anotace ten inject nejede ze? To tam musi byt * @inject
i ta cesta k te sluzbe * @var \App\KontaktFormFactory taky,
Jinak ten inject nepojede ze ?? Jinak diky vsem za trpelivost

David Matějka
Moderator | 6445
+
0
-

inject anotace je jen jedna z moznosti, jak dostat zavislosti do presenteru, dale muzes vyuzit klasicky konstruktor injection

class FooPresenter extends BasePresenter
{
	protected $bar;
	public function __construct(Bar $bar)
	{
		$this->bar = $bar;
	}
}

nebo inject* metody – kazda metoda, ktera zacina na inject* se zavola s prislusnyma zavislostma

class FooPresenter extends BasePresenter
{
	protected $bar;
	public function injectBar(Bar $bar)
	{
		$this->bar = $bar;
	}
}

u tohoto zpusobu injectovani zavislosti (jak konstruktor, tak inject metody) nejsou dulezite anotace, ale typehint v argumentech metody.

konstruktor injection je vsak v presenterech pouzitelny malokdy, na druhou stranu, ve sluzbach a komponentach preferuj konstruktor injection a jiny zpusob pouzivej jen v krajni nouzi

pro presentery je v soucasnosti „preferovanym“ zpusobem pouziti @inject anotaci

marcelxy
Člen | 70
+
0
-

Aha ok tak to jsem se v dokumentaci nedozvedel ! Diky moc vsem