Posiadam klasę HFilters:
<?php class HFilters { private $aFilterList = http://www.php.net/array(); private $oContext; public function __construct(& $oContext) { $this->oContext = & $oContext; } public function add(iFilter $oFilter, $iPreWeight = 10, $iPostWeight = 10) { $this->aFilterList[] = $oFilter; } public function pre() { foreach($this->aFilterList as $oFilter) { $oFilter->pre($this->oContext); } } public function post() { foreach($this->aFilterList as $oFilter) { $oFilter->post($this->oContext); } } } ?>
<?php interface iFilter { public function pre($oContext); public function post($oContext); } ?>
Proste.
Zamiast HFilters::aFilterList daj HFilters::aPreFilterList i HFilters::aPostFilterList. Potem przy wrzucaniu daj:
<?php // ... public function add(iFilter $oFilter, $iPreWeight = 10, $iPostWeight = 10) { $this->aPreFilterList[$iPreWeight] = $oFilter; $this->aPostFilterList[$iPostWeight] = $oFilter; // Tutaj posortuj tak jak Ci wygodnie } // ... ?>
<?php abstract class AbstractFilter implements Filter class PreFilter extends AbstractFilter class PostFilter extends AbstractFilter class FilterChain implements Filter ?>
Nie sprawdzi się jeśli ustawimy dla dwóch filtrów taką samą wagę, jeden nadpisze drugi.
Implementacja wcale nie jest taka prosta. Ponieważ klucz musi być unikalny, czyli można by to rozwiązać poprzez dodanie iteracyjnego przyrostku, ale to powoduje, że musimy ustalić zakres. Jeśli to będzie liczba złożona z jednej cyfry to mamy ograniczenie do 10 pozycji tylko.
Przy okazji Twój przykład kopiuje dwukrotnie ten sam obiekt. Rozwiązałem całość w następujący sposób.
<?php class HFilters { /** Filters objects list. */ private $aFilters = http://www.php.net/array(); /** Pre methods order. */ private $aPreOrder = http://www.php.net/array(); /** Post methods order. */ private $aPostOrder = http://www.php.net/array(); /** Context objects. */ private $oContext; public function __construct($oContext) { $this->oContext = & $oContext; } public function add(iFilter $oFilter, $iPreWeight = 10, $iPostWeight = 10) { $this->aFilters[] = $oFilter; $this->aPreOrder[] = $iPreWeight; $this->aPostOrder[] = $iPostWeight; } public function pre() { http://www.php.net/asort($this->aPreOrder); foreach($this->aPreOrder as $iKey => $iWeight) { $this->aFilters[$iKey]->pre($this->oContext); } } public function post() { http://www.php.net/asort($this->aPostOrder); foreach($this->aPostOrder as $iKey => $iWeight) { $this->aFilters[$iKey]->post($this->oContext); } } } ?>
(PHP5 naprawdę już nie jest takie ułomne jeśli chodzi o obiekty )
<?php class testClass { public $property = 10; } $testObject = new testClass(); $array1 = http://www.php.net/array(); $array1[] = $testObject; $array2 = http://www.php.net/array(); $array2[] = $testObject; $array1[0]->property = 20; http://www.php.net/echo $array2[0]->property; ?>
Rozwiązanie takich filtrów jak dla mnie jest trochę mało wygodne. Ja rozwiązuję to o wiele wygodniej i filtry mają większe możliwości. Mianowicie filtr implemetuje interface z jedną metodą - execute która przyjmuje jako argument $filterChain'a z publiczną metodą next() która wykonuje następny filtr. Kod zapisany przed wykonaniem metody next to pre, a po metodzie to post. Proste w działaniu, banalne w implementacji.
<?php interface IFilter { public function execute(IFilterChain $filterChain); } interface IFilterChain { public function addFilter(IFilter $filter); public function http://www.php.net/next(); } class FilterChain implements IFilterChain { public $filters = http://www.php.net/array(); public function addFilter(IFilter $filter){ $this -> filters[] = $filter; } public function http://www.php.net/next(){ if($filter = http://www.php.net/array_shift($this -> filters)){ $filter -> execute($this); } } public function execute(){ $this -> http://www.php.net/next(); } } class AuthFilter implements IFilter { public function execute(IFilterChain $filterChain){ if($auth -> isLoged()){ $this -> http://www.php.net/next(); }else{ http://www.php.net/echo 'zaloguj się'; } } } class ExecutionFilter implements IFilter { public function execute(IFilterChain $filterChain){ //odpalamy aplikacje $filterChain -> http://www.php.net/next(); } } $filterChain = new FilterChain(); $filterChain -> addFilter(new AuthFilter()); $filterChain -> addFilter(new ExecutionFilter()); $filterChain -> execute(); ?>
Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)