Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/topic.php on line 737
Форумы портала PHP.SU :: оптимизация, и прочие улучшения

 PHP.SU

Программирование на PHP, MySQL и другие веб-технологии
PHP.SU Портал     На главную страницу форума Главная     Помощь Помощь     Поиск Поиск     Поиск Яндекс Поиск Яндекс     Вакансии  Пользователи Пользователи


 Страниц (1): [1]   

> Описание: поиск компромиса
DlTA
Отправлено: 18 Апреля, 2014 - 10:41:32
Post Id



Постоянный участник


Покинул форум
Сообщений всего: 2952
Дата рег-ции: Окт. 2010  


Помог: 53 раз(а)




как бы изловчиться при выводе нескольких однотипных элементов

в моем случае это товары, хотя могут быть и анонсы, и еще кака я нить упрощенная тому подобная однотипная структура

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

2) хотелось бы: получасть список индексов для объектов-моделей, передаваемый в шаблонизатор или итерационный объект который будет возвращать объекты модели,
а там уже по полученным ID получить объекты (товаров/статей/отзывов/коментов/...) подставлять их в шаблон
тут уже от реализации объектов, если получение значений делается в виде дерганья каждый раз базы, то база будет дергаться ну очень часто, а в манах к мускулю написано что запросы в цыкле это зло

3) иной вариант реализации это если для объекта а точнее вывода будут выдергиваться все необходимые элементы из базы за один присест
минусы почти теже что и в предыдущем варианте, хотя база дергается чуть реже. но по прежлему в цикле

4) следующий вариант, получить индексы для базы, и уже на основе них делать запрос к базе, и итеративно полученные значения впихивать в шаблон или генерить объект, а потом объект в шаблон
минусы с объектом в том, что это не модель, а некий вывод, который работает в обход модели

в общем вот такая каша в голове, может есть светлые идеи по реализации?

(Отредактировано автором: 18 Апреля, 2014 - 15:51:58)

 
 Top
DlTA
Отправлено: 18 Апреля, 2014 - 14:48:07
Post Id



Постоянный участник


Покинул форум
Сообщений всего: 2952
Дата рег-ции: Окт. 2010  


Помог: 53 раз(а)




ребята ну хоть какую то мыслю толкните, есть чет не понятно описал, укажите, приложу примеры кода

а то и обсудить нескем(

(Отредактировано автором: 18 Апреля, 2014 - 14:48:35)

 
 Top
Edwvee
Отправлено: 18 Апреля, 2014 - 15:34:20
Post Id


Частый гость


Покинул форум
Сообщений всего: 195
Дата рег-ции: Июнь 2013  


Помог: 1 раз(а)




Первый способ видится самым нормальным:
1. Неужели на странице так много товаров, что есть смысл экономить память?
2. Работай с обычным массивом, необязательно же получать из бд именно ассоциативный массив. Сэкономишь память значительно.
3. Ничего непонятно. Конкретнее объяснить не можешь?

В остальных вариантах по описанию не очень понятно. Но из базы лучше за один запрос все получить, так что они отметаются.
(Добавление)
Цитата:
плюсы (если их так можно назвать):
1 базу дергаем не часто

Это очень значительный плюс.
 
 Top
DlTA
Отправлено: 18 Апреля, 2014 - 16:02:54
Post Id



Постоянный участник


Покинул форум
Сообщений всего: 2952
Дата рег-ции: Окт. 2010  


Помог: 53 раз(а)




примеры для 1 просты

PHP:
скопировать код в буфер обмена
  1. /** @return mixed[] */
  2. $arListGoods = CDB::rows('SELECT ........ WHERE ...');
  3. foreach($arListGoods as $itemGoods){
  4.   echo "<b>{$itemGoods['name']}</b><br>";
  5. }


для 2
PHP:
скопировать код в буфер обмена
  1.  
  2. /** @return int[] */
  3. $listGoodsId = CDB::cols('SELECT `id` WHERE ...');
  4.  
  5. foreach($listGoodsId as $goodsId){
  6. $oGoods = new CGoods($goodsId);
  7.   echo "<b>{$oGoods->getName()}</b><br>";
  8. }


для 3
такой же как и 2, но разница в том что все поля для объекта выдергиваются из базы пни создании объекта, а не по запросу метода

для 4
PHP:
скопировать код в буфер обмена
  1. /** @return CDBLink */
  2. $oDBLink = CDB::link('SELECT `name`, `text`, ... WHERE ...');
  3. foreach($oDBLink as $itemGoods){
  4.   echo "<b>{$itemGoods['name']}</b><br>";
  5. }


понимаю что примеры слабоваты, и скорее всего не показывают масштаб опы
 
 Top
Edwvee
Отправлено: 18 Апреля, 2014 - 16:43:31
Post Id


Частый гость


Покинул форум
Сообщений всего: 195
Дата рег-ции: Июнь 2013  


Помог: 1 раз(а)




Не понял, чем первый от последнего отличается. Так как не нашел ничего по запросу "php cdb". Но первый лучше всего, только в целях экономии памяти, запрос должен быть таким, чтобы было например:
PHP:
скопировать код в буфер обмена
  1.  
  2. foreach($arListGoods as $itemGoods){
  3.   echo "<b>{$itemGoods[0]}</b><br>";
  4. }
  5.  

Экономить на памяти, когда размер массива составляет кол-во элементов на страницу - странно.
 
 Top
DlTA
Отправлено: 18 Апреля, 2014 - 17:41:52
Post Id



Постоянный участник


Покинул форум
Сообщений всего: 2952
Дата рег-ции: Окт. 2010  


Помог: 53 раз(а)




Edwvee пишет:
Не понял, чем первый от последнего отличается.
если развернуть и упростить то
1) будет так:
PHP:
скопировать код в буфер обмена
  1. $arListGoods  = array();
  2. $result = mysql_query($SQL_select);
  3. while ($row = mysql_fetch_assoc($result)) {
  4.     $arListGoods[] = $row;
  5. }
  6. // ...
  7. foreach($arListGoods as $itemGoods){
  8.   echo "<b>{$itemGoods['name']}</b><br>";
  9. }


а последний :

PHP:
скопировать код в буфер обмена
  1. $result = mysql_query($SQL_select);
  2. while ($itemGoods = mysql_fetch_assoc($result)) {
  3.     echo "<b>{$itemGoods['name']}</b><br>";
  4. }

но для удобности песледний завернут в класс итерратор
 
 Top
Edwvee
Отправлено: 21 Апреля, 2014 - 09:46:05
Post Id


Частый гость


Покинул форум
Сообщений всего: 195
Дата рег-ции: Июнь 2013  


Помог: 1 раз(а)




Ну можно просто mysql_fetch, но это уже из того что я говорил понятно.
По скорости выполнения разницы не должно быть особой. По памяти не знаю, смотрите разницу в memory_get_peak_usage(). Предполагаю, что это окажется экономией на спичках, а первый подход правильнее с точки зрения разделения логики и представления.
 
 Top
Stierus Супермодератор
Отправлено: 24 Апреля, 2014 - 23:56:55
Post Id



Рекордсмен по количеству сообщений за 7 дней


Покинул форум
Сообщений всего: 2132
Дата рег-ции: Дек. 2008  
Откуда: Москваль


Помог: 52 раз(а)




Рабочий из показанных - первый Улыбка

Плюсы:
1) 1 запрос на получение всех данных (ну, может 2 или 3 вместе с обогащением из других таблиц/кешей и прочего)
2) Самая высокая скорость работы

Если смущает результат в виде ассоциативного массива (в шаблоне, принимающем данные, не понятно, какие ключи могут быть у массива) - то перед отдачей в шаблон, этот ассоциативный массив можно положить внутрь класса - итератора с четким интерфейсом. Таким образом и скорость будет примерно такой же (добавляется всего 1 - 2 экземпляра класса, массив не копируется) и в шаблоне понятно, какие геттеры есть у объекта.

Для экономии делают либо пагинацию, либо аяксовую подгрузку данных. Оба эти решения скорее клиентские, чем серверные.
 
My status
 Top
DlTA
Отправлено: 25 Апреля, 2014 - 01:26:18
Post Id



Постоянный участник


Покинул форум
Сообщений всего: 2952
Дата рег-ции: Окт. 2010  


Помог: 53 раз(а)




сижу дамаю, как получить максимальную скорость и удобстро, и при этом экономить память и т.д.
и на мысль приходит только следующее решение

PHP:
скопировать код в буфер обмена
  1. foreach(CDBIterator::classIterator('CModel', array(1,2,3,4)) as $oModel){
  2.         echo $oModel->getValue();
  3.         // или
  4.         echo $oModel->getValue(true);
  5. }
  6.  
  7. class CModel{
  8.         /**
  9.         * @return string[] возвращает список полей, для запроса из базы
  10.         */
  11.         static public function listField(){}
  12.         /**
  13.         * @return string возвращает название таблицы из которой будет делаться запрос
  14.         */
  15.         static public function tableName(){}
  16.        
  17.         private $data = array();
  18.         private $id = 0;
  19.        
  20.         public function __construct($id, array $data){
  21.                 $this->data = $data;
  22.                 $this->id = $id;
  23.         }
  24.        
  25.         /**
  26.         * @param bool $active флаг, получать из базы только активные значения, иначе по возможности срез на момент создания объекта
  27.         */
  28.         public function getValue($active = false){
  29.                 if($active and isset($this->data['field'])){
  30.                         return $this->data['field'];
  31.                 }
  32.                 else{
  33.                         return $this->getValueFromDB('fieldName');
  34.                 }
  35.         }
  36.        
  37.         public function getValueFromDB($fieldName){
  38.                 // делаем запрос к базе для получения данных
  39.         }
  40. }
  41.  
  42. class CDBIterator implements Iterator, Countable{
  43.        
  44.         /**
  45.         * @return CDBIterator
  46.         */
  47.         static public function classIterator($className, $listId){}
  48.  
  49.         private $className = '';
  50.         private function __construct($className, $listId){
  51.                 $this->className = $className;
  52.                
  53.                 $reqSQL = 'SELECT '.'`' . implode('`, `',$className::listField()) . '`
  54.                 FROM `'.$className::tableName()'`
  55.                 WHERE `id` IN ('.implode(',', $listId).')';
  56.                 // делаем запрос, поулчаем линк
  57.         }
  58.        
  59.         /**
  60.         * @return CModel
  61.         */
  62.         public function current(){
  63.                 // получаем очередную строку из базы и запихиваем в создаваемый объект
  64.                
  65.                 $oModel = new $this->className($id, $arrData);
  66.                 return $oModel;
  67.         }
  68. }
  69.  

то есть: некая модель, конструктор которой получает как id для возможности осуществления запроса, так и массив с данными,
дальше для получения значений, данные вытаскиваются из массива, если же нужны только актуальные данные, то ставится соответствующий флаг в методе

вроде красиво получилось?
 
 Top
tato
Отправлено: 30 Апреля, 2014 - 09:23:18
Post Id



Посетитель


Покинул форум
Сообщений всего: 468
Дата рег-ции: Сент. 2011  
Откуда: Владивосток


Помог: 8 раз(а)




Вот если б PDO заюзать, то тогда подошла бы вот такая штука PDO::FETCH_CLASS
И вы бы сразу получали массив нужных объектов, например Ваш CModel


-----
просто ?: сложно
 
 Top
DlTA
Отправлено: 30 Апреля, 2014 - 10:25:21
Post Id



Постоянный участник


Покинул форум
Сообщений всего: 2952
Дата рег-ции: Окт. 2010  


Помог: 53 раз(а)




tato пишет:
Вот если б PDO заюзать, то тогда подошла бы вот такая штука PDO::FETCH_CLASS
И вы бы сразу получали массив нужных объектов, например Ваш CModel
мда, прикольно, в итоге получается что я на своем лесопеде реализовал по сути туже хрень, хотя есть некоторые внутренние отличия, что делает мой вариант в моих условиях более оптимальным
 
 Top
Страниц (1): [1]
Сейчас эту тему просматривают: 0 (гостей: 0, зарегистрированных: 0)
« Объектно-ориентированное программирование »


Все гости форума могут просматривать этот раздел.
Только зарегистрированные пользователи могут создавать новые темы в этом разделе.
Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.
 



Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS  RSS

 
Powered by ExBB FM 1.0 RC1. InvisionExBB