jgswift/kfiltr

PHP 5.5+ filtering pattern implementation

0.1.2 2014-09-11 04:10 UTC

This package is not auto-updated.

Last update: 2024-04-17 23:45:23 UTC


README

PHP 5.5+ filtering pattern implementation

Build Status Scrutinizer Code Quality Latest Stable Version License Coverage Status

Installation

Install via cli using composer:

php composer.phar require jgswift/kfiltr:0.1.*

Install via composer.json using composer:

{
    "require": {
        "jgswift/kfiltr": "0.1.*"
    }
}

Description

Kfiltr provides a set of generic traits that handle filtering, mapping, and hooking in a domain-agnostic way.
Interfaces are also provided to broadly describe the intended implementation, however they are required to use this package.

Dependency

  • php 5.5+

Usage

Filters

A minimal Filter example. The execute method does not enforce any particular signature and may define whatever arguments needed

<?php
class MyFilter implements kfiltr\Interfaces\Filter {
    use kfilter\Filter;

    function execute() {
        return func_get_arg(0);
    }
}

$filter = new MyFilter();

var_dump($filter('foo')); // returns 'foo'

Delegate

Effectively a filter is the same except that filters can be bypassed by a custom callable.

<?php
$filter = new MyFilter();
$filter->setDelegate(function() {
    return 'bar';
});

var_dump($filter('foo')); // returns 'bar'

Mappers

Similar to the Filter approach above, the Mapping approach is used specifically for populating already instantiated objects with input data Using a mapper requires jgswift/qtil

<?php

class MyFactory {
    use qtil\Factory;
}

class MyMapper {
    use kfiltr\Mapper;

    function __construct(MyFactory $factory) {
        $this->setFactory($factory);
    }

    // do stuff to map object here.
    function map($input,$object) {
        return $object;
    }
}

class MyMiscClass {

}

$mapper = new MyMapper(new MyFactory());

$object = $mapper([],'MyMiscClass');

var_dump($object); // returns blank MyMiscClass object

If no map method is provided then a default mapping callback will be used. The default mapping callback assumes that input is an array and object is an object respectively.

Hooks

To assist filter processing, a standard hook implementation is provided. Hooks are containers for multiple filters that typically run sequentially. Hooks may also be filters, but are not by default. In the example below, the hook will iterate over and perform all contained filtering operations.

<?php
// the same filter class from above
class MyFilter implements kfiltr\Interfaces\Filter {
    use kfilter\Filter;

    function execute() {
        return func_get_arg(0);
    }
}

class MyHook implements kfiltr\Interfaces\Filter, kfiltr\Interfaces\Hook {
    use kfiltr\Hook, kfiltr\Filter;

    // this will execute all filters in order and return an array containing all results
    function execute() {
        $filters = $this->getFilters();

        $results = [];
        if(!empty($filters)) {
            foreach($filters as $filter) {
                $results[] = call_user_func_array($filter,func_get_args());
            }
        }

        return $results;
    }
}

$filter = new MyFilter();

$hook = new MyHook();

$hook->addFilter($filter);

var_dump($hook('foo')); // returns [ 0 => 'foo' ]

Factory Filter/Mapper

Filter

Using this filter requires jgswift/qtil

Factory filters make objects using a class map. Arguments are passed to the constructor

namespace Creatures {
    class Animal { 
        function __construct($species) { /* ... */ }
    }

    class Human extends Animal {
        function __construct($ethnicity) { /* ... */ }
    }
}

class MyFilter {
    use kfiltr\Factory\Filter;
}

// specific class names keyed by an id
$mapping = [
    'animal' => 'Creatures\Animal',
    'human' => 'Creatures\Human'
];

$filter = new MyFilter(); // create filter
$filter->setMapping($mapping); // apply mapping

$animal = $filter(['cat'],'animal'); // create animal
$human = $filter(['polish'],'human');// create human

var_dump(get_class($animal));   // Creatures\Animal
var_dump(get_class($human));    // Creatures\Human

Mapper

This filter makes object using a factory and maps the properties using kfiltr\Mapper. Arguments are mapped and the constructor must be empty for mapped classes. To map objects with non-empty constructors, a custom factory is required. Using this filter requires jgswift/qtil

namespace Creatures {
    class Animal { 
        function __construct($species) { /* ... */ }
    }

    class Human extends Animal {
        function __construct($ethnicity) { /* ... */ }
    }
}

class MyFactory {
    use qtil\Factory;
}

class MyMapper {
    use kfiltr\Factory\Mapper;
}

$mapping = [
    'animal' => 'Creatures\Animal',
    'human' => 'Creatures\Human'
];

$mapper = new MyMapper();
$mapper->setFactory(new MyFactory);
$mapper->setMapping($mapping);

$caucasian = $mapper(['ethnicity'=>'caucasian'],'human');
$indian = $mapper(['ethnicity'=>'indian'],'human');
$elephant = $mapper(['species'=>'elephant'],'animal');

var_dump($caucasian->ethnicity);
var_dump($indian->ethnicity);
var_dump($elephant->species);