Как вызвать метод по имени?

#php #eval #zend-search-lucene

#php #оценка #zend-поиск-lucene

Вопрос:

Я хочу передать объект row функции, которая использует информацию о конфигурации, хранящуюся в строке, для создания документа Zend Search Lucene и добавления его в мой индекс.

Сохраненная информация выглядит следующим образом:

 protected $_index = array(
    'url' => array('UnIndexed', 'getUrl()'),
    'fragment' => array('UnIndexed', 'getFragment()'),
    'edited' => array('UnIndexed', 'edited'),
    'title' => array('Text', 'getTitle()'),
    'summary' => array('Text', 'getSummary()'),
    'text' => array('UnStored', 'getText()'),
);
  

Вот функция, которую я вызываю:

 public static function addDoc(My_Db_Table_Row_Abstract $row)
{
    $config = $row->getIndexConfig();
    if (empty($config)) {
        return;
    }

    // setup the document
    $document = new Zend_Search_Lucene_Document();
    $document->addField(Zend_Search_Lucene_Field::keyword('table_name', $row->getTable()->info('name')))
            ->addField(Zend_Search_Lucene_Field::keyword('table_row_key', $row->getIndexRowKey()));

    // add the configured fields
    foreach ($config as $name => $opts) {
        $type = $opts[0];
        $value = eval('return $row->' . $opts[1]);
        switch ($type) {
            case 'Keyword' :
                $field = Zend_Search_Lucene_Field::keyword($name, $value);
                break;
            case 'UnIndexed' :
                $field = Zend_Search_Lucene_Field::unIndexed($name, $value);
                break;
            case 'Binary' :
                $field = Zend_Search_Lucene_Field::binary($name, $value);
                break;
            case 'Text' :
                $field = Zend_Search_Lucene_Field::text($name, $value);
                break;
            case 'UnStored ' :
                $field = Zend_Search_Lucene_Field::unStored($name, $value);
                break;
        }
        $document->addField($field);
    }

    // add to the index
    self::getIndex()->addDocument($document);
}
  

Как вы можете видеть, мне нужно получить информацию через вызовы функций в поля документа. Я обеспокоен использованием eval() , но я не знаю другого способа. Есть ли лучший способ реализовать ту же функциональность?


РЕШЕНИЕ

Я изменил данные конфигурации, чтобы использовать функции для всех полей (убрав скобки), и уменьшил первую букву type , чтобы я мог использовать это для call_user_func также:

 protected $_index = array(
    'url' => array('unIndexed', 'getUrl'),
    'fragment' => array('unIndexed', 'getFragment'),
    'edited' => array('unIndexed', 'getEdited'),
    'active_self' => array('keyword', 'isActive'),
    'active_block' => array('keyword', 'isActiveBlock'),
    'active_page' => array('keyword', 'isActiveNav'),
    'members_only' => array('keyword', 'isMembersOnly'),
    'title' => array('text', 'getTitle'),
    'summary' => array('text', 'getSummary'),
    'text' => array('unStored', 'getText'),
);
  

И вызов функции, который в итоге оказался намного проще:

 public static function addDoc(My_Db_Table_Row_Abstract $row)
{
    $config = $row->getIndexConfig();
    if (empty($config)) {
        return;
    }

    // setup the document
    $document = new Zend_Search_Lucene_Document();
    $document->addField(Zend_Search_Lucene_Field::keyword('table_name', $row->getTable()->info('name')))
            ->addField(Zend_Search_Lucene_Field::keyword('table_row_key', $row->getIndexRowKey()));

    // add the configured fields
    foreach ($config as $name => $opts) {
        $value = call_user_func(array($row, $opts[1]));
        $field = call_user_func(array('Zend_Search_Lucene_Field', $opts[0]), $name, $value);
        $document->addField($field);
    }

    // add to the index
    self::getIndex()->addDocument($document);
}
  

Комментарии:

1. вы пробовали $ObjectInstance->$methodName() ? я знаю, что это работает для переменных экземпляра.

Ответ №1:

Вы также можете использовать call_user_func . Вот документ по PHP.

Пример:

 <?php
function barber($type)
{
    echo "You wanted a $type haircut, no problemn";
}
call_user_func('barber', "mushroom");
call_user_func('barber', "shave");
?>
  

Вывод:

  You wanted a mushroom haircut, no problem
 You wanted a shave haircut, no problem
  

Для вас, например, вам нужно изменить :

 $value = eval('return $row->' . $opts[1]);
  

Автор:

 $value = call_user_func($row->' . $opts[1]);
  

Комментарии:

1. Опередил меня на 5 секунд :). Вот ссылка на документацию: php.net/manual/en/function.call-user-func.php

2. Из примеров, которые я видел, call_user_func вызывает статические функции. Как бы вы изменили строку в моем коде для использования call_user_func ?

3. Он МОЖЕТ вызывать статику … это не значит, что у него тоже есть 🙂

Ответ №2:

Я думаю, вы можете сделать:

 // ...
$type = $opts[0];
$method = $opts[1];
$value = $row->$method;
  

Или:

 // ...
$type = $opts[0];
call_user_func(array($row, $opts[1]));
  

Ответ №3:

Удалите скобки из имен ваших методов:

 protected $_index = array(
    'url' => array('UnIndexed', 'getUrl'),
    'fragment' => array('UnIndexed', 'getFragment'),
    ...
  

Замените этот атрибут:

 'edited' => array('UnIndexed', 'edited'),
  

С помощью эквивалентного метода получения:

 'edited' => array('UnIndexed', 'getEdited'),
  

Тогда просто сделайте это:

 $method = $opts[1];
$value = $row->$method();