I have a complex web app, where special plugins are created for user groups. Eg Admin, Editor all have their groups. Each of these groups has its own tasks and customized forms in processing one saved entry, often with a different layout / elements.
It has worked great so far. But now we have one new request from the client, their special customer needs a completely different or customized flow, which is not compatible with the existing MVC structure. This means that in one user group we have to add some functionality from other groups, also change templates, validation, relations.
In this case we do the overriding template via an additional plugin, but how about the override controller and the model?
For example: When we call example.com/editor/articles/add the plugin Editor has its own MVC, for a special customer, the Editor should use the MVC from the SpecialEditor plugin.
How to override the existing MVC?
You can override controller via routes:
// routes.php or Application::routes()
$routes->plugin('Editor', function (RouteBuilder $routes) {
// Routes connected here are prefixed with '/debug-kit' and
// have the plugin route element set to 'DebugKit'.
$routes->connect('/articles/add', ['plugin' => 'SpecialEditor', 'controller' => 'Articles', 'action' => 'add']);
});
Inside the ArticlesController
of the SpecialEditor
plugin you can load a new model (eg extend original model) and also have the template inside that plugin too.
Also, if you only have to override the controller and not the model, set the modelClass
namespace SpecialEditor\Controller;
class ArticlesController
{
public $modelClass = "Editor.Articles";
}
1 Like
I’m sorry, but it doesn’t work.
You cannot define routes that conflict with the scope. Scope had plugin = Editor, while route had plugin = SpecialEditor
The question still applies, how to override the controller with another. Is there a similar method as when override a template?
It would be ideal if we could switch plugins for the user but keep the same url.
I have tried this
in the plugin’s src/Plugin.php
public function routes(RouteBuilder $routes): void
{
parent::routes($routes);
$params = ['controller' => 'ExportTypes', 'plugin' => 'MyPlugin'];
$routes->scope('/export-types', $params, function (RouteBuilder $builder) {
$builder->connect('/', ['action' => 'index']);
});
// ....
}
in the app config/routes.php
$routes->prefix('api', function (RouteBuilder $builder) {
$builder->scope('/export-types', ['plugin' => false, 'controller' => 'ExportTypes'], function (RouteBuilder $builder) {
$builder->connect('/', ['action' => 'index']);
});
$builder->fallbacks();
});
bin/cake routes
output:
+--------------------------------+--------------------+----------------------------------------------------------------------------------+
| Route name | URI template | Defaults |
+--------------------------------+--------------------+----------------------------------------------------------------------------------+
| api:0.exporttypes:index | /api/export-types | {"action":"index","controller":"ExportTypes","plugin":false,"prefix":"Api"} |
| api:myplugin.exporttypes:index | /api/export-types | {"action":"index","controller":"ExportTypes","plugin":"MyPlugin","prefix":"Api"} |
+--------------------------------+--------------------+----------------------------------------------------------------------------------+
I used the api
prefix since I only use as a rest backend, but should work without it
1 Like