SnIpY SnIpY - 3 months ago 12
PHP Question

Call all classes that implement an interface

I have the following code in place.

Interface Vehicle which has a method calculateDistance.

Class Car implements Vehicle
Class Bicycle implements Vehicle
Class MotorCycle implements Vehicle

What I want to do next is a method in my controller that calls every class that implements Vehicle and get the values from calculateDistance.

What would be the best way/design pattern to achieve this?

At this moment I am just calling all the classes that implement the interface Vehicle (via ReflectionClass) and loop over them to call this method.

Answer

The best way is to implement CompilerPass. Here is an example . So, create a registry class (TransportChain class in that example), interface, and all classes that implements that interface, define them as services and give them tag name. After that, you can call that registry service in your action, and call your desired method by each service.

Basic example:

interface

interface SomeInterface {
   public function doSomething();
}

Service 1:

class First implement SomeInterface {
    public function doSomething() {
        // do smth
    }
}

Service 2:

class Second implement SomeInterface {
    public function doSomething() {
        // do smth
    }
}

Registry class:

class MyRegistry
{
    private $services = [];

    public function addMyService($service)
    {
        $this->services[] = $service;
    }

    public function all()
    {
        return $this->services;
    }
}

CompilerPass:

   ...

   $myServices = $container->findTaggedServiceIds('my_tag');

    if (empty($myServices)) {
        return;
    }

    $registry = $container->getDefinition('my_registry');

    foreach ($myServices as $key => $myService) {
        $registry->addMethodCall('add', [new Reference($key)]);
    }

    ...

After clearign the cache, you can call them in your action:

...

foreach ($this->get('my_registry')->all() as $myService) {
    $myService->doSomething();
}

...

The whole other stuff, like declaring services, give them tag name, registering your compiler pass has been written here.

Comments