PHPackages                             crysalead/filter - 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. crysalead/filter

ActiveLibrary

crysalead/filter
================

Method filtering system

4.0.0(10y ago)931.3k↓26.9%3MITPHPPHP &gt;=5.5

Since Mar 21Pushed 8y ago2 watchersCompare

[ Source](https://github.com/crysalead/filter)[ Packagist](https://packagist.org/packages/crysalead/filter)[ RSS](/packages/crysalead-filter/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependencies (2)Versions (9)Used By (0)

Filter - Method Filtering System.
=================================

[](#filter---method-filtering-system)

[![Build Status](https://camo.githubusercontent.com/3b5b634bff1fef84b6b531179888a1121eab9019e6bd9055e697e0f1d447c2a8/68747470733a2f2f7472617669732d63692e6f72672f63727973616c6561642f66696c7465722e706e673f6272616e63683d6d6173746572)](https://travis-ci.org/crysalead/filter) [![Code Coverage](https://camo.githubusercontent.com/a30a2ba9cfa25e60655173289c94a6f61c7d9751de49622df9b6ea4e6ff7ae58/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f63727973616c6561642f66696c7465722f6261646765732f636f7665726167652e706e673f733d35306233633536626436326536613134633163313562376337663563323635383466663262663761)](https://scrutinizer-ci.com/g/crysalead/filter/)

Method filtering is an alternative to event-driven architectures. It provide a way to inject/override some logic in the program flow without polluting too much the original source code.

There's a couple of different existing approches which try to bring the AOP concepts in PHP:

- [AOP](https://github.com/AOP-PHP/AOP) (PECL extension)
- [li3](https://github.com/UnionOfRAD/lithium)
- [Go!](https://github.com/lisachenko/go-aop-php)

All this approaches aims to provide the following control on methods:

```
        │                ▲
        │                │
 ┌──────┼────────────────┼──────┐
 │      │    Filter 1    │      │
 │      │                │      │
 │ ┌────┼────────────────┼────┐ │
 │ │    │    Filter 2    │    │ │
 │ │    │                │    │ │
 │ │┌───┼────────────────┼───┐│ │
 │ ││   │ Implementation │   ││ │
 │ ││   ▼                │   ││ │
 │ ││                        ││ │
 │ │└────────────────────────┘│ │
 │ └──────────────────────────┘ │
 └──────────────────────────────┘

```

The goal of this AOP library is to bring the simplicity of [li3](https://github.com/UnionOfRAD/lithium) filtering system with a Just In Time code patching technique so any kind of method will be filterable (even vendor's one).

The example
-----------

[](#the-example)

So let's take the following code example:

```
class Home
{
    public static function version()
    {
        return '1.0.0';
    }

    public function enter($name)
    {
        return "Welcome {$name}!";
    }
}
```

At this point it's not possible to change method's behavior like in JavaScript or any other more permissive language. At this point we can make the above method in two ways. First by manually adding some boilerplate code to make your methods filterable or by simply enabling some Just In Time patching which will do the rewriting on the fly.

The manually way
----------------

[](#the-manually-way)

To show how AOP works under the hood, I'll first show how to make a method filterable manually (i.e. without the Just In Time patching).

So to make a method filterable, some boilerplate code is required:

```
namespace City;

use Lead\Filter\Filters;

class Home {

    public static function version()
    {
        Filters::run(get_called_class(), __FUNCTION__, [], function($next) {
            return '1.0.0'; // Your inchanged code here
        });
    }

    public function enter($name)
    {
        Filters::run($this, __FUNCTION__, [$name], function($next, $name) {
            return "Welcome {$name}!"; // Your inchanged code here
        });
    }
}
```

The idea is to wrap the method logic in a closure and prepend a mandatory `$next` parameter in the parameter list. `$next` represents the chain of filters to apply and will be used in filters to execute the next appliable filter.

Once the code rewrited, it's now possible to setup filters:

```
use Lead\Filter\Filters;

Filters::apply('city\Home', 'version', function($next) {
    $version = $next();
    return "Version: {$version}";
});

$home = new Home();
Filters::apply($home, 'enter', function($next, $name) {
    $name = "Mister {$name}";
    return $next($name);
});

echo "You are using the Home " . Home::version();
echo $home->enter('Bob');
```

And it will produce:

```
You are using the Home Version 1.0.0
Welcome Mister Bob

```

The automatic way
-----------------

[](#the-automatic-way)

For the automatic way, we are going to use a JIT code patcher to make this rewriting step automatic and transparent for the user.

This is done using `Filters::patch()`. The patcher must be initialized as soon as possible for example just after the composer autoloader include:

```
include __DIR__ . '/../vendor/autoload.php';

use Lead\Filter\Filters;

Filters::patch(true);
```

Note: patching works for classes loaded by the composer autoloader. If a class is included using `require` or `include` or has already been loaded before the `Filters::patch(true)` call, it won't be patched.

Using `Filters::patch(true)` is the no brainer way to setup the patcher but you should keep in mind that all your code as well as your vendor code will be patched. Even if patched classes are cached once patched, having all methods wrapped inside a filter closure can be time consuming.

So the prefered approach is to only patch needed files:

```
Filters::patch([
 'City\Home',
 'An\Example\ClassName::foo',
 'A\Second\Example\ClassName' => ['foo', 'bar'],
]);
```

It's therefore possible to makes your own methods filterable as well as vendor methods.

It's also possible to configure the cached path like the following:

```
Filters::patch([
 'City\Home',
 'An\Example\ClassName::foo',
 'A\Second\Example\ClassName' => ['foo', 'bar'],
], [
    'cachePath' => __DIR__ . '/../cache/jit',
]);
```

Note: make sure apache will be able to write in your cache folder.

API
---

[](#api)

### Make a method filterable

[](#make-a-method-filterable)

Either manually with:

```
Filters::run($context, $method, $args, $closure);
```

Or automatically:

```
Filters::patch(['City\Home']);
```

### Apply a filter to a class or an instance

[](#apply-a-filter-to-a-class-or-an-instance)

```
$id = Filters::apply($context, $method, $closure);
```

### Detach a filter from a class or an instance

[](#detach-a-filter-from-a-class-or-an-instance)

Detach all filters associated to a callable:

```
Filters::detach($context, $method);
```

Detach a specific filter only:

```
Filters::detach($id);
```

### Export/Restore the filtering system.

[](#exportrestore-the-filtering-system)

Getter:

```
$filters = Filters::get();
```

Setter:

```
Filters::set($filters);
```

### Clearing the registred closure &amp; applied filters.

[](#clearing-the-registred-closure--applied-filters)

```
Filters::reset();
```

Note: It also detaches all filters attached statically (i.e it doesn't affect filters on intance's methods).

### Enable/Disable the filter system globaly

[](#enabledisable-the-filter-system-globaly)

```
Filters::enable(); // Enable
Filters::enable(false); // Disable
```

Note: It doesn't detach any filters but simply bypasses filters on `Filters::run()`.

FAQ
---

[](#faq)

- **Is it possible to apply a filter for all instances ?** Yes, for such behavior, you need to set your filter using the class name string as context.
- **If sub class inherit from filters setted at a parent class level ?** Yes.

###  Health Score

36

—

LowBetter than 82% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity35

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity63

Established project with proven stability

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

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

Every ~47 days

Recently: every ~20 days

Total

8

Last Release

3745d ago

Major Versions

1.1.2 → 2.0.02015-12-06

2.0.0 → 3.0.02016-01-17

3.0.1 → 4.0.02016-02-15

PHP version history (2 changes)1.0.0PHP &gt;=5.4

3.0.0PHP &gt;=5.5

### Community

Maintainers

![](https://www.gravatar.com/avatar/67c78f317fdfb9f077b1f16c88193192f7562e999c536b25943b759c3b5099fb?d=identicon)[jails](/maintainers/jails)

---

Top Contributors

[![jails](https://avatars.githubusercontent.com/u/1306941?v=4)](https://github.com/jails "jails (19 commits)")

---

Tags

aopaspectaspect programmingmethod filtering

### Embed Badge

![Health badge](/badges/crysalead-filter/health.svg)

```
[![Health](https://phpackages.com/badges/crysalead-filter/health.svg)](https://phpackages.com/packages/crysalead-filter)
```

###  Alternatives

[ocramius/proxy-manager

A library providing utilities to generate, instantiate and generally operate with Object Proxies

5.0k82.4M230](/packages/ocramius-proxy-manager)[goaop/framework

Framework for aspect-oriented programming in PHP.

1.7k4.0M33](/packages/goaop-framework)[antecedent/patchwork

Method redefinition (monkey-patching) functionality for PHP.

45118.7M35](/packages/antecedent-patchwork)[friendsofphp/proxy-manager-lts

Adding support for a wider range of PHP versions to ocramius/proxy-manager

1.2k139.1M104](/packages/friendsofphp-proxy-manager-lts)[ray/di

Guice style dependency injection framework

1992.0M67](/packages/ray-di)[goaop/goaop-laravel-bridge

Integration bridge for Go! AOP framework

9420.6k](/packages/goaop-goaop-laravel-bridge)

PHPackages © 2026

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