Rozšíření ContainerBuilder
- Trunda
- Člen | 26
Zdravím,
z jistého důvodu jsem si chtěl rozšířit ContainerBuilder
,
ale zjistil jsem nepříjemnou věc. Vzhledem k tomu, že
Nette\Config\Compiler
má vlastnost container
privátní, není možné vlastní implementaci
ContainerBuilder
u do Compiler
u injectnout.
Uniká mi něco? Proč je container
private?
- Filip Procházka
- Moderator | 4668
Proč bys něco takového dělal? Určitě najdeme lepší řešení, než hackovat „jádro“ Nette.
- Trunda
- Člen | 26
V pozadí této změny je lenost a pohodlnost ;). Pokusím se to popsat:
Přepsal jsem si své nadstavby, resp. jejich zavedení do DI, jako CompilerExtensions, a mým cílem bylo aby mi IDE napovídalo i pro NestedAccesor. Jediná možnost jak to udělat je upravit generování SystemContaineru tak aby „vyrobil“ více tříd resp. třídu pro každý současný NestedAccesor a přidal k ní dokumentaci jejich properties. Pak by IDE napovídalo například u Doctrine 2 a NestedSet i tuto konstrukci:
// Presneter
$this->context->doctrine->nestedSet->getManager('Entita');
// nebo i
$this->context->doctrine->entityManager;
Původně jsem to chtěl udělat také jako extension v metodě
afterCompile
, ale to vzhledem k tomu, že generováná třída
(istance třídy Nette\Utils\PhpGenerator\ClassType
) není
předávána referencí nelze.
Vím že IDE mi bude napovídat pro tuto konstrukci:
// Presneter
$this->context->doctrine_nestedSet->getManager('Entita');
// nebo i
$this->context->doctrine_entityManager;
ale já to podtržítko prostě nemůžu vystát :)
Doufám, že je to pochopitelné.
Editoval Trunda (18. 1. 2012 15:14)
- Filip Procházka
- Moderator | 4668
V první řadě bych si rejpl. Třídy se vždy předávají „referencí“. Když někam předáváš objekt, tak je to pořád ten stejný objekt, po cestě přes argumenty metody se ti sám neklonuje ;)
Co se týče toho napovídání, určitě by bylo lepší udělat podporu přímo do Nette. Já bych to také ocenil ;) Pokud víš jak, úplně nejlepší by bylo, kdyby jsi to implementoval a poslal pull request na githubu.
- Trunda
- Člen | 26
HosipLan napsal(a):
Pokud víš jak, úplně nejlepší by bylo, kdyby jsi to implementoval a poslal pull request na githubu.
Tak jsem to sepsal viz https://github.com/…ea7878553342
Je to ozkoušené a funguje to dobře.
pokud mám například rozšíření:
class ConfigExtension extends Nette\Config\CompilerExtension
{
public function loadConfiguration()
{
$container = $this->getContainerBuilder();
$container->addDefinition($this->prefix('bar'))
->setClass('Foo\Bar')
->setFactory(__CLASS__ . '::createBar');
}
/**
* @return Foo\Bar
*/
public static function createBar()
{
return new Foo\Bar;
}
}
Vytvoří to container:
/**
* @property Nette\Application\Application $application
* @property Nette\Caching\Storages\FileJournal $cacheJournal
* @property Nette\Caching\Storages\FileStorage $cacheStorage
* @property Symfony\Component\Console\Application $console
* @property NestedAccessor_constants $constants
* @property Nette\DI\Container $container
* @property NestedAccessor_foo $foo
* @property Nette\Http\Context $httpContext
* @property Nette\Http\Request $httpRequest
* @property Nette\Http\Response $httpResponse
* @property Nette\Mail\SendmailMailer $mailer
* @property NestedAccessor_nette $nette
* @property NestedAccessor_php $php
* @property Nette\Application\PresenterFactory $presenterFactory
* @property Nette\Application\Routers\RouteList $router
* @property Nette\Http\Session $session
* @property Nette\Caching\Storages\PhpFileStorage $templateCacheStorage
* @property Nette\Security\User $user
* @property Nette\Http\UserStorage $userStorage
*/
class SystemContainer extends Nette\DI\Container
{
/**
* @return NestedAccessor_php
*/
protected function createServiceFoo()
{
$service = new NestedAccessor_foo($this, 'foo');
return $service;
}
// ....
}
// ....
/**
* @property Foo\Bar $bar
*/
class NestedAccessor_foo extends Nette\DI\NestedAccessor
{
}
Takže IDE napovídá jak má :).
- Trunda
- Člen | 26
Díky, mohu se zeptat proč se na řádku 133 nekontroluje přítomnost definice? Pokud mám rozšíření, které obsahuje definici jen jedné služby, nemohu pro něj použít přímo jméno rozšíření a zanáším si tak „jmenný prostor“ pouze s jednou službou.
Ukázka:
class ConfigExtension extends Nette\Config\CompilerExtension
{
public function loadConfiguration()
{
$container = $this->getContainerBuilder();
$container->addDefinition($this->name)
->setClass('Foo\Bar')
->setFactory(__CLASS__ . '::createBar');
}
/**
* @return Foo\Bar
*/
public static function createBar()
{
return new Foo\Bar;
}
}
- Filip Procházka
- Moderator | 4668
To je ale tvoje mínus, že. Pokud máš jen jednu službu, dej ji do configu ;)
- David Grudl
- Nette Core | 8228
Mám takovou představu, že každá služba by existovala ve vlastním „namespace“, který představuje název rozšíření. Z důvodů historickým jsou služby Nette bez prefixu, ale nové služby už taky prefixuju.