PHP基于父类的现有实例创建子类的新实例
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PHP基于父类的现有实例创建子类的新实例相关的知识,希望对你有一定的参考价值。
我知道这将是一个奇怪的,所以我会尽量简短明了。
我正在为Grav制作一个插件。我已经确定,实现我的目标的最有效方法是扩展其中一个基类Pages。
结构看起来像这样:
- index.php创建一个grav类的实例。
- Base grav类创建Pages类的实例并将其存储为服务。
- 在grav类完成它的加载过程之后,index.php告诉grav在它的服务处理程序上运行进程。
- PagesProcessor在存储的Pages类上运行init()函数。
- Pages Processor触发一个事件,指示页面已初始化。
- 插件接收事件。
实际上这看起来像什么。
- 的index.php
$grav = Grav::instance( array( 'loader' => $loader ) );
- 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); }; }
- 的index.php
try { $grav->process(); }
- Grav.php
public function process() { foreach ($this->processors as $processor) { $processor = $this[$processor]; ..... $processor->process(); ..... } ..... }
- 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']])); ..... }
- 最后,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基于父类的现有实例创建子类的新实例的主要内容,如果未能解决你的问题,请参考以下文章