Generované továrničky s parametry

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

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?

enumag
Člen | 2118
+
+3
-

V master větvi nette/di je ta magie implementovaná.

Eda
Backer | 220
+
+2
-

Paráda, díky. Nette je vždy o krok napřed :-)
Tak snad to brzo bude ve stable verzi.

Šaman
Člen | 2665
+
0
-

@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
+
0
-

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

Šaman
Člen | 2665
+
0
-

Ok. Zkoušel jsem to takhle.
A jak se dá z gitu zjistit, ve kterých větvích je daný commit zmergován?

enumag
Člen | 2118
+
0
-

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
+
0
-

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
+
0
-

@Š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
+
+1
-

Pull request s fixem: https://github.com/…e/di/pull/17

Editoval enumag (7. 9. 2014 2:21)

Šaman
Člen | 2665
+
0
-
  • 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
+
0
-

Není tam ještě nějaký problém? Na 2.2@dev mě to nechce fungovat.

Parameter $templateFile has no type hint, so its value must be specified.

enumag
Člen | 2118
+
0
-

@akadlec Můj PR s fixem už tam nějakou dobu je. Zkus 2.3-beta2 a jestli to nebude fungovat tak ukaž kód.

akadlec
Člen | 1326
+
0
-

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');
enumag
Člen | 2118
+
+2
-

@akadlec Ve 2.2 auto-binding parametrů není implementován, musíš to naspecifikovat ručně pomocí parameters a arguments. Konkrétní syntaxi si nepamatuju – právě proto jsem to tlačil aby to ve 2.3 konečně bylo.

akadlec
Člen | 1326
+
0
-

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
+
0
-

@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%']);
akadlec
Člen | 1326
+
0
-

Jasně ale to tvoje udělá skoro to samé co to moje:

	public function create($templateFile)
	{
		$service = new IPub\SomeComponent\Components\Control('%templateFile%');
		return $service;
	}

předá to do konstruktoru string

enumag
Člen | 2118
+
0
-

Tak zkus trochu experimentovat se Statement. Nebo se podívej do testů jestli to tam nějak není. Přes neon to jde určitě, viz první příspěvek tématu. V extension jsem to nikdy nedělal.

David Matějka
Moderator | 6445
+
0
-

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)

akadlec
Člen | 1326
+
0
-

@matej21 perfekt tohle funguje.