Hooks
What are hooks?
Kirby fires a bunch of events when important things happen in the background. For example when a page is being created or deleted or a file gets uploaded. You can hook into those events and add your own functions that will be executed when those events happen.
Hooks are not restricted to Panel events, but are implemented everywhere: hooks are called no matter if an event happens in the Panel, on the command line or in your own scripts.
Kirby provides two variants of each hook: before
and after
hooks.
Before
hooks
A before
hook is triggered before an action is executed, i.e. before a page is actually updated, a file uploaded, a route called etc.
Typical use cases for before
hooks include:
- Throw an error to prevent certain users from executing an action in general or under certain circumstances.
- Store information in the session.
- Log something before an action is executed.
- …
After
hooks
An after
hook is triggered right after the action was executed. Some typical use cases for these hooks are:
- Automatically resize a huge image and save a smaller version instead.
- Modify user entered information when a user saves the page.
- Log something when an action is executed.
- …
Hooks can execute code, but you can't return anything from them or redirect anywhere. If you try to, an error is thrown in the Panel.
Available events
Registering hooks
Hooks can be registered in your config.php
or in plugins:
In your config
return [
'hooks' => [
'page.delete:before' => function ($page) {
// do something before a page gets deleted
}
]
];
In a plugin
In a plugin, hooks are registered with the hooks
extension. The extension accepts an array of key/value pairs where the key is the event and the value a function with the code that should be executed before or after an event.
Kirby::plugin('your/plugin', [
'hooks' => [
'page.delete:before' => function ($page) {
// do something before a page gets deleted
},
'page.create:after' => function ($page) {
// do something after the page was created
}
]
]);
Wildcard hooks
If you want to register the same hook for multiple events, you can register a wildcard hook (either in your config or in a plugin):
return [
'hooks' => [
'page.*:before' => function ($page) {
// do something before something happens with a page
}
]
];
The following wildcards are supported (in this example for an event type.action:state
):
type.*:state
,type.action:*
,type.*:*
,*.action:state
,*.action:*
,*:state
,*
Depending on where you put the wildcard *
, your hook will receive all events that match the wildcard name.
If you only want to react on some, but not all matched events, you can filter inside the hook with the $event
object:
return [
'hooks' => [
'page.*:before' => function ($event, $page) {
// check if we want to handle the action
if (in_array($event->action(), ['create', 'delete']) !== true) {
// no, return early
return;
}
// do something before a page gets created or deleted
}
]
];
You can read more about the $event
object below.
Accessing $kirby
, $site
and $user
in a hook callback
You get full access to the current Kirby instance and its API with $this
in a hook callback.
$kirby = $this;
$site = $this->site();
$user = $this->user();
$username = $this->user()->username();
$role = $this->user()->role();
Hook arguments
Kirby provides the hook arguments by variable name, not by position (similar to controllers). This allows you to request just the arguments you need in any order. All arguments that are not available will be passed as null
:
return [
'hooks' => [
'route:after' => function ($result, $path) {
// this hook only cares about these two arguments
}
]
];
There is also a special $event
argument that contains all information about the event, including the full event name, its individual parts (type, action and state) and all named hook arguments:
return [
'hooks' => [
'page.create:before' => function ($event) {
$name = $event->name(); // 'page.create:before'
$type = $event->type(); // 'page'
$action = $event->action(); // 'create'
$state = $event->state(); // 'before'
$page = $event->page(); // $page
$input = $event->input(); // $input
}
]
];
Error Handling
You can react on errors in a hook callback by throwing an Exception. The error message will be displayed in the Panel.
Kirby::plugin('your/plugin', [
'hooks' => [
'page.update:after' => function ($newPage, $oldPage) {
throw new Exception('Page Updated');
},
'page.create:after' => function ($page) {
throw new Exception('Page Created');
},
]
]);
Creating your own hooks
You can also define your own custom hook types in plugins, which works just like with the built-in hooks:
Kirby::plugin('your/plugin', [
'hooks' => [
'your-plugin.your-hook' => function ($page) {
// do whatever you need
},
]
]);
As you can see, only the name of the hook has changed. Please make sure to namespace your hooks by including the plugin name in the hook name. Otherwise your hooks might conflict with other plugins or future built-in hooks.
You can trigger your own hooks from anywhere in the system with the $kirby->trigger()
and $kirby->apply()
methods.
The two main use-cases for custom hooks are communication between two plugins (one plugin triggers an event and another registers a hook to listen for it) and hooks that are registered from the site config to allow users to add custom behavior to plugins.