PHPackages                             crazycodr/data-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. [Utility &amp; Helpers](/categories/utility)
4. /
5. crazycodr/data-filter

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

crazycodr/data-filter
=====================

Used to filter out data from an enumerable source using more flexible patterns than the filter iterator spl class

2.0.2(12y ago)2151MITPHP

Since Jul 20Pushed 12y agoCompare

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

READMEChangelog (5)Dependencies (2)Versions (6)Used By (0)

[![Latest Stable Version](https://camo.githubusercontent.com/2f09796289a18792e3fa2671dd7cdbce796ac48019666e907d47160a50c58908/68747470733a2f2f706f7365722e707567782e6f72672f6372617a79636f64722f646174612d66696c7465722f76657273696f6e2e706e67)](https://packagist.org/packages/crazycodr/data-filter) [![Total Downloads](https://camo.githubusercontent.com/3eb92a4ba2935466457361d5c3f25b285b010393d6926bff4e38bcbebf247ff0/68747470733a2f2f706f7365722e707567782e6f72672f6372617a79636f64722f646174612d66696c7465722f646f776e6c6f6164732e706e67)](https://packagist.org/packages/crazycodr/data-filter) [![Build Status](https://camo.githubusercontent.com/6d64d2eec182d3fb2e20e6a5344f8e3df4d17644ab62a296fee20502df95fc4a/68747470733a2f2f7472617669732d63692e6f72672f6372617a79636f64722f646174612d66696c7465722e706e673f6272616e63683d6d6173746572)](https://travis-ci.org/crazycodr/data-filter)CrazyCodr/Data/Filter
===============================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================

[](#--crazycodrdatafilter)

This package contains facilities to easily filter live iterated data from any enumerable source.

This class features a filtering iterator accompagnied by different filters/filter groups that you can use to filter incoming data from any iteratable data-source. With this class package, you can create simple or complex groups of filters and filters an even be modified on the fly because it is an iterator over an iterator.

Table of contents
-----------------

[](#table-of-contents)

1. [Installation](#installation)
2. [Creating a basic filtering iterator](#creating-a-basic-filtering-iterator)
3. [Supporting many filters at once](#supporting-many-filters-at-once)
4. [Building complex filtering groups](#building-complex-filtering-groups)
5. [Using components outside of the iterator context](#using-components-outside-of-the-iterator-context)
6. [Creating your own testable classes](#creating-your-own-testable-classes)

Installation
------------

[](#installation)

To install it, just include this requirement into your composer.json

```
{
    "require": {
        "crazycodr/data-filter": "2.*"
    }
}
```

And then run composer install/update as necessary.

Creating a basic filtering iterator
-----------------------------------

[](#creating-a-basic-filtering-iterator)

Creating a filtering iterator requires at least three items:

1. A FilterGroup used to contain the different filters for your iterator
2. A FilterIterator used to iterate your data and provide filtering features
3. A Filter used to detect if the current data should be kept or discarded from the iteration

(Note: This code assumes that you have an array based datasource with columns: Name, Type, Sex and Age)

```
//Create the male only filter
$maleOnlyFilter = new ClosureFilter(function($a){ return $a['sex'] == 'male'; });
$sexBasedFilter = new FilterIterator(new FilterGroup(), $data);
$sexBasedFilter->addFilter($maleOnlyFilter);

//Iterate our data source and automatically only get males
foreach($sexBasedFilter as $employee)
{
	echo 'Employee: '.$employee['name'].'';
}
```

Supporting many filters at once
-------------------------------

[](#supporting-many-filters-at-once)

The library supports multiple filters at once and will also respect the short-circuiting pattern. (A condition is only fully evaluated if necessary)

In this case, we have to switch the FilterGroup to "ANY" mode or else nothing will go through.

```
//Create the male only filter and the "female is called julie"
$maleOnlyFilter = new ClosureFilter(function($a){ return $a['sex'] == 'male'; });
$julieFemalesOnlyFilter = new ClosureFilter(function($a){ return $a['sex'] == 'female' && $a['name'] == 'Julie'; });
$sexBasedFilter = new FilterIterator(new FilterGroup(FilterGroup::CONTAINER_TYPE_ANY), $data);
$sexBasedFilter->addFilter($maleOnlyFilter);
$sexBasedFilter->addFilter($julieFemalesOnlyFilter);

//Iterate our data source and automatically only get males or females called Julie
foreach($sexBasedFilter as $employee)
{
	echo 'Employee: '.$employee['name'].'';
}
```

Building complex filtering groups
---------------------------------

[](#building-complex-filtering-groups)

Last example showed us a closure filter that add many conditions. What if you want to explode that or combine many different closure filters in groups and sub groups such as:

- MaleOf30OrLess
    - Male Only
    - 30 or less
- FemaleOf30OrMore
    - Female Only
    - 30 or more

```
//Setup the basic filters
$maleOnlyFilter = new ClosureFilter(function($a){ return $a['sex'] == 'male'; });
$femalesOnlyFilter = new ClosureFilter(function($a){ return $a['sex'] == 'female'; });
$age30OrLess = new ClosureFilter(function($a){ return $a['age'] = 30; });

//Setup the groups
$fullMaleFilter = new FilterGroup();
$fullFemaleFilter = new FilterGroup();
$fullMaleFilter->addFilter($maleOnlyFilter);
$fullMaleFilter->addFilter($age30OrLess);
$fullFemaleFilter->addFilter($femalesOnlyFilter);
$fullFemaleFilter->addFilter($age30OrMore);

//Create the master filter
$sexBasedFilter = new FilterIterator(new FilterGroup(FilterGroup::CONTAINER_TYPE_ANY), $data);
$sexBasedFilter->addFilter($fullMaleFilter);
$sexBasedFilter->addFilter($fullFemaleFilter);

//Iterate our data source and automatically only get males of 30 or less or females of 30 or more
foreach($sexBasedFilter as $employee)
{
	echo 'Employee: '.$employee['name'].'';
}
```

The important aspect to remember is that, by default, FilterGroups are "ALL" groups and must be changed to "ANY" groups when necessary.

Using components outside of the iterator context
------------------------------------------------

[](#using-components-outside-of-the-iterator-context)

You don't need to use a filtering iterator... The ClosureFilter and FilterGroup can be used outside of a loop. Build conditions normally using concrete/non-concrete classes and call "shouldKeep" with some data.

```
//Create the male only filter and the "female is called julie"
$maleOnlyFilter = new ClosureFilter(function($a){ return $a['sex'] == 'male'; });
$julieFemalesOnlyFilter = new ClosureFilter(function($a){ return $a['sex'] == 'female' && $a['name'] == 'Julie'; });
$filter = new FilterGroup(FilterGroup::CONTAINER_TYPE_ANY);
$filter->addFilter($maleOnlyFilter);
$filter->addFilter($julieFemalesOnlyFilter);

if($filter->shouldKeep($data))
{
	//Do something
}
```

Creating your own testable classes
----------------------------------

[](#creating-your-own-testable-classes)

The point of this library is not to have to create the iterators and they sub-components each time and be able to test the lot easily. To this end, simply create concrete extensions of your iterators and sub-components and then test them.

```
class MaleOnlyFilter extends ClosureFilter
{
	public function __construct()
	{
		parent::__construct(new ClosureFilter(function($a){ return $a['sex'] == 'male'; }));
	}
}
```

```
class FemaleOnlyFilter extends ClosureFilter
{
	public function __construct()
	{
		parent::__construct(new ClosureFilter(function($a){ return $a['sex'] == 'female'; }));
	}
}
```

```
class SexBasedFilterIterator extends FilterIterator
{
	public function __construct($data)
	{
		parent::__construct(new FilterGroup(), $data);
		$this->addFilter(new MaleOnlyFilter());
		$this->addFilter(new FemaleOnlyFilter());
	}
}
```

It might look extreme but this way you are creating a concrete functional class that can be reused and tested. Note that DataProviders are a great way to test your components but it will look strange to use a DataProvider when testing the iterators.

```
class MaleOnlyFilterTest extends PHPUnit_Framework_TestCase
{

	/**
	* @dataProvider maleOnlyFilterDataProvider
	*/
	public function testShouldKeep($data)
	{
		$filter = new MaleOnlyFilter();
		$this->assertEquals($data['expected'], $filter->shouldKeep($data['testdata']));
	}

	public function maleOnlyFilterDataProvider()
	{
		return array(
			array(
				'expected' => true,
				'testdata' => array('name' => 'John doe', 'age' => 35, 'sex' => 'male'),
			),
			array(
				'expected' => false,
				'testdata' => array('name' => 'Jone doe', 'age' => 30, 'sex' => 'female'),
			),
		);
	}

}
```

###  Health Score

29

—

LowBetter than 60% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity13

Limited adoption so far

Community2

Small or concentrated contributor base

Maturity67

Established project with proven stability

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 ~8 days

Total

5

Last Release

4645d ago

Major Versions

1.1 → 2.02013-07-27

### Community

Maintainers

![](https://www.gravatar.com/avatar/a264166a26f76e0a35c096552dc773f8d90d8e1180bd65013234d9f42c021ff0?d=identicon)[crazycodr](/maintainers/crazycodr)

###  Code Quality

TestsPHPUnit

### Embed Badge

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

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

###  Alternatives

[adigital/cookie-consent-banner

Add a configurable cookie consent banner to the website.

1150.7k](/packages/adigital-cookie-consent-banner)[michaels/data-manager

Simple data manager for nested data, dot notation array access, extendability, and container interoperability.

121.9k2](/packages/michaels-data-manager)

PHPackages © 2026

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