Jump to content

Passing additional parameters to closure in the container


NotionCommotion

Recommended Posts

Slim automatically passes the container to closure defined in the container.  How can an additional parameter be passed such as my someOtherService() example?  Thanks

<?php
require '../vendor/autoload.php';

use \Psr\Http\Message\ServerRequestInterface as Request;
use \Psr\Http\Message\ResponseInterface as Response;

$app = new \Slim\App(/* as applicable */);

$c = $app->getContainer();

$c['someService'] = function ($c) {
    return 'someService';
};

$c['someOtherService'] = function ($c, $id) {
    return 'someOtherService';
};


$app->get('/endpoint/{id:[0-9]+}', function (Request $request, Response $response, $args) use ($c) {
    //The following will all pass the container to someService and I believe are all identical ways to perform the same thing
    $someService1=$c['someService'];
    $someService2=$c->get('someService');
    $someService3=$this->someService;

    //The following will not work since only the container is first passed to someOtherService()
    $someOtherService1=$c['someOtherService']($c, $args['id']);
    $someOtherService2=$c->get('someOtherService')($c, $args['id']);
    $someOtherService3=$this->someOtherService($c, $args['id']);
});

 

Link to comment
Share on other sites

Pimple (the container) only supports a single parameter, so either you make the value not be callable (so not a function or __invoke-able object) or you wrap the function in another function.

If $id is required for the someOtherService factory, then what you need is a factory "factory" - the second one in quotes because really the container is about lazy loading, not about actually being a factory.

$c['someOtherServiceFactory'] = function ($c) {
	return function ($id) use ($c) {
		return 'someOtherService';
	};
};

The outer function gets evaluated the first time you use someOtherServiceFactory, and the value you get from the container is the inner function.

$someOtherService1 = $c['someOtherServiceFactory']($args['id']);

 

The container does have a raw() method that gives you the original value - your function($c,$id) - but I wouldn't use it because then you're completely ignoring the container's main lazy loading feature. You'd be using the container normally elsewhere, but not here where you can't use it normally and have to go through raw().

Link to comment
Share on other sites

14 hours ago, requinix said:

If $id is required for the someOtherService factory, then what you need is a factory "factory" - the second one in quotes because really the container is about lazy loading, not about actually being a factory.


$c['someOtherServiceFactory'] = function ($c) {
	return function ($id) use ($c) {
		return 'someOtherService';
	};
};

 

Thanks requinix,  Your example of wrapping in a second function makes sense and so does your statement regarding lazy loading versus being a factory as well as your recommendation not to use raw().

Not sure, however, about having "the second one in quotes".  Just to confirm, the script you posted afterwards pertains to wrapping in a second function and not about factory "factory", correct?  Please elaborate on this part.

Thanks

Link to comment
Share on other sites

It kinda contradicts what I said about lazy loading. The thought was "if a Pimple container acts as a factory" (which it kinda does) "then this would be a factory factory". As in you're using Pimple's own factory/lazy-loading mechanism to create a factory instead of some normal resource.

$container["foo"] = function() { // this is a factory that only fires once
	return "foo"; // the product of the factory
};

echo $container["foo"]; // invoke factory, get product, discard factory

$container["bar"] = function() { // factory
	return function() { // product of the factory is itself a factory
		return "bar"; // product of the second factory
	};
};

echo $container["bar"] // invoke outer factory, get inner factory, discard outer factory
	(); // ...invoke inner factory, get product

 

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.