Lze nastavit konkrétní implementaci služby pro službu generovanou továrnou?
- CZechBoY
- Člen | 3608
Zdravím,
mám formulář, který odesílá nějaký data po api – takže dostane
v konstruktoru nějakej interface na api, kam potom pošle odeslaná data.
Klasicky v 99% případů používám jednu třídu, kterou mám teď v dic a
normálně se autowirem předá.
Teďka potřebuju tomu formuláři dát nějakou jinou implementaci api. Jak to
udělat?
Co mě zatím napadlo je udělat setter tomu formuláři a apinu dodatečně
nastavit. Problém je kde sehnat instanci tý nový api – když ji registruju
jako službu v dic tak mi vyběhne hláška, že mám 2 služby stejnýho typu
(IApi třeba).
Šlo by to vyřešit i bez toho setteru? Že bych tý tovární třídě
(automaticky generovaná přes nette interface) řekl, že pro tenhle presenter
tam dosaď (v presenteru mám inject) tuhle třídu, jinak autowire.
Snad jsem to popsal pochopitelně.
Díky za reakce.
- ondraondra81
- Člen | 82
U te druhe sluzby v config neon pridej autowire: false a nejak si ji pojmenuj
A pak ji muzes pro ten dany form predat zase v configu primo do konstruktoru.
sorry odpovidam z mobilu takze presny kod ti ted nenapisu
- CZechBoY
- Člen | 3608
Presenter využívající apiA (defaultní autowired)
class ApiAPresenter extends Presenter
{
/** @var IFormFactory @inject */
public $formFactory;
protected function createComponentForm()
{
return $this->formFactory->create();
}
}
Presenter využívající apiB
class ApiBPresenter extends Presenter
{
/** @var IFormFactory @inject */
public $formFactory;
protected function createComponentForm()
{
$form = $this->formFactory->create();
$form->setApi(new ApiB); // toho new bych se chtěl minimálně zbavit a vyžádaj nějak službu
// nebo nějak do tohohle presenteru dostat už nastavenou factory
return $form;
}
}
formulář používající api
/**
* @method setApi(IApi $api) <-- tohohle bych se chtěl taky zbavit a rovnou v konstruktoru předat správnou službu
*/
class Form extends UI\Form
{
private $api;
public function __construct(IApi $api)
{
$this->api = $api;
$this->setupForm();
}
private function create()
{
$this->addText(...);
$this->onSuccess[] = function (Form $form, ArrayHash $values) {
...
$this->api->process(...);
});
}
}
interface IFormFactory
{
/** @return Form */
function create();
}
Editoval CZechBoY (13. 5. 2016 22:25)
- Unlink
- Člen | 298
No dalo by sa vytvoriť druhú továrničku, len v tom druhom presenteri ju musíš injectnúť pomocou konštruktoru.
services
- Model\ApiA # Api A - Autowirovaná
apiBService: # Api B - neautowirovaná
class: Model\ApiB
autowired: false
- MyApp\IFormFactory # Štandartná automaticky generovaná továrnička
apiBFormFactory: # Druhá automaticky vygenerovaná tovarnička, využívajúca ApiB
class: MyApp\Form
implement: MyApp\IFormFactory
autowired: false
arguments: [@apiBService]
- ApiBPresenter(@apiBFormFactory) # Pomocou konštruktoru vložime druhú tovarničku
class ApiBPresenter extends Presenter
{
/** @var IFormFactory */
public $formFactory;
public function __construct(IFormFactory $formFactory)
{
$this->formFactory = $formFactory;
}
protected function createComponentForm()
{
$form = $this->formFactory->create();
return $form;
}
}
v 2.4 by teoreticky malo fungovať aj
interface IFormFactory2 extends IFormFactory
{
}
-
class: MyApp\Form
implement: MyApp\IFormFactory2
autowired: ['MyApp\IFormFactory2']
arguments: [@apiBService]
A potom si klasicky injectneješ len MyApp\IFormFactory2
Editoval Unlink (14. 5. 2016 9:03)
- CZechBoY
- Člen | 3608
Moc diky za napady.
No rikam si, ze prece nebudu delat dve tovarny pro jednu vec, jen s jinym parametrem…
Takze tovarnu v dic jde v pohode jednoduse nastavit, ted uz zbejva jen ji
nejak dopravit do presenteru.
Nastavit parametr inject metody by treba neslo?
Vola se driv inject nebo setup? :D
Asi teda pouziju konstruktorovy predani, protoze s tim injectem by byl jen
problem.
Jeste jednou diky :-)
- Unlink
- Člen | 298
CZechBoY napsal(a):
No rikam si, ze prece nebudu delat dve tovarny pro jednu vec, jen s jinym parametrem…
No ono defakto sú dve, len si ich nette vygeneruje samo
Ono by bola ešte jedna možnosť, naimplementovať si tú továrničku sám a potom spraviť nejaký parameter pre metódu create.
class FormFactory {
private $apiA;
private $apiB;
function __construct(ApiA $apiA, ApiB $apiB) {
$this->apiA = $apiA;
$this->apiB = $apiB;
}
function create($api = 'A') {
if ($api == 'A) {
...
}
else {
}
}
}
Nevýhodou je to, že sa viac napíšeš a nieje tie api služby sa nevytvárajú lazy.