Product Lifecycle Hooks

2 vues Markdown

The eight hooks over creating, updating, deleting and switching a product.

Overview

A product travels three steps: it is created, updated and deleted. Each has a gate you can stop at in front of it and an event that reports it behind.

Two status hooks sit beside them. The single one fires per product; the bulk one fires once when an action reaches many products from the list.

Reference

Stopping a product being created

gateproduct.create
AdminProducts before the write

Runs before a new product is created.

Parameters 2
$inputarrayThe form input: type, group, category, name, module and address.
$statearrayContext: the group keys, the default currency and the language keys.
Return 1
string|nullA non-empty text blocks the operation and is shown to the administrator as the error. An empty return lets it carry on.
Listener
Hook::add('gate:product.create', 10, function ($input, $state) {
    if (!Acme::namingOk($input['name'] ?? '')) return 'The product name breaks the naming rule.';

    return null;
});

Following a product being created

actionproduct.created
AdminProducts zero means it failed

Runs after a product is created.

Parameters 2
$new_idintThe id of the new product. ? A zero means no product was created. A listener that uses the id straight away then works on a record that is not there.
$inputarrayThe creation input: type, group, category, name, module and address.
Return 1
voidThe return is ignored.
Listener
Hook::add('action:product.created', 10, function ($new_id, $input) {
    // ZERO = no product was created.
    if (!$new_id) return;

    Acme::registerCatalogItem($new_id, $input['name'] ?? '');
});

Stopping a product update

gateproduct.update
AdminProducts before and after in hand

Runs before a product is updated. You hold both the new data and the old record, so you can compare what changed.

Parameters 3
$idintThe product id.
$inputarrayThe new data about to be written.
$detailarrayThe record as it was before the change.
Return 1
string|nullA non-empty text blocks the operation and is shown to the administrator as the error. An empty return lets it carry on.
Listener
Hook::add('gate:product.update', 10, function ($id, $input, $detail) {
    // You hold both records: measure the difference.
    if (($detail['module'] ?? '') !== ($input['module'] ?? '') && Acme::hasLiveServices($id))
        return 'The module cannot change while live services run on it.';

    return null;
});

Following a product update

actionproduct.updated
AdminProducts before and after in hand

Runs after the product is updated.

Parameters 3
$idintThe product id.
$inputarrayThe full edit input: pricing, languages, module data and resource limits.
$detailarrayThe record from before the update.
Return 1
voidThe return is ignored.
Listener
Hook::add('action:product.updated', 10, function ($id, $input, $detail) {
    Acme::syncCatalog($id, $input, $detail);
});

Stopping a product deletion

gateproduct.delete
AdminProducts before the write

Runs before a product is deleted.

Parameters 2
$idintThe id of the product to be deleted.
$detailarrayThe product record: type, module and group.
Return 1
string|nullA non-empty text blocks the operation and is shown to the administrator as the error. An empty return lets it carry on.
Listener
Hook::add('gate:product.delete', 10, function ($id, $detail) {
    if (Acme::hasLiveServices($id)) return 'Live services still run on this product.';

    return null;
});

Following a product deletion

actionproduct.deleted
AdminProducts after deletion

Runs after the product is deleted.

Parameters 2
$product_idintThe id of the deleted product.
$detailarrayIts last state. The record is gone: take what you need from here.
Return 1
voidThe return is ignored.
Listener
Hook::add('action:product.deleted', 10, function ($product_id, $detail) {
    Acme::dropCatalogItem($product_id);
});

Following a product status change

actionproduct.status_changed
AdminProducts one product

Runs when a product is opened for sale or closed.

Parameters 2
$product_idintThe product id.
$statusstringThe new state: active or inactive.
Return 1
voidThe return is ignored.
Listener
Hook::add('action:product.status_changed', 10, function ($product_id, $status) {
    Acme::setCatalogVisible($product_id, $status === 'active');
});

Following a bulk action

actionproduct.bulk_action_applied
AdminProducts one call, many products

Runs when an action is applied to several products at once from the list. Unlike the single status event, this is one call, not one per product.

Parameters 2
$actionstringThe action applied: active or inactive.
$idsarrayThe ids of the products handled.
Return 1
voidThe return is ignored.
Listener
Hook::add('action:product.bulk_action_applied', 10, function ($action, $ids) {
    // One call, many products: the single status event does not fire here.
    Acme::bulkVisibility($ids, $action === 'active');
});

Pitfalls

A zero in the create event means it failed

The new product id can arrive as zero, which means no product was created. A listener that uses the id straight away then works on a record that is not there. Check it on the first line.

A bulk action does not raise the single status event

When an action reaches many products from the list, only the bulk event fires. Work hung on the single status hook never runs on that path; listen on both.

Cet article vous a-t-il été utile ?

Merci pour votre retour !

Besoin d'aide supplémentaire ?

Notre équipe d'assistance est disponible 24h/24 pour tout ce que vous ne trouvez pas ci-dessus.