Nette-dotenv implementace a konfigurace

BaruCepa
Člen | 33
+
0
-

Zdravím, snažíme se naimplementovat do Nette projektu nette-dotenv pro ostrou produkci, do .env chceme ukládat data pro připojení na db. Přes composer jsem nette-dotenv natáhla a dle dokumentace na GitHubu nachystala úpravu v config.neon, ale aplikace padá na tuto chybu:

Nette\DI\ServiceCreationException

Service 'env' (type of wodCZ\NetteDotenv\EnvAccessor): Parameter $directory in EnvAccessor::__construct() has no class type or default value, so its value must be specified.
File: /srv/vendor/nette/di/src/DI/Resolver.php:676

config.neon úpravy vypadají takto:

parameters:
    db_host: @env::get('DB_HOST')
    db_port: @env::get('DB_PORT')
    db_user: @env::get('DB_USER')
    db_password: @env::get('DB_PASSWORD')
    db_name: @env::get('DB_NAME')
    db_schema: project

extensions:
    env: wodCZ\NetteDotenv\DotEnvExtension

env:
    directory: "%appDir%/../../"
    fileName: ".env"
    overload: false
    localOnly: false
    prefix: false
    class: \wodCZ\NetteDotenv\EnvAccessor

Už nevím, kde hledat chybu.

Marek Bartoš
Nette Blogger | 1261
+
0
-

Rádi si přiděláváte práci?
Ten symfony/dotenv co jsem ti doporučoval na slacku jsou dva řádky v bootstrapu. Mohli jste mít problém vyřešený během pěti minut.

BaruCepa
Člen | 33
+
0
-

@MarekBartoš To ne, ale symfony/dotenv máme v composer.lock v konfliktech a není úplně žádoucí teď začínat upgrade celé symfony/console. Tak jsme zkusili nette-dotenv a narazili.

Marek Bartoš
Nette Blogger | 1261
+
+1
-

vlucas/phpdotenv je skoro totéž

Jestli máte nějaký konflikt mezi symfony/dotenv a symfony/console, tak update console je obvykle velmi jednoduchý. Symfony málokdy dělá bc breaky

nightfish
Člen | 517
+
+1
-

@BaruCepa Balíček wodcz/nette-dotenv má poslední release v roce 2017, to opravdu nechcete použít.

Dobrá zpráva je, že když se vykašlete na DotEnvExtension a zaregistrujete jen službu EnvAccessor, tak to bude nejspíš fungovat:

services:
    env:
        type: \wodCZ\NetteDotenv\EnvAccessor
        arguments:
            directory: "%appDir%/../../"

Osobně bych si spíš do projektu zaintegroval vlucas/phpdotenv (nebo již zmíněné symfony/dotenv) v moderní verzi.

BaruCepa
Člen | 33
+
0
-

@nightfish @MarekBartoš Tak už jsme odinstalovali nette-dotenv, to byla fakt šlápota mimo. Natáhli jsme symfony/dotenv, verzi, se kterou náš symfony/console není v konfliktu. Akorát se snažím doladit konfiguraci, zatím jsem se zasekla na tomto erroru při spouštění migrací Nextras:

235:                    }
236:
237:                    break;
238:
239:                case $entity instanceof Reference:
240:                    $entity = [new Reference(ContainerBuilder::ThisContainer), Container::getMethodName($entity->getValue())];
241:                    break;
242:
243:                case is_array($entity):
244:                    if (!preg_match('#^\$?(\\\\?' . PhpHelpers::PHP_IDENT . ')+(\[\])?$#D', $entity[1])) {
245:                        throw new ServiceCreationException(sprintf(
246:                            "Expected function, method or property name, '%s' given.",
247:                            $entity[1]
248:                        ));
249:                    }
Nette\DI\ServiceCreationException: Service 'nextras.dbal.connection' (type of Nextras\Dbal\Connection): Expected function, method or property name, '%' given. (used in Connection::__construct()) in /srv/vendor/nette/di/src/DI/Resolver.php:245
Stack trace:
#0 /srv/vendor/nette/di/src/DI/Resolver.php(334): Nette\DI\Resolver->completeStatement(Object(Nette\DI\Definitions\Statement), false)
#1 [internal function]: Nette\DI\Resolver->Nette\DI\{closure}(Object(Nette\DI\Definitions\Statement), '...')
#2 /srv/vendor/nette/di/src/DI/Resolver.php(339): array_walk_recursive(Array, Object(Closure))
#3 /srv/vendor/nette/di/src/DI/Resolver.php(301): Nette\DI\Resolver->completeArguments(Array)
#4 /srv/vendor/nette/di/src/DI/Definitions/ServiceDefinition.php(180): Nette\DI\Resolver->completeStatement(Object(Nette\DI\Definitions\Statement))
#5 /srv/vendor/nette/di/src/DI/Resolver.php(172): Nette\DI\Definitions\ServiceDefinition->complete(Object(Nette\DI\Resolver))
#6 /srv/vendor/nette/di/src/DI/ContainerBuilder.php(339): Nette\DI\Resolver->completeDefinition(Object(Nette\DI\Definitions\ServiceDefinition))
#7 /srv/vendor/nette/di/src/DI/Compiler.php(275): Nette\DI\ContainerBuilder->complete()
#8 /srv/vendor/nette/di/src/DI/Compiler.php(212): Nette\DI\Compiler->processBeforeCompile()
#9 /srv/vendor/nette/di/src/DI/ContainerLoader.php(119): Nette\DI\Compiler->compile()
#10 /srv/vendor/nette/di/src/DI/ContainerLoader.php(80): Nette\DI\ContainerLoader->generate('...', Array)
#11 /srv/vendor/nette/di/src/DI/ContainerLoader.php(44): Nette\DI\ContainerLoader->loadFile('...', Array)
#12 /srv/vendor/nette/bootstrap/src/Bootstrap/Configurator.php(259): Nette\DI\ContainerLoader->load(Array, Array)
#13 /srv/vendor/nette/bootstrap/src/Bootstrap/Configurator.php(234): Nette\Bootstrap\Configurator->loadContainer()
#14 /srv/bin/console(9): Nette\Bootstrap\Configurator->createContainer()
#15 {main}

Předpokládám, že mám špatně odkazováno v config.neon:

parameters:
    db_host: %env(DB_HOST)%
    db_port: %env(DB_PORT)%
    db_user: %env(DB_USER)%
    db_password: %env(DB_PASSWORD)%
    db_name: %env(DB_NAME)%
    db_schema: project

nextras.dbal:
    driver: pgsql
    host: %db_host%
    username: %db_user%
    password: %db_password%
    database: %db_name%
    searchPath: %db_schema%
Marek Bartoš
Nette Blogger | 1261
+
+1
-

%env(DB_HOST)% bude spíš %env.DB_HOST%, ne?

BaruCepa
Člen | 33
+
0
-

@MarekBartoš To jsme tam měli původně, ale ani přes to to neprošlo, tato varianta vyhazovala při spouštění migrací tuto chybu:

109:                        }
110:                        $val = $fullExpand
111:                            ? self::expand($val, $params, $recursive + [$pathStr => 1])
112:                            : self::expandString($val, $params, $recursive + [$pathStr => 1], true);
113:                    }
114:                } elseif ($val instanceof DynamicParameter) {
115:                    $val = new DynamicParameter($val . '[' . var_export($key, true) . ']');
116:                } elseif ($val instanceof Statement) {
117:                    $val = new Statement('(?)[?]', [$val, $key]);
118:                } else {
119:                    throw new Nette\InvalidArgumentException(sprintf("Missing parameter '%s'.", $parameter));
120:                }
121:            }
122:            return $val;
123:        }
Nette\InvalidArgumentException: Missing parameter 'env.DB_HOST'. in /srv/vendor/nette/di/src/DI/Helpers.php:119
Stack trace:
#0 /srv/vendor/nette/di/src/DI/Helpers.php(79): Nette\DI\Helpers::expandParameter('...', Array, Array, false)
#1 /srv/vendor/nette/di/src/DI/Helpers.php(56): Nette\DI\Helpers::expandString('...', Array, Array)
#2 /srv/vendor/nette/di/src/DI/Helpers.php(39): Nette\DI\Helpers::expand('...', Array, Array)
#3 /srv/vendor/nette/di/src/DI/Extensions/ParametersExtension.php(48): Nette\DI\Helpers::expand(Array, Array, true)
#4 /srv/vendor/nette/di/src/DI/Compiler.php(224): Nette\DI\Extensions\ParametersExtension->loadConfiguration()
#5 /srv/vendor/nette/di/src/DI/Compiler.php(211): Nette\DI\Compiler->processExtensions()
#6 /srv/vendor/nette/di/src/DI/ContainerLoader.php(119): Nette\DI\Compiler->compile()
#7 /srv/vendor/nette/di/src/DI/ContainerLoader.php(80): Nette\DI\ContainerLoader->generate('...', Array)
#8 /srv/vendor/nette/di/src/DI/ContainerLoader.php(44): Nette\DI\ContainerLoader->loadFile('...', Array)
#9 /srv/vendor/nette/bootstrap/src/Bootstrap/Configurator.php(259): Nette\DI\ContainerLoader->load(Array, Array)
#10 /srv/vendor/nette/bootstrap/src/Bootstrap/Configurator.php(234): Nette\Bootstrap\Configurator->loadContainer()
#11 /srv/bin/console(9): Nette\Bootstrap\Configurator->createContainer()
#12 {main}

Na to konto jsem zkusila upravit právě na %env(DB_HOST)%, který by se zase měl zamlouvat symfony/dotenv, ale není typický pro nette. A migrace začaly padat na jinou chybu.

Marek Bartoš
Nette Blogger | 1261
+
+4
-

%env(DB_HOST)%, který by se zase měl zamlouvat symfony/dotenv

A na to jste přišli jak? Jediné, co dělá symfony/dotenv je, že to naplní proměnnou $_SERVER. Syntaxi v nette/di to nemá jak ovlivnit.

Do bootstrapu si přidáte tohle

use Symfony\Component\Dotenv\Dotenv;

$dotenv = new Dotenv();
$dotenv->load(__DIR__.'/.env');

Potom si ověříte, že se vám načítají všechny proměnné přes dump($_SERVER);
Do di je dostanete přes $configurator->addParameters(['env' => $_SERVER + getenv()]);
A v di se odkazujete přes %env.example%

Missing parameter ‚env.DB_HOST‘

Tak to vám v .env hodnota DB_HOST nejspíš chybí. Nebo se vám env nenačítá vůbec.

BaruCepa
Člen | 33
+
0
-

@MarekBartoš Sláva, tak už jsem to pochopila, já sice krásně doplnila do bootstrapu $dotenv, ale vyrušila jsem zase getenv(), že… Teď už všecko v pořádku, na lokále dobrý, na produkčním serveru zjistím za chvílu, ale věřím, že už to snad taky bude v pořádku. Moc děkuji za pomoc :)