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 | 2668
 
@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 | 2668
 
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 | 2668
 
- 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)