Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > PHP: Общие вопросы > Как оптимизировать код


Автор: lemniscate 18.1.2013, 07:00
Добрый день уважаемый форумчане! Прошу вашей помощи и не закидать помидорами. Есть вот такой код, который выводит данные из бд в таблицу. 
Код

function htmlTableRow(){
                
            while($row = $this->db->fetchArray()){
                // устанавливаем начальный тег строки
                $l .= $this->rowTags[0];
                
                // показать нумерацию строк таблиц
                if($this->numRows){           
                    $l .= $this->cellTags[0].++$num.$this->cellTags[1];           
                }
                $i = 0;
                // вывод ячеек строки таблицы 
                while($i < $this->db->numFields){                     
                    $l .= $this->cellTags[0].$row[$this->db->fields[$i]].$this->cellTags[1];
                    $i++;
                }
                
                //    Добавляем в конец таблицы дополнительные поля
                $l .= $this->addfld();
                // устанавливаем конечный тег строки
                $l .= $this->rowTags[1];                
            }            
            
        return $this->htmlTableRow = $l;
    }


Суть проблемы такова, для каждого поля(колонки) нужно установить свое форматирование данных, например 
Код


<tr>
 <td><input type=text value="Значение из бд"></td>    // например в этой строке надо значение полученное из бд вставить в тег input
 <td>V</td>  // здесь например при получении true или любого истинного значения поставить галочку (булев тип)
 <td>20.1</td>    // округлить (знаю знаю, можно на уровне mysql округлить) 
 <td><select>....</select></td>  // вставить селект со значениями из другой таблицы
 <td>СвязанноеЗначение</td>  // здесь вместо id вставить связанное значение из другой таблицы
 ... // и т.д. 
</tr>



сейчас я это реализовал на мой взгляд крайне коряво: 

Код

function formatValue($str, $fld){
...

// вставляет строку в input value
            if($this->formaValParam[$fld][0] == 'input' and $this->updateAllow){                
                $str = "<input ".$this->formaValParam[$fld][1]." value='".$str."' $this->inputAttr >";                
            }

// вставляет строку в input check value
            if($this->formaValParam[$fld][0] == 'inputCheck'){                
                // ставим галочку
                if($str == 1)$checked = 'checked';
                // если разрешено редактировать добавляем форму input 
                if($this->updateAllow)$str = "<input type='checkbox' $checked value='1' $this->inputAttr ".$this->formaValParam[$fld][1].">";
                // если редактировать запрещено
                if(!$this->updateAllow and $str == 1)$str = '<b>V</b>';
                // если редактировать запрещено и галочка не стоит
                elseif(!$this->updateAllow and $str == 0)$str = '-';
            }

// вставляем select с данными из другой таблицы
            if($this->formaValParam[$fld][0] == 'joinSelect' and $this->updateAllow){
                    ... // чтоб здесь не загнобили, поясню что если селект уже был создан то вставляем готовый, а не создаем снова каждый раз 
                        $this->select = new select($this->joinArr[$fld]);
                        $str = $this->select->makeSelect($this->formaValParam[$fld][4].$attr,$str);                    
                    ...            
                }

 и т.д. вариантов гора


return $this->celltags[0].$str.$this->celltags[1];
}

//соответственно создаем массив в котором определяем параметры для форматирования каждого поля

$tbl->formaValParam = array(            
            'какоетополе' => array('input'),
            'какоетополе2' => array('joinSelect', "select * from какаятотаблица","значениеИД", "отображаемоезначение"),
            'какоетополе3' => array('joinSelect', "select * from какаятотаблица2","значениеИД2", "отображаемоезначение2",'текущеевыбранноезначение'),
            'какоетополе4' => array('inputCheck'),
            'какоетополе5' => array('input')    
 и т.д.                
);

вот как то так. Все вроде бы и работает но хочется узнать может есть способ проще все сделать? да и время выполнения скажем так не очень для таблицы в 370 строк с 14 полями, время "генерации" такой таблицы составило 0.096 сек. При этом если полностью отключить форматирование то время выполнения составляет 0.018 разница чувствуется. 

Автор: Gold Dragon 18.1.2013, 12:52
а проще никак нельзя спросить? Я не понял сути вопроса

Автор: lemniscate 18.1.2013, 13:03
проще, хм. ну если в двух словах, то надо для каждого выводимого значения из бд применять какой нибудь способ форматирования

Автор: Gold Dragon 18.1.2013, 13:34
тогда тоже в двух слова.. что-то подобное я использую у себя в движках... Будем считать что есть массив данных полученных из базы, тогда всё очень просто

Код

// $rows - данные из базы

// будем складывать результат
$result = array();

// прокручиваем массив с данными
foreach ($rows as $row) {
    $result[] = '<td>' . val_1($row->val1) . '</td>';
    $result[] = '<td>' . val_2($row->val2) . '</td>';
    $result[] = '<td>' . val_3($row->val3) . '</td>';
}

// выводим таблицу
if(count($result)){
    echo '<table>' . implode($result) . '</table>';
}

// функция обрабатывает первое значение
function val_1($value)
{
    // здесь обрабатываем то что нам нужно
}

// функция обрабатывает второе значение
function val_2($value)
{
    // здесь обрабатываем то что нам нужно
}

// функция обрабатывает третье значение
function val_3($value)
{
    // здесь обрабатываем то что нам нужно
}

Автор: Aliance 18.1.2013, 14:21
Я писал около 1,5 лет назад Grid с выводом из БД и автоматической обработкой данных в зависимости от конфига. Весь код кидать не буду, он огромный, но суть такова, что я создавал конфиг, где указывал какой callback вызывать для определенного типа поля, соотв. значение направлялось в этот Callback, который уже выводил его определенным образом (там в инпуте, как число, etc).

Автор: baldina 18.1.2013, 14:37
Цитата(lemniscate @  18.1.2013,  07:00 Найти цитируемый пост)
может есть способ проще все сделать

если не вдаваться в детали форматирования, то здесь налицо каскад if.
кстати, некоторое ускорение можно получить, используя else:
если $this->formaValParam[$fld][0] равно 'input', то оно точно не равно 'inputCheck' и т.д.

упростить код можно, если $this->formaValParam[$fld] будет объектом полиморфного типа (с переопределенной функцией типа formatValue)
тогда большая функция formatValue разделяется на множество маленьких, каждая из которых форматирует свой тип значения

что-то типа
Код

abstract class Value{
  abstract function format ();
}

class TextValue extends Value{
  function format () { return '<input type="text" value="' . $this->value . '">'; }
}

class CheckValue extends Value{
  function format () { return '<input type="checkbox"' .  $this->checked() ? ' checked ' :'' . '>'; }
}


и работать быстрее будет

Добавлено через 54 секунды
Цитата(Aliance @  18.1.2013,  14:21 Найти цитируемый пост)
callback вызывать для определенного типа поля

так тоже хорошо

Автор: Gold Dragon 18.1.2013, 15:32
baldina, а не слишком ли для простой задачи создавать абстрактные классы? smile

Автор: baldina 18.1.2013, 16:06
для данной думаю не слишком. она кстати не настолько простая, да и такое решение может быть использовано повторно.

само использование классов в данном случае добавит не слишком большой процент новых строк, хотя выбор имени calbback функции  непосредственно из БД конечно лаконичнее.
выбор между callback функциями и объектами может быть сделан исходя из характера и числа параметров форматтеров, наличия/отсутствия одинакового кода в форматтерах и вкусов разработчика. 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)