Last active
August 26, 2022 12:36
-
-
Save benblub/b799c4d46facb7ff89244dede3cac02c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App; | |
class BarService | |
{ | |
public function bar(): string | |
{ | |
return 'bar'; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App; | |
use ApiPlatform\Core\JsonSchema\TypeFactoryInterface; | |
use Symfony\Component\DependencyInjection\Attribute\AsDecorator; | |
use Symfony\Component\DependencyInjection\Attribute\MapDecorated; | |
#[AsDecorator(decorates: BarService::class)] | |
class BarServiceDecorator | |
{ | |
private $inner; | |
public function __construct(#[MapDecorated] $inner) | |
{ | |
$this->inner = $inner; | |
} | |
public function bar(): string | |
{ | |
return $this->inner->bar() . ' Bar'; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Controller; | |
use App\Service\BarService; | |
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; | |
use Symfony\Component\HttpFoundation\Response; | |
use Symfony\Component\Routing\Annotation\Route; | |
class TestController extends AbstractController | |
{ | |
/** | |
* @Route("/foo") | |
*/ | |
public function foo(BarService $barService) | |
{ | |
return new Response('foo ' . $barService->bar()); | |
} | |
} |
If our BarService now implements a BarInterface and I set the interface as type in the controller I get almost the same error.
App\Controller\TestController::foo(): Argument #1 ($barService) must be of type App\Service\BarServiceInterface, App\Service\BarServiceDecorator given.
BarServiceDecorator needs to either extends BarService, or implements BarServiceInterface
BarServiceDecorator needs to either extends BarService, or implements BarServiceInterface
Thanks 👍
Here is another example of how to use the whole thing with interfaces.
<?php
namespace App\Controller;
use App\Service\BarServiceInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
class TestController extends AbstractController
{
/**
* @Route("/foo")
*/
public function foo(BarServiceInterface $barService)
{
return new Response('foo ' . $barService->bar());
}
}
<?php
namespace App\Service;
use Symfony\Component\DependencyInjection\Attribute\AsDecorator;
use Symfony\Component\DependencyInjection\Attribute\MapDecorated;
#[AsDecorator(decorates: BarServiceInterface::class)]
class BarServiceDecorator implements BarServiceInterface
{
private $inner;
public function __construct(#[MapDecorated] $inner)
{
$this->inner = $inner;
}
public function bar()
{
return $this->inner->bar() . ' BAZ';
}
}
<?php
namespace App\Service;
interface BarServiceInterface
{
public function bar();
}
<?php
namespace App\Service;
class BarService implements BarServiceInterface
{
public function bar()
{
return 'bar';
}
}
# services.yaml
App\Service\BarServiceInterface: '@App\Service\BarService'
https://symfony.com/doc/current/service_container/autowiring.html#working-with-interfaces
https://symfony.com/doc/current/service_container/service_decoration.html
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
As typehint I use the service which we want to decorate. The example is deliberately without interfaces, as in the Symfony docs.
Without our decorator extending the service class, we get a type hint error.
Isn't the Decorator supposed to wrap the service?
like $this->services[BarService::class] = new BarServiceDecorator(new BarService());
If I debug the Container with
php bin/console debug:container App\Service\BarService
Then I get the Decorator displayed as a service.Shouldn't it be possible to continue using the original typehint in the controller without Decorator having to extend the class?