0

I can't read a parameter from parameters.yml in my controller.

I want to do this:

//My Controller
class ExampleController extends Controller
{
    function someMethod($argument)
    {
        dump($this->getParameter('free_proxy'));die();

and in parameters.yml I got:

parameters:
    free_proxy: "http://xxx:8080"

I get an error: Call to a member function getParameter() on null

I've tested some solutions like adding some services and using get and stuff but nothing works.

EDIT: also, I tried this:

services:
    _defaults:
        autowire: true
        autoconfigure: true
        public: false
        bind:
          $freeProxy: '%free_proxy%'

Then using:

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

But I got an error: Unused binding "$freeProxy" in service...

pmiranda
  • 7,602
  • 14
  • 72
  • 155
  • Things have changed a bit with the introduction of autowire. [Read through here](https://symfony.com/blog/new-in-symfony-4-1-getting-container-parameters-as-a-service) for several recommended approaches. Or else consult the container docs to see how to inject the container into your controller. – Cerad Jan 02 '19 at 15:54
  • @Cerad I tried some solution like that. I don't get it, why so complicated. In Laravel is ENV.free_proxy and that's all. I've read different aproaches to to this for symonfy 3.4, for 3.3 and for above 2.8 (which is symfony 3.3 and 3.4 too) – pmiranda Jan 02 '19 at 16:19
  • Many things seem complicated the first time you work through them but after awhile they become routine. Just bind $freeProxy to your value and then all you need to do is to name a variable $freeProxy in your action method. From a bigger point of view, injecting the complete container has always been considered to be a bit of an anti-pattern which was tolerated because it made life much simpler. Sort of like a rich but obnoxious uncle. But the fairly new autowire functionality has made eliminating the container more practical. – Cerad Jan 02 '19 at 16:26
  • I might add that configuring and injecting services/parameters is one of the key cornerstones of Symfony. It's well worth taking the time to understand. – Cerad Jan 02 '19 at 16:28
  • I'll edit my answer with `services.yml` for more help, because it didn't work for me. – pmiranda Jan 02 '19 at 16:39
  • function someMethod($freeProxy) – Cerad Jan 02 '19 at 16:54
  • Yes, I had to set correctly the controller to use. It's giving me error for every controller in the bundle... argh. I don't understand, in SwiftMailer I can use without problems `$this->getParameter('free_proxy')` but not in other method – pmiranda Jan 02 '19 at 17:02
  • Possible duplicate of [How do I read from parameters.yml in a controller in symfony2?](https://stackoverflow.com/questions/13901256/how-do-i-read-from-parameters-yml-in-a-controller-in-symfony2) – Tomas Votruba Jan 02 '19 at 20:16
  • You need to use constructor. See answer to the same question: https://stackoverflow.com/a/48371606/1348344 I also summed it up [in a post](https://www.tomasvotruba.cz/blog/2018/01/22/how-to-get-parameter-in-symfony-controller-the-clean-way/#the-clean-way). – Tomas Votruba Jan 02 '19 at 20:16
  • I come from that thread, but it mixes a lot of different ways and versions, none works for my code, of course I'm doing something wrong there, that's why I made this answer, not just asking how to to something. – pmiranda Jan 02 '19 at 22:29

2 Answers2

2

So there are two mysteries here. First is why is the container not being injected which in turn causes getParameter to fail. And second, why does bind generate that unused binding error.

You did not show your routing but I suspect that somewhere along the line you actually have:

$exampleController = new ExampleController();

If so then this explains why getParameter is failing. You really need to let Symfony create the controller based on the route. Otherwise the container is not injected and other controller magic is skipped.

I installed a fresh 3.4 app with the old directory structure and added a parameter

composer create-project symfony/framework-standard-edition s34

# app/config/parameters.yml
parameters:
    free_proxy: "http://xxx:8080"

I then tweaked the default controller using the default route annotation:

class DefaultController extends Controller
{
    /**
     * @Route("/", name="homepage")
     */
    public function indexAction(Request $request)
    {
        $freeProxy = $this->getParameter('free_proxy');

        // replace this example code with whatever you need
        return $this->render('default/index.html.twig', [
            'base_dir' => realpath($this->getParameter('kernel.project_dir')).DIRECTORY_SEPARATOR.$freeProxy,
        ]);
    }
}

And everything worked as expected. The Symfony request handler takes care of injecting the container and thus gives you access to the parameters. If you cannot get this working then please update your question with your routing information.

I then took a look at the bind issue. You really want to inject these parameters instead of pulling them. I updated services.yml

# app/config/services.yml
services:
    bind:
        $freeProxy: '%free_proxy%'

And started getting those unused binding errors. It turns out that bind does not work for action injection. Not really sure why. I don't use it much but I really would have expected that just adding $freeProxy to your action method would work. In any event, here is a working example of the proper way to do things.

class ExampleController extends Controller
{
    private $freeProxy;

    public function __construct($freeProxy)
    {
        $this->freeProxy = $freeProxy;
    }
    /**
     * @Route("/example", name="example")
     */
    function someMethod()
    {
        dump($this->freeProxy);
        dump($this->getParameter('free_proxy'));die();
    }
}

I then went to a fresh 4.2 project and tried action injection:

class IndexController extends AbstractController
{
    public function index($freeProxy)
    {
        return new Response("Index $freeProxy");
    }
}

Action injection works as expected for 4.2 but not 3.4. Constructor injection works fine in either version.

Cerad
  • 48,157
  • 8
  • 90
  • 92
0

documentation show like this :

parameters.yml :
parameters:
    mailer.transport: sendmail

to set :

$container->setParameter('mailer.transport', 'sendmail');

to get :

$container->getParameter('mailer.transport');
hrust
  • 734
  • 1
  • 11
  • 34
Aym2ric
  • 31
  • 1
  • 1
  • 6
  • maybe you need to set before get and this can explain : " I get an error: Call to a member function getParameter() on null " – Aym2ric Jan 03 '19 at 13:05