PHP基于父类的现有实例创建子类的新实例

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PHP基于父类的现有实例创建子类的新实例相关的知识,希望对你有一定的参考价值。

我知道这将是一个奇怪的,所以我会尽量简短明了。

我正在为Grav制作一个插件。我已经确定,实现我的目标的最有效方法是扩展其中一个基类Pages。

结构看起来像这样:

  • index.php创建一个grav类的实例。
  • Base grav类创建Pages类的实例并将其存储为服务。
  • 在grav类完成它的加载过程之后,index.php告诉grav在它的服务处理程序上运行进程。
  • PagesProcessor在存储的Pages类上运行init()函数。
  • Pages Processor触发一个事件,指示页面已初始化。
  • 插件接收事件。

实际上这看起来像什么。

  1. 的index.php $grav = Grav::instance( array( 'loader' => $loader ) );
  2. Grav.php protected static $diMap = [ ..... 'pages' => 'GravCommonPagePages', 'pagesProcessor' => 'GravCommonProcessorsPagesProcessor', ..... ]; protected $processors = [ ..... 'pagesProcessor', ..... ]; public static function instance(array $values = []) { if (!self::$instance) { self::$instance = static::load($values); ..... return self::$instance; } protected static function load(array $values) { $container = new static($values); ..... $container->registerServices($container); return $container; } protected function registerServices() { foreach (self::$diMap as $serviceKey => $serviceClass) { ..... $this->registerService($serviceKey, $serviceClass); ..... } } protected function registerService($serviceKey, $serviceClass) { $this[$serviceKey] = function ($c) use ($serviceClass) { return new $serviceClass($c); }; }
  3. 的index.php try { $grav->process(); }
  4. Grav.php public function process() { foreach ($this->processors as $processor) { $processor = $this[$processor]; ..... $processor->process(); ..... } ..... }
  5. PageProcessor.php public function __construct(Grav $container) { $this->container = $container; } public function process() { ..... $this->container['pages']->init(); $this->container->fireEvent('onPagesInitialized', new Event(['pages' => $this->container['pages']])); ..... }
  6. 最后,Plugin.php public static function getSubscribedEvents() { return [ 'onPagesInitialized' => ['onPagesInitialized', 0] ]; } public function onPagesInitialized(Event $event) { // Do things here... }

哇......好的。

现在我想要做的是扩展Pages.php(上面没有列出),以便我可以修改一些没有setter nativly的受保护属性。问题是,没有办法告诉grav使用扩展方法,直到它被启动后。

我总是可以创建我的扩展类的新实例,初始化它,并覆盖现有的实例,但这意味着有效地强制执行两次,这意味着处理时间加倍,这是非常无效的。

我想做的是如下:

Pages.php < - 我不能改变这个:

class Pages
{
    protected $grav;

    protected $instances;

    protected $children;

    protected $routes = [];

    public function __construct(Grav $c)
    {
        $this->grav = $c;
    }
    .....
    public function init()
    {
        .....
        $this->instances = [];
        $this->children = [];
        $this->routes = [];

        $this->buildPages();
    }
    .....

PagesExtended.php < - 我的班级

class PagesExtended extends Pages
{
    public function __construct(Pages $original)
    {
        // set the properties of this class to the original instance
        parent = $original;
    }

    public function setInstances(Array $newInstances){
        $this->instances = $newInstances;
    }
    .....
}

然后在我的Plugin.php中

public function onPagesInitialized(Event $event) {
    // Do things here...
    $this->grav['pages'] = new PagesExtended($event['pages']);
}

我能想到的另一件事就是某种__call技巧。

那么......想法?

编辑 - - - - - - - - - - - -

嗯......我仍然想知道是否可以做到这一点,但事实证明,“冻结”这些服务使他们无法被覆盖......现在不是很开心。

答案

我不知道你真正想要实现什么,但是你的自定义方法必须返回一些东西,并且它们在Twig中使用。

我经常将Page的自定义数据放入页面标题中。在我的插件中,它获取自定义数据($oldHeader = $page->header()),计算内容并将最终结果再次添加到Page对象作为自定义新属性($page->header($newHeader)),然后在Twig中我可以访问并打印出我页面的这些新数据({{ page.header.data_generated_in_plugin }}) )。

这样我可以做任何事情而不会覆盖Page class。

另一答案

事实证明,无论我试图扩展什么类,我在grav环境中尝试做的事情都是不可能的。它永远不能从插件中完成,因为这些类被grav“冻结”了。

以上是关于PHP基于父类的现有实例创建子类的新实例的主要内容,如果未能解决你的问题,请参考以下文章

Java-继承基本知识

类初始化过程

类加载器实例化时的顺序

类加载器实例化时的顺序

面向对象—继承

关于常见继承的几种方法