Confused with the conception "$container" ---- solved!

I finally understood! no bother.

from the official tutorial Database and Models - tutorials - Laminas Docs

Besides, there are “Psr\Container\ContainerInterface” and “Interop\Container\ContainerInterface” also used as “$container”, I am confused among these.
I got to known “Psr\Container\ContainerInterface” and “Interop\Container\ContainerInterface” maybe the same.

I use “LazyControllerAbstractFactory::class” as a abstract_factories:

the error like:

However,

Should I use “Laminas\ServiceManager\ServiceManager” as “$container” in anywhere instead of using “Psr\Container\ContainerInterface”, I don’t remember where I got to learn “Psr\Container\ContainerInterface”, maybe also in offcial tutorial or from laminas’ source code.

Where to use “Psr\Container\ContainerInterface” and “Laminas\ServiceManager\ServiceManager”.
What’s the differences?

Main problem is still there: do not inject the service manager or any other dependency injection container in your classes!
So your IndexController and your BaseFuncModel are wrong here.

See also in the documentation:

However, we also maintain that service locator injection is an anti-pattern; dependencies should be injected directly into instances instead.

https://docs.laminas.dev/laminas-mvc/migration/to-v2-7/#servicelocatoraware-initializers

Ok, I am trying not to inject Container to my IndexController.

But I just encontered a problem.
I wanna to get a privatekey for a 3rd-part application which I centeral set in the global.php config file.

How I get the configed privatekey from IndexController’s constructor and then pass into some model method?

I use ‘LazyControllerAbstractFactory::class’ and without a factory for each of my Controllers.

I don’t want to write a factory for each Controller, I know this way can fulfil the above goal.

Which one? or none of them

If I won’t inject Container or ServiceManager to Controller’s construct function, as well I don’t want to write factory for each controller. I prefer " ‘LazyControllerAbstractFactory::class’". Is there any good way to retrive ‘config’?

Service with name "Laminas\Config\Config" could not be created. Reason: Could not resolve value for parameter "array" of type array in class Laminas\Config\Config (requested as Laminas\Config\Config)   
···

Check the documentation:

  • A parameter named $config typehinted as an array will receive the application “config” service (i.e., the merged configuration).

https://docs.laminas.dev/laminas-mvc/cookbook/automating-controller-factories/

Ok, got it! Thank you so much!

Have a nice weekend!!

@froschdesign

Hi!

I got a new problem I guess it belong to this topic

I can not figure out another way to reach the setService() method

Oh oh! What is $container? :wink:

echo get_class($container); // 'Laminas\ServiceManager\ServiceManager'

And the documentation says:

laminas-servicemanager: factory-driven dependency injection container

https://docs.laminas.dev/laminas-servicemanager/

so, inject $container or $servicemanager from AuthManagerFactory to AuthManager is totally ok? rule allow?

Like the above pictures?

No, this is also a wrong usage because your AuthManager should not modify the service manager. The AuthManager shouldn’t even know that a service manager exists!

You already have an authentication manager and this manager is also registered in the service manager of your application, so you can use: $authManager->getIdentity(); – there is no need to register another service.

no, it is not the same authManager as the one you thought.

I know there is an anthenticationService as a laminas component.
But this authManager just my handmake service.

Ordinary service class inject depency via ordinary factory. It is a normal class. not involved in any other component.

I just want to setService in the ordinary AuthManager.
How can I do that?

Don’t worry, I can see that AuthManager is a custom class.

So my suggestion still stands: create a method to fetch the identity from your AuthManager class.

If you need the identity in a view helper or elsewhere then create a factory and fetch your authentication manager:

class ExampleViewHelperFactory
{
    public function __invoke(Psr\Container\ContainerInterface $container)
    {
        return new ExampleViewHelper(
            $container->get(Application\Service\AuthManager::class)->getIdentity()
        );
    }
}

That is kinda the point: you shouldn’t do it.

The container is to be kept pretty much unchanged post-bootstrap.

At a conceptual level, you seem to want to “create a service only if Request contains X”: instead, can you perhaps make that service receive X as a runtime parameter?

1 Like

It affect the performance? I mean it will slow down the response speed of the web services?

Or it will make concurrent smaller?

I tried to print_r the var $container, it is very big. The point is that I should not pass a very big var in between the functions of my application?

What I am trying to solve is that:
I need to get the authorization via cookie, header[authentication line], or get param($_[‘GET’]), I do not need a normal login or logout logic in my application, this part jobs done by other subdomain.

I want to centeral controller the authentication and store it in a shared servie, maybe just a global shared var. And then I can fetch it from any where like controller plugin, view helper, etc.

If I don’t change the $container as you said. What I can think about is to do this logic at the action. Then I need to write many duplicate code in many actions.

Ok, I see, call the method whenever it needed, it is almost the same with global shared var.
Thank you so much!

Heya,

Sorry, it is indeed true that I told you what not to do, without telling you why it is like that :slight_smile:

jobsfan
June 8

It affect the performance? I mean it will slow down the response speed of the web services?

Or it will make concurrent smaller?

The reason you want to avoid having Container (or ServiceManager, or any similar service locator structure) in your services is that your service should:

  1. be as-stateless-as-possible: this means that the service does not mutate during runtime, so that multiple usages of it lead to reproducible results.

  2. be only aware of its direct dependencies: your AuthManager is only responsible for handling authentication, so it should not mess with other unrelated services, nor should it modify them

  3. the ServiceManager itself is also a service, and should stay immutable post-initialization

I tried to print_r the var $container, it is very big. The point is that I should not pass a very big var in between the functions of my application?

What I am trying to solve is that:
I need to get the authorization via cookie, header[authentication line], or get param($_[‘GET’]), I do not need a normal login or logout logic in my application, this part jobs done by other subdomain.

It sounds like your authorization service needs a Request object as input, so it can take the decision (using a header, the session cookie, or a query string parameter) to take runtime decisions.

I want to centeral controller the authentication and store it in a shared servie, maybe just a global shared var. And then I can fetch it from any where like controller plugin, view helper, etc.

The “authentication” being the current “context” an user is operating within, right? It should probably always be queried as:

$authentication = $this->authManager->contextFor($request);

// now operate with $authentication

Alternatively, if you are operating with a PSR-7/PSR-15 structure, you can have this done by a middleware that injects the authentication (see presentation @ https://ocramius.github.io/from-helpers-to-middleware/#/69 )


final class InitializeSession implements MiddlewareInterface
{
public function process(ServerRequestInterface $request, DelegateInterface $delegate) : ResponseInterface
{
return $delegate->process(
$request->withAttribute(
‘session’,
$this->loadSession($request)
)
);
}

private function loadSession(ServerRequestInterface $request) : array
{
    // ...
}

}


If I don’t change the $container as you said. What I can think about is to do this logic at the action. Then I need to write many duplicate code in many actions.


Yes, duplication is still preferable to hidden global state mutation though.

Marco Pivetta

http://twitter.com/Ocramius

http://ocramius.github.com/

Thank you! I will try to achieve stateless in my project. I need to change my mind. Before I am highly depend on global shared var.