2

I'm trying to create custom functions with parameters within my container but everything I do ends up failing. My current code is as folllows:

$container['myFunction'] = function($container) {
    return function($arg) {
        return $arg;
    };
};

// Called from a route:
echo $this->myFunction("test"); // Call to undefined method Slim\Container::myFunction()

Am I doing something wrong? From what I read online this should be the correct way to define a custom container functions with Slim 3. Any help would be great, thanks!

Joe Scotto
  • 10,936
  • 14
  • 66
  • 136

1 Answers1

2

You need to create an instance of the container service before you can use it.

$myFunc = $this->myFunction;
echo $myFunc('test');

Or on one line:

echo ($this->myFunction)('test');

Scriptonomy
  • 3,975
  • 1
  • 15
  • 23
  • That works but is there any way to bypass that? Little fuzzy on how the container works in slim. – Joe Scotto Oct 22 '17 at 23:39
  • @JoeScotto If you instantiate the container, then `echo $this->myFunction('test');` should work too. See [Pass arguments in Slim DI service](https://stackoverflow.com/questions/36993560/pass-arguments-in-slim-di-service). –  Oct 23 '17 at 00:21
  • @JoeScotto What do you mean by saying `to bypass` that? This does not visually look elegant but it must be this way, because your service provider is a function thus `$this->myFunction` is an instance of `Clousoure` and you have to call it somehow. Maybe defining your service provider as an object would be a better idea. In that case you'll have calls like `$this->myService->myFunc('test');` – Nima Oct 23 '17 at 00:46
  • @Nima How would one go about doing that with Slim? – Joe Scotto Oct 23 '17 at 00:46
  • 1
    @aendeerei the accepted answer on that question seems to be incorrect, I tried that code and it raised the same error as mentioned by Joe. – Nima Oct 23 '17 at 00:47
  • 1
    @JoeScotto It is not related to Slim actually, you just need to solve your main problem in a OOP manner instead of procedural approach. Not a good idea to write code in comments, but only to give an example: `class MyService { function myFunction($arg){ return $arg;}}` and then `$container['myService'] = function($c){return new MyService;};` and in your route `$this->myService->myFunction('some arguments');` – Nima Oct 23 '17 at 00:56
  • @JoeScotto in real world use cases, your service providers are probably objects with some dependencies, that's why we use DIC to be able to set them up, for example `Monolog` or `SwiftMailer` or `Twig`, otherwise if they are simple functions that do not need any dependencies (like your example case) you probably don't want to add them to DIC and they are simply accessible in any scope. There is also one other case that is discussed here https://pimple.symfony.com/ under `Protecting Parameters` section. – Nima Oct 23 '17 at 01:08
  • Thank you, @Nima. I didn't knew that about that answer. And I appreciate that you also tested it. The Slim docs present sadly only calling the container methods without arguments. But, in their API's [**__call()**](https://github.com/slimphp/Slim/blob/3.x/Slim/App.php#L117), they are calling `call_user_func_array`, which require an **array as arguments list**. So, I suppose, the container method should be actually called like this: `echo $this->myFunction(array('arg1', 'arg2'));`. What do you think? –  Oct 23 '17 at 01:19
  • 1
    @aendeerei Slim uses Pimple as its DIC, so we can't expect much documentation from Slim team, but fortunately Pimple is well documented itself. Have a look here if you're interested http://pimple.symfony.com. And about your point about the magic `__call` function, please note that is defined in `Slim\App` class not the `Pimple\Container` and in a route callback `$this` is an instance of Container not App. **I'm not sure but I guess** `$app->myFunction(...)` works fine but not `$this->myFunction(...)` – Nima Oct 23 '17 at 01:44
  • 1
    @Nima Indeed, I looked in the wrong place since I don't have much practice with the closures handling/scopes. Yes, the route is added with [$app->get(...)](https://github.com/slimphp/Slim/blob/3.x/Slim/App.php#L141), which calls the [map()](https://github.com/slimphp/Slim/blob/3.x/Slim/App.php#L233), which binds the closure to the container with [bindTo()](https://github.com/slimphp/Slim/blob/403b7980e0bc19ca43015f6232259d81479b24b2/Slim/App.php#L236). Therefore `$this` refers to the container. Thank you ;-) –  Oct 23 '17 at 02:08