Hooks, Slots & Registry
Actions (Events)
Fire after state changes. Payloads are scalars/arrays only — never models or requests.
// Register an action
$this->ctx->hooks->addAction('order.paid', function (int $orderId, array $meta): void {
// React to order payment
});
// Fire a custom action
plugin_do_action('myplugin.order_processed', $orderId, $data);
Common Core Actions
| Hook | Payload | When |
|---|---|---|
user.registered | $userId, $data | New user signs up |
user.login | $userId, $data | User logs in |
order.paid | $orderId, $data | Order payment confirmed |
order.completed | $orderId | Order marked complete |
wallet.deposit.completed | $historyId, $data | Wallet deposit confirmed |
subscription.activated | $subscriptionId | Subscription activated |
proposal.rejected | $jobId, $freelancerId, $clientId | Proposal rejected |
Filters (Value Transformation)
Input value in, transformed value out.
// Register a filter
$this->ctx->hooks->addFilter('checkout.price.calculate',
fn(float $price, array $ctx = []): float => $price * 0.95 // 5% discount
);
// Apply a filter
$value = plugin_apply_filters('myplugin.data', $default, $context);
Common Core Filters
| Hook | Transform | Context |
|---|---|---|
checkout.price.calculate | float price | order_kind, freelancer_id, client_id |
user.create_data | array of fillable data | User registration |
job.create_data | array of fillable data | Job creation |
menu.primary_items | array of menu items | Navbar rendering |
seo.meta_title | string title | Page rendering |
payment.complete | array result | IPN verification |
Slots (HTML Injection Points)
Named render points with context arrays.
// Register a slot renderer
$this->ctx->slots->register('checkout.coupon_field', 'my-plugin.coupon',
fn(array $context): string => '<input name="coupon_code" placeholder="Coupon">'
);
// Render a slot (called by core)
$output = plugin_render_slot('checkout.coupon_field', ['order_id' => $id]);
Available Slots
| Slot | Context | Location |
|---|---|---|
checkout.coupon_field | — | Checkout page |
order.success_after | order_id | Order success page |
order.details_after | order_id, role | Order details page |
job.proposal_box_after | job_id | Job details page |
project.offer_box_after | project_id | Project details page |
profile.completion | user_id, role | Profile completion |
dashboard.referral_panel | role, user_id | User dashboard |
admin.dashboard_widgets | — | Admin dashboard |
admin.order_details_after | order_id | Admin order details |
admin.user_details_after | user_id | Admin user details |
Registry (Structured Contributions)
Generic priority-ordered registry for typed domains.
// Register an entry
$this->ctx->registry->register('admin.menu', 'my-plugin', [
'label' => 'My Plugin',
'route' => '/admin/my-plugin',
'icon' => 'fa-solid fa-star',
'permissions' => 'my-plugin-manage',
]);
// Get all entries for a domain
$all = $this->ctx->registry->all('admin.menu');
// Check if entry exists
$exists = $this->ctx->registry->has('gateway', 'mygateway');
Registry Domains
| Domain | Entry Shape |
|---|---|
gateway | id, label, module, ipn_route, settings_prefix, enabled_option |
checkout.adjuster | id, label, adjust: callable |
admin.menu | label, route, icon, permissions |
dashboard.menu | label, route, icon, roles |
widget | title, render: callable |
auth.provider | id, label, redirect, callback |
Last updated: September 2026
Still stuck?
Our support team is ready to help you get set up.

