【问题标题】:Limit scope of require'd class definitions to a function将所需类定义的范围限制为函数
【发布时间】:2014-08-10 19:29:34
【问题描述】:

我有很多插件的文件夹。每个插件包含相同名称的类但不同的内容:

plugin01.php

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

plugin02.php

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

在 Plugins.php 中,我想加载这个插件。但不止一次。

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

预期结果:

Plugin01 - 测试

Plugin02 - 测试

Plugin01 - 测试

当前结果:

致命错误:无法重新声明类插件

这绝对行不通,因为我是 redefining 类名和 including 多次相同的插件。

我的问题是,我可以只在函数范围内包含文件(包括在外部文件中定义的所有类),如果不会出现在函数之外?

我可以用 PHP 做到这一点,还是必须为每个类使用不同的名称?

【问题讨论】:

    标签: php plugins php-include


    【解决方案1】:

    如果您一次只能加载一个插件,那么您的方法会奏效。但正如您所发现的,它将与多个具有相同名称的类中断。

    我认为更好的解决方案是使用interfaces,然后让不同的插件实现这些接口。

    所以用插件应该有的所有方法定义一个接口:

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

    然后让每个插件实现它:

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

    然后您可以几乎以相同的方式加载和实例化它们:

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

    【讨论】:

    • +1 看起来不错,但这并不能解决我的问题。在这种情况下,我还关心插件的唯一名称,当您有 500 个来自外部开发人员的插件时,这很难做到。
    • @M1K1O 你可以尝试使用命名空间。
    • 嗯,这不是我所期望的(我还必须关心 uniq 命名空间),但看起来 PHP 没有办法做到这一点。
    【解决方案2】:

    来自手册:include function

    当一个文件被包含时,它包含的代码继承了包含发生的行的变量范围。从那时起,调用文件中该行的任何可用变量都将在被调用文件中可用。但是,包含文件中定义的所有函数和类都具有全局范围。

    所以,你应该重命名你的类,因为范围是全局的。

    【讨论】:

    • 其实这个问题与include 本身无关。只是这样(非命名空间的)函数和类在 php 中始终是全局的。
    • 是的,根据他的PHP版本,他可以使用命名空间。
    • 嗯,在 PHP 中取消定义类也是不可能的。主要问题是,可以有超过 500 个插件。可能会发生重复名称。
    • 通常你有一个命名约定并遵守它,例如:github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-04-03
    • 1970-01-01
    • 1970-01-01
    • 2012-03-21
    • 1970-01-01
    • 1970-01-01
    • 2013-11-30
    相关资源
    最近更新 更多