PHP包含2个使用相同函数名的文件会给出重新声明错误吗?

时间:2011-06-21 08:28:37

标签: php function variables include

我遇到重新声明错误的问题。我还找不到它的解决办法,但基本上是:

  • 我有两个模块文件,它们使用相同的函数名,如系统使用的install(),uninstall()等等。
  • 当我同时包含两个文件以收集数据时,我收到重新声明错误。我想要它,以便我可以包含这两个文件,当加载下一个文件时,它只会重写上一个函数。

或者有没有办法可以取消或清除功能?我尝试过include,require,require_once等......没有工作:(

7 个答案:

答案 0 :(得分:7)

在PHP中,无法覆盖之前定义的函数。

因此模块以彼此的方式站立,一个模块阻止另一个模块工作。

实际上,模块需要使用相同的命名函数,而它们必须能够彼此并存。

可以通过将模块代码移动到自己的类中来完成。一个模块就是一个类。

然后,您可以使用模块类必须提供的功能定义接口。因此,模块必须具有简化的接口 - 例如,每个模块都有install()uninstall()函数 - 只需在首先指定所需的模块函数时定义object interface

module_definitions.php

interface Module {
  public function install();
  public function uninstall();
}

mod_Module1.php:

class Module1 implements Module {
  public function install() {...}
  public function uninstall() {...}
}

mod_Module2.php:

class Module2 implements Module {
  public function install() {...}
  public function uninstall() {...}
}

这样做之后,只要你的一个例程需要处理任何模块,你就可以使该函数需要一个模块:

function module_install(Module $module) {
  $module->install();
}

此功能仅接受现有模块作为参数。因此,您无法使用标准require / include,但模块需要在使用前进行实例化。您也可以将它放入模块加载器函数中:

function module_require($moduleName) {
  $class = $moduleName;
  if (!class_exists($class) {
    $file = sprintf('mod_%s.php', $moduleName);
    require $file;
    if (!class_exists($class)) {
      throw new DomainException(sprintf('Invalid Module File %s for Module %s.', $file, $moduleName));
    }
  }
}

如何访问模块功能呢?

现在唯一剩下的就是访问实际的模块了。

您可以创建一个包含所有模块的全局数组变量:

// Define existing modules
$modules = array('Module1', 'Module2');

// Require the modules
array_map('module_require', $modules);

// instantiate each module:
$moduleInstances = array_map(function($module){return new $module;}, $modules);

// map modules name (key) to it's module instance:
$modules = array_combine($modules, $moduleInstances);

// access module by name:
$modules['Module1]->install();

然而,这有一些问题。例如,所有模块都需要一次加载,但您可能不需要使用所有模块。或者想象你会覆盖全局$modules数组,所有模块都会丢失。

为了防止所有这些并允许更多控制和更容易访问模块,可以将其放入自己的类中来处理所有细节。就像知道加载了哪些模块的寄存器一样,根据需要进行注册。

对于以下内容,我假设一个模块只能存在一次。如果一个对象只能存在一次,通常称为 Singleton 。因此,我们将包装加载管理并将模块的名称提供给它自己的类来处理细节:

class Modules {
  private $modules = array();
  private static $instance;

  // singleton implementation for Modules manager
  private static function getInstance() {
    if (null === Modules::$instance) {
      Modules::$instance = new Modules;
    }
    return Modules::$instance;
  }

  // singleton-like implementation for each Module
  public function get($moduleName) {
    if (!isset($this->modules[$moduleName]) {
     module_require($moduleName);
     $newModule = new $moduleName();
     if (! $newModule instanceof Module) {
       throw new DomainException(sprintf('Not a Module: %s', $moduleName));
     }
     $this->modules[$moduleName] = $newModule;
    }
    return $this->modules[$moduleName];
  }

  // get a module by name
  public static function get($moduleName) {
    return Modules::getInstance()->get($moduleName);
  }
}

将此类放入module_definitions.php中,该类应始终包含在您的应用程序中。

因此,无论何时需要访问模块,您都可以使用带有模块名称的静态get函数来执行此操作:

Modules::get('Module1')->install();
Modules::get('Module2')->install();

答案 1 :(得分:2)

没有。您有应用程序设计问题。

重命名第二个函数,并在想要使用第二个函数的位置上调用它。

答案 2 :(得分:1)

在同一范围内,您不能拥有两个具有相同名称的功能。

如果您有php5.3或更高版本,名称空间可以是答案:每个插件都有自己的,所以函数变为

\plugin1\install()
\plugin2\install()

等等。

答案 3 :(得分:1)

您可能还希望在这些包含文件中创建唯一的类,然后让它们扩展泛型类,并将该泛型类用作要在更高级别调用这些函数时锚定的类型。你也可以让另一个重载,然后当你在一个方法中执行一个方法时,它可以直接传递给下一个方法。

答案 4 :(得分:0)

理论上如果你将每个文件的函数包装在一个单独的类中,那么你可以毫无问题地调用它们。如果静态调用它们,你甚至不需要真正担心类状态。

答案 5 :(得分:0)

您不能在同一名称空间中使用两次相同的函数名称。 您应该重命名第二个函数或使用“Maerlyn”建议

之类的命名空间

答案 6 :(得分:0)

这个问题可以通过命名空间或/和静态类来解决 最简单的方法是使用静态方法将这些函数包装在类中 之后,您不仅可以同时包含它们,还可以使用autoload - 函数并忘记“包含”。

class Class1
{
    public static function install()
    {}
}

class Class2
{
    public static function install()
    {}
}

More about namespaces and autoload