Abstract Constants In PHP - Force A Child Class To Define A Constant
Answer :
This may be a bit of a ‘hack’, but does the job with very little effort, but just with a different error message if the constant is not declared in the child class.
A self-referential constant declaration is syntactically correct and parses without problem, only throwing an error if that declaration is actually executed at runtime, so a self-referential declaration in the abstract class must be overridden in a child class else there will be fatal error: Cannot declare self-referencing constant
.
In this example, the abstract, parent class Foo
forces all its children to declare the variable NAME
. This code runs fine, outputting Donald
. However, if the child class Fooling
did not declare the variable, the fatal error would be triggered.
<?php abstract class Foo { // Self-referential 'abstract' declaration const NAME = self::NAME; } class Fooling extends Foo { // Overrides definition from parent class // Without this declaration, an error will be triggered const NAME = 'Donald'; } $fooling = new Fooling(); echo $fooling::NAME;
A constant
is a constant
; there is no abstract
or private
constants in PHP as far as I know, but you can have a work around:
Sample Abstract Class
abstract class Hello { const CONSTANT_1 = 'abstract'; // Make Abstract const CONSTANT_2 = 'abstract'; // Make Abstract const CONSTANT_3 = 'Hello World'; // Normal Constant function __construct() { Enforcer::__add(__CLASS__, get_called_class()); } }
This would run fine
class Foo extends Hello { const CONSTANT_1 = 'HELLO_A'; const CONSTANT_2 = 'HELLO_B'; } new Foo();
Bar would return Error
class Bar extends Hello { const CONSTANT_1 = 'BAR_A'; } new Bar();
Songo would return Error
class Songo extends Hello { } new Songo();
Enforcer Class
class Enforcer { public static function __add($class, $c) { $reflection = new ReflectionClass($class); $constantsForced = $reflection->getConstants(); foreach ($constantsForced as $constant => $value) { if (constant("$c::$constant") == "abstract") { throw new Exception("Undefined $constant in " . (string) $c); } } } }
Unfortunately not... a constant is exactly what it says on the tin, constant. Once defined it can't be redefined, so in that way, it is impossible to require its definition through PHP's abstract inheritance or interfaces.
However... you could check to see if the constant is defined in the parent class's constructor. If it doesn't, throw an Exception.
abstract class A { public function __construct() { if (!defined('static::BLAH')) { throw new Exception('Constant BLAH is not defined on subclass ' . get_class($this)); } } } class B extends A { const BLAH = 'here'; } $b = new B();
This is the best way I can think of doing this from your initial description.
Comments
Post a Comment