I need to get request headers in a dependency of container. I’m using PHP-DI

Is it possible to get the request inside the container? I want to get the language of the user sent to each request. Picking up the controller and going over it with each call I found it a lot of work…

$container->set('language', function (// how get request here) {
    return new App\language\Language($request->getHeaderLine('Accept-Language'));
});

Tanks…

This is not recommended anymore because the request is context specific.
Instead you may try to use the request attributes like this:

$request = $request->withAttribute('my-key', 'my-value');

// 'my-value'
$value = $request->getAttribute('my-key');

If you want to set the language for a translator (for example), you may use a specific middleware to that fetches the language from the request and sets it into the translator. All this depends on your specific use case.

<?php namespace App\middlewares;

use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;

class LanguageMiddleware {

    public function __invoke(Request $request, RequestHandler $handler): Response {
        $language = $request->getHeaderLine('Accept-Language'); 

        $request = $request->withAttribute('language', $language);
        $response = $handler->handle($request);

        return $response;
    }
}

in controller

$language = $request->getAttribute('language')

I arrived and ate here. My middleware receives and detects the language. I create an attribute that can be retrieved in. controller. The problem is that I always need to pass it on to my service. I wanted to put the language inside the. container for me to receive directly in my service and use with annotations.

Ok the middleware looks fine. Without knowing more about your application, have you tried to change the language of your “translator” component there too? Then you may not need to pass the language everywhere and keep to focus more where it belongs to.

This example requires PHP-DI with Autowiring enabled (by default):

<?php

namespace App\middlewares;

use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
use Acme\Translator;

final class LanguageMiddleware implements MiddlewareInterface
{
    private Translator $translator;

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

    public function __invoke(Request $request, RequestHandler $handler): Response
    {
        $language = $request->getHeaderLine('Accept-Language'); 

        if ($language) {
            // pseudo example
            $this->translator->setLanguage($language);
        }

        return $handler->handle($request);
    }
}

Hello, tanks for you help!
I could not retrieve the “translator” in the service…

Don’t give up :D. If so, I’ll make the code available on github. It seems to be something simple… but I’m a few days into it.

<?php namespace App\middlewares;

use DI\Container;

class LanguageMiddleware {

    protected $container;

    public function __construct(Container $container){
        return $this->container = $container;
    }

    public function __invoke($request, $handler) {

        $this->container->set('language', function() use ($request){
            return new App\language\Language($request->getHeaderLine('Accept-Language'));
        });

        $response = $handler->handle($request);
        return $response;
    }
}

in my service

/**
* @Inject("language")
*/
private $language;

So it works well, I can pass the language in the constructor of the Language class and retrieve it later by Annotation in the service… not needing to go through the controller. Is this a good solution?