PHP Включение 2-х файлов с одинаковыми именами функций выдает ошибку redeclare? - PullRequest
3 голосов
/ 21 июня 2011

У меня возникла проблема с ошибкой redeclare.Я пока не могу найти исправление, но в основном:

  • У меня есть 2 файла, которые являются модулями, и они используют те же имена функций, что и install (), uninstall () и т. Д., Которые используютсясистемой.
  • Когда я включаю оба файла одновременно для сбора данных, я получаю ошибку повторного объявления.Я хочу, чтобы я мог включить оба, и когда следующий файл загружен, он просто перезаписывает предыдущую функцию.

Или есть способ, которым я могу сбросить или удалить функцию?Я пытался включить, требовать, require_once и т. Д ... Нет работы: (

Ответы [ 7 ]

7 голосов
/ 21 июня 2011

В PHP невозможно переписать функцию, которую вы ранее определили.

Таким образом, модули стоят друг на друге, и один модуль препятствует работе другого.

На самом деле модули должны использовать функции с одинаковыми именами, в то время как они должны быть в состоянии сосуществовать рядом друг с другом.

Это можно сделать, переместив код модулей в собственные классы. Один модуль - это один класс.

Затем вы можете определить интерфейс с функциями, которые должны обеспечивать ваши классы модулей. Поэтому модули должны иметь упрощенный интерфейс - например, каждый модуль имеет функцию install() и uninstall() - просто определите объектный интерфейс , сначала указав необходимые функции модуля:

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();
}

Эта функция будет принимать только существующий модуль в качестве параметра. Таким образом, вы не можете использовать ваши стандартные требования / включения для этого, но модули должны быть созданы перед использованием. Вы также можете поместить это в функцию загрузчика модулей:

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();
2 голосов
/ 21 июня 2011

Нет. У вас проблема с дизайном приложения.

Переименуйте вторую функцию и вызовите ее в тех местах, где вы хотите использовать вторую.

1 голос
/ 21 июня 2011

Вы также можете создать уникальные классы внутри этих включаемых файлов, затем попросить их расширить универсальный класс и использовать этот универсальный класс в качестве типа для привязки, когда вы хотите вызвать эти функции на более высоком уровне. У вас также может быть одна перегрузка другой, а затем, когда вы выполняете метод в одном, он может быть передан сразу другому.

1 голос
/ 21 июня 2011

Вы не можете иметь две функции с одинаковыми именами в одной и той же области видимости.

Если у вас php5.3 или выше, пространства имен могут быть ответом: каждый плагин имеет свои собственные, поэтому функции стали

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

и так далее.

0 голосов
/ 21 июня 2011

Эту проблему можно решить с помощью пространств имен и / или статического класса.
Самый простой способ - обернуть эти функции в классе статическими методами.
После этого вы сможете не только включать их оба, но итакже использовать функции автозагрузки и забыть о включении.

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

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

Подробнее о пространствах имен и автозагрузке

0 голосов
/ 21 июня 2011

Вы не можете использовать два раза одно и то же имя функции в одном и том же пространстве имен. Вам следует переименовать вторую функцию или использовать пространства имен, например, «Maerlyn»:

0 голосов
/ 21 июня 2011

Теоретически, если вы оберните функции каждого файла в отдельный класс, вы можете вызвать их оба без проблем. Вам даже не нужно беспокоиться о состоянии класса, если вы называете их статически.

...