PHP:将函数传递给类

tap*_*pe2 1 php

我上了课.我给它一些对象(主要是retreived数据库行)作为输入,并告诉它必须显示哪些字段,以及我想要的按钮.然后它呈现一个非常好的html表!我想,这真是太棒了.

$ot = new ObjectTable();
$ot->objects = $some_objects;
$ot->fields = array('id','name','description','image');
$ot->buttons = array('edit','delete');
$ot->render();
Run Code Online (Sandbox Code Playgroud)

但是,我也希望能够操纵它显示的数据.例如,我希望能够截断"描述"字段.或者显示图像缩略图(而不是'picture.jpg'作为文本).我不知道如何将这些函数传递给类.也许是这样的:

$ot->functions = array(null,null,'truncate','thumbnail');
Run Code Online (Sandbox Code Playgroud)

但后来我不知道如何转换这些字符串来运行一些实际的代码,或者如何传递参数.

必须有一个很好的方式来做我想要的.怎么样?

Gor*_*don 7

检查这个问题,答案是:

从PHP5.3开始,您可以使用闭包或仿函数来传递方法.在此之前,您可以使用create_function()编写一个匿名函数 ,但这很尴尬.

但是,您尝试实现的目标最好通过将过滤器对象传递给渲染器来解决.所有过滤器都应该使用相同的方法,因此您可以以策略模式的方式使用它,例如首先编写一个接口:

interface Filter
{
    public function filter($value);
}
Run Code Online (Sandbox Code Playgroud)

然后编写实现该接口的过滤器

class TruncateFilter implements Filter
{
    protected $_maxLength;
    public function __construct($maxLength = 50)
    {
        $this->_maxLength = (int) $maxLength;
    }
    public function filter($value)
    {
        return substr(0, $this->_maxLength, $value) . '…';
    }
}
Run Code Online (Sandbox Code Playgroud)

为ObjectTable提供一个接受过滤器的方法

public function addFilter($field, Filter $filter)
{
    if(in_array($field, $this->fields)) {
        $this->_filters[$field][] = $filter;
    }
    return $this;
}
Run Code Online (Sandbox Code Playgroud)

当你进行ObjectTable实例化时,请使用

$ot = new ObjectTable();
$ot->objects = $some_objects;
$ot->fields = array('id','name','description','image');
$ot->addFilter('description', new TruncateFilter)
   ->addFilter('name', new TruncateFilter(10))
   ->addFilter('image', new ThumbnailFilter);
Run Code Online (Sandbox Code Playgroud)

然后修改render()方法以检查是否为要渲染的字段设置了任何Filters,并对它们调用filter()方法.

public function render()
{
    foreach($this->fields as $field) {
        $fieldValue = // get field value somehow
        if(isset($this->filters[$field])) {
            foreach($this->filters[$field] as $filter) {
               $fieldValue = $filter->filter($fieldValue)
            }
        }
        // render filtered value
    }
}
Run Code Online (Sandbox Code Playgroud)

这样您就可以添加无限过滤器.