1

I have folder with many plugins. Each plugin contains same name class but different content:

plugin01.php

class Plugin{
  public function get($a){
    return 'Plugin01 - '.$a;
  }
}

plugin02.php

class Plugin{
  public function get($a){
    return 'Plugin02 - '.$a;
  }
}

In Plugins.php, i want to load this plugins. But not only once.

class Plugins{
  public static function load($id){
    require $id.'.php';
    
    $plugin = new Plugin();
    return $plugin->get('test');
  }
}

echo Plugins::load('plugin01')."\n";
echo Plugins::load('plugin02')."\n";
echo Plugins::load('plugin01');

Expected result:

Plugin01 - test

Plugin02 - test

Plugin01 - test

Current Result:

Fatal error: Cannot redeclare class Plugin

This definitely does not work, because i am redefining class name and including more times same plugin.

My question is, can I include file only in Function scope (including all classes defined in external file), that if will not appear outside function?

Can I do that with PHP, or must I use different names for each class?

Community
  • 1
  • 1
m1k1o
  • 2,344
  • 16
  • 27

2 Answers2

1

If you only ever could have one plugin loaded at a time, your method would work. But as you have found out, it will break with multiple classes with the same name.

I think a better solution would be to use interfaces, and then have the different plugins implement those interfaces.

So define an interface with all the methods a plugin should have:

interface Plugin
{
    public function get($a);
}

then make each plugin implement it:

// Plugin1.php
class Plugin1 implements Plugin
{
    public function get($a)
    {
        return 'Plugin 1 ' . $a;
    }
}

 

// Plugin2.php
class Plugin2 implements Plugin
{
    public function get($a)
    {
        return 'Plugin 2 ' . $a;
    }
}

and then you can load and instantiate them almost in the same way:

class Plugins{
  public static function load($pluginName){
    require_once( $pluginName.'.php');

    $plugin = new $pluginName();
    return $plugin;
  }
}

$plugin1 = Plugins::load('Plugin1');
echo $plugin1->get('Test');
$plugin2 = Plugins::load('Plugin2');
echo $plugin2->get('Test');
Matsemann
  • 21,083
  • 19
  • 56
  • 89
  • +1 Looks well, but it is not solution to my problem. In this case muss I also care for unique names for plugins which is hard to do when you have 500 plugin form external developers. – m1k1o Aug 08 '14 at 20:41
  • @M1K1O you could try with namespaces. – Matsemann Aug 08 '14 at 20:44
  • Well, it is not what i exacly expected (i must also care for uniq namespaces), but it looks like there is no way to do it with PHP. – m1k1o Aug 08 '14 at 20:52
-1

From the manual: include function

When a file is included, the code it contains inherits the variable scope of the line on which the include occurs. Any variables available at that line in the calling file will be available within the called file, from that point forward. However, all functions and classes defined in the included file have the global scope.

So, you should rename your classes, since the scope is global.

Emi
  • 1,018
  • 9
  • 13
  • 1
    Actually, the issue has nothing to do with `include` per se. It's just so that (non-namespaced) functions and classes are always global in php. – georg Aug 08 '14 at 08:27
  • Yes, depending on the version of PHP he has, he could use namespaces. – Emi Aug 08 '14 at 08:34
  • Well, it is also impossibble to undefinide classes in PHP. The main problem is, there can be more than 500 Plugins. It can happens there will be duplicate names. – m1k1o Aug 08 '14 at 08:37
  • Usually you have a naming convention and stick to it, for example: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md – Emi Aug 08 '14 at 08:47