PHP: передача функций в класс - PullRequest
1 голос
/ 26 ноября 2009

Я сделал класс. Я даю ему некоторые объекты (в основном, полученные строки базы данных) и сообщаю ему, какие поля он должен показывать, и какие кнопки я хочу. Затем он создает очень хороший HTML-таблицу! Я думаю, это довольно круто.

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

Однако я также хочу иметь возможность манипулировать данными, которые он показывает. Например, я хочу иметь возможность обрезать поле «описание». Или для отображения эскиза изображения (вместо «picture.jpg» в виде текста). Я не знаю, как передать эти функции в классе. Возможно что-то вроде:

$ot->functions = array(null,null,'truncate','thumbnail');

Но тогда я не знаю, как преобразовать эти строки для запуска какого-то реального кода или как передать параметры.

Должен быть хороший способ сделать то, что я хочу. Как?

Ответы [ 5 ]

7 голосов
/ 26 ноября 2009

Отметьте вопрос и ответ:

Начиная с PHP5.3 вы можете использовать замыкания или функторы для передачи методов вокруг. До этого вы могли написать анонимная функция с create_function () , но это довольно неловко.

Но то, что вы пытаетесь достичь, лучше всего решить, передав Объекты Фильтра вашему рендереру. Все фильтры должны использовать один и тот же метод, поэтому вы можете использовать его в виде шаблона стратегии, например, сначала напишите интерфейс:

interface Filter
{
    public function filter($value);
}

Затем напишите ваши фильтры, реализующие интерфейс

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) . '…';
    }
}

Дайте вашему ObjectTable метод приема фильтров

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

А когда вы создаете экземпляр 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);

Затем измените ваш метод render (), чтобы проверить, есть ли какие-либо фильтры, установленные для полей, которые вы отображаете, и вызовите для них метод 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
    }
}

Таким образом, вы можете добавлять бесконечные фильтры.

3 голосов
/ 26 ноября 2009

PHP имеет псевдотип , называемый «обратный вызов» , который на самом деле является замаскированным замкнутым замыканием. Вы можете вызвать такие обратные вызовы, используя call_user_func() или call_user_func_array():

$callback = 'strlen';
echo call_user_func($callback, '123');
// will output 3 (unless you're using a strange encoding)
2 голосов
/ 26 ноября 2009

$ functions = array (null, null, 'truncate', 'thumbnail');
$ function_1 = $ functions [3];
$ my_string = 'строка для усечения';

$ result = call_user_func ($ functions [2], $ my_string);

Если вы хотите передать несколько параметров, используйте call_user_func_array.

2 голосов
/ 26 ноября 2009

Вы ищете create_function () .

Однако создание функций во время выполнения и добавление их в класс не подходит мне. Это может быстро стать кошмаром для техобслуживания. Есть лучшие способы достичь того, что вы хотите. Какого рода манипуляции будут выполнять функции с данными? Как насчет хранения их в классе «tools» и при необходимости связать его с объектом таблицы?

1 голос
/ 26 ноября 2009

Возможно, вы также захотите изучить call_user_func, который позволяет вызывать функцию на основе строки, представляющей ее имя.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...