In order to build an extendable blogging system with CakePHP I’d like to realize something like extension hooks in Wordpress. My plan is to have a base SQL to load the articles in the main application. This SQL should be possible to extend by a variable set of plugins (one plugin for each special article type).
I already know that CakePHP’s way to realize something like that is the events system. I have some trouble registering listeners residing in my plugins, though.
The official documentation (3.x Book; http://book.cakephp.org/3.0/en/core-libraries/events.html#registering-listeners) says, that a listener can be registered this way:
// Attach the UserStatistic object to the Order's event manager
$statistics = new UserStatistic();
$this->Orders->eventManager()->on($statistics);
Unfortunately it doesn’t tell where to place this code in order to register the listener automatically while bootstrapping. Placing the following lines in my plugin’s bootstrap.php
like so:
$tester = new Lib\Tester();
$this->Orders->eventManager()->on($tester);
… (having a class Tester
in plugins/MyPlugin/src/Lib
of course) results in errors.
In the first line the listener class cannot be found (“Error: Class 'Lib\Tester' not found”
). And in the second line $this
must not be used in the context of bootstrap.php
(“Error: Using $this when not in object context”
).
In an old thread (Where to register event listeners) someone else asked for the same thing and got a pretty detailed answer. It was for CakePHP 2.x, though, and doesn’t work with CakePHP 3.x anymore. For example, the function App::uses
doesn’t exist in CakePHP 3.x and I couldn’t find a replacement.
So: can someone please help me find the right way to set up a working listener within a plugin in CakePHP 3.x?
[UPDATE #1]
I've found a workaround that works for me (but is quite ugly). In the bootstrap.php
of the plugin I was able to instantiate an object of my event listener class like this:
require __DIR__ . '/../src/Lib/Tester.php';
$tester = new MyPlugin\Lib\Tester();
After that I could register the listener on the Articles model (also in bootstrap.php
of course):
Cake\ORM\TableRegistry::get('Articles')->eventManager()->on($tester);
That way I'm now able to build up a base request on the articles table and send it to several plugins. Then the plugins can enrich the request to join special tables or something like that.
So, one question remains: how can I avoid the use of the __DIR__
in bootstrap.php
? How can the listener be instantiated properly?
[UPDATE #2]
It seems as if the complete src
subdirectory of my plugin isn't part of the import path. None of the classes I put there gets loaded. That means that CakePHP doesn't find a simple Controller when I place one there.
Am I doing something wrong in general? Or might that be a bug in CakePHP?
Unfortunately I neither can find plugins for CakePHP 3.x whose source code could help me understand what I might do wrong.