Konfigurace extension a parametry z config.neon

před rokem

Croc
Backer | 264
+
0
-

Zdravím,
mám takový problém ohledně konfigrace vlastní extension a jejích parametrů z config.neon. Procházel jsem dokumentaci i forum ale nejsem schopen to rozchodit…

config.neon

extensions:
    # Own extensions
    menu: Menu\DI\MenuExtension

menu:
    mobile_version: true

menu.neon

services:

    #services
    # Menu
    - Menu\MenuFactory
    - Menu\MenuModel
    - Menu\MenuRepository

    # Menu\Section
    - Menu\Section\SectionFactory

    # Menu\Item
    - Menu\Item\ItemFactory
    - Menu\Item\ItemModel
    - Menu\Item\ItemRepository

    # Menu\Link
    - Menu\Link\LinkFactory

    - Menu\MenuControl\IMenuControlFactory

MenuExtension.php

namespace Menu\DI;

use Menu\MenuControl\MenuControl;

class MenuExtension extends Nette\DI\CompilerExtension {

    public $defaults = [
        'mobile_version' => true,
    ];

    /**
     *
     */
    public function loadConfiguration() {

        $this->validateConfig($this->defaults);

        $builder = $this->getContainerBuilder();
        $builder->addDefinition($this->prefix('menu'))
            ->setFactory(MenuControl::class, [$this->config['mobile_version']])
            ->addSetup('mobile_version', [$this->config['mobile_version']]);

        $this->compiler->loadDefinitions(
            $builder,
            $this->loadFromFile(__DIR__ . '/menu.neon')['services'],
            $this->name
        );
    }
}

MenuControl.php

namespace Menu\MenuControl;

class MenuControl extends Control {
//.....
	public function __construct(bool $mobile_version = false, User $user, Translator $translator, MenuFactory $menuFactory, AppuserFactory $appuserFactory) {
        parent::__construct();
        $this->mobile_version = $mobile_version;
        $this->user = $user;
        $this->translator = $translator;
        $this->menuFactory = $menuFactory;
        $this->appuser = $appuserFactory->create($user->getIdentity());
        $this->menu = $this->menuFactory->create();
    }

//.....

}

/**
 * Interface IMenuControlFactory
 * @package Menu\MenuControl
 */
interface IMenuControlFactory {

    /**
     * @return MenuControl
     */
    public function create();
}

Výsledek je:

Nette\DI\ServiceCreationException
Class Menu\MenuControl\IMenuControl used in service 'menu.menu' not found.

Prosím o pomoc jak to rozchodit. Moc děkuju

EDIT-1: upraveno. Aplikace nepadá, ale hodnota proměnné $mobile_version je false. Takže to vezme default hodnotu z konstruktoru.

Editoval Croc (4. 9. 2018 10:49)

před rokem

David Matějka
Moderator | 5983
+
0
-

jaky mas namespace v tom MenuControl.php?

mimochodem, ten interface IMenuControl by mel obsahovat slovo factory, tedy treba IMenuControlFactory, jelikoz to neni rozhrani te komponenty, ale rozhrani tovarny na komponentu

před rokem

Croc
Backer | 264
+
0
-

Děkuju za zpětnou vazbu. Do prvního příspěvku jsem doplnil namespace, které používám a factory (děkuju za upozornění).
Nicméně stav se změnil, ale stále to nenačte ten parametr:
Aplikace nepadá, ale hodnota proměnné $mobile_version je false. Takže to vezme default hodnotu z konstruktoru.

Editoval Croc (4. 9. 2018 10:49)

před rokem

David Matějka
Moderator | 5983
+
0
-

ty totiz ten parametr nepredavas do komponenty vytvorene pres registrovanou - Menu\MenuControl\IMenuControlFactory, ale pridavas tam novou definici sluzby

$builder->addDefinition($this->prefix('menu'))
    ->setFactory(MenuControl::class, [$this->config['mobile_version']])
    ->addSetup('mobile_version', [$this->config['mobile_version']]);

tenhle blok kodu muzes cely smazat.

dalsi chybou je, ze kodem ` [$this->config[‚mobile_version‘]]` se neodkazes na hodnotu v configu, ale na tu definovanou property $this->config

jedna z moznosti, jak dostat parametr na sparvne misto je zmena nacitani toho configu:

		$config = $this->loadFromFile(__DIR__ . '/menu.neon');
		$config = \Nette\DI\Helpers::expand($config, $this->validateConfig($this->config));

		Compiler::loadDefinitions(
			$this->getContainerBuilder(),
			$config['services'],
			$this->name
		);

a v menu neon pak upravit definici sluzby s tovarnou na:

-
		implement: Menu\MenuControl\IMenuControlFactory
		arguments: [%mobile_version%]

před rokem

Croc
Backer | 264
+
0
-

Super moc děkuju, to je ono :) Ještě mám jeden dotaz. V jedné extension mám službu, která vyžaduje dva parametry.

-
    implement: Item\Model\FileModel
    arguments: [%itemFilesDir%, %wwwDir%]

%itemFilesDir% je definovaná v rámci extension, ale %wwwDir% je standardně dostupná v konfig neon bez definice. Problém je, že při této definici mi to hází chybu, že %wwwDir% neexistuje (což je pravda). Lze to vůbec?

Editoval Croc (4. 9. 2018 12:54)

před rokem

David Matějka
Moderator | 5983
+
0
-

myslim, ze k temhle parametrum se v extension dostanes pres $this->getContainerBuilder()->parameters, ale je lepsi, kdyz si wwwDir predas primo te extension, at neni zavisla na globalnim parametru

před rokem

Croc
Backer | 264
+
0
-

Můžu se prosím zeptat, jakým způsobem to mám předat té extension? Ideálně příklad. Díky moc.
Ohledně configurace jsem na tom špatně zatím…

Editoval Croc (4. 9. 2018 13:05)

před rokem

David Matějka
Moderator | 5983
+
0
-

jako jine parametry, v hlavnim configu:

menu:
	wwwDir: %wwwDir%

před rokem

Croc
Backer | 264
+
0
-

Jo takhle :) no to mě taky napadlo, ale myslel jsem že to jde i jinak :) Díky moc :)

před rokem

Croc
Backer | 264
+
0
-

Tak po konfiguraci všech vlastních extension a jejich parametrů v configu dostávám hlášku:

Nette\DI\ServiceCreationException
Interface Item\Model\FileModel used in service '131' not found.

item.neon

services:
    -
        implement: Item\Model\FileModel
        arguments: [%itemFilesDir%, %wwwDir%]

config.neon

extensions:
    # Own extensions
    item: Item\DI\ItemExtension

item:
    wwwDir: %wwwDir%
    itemFilesDir: 'item_files'

FileModel.php

namespace Item\Model;

class FileModel extends BaseModel {

    /**
     * @var string
     */
    protected $item_files_dir;

    /**
     * @var string
     */
    protected $www_dir;

    /**
     * @var FileRepository
     */
    protected $fileRepository;

    /**
     * FileModel constructor.
     * @param string $item_files_dir
     * @param string $www_dir
     * @param LookupService $lookupService
     * @param Translator $translator
     * @param LogService $logService
     * @param FileRepository $fileRepository
     */
    public function __construct(string $item_files_dir, string $www_dir, LookupService $lookupService, Translator $translator, LogService $logService, FileRepository $fileRepository) {
        parent::__construct($lookupService, $translator, $logService);
        $this->fileRepository = $fileRepository;
        $this->item_files_dir = $item_files_dir;
        $this->www_dir = $www_dir;
    }

	// metody třídy
}

Není to tím, že při této definici to chce interface jako u továrničky na komponentu?

EDIT: Je to tak, vlastně jsem si tím odpověděl. Takže pokud má služba interface definuje se jako si psal a pokud nemá, tak klasicky.

Editoval Croc (4. 9. 2018 14:33)

před rokem

David Matějka
Moderator | 5983
+
0
-

implement se pouziva u tovaren generovanych z interface, filemodel neni ten pripad, takze to zmen na:

services:
    -
        class: Item\Model\FileModel
        arguments: [%itemFilesDir%, %wwwDir%]

před rokem

Croc
Backer | 264
+
0
-

díky moc :)