[php /alg] stackable filters

Pagina: 1
Acties:

Onderwerpen


  • Suepahfly
  • Registratie: Juni 2001
  • Laatst online: 17-09 17:05
Ik zit met het volgende:
Ik wil een filter mechanisme maken waarmee ik meerdere filters op een waarde kan loslaten op een makkelijke manier.

Als ik bij voorbeeld een string als 'numb3rs_()_#' wil ik alleen het 'numb3rs' deel overhouden. Uiteraard wil ik ook kunnen filteren op andere criteria. De huidige implementatie rammelt aan alle kanten en de logica is ver te zoeken. Even wat pseudo code
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
function filter($var, $filters)
{
    $filters = eplode(":", $filter);
    $n = count($filter);
    $tmpArray = array();
    for($i=0; $i<$n; $i++)
    {
        if(is_callable($filters[$i]))
        {
            $tmpArray[] = call_user_func($var, "filter_" . $filters[$i);
        }
    }
    $now = time()
    $var = implode("<|" . crc32($now) . "|>", $tmpArray);
    $var = str_replace("<|" . $now . "|>", $var);
    return $var;
}


/* Helper functies */

function filter_alpha($var)
{
    // Verwijder alles behalve letters
}

function filter_num($var)
{
    // verwijder alles behalve nummers
}


/* Aanroep als volgt*/
$var = filter($var, "alpha:num");


Je hoeft geen expert te zijn om te zien dat dit niet werk, ik heb de code nog niet eens gebruikt maar ik iets als 'numb3rs_()_#' zal waarschijnlijk terug komen als 'numbrs3' of '3numbrs' (afhankelijk hoe je de functie aanroept) en niet 'numb3rs'

Hoewel het voorbeeld makkelijk met een regex is op te lossen zoek ik toch wat meer functionaliteit en wil de code natuurlijk ook in meerdere projecten kunnen gebruiken.

Enige input wordt dan ook gewaardeerd

[ Voor 0% gewijzigd door Suepahfly op 14-09-2006 22:40 . Reden: TR voor titel is al verzonden ]


Acties:
  • 0 Henk 'm!

Verwijderd

Ben niet thuis in PHP, maar je "pseudo-code" kon ik aardig lezen... ;)
Hoe je op resultaten als 'numbrs3' of '3numbrs' uitkomt met jouw code is me een raadsel, want na het 'alpha' filter is die '3' al verdwenen. En als 'ie er nog was geweest had 'ie nooit op een andere plek terecht mogen komen. Je resultaat zou overigens altijd op een lege string uitkomen (num wordt aangeroepen na alpha, en dan staan er al geen cijfers meer in $var).

Als ik goed begrijp wat je wil, zoek je een filter functie waar je diverse filters op los kunt laten, maar dan op de OR manier.
Ik zou dan in je hoofdfunctie (filter) een array van booleans aanmaken die net zo lang is als $var, en die in eerste instantie allemaal op false zetten. Die array geef je dan ook mee aan je helper functies, en die mogen dan per karakter bepalen of ze door het filter komen, en zo ja dan de bijbehorende boolean op true zetten.
Aan 't eind return je dan alleen de karakters waarvan de bijbehorende boolean true is.

Acties:
  • 0 Henk 'm!

  • MBV
  • Registratie: Februari 2002
  • Laatst online: 20-09 22:44

MBV

Zoek eens op het decorator-pattern, dat is voor dit soort dingen gemaakt. Of je bedoelt iets anders dan lijkt, wat Afterlife suggereert :)

Acties:
  • 0 Henk 'm!

Verwijderd

Je bent de heilige graal van uitbreidbaarheid aan het najagen op een plek waar dat helemaal niet van toepassing is.

Kijk hoe je je "filters" aanroept:

PHP:
1
$var = filter($var, "alpha:num");


Jij wilt dat dit betekent: "Laat alleen alpha's en nummers door".

Dat valt wel te regelen, maar alleen op zo'n manier dat je filter functies alleen nog gebruikt kunnen worden om karakters uit de invoerstring te verwijderen. Namelijk, wat als je straks een "filter" introduceert om alle kleine letters in hoofdletters te veranderen; en we noemen die even "upper".

Wat betekent dan het volgende volgens jou?

PHP:
1
$var = filter($var, "alpha:upper");


Dit is volledig betekenisloos geworden. Ja, je kan wel zeggen, dit betekent "laat alleen letters en hoofdletters door" (in de praktijk dus gewoon alle letters), maar dan ben je nog steeds alleen karakters aan het filteren, en geen geavanceerdere transformaties aan het uitvoeren.
Hoewel het voorbeeld makkelijk met een regex is op te lossen zoek ik toch wat meer functionaliteit en wil de code natuurlijk ook in meerdere projecten kunnen gebruiken.
Het punt is juist dat je op deze manier geen andere functionaliteit dan alleen karakters filteren kunt implementeren. Ja, het kán natuurlijk wel, maar dan krijg je straks codebrij zonder enige logica.

Karakters filteren kun je het beste met een regex doen. Ik weet niet wat voor "meer functionaliteit" je in gedachten had, maar ik zou alvast anders beginnen.

De term "filter" wordt meestal gebruikt voor een functie die invoer accepteert, op een bepaalde manier transformeert (bijvoorbeeld door er karakters uit te filteren) en het resultaat teruggeeft. Sja, en in de praktijk worden dat gewoon functieaanroepen:

PHP:
1
$var = filter_upperCase(filter_alphaNumeric($var));


Al kun je het natuurlijk ook declaratief doen, afhankelijk van de rest van de code die je gebruikt (zie HTML_QuickForm in PEAR):

PHP:
1
2
$form->addFilter("myField", "filter_alphaNumeric");
$form->addFilter("myField", "filter_upperCase");

[ Voor 26% gewijzigd door Verwijderd op 15-09-2006 16:47 ]


Acties:
  • 0 Henk 'm!

  • MBV
  • Registratie: Februari 2002
  • Laatst online: 20-09 22:44

MBV

bij het decorator-pattern krijg je dus zoiets:
code:
1
2
3
$basic_filter = new basic_filter();
$basic_and_advanced_filter = new advanced_filter($basic_filter);
$output = $basic_and_advanced_filter->parse($input);

Decorator wordt vooral veel gebruikt voor gui's, maar lijkt me hier ook toepasbaar. Alhoewel ik me afvraag of je niet beter met een regex aan de slag kunt gaan :)