Nette 3.0 nahrazení za loadDefinition

Barbarossa
Člen | 74
+
0
-

Ahoj,

existuje už někde návod jak migrovat na Nette DI 3.0? Nejsem v tom zběhlý, a tak s tím docela bojuju. Dneska to je loadDefinition, které je v 3.0 označené jako deprecated s pomocnou hláškou: loadDefinition() is deprecated.

mám tento kus kódu, který bych rád převedl, asi do loadDefinitions, ale nevím jak…

// převzato z  contributte/flysystem
$processor = $builder->addDefinition($adapterName)
	->setAutowired(false);

Compiler::loadDefinition($processor, $args['adapter']);  //$args['adapter'] je Statement (DI)

Díky za pomoc.

David Grudl
Nette Core | 8227
+
0
-

Návod, jak migrovat, zatím není, protože ještě nevyšla ostrá verze a některé věci se mohou měnit.

Co přesně potřebuješ zmigrovat?

Barbarossa
Člen | 74
+
0
-

Aha díky, nevšiml jsem si že DI je beta (zatímco většina je RC). Zkouším balíky z Contributte (na Nette 3) a už je mi jasné proč se nikdo nehrne do aktualizování repozitářů…

Můj názor je takový, že nikdo jiný zřejmě to DI lépe nenapíše, a pokud jsi přesvědčený, že to máš napsané dobře a má to budoucnost tak se hold vývojáři rozšíření musí přizpůsobit… nebo nevím kolik návrhů na zlepšení denně od nich dostáváš.

Mě by zatím zajímal ten přepis toho výše uvedeného kódu, je to nějak takhle?
Celý 2.4 kod je zde

$processor = $builder->addDefinition($adapterName)
	->setAutowired(false);

$this->compiler->loadDefinitions([$args['adapter']], $adapterName);

Editoval Barbarossa (3. 2. 2019 15:39)

David Grudl
Nette Core | 8227
+
+1
-

Rozumím o co jde, najdu nějaký způsob, jak to řešit.

David Grudl
Nette Core | 8227
+
+1
-

Statické metody Compiler::loadDefinition() a loadDefinitions() nahradily nestatické Compiler::loadDefinitionsFromConfig(array $config) a CompilerExtension::loadDefinitionsFromConfig(array $config), kde $config je pole definic služeb (vlastně obsah sekce services:).

Rozdíl mezi metodou ze třídy Compiler a CompilerExtensions je ten, že ta v CompilerExtension prefixuje názvy tříd názvem extension.

Takže v uvedeném kódu contributte/flysystem by se použilo

$this->compiler->loadDefinitionsFromConfig([$adapterName => $args['adapter']]);

Je tam $this->compiler, protože $adapterName už je prefixovaný.

edit: loadDefinitionsFromConfig

Croc
Člen | 270
+
0
-

Zdravím, mám obdobný problém. Mám aplikaci, která se částečně skládá z interních extensions.

Aktuálně mám DI takto:

private $defaults = [

    ];

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

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

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

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

Koukal jsem do dokumentace, ale vůbec netuším jak to přepsat aby to jelo na Nette 3.

Moc děkuju

Marek Bartoš
Nette Blogger | 1274
+
+2
-

@Croc Však už to David napsal – $this->compiler->loadDefinitionsFromConfig($config['services'])

Croc
Člen | 270
+
0
-

Díky za odpověď. Spíš se mi jedná o config a parametry:

hlavní /app/config/config.neon:

agenda:
    agendaFilesDir: 'agenda_files'

extension config /libs/agenda/src/di/agenda.neon:

services:
    - Agenda\Model\FileModel(%agendaFilesDir%)
	/**
 * @return Nette\Schema\Schema
 */
public function getConfigSchema(): Nette\Schema\Schema
{
    return Expect::structure([
         'migration' => Expect::array()->dynamic(),
         'iv' => Expect::string('xxxxxxx')->dynamic(),
     ])->castTo('array');
}

	public function loadConfiguration()
{
    $config = $this->loadFromFile(__DIR__ . '/agenda.neon');
    $this->compiler->loadDefinitionsFromConfig($config['services']);

		// půvondí část pro nette 2.4
		// $this->config - pole defaultních parametrů (nyní přepsáno do getConfigSchema)

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

		// Nette\DI\Compiler::loadDefinitions(
    //     $this->getContainerBuilder(),
    //     $config['services'],
    //     $this->name
    // );
}

Ve službě v extension agenda potřebuju parametr z hlavního configu.

Moc děkuju za pomoc

Editoval Croc (6. 6. 2019 13:05)

MajklNajt
Člen | 498
+
0
-

keď si upravíš v config.neon:

parameters:
    agendaFilesDir: 'agenda_files'

potom môžeš v použiť v agenda.neon:

services:
    - Agenda\Model\FileModel(%agendaFilesDir%)
Croc
Člen | 270
+
0
-

Děkuji za odpověd.

Takto to právě nechci, aby se to ztratilo v ostatních parametrech, které s extension nesouvisí (takto jsem to měl na začátku).

Když konfiguruješ jakoukoliv extension, tak to je taky tak, název extension a pak parametry.

Koukal jsem do kódu nějakých extension pro Nette 3, ale mám v tom dost hokej a netuším jak to napsat. V dokumentaci také nic…

MajklNajt
Člen | 498
+
0
-

v tom prípade to v config.neon urob tak, ako si písal:

agenda:
    agendaFilesDir: 'agenda_files'

a vytiahni si ho cez:

public function getConfigSchema(): Nette\Schema\Schema
{
	return Expect::structure([
		'agendaFilesDir' => Expect::string(),
		'migration' => Expect::array()->dynamic(),
		'iv' => Expect::string('xxxxxxx')->dynamic()
	])->castTo('array');
}
Croc
Člen | 270
+
0
-

To bohužel vůbec nepomohlo. Stále stejná chyba:

Nette\InvalidArgumentException
Missing parameter 'agendaFilesDir'.

EDIT: Zdá se že toto funguje (nicméně validateConfig je deprecated):

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

    $config = $this->loadFromFile(__DIR__ . '/agenda.neon');
    $config = Helpers::expand($config, $this->validateConfig($this->config));
    $this->compiler->loadDefinitionsFromConfig($config['services']);
}

Editoval Croc (6. 6. 2019 16:40)

MajklNajt
Člen | 498
+
0
-

malo by to fungovať tak, ako som napísal – máš tú extension zaregistorvanú pod menom agenda?

MajklNajt
Člen | 498
+
0
-

sorry, až teraz som si všimol, že ty sa snažíš ten parameter dostať do servisy, takže máš 2 možnosti:

  1. zaregistrovať servisu do kontajneru ručne v CompilerExtension, kde jej ten parameter predáš z cez $this->config->agendaFilesDir

2) malo byť fungovať dať pred názov parametru prefix extension, ktorý sa nahradí kľúčom, pod ktorým registruješ rozšírenie:

services:
    - Agenda\Model\FileModel(extension.agendaFilesDir)

EDIT: tak to druhé riešenie funguje iba so službami – @extension.serviceName

Editoval MajklNajt (6. 6. 2019 20:11)

Croc
Člen | 270
+
0
-

Díky moc za nasměrování, nakonec se mi to asi povedlo:

/**
 * Class AgendaExtension
 * @package Agenda\DI
 */
class AgendaExtension extends CompilerExtension
{

    /**
     * @return Schema
     */
    public function getConfigSchema(): Schema
    {
        return Expect::structure([
             'agendaFilesDir' => Expect::string()->dynamic(),
         ])->castTo('array');
    }

    /**
     *
     */
    public function loadConfiguration()
    {
        $config = $this->loadFromFile(__DIR__ . '/agenda.neon');
        $this->compiler->loadDefinitionsFromConfig($config['services']);

        $builder = $this->getContainerBuilder();

        $builder->addDefinition(null)
                ->setFactory(
                    FileModel::class,
                    [
                        'agendaFilesDir' => $this->config['agendaFilesDir'],
                    ]
                );
    }
}

Díky!!!

Ivorius
Nette Blogger | 119
+
0
-

@Mabar mi doporučil ještě jedno možné řešení – trošku jsem si to poupravil, ale třeba se to bude hodit i někomu dalšímu.

	public function loadConfiguration()
	{
		$builder = $this->getContainerBuilder();
		$realParameters = $builder->parameters;
		$builder->parameters = Arrays::mergeTree((array) $this->config, $realParameters);

		$extensionNeon = $this->loadFromFile('./something.neon');
		$services = $extensionNeon['services'];
		$this->loadDefinitionsFromConfig($services);

		$builder->parameters = $realParameters;
	}