Manual Wiring Arguments for Service depending on route

Hello everyone and thank you for your time reading that.
I have two different routes, which are described via ConfigProvider, and two middlewares inside:

  1. Auth
  2. Handler

The behavior for both of them should be exactly the same but saved for different databases. So I’m going to create Handler via Factory and provide inside my service via $continer->get(Service). That Service contains dependency, let’s call it Repository. How can I determine that Repo instance for two different routes? For Symony I’d use ‘Manual Wiring Arguments’ and provide it. I’d tried to do the same with Mezzio but useless spent a few hours without any result. I really need your advice.
Thank you for any reply

'dependencies' => [
    'services' => [
        'routes' => [
                'path' => '/api/first-route',
                'middleware' => [
                'methods' => [Request::METHOD_POST],
                'path' => '/api/second-route',
                'middleware' => [
                'methods' => [Request::METHOD_POST],

I guess that I have to determine FirstService and SecondService somewhere. I guess it should be inside factories with InvokableFactory::class. Both services accept Importer as dependency. Which called via $container->get(Importer). And Importer has Repository as a dependency

Currently I solved that with

'FirstService' => MyServiceFactory::class,
'SecondService' => MyServiceFactory::class

Inside MyServiceFactory I have $requestedName parameter on __invoke method. So it helps to determine original route where Service was called and build some logic. But for my point of view it looks ugly

I’ve only one question here for you and that is how did you achieved passing an Importer object via Invokeable factory? Thanks!

If it was via InvokableFactory then it can only be done using the options array as far as I know.

Hi @Tyrsson, that is what I wanted to ask how he did it via InvokeableFactory. As I’m not familiar with the usage of $container->get(‘servicename’) usage within InvokeableFactory. So, how he or anyone can achieve it via options? Thanks!

I think there has been some confusion in this thread and I do not think we have full examples of his code. In the next response the OP mentions this:

InvokableFactory is marked as final so it can not be extended. You never work within a InvokableFactory since you can only map a service to it. You can only pass it options when calling the $containers build method as far as I am aware. So, it seems as if that code would have to be somewhere else. I am guessing it’s in the referenced MyServiceFactory.

With that said the only way to get Importer into an instance using InvokableFactory would be something like:

$container->build(SomeService::class, $options[Importer::class => $container->get(Importer::class)]);

Given that SomeService is mapped to InvokableFactory.

Welcome to the forum :slight_smile:

I’m not sure where your problem lies. With the way you have the routes setup FirstService will only run for that route ie ‘/api/first-route’, which means that first the AuthMiddleware will execute then pass through to FirstService, which I understand to be your Handler for that route? Is that correct?

If that is indeed the case then you could just provide factories for your handlers and inject the required dependencies. In FirstServiceFactory just call the required Repository from the container and inject it into the FirstService Handler.

Here wa some question how I achieved that, but I still not sure that it’s a right way.
My ConfigProvider has mapping into my factory, as I said above:

FirstService => MyAwesomeFactory::class,
SecondService => MyAwesomeFactory::class,

Inside that Factory you should implement Laminas\ServiceManager\Factory\FactoryInterface __invoke. As first parameter would be a container, $requestedName for second one (FirstService or SecondService as a FQN) and options for the third.
As @Tyrsson said you can use options to pass something into next factory or service and do the same ‘magic’ there.

As I said it looks like wrong solution for obvious problem. build method doesn’t using caching so it means it’d be called each time

Couple things.

  • I would suggest using FQCN as service identifiers ie FirstServiceHandler::class
  • If you provide a factory for each service then you can pass just the repository that is required for that service to do its work instead of needing to pass the “Importer”. Maybe Importer is required for other reasons? If its solely to react to which route and bring in your Repository then I would say its better to just provide each their own factory.

Another option here would be to provide a common delegator for First and Second service that would inject the correct respository service based on which handler is being delegated. Since each handler is routed and not piped then they will only run for that route insuring that based on route you have the correct repository injected.