开发者

PHP Including 2 files using same function names give redeclare error?

开发者 https://www.devze.com 2023-03-14 13:26 出处:网络
i\'m having trouble with a redeclare error. I can\'t find a fix for 开发者_如何学运维it yet, but basically:

i'm having trouble with a redeclare error. I can't find a fix for 开发者_如何学运维it yet, but basically:

  • I have 2 files that are modules and they use the same function names like install(), uninstall() etc etc which are used by the system.
  • When I include both the files at the same time for gathering data, I get a redeclare error. I want it so that I can include both and when the next file is loaded, it just rewrites over the previous function.

Or is there a way I can unset or clear the function? I've tried include, require, require_once etc... No work :(


In PHP it is not possible to overwrite a function that you have previously defined.

So the modules stand in each others way and one module prevents the other from working.

Actually Modules need to make use of the same named functions while they must be able to co-exist next to each other.

That can be done by moving the modules code into classes of their own. One module is one class then.

You can then define an interface with the functions your module classes must provide. As Modules therefore must have a streamlined interface - each module has a install() and uninstall() function for example - just define an object interface at first specifying those needed module functions:

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() {...}
}

After doing so, whenever one of your routines needs to deal with any module, you can make that function require a module:

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

This function will only accept an existing module as a parameter. So you can not use your standard require/include for this but modules need to be instantiated prior use. You can put that into a module loader function as well:

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

How to access the modules functions then?

The only thing left is now to access the actual module.

You could the create a global array variable containing all modules:

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

However this has some problems. All modules need to be loaded at once for example, but you might not need to use all modules. Or imagine you would overwrite the global $modules array, all modules would be lost.

To prevent all that and allow more control and easier access to the modules, this can be put into a class of it's own that will take care of all the details. Like a register that knows which modules are loaded or not, registers them as needed.

For the following I assume a module can only exists once. If an object can only exist once this is often called a Singleton. So we'll wrap the management of loading and providing the module by it's name into a class of it's own that deals with the details:

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

Put this class into module_definitions.php as well, which should be always included in your application.

So whenever you need to access a module you can do now by using the static get function with the name of the module:

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


No. You have a application design problem.

Rename the second function and call it on the locations you want the second to be used.


You cannot have two functions with the same name in the same scope.

If you have php5.3 or above, namespaces can be the answer: each plugin has its own, so the functions became

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

et cetera.


You may also wish to create unique classes inside these include files, then have them extend a generic class and use that generic class as a type to anchor to when you want to call up these functions at a higher level. You could also have one overload the other and then when you execute a method in one, it could be passed right on to the next.


Theoretically if you wrap the functions of each file in a separate class then you can call them both without problems. You don't even need to really worry about class state if you call them statically.


You cant use two time the same function name in the same namespace. You should rename your second function or use namespaces like "Maerlyn" suggest


This problem can be solved by namespaces or/and static class.
Easiest way is to wrap these functions in class with static methods.
After that you'll be able not only to include them both, but also to use autoload-functions and forget about 'include'.

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

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

More about namespaces and autoload

0

精彩评论

暂无评论...
验证码 换一张
取 消