Skip to content

Events and Hooks

QUIQQER packages use events to react to framework actions and to extension points provided by other packages.

Use events.xml when a package should run PHP code after a setup step, during a request, when a business object changes, or when another package exposes an extension point.

events.xml

Create events.xml in the package root and add one <event> entry per listener.

xml
<?xml version="1.0" encoding="UTF-8"?>
<events>
    <event on="eventName" fire="\Vendor\Package\EventHandler::method"/>
</events>

The on attribute contains the event name. The fire attribute contains the static PHP method that should be called.

Real package shape:

xml
<?xml version="1.0" encoding="UTF-8"?>
<events>
    <event on="onSiteSave" fire="\QUI\Bricks\Events::onSiteSave"/>
    <event on="onSmartyInit" fire="\QUI\Bricks\Events::onSmartyInit"/>
    <event on="onPackageSetup" fire="\QUI\Bricks\Events::onPackageSetup"/>
</events>

Listener Classes

Event listener methods are usually grouped in an EventHandler or EventHandling class inside the package namespace.

php
<?php

namespace Vendor\Package;

use QUI;

class EventHandler
{
    public static function onPackageSetup(QUI\Package\Package $Package): void
    {
        if ($Package->getName() !== 'vendor/package') {
            return;
        }

        // Run package setup logic here.
    }
}

The method signature must match the event that is fired. Check existing event usage before adding a listener because parameters differ between events.

Multiple Listeners

A package can register more than one listener for the same event. This is useful when different setup routines should stay separated.

xml
<events>
    <event on="onPackageSetup" fire="\Vendor\Package\EventHandler::onPackageSetup"/>
    <event on="onPackageSetup" fire="\Vendor\Package\EventHandler::onOtherPackageSetup"/>
</events>

In the listener, guard against unrelated packages or contexts:

php
if ($Package->getName() !== 'vendor/package') {
    return;
}

This pattern is common for setup events because setup can run for different packages.

Priority

Use priority only when the order between listeners matters.

xml
<event on="eventName"
       fire="\Vendor\Package\EventHandler::method"
       priority="20"
/>

If no priority is set, QUIQQER uses the default priority. Most package listeners should not need a custom priority.

Common Event Types

Current packages use events for different extension scenarios:

  • onPackageSetup for setup-time initialization and data preparation.
  • onRequest for request-specific behavior.
  • site and rendering events such as onSiteSave, onSmartyInit, and onOutputParseEnd for content and template integration.
  • package-specific events for domain workflows.
  • template and frontend extension points such as onQuiqqer::template::header::end.
  • migration events such as onQuiqqerMigrationV2 for version-specific migration behavior.

Naming

Use the event name that is already provided by the framework or by the package you integrate with. Do not invent a new event name unless your package also fires that event and documents its parameters.

Package-specific event names should be explicit and namespaced enough to avoid collisions. Current packages use both classic names such as onTransactionCreate and namespaced names such as onQuiqqer::template::header::end.

Error Handling

Listener code runs as part of the operation that fires the event. Keep listeners small and predictable:

  • return early when the listener does not apply to the current context.
  • catch expected exceptions when the event should not abort the whole workflow.
  • log exceptions that need later inspection.
  • avoid expensive work in request-level events unless it is strictly necessary.

Event Names

Event names in events.xml usually start with on, for example onPackageSetup.

When events are fired in PHP, QUIQQER also accepts names without the on prefix. The event dispatcher normalizes packageSetup to onPackageSetup. Use the on... form in events.xml.

Common Core Events

The following events are general platform events that packages can subscribe to. Parameter names describe the values passed to the listener method.

This reference covers global events fired through QUI::getEvents(). Some objects also expose local event dispatchers for object-internal hooks; those are not part of the global package event reference.

Parameters marked with & are passed by reference and can be changed by listeners.

The reference is checked against current global event calls. Older wiki entries are not listed as Core events unless the current runtime fires them. For example, onLogWrite is registered by the optional quiqqer/log package and is not a Core event in the checked source.

System Events

EventTriggered whenParameters
onQuiqqerInitafter the central QUIQQER runtime initialization finishednone
onFireEventbefore another event is dispatched by the global event managerstring $eventName, array $params
onHeaderLoadedafter the runtime header was loadednone
onIconsInitwhen the icon handler is initializedicon handler object
onHtaccessGeneratewhen .htaccess content is generatedstring &$htaccessContent
onPermissionsSetwhen permissions are assigned to a supported permission objectpermission object, permissions array
onQuiqqerSessionStorageInitbefore Symfony session storage is initializedQUI\Session $Session, array &$storageOptions

onFireEvent is useful for diagnostics and generic event coordination. Avoid heavy work in this listener because it runs before every global event dispatch.

Setup Events

EventTriggered whenParameters
onSetupAllBeginwhen the full setup process startsnone
onSetupAllEndwhen the full setup process endssetup output object
onSetupMakeDirectoriesBeginbefore setup creates required runtime directoriesnone
onSetupMakeDirectoriesEndafter setup created required runtime directoriesnone
onSetupMainSystemBeginbefore setup prepares permissions, groups, users, workspaces and login defaultsnone
onSetupMainSystemEndafter setup prepared the main system datanone
onSetupCommunicationBeginbefore setup prepares mail, messages, editor and eventsnone
onSetupCommunicationEndafter setup prepared communication-related systemsnone
onSetupMakeHeaderFilesBeginbefore setup writes runtime header filesnone
onSetupMakeHeaderFilesEndafter setup wrote runtime header filesnone
onSetupPackageSetupBeginbefore setup executes package setup for installed packagesnone
onSetupPackageSetupEndafter setup executed package setup for installed packagesnone

Package And Setup Events

EventTriggered whenParameters
onPackageInstallBeforebefore a package import/install startsQUI\Package\Package $Package
onPackageInstallafter events.xml was imported during package installQUI\Package\Package $Package
onPackageInstallAfterafter package install and optional setup finishedQUI\Package\Package $Package
onPackageConfigSaveafter package configuration values were saved through the settings XML workflowQUI\Package\Package $Package, array $params
onPackageSetupBeginbefore a package setup imports metadata, permissions, events, database XML, locale and settingsQUI\Package\Package $Package
onPackageSetupduring package setup after XML imports and settings processingQUI\Package\Package $Package
onPackageSetupEndafter package setup finishedQUI\Package\Package $Package
onPackageUnInstallwhen a package is uninstalledstring $packageName
onPackageDestroywhen a package is destroyed/removedstring $packageName
onPackageUpdatewhen a package update is executedQUI\Package\Package $Package
onUpdateBeginwhen a system/package update run startsnone
onUpdateEndwhen a system/package update run endsnone
onQuiqqerMigrationV2when the v2 migration console tool runsQUI\System\Console\Tools\MigrationV2 $Tool

Package-specific variants also exist for package lifecycle events. They append the package name to the event, for example onPackageSetup-quiqqer/bricks. The package-specific variants use the same parameters as the base lifecycle event.

Request And Output Events

EventTriggered whenParameters
onRequestduring URL/request rewrite handlingQUI\Rewrite $Rewrite, string $url
onRequestImageNotFoundwhen a requested image/cache URL cannot be resolvedstring $url
onRequestOutputwhen the administration preview output has been parsed and can be changedstring &$content
onRewriteOutputBeginbefore rewrite output is parsedarray $eventData with Rewrite and output
onRewriteOutputafter rewrite output was parsed and assigned to the rewrite objectarray $eventData with Rewrite and output
onQUI::rewriteOutputafter parsed output was assigned to the rewrite objectarray $eventData with Rewrite
onOutputParseBeginbefore QUI\Output parses contentstring &$content
onOutputParseEndafter QUI\Output parsed contentstring &$content
onErrorHeaderShowBeforebefore an error/redirect header is shownint $code, string $url
onErrorHeaderShowAfterafter an error/redirect header is shownint $code, string $url

Template Events

EventTriggered whenParameters
onTemplateSiteFetchwhen a template fetches/renders a siteQUI\Template $Template, QUI\Interfaces\Projects\Site $Site
onTemplateGetSiteTitlewhen the template builds a site titleQUI\Template $Template, QUI\Interfaces\Projects\Site $Site
onTemplateGetHeaderwhen the template builds the document headerQUI\Template $Template
onSmartyInitwhen Smarty is initialized by packages/templates that expose the eventSmarty $Smarty

Project And Site Events

EventTriggered whenParameters
onCreateProjectafter a project was createdQUI\Projects\Project $Project
onDeleteProjectafter a project was deletedstring $projectName
onProjectConfigSaveafter project configuration was savedstring $projectName, array $config, array $params
onProjectRenamedafter a project was renamedevent data array
onProjectSetupBeginbefore project setup startsQUI\Projects\Project $Project
onProjectSetupEndafter project setup endsQUI\Projects\Project $Project
onSiteInitwhen a site object is initializedQUI\Interfaces\Projects\Site $Site
onSiteLoadwhen a site is loadedQUI\Interfaces\Projects\Site $Site
onSiteCheckActivatebefore a site activation is executedQUI\Projects\Site\Edit $Site
onSiteCheckDeactivatebefore a site deactivation is executedQUI\Projects\Site\Edit $Site
onSiteSaveBeforebefore an editable site is savedQUI\Projects\Site\Edit $Site
onSiteSaveafter an editable site was savedQUI\Projects\Site\Edit $Site
onSiteSaveAjaxBeginbefore the backend site-save AJAX handler applies submitted attributesQUI\Projects\Site\Edit $Site
onSiteSaveAjaxEndafter the backend site-save AJAX handler saved and refreshed the siteQUI\Projects\Site\Edit $Site
onSiteDeleteBeforebefore a site delete operation startsint $siteId, QUI\Projects\Project $Project
onSiteDeletewhen a site is deleted`int
onSiteDestroywhen an editable site is destroyed and package-owned site data can be removedQUI\Projects\Site\Edit $Site
onSiteActivatewhen a site is activatedQUI\Projects\Site\Edit $Site
onSiteDeactivatewhen a site is deactivatedQUI\Projects\Site\Edit $Site
onSiteMoveBeforebefore a site is movedQUI\Projects\Site\Edit $Site, int $oldParentId
onSiteMoveafter a site was movedQUI\Projects\Site\Edit $Site, int $parentId
onSiteCreateChildafter a child site was createdint $newId, QUI\Projects\Site\Edit $Parent
onSiteCreateChildEndafter the backend child-site creation AJAX handler saved the new childQUI\Projects\Site\Edit $Child
onSiteGetUrlRewrittenwhen the rewritten site URL is builtQUI\Interfaces\Projects\Site $Site, mixed &$eventResult

Media Events

EventTriggered whenParameters
onMediaSaveBeginbefore a media item is savedQUI\Projects\Media\Item $Item
onMediaSaveafter a media item was savedQUI\Projects\Media\Item $Item
onMediaReplacewhen a media file is replacedQUI\Projects\Media $Media, QUI\Projects\Media\File $File
onMediaActivatewhen a media item/folder is activatedmedia item/folder object
onMediaDeactivatewhen a media item/folder is deactivatedmedia item/folder object
onMediaDeleteBeginbefore a media item/folder is deletedmedia item/folder object
onMediaDeleteafter a media item/folder was deletedmedia item/folder object
onMediaDestroywhen a media item/folder is destroyedmedia item/folder object
onMediaRenamewhen a media item/folder is renamedmedia item/folder object
onMediaCreateSizeCachewhen an image size/cache variant is createdQUI\Projects\Media\Image $ImageItem, image object
onMediaCreateImageHtmlBeginbefore media image HTML is createdevent data array
onMediaCreateImageHtmlafter media image HTML data was preparedarray &$picture

User And Group Events

EventTriggered whenParameters
onUserCreateafter a user was createdQUI\Users\User $User
onUserGetwhen a user cannot be loaded normally and packages may provide a user object`int
onUserGetBySessionwhen the current session user is resolved and packages may provide a user objectnone
onUserGetAvatarwhen a user's avatar image is requested and packages may provide an imageQUI\Users\User $User
onUserLoadwhen a user object is loadedQUI\Users\User $User
onUserSaveBeginbefore a user is savedQUI\Users\User $User
onUserSaveduring user save before database writeQUI\Users\User $User
onUserSaveEndafter a user was savedQUI\Users\User $User
onUserLoginAjaxStartwhen the backend login AJAX handler startsnone
onUserLoginStartwhen login starts and the user id is known or guessed`string
onUserAuthenticatorLoginStartbefore an authenticator starts authentication`string
onUserLoginafter a user successfully logged inQUI\Users\User $User
onUserLoginErrorwhen login fails`string
onUserCliLoginafter successful console loginQUI\Users\User $User
onUserCliLoginErrorwhen console login failsusername, optional exception
onUserLogoutBeginbefore a user logs outQUI\Users\User $User
onUserLogoutafter a user logged outQUI\Users\User $User
onUserChangePasswordBeforebefore a user changes their own passwordQUI\Users\User $User, string $newPassword, string $oldPassword
onUserChangePasswordafter a user changed their own passwordQUI\Users\User $User, string $newPassword, string $oldPassword
onUserSetPasswordafter a user's password was changedQUI\Users\User $User
onUserActivateBeginbefore user activationQUI\Users\User $User, string $code, permission user
onUserActivateafter user activationQUI\Users\User $User, permission user
onUserDeactivatewhen a user is deactivatedQUI\Users\User $User
onUserDisablewhen a user is disabledQUI\Users\User $User
onUserDeletebefore a user is deletedQUI\Users\User $User
onUserExtraAttributeswhen user extra attributes are collectedQUI\Users\User $User, array &$attributes
onUserAddressInitDatawhen user address database data is loaded before it is assigned to the address objectaddress object, array &$data
onUserAddressSaveBeginbefore a user address is savedaddress object, user object
onUserAddressSaveBeforebefore address database data is writtenaddress object, user object, array &$dbData
onUserAddressSaveafter a user address was savedaddress object, user object
onGroupCreateafter a group was createdQUI\Groups\Group $Group
onGroupLoadwhen a group object is loadedQUI\Groups\Group $Group
onGroupSaveBeginbefore a group is savedQUI\Groups\Group $Group
onGroupSaveduring group saveQUI\Groups\Group $Group
onGroupSaveEndafter a group was savedQUI\Groups\Group $Group
onGroupActivatewhen a group is activatedQUI\Groups\Group $Group
onGroupDeactivatewhen a group is deactivatedQUI\Groups\Group $Group
onGroupDeletewhen a group is deletedQUI\Groups\Group $Group
onSetParentwhen a group parent is changedQUI\Groups\Group $Group, new parent group

Administration, AJAX, Cache, And Mail Events

EventTriggered whenParameters
onAdminRequestwhen the administration entry point handles a requestnone
onAdminLoadBeginbefore the administration UI is renderednone
onAdminLoadwhile the administration UI is renderednone
onAdminLoadFooterwhen the administration footer is renderednone
onAdminLoginwhen the administration login page is builtnone
onAdminLoginFooterwhen the administration login footer is renderednone
onAjaxCallBeforebefore an AJAX call is executedevent data array
onAjaxCallafter an AJAX call was executedevent data array
onAjaxResultbefore an AJAX result is returnedmixed &$result
onCacheClearwhen a cache key is clearedstring $key
onCacheClearAllwhen all cache areas are clearednone
onCachePurgewhen cache purge is executednone
onClearCompleteQuiqqerCachewhen the complete QUIQQER cache area is clearednone
onClearSettingsCachewhen settings cache is clearednone
onClearTemplateCachewhen template cache is clearednone
onClearProjectsCachewhen project cache is clearednone
onClearProjectCachewhen one project cache is clearedstring $projectName
onClearGroupsCachewhen group cache is clearednone
onClearUsersCachewhen user cache is clearednone
onClearPermissionsCachewhen permissions cache is clearednone
onClearPackagesCachewhen package cache is clearednone
onClearPackageCachewhen one package cache is clearedstring $packageName
onLongTimeCacheClearwhen a long-term cache key is clearedstring $key
onLongTimeCacheClearCompleteQuiqqerCachewhen the complete QUIQQER long-term cache area is clearednone
onGetPhpMailerInitStartbefore the mail manager initializes a PHPMailer instancenone
onMailerwhen a mailer object is initializedmailer object
onMailerSendInitbefore mail send preparationevent data array or mailer/phpmailer objects
onMailerSendBeginbefore a prepared mail is sentmailer object, PHPMailer object
onMailerSendafter a mail was sentmailer object, PHPMailer object
onMailSendErrorwhen direct mail sending failsmailer object, PHPMailer object, exception
onMailQueueSendErrorwhen queued mail sending failsqueue object, PHPMailer object, exception
onMailQueueErrorwhen queued mail delivery failed and the queue entry remains failedqueue entry array
onQuiqqerConsoleLicencewhen the license console tool needs package-specific license outputstring $packageName
onQuiqqerConsoleLicenceListwhen the license console tool builds the installed package license listarray &$data
onMcpSiteUpdateAttributeswhen MCP site updates build the allow-list of writable site attributesarray &$attributes, QUI\Projects\Site\Edit $Site

Database Events

EventTriggered whenParameters
onDataBaseQueryCreatebefore a database query is built from query parametersdatabase connection object
onDataBaseQueryafter query SQL and prepare data were built, before executiondatabase connection object, query data array
onDataBaseQueryEndafter query execution finished or before a query error is reporteddatabase connection object, query data array, start time, end time
onDataBaseQueryErrorwhen query execution raises a PDO exceptiondatabase connection object, PDO exception, query data array, start time, error time

Package Events

Packages can define their own events. These events must be documented separately from Core events because they only exist when the package that fires them is installed.

Use a namespaced event name when the event belongs to one package or domain, for example onQuiqqer::template::header::end.

Current free package examples:

EventPackageTriggered whenParameters
onQuiqqerBricksCreatequiqqer/bricksafter a brick record was createdint $brickId
onQuiqqerBricksSaveBeforequiqqer/bricksbefore a brick is saved`int
onQuiqqerBricksSavequiqqer/bricksafter a brick was saved and related caches were cleared`int
onQuiqqerBricksBrickDeleteBeforequiqqer/bricksbefore a brick is deletedbrick object
onQuiqqerBricksBrickDeleteAfterquiqqer/bricksafter a brick was deletedint $brickId
onBricksGetAreaByProjectquiqqer/brickswhen available brick areas for a project are collectedbricks manager, QUI\Projects\Project $Project, array &$bricks
onQuiqqerBricksGetBricksByAreaBeginquiqqer/bricksbefore bricks for a site area are resolvedbrick area, site object, array &$result
onQuiqqerBricksGetBricksByAreaEndquiqqer/bricksafter bricks for a site area were resolvedbrick area, site object, array &$result
onQuiqqerMenuIndependentClearquiqqer/menuwhen an independent menu cache is clearedmenu id
onQuiqqerMenuIndependentSavequiqqer/menuafter an independent menu was savedmenu object
onQuiqqerMenuIndependentCreatequiqqer/menuafter an independent menu was createdmenu object
onQuiqqerMenuIndependentDeletequiqqer/menuafter an independent menu was deletedmenu id
onQuiqqerTranslatorPublishquiqqer/translatorafter translations were published and locale cache was refreshednone
onQuiqqerTranslatorUpdatequiqqer/translatorafter a translation value was updated in development modestring $group, string $var, string $packageName, array $data
onQuiqqerTranslatorEditquiqqer/translatorafter a translation value was editedstring $group, string $var, string $packageName, array $data
onQuiqqerTranslatorEditByIdquiqqer/translatorafter a translation value was edited by idint $id, array $data

Packages can also listen to package-specific events from other packages. For example, quiqqer/cache listens to Bricks, Frontend Users, Translator, and Menu events to invalidate caches when those packages change output-relevant data.

Document custom events in the package that fires them. At minimum, document:

  • when the event is fired
  • whether listeners can modify parameters by reference
  • all parameters in order
  • whether listener return values are used

Import Rules

When events.xml is imported:

  • entries without on are ignored
  • entries without fire are ignored
  • priority is optional
  • default priority is 10
  • imported listeners are registered in the QUIQQER event manager

Released under GPL-3.0-or-later.