PHPackages                             tombroucke/wp-fluent-hooks - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. tombroucke/wp-fluent-hooks

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

tombroucke/wp-fluent-hooks
==========================

A small utility package that provides a modern, fluent interface for adding WordPress action and filter hooks. Chain methods to build your hooks in a more expressive and readable way.

1.0.0(1mo ago)1133PHP &gt;=8.0

Since May 11Compare

[ Source](https://github.com/tombroucke/wp-fluent-hooks)[ Packagist](https://packagist.org/packages/tombroucke/wp-fluent-hooks)[ RSS](/packages/tombroucke-wp-fluent-hooks/feed)WikiDiscussions Synced 3w ago

READMEChangelogDependencies (5)Versions (3)Used By (0)

WP Fluent Hooks
===============

[](#wp-fluent-hooks)

A fluent interface for registering and deregistering WordPress filters and actions. Instead of repeating the hook name across multiple `add_filter()` and `remove_filter()` calls, you chain everything together. This makes your hook logic easier to read and maintain.

```
// Before
remove_filter('woocommerce_before_shop_loop', 'woocommerce_result_count', 20);
remove_filter('woocommerce_before_shop_loop', 'woocommerce_catalog_ordering', 30);

// After
Action::hook('woocommerce_before_shop_loop')
    ->deregister('woocommerce_result_count', 20)
    ->deregister('woocommerce_catalog_ordering', 30);
```

Examples
--------

[](#examples)

### Filters

[](#filters)

```
Filter::hook('the_title')
    ->register(fn ($title) => strtoupper($title));
```

With priority and argument count:

```
Filter::hook('save_post')
    ->register(function ($postId, $post, $update) {
        // Do something
    }, priority: 11, args: 3);
```

### Actions

[](#actions)

`Action` and `Filter` share the same API and can be used interchangeably.

```
Action::hook('init')
    ->register(function () {
        // Do something
    });
```

### Deregistering

[](#deregistering)

Deregister external hooks by passing the callback name and priority inline:

```
Action::hook('woocommerce_before_shop_loop')
    ->deregister('woocommerce_result_count', 20)
    ->deregister('woocommerce_catalog_ordering', 30);
```

Chain deregistering and registering on the same hook. Use chainable methods `priority()` and `args()` to set values for the rest of the chain:

```
Action::hook('woocommerce_before_main_content')
    ->priority(20)
    ->deregister('woocommerce_breadcrumb')
    ->register(function () {
        yoast_breadcrumb('', '');
    });
```

### Conditional registration

[](#conditional-registration)

Use `when()` to conditionally run a registered callback. The condition receives the same arguments as the filter/action and is evaluated at the time the hook fires

```
Filter::hook('the_title')
    ->when(fn ($title) => strlen($title) > 10)
    ->register(fn ($title) => strtoupper($title));
```

Use `always()` to remove a previously set condition:

```
Filter::hook('the_title')
    ->when(fn ($title) => strlen($title) > 10)
    ->register(fn ($title) => strtoupper($title))
    ->always()
    ->register(fn ($title) => strtolower($title));
```

> `when()` currently cannot be combined with `deregister()`. You will need to find a workaround for now.

### Deferring to another hook

[](#deferring-to-another-hook)

Use `at()` to defer `register()` or `deregister()` until another hook fires. This is useful when the context you need (e.g. the current post, the current page) is not yet available at the time your code runs.

When a plugin or theme nests the actions and filters

```
add_action('template_redirect', function () {
    add_filter('the_title', 'strtoupper');
}, 100);
```

You can

```
Filter::hook('the_title')
    ->at('template_redirect', 101)
    ->deregister('strtoupper');
```

### Aliases

[](#aliases)

Only hooks registered with an alias are tracked internally. Without an alias, the hook is registered with WordPress but cannot be deregistered via this library. Assign an alias to reference a hook registered via this library:

```
Action::hook('body_class')
    ->alias('my_custom_body_class')
    ->register(fn ($classes) => array_merge($classes, ['custom-class']));

// Later:
Action::hook('body_class')
    ->deregister('my_custom_body_class');
```

###  Health Score

41

—

FairBetter than 87% of packages

Maintenance93

Actively maintained with recent releases

Popularity17

Limited adoption so far

Community2

Small or concentrated contributor base

Maturity40

Maturing project, gaining track record

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

35d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/4178291ccf36e3530aa8a8845124c3af1b24c064739ad98ded5b9679a4316033?d=identicon)[tombroucke](/maintainers/tombroucke)

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/tombroucke-wp-fluent-hooks/health.svg)

```
[![Health](https://phpackages.com/badges/tombroucke-wp-fluent-hooks/health.svg)](https://phpackages.com/packages/tombroucke-wp-fluent-hooks)
```

###  Alternatives

[kunststube/rison

A PHP encoder and decoder for Rison, the compact JSON-like data format optimized for URIs.

2468.8k3](/packages/kunststube-rison)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
