PHP基于父类

时间:2018-06-13 02:42:01

标签: php inheritance plugins instance grav

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

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

结构看起来像这样:

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

实际上看起来像这样。

  1. 的index.php

    $grav = Grav::instance(
        array(
            'loader' => $loader
        )
    );
    
  2. Grav.php

    protected static $diMap = [
        .....
        'pages' => 'Grav\Common\Page\Pages',
        'pagesProcessor' => 'Grav\Common\Processors\PagesProcessor',
        .....
    ];
    
    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...
    }
    
  7. 哇......好的。

    现在我想要做的是扩展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技巧。

    所以......想法?

    修改 ------------------------

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

2 个答案:

答案 0 :(得分:0)

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

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

这样,我可以执行任何操作而无需覆盖Page类。

答案 1 :(得分:0)

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