$container->getService(‚service_name‘) funguje, ale @inject ne
- svezij
- Člen | 69
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)
- svezij
- Člen | 69
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
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
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
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
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
Ř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.