$container->getService(‚service_name‘) funguje, ale @inject ne

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

Ahojte, myslím, že jsem problém popsal již jednou krátkou větou v nadpise :-). Službu potřebuji definovat programově, tzn. že jsem ji definoval v bootstrap.php:

<?php
	require __DIR__ . '/path/to/autoload.php';

	$configurator = new Nette\Configurator();

	$configurator->enableDebugger(__DIR__ . '/../log');
	$configurator->setTempDirectory(__DIR__ . '/../temp');

	$configurator->createRobotLoader()
				 ->addDirectory(__DIR__)
				 ->register();

	$environment = ((Nette\Configurator::detectDebugMode('IP.ADD.RES.S')) ? 'development' : 'production');
	$configurator->addConfig(__DIR__ . '/config/config.neon', $environment);

	$container = $configurator->createContainer();

  	// prida sluzbu
  	$container->addService('hello_world', new \helloWorld\HelloWorld());

	return $container;
?>

Když pak kdekoliv v aplikaci zavolám $container->getService('hello_world'), tak funguje správně, ale když napíšu v presenteru:

<?php
  class HelloWorldPresenter extends Presenter
  {
    /** @var \helloWorld\HelloWorld @inject */
    public $helloWorld;
  }
?>

tak dostanu hlášku:

Service of type helloWorld\HelloWorld used in @var annotation at presenters\HelloWorldPresenter::$helloWorld not found. Did you register it in configuration file?

Co dělám špatně? Díky, mějte se.

Editoval svezij (21. 6. 2016 9:33)

Felix
Nette Core | 1247
+
+1
-

Jses si na 100% jisty, ze ten namespace je spravne?

Protoze getService ti vraci sluzbu podle nazvu, ktery si zaregistroval. Takze ta sluzba tam je.

Potom me napada, nemas tam nekde inject: false?

:)

Editoval Felix (21. 6. 2016 9:09)

svezij
Člen | 69
+
0
-

Děkuji za odpověď, určitě, jsem si jistý, že NS je ok – navíc mi je generuje PhpStorm, nicméně jsem to ověřil a opravdu sedí. inject: false nemám, ale abych pravdu řekl, já používám Kdyby\Autowired, takže můj kód vypadá takto:

<?php
  class HelloWorldPresenter extends Presenter
  {
    /** @var \helloWorld\HelloWorld @autowire */
    protected $helloWorld;
  }
?>

a hláška, kterou dostávám je:

Service of type "helloWorld\HelloWorld" not found for presenters\HelloWorldPresenter::$helloWorld in annotation @var.

ale to by neměl být rozdíl. Nicméně, „autowajrování“ služeb mi funguje u mnoha jiných, takže tu by problém být neměl. Jediné, co mě napadá, jestli by nemohl být problém v tom, že HelloWorld je rozšíření, takže je uvedeno v config.neon v sekci extensions, konkrétně:

extensions:
    events: Kdyby\Events\DI\EventsExtension
    translation: Kdyby\Translation\DI\TranslationExtension
    autowired: Kdyby\Autowired\DI\AutowiredExtension
    menu: DK\Menu\DI\Extension
    dbal: Nextras\Dbal\Bridges\NetteDI\DbalExtension
    orm: Nextras\Orm\Bridges\NetteDI\OrmExtension
    hello_world: helloWorld\HelloWorld

a pak vytvářím službu se stejným jménem, ale to jsem myslel, že také není problém, to přeci nejsou nějaké kolidující entity, ne? A jen se ujistím, zda předpokládám správně, když předpokládám, že jde-li získat službu pomocí metody Container::getService(string $name), pak by měla jít získat i přes inject, je tak? Nevím, jak to funguje uvnitř, ale jak jsem se snažil vysvětlit kolegovi, myslím, že by dokonce inject mohl využívat právě getService(), ne?

Ještě jednou dík.

Editoval svezij (21. 6. 2016 9:40)

David Matějka
Moderator | 6445
+
0
-

Takze ty mas HelloWorld rozsireni? jak vypada? jake sluzby v nem registrujes? jako rozsireni se injectovat nenechaji. A je to i spatny napad.

svezij
Člen | 69
+
0
-

Aha, tak tady je problém, má neznalost. Nj, učím se. Vysvětlím důvod a budu rád, když mi poradíš, proč je to špatně, a zkusíš nakopnout, aby to bylo správně. Poprvé v životě se snažím programovat modulární systém, je to velmi komplikované a nechci to moc rozvádět, protože mám v návrhu spoustu chyb a moc rád bych si načetl více informací a postupně se jich zbavoval a nakonec udělal systém správným, nicméně nás bohužel tlačí čas ze strany nadřízeného a klienta.

Zkrátka jsem systém „rozsekal“ na menší části a každá z nich je potomkem CompilerExtension (ve skutečnosti je potomkem MyExtension, která je potomkem CompilerExtension kvůli abstraktním metodám a nějakému společnému vnitřnímu stavu – např. má přístup ke službě observeru). Každá ta část je „samostatnou jednotkou“, a tudíž se sama např. umí nainstalovat (musí implementovat metodu install()). Na konci instalace pošle zprávu, že se úspěšně nainstalovala, odchytí si ji systém a zapíše do databáze ke sloupci installed hodnotu TRUE.

Potřebuji tedy zajistit jakousi dynamickou registraci nainstalovaných extension a také potřebuji služby, které mi zpřístupní doposud nenainstalovaná rozšíření, abych si je přes DI mohl kdykoliv vzít a zavolat na ně metodu install().

Snad je to pochopitelné, i když možná nelogické. Máme zkrátka časový press a hlavně jsem, když jsme systém plánovali, nenašel žádnou literaturu, která by mě navedla, jak vytvářet modulární systém, na co si dát pozor, do jaké míry co separovat, co ještě patří do jádra systému a co už by měla být samostatná rozšíření. Nevíš náhodou o nějaké takové literatuře? Mám příliš mnoho otázek a příliš málo času a hlavně jsem opravdu nenarazil na žádnou rozumnou literaturu (angličtina nevadí).

Díky.

Edit: odpovědi na otázky
@DavidMatějka
Promiň, neodpověděl jsem na tvé dotazy. Rozšíření nedělá zatím nic. Pouze se na tom učím rozšíření používat a snažím se jej hned od začátku „napojit“ na celý systém – aby bylo v přehledu rozšíření vidět, zda je nainstalované, v jaké verzi, atd. Celý kód je tu:

<?php
  namespace extensions\helloWorld;

  use core\Extension;
  use Tracy\Debugger;

  /**
   * První rozšíření systému.
   */
  class HelloWorld extends Extension
  {
    protected $defaults = [
      'whatever' => 'Vychozi hodnota whatever parametru rozsireni'
    ];

    public function loadConfiguration() {
      $this->compiler->parseServices(
        $this->getContainerBuilder(),
        $this->loadFromFile(__DIR__ . '/config.neon'),
        $this->name
      );
    }

    /**
     * @inheritdoc
     */
    public function install(): bool {
      return FALSE;
      $installer = new Installer($this);
      return $installer->install();
    }

    /**
     * @inheritdoc
     */
    public function uninstall(): bool {
      $installer = new Installer($this);
      return $installer->uninstall();
    }
  }
?>

config.neon je zatím úplně prázdný, služby tedy zatím neregistruji žádné. Rodič core\Extension má pouze metodu init, do které se vkládá Kdyby\Events\EventManager $observer observer systému a Nextras\Dbal\Connection $connection připojení k databázi, což se mi vůbec nelíbí, raději bych to měl přímo v konstruktoru, ale nefungovalo to, takže jsem to dal do init – nicméně pak jsem změnil přístup a teď už by to přímo v konstruktoru fungovalo ⇒ změním to zpět.

Editoval svezij (21. 6. 2016 10:19)

David Matějka
Moderator | 6445
+
0
-

Problem je v tom, ze se vubec snazis udelat nejaky takovyhle univerzalni, automaticky system instalace :) Prece nechces psat dalsi wordpress? Tohle ma vyznam, kdyz ocekavas nejakou spravu toho systemu BFU. Tobe, jako programatorovi to (krome implementace samotne automaticke instalace) prinese i ruzny problemy s composerem, cache…

Mnohem snazsi pro tebe bude, ze to extension proste jen registruje svoje sluzby atd. A ty, kdyz extension budes potrebovat, tak ho nainstalujes pres composer, registrujes v configu, nastavis..

svezij
Člen | 69
+
0
-

Nj, ale to je právě ono, ta rozšíření budou spravovat BFU. Ve skutečnosti je našim zadáním udělat další „wordpress“, jen je hodně specifický, zaměřený na e-shopy atd. Nicméně tomu se ale nevyhneme. Já zadání neovlivním, takže i kdyby bylo hloupé, nic s tím nenadělám. Opravdu přesně to děláme. Ze začátku to budeme spravovat jen my, ale během příštího roku se to musí udělat tak, aby si to mohl běžný uživatel spravovat alespoň částečně sám – dostane k dispozici určité moduly a buď si je nainstaluje nebo ne, buď si je updatuje nebo ne atd.

Jako… pro začátek bych to řešit nemusel, ale stejně k tomu dojdu. Nicméně, dotaz ohledně nějaké literatury „jak tvořit modulární systém“ bych chtěl připomenout. Nevíš/te náhodou o nějaké literatuře, která by mi při vývoji takového systému pomohla?

Edit:
Každopádně, teď bych mohl ušetřit čas, kdybych ten univerzální systém instalací nedělal, a vrátil se k němu, až bude potřeba. Díky za nápad. Tak dejme tomu, že už jsme vyřešili můj původní dotaz (na nový rok se k němu tady třeba vrátím). Co se týká té literatury, mám založit nové vlákno nebo to nechat tady? Moc rád bych si přečetl něco o tom, jak správně vytvářet takový systém. Navíc, je to pro mě stěžejní a mohlo by mi to ušetřit spoustu času a problémů.

Editoval svezij (21. 6. 2016 10:39)

akadlec
Člen | 1326
+
0
-

Řešíš to co já. Mám rozdělanou extension na jakýsi balíčkovač co se bude dát spravovat přes GUI. Klikem zapneš/vypneš extension, nainstaluješ či odinstaluješ…první verzi co jsem měl jsem zahodil neb byla mimo composer, teď to stavím nad composerem aby se daly hlídat závislosti apod. Snad to během týdne dvou už budu mít v publikovatelné verzi.

svezij
Člen | 69
+
0
-

Hmm… to zní dobře, a dáš to k dispozici na git? To by bylo super, jednak nebudu muset „objevovat Ameriku“ a jednak mi to ušetří dost času. Super :-)

akadlec
Člen | 1326
+
+1
-

jj mám to v plánu.