Generované továrničky s parametry
- Eda
- Backer | 220
Mám nějakou komponentu, která pro své vytvoření vyžaduje v konstruktoru nějaký textový parametr.
class Control extends BaseControl
{
public function __construct($myString)
{
...
}
...
}
Mám taky rozhraní, podle kterého se má generovat továrna:
interface IControlFactory
{
/** @var Control */
function create($myString);
}
V konfigu to mám zatím řešeno takto:
-
implement: IControlFactory
parameters: [myString]
arguments: [%myString%]
Můj dotaz zní: nejde to udělat nějakým způsobem tak, že bych můj argument z funkce create() nemusel vůbec v configu uvádět? Takto to totiž mám na dvou místech.
Pokud to nejde, další otázka zní: je dobrý nápad zkusit se zamyslet nad magickou implementací, která by v případě, že by našla nějaké parametry ve funkci create onoho rozhraní tyto parametry podle názvu automaticky předala konstruktoru vytvářené komponenty?
- Šaman
- Člen | 2665
@enumag: Zkouším teď Nette 2.2@dev i 2.3@dev a stále mi to hlásí
Parameter $pok in App\Components\Pok::__construct() has no type hint, so its value must be specified.
Nevíš, jak ta magie má fungovat? A ve které verzi? (2.2@dev je ještě relativně v pohodě, ale po zkušenostech s Nette 2.1@dev už na master verzi jet nechci.)
- enumag
- Člen | 2118
@Šaman Nechybí ti náhodou parametr v metodě create toho interface? Kdyžtak mrkni na testy, zde commit který to implementuje: https://github.com/…62dc67e109cf.
EDIT: Teď to zkoušim a taky mi to nechce fungovat tak jak by mělo. Podívám se na to.
Editoval enumag (6. 9. 2014 23:15)
- enumag
- Člen | 2118
Co jsem zkoušel tak to funguje pokud tu třídu co vytváříš dáš přímo do configu, z nějakého důvodu si ji to neumí přečíst z té return anotace respektive si ji to nepřečte včas. Důvodem je zřejmě to že jsem to implementoval už poměrně dávno a pak dělal rebase na novější verzi. Vím že to před rebasem fungovalo, akorát mne nenapadlo na to napsat test. :-/
- Šaman
- Člen | 2665
Upravil jsem config,
ale teď mi to asi vůbec nevytváří instanci IFooFactory
(v kontejneru mám proměnnou, která obsahuje text
App\Components\IFooFactory
, ale nikoliv instanci). Takže to
skončí na Call to a member function create() on a non-object
v továrničce presenteru.
// dodatek: Zkouším to na Nette 2.3.x @dev
Editoval Šaman (6. 9. 2014 23:53)
- enumag
- Člen | 2118
@Šaman Vrať ten config tak jak byl předtim a zkus pls tenhle hotfix, u mne zabral.
EDIT: U druhého projektu zabral až tenhle.
Editoval enumag (7. 9. 2014 0:17)
- enumag
- Člen | 2118
Pull request s fixem: https://github.com/…e/di/pull/17
Editoval enumag (7. 9. 2014 2:21)
- Šaman
- Člen | 2665
- Díky, zkoušel jsem rovnou ten druhý fix a funguje to i s krátkým zápisem v configu. Originál bez fixu funguje s dlouhým zápisem.
- Ta chyba, o které jsem psal podruhé, vznikla špatným injectováním (protected property a anotace @inject, kterou běžně nepoužívám).
- Ale funguje to až v dev verzi nette 2.3, takže to asi zatím používat nebudu. U 2.1@dev jsem si naběhl, když jsem nevěřil, že finální verze může být ještě silně nekompatibilní s vývojovou verzí (používal jsem injectování všude, i v modelu).
- Funkční ukázka použití je na Gistu.
- akadlec
- Člen | 1326
2.3 teď zkoušet nehodlám, potřebuju aby to jelo na 2.2
interface IControl
{
/**
* @param string $templateFile
*
* @return Control
*/
public function create($templateFile);
}
class Control extends Application\UI\Control
{
public function __construct($templateFile)
{
}
}
Registrace:
$builder->addDefinition($this->prefix('someComponent'))
->setClass('IPub\SomeComponent\Components\Control')
->setImplement('IPub\SomeComponent\Components\IControl');
- akadlec
- Člen | 1326
Mmnt takže to co uvedl @Šaman na gistu jede jen pro 2.3? Jinak sem zkusil i to definování
$builder->addDefinition($this->prefix('someComponent'))
->setClass('IPub\SomeComponent\Components\Control')
->setImplement('IPub\SomeComponent\Components\IControl')
->setParameters(['templateFile'])
->addSetup('$service->setTemplateFile(?)', ['%templateFile%']);
A to se zdálo vygenerováno ok, akorát teda až na ten setup:
$service->setTemplateFile('%templateFile%');
Takže to tu proměnnou nepředalo
- enumag
- Člen | 2118
@akadlec Ano a mimochodem to @Šaman i sám jasně napsal. ;-)
V tomto tématu se bavíme o předávání parametrů konstruktoru té komponenty, addSetup sem vůbec nepleť. Spíš zkus tohle:
$builder->addDefinition($this->prefix('someComponent'))
->setClass('IPub\SomeComponent\Components\Control')
->setImplement('IPub\SomeComponent\Components\IControl')
->setParameters(['templateFile'])
->setArguments(['%templateFile%']);
- David Matějka
- Moderator | 6445
v compiler extension pouzij:
->setArguments([new Nette\PhpGenerator\PhpLiteral('$templateFile')])
a parameters nemusis uvadet ani 2.2, v compiler extension se dokazou detekovat. (v neonu je uvest musis)