有没有办法在PHP中安全地重新声明一个类?

时间:2010-04-17 15:31:52

标签: php oop class

我们都知道臭名昭着的“不能重新宣布上课”的错误。有没有任何方法可以克服这个问题并实际声明一个具有相同名称的新类,或者这在PHP 5中是不可能的?

7 个答案:

答案 0 :(得分:13)

正如Pekka和Techpriester都指出的那样:不,你做不到。但是,如果您使用PHP> = 5.3,则可以使用namespaces和“use”构造来有效地“重新声明”该类。这是一个例子:

// 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

因此,您已获得所需的结果,因为MyClass现在引用了您的命名空间类。

答案 1 :(得分:6)

可能有一种方法使用一些不起眼的扩展,但在基本的标准PHP中,据我所知,没有。

但是,您可以始终扩展现有类,并且 - 根据您的情况,可能会将该扩展类的实例“偷偷”到您正在处理的应用程序中。

答案 2 :(得分:2)

这是不可能的。根据用例,名称空间(如jpfuentes2)可能适合您。

一个黑客就是实现一个自定义的新“运营商”。

实施例:


$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');

另一个黑客是使用runkit来重新实现一个类。

答案 3 :(得分:2)

2016年的答案可能更为现代,看起来现在至少有3个选项:

选项1.使用runkit

参考:http://php.net/manual/en/function.runkit-class-emancipate.php

bool runkit_class_emancipate ( string $classname )

“将继承的类转换为基类,删除范围为祖先的任何方法”

虽然我自己没有对此进行测试,但如果您可以控制加载的扩展,那么它似乎是一个可行的选项。这里的缺点是你失去了所有祖先方法。

选项2.再次使用runkit

参考: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 ] )

“动态更改给定方法的代码”

如果您的目标是在基类上调整一两个方法,这就解决了选项1的问题。

选项3.实施自动装带器

参考:http://php.net/manual/en/function.spl-autoload-register.php

bool spl_autoload_register ([ callable $autoload_function [, bool $throw = true [, bool $prepend = false ]]] )

“将给定的函数注册为__autoload()实现”

这是我个人最喜欢的3,因为:

  • 它在现代PHP版本中本地工作
  • 它可以与其他自动加载器配合使用
  • 它允许您围绕覆盖实现条件逻辑

这也是我的经验之一。示例实现如下:

// 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';
  }
}

答案 4 :(得分:1)

AFAIK,在PHP中无法重新声明现有的函数或类。

如果你能说出来,你想要做什么,也许还有另一种解决方案......

答案 5 :(得分:0)

基本上你不能重新开课。但如果你真的想,你可以。 :) 一切皆有可能。需要一个类,它会改变它的结构动态?您可以使用魔术方法__call和模式状态。

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
  }

}

还有一个PHP工具包可以动态地使用类:http://php.net/manual/en/book.runkit.php

我知道在Ruby中重新声明类及其方法是可能的(我会认为这是语言设计中的一个错误。)

答案 6 :(得分:0)

基本上我们无法在PHP directly中重新声明一个类。如果您需要在php中重新声明一个类,那么我建议您在单独的文件中编写该类,并使用require_one将该文件调用到所需的页面。它如下:

<强> 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。它适用于me

输出如下:

 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