cakephp - php menu generated from a db -
i have database products organized categories , subcategories. thing generate menu querying categories table. because categories same(they can change/add once month or something), don't think have query database each access of web-page. have better idea me?
many thanks!
ps: i'm using cakephp framework, answer/idea doesn't have relate it. find memcache
i think in instance use combination of action caching , view caching. won't go vagaries of different caching engines, basics solve problem.
the first thing need turn caching on. in app/config/core.php
, you'll need make couple changes. first, comment out cache.disable
line:
//configure::write('cache.disable', true);
second, uncomment cache.check
line:
configure::write('cache.check', true);
finally, you'll need make cachehelper
available views, add $helpers
member definition in app/app_controller.php
:
class appcontroller extends controller { var $helpers = array('cache'); }
next, we'll set view element contains category menu (doing view stuff before controller stuff may seem little backwards, bear me -- it'll make sense). putting menu in view element makes caching bit simpler trying selectively designate parts of larger view or layout uncached <cake:no-cache></cake:no-cache>
tags.
here's sample view element, rendering category menu in simple unordered list (<ul>
):
<?php $menuitems = $this->requestaction(array('controller'=>'categories','action'=>'menu')); echo $html->nestedlist( $menuitems, 'ul' ); ?>
you may have been told 1 or more people in past requestaction
evil, initiates whole new dispatch. true. should avoid requestaction
plague, except when you're doing type of view-caching, in case it's best way go.
we'll store new view element app/views/elements/category_menu.ctp
. requestaction
invokes menu
action in categoriescontroller
. here's categoriescontroller
looks like, i'll go through bit bit:
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') )); } }
what does:
- the member definition
$cacheaction
tells cake should cache results ofmenu
action 1 day. - the
menu
method returns one-dimensional array of categories, usingcategory.id
keys, ,category.label
values.
so, let's go on we've got far. have category_menu
element, requests categoriescontroller::menu
action. when request received, cake check see whether result of action has been cached, , hasn't expired. if cached result still valid, cake return without invoking menu
method defined. otherwise, cake invoke method, , cache result. view element renders result nestedlist.
all remains, then, use view element in other views. here's simple sample 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>
we use familiar view::element
render category_menu
view element created earlier, tell cake want render view element once, cache rendered version, , hold onto month. subsequent requests element, until month elapses or clear cache, deliver pre-rendered view element. won't interpret app/views/elements/category_menu.ctp
, less invoke requestaction
, or hit database.
to ensure changes make category
model records reflected immesiately, can invoke global function clearcache()
in create/update actions. 1 caveat clearcache()
: it's bit of shotgun approach: inelegant effective. clearcache()
wipes out entire cache, rather selectively clearing necessary views. simple approach, however, , given you're talking updating categories monthly, having regenerate cache once month worth diminished hassle of more selective approach.
very long answer! hth
Comments
Post a Comment