Skip to content

Latest commit

 

History

History
105 lines (89 loc) · 4.29 KB

File metadata and controls

105 lines (89 loc) · 4.29 KB

Callable Definitions Extended

Callable definitions in yiisoft/queue are based on native PHP callables and provide additional ways to define a callable.

Both definition types (native PHP callables and extended callables) allow you to use a DI container and yiisoft/injector to resolve dependencies in a lazy way. These callable definition formats are used across the package to convert configuration definitions into real callables.

Type 1: Native PHP callable

When you define a callable as a native PHP callable, it is not modified in any way and is called as is. Dependencies in the parameter list are resolved via yiisoft/injector and a DI container.
As you can see in the PHP documentation, there are several ways to define a native callable:

  • Closure (lambda function). It may be static. Example:
    $callable = static function(MyDependency $dependency) {
      // do stuff
    }
  • First class callable. It is itself a Closure. Example:
    $callable = trim(...);
    $callable2 = $this->foo(...);
  • A class static function. When a class has a static function, an array syntax may be used:
    $callable = [Foo::class, 'bar']; // calls Foo::bar() statically
  • An object method. The same as above, but with an object and a non-static method:
    $foo = new Foo();
    $callable = [$foo, 'bar']; // this will be called the same way as $foo->bar();
  • A class static function as a string. This format is non-obvious and hard to refactor; it exists for completeness only:
    $callable = 'Foo::bar'; // this will be called the same way as Foo::bar();
  • A name of a named function:
    function foo() {
      // do stuff
    }
    $callable = 'foo';
    $callable2 = 'array_map';
  • Callable objects. An object with the __invoke method implemented:
    class Foo 
    {
      public function __invoke()
      {
        // do stuff
      }
    }
    
    $callable = new Foo();

Type 2: Callable definition extensions (via container)

The difference from native PHP callables is that you don't need to instantiate objects yourself: you pass a class name or alias, and the DI container resolves the instance lazily, only when the callable is actually invoked. Ways to define an extended callable:

  • An object method through a class name or alias (non-static method only):
    final readonly class Foo 
    {
      public function __construct(private MyHeavyDependency $dependency) {}
    
      public function bar()
      {
        // do stuff
      }
    }
    
    $callable = [Foo::class, 'bar']; // resolves Foo from container and calls $foo->bar()

    [!NOTE] This format differs from Type 1: here the object is resolved from the DI container lazily when the callable is invoked. In Type 1, the same array syntax works only for static methods or pre-instantiated objects. Here is a simplified example of how it works (for non-static methods):

    if ($container->has($callable[0])) {
      $callable[0] = $container->get($callable[0]);
    }
    
    $callable();

Note

If bar is declared static, no object is instantiated — the method is called statically on the class. In this case, Type 2 behaves the same as Type 1.

  • Class name of an object with the __invoke method implemented:
    $callable = Foo::class;
    It works the same way as above: an object will be retrieved from a DI container and called as a function.

Note

You can use an alias registered in your DI Container instead of a class name. This will also work if you have a "class alias" definition in container:

$callable = 'class alias'; // for a "callable object" 
$callable2 = ['class alias', 'foo']; // to call "foo" method of an object found by "class alias" in DI Container

Invalid definitions

The factory throws Yiisoft\Queue\Middleware\InvalidCallableConfigurationException when it cannot create a callable (for example: null, unsupported array format, missing method, container entry is not callable).