We all know the infamous "cannot redeclare class" error. Is there any method to overcome this and actually declare a new class with the same name, or is this impossible in PHP 5?
问题:
回答1:
As Pekka and Techpriester both pointed out: no, you cannot. However, if you're using PHP >= 5.3, then you can use namespaces and the "use" construct to effectively "redeclare" the class. Here's an example:
// MyClass.php
class MyClass {
const MY_CONST = 1;
}
// MyNamespaceMyClass.php
namespace Mynamespace;
class MyClass {
const MY_CONST = 2;
}
// example.php
require_once 'MyClass.php';
require_once 'MyNamespaceMyClass.php';
use Mynamespace\MyClass as MyClass;
echo MyClass::MY_CONST; // outputs 2
Thus, you've got your desired result, as MyClass now refers to your namespaced class.
回答2:
There may be a way using some obscure extension, but in basic standard PHP, as far as I know, no.
You can, however, always extend an existing class and - maybe, depending on your scenario - "smuggle" an instance of that extended class into the application you're working on.
回答3:
It is impossible. Depending on the use case, namespaces, like jpfuentes2 mentioned, might work for you.
One hack is to implement a custom new "operator".
Example:
$GLOBALS['class_map'] = array('A' => 'A');
function _new($class){
$realClass = $GLOBALS['class_map'][$class];
return new $realClass;
}
class A {}
$a = _new('A');
// change the implementation
$GLOBALS['class_map']['A'] = 'B';
$a2 = _new('A');
Another hack is to use runkit to re-implement a class.
回答4:
Perhaps a more modern answer for 2016, it looks like there are now at least 3 options:
Option 1. Using runkit
Ref: http://php.net/manual/en/function.runkit-class-emancipate.php
bool runkit_class_emancipate ( string $classname )
"Convert an inherited class to a base class, removes any method whose scope is ancestral"
Though I haven't tested this myself, it seems like a viable option if you have control over the extensions loaded. The drawback here would be that you lose all ancestral methods.
Option 2. Using runkit, again
Ref: http://php.net/manual/en/function.runkit-method-redefine.php
bool runkit_method_redefine ( string $classname , string $methodname , string $args , string $code [, int $flags = RUNKIT_ACC_PUBLIC ] )
"Dynamically changes the code of the given method"
This solves the problem of option 1 if your goal is to tweak a method or two on the base class.
Option 3. Implement an Autoloader
Ref: http://php.net/manual/en/function.spl-autoload-register.php
bool spl_autoload_register ([ callable $autoload_function [, bool $throw = true [, bool $prepend = false ]]] )
"Register given function as __autoload() implementation"
This is personally my favorite of the 3, because:
- It works natively in modern PHP versions
- It can work in conjunction with other autoloaders
- It allows you to implement conditional logic around your overrides
This is also one for which I do have some experience. An example implementation is as follows:
// Some early point in your application
// Ideally after other autoloaders have registered
spl_autoload_register('autoload_override');
function autoload_override($class) {
if ($class == 'TargetClassName') {
include '/path/to/overriding/class.php';
}
}
回答5:
AFAIK, redeclaring exiting functions or classes is not possible in PHP.
If you could tell, what you are trying to do, maybe there's another solution ...
回答6:
Basically you cannot redeclare a class. But if you really want to, you can. :) Everything is possible. Need a class, that changes it's structure dynamically? You can use magic method __call and pattern State.
class Example
{
var $state;
public function setImplementation($state)
{
$this->state = $state;
}
public function __call($method, $args)
{
if (method_exists($this->state, $method))
return $this->state->$method($args);
else
// error
}
}
There is also a PHP toolkit to play with classes dynamically: http://php.net/manual/en/book.runkit.php
I know that redeclaring class and its methods is possible in Ruby (and I would consider it as a mistake in a language design).
回答7:
Basically we can't redeclare a class in PHP directly
. If you are in need to get redeclare a class in php, then I suggest you to write that class in a separate file and use require_one
to call that file to the desired page. It's as follows:
Page1.php
class abcd
{
function max()
{
echo "Hello World!!! count:-".$GLOBALS['x'];
}
}
Page2.php
$i=10;
for($x=0;$x<$i;$x++)
{
require_once "Page1.php";
$myclass = new abcd();
$myclass->max();
}
Now it will work as you desired. It worked for me.
The output will be as follows :
Hello World!!! count:- 0
Hello World!!! count:- 1
Hello World!!! count:- 2
Hello World!!! count:- 3
Hello World!!! count:- 4
Hello World!!! count:- 5
Hello World!!! count:- 6
Hello World!!! count:- 7
Hello World!!! count:- 8
Hello World!!! count:- 9