Odkaz na service z includovaného konfiguráku
- uestla
- Backer | 799
Dobrý večer.
Mám dotaz, je-li možné – případně jak – z includovaného konfiguráku přistoupit ke službě definované v konfiguráku nadřaženém?
#config.neon
common:
includes:
- include.neon
service:
myService: MyServiceService( ... )
#include.neon
parameters:
callback: [@myService, loadKey]
Předchozí ukázka bohužel při zavolání
$cb = $container->parameters['callback'];
callback($cb[0], $cb[1])->invoke();
zařve, že callback @myService::loadKey()
je nevolatelný –
čili @myService
se nepřeloží na instanci služby :-(
Předem děkuji.
- Filip Procházka
- Moderator | 4668
A proč bys to dělal? Nepiš mi, jak to potřebuješ udělat, napiš mi proč to potřebuješ udělat a já ti poradím, jak to udělat lépe.
- uestla
- Backer | 799
Tvořím dynamickou navigaci a některé položky je třeba načítat odjinud (z databáze, z jiného konfigu, …).
Základní strukturu menu tahám právě z includovaného configu:
# config.neon --------
common:
includes:
- menu.neon
# menu.neon --------
parameters:
menu:
':Homepage:default': 'Úvod'
':Homepage:contact?lang=cs': 'Kontakt'
':Homepage:contact?lang=en': 'Contact'
# a teď je tu např. potřeba pro hierarchizaci načíst položky odjinud
':Gallery:default':
title: 'Fotogalerie'
items: '...' # a zde by se mi hodil callback
# využívající služby kontejneru,
# který by natáhl dynamické položky
Při zpracovávání konfigu (iterací položek) si zjišťuji, zda
aktuální položka náhodou není pole (resp. ArrayHash
, na který
si to pro ušetření paměti přetypovávám) a neobsahuje 'items'
a když je to callback, tak ho volám pro načtení.
# metoda komponenty MenuControl
private function processItems($parent, ArrayHash $items)
{
foreach ($items as $dest => $item) {
if ($item instanceof ArrayHash) {
$item['parent'] = $parent;
$item['dest'] = $dest;
if (isset($item['items'])) {
$this->processItems($item, $item['items']);
}
} else {
$items[$dest] = ArrayHash::from(array(
'parent' => $parent,
'dest' => $dest,
'text' => $item,
));
}
}
}
Děkuji za ochotu.
EDIT: komentář v NEONu
Editoval uestla (9. 3. 2012 18:35)
- Filip Procházka
- Moderator | 4668
Především, celé tvé menu může být v samostatném souboru, tomu snad nic nebrání, ne?
':Homepage:default': 'Úvod'
':Homepage:contact?lang=cs': 'Kontakt'
':Homepage:contact?lang=en': 'Contact'
# a teď je tu např. potřeba pro hierarchizaci načíst položky odjinud
':Gallery:default':
title: 'Fotogalerie'
items: '...' # a zde by se mi hodil callback využívající služby kontejneru, který by natáhl dynamické položky
Můžeš ho načítat cca takto
$menuItems = Nette\Utils\Neon::decode(file_get_contents($file));
Asi by bylo dobré, si na to vytvořit nějaký pěkný interface
interface MenuItemsProvider
{
function getMenuItems();
}
Tohle interface si pak implementuješ ve své službě a už tam pak nastavíš pouze jméno služby
':Gallery:default':
title: 'Fotogalerie'
items: myCoolService
A trošku upravíš metodu na vytvoření menu
private function processItems($items, $parent = NULL)
{
foreach ($items as $dest => $item) {
if ($item instanceof ArrayHash) {
$item['parent'] = $parent;
$item['dest'] = $dest;
if (is_string($item['items'])) {
$provider = $this->container->getService($item['items']);
$item['items'] = $provider->getMenuItems();
}
if (isset($item['items'])) {
$this->processItems($item['items'], $item);
}
} else {
$items[$dest] = ArrayHash::from(array(
'parent' => $parent,
'dest' => $dest,
'text' => $item,
));
}
}
}
Příklad pracuje s Containerem, který tam musíš přidat. Pokud to chceš mít ale ještě čistější, tak si můžeš všem službám, které budou implementovat ten interface, přidat tag
services:
galleries:
class: Galleries(@db)
tags: {menuProvider: gallery}
Potom si je z containeru získáš (ideálně v compileru) a nastavíš je, aby se předávaly té komponentě na menu, do jednoho setteru
public function addProvider($name, $service)
{
$this->providers[$name] = $service;
}
Takto si nebudeš muset předávat celý container (čistější) a budeš tam mít rovnou služby, které budeš potřebovat.
Editoval HosipLan (9. 3. 2012 20:01)
- uestla
- Backer | 799
Děkuji moc za nástřel. Nakonec jsem na to šel trochu přímočařeji, tak se podělím:
https://gist.github.com/2008990
Ještě jednou díky.