note 84525 added to language.oop5.late-static-bindings
| From: | sebastien at info-conseil dot fr | Date: | Thu, 17 Jul 2008 14:26:29 +0000 |
| Subject: | note 84525 added to language.oop5.late-static-bindings | ||
| Groups: | php.notes | ||
| Request: | Send a blank email to php-notes+get-141627@lists.php.net to get a copy of this message | ||
Here is a small workaround I made for the static inheritance issue. It's not perfect, but it
works.
<?php
// BaseClass class will be extended by any class needing static inheritance workaroud
class BaseClass {
// Temporarily stores class name for Entry::getStatic() and Entry::setNextStatic()
protected static $nextStatic = false;
// Returns the real name of the class calling the method, not the one in which it was declared.
protected static function getStatic() {
// If already stored
if (self::$nextStatic) {
// Clean and return
$class = self::$nextStatic;
self::$nextStatic = false;
return $class;
}
// Init
$backTrace = debug_backtrace();
$class = false;
// Walk through
for ($i=0; $i<count($backTrace); $i++) {
// If a class is defined
if (isset($backTrace[$i]['class'])) {
// Check if it is not a basic class
if (!in_array($backTrace[$i]['class'], array('BaseClass',
'GenericClass'))) {
return $backTrace[$i]['class'];
} else {
$class = $backTrace[$i]['class'];
}
} else {
// Returns last known class
return $class;
}
}
// Default
return $class;
}
// If a static method is called within global env, the previous method won't work, so we need
to tell BaseClass which
public static function setNextStatic($class) {
// Save value
self::$nextStatic = $class;
}
}
// Generic class declaring various static methods
class GenericClass extends BaseClass {
public static $name = 'Generic';
public function getName() {
$static = get_class_vars(get_class($this));
return $static['name'];
}
public static function basicClassName() {
return self::$name;
}
public static function staticClassName() {
// Get real name
$staticName = self::getStatic();
// Return final class name
$static = get_class_vars($staticName);
return $static['name'];
}
}
// Final class
class SomeClass extends GenericClass {
public static $name = 'Some';
public static function returnClassNameWith($string) {
return $string.' : '.self::staticClassName();
}
}
// Instance call
// Will print 'Some'
$a = new SomeClass();
echo 'Name of $a : '.$a->getName().'<br />';
// Static calls
// Will print 'Generic'
echo 'Basic call to SomeClass::$name : '.SomeClass::basicClassName().'<br
/>';
// Will print 'Generic'
echo 'Global call to SomeClass::$name : '.SomeClass::staticClassName().'<br
/>';
// Will print 'Some'
BaseClass::setNextStatic('SomeClass');
echo 'Global call to SomeClass::$name with pre-set :
'.SomeClass::staticClassName().'<br />';
// Will print 'Some'
echo 'Internal call to SomeClass::$name : '.SomeClass::returnClassNameWith('This is a
').'<br />';
?>
There are two issues with this workaround :
- if you call a static method from global env, you need to declare the name of the class BEFORE
calling the method, otherwise the workaround won't work (see 3rd and 4th examples). But I
assume good programming makes few calls to static methods from global scope, so this shouldn't
be long to fix if you use it.
- the workaround fails to access to private or protected static vars, as it uses get_class_vars().
If you find any better solution, let us know.
With Php 5.3.0, upgrading will be easy : just delete the methods from the basic class, and
search/replace any call to getStatic() and setNextStatic() by static:: - or one could use a selector
on PHP_VERSION value to include either the BaseClass file with workaround or a BaseClass file using
static::
----
Server IP: 195.221.21.36
Probable Submitter: 86.72.239.48
----
Manual Page -- http://www.php.net/manual/en/language.oop5.late-static-bindings.php
Edit -- https://master.php.net/note/edit/84525
Del: integrated -- https://master.php.net/note/delete/84525/integrated
Del: useless -- https://master.php.net/note/delete/84525/useless
Del: bad code -- https://master.php.net/note/delete/84525/bad+code
Del: spam -- https://master.php.net/note/delete/84525/spam
Del: non-english -- https://master.php.net/note/delete/84525/non-english
Del: in docs -- https://master.php.net/note/delete/84525/in+docs
Del: other reasons-- https://master.php.net/note/delete/84525
Reject -- https://master.php.net/note/reject/84525
Search -- https://master.php.net/manage/user-notes.php