Actions and hooks
When building large applications with multiple modules and plugins installed, it might get hard to customize or hook into existing functionalities.
Qore provides actions
and hooks
to make it easier to customize certain features.
Definitions
Action
An action is a simple class that can be executed. For example, you can have an action that retrieves all issues from Gitlab.
Hooks
Hooks are also simple classes that can be executed before (pre hooks
) or after (post hooks
) actions.
Hooks can also be executed before or after other hooks.
For example, you could have a hook that logs something before or after you do an action.
Return values
When actions run, they may optionally return something.
In your post-hooks
, you can use these return values, and even modify it.
Getting started
Let's start by creating an action that retrieves issues from Gitlab:
use Qore\System\Action\Action;
class RetrieveIssuesAction extends Action
{
public function identifier(): string
{
return 'gitlab.retrieve.issues';
}
public function run(): array
{
return [
[
'id' => 'issue1',
],
[
'id' => 'issue2'
]
];
}
}
The identifier is used later to run your action.
You can have multiple actions with the same identifier. The last registered action will always override the other actions.
Registering your action
You can register your action anywhere:
actions()->add(new RetrieveIssuesAction);
Running your action
You can run your action now:
$results = run('gitlab.retrieve.issues');
dd($results); // Array of issues
Hooks
Let's say we want to log something before and after the action is called.
We can define create a pre-hook
:
class BeforeIssuesRetrievedHook extends ActionHook
{
public function identifier(): string
{
return 'gitlab.retrieve.issues.before';
}
public function run()
{
logger('Before issues are retrieved');
}
}
And a post-hook
:
class AfterIssuesRetrievedHook extends ActionHook
{
public function identifier(): string
{
return 'gitlab.retrieve.issues.after';
}
public function run()
{
logger('After issues are retrieved');
}
}
Adding the hooks
You can add your hooks anywhere after the action has been registered:
actions()->add(new RetrieveIssuesAction);
actions()->before('gitlab.retrieve.issues', BeforeIssuesRetrievedHook::class);
actions()->after('gitlab.retrieve.issues', AfterIssuesRetrievedHook::class);
$results = run('gitlab.retrieve.issues');
dd($results);
There should now be 2 new entries in your laravel.log
.
Return values
If we take the previous example, you may notice that the $results
is actually null
now.
This is because our AfterIssuesRetrievedHook
does not return anything.
We can use the return value from the previously called action (or hook):
class AfterIssuesRetrievedHook extends ActionHook
{
// The modified return value from the last hook
private $modifiedValue;
// The original return value from the action
private $originalValue;
public function __construct($modifiedValue, $originalValue)
{
$this->modifiedValue = $modifiedValue;
$this->originalValue = $originalValue;
}
public function identifier(): string
{
return 'gitlab.retrieve.issues.after';
}
public function run()
{
logger('After issues are retrieved');
return array_merge($this->originalValue, [
[
'id' => 'custom issue'
]
]);
}
}
Our $results
is actually the modified value now.
Arguments
Providing arguments
Sometimes you need to provide additional arguments when running your actions:
$results = run('gitlab.retrieve.issues', ['my custom arg' => true]);
In your action you can retrieve these arguments:
class FillMenuAction extends Action
{
public function identifier(): string
{
return 'dev.fill_menu';
}
public function run(): array
{
dd($this->args);
}
}
In your post-hook
you will also retrieve the modified and original values:
class AfterIssuesRetrievedHook extends ActionHook
{
public function __construct($modifiedValue, $originalValue)
{
$this->modifiedValue = $modifiedValue;
$this->originalValue = $originalValue;
}
public function run(): array
{
dd($this->args);
}
}
Pre-hooks will not have the $modifiedValue and $originalValue arguments
Retrieving more action information
Your hooks may modify the return value of the initial action, however sometimes you need the initial value back.
You can retrieve full information by providing true
as the third parameter:
$results = run('gitlab.retrieve.issues', 'some argument', true);
dd($results);
//
array:3 [▼
"original" => array:2 [▶]
"modified" => array:3 [▶]
"arguments" => "some argument"
]