За последние 24 часа нас посетили 21180 программистов и 1626 роботов. Сейчас ищут 1399 программистов ...

Однократность обращения к файлу в массиве

Тема в разделе "Прочие вопросы по PHP", создана пользователем Mr.Miksar, 19 фев 2012.

  1. Mr.Miksar

    Mr.Miksar Активный пользователь

    С нами с:
    4 дек 2009
    Сообщения:
    24
    Симпатии:
    0
    Адрес:
    Нижний Новгород
    Здравствуйте!
    Возникла у меня идея оградить сервер от многочисленных загрузок файла шаблона при выводе новостей.
    Допустим мы выводим 20 новостей, допустим, из них для 15 задан шаблон active1.tpl, для 3-х active2.tpl и для 2-х active5.tpl.
    Т.е. не имеет смысла обращаться к серверу за файлом active1.tpl 15 раз (а если высокая посещаемость?). Сильным серверам все равно (даже если по 50 новостей выводить), но если сервер и так перегружен (во время атак).

    Я набросал пример. Там даны комментарии. Подскажите, пожалуйста, как мне лучше реализовать идею?
    Файл вывода новостей.
    Код (Text):
    1. ######################################
    2.  
    3. $tmp = "active1.tpl"; // шаблон установленный по умолчанию
    4. $dd = array();
    5. $cache = array();
    6.  
    7. // data - исходный массив данных
    8. // шаблон, определенный для текста
    9. $dd['a']['tpl']="active1.tpl";
    10. $dd['b']['tpl']="active1.tpl";
    11. $dd['c']['tpl']="active3.tpl";
    12. $dd['d']['tpl']="active1.tpl";
    13. $dd['e']['tpl']="active5.tpl";
    14. $dd['f']['tpl']="active1.tpl";
    15.  
    16. // текст, который должен отображаться в заданном шаблоне
    17. $dd['a']['txt']="первый шаблон!.tpl";
    18. $dd['b']['txt']="второй шаблон!.tpl";
    19. $dd['c']['txt']="третий шаблон!.tpl";
    20. $dd['d']['txt']="четвертый шаблон!.tpl";
    21. $dd['e']['txt']="пятый шаблон!.tpl";
    22. $dd['f']['txt']="шестой шаблон!.tpl";
    23.  
    24. // функция вывода шаблона и текста
    25. // $in - входящее имя шаблона (файла)
    26. function tpl_out($in="default"){
    27. global $tpl;  // содержит в себе данные текущей итерации
    28. static $out; // статическая переменная держит в себе массив уникальных шаблонов, где ключ - имя шаблона
    29. #########
    30. // если массив содержит данные с ключём входящего имени шаблона, то выводим "кешированный" шаблон
    31.   if (!empty($out[$in])) {
    32.     $ff = $out[$in];  // тут проблема. Переменная в шаблоне не заменяется данными объявленными в глобальной переменной $tpl
    33.     return $ff;
    34. // иначе подгружаем файл с указанным именем шаблона
    35.   } else {
    36.     ob_start();
    37.       include templates_directory.'/'.$in;
    38.       $out[$in] = ob_get_contents(); // добавляем шаблон в массив уникальных шаблонов
    39.     ob_end_clean();
    40.     return $out[$in];
    41.   }
    42. #########
    43. }
    44.  
    45. //print - перебор данных исходного массива
    46. foreach ($dd as $ddk => $ddv) {
    47.   $tpl = array();
    48.   $tpl['post'] = $ddv['txt']; // определяем текст для переменной в шаблоне.
    49.   echo tpl_out($ddv['tpl']); // задача функции - использовать (подгружать) файл шаблона только один раз после первого упоминания в итерациях
    50. }
    51. echo "<hr />"; // элемент декора :)
    52. ######################################
    Файл active1.tpl. (шаблоны с другими номерами идентичны)
    Код (Text):
    1. <hr />
    2. <div style="border: 1px solid #ccc; background-color: #D2F0DA;">Шаблон №1: <br /> $tpl['post'] <br /> ".$tpl['post']." <br /> <?php echo $tpl['post']; ?> </div>
    3. <hr />
     
  2. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    если новость и шаблон не меняются месяцами или годами, имеет смысл результат применения шаблона запихать в файл или бд.
     
  3. Mr.Miksar

    Mr.Miksar Активный пользователь

    С нами с:
    4 дек 2009
    Сообщения:
    24
    Симпатии:
    0
    Адрес:
    Нижний Новгород
    а если меняется? Смысл в вашем предложении есть, но нет универсальности )))
    Я же не знаю как пользователь будет распоряжаться файлами...

    ЗЫ
    Это для бесплатной cms.
     
  4. Mr.Miksar

    Mr.Miksar Активный пользователь

    С нами с:
    4 дек 2009
    Сообщения:
    24
    Симпатии:
    0
    Адрес:
    Нижний Новгород
    Ребята, неужели никто помочь не может? (
     
  5. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    либо кешируй, либо не кешируй =)
     
  6. Крыс

    Крыс Активный пользователь

    С нами с:
    3 фев 2012
    Сообщения:
    449
    Симпатии:
    0
    Хм.. А чем тебе кеширование в плане универсальности не угодило?
     
  7. Mr.Miksar

    Mr.Miksar Активный пользователь

    С нами с:
    4 дек 2009
    Сообщения:
    24
    Симпатии:
    0
    Адрес:
    Нижний Новгород
    Как вы предлагаете выполнить кеширование?
    В файл? - меняем шило на мыло. %) у нас и так шаблоны - это файлы.
    В базу? - куча ненужных запросов. о_О
    В переменную (массив) - я работаю в этом направлении. Но не выходит.
    Пробовал создавать функции с содержимым шаблона через create_function, но он мне что-то не дался. ((

    Может кто-то видел где-то что-то подобное? Наверняка есть решение.
    Помогите пожалуйста с приведенным примером )
     
  8. Denis.Y

    Denis.Y Активный пользователь

    С нами с:
    8 авг 2011
    Сообщения:
    145
    Симпатии:
    0
    Адрес:
    Россия, Самарская область
    создавать объект шаблона (заполняя его данными из файла) при обработки новости.
    при обработки следующей новости проверять,
    нужен ей шаблон из существующих объектов или подгружать новый.
    после отработки собственно, уничтожать все объекты.
     
  9. Mr.Miksar

    Mr.Miksar Активный пользователь

    С нами с:
    4 дек 2009
    Сообщения:
    24
    Симпатии:
    0
    Адрес:
    Нижний Новгород
    Вы мне классы предлагаете?
    При загрузке шаблона (как у меня в примере) - переменные заменяются раньше, чем шаблон успевает попасть в какой либо контейнер.... Вот в чем проблема.

    Или я вас не понял. Можно примерчик для доступности?
     
  10. Denis.Y

    Denis.Y Активный пользователь

    С нами с:
    8 авг 2011
    Сообщения:
    145
    Симпатии:
    0
    Адрес:
    Россия, Самарская область
    можно как класс, можно, да как угодно можно это реализовать.
    механика какая у вас? tpl что хранит в себе ?! html с метками аля -
    Код (Text):
    1. {main_menu}
    или подключением компанентов аля -
    Код (Text):
    1. <?=$core->render->main_menu?;>
    ?!
    в принципе и там и там алгоритм я бы делал один и тот же, примерно следующий:


    Код (Text):
    1.  
    2.  // берём новость, смотрим какой тип шаблона ей нужен.
    3. if (!in_array('id_шаблона',$tpl_list))
    4. {
    5.  // нужного ей шаблона нет в массиве шаблонов (уже загруженных с файла)
    6.  // загружаем в $tpl_list[] новый шаблон, после чего
    7.  // обрабатываем вывод новости
    8. }
    9. else
    10. {
    11.  // шаблон уже загружен, значит грузить вновь его не нужно
    12.  // просто обрабатываем вывод новости
    13. }
    14.  // освобождаем массив с загруженными шаблонами.
    что-то в этом духе.
    с компанентами (классами, виджетами) как вам удобнее будет, алгоритм собственно такой же.
     
  11. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.119
    Симпатии:
    1.245
    Адрес:
    там-сям
    @Mr.Miksar, [ повторное ] чтение из файла это довольно шустрая операция, кешируемая на уровне ОС. это не то, что стоит оптимизировать в скрипте!
    замерь затраты времени на основные операции и работай над главным
     
  12. Mr.Miksar

    Mr.Miksar Активный пользователь

    С нами с:
    4 дек 2009
    Сообщения:
    24
    Симпатии:
    0
    Адрес:
    Нижний Новгород
    Всю механику привел в примере. только вместо запроса из БД сделал готовый массив.
    Шаблон содержит переменные. Обычные самые. В исходной версии движка они выводились в шаблоне, например, как <?=$tpl['id']; ?>. Для совместимости старых версий движков - хотелось бы структуру шаблона сохранить.
    И вашу идею и пытался реализовать (это была моя первая версия с массивом, но с функцией (через static) показалось как то удобнее, хотя и не критично). В общем, не получается с моей структурой. ))) Еще идеи будут?

    Это мне уже предложили. Буду тестировать )

    Дык вот и стараюсь везде учесть возможные "неровности" ))
    Спасибо! )
     
  13. Mr.Miksar

    Mr.Miksar Активный пользователь

    С нами с:
    4 дек 2009
    Сообщения:
    24
    Симпатии:
    0
    Адрес:
    Нижний Новгород
    Итак в своем примере сделал следующие поправки:
    Код (Text):
    1. foreach ($dd as $ddk => $ddv) {
    2.   $tpl = array();
    3.   $tpl['post'] = $ddv['txt'];
    4.   $st = array_sum(explode(" ", microtime()));
    5.   echo tpl_out($ddv['tpl']); // задача функции - использовать (подгружать) файл шаблона только один раз после первого упоминания в итерациях
    6.   $tot =  round(((array_sum(explode(" ", microtime()))) - $st), 6);
    7.   echo "<b>".$tot."</b>";
    8. }
    Время с округлением до 6 знаков после запятой.
    подключался один и тот же файл. Каждый столбец - обновление браузера. Каждая строка - последующее подключение файла.
    Вот мои результаты:
    // если с кешированием в массив (в функции через статик)
    0,000823 0,000773 0,000817
    1,6E-5 1,5E-5 1,6E-5
    1,2E-5 1,3E-5 1,3E-5
    1,1E-5 1,1E-5 1,2E-5

    // если без кеширование - прямое подключение
    0,0007 0,000758 0,000708
    0,000228 0,000237 0,000218
    0,00017 0,000181 0,000166
    0,000169 0,000166 0,000168

    Итак - результат из массива выводится практически на 0.0002 быстрее чем подключение файла. В любом случае подтвердилось и то, что повторное подключение файла не происходит, а берется он из некоего кеша ОС.
     
  14. Апельсин

    Апельсин Активный пользователь

    С нами с:
    20 мар 2010
    Сообщения:
    3.645
    Симпатии:
    2
    В тему не вникал. Но "оптимизация" в 0.0002 - не есть оптимизацией.
     
  15. Mr.Miksar

    Mr.Miksar Активный пользователь

    С нами с:
    4 дек 2009
    Сообщения:
    24
    Симпатии:
    0
    Адрес:
    Нижний Новгород
    Я прикидывал вывод (вроде как) 1000 или 10000 новостей. тогда время вывода сокращается с 32с. до 3с.
    Но это так... эксперимент )) Провел опыт и дал пищу для ума - а уж как кто воспользуется - дело его.
    Да, не забывайте еще время на запросы в БД. Время загрузки других файлов с сервера. Время есть куда поберечь ;)

    ЗЫ
    Функцию кеширования через статик все же написал. Но есть минусы. Кому интересно - кину в личку.
     
  16. AndreJM

    AndreJM Активный пользователь

    С нами с:
    25 янв 2012
    Сообщения:
    522
    Симпатии:
    0
    Код (PHP):
    1. // сохраняем шаблон, сериализуем 
    2. $ser = serialize(file_get_contents("template.tpl"));
    3.  
    4. // -----
    5. $tpl['post'] = "Hello";
    6. eval(" ?> ".unserialize($ser)." <?php ");
    7.  
    8. ......
    9.  
    10. $tpl['post'] = "Bye";
    11. eval(" ?> ".unserialize($ser)." <?php ");
    не проще? ... хотя кому как.
     
  17. Mr.Miksar

    Mr.Miksar Активный пользователь

    С нами с:
    4 дек 2009
    Сообщения:
    24
    Симпатии:
    0
    Адрес:
    Нижний Новгород
    Вот вы припоздали уже )) Почти так и реализовал идею ) Спасибо )