Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

method chain hijacking

Tags:

php

This isn't a real fluent interface. I have an object which builds up a method stack. Which gets executed by a single function call. But now I might add another virtual method, which "takes over" that method stack.


Use case: I'm wrapping my superglobals into objects. This allows me to "enforce" input filtering. $_GET and co provide simple sanitizing methods. And my new version now allows chaining of atomic filters. As example:

$_GET->ascii->nocontrol->text["field"]

This is a method call. It uses angle brackets. But that's just a nice trick which eases rewriting any occourence of $_GET["field"]. Anyway.

Now there are also occasionally forms with enumerated fields, as in field[0],field[1],field[2]. That's why I've added a virtual ->array filter method. It hijacks the collected method stack, and iterates the remaining filters on e.g. a $_POST array value. For example $_POST->array->int["list"].

Somewhat shortened implementation:

function exec_chain ($data) {
    ...
    while ($filtername = array_pop($this->__filter)) {
    ...
        $data = $this->{"_$filtername"} ($data);
    ...
}

function _array($data) {
    list($multiplex, $this->__filter) = array($this->__filter, array());
    $data = (array) $data;
    foreach (array_keys($data) as $i) {
        $this->__filter = $multiplex;
        $data[$i] = $this->exec_chain($data[$i]);
    }
    return $data;
}

The method stack gets assembled in the $this->__filter list. Above exec_chain() just loops over it, each time removing the first method name. The virtual _array handler is usually the first method. And it simply steals that method stack, and reexecutes the remainder on each array element. Not exactly like in above example code, but it just repeatedly repopulates the original method stack.

It works. But it feels kind of unclean. And I'm thinking of adding another virtual method ->xor. (YAGNI?) Which would not just iterate over fields, but rather evaluate if alternate filters were successful. For example $_REQUEST->array->xor->email->url["fields"]. And I'm wondering if there is a better pattern for hijacking a function list. My current hook list ($this->__filter) swapping doesn't lend itself to chaining. Hmm well actually, the ->xor example wouldn't need to iterate / behave exactly like ->array.

So specifically, I'm interested in finding an alternative to my $this->__filter list usage with array_pop() and the sneaky swapping it out. This is bad. Is there a better implementation scheme to executing a method list half part me -> half part you?

like image 721
mario Avatar asked Nov 06 '22 08:11

mario


1 Answers

I've made a similar chaining interface before, I like your idea of using it on GET/POST vars.

I think you will be better off doing something like

$var->array->email_XOR_url;
rather than
$var->array->email->XOR->url;
. That way you can catch the various combinations with your __get/__call magic.
like image 146
bobdiaes Avatar answered Nov 09 '22 04:11

bobdiaes