Předání parametrů do továrny formuláře

před 4 měsíci

ondrapech
Backer | 46
+
0
-

Ahoj, řeším takový asi dost začátečnický problém s továrnami. Aktuálně formulářové komponenty vytvářím v presenteru např.

// ...
public function createComponentOrderForm()
{
	$form = new Form();
	//...
	return $form
}
//...

jelikož to v presenteru udělá celkem dost řádků, které by mohli být v samostatné třídě, chtěl bych na ten formulář udělat továrnu. První otázka zní, kde je zvykem takové třídy mít jestli v modelech nebo třeba App/Forms nebo prostě kde mají místo ve struktuře projektu.
A druhá ta hlavní otázka. V těch komponentách potřebuju nějaké data která á presenter například id/data objednávky, identitu uživatele (role) nebo id/data prodejce, které potřebuju logicky předat do toho formuláře v továrně. Už sem našel,že závislosti jako třeba databázi si DI předává nějak samo. Ale co s těmito údaji? jak si je můžu předat?
Poradil by mi někdo prosím? :) Moc díky :)

před 4 měsíci

kamil_v
Člen | 99
+
+2
-

app/forms je fajn místo, protože ne vždy dopředu víš, kde v aplikaci bude form použit, takže je fajn mít je v nezávislém „úložišti“.

Závislosti adhoc si vyžádáš z DI, jiné parametry (různá ID apod.) si předávám normálně setterem.

před 4 měsíci

ondrapech
Backer | 46
+
0
-

kamil_v napsal(a):

app/forms je fajn místo, protože ne vždy dopředu víš, kde v aplikaci bude form použit, takže je fajn mít je v nezávislém „úložišti“.

Závislosti adhoc si vyžádáš z DI, jiné parametry (různá ID apod.) si předávám normálně setterem.

Co to znamená normálně setterem? :) jakože si udělám nějakou set metodu nebo v parametrech create funkce nebo přes __set() si budu nastavovat třídní atribut. nevím co tím myslíš?

Editoval ondrapech (30. 7. 11:02)

před 4 měsíci

kocourPB
Člen | 43
+
+1
-

ondrapech napsal(a):

kamil_v napsal(a):

app/forms je fajn místo, protože ne vždy dopředu víš, kde v aplikaci bude form použit, takže je fajn mít je v nezávislém „úložišti“.

Závislosti adhoc si vyžádáš z DI, jiné parametry (různá ID apod.) si předávám normálně setterem.

Co to znamená normálně setterem? :) jakože si udělám nějakou set metodu nebo v parametrech create funkce nebo přes __set() si budu nastavovat třídní atribut. nevím co tím myslíš?

V komponente budes mat private/protected atributy a na ne si vytvoris settery. Napr nejak takto:

interface IOrderForm
{
	/** @return OrderForm */
	function create();
}

class OrderForm extends \Nette\Application\UI\Control {

	protected $product;

	// ...

	public function setProduct($product): Product
	{
		$this->product = $product;
	}

	// ...

}

a v presenteru potom zavolas

/** IOrderForm @inject */
public $orderFormFactory;

public funtion createOrderForm()
{
	$form = $this->orderFormFactory->create();
	$form->setProduct($this->product); // priklad

	// ...
	return $form;
}

Editoval kocourPB (30. 7. 11:16)

před 4 měsíci

jiri.pudil
Člen | 883
+
+7
-

imo je to lepší vyžadovat v konstruktoru a předávat v metodě create(). Třída OrderForm pak nejde vytvořit „špatně“, tj. bez produktu. Nette parametry v konstruktoru podle názvu napáruje s metodou create a zbytek automaticky dohledá v DI kontejneru:

class OrderForm extends Nette\Application\UI\Control
{
	private $product;
	private $userContext;

	public function __construct(
		Product $product, // parametr předaný v create()
		Nette\Security\User $userContext // služba z kontejneru
	)
	{
		$this->product = $product;
		$this->userContext = $userContext;
	}
}

interface OrderFormFactory
{
	public function create(Product $product): OrderForm;
}

class OrderPresenter extends Nette\Application\UI\Presenter
{
	protected function createComponentOrderForm(): OrderForm
	{
		return $this->orderFormFactory->create($this->product);
	}
}

před 4 měsíci

kocourPB
Člen | 43
+
0
-

jo s tym suhlasim, povinne parametry urcite setovat v konstruktoru … to som zapomenul zminit :o)

před 4 měsíci

ondrapech
Backer | 46
+
0
-

jiri.pudil napsal(a):

imo je to lepší vyžadovat v konstruktoru a předávat v metodě create(). Třída OrderForm pak nejde vytvořit „špatně“, tj. bez produktu. Nette parametry v konstruktoru podle názvu napáruje s metodou create a zbytek automaticky dohledá v DI kontejneru:

class OrderForm extends Nette\Application\UI\Control
{
	private $product;
	private $userContext;

	public function __construct(
		Product $product, // parametr předaný v create()
		Nette\Security\User $userContext // služba z kontejneru
	)
	{
		$this->product = $product;
		$this->userContext = $userContext;
	}
}

interface OrderFormFactory
{
	public function create(Product $product): OrderForm;
}

class OrderPresenter extends Nette\Application\UI\Presenter
{
	protected function createComponentOrderForm(): OrderForm
	{
		return $this->orderFormFactory->create($this->product);
	}
}

Kluci, díky za rady. Ještě mám jeden dotaz. používáte tu oba interface. Je potřeba? k čemu je to dobré? a ten patří ve struktuře projektu tam pokud bych měl OrderFormFactory v App\Forms tak interface kam?

před 4 měsíci

kamil_v
Člen | 99
+
0
-

Ten interface máš uvedený v anotaci, díky němu Ti IDE bude napovídat. Samotná create() se zavolá až ve chvíli, kdy je objekt skutečně inicializován, tedy líně.

Já dávám interfacy vždy do stejného adresáře, kde je rodičovská třída, která interface implementuje. Tedy továrničky formů do app/forms, továrničky gridů do app/grids, interfacy jiných tříd do app/model/…
Dělám to tak kvůli snadné přenositelnosti celků, aby stačilo zkopírovat adresář a přeneslo se tak vše, co je potřeba, bez nutnosti „vyďobávat“ interface z nějakého hromadného úložiště…

před 4 měsíci

kocourPB
Člen | 43
+
+1
-

Ja som este zvyknuty ten interface komponenty (pokial obsahuje len create() metodu) pisat priamo do toho suboru s classou, takze to mam pohromade.
Pouziva to niekto podobne? Alebo je to uplna blbost a porusuje to PSR standard? Samozrejme pre interfacy s viacerymi metodami vytvaram zvlast subor.

Diky za nazory.

před 4 měsíci

jiri.pudil
Člen | 883
+
+1
-

Ten interface je dobrý k tomu, aby ti ušetřil psaní – Nette totiž jeho implementaci vygeneruje automaticky za tebe během kompilování DI kontejneru. Jinak by sis musel napsat celou factory ručně.

před 4 měsíci

janpecha
Backer | 62
+
0
-

Pokud by ses chtěl tomu interface vyhnout (ve většině případů ho reálně nepotřebuješ), můžeš se inspirovat tím, jak jsou formuláře vytvářeny v sandboxu.

před 4 měsíci

ondrapech
Backer | 46
+
0
-

janpecha napsal(a):

Pokud by ses chtěl tomu interface vyhnout (ve většině případů ho reálně nepotřebuješ), můžeš se inspirovat tím, jak jsou formuláře vytvářeny v sandboxu.

A jak potom takový formulář dostanu v presenteru?

před 4 měsíci

nightfish
Člen | 153
+
+1
-

ondrapech napsal(a):
A jak potom takový formulář dostanu v presenteru?

Továrnu předáš do presenteru a zavoláš ji v createComponent metodě. Inspirovat se můžeš opět v sandboxu

před 4 měsíci

Rybajz
Člen | 4
+
+1
-

kocourPB napsal(a):

Ja som este zvyknuty ten interface komponenty (pokial obsahuje len create() metodu) pisat priamo do toho suboru s classou, takze to mam pohromade.
Pouziva to niekto podobne? Alebo je to uplna blbost a porusuje to PSR standard? Samozrejme pre interfacy s viacerymi metodami vytvaram zvlast subor.

Diky za nazory.

Používám to stejně.