Как мне прочитать из parameters.yml в контроллере в symfony2?


146

Я поместил несколько пользовательских переменных в мой app / config / parameters.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()метод в контроллере будет загружать службу ( документ )

В Symfony 2.7 и более новых версиях для получения параметра в контроллере вы можете использовать следующее:

$this->getParameter('api_user');

3
Обратите внимание, что getметод в контроллере также использует контейнер, но он может получать сервисы только из контейнера, а не из параметров. Вам нужно getParameterполучить параметры.
Wouter J

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

1
@ Бор извините, другая версия 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"
    }
}

Мгновенное обновление готово!

Если вы используете более старый подход, вы можете автоматизировать его с помощью Rector .

Читать далее

Это называется инжекцией конструктора через поиск сервисов .

Чтобы узнать больше об этом, прочитайте мой пост Как получить параметр в Symfony Controller Чистым способом .

(Он протестирован, и я обновляю его для новой основной версии Symfony (5, 6 ...)).


Новый минималистичный подход к этой теме: tomasvotruba.cz/blog/2018/11/05/…
Томаш Вотруба

10

Я отправляю вам пример с swiftmailer:

parameters.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
Передача целых параметров мешка аналогична прохождению целого контейнера. Это имеет смысл только в том случае, если «какой-то конкретной службе требуется много параметров контейнера» (цитата из поста)
Томаш Вотруба

Итак, вы имеете в виду передачу всего параметра причиной проблемы в производительности?
Газалех Джавахери

Это одна из причин, но в основном для удобства чтения. Если я увижу имя параметра, $meetupApiKeyя знаю, что ожидать немного лучше, чем в$parameterBag
Томаш Вотруба


0

В Symfony 4.3.1 я использую это:

services.yaml

HTTP_USERNAME: 'admin'
HTTP_PASSWORD: 'password123'

FrontController.php

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

Не работает в 4.8. Вы уверены, что когда-нибудь это сработало?
Рикардо Мартинс

Я действительно забыл об этом, но да, вероятно, это сработало, потому что я публикую только проверенные материалы!
Achraf JEDAY

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.