Як я читаю з parametri.yml в контролері в symfony2?


146

Я помістив декілька спеціальних змінних у свій додаток / config / settings.yml.

parameters:
    api_pass: apipass
    api_user: apiuser

Мені потрібно отримати доступ до них з мого контролера, і я спробував їх отримати

$this->get('api_user');

з мого файлу контролера. Коли я намагаюся це, я отримую це повідомлення про помилку:

You have requested a non-existent service "api_user".

Який правильний спосіб це зробити?

Відповіді:


296

У Symfony 2.6 та старіших версіях , щоб отримати параметр у контролері - спочатку слід отримати контейнер, а потім - необхідний параметр.

$this->container->getParameter('api_user');

Цей розділ документації пояснює це.

Поки $this->get()метод в контролері завантажить службу ( doc )

У Symfony 2.7 та новіших версіях для отримання параметра в контролері ви можете скористатись такими:

$this->getParameter('api_user');

3
Зауважте, що getметод у контролері також використовує контейнер, але він може отримувати лише послуги з контейнера, а не параметри. Потрібно getParameterотримати параметри.
Wouter J

Коли я намагаюсь, $this->getContainer()->getParameter('api_user');я отримую фатальну помилку: зателефонуйте до не визначеного методу ..Longpath .. \ Controller :: getContainer ().
Бор

1
@Bohr вибачте, інша версія Symfony2. Я відредагував свою відповідь - перевіри її зараз;)
Віталій Зуріан

2
URL-адреса документації тепер є symfony.com/doc/2.7/components/dependency_injection/…
SilvioQ

Symfony 2.7 і новіші: ще $this->hasParameter()не працює.
Саман Мохамаді

23

Чистий шлях - 2018+, Symfony 3.4+

З 2017 року та Symfony 3.3 + 3.4 існує набагато більш чистий спосіб - простий в налаштуванні та використанні.

Замість того, щоб використовувати анти-шаблон контейнера та послуги / локатора параметрів, ви можете передати параметри класу за допомогою конструктора . Не хвилюйтесь, це не трудомістка робота, а швидше налаштування один раз і забудьте підхід.

Як налаштувати його в 2 кроки?

1. app/config/services.yml

# config.yml

# config.yml
parameters:
    api_pass: 'secret_password'
    api_user: 'my_name'

services:
    _defaults:
        autowire: true
        bind:
            $apiPass: '%api_pass%'
            $apiUser: '%api_user%'

    App\:
        resource: ..

2. Будь-який Controller

<?php declare(strict_types=1);

final class ApiController extends SymfonyController
{
    /**
     * @var string 
     */
    private $apiPass;

    /**
     * @var string
     */
    private $apiUser;

    public function __construct(string $apiPass, string $apiUser)
    {
        $this->apiPass = $apiPass;
        $this->apiUser = $apiUser;
    }

    public function registerAction(): void
    {
        var_dump($this->apiPass); // "secret_password"
        var_dump($this->apiUser); // "my_name"
    }
}

Моментальна оновлення готова!

Якщо ви використовуєте більш старий підхід, ви можете автоматизувати його за допомогою ректора .

Детальніше

Це називається введенням конструктора над підходом служб локатора .

Щоб прочитати більше про це, перевірте мій пост Як отримати параметр в контролері Symfony чистим шляхом .

(Це тестовано, і я постійно оновлюю його для нової основної версії Symfony (5, 6 ...)).


Новий мінімалістичний спосіб на цю тему: tomasvotruba.cz/blog/2018/11/05/…
Томаш Вотруба

10

Я надсилаю вам приклад із swiftmailer:

parametri.yml

recipients: [email1, email2, email3]

послуги:

your_service_name:
        class: your_namespace
        arguments: ["%recipients%"]

клас послуги:

protected $recipients;

public function __construct($recipients)
{
    $this->recipients = $recipients;
}

8

У Symfony 4 ви можете використовувати ParameterBagInterface:

use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;

class MessageGenerator
{
    private $params;

    public function __construct(ParameterBagInterface $params)
    {
        $this->params = $params;
    }

    public function someMethod()
    {
        $parameterValue = $this->params->get('parameter_name');
        // ...
    }
}

і в app/config/services.yaml:

parameters:
    locale: 'en'
    dir: '%kernel.project_dir%'

Він працює для мене і в класах контролерів, і у формах. Більш детально можна ознайомитись у блозі Symfony .


1
Передача пакета цілих параметрів - це як проходження цілого контейнера. Це має сенс лише у тому випадку, "якщо якійсь певній службі потрібно багато параметрів контейнера" ​​(цитується з поста)
Томаш Вотруба

Отже, ти маєш на увазі, що передача цілого параметра спричинить проблеми у продуктивності?
ghazaleh javaheri

Це одна з причин, але в основному для читабельності. Якщо я бачу ім'я параметра, $meetupApiKeyя знаю, чого очікувати трохи краще, ніж у$parameterBag
Томаш Вотруба


0

У Symfony 4.3.1 я використовую це:

послуги.ямл

HTTP_USERNAME: 'admin'
HTTP_PASSWORD: 'password123'

FrontController.php

$username = $this->container->getParameter('HTTP_USERNAME');
$password = $this->container->getParameter('HTTP_PASSWORD');

Не працює в 4.8. Ви впевнені, що це спрацювало колись?
Рікардо Мартінс

Я справді забув про це, але так, ймовірно, це спрацювало, оскільки я публікую лише перевірені речі!
Ахраф ІДЕЙ

1
Вибачте, Ахараф. Я не знаю, але не працював у своєму контролері. Всередині контролера ви можете зателефонувати getParameter безпосередньо, без DI. Тобто: $this->getParameter('foo'). Ось що я зробив для того, щоб він працював у SF 4.8.
Рікардо Мартінс

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.