php меню, сгенерированное из базы данных - PullRequest
1 голос
/ 27 апреля 2010

У меня есть база данных с продуктами, организованными по категориям и подкатегориям. Дело в том, что я генерирую меню, запрашивая таблицу категорий. Поскольку категории почти одинаковы (они могут меняться / добавляться один раз в месяц или около того), я не думаю, что мне нужно запрашивать базу данных для каждого доступа к веб-странице. У тебя есть идея получше?

Большое спасибо!

ps: я использую фреймворк CakePHP, но ваш ответ / идея не должны иметь к нему отношения. Я просто нахожу около memcache

Ответы [ 3 ]

2 голосов
/ 27 апреля 2010

Я думаю, что в этом случае я бы использовал комбинацию кэширования действий и кэширования представлений. Я не буду вдаваться в капризы различных механизмов кэширования, а только основы для решения вашей проблемы.

Первое, что вам нужно сделать, это включить кеширование. В app/config/core.php вам нужно внести пару изменений. Сначала закомментируйте строку Cache.disable:

//Configure::write('Cache.disable', true);

Во-вторых, раскомментируйте строку Cache.check:

Configure::write('Cache.check', true);

Наконец, вам нужно сделать CacheHelper доступным для всех представлений, поэтому добавьте его к определению $helpers в app/app_controller.php:

class AppController extends Controller
{
    var $helpers = array('Cache');
}

Далее мы настроим элемент view, который содержит меню вашей категории (выполнение представления до того, как будет выполнено управление, может показаться немного отсталым, но потерпите меня - это будет иметь смысл). Помещение меню в элемент представления делает его кэширование немного проще, чем попытка выборочно назначить части большего представления или макета как некэшированные с тегами <cake:no-cache></cake:no-cache>.

Вот пример элемента представления, отображающий меню категорий в простом неупорядоченном списке (<ul>):

<?php
    $menuItems = $this->requestAction(array('controller'=>'categories','action'=>'menu'));

    echo $html->nestedList( $menuItems, 'ul' );
?>

Возможно, в прошлом один или несколько человек говорили вам, что requestAction является злом, поскольку оно инициирует целую новую отправку. Это правда. Вам следует избегать requestAction, как чумы, , за исключением , когда вы используете этот тип кэширования представлений, и в этом случае это лучший способ.

Мы будем хранить этот новый элемент представления как app/views/elements/category_menu.ctp. requestAction вызывает действие menu в CategoriesController. Вот как выглядит CategoriesController, а потом я буду разбираться с этим постепенно:

class CategoriesController extends AppController
{
    var $cacheAction = array(
        'menu/' => '1 day'
    );

    function menu()
    {
        return $this->Category->find('list', array(
            'fields' => array('Category.id','Category.label'),
            'order'  => array('Category.order')
        ));
    }
}

Что это делает:

  • Определение элемента для $cacheAction говорит Cake, что он должен кэшировать результаты действия menu в течение 1 дня.
  • Метод menu возвращает одномерный массив категорий, используя Category.id в качестве ключей и Category.label в качестве значений.

Итак, давайте рассмотрим, что у нас так далеко. У нас есть элемент category_menu, который запрашивает действие CategoriesController::menu. Когда этот запрос получен, Cake проверит, кэширован ли результат этого действия и не истек ли он. Если кэшированный результат все еще действителен, Cake вернет его, не вызывая метод menu, который мы определили. В противном случае Cake вызовет метод и кеширует результат. Элемент view затем отображает результат как nestedList.

Остается только использовать элемент представления в других представлениях. Вот простой пример app/views/layouts/default.ctp:

<html>
[ snip... ]
<body>
<div class="category-menu">
    <?php echo $this->element('category_menu', array('cache'=>'1 day')); ?>
</div>
<div class="content">
     <p>Lorem ipsum sit dolor amet.</p>
</div>
</body
</html>

Мы используем знакомый View::element для визуализации элемента представления category_menu, который мы создали ранее, но мы также говорим Cake, что мы хотим, чтобы он визуализировал элемент представления один раз, затем кэшируем эту визуализированную версию и держим ее для месяц. Любые последующие запросы на этот элемент, пока не истечет месяц, или мы не очистим кеш, доставят предварительно обработанный элемент представления. Он даже не будет интерпретировать app/views/elements/category_menu.ctp, а тем более вызывать requestAction или попадать в базу данных.

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

Очень длинный ответ! НТН

1 голос
/ 27 апреля 2010

Ответ Марка правильный, и мне нравится его простота. То, что это не Cakey, не означает, что вы должны его использовать. Я причинил себе больше горя и времени, пытаясь приспособить что-то к «пирожному» формату, чем хочу признаться.

В быстром развитии иногда нужны взломы.

Тем не менее, если вы хотите пойти по более похожему на Cake маршруту, я предлагаю вам проверить кэширование запросов. Хорошая статья об этом в http://www.endyourif.com/caching-queries-in-cakephp/

1 голос
/ 27 апреля 2010

Вы можете написать скрипт для запроса базы данных о доступных категориях и записать вывод в файл .php, / inc / Categories.php , который используется вашим сайтом.

Этот скрипт запускается заданием cron один раз в месяц или столько раз, сколько вы пожелаете

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