Skip to main content
drupalreleases

Use direct release data with your AI assistant.

Learn more

Hux

Security covered Under active development 623 sites

Hux allows developers to implement Drupal hooks using classes and methods tagged with attributes, eliminating the need for .module files. This approach provides the benefits of dependency injection and class-driven logic for hook implementations, and allows for multiple implementations of the same hook.

Read the blog post: A modern alternative to Hooks

Hux is a project specifically designed for developers, allowing hook implementations without needing to define a .module file or any kind of proxy class/service features.

There are a few projects out there that try to introduce an event subscriber driven way of working. Hux is an in between solution, allowing the full benefits of dependency injection and class driven logic without going fully in with events.

Hooks are implemented with classes, wherein methods tagged with attributes are used for discovery. Methods have the same parameter/return signature as original hook implementations. Discovery is automatic, requiring a cache clear for each new class added.

You can also define multiple of the same hook per module!

Requires Drupal 9.4 or later, and PHP 8.0 or later. (Drupal 9.3 users may use a patch in #2616814: Delegate all hook invocations to ModuleHandler)

Usage Examples (See README.md for more)


declare(strict_types = 1);

namespace Drupal\my_module;

use Drupal\hux\Attribute\Alter;
use Drupal\hux\Attribute\Hook;
use Drupal\hux\Attribute\ReplaceOriginalHook;

/**
 * Usage examples.
 */
final class MyModuleHooks {

  public function __construct(
    // Autowiring is enabled.
    // \Drupal\Core\DependencyInjection\ContainerInjectionInterface, or manual service definitions are available for older Drupal installs or usage of non-autowirable services.
    private readonly \Drupal\Component\Datetime\TimeInterface $time,
  )

  #[Hook('entity_access')]
  public function myEntityAccess(EntityInterface $entity, string $operation, AccountInterface $account): AccessResultInterface {
    // A barebones implementation.
    return AccessResult::neutral();
  }

  #[Hook('entity_access', priority: 100)]
  public function myEntityAccess2(EntityInterface $entity, string $operation, AccountInterface $account): AccessResultInterface {
    // You can set priority if you have multiple of the same hook!
    return AccessResult::neutral();
  }

  #[Hook('entity_access', moduleName: 'a_different_module', priority: 200)]
  public function myEntityAccess3(EntityInterface $entity, string $operation, AccountInterface $account): AccessResultInterface {
    // You can masquerade as a different module!
    return AccessResult::neutral();
  }

  #[ReplaceOriginalHook(hook: 'entity_access', moduleName: 'media')]
  public function myEntityAccess4(EntityInterface $entity, string $operation, AccountInterface $account): AccessResultInterface {
    // You can override hooks for other modules! E.g \media_entity_access()
    return AccessResult::neutral();
  }


  #[ReplaceOriginalHook(hook: 'entity_access', moduleName: 'media')]
  public function myEntityAccess5(EntityInterface $entity, string $operation, AccountInterface $account, #[OriginalInvoker] callable $originalInvoker): AccessResultInterface {
    // If you override a hook for another module, you can have the original
    // implementation passed to you as a callable!
    $originalResult = $originalInvoker($entity, $operation, $account);
    // Do something...
    return AccessResult::neutral();
  }

  #[Alter('user_format_name')]
  public function myCustomAlter(string &$name, AccountInterface $account): void {
    $name .= ' altered!'; 
  }

  #[
    Hook('entity_insert'),
    Hook('entity_delete'),
  ]
  public function myEntityInsertOrDelete(EntityInterface $entity): void {
    // Associate with multiple!
    // Also works with Alters and Replacements.
  }

}

Contribution tips

Only Merge Requests are accepted. Patches are not accepted.

Tests use a customized Gitlab template with custom PHP Code Sniffer and PHPStan ruleset. You can fix these issues by running linting locally or wait for errors after pushing your work to an MR.

Similar projects

Versions

  • 1.1.x is compatible with Drupal 9 and 10.
  • 1.2.x, Drupal ^10.0
  • 1.3.x, Drupal ^10.1
  • 1.4.x, Drupal ^10.2
  • 1.5.x, Drupal ^10.3
  • 1.6.x, Drupal ^10.3 || ^11
  • 1.7.x, Drupal 11.0 minimum
  • 1.8.x, Drupal 11.1 minimum

Actual constraints may vary. Older incompatible releases may match an untested version of core.

Drupal 11 · not 10

Ask your assistant about Hux

Check compatibility with your Drupal and PHP version, maintenance and security coverage, from current release data. How it works

Depends on

Dependencies of the latest stable release

No dependencies recorded for this project.

Required by

2 tracked projects depend on this one

Activity

Tracked releases
25
Tracked since
Feb 2023
Latest release
1 year ago
Releases (12 mo)
0 ▼ from 5
Maintenance
Dormant

Release Timeline

Releases

Version Type Core PHP Release date
1.2.2 Stable 10–11 PHP 8.1 Nov 28, 2023
1.2.1 Stable 10–11 PHP 8.1 Sep 28, 2023
1.2.0 Stable 10–11 PHP 8.1 Aug 22, 2023
1.2.0-rc1 Pre-release 10–11 PHP 8.1 Feb 28, 2023
1.2.x-dev Dev 10–11 PHP 8.1 Feb 28, 2023