I'm working with a Symfony 3.4 (PHP 7.2, update to 7.4 soon) project. I have some classes who extends an abstract class and i would like all my classes got the same constant name (constant have value different in each class). I'm starting with a pattern like this :
abstract class AbstractClass
{
abstract public function getConstant(): string;
}
final class Foo extends AbstractClass
{
const MY_CONST = 'foo';
public function getConstant(): string
{
return self::MY_CONST;
}
}
final class Bar extends AbstractClass
{
const MY_CONST = 'bar';
public function getConstant(): string
{
return self::MY_CONST;
}
}
// echo $foo->getConstant() : 'foo'
// echo $bar->getConstant() : 'bar'
The goal: if a class who extends AbstractClass don't have MY_CONST, i want return an message error.
I have excluded theses solutions :
- I can't add a constant in an interface (maybe in PHP 8 ?)
- I can't use "abstract factory" pattern for a constant (in my code it runs with
getConstant()method - I can't use a static property
The only way i have found is : implement an interface and tag the interface like explain in documentation. With compilerpass, helped with ReflexionClass, i will check if constant name exist, and if not: thrown an error or something like this.
So, i've edit like this :
final class Foo extends AbstractClass implements MyCustomInterface
{
// ...
}
final class Bar extends AbstractClass implements MyCustomInterface
{
// ...
}
The interface :
interface MyCustomInterface
{
}
Adding tag in AppKernel.php
protected function build(ContainerBuilder $container): void
{
$container
->registerForAutoconfiguration(MyCustomInterface::class)
->addTag('my_custom_tag');
}
And a compilerpass :
class MyCustomPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container): void
{
if (!$container->has(MyCustomInterface::class)) {
dump('No interface found');
return;
}
$definition = $container->findDefinition(MyCustomInterface::class);
$taggedServices = $container->findTaggedServiceIds('my_custom_tag');
dump($taggedServices);
}
}
The fun begin here...if i have only ONE class who implement the interface, $taggedServices find the service. BUT, if more than one class implements interface, no class are found...
I don't find where i am wrong. Do i need to implements AbstractClass instead of children classes ?
bin/console debug:containershow all the expected services?$container->has(interface)failing. So i think using Interface is not the solution i need. thank you for answer. Have you an idea for forcing a class to have a specific constant name when extends abstract or implements specific interface ?