Late Static Binding in PHP 5.3
Problem with early Binding
Static References to the current class like __CLASS__ or self:: resolved to the class in which the function belongs, as in where it was defined. Consider the following code snippet
<?php class parentClass { public static function getClassName() { echo __CLASS__; } public static function who() { self::getClassName(); } } class childClass extends parentClass { public static function getClassName() { echo __CLASS__; } } childClass::who(); // Output: "parentClass" ?>
Calling static function “who” would call getClassName() and the output will be “parentClass” because the function “who” defined in base class. So the static reference __CLASS__ would print “parentClass”.
Late Binding
The latest version of php introduces a new possibility by allowing a keyword that references the class that was initially called at runtime. So that output will be “childClass” that what’s we expected. Modifying the code with a slight change.
<?php class parentClass { public static function getClassName() { echo __CLASS__; } public static function who() { static::getClassName(); // late state binding } } class childClass extends parentClass { public static function getClassName() { echo __CLASS__; } } childClass::who(); // Output: "childClass" ?>
Practical Use
We may require the actual class name it was called to determine the action. For example if a base database table class do operation like create,update and we have sub classes for each table. To know the table name we think to use class name as table name instead of a separate property this late state Binding would help us to derive the class using late state binding.
Before some time we were using debug_backtrace() to determine the classname and this is no longer needed now. The following code explains that.
<?php class Table { public static function getClass() { return __CLASS__; } public static function save($id) { $tableName = static::getClass(); // return Content // The magic... } } class Content extends Table { public static function getClass() { return __CLASS__; } } Content::save(1); ?>
Running this code would use getClass() method to determine the class name in current called context. We have a great function provided by php namely get_called_class() to repeat the same function.
Another example would be a subset of roles as class assigned to users. All class extends the base role and some common methods in base class would need the current role and itself can be from the class name.
The following code would illustrate this
<?php class Role { public function __construct(){ if (CURRENT_USER_TYPE!=get_called_class()){ throw new Exception('Restricted Access'); } } } class Administrator extends Role{ public function __construct(){ parent::_construct(): } } class Manager extends Role{ public function __construct(){ parent::__construct(): } } ?>
In the above code, restriction is made to validate class name before that get instantiated. Current Logged in UserType is matched again Class Name. It can be applied to some common methods too.
- Late Static Binding in PHP 5.3 - July 14, 2014
- Introduction to Web Notifications API - May 10, 2014
- Manage Dependency with Composer - April 21, 2014