方法链劫持

method chain hijacking

提问人:mario 提问时间:10/3/2010 最后编辑:mario 更新时间:10/6/2010 访问量:268

问:

这不是一个真正流畅的界面。我有一个对象,它构建了一个方法堆栈。它由单个函数调用执行。但现在我可能会添加另一个虚拟方法,它“接管”该方法堆栈。


用例:我正在将我的超全局变量包装到对象中。这允许我“强制”输入过滤。$_GET 和 CO 提供简单的消毒方法。我的新版本现在允许链接原子过滤器。例如:

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

这是一个方法调用。它使用尖括号。但这是一个很好的技巧,可以简化重写 .无论如何。$_GET["field"]

现在偶尔也会有带有枚举字段的表单,如 field[0],field[1],field[2]。这就是我添加虚拟 ->array 过滤器方法的原因。它劫持收集到的方法堆栈,并迭代剩余的过滤器,例如 $_POST 数组值。例如。$_POST->array->int["list"]

略微缩短的实现:

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;
}

方法堆栈在列表中组装。上面的 exec_chain() 只是遍历它,每次删除第一个方法名称。虚拟_array处理程序通常是第一种方法。它只是窃取该方法堆栈,并在每个数组元素上重新执行其余部分。与上面的示例代码不完全相同,但它只是重复重新填充原始方法堆栈。$this->__filter

它有效。但感觉有点不洁。我正在考虑添加另一个虚拟方法。(亚格尼?这不仅会遍历字段,还会评估备用过滤器是否成功。例如。我想知道是否有更好的模式来劫持函数列表。我目前的钩子列表($this->__filter)交换不适合链接。嗯,实际上,->xor 示例不需要迭代/行为与 ->array 完全相同。->xor$_REQUEST->array->xor->email->url["fields"]

所以具体来说,我有兴趣找到一种替代我的 $this->__filter 列表用法的 array_pop() 和偷偷摸摸地把它换掉。这很糟糕。有没有更好的实现方案来执行方法列表一半是我>一半是你?

PHP的

评论

1赞 Wez Furlong 10/3/2010
目前还不清楚你在问什么。也很难不对“流畅的界面”做出下意识的反应,并建议你做其他事情(!),即使你明确表示你没有问那部分。
0赞 Wez Furlong 10/3/2010
嘎,该死的输入提交但只能在评论框中再次咬我......您能否详细介绍一下您认为需要更智能的用例。从我所知道的你粘贴的代码来看,你已经得到了一些你想要的东西,而且它并不太可怕——我更反对流畅的界面而不是实现。
0赞 mario 10/3/2010
嗯,它有效。但是钩子列表热插拔似乎真的很脏。客观地说,这只是一个特征性问题,不确定我是否真的需要新的 virtal 方法。这是可以由应用程序逻辑处理的东西,它只感觉属于输入处理程序。无论如何,如果我需要 ->xor 或其他一些新功能,我当然需要摆脱并发数组操作。这是我问题的重点。
0赞 mario 10/3/2010
顺便说一句,我流畅的界面笔记。我是说这实际上不是一个流畅的界面。这些方法并没有真正链接起来。它基本上是捕获属性访问,从而构建了我的 $__filter 链方法堆栈。一个有趣的副作用:如果我先写一个非语句,它会保存一个过滤器链,如果我访问 .让我想起了我最近写的一个jQuery插件。$_GET->name->text;$_GET["field"]

答:

2赞 bobdiaes 10/6/2010 #1

我之前做过一个类似的链接接口,我喜欢你在 GET/POST 变量上使用它的想法。

我认为你最好做这样的事情

$var->array->email_XOR_url;
而不是.这样你就可以用你的__get/__call魔法捕捉各种组合。
$var->array->email->XOR->url;

评论

0赞 mario 10/6/2010
不是我想要的。但是,我不会使我的代码进一步复杂化,而是采用这种方法。在 __call 中管理此功能绝对比添加其他解决方法更简单。或者我什至可以尝试一个简单的方法。->xor(var, filter1, filter2, filter3)
0赞 bobdiaes 10/6/2010
是的,我也不喜欢它。使用 $var->array->xor('email','url') 似乎是最好的选择。
0赞 bobdiaes 10/6/2010
实际上,我认为您应该摆脱数组过滤器,因为它始终位于位置 1。只需在构造函数中拨动一个开关即可。如果开关处于打开状态,则任何链都将应用于每个数组成员。
0赞 Christian 3/19/2011
我会投票支持xor()-as-a-function方法,我自己过去经常使用它。