Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHP中的类插件?_Php_Class_Plugins - Fatal编程技术网

PHP中的类插件?

PHP中的类插件?,php,class,plugins,Php,Class,Plugins,在学习PHP的过程中,我还遇到了一些问题,PHP是否实现了任何内置插件系统 因此,插件将能够改变核心组件的行为 例如,类似这样的工作方式: include 'core.class.php'; include 'plugin1.class.php'; include 'plugin2.class.php'; new plugin2; 在哪里 php包含 class core { public function coremethod1(){ echo 'coremethod1';

在学习PHP的过程中,我还遇到了一些问题,PHP是否实现了任何内置插件系统

因此,插件将能够改变核心组件的行为

例如,类似这样的工作方式:

include 'core.class.php';
include 'plugin1.class.php';
include 'plugin2.class.php';
new plugin2;
在哪里 php包含

class core {
  public function coremethod1(){
    echo 'coremethod1';
  }
  public function coremethod2(){
    echo 'coremethod2';
  }
}
class plugin1 extends core {
  public function coremethod1(){
    echo 'plugin1method1';
  }
}
class plugin2 extends plugin1 {
  public function coremethod2(){
    echo 'plugin2method2';
  }
}
plugin1.class.php包含

class core {
  public function coremethod1(){
    echo 'coremethod1';
  }
  public function coremethod2(){
    echo 'coremethod2';
  }
}
class plugin1 extends core {
  public function coremethod1(){
    echo 'plugin1method1';
  }
}
class plugin2 extends plugin1 {
  public function coremethod2(){
    echo 'plugin2method2';
  }
}
plugin2.class.php包含

class core {
  public function coremethod1(){
    echo 'coremethod1';
  }
  public function coremethod2(){
    echo 'coremethod2';
  }
}
class plugin1 extends core {
  public function coremethod1(){
    echo 'plugin1method1';
  }
}
class plugin2 extends plugin1 {
  public function coremethod2(){
    echo 'plugin2method2';
  }
}
这将是理想的,如果不是因为现在插件彼此可靠的问题,并删除其中一个插件:

include 'core.class.php';
//include 'plugin1.class.php';
include 'plugin2.class.php';
new plugin2;
破坏了整件事

有什么合适的方法可以做到这一点吗? 如果没有,他们可能会考虑移到一个支持这一点的不同语言……/P> 谢谢你的帮助

编辑: 显然,这是我的理解是缺乏的,所以这里有一个 试图澄清

php包含任何内容

include 'core.class.php';
include 'plugin1.class.php';
include 'plugin2.class.php';
$core = new core;
$core->coremethod1();//outputs plugin2method1
plugin1.class.php包含任何内容

include 'core.class.php';
include 'plugin1.class.php';
include 'plugin2.class.php';
$core = new core;
$core->coremethod1();//outputs plugin2method1
plugin2.class.php包含任何内容

include 'core.class.php';
include 'plugin1.class.php';
include 'plugin2.class.php';
$core = new core;
$core->coremethod1();//outputs plugin2method1
鉴于:

include 'core.class.php';
include 'plugin2.class.php';
$core = new core;
$core->coremethod1();//outputs plugin1method1
我对任何实现都感兴趣,即使是不涉及类的实现 比如说

include 'core.php';
//does core stuff

include 'core.php';
include 'plugin1';
//does extended core stuff

include 'core.php';
include 'plugin2';
//does extended core stuff


include 'core.php';
include 'plugin2';
include 'plugin1';
//does very extended core stuff
包含文件需要更改应用程序行为。它才有意义


我也不知道这是什么意思,所以请给我指出适当的命名,如果有的话,

核可以用PECL扩展(C++,我相信)扩展。 核心功能可以通过
override\u功能覆盖(如果您安装了APD PECL扩展)

用户函数可以通过调用用户函数执行

如果你能解释一下你的计划,也许我们能提供一个更好的答案?

你误用了“插件”这个术语。插件通常是一个代码包,它扩展或改变系统的基本功能-使实际PHP插件(在PHP世界中称为扩展),您将编写C或C++。 您在这里描述的只是将类或类树包含到当前执行中以供使用。有一种方法可以“自动”将它们引入当前的执行上下文,这就是通过

如果在阅读了有关自动加载的文档后,仍然不确定如何继续,请在此处发表评论,我将帮助您

编辑 好的,我明白你的意思了。你不能完全按照你想要的去做。当您执行
新核心时将返回类
core
的实例-您根本无法修改它

但是,如果您愿意修改如何创建
core
的实例,那么我想我有一些东西可以为您工作,它可能看起来像这样

class core {
  public function coremethod1(){
    echo 'coremethod1';
  }
  public function coremethod2(){
    echo 'coremethod2';
  }

  /**
   * @return core
   */
  final public static function create()
  {
    // listed in order of preference
    $plugins = array( 'plugin2', 'plugin1' );

    foreach ( $plugins as $plugin )
    {
        if ( class_exists( $plugin ) )
        {
          return new $plugin();
        }
    }

    return new self;
  }
}

class plugin1 extends core {
  public function coremethod1(){
    echo 'plugin1method1';
  }
}

class plugin2 extends plugin1 {
  public function coremethod2(){
    echo 'plugin2method2';
  }
}

$core = core::create();

// test what we have
echo get_class( $core ), '<br>'
   , $core->coremethod1(), '<br>'
   , $core->coremethod2()
;
类核心{
公共函数coremethod1(){
回声“coremethod1”;
}
公共函数coremethod2(){
echo‘coremethod2’;
}
/**
*@返回核心
*/
最终公共静态函数create()
{
//按优先顺序列出
$plugins=array('plugin2','plugin1');
foreach($plugins作为$plugin)
{
如果(类_存在($plugin))
{
返回新的$plugin();
}
}
回归新自我;
}
}
类plugin1扩展了内核{
公共函数coremethod1(){
echo“pluginMethod1”;
}
}
类plugin2扩展了plugin1{
公共函数coremethod2(){
echo“plugin2方法2”;
}
}
$core=core::create();
//测试我们所拥有的
echo获取类($core),“
” ,$core->coremethod1(),“
” ,$core->coremethod2() ;
您的代码正在中断,因为plugin2扩展了plugin1,而您没有包括plugin1类。为什么不让类plugin2扩展核心呢?这似乎就是你想要的

如果您唯一担心的是不包括plugin1会产生错误,那么您可以求助于自动加载,让plugin2自动加载plugin1:

但是,如果您正在寻找类似traits/mixin的特性,那么答案是否定的。PHP目前还不支持这种特性。至少,您不希望在生产代码中使用API

更改对象在运行时的行为方式的正确方法是使用:

或模式:

$class = new Basic;
$class->setStrategy(function() { return 'foo'} );
echo $class->callStrategy(); // foo
$class->setStrategy(function() { return 'bar'} );
echo $class->callStrategy(); // bar
有关最常见的模式,请参见


编辑下面是一个如何使用装饰器创建插件的示例。假设,我们有一个类似的游戏,其中一些非玩家角色在虚拟空间中走动,不时与主角打招呼。这就是他们现在所做的。不过,我们希望他们的问候方式有所不同,这就是为什么在这个场景中我们需要我们的插件/装饰器

首先,我们定义了一些能够问候的对象应该具有的方法。我们不关心在特定对象上调用这些方法时它会做什么。我们只想确保这些方法可用,并且使用明确定义的输入调用它们:

interface GreetInterface
{
    public function greet($name);
    public function setGreeting($greeting);
}
接口基本上是任何实现对象必须履行的契约。在我们的例子中,合同上说,如果你是一个能打招呼的对象,你必须有两种方法。以任何你喜欢的方式实现它们,但是要有这些方法

现在让我们构建非玩家角色类,实现这个接口

class Dude implements GreetInterface
{
    protected $greeting = 'hello';
    public function greet($name)
    {
        return sprintf('%s %s', $this->greeting, $name);
    }
    public function setGreeting($greeting)
    {
        $this->greeting = $greeting;
        return $this;
    }
}
我想这是相当严重的。Dude类只是从接口定义了两个方法。调用greet()时,它将获取存储在greeting中的字符串,并将其前置到传递给greet方法的参数。setGreeting方法允许我们在运行时更改问候语。注意:您也可以添加一个getter(我只是懒惰)

现在来看看插件。我们将创建一个抽象的GreetPlugin类来包含一些,因为我们不想在实际的插件中重复代码。抽象插件类将实现GreetInterface,因此我们可以确保所有子类也实现该接口

由于Dude已经实现了接口,我们可以让插件扩展Dude,但这在概念上是错误的,因为扩展创建了is-a关系,但是
echo $regularDude->greet('Yuri'), PHP_EOL,
     $frenchDude->greet('Yuri'), PHP_EOL,
     $easygoingDude->greet('Yuri'), PHP_EOL,
     $frenchEasyGoingDude->greet('Yuri'), PHP_EOL;

// gives

hello Yuri
éllo Yuri
heya Yuri
éya Yuri