Maslosoft Framework Documentation
Flexible Application Foundation
Controller Action Aspects
Basics
The action aspects allows execution of additional code for an action if it has aspect attached. Using aspects allows developing maintainable and reusable code that can be executed around controller actions. The aspect itself is a class implementing particular interface - nothing magic here. The interface names are self-explanatory and have only one method to implement.
The list of interfaces for controller actions in the execution order:
One aspect implementation can implement several interfaces, so that it can react on several points of execution.
Creating Action Aspect
To create new aspect for controller actions, implement one of forementioned interfaces.
For example let's create Aspect which will
add extra CSS class to body
for certain actions.
We could as well add in action function body,
or wrap it with some function and call it for each
action. However it is not really related to action
logic, but only adds extra processing to action.
By using aspects, the extra processing is separated
from action code literally.
class Wider implements BeforeRenderInterface
{
const CssClass = 'wide-backend';
public function beforeRender(Controller $controller = null, array $data = null)
{
Head::fly()->bodyCssClasses[] = self::CssClass;
}
}
Using Action Aspect
To use aspect on action, add @Aspect
annotation
on desired action with parameter of class
name of aspect. Class literal is recommended,
allowing import and use of short name in annotation.
The extra @see
doc tag is used to keep use statements by IDE's
class MyController extends Controller
{
/**
* @Aspect(Wider)
* @see Wider
*/
public function actionView()
{
// Action logic
$this->render('my-view');
}
}
In such setup the beforeRender
method will be called
after executing action logic, but before rendering output
to the browser.
Using on all actions
Adding annotation on each action of controller would break DRY principle. Another option to apply aspect to all actions simply place same aspect on class declaration docblock.
/**
* @Aspect(Wider)
* @see Wider
*/
class MyController extends Controller
{
public function actionView()
{
// Action logic
$this->render('my-view');
}
}
In setup like in the code snippet above, the Wider
aspect
will be applied for each controller action. This brings two
benefits:
- The code is not repeated
- Each newly added action will have aspect too
The drawback is that currently it is not possible to remove
aspect for selected actions. However this limitation can be mitigated
by creating apposite aspect. For instance Narrower
, which would revert
the Wider
aspect settings in our example.
The aspects for before/after action/render are evaluated by calling the type (class) aspect, then the particular action aspects are being applied.
Add @see
doctag to instruct your IDE
to keep use statements.
Built-in Controller Aspects
Class Name | Documentation |
---|---|
DontReturn |
The DontReturn aspect will instruct controller to not return to such action after authentication. This can be used to prevent certain actions to redirect back after successful sign in, for instance when action serves image - this will prevent redirecting to image instead of page. |
NoIndex |
Use |
Printing |
Use printing aspect to instruct framework to switch rendering for printer friendly mode. Use of this aspect implies |
TryToConvert |
|
TryToImprove |
|
WideBackend |
Use this aspect to allow wider user interface. This
aspect will enable The full behavior might be defined with CSS rules of active theme. |