Full CakePHP Application Part 9


Cake Catalog Main Index Page

I've been a bit slow on the updates recently, been super busy with life and everything but thats no excuse. In my last article I went through the process of turning a Photoshop design into HTML/CSS and now its time to get CakePHP involved.
In this article I'm going to transfer the design and code over to CakePHP by using a new Layout and making use of some elements, this isn't necessarilly hard to do but the process it quite involved so I'm going to break it down.

Layouts

Have a quick read of the Layouts Chapter, basically a layout acts as a wrapper file with the code contained in your View files gets outputted in the "$content_for_layout" variable.
In essence a layout saves you from writing out the DocType and head section of the HTML including all the links to your CSS and Javascript files. Layouts can also make use of special variables that allow you to change the Title of the page in your Controllers as well as include page specific Javascript. These variables are $title_for_layout and $scripts_for_layout respectively.
I've created a new layout file at /app/views/layout/index.ctp and it includes all the basic code for any HTML page. It has a DocType declaration along with a head and body section. The file also include the $title_for_layout variable and goes on to include all my CSS and Javascript files. As you can see I'm using the Cake helpers to link to the files.
Inside the body I'm using elements (which I'll cover very shortly) to include some header code, then echoing out my View code by using the $content_for_layout variable and finally use another element for a footer and close the body and html tag.
  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
  2. <html xmlns="http://www.w3.org/1999/xhtml">  
  3. <head>  
  4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />  
  5. <title><?php echo $title_for_layout; ?></title>  
  6. <?php  
  7. // include css file  
  8. echo $html->css('cakecatalog');  
  9. // if the javscript helper is set include the javascript library  
  10. if(isset($javascript)) {  
  11.     echo $javascript->link(array('jquery-1.2.3.pack''common'), true);  
  12. }  
  13. // variable for any other javascript  
  14. echo $scripts_for_layout;  
  15. ?>  
  16. </head>  
  17.   
  18. <body>  
  19. <?php  
  20. // include a header element  
  21. echo $this->element('index_header');  
  22. // echo out view code  
  23. echo $content_for_layout;  
  24. // include a footer element  
  25. echo $this->element('index_footer');  
  26. // if debug is on echo to screen  
  27. echo $cakeDebug;  
  28. ?>  
  29. </body>  
  30. </html>  
To make use of the new layout file and to dynamically set the page title in a controller I can do the following:
  1. // file: /app/controllers/dvds_controller.php  
  2.   
  3. // set page title  
  4. $this->pageTitle = 'CakeCatalog - Index Page';  
  5. // set layout file  
  6. $this->layout = 'index';  
At the moment I'm only using the new layout for the index() view of the dvds_controller, if I wanted to use the layout permanently I could either set the layout in the beforeFilter() method of my controller or I could simply rename the file from index.ctp to default.ctp. If a default file is present Cake will automatically use it for.... you guessed it, the default layout across your application.

Elements

Again have a quick read of the Elements Chapter in the Cookbook to get a greater understanding of what they're all about. Basically they work the same way as general PHP includes, small chunks of re-usable code that you can put in a seperate file to save you some time.
I've created two Elements at /app/elements called index_header.ctp and index_footer.ctp and obviously they will contain code for the Header and Footer of my main page.
The Header element looks like this:
  1. // file: /app/views/elements/index_header.ctp  
  2.   
  3. <div id="wrapper-header">  
  4.     <div id="header">  
  5.         <div class="logo">  
  6.             <h1>CakeCatalog</h1>  
  7.             <h2>an online application to track and catalog your collection of dvds built using cakephp</h2>  
  8.         </div>  
  9.   
  10.         <div class="filters">  
  11.             <form action="" method="post">  
  12.                 <fieldset>  
  13.                     <div class="input">  
  14.                         <select>  
  15.                             <option>Format</option>  
  16.                             <option>Option 1</option>  
  17.                             <option>Option 2</option>  
  18.                             <option>Option 3</option>  
  19.                         </select>  
  20.                     </div>  
  21.                     <div class="input">  
  22.                         <select>  
  23.                             <option>Type</option>  
  24.                             <option>Option 1</option>  
  25.                             <option>Option 2</option>  
  26.                             <option>Option 3</option>  
  27.                         </select>  
  28.                     </div>  
  29.                     <div class="input">  
  30.                         <select>  
  31.                             <option>Location</option>  
  32.                             <option>Option 1</option>  
  33.                             <option>Option 2</option>  
  34.                             <option>Option 3</option>  
  35.                         </select>  
  36.                     </div>  
  37.                     <div class="input">  
  38.                         <select>  
  39.                             <option>Genre</option>  
  40.                             <option>Option 1</option>  
  41.                             <option>Option 2</option>  
  42.                             <option>Option 3</option>  
  43.                         </select>  
  44.                     </div>  
  45.                     <div class="clear"></div>  
  46.                     <div class="input">  
  47.                         <input type="text" value="enter search items" />  
  48.                     </div>  
  49.                     <div class="input">  
  50.                         <button type="submit" name="submit">Filter</button>  
  51.                         <button type="reset" name="reset">Reset</button>  
  52.                     </div>  
  53.                 </fieldset>  
  54.             </form>  
  55.         </div>  
  56.     </div>  
  57. </div>  
The Footer Element looks like this:
  1. // file: /app/views/elements/index_footer.ctp  
  2.   
  3. <div id="wrapper-footer">  
  4.     <div id="footer">  
  5.         <div class="box top-rated">  
  6.             <h2>Top Rated</h2>  
  7.             <ol>  
  8.                 <li><a href="">Desperado</a></li>  
  9.                 <li><a href="">From Dusk Till Dawn</a></li>  
  10.                 <li><a href="">Kill Bill Vol.1</a></li>  
  11.                 <li><a href="">Pulp Fiction</a></li>  
  12.                 <li><a href="">Reservior Dogs</a></li>  
  13.             </ol>  
  14.         </div>  
  15.         <div class="box recently-added">  
  16.             <h2>Recently Added</h2>  
  17.             <ol>  
  18.                 <li><a href="">Desperado</a></li>  
  19.                 <li><a href="">From Dusk Till Dawn</a></li>  
  20.                 <li><a href="">Kill Bill Vol.1</a></li>  
  21.                 <li><a href="">Pulp Fiction</a></li>  
  22.                 <li><a href="">Reservior Dogs</a></li>  
  23.             </ol>  
  24.         </div>  
  25.         <div class="box top-genres">  
  26.             <h2>Top Genres</h2>  
  27.             <ol>  
  28.                 <li><a href="">Desperado</a></li>  
  29.                 <li><a href="">From Dusk Till Dawn</a></li>  
  30.                 <li><a href="">Kill Bill Vol.1</a></li>  
  31.                 <li><a href="">Pulp Fiction</a></li>  
  32.                 <li><a href="">Reservior Dogs</a></li>  
  33.             </ol>  
  34.         </div>  
  35.         <div class="box most-active box-last">  
  36.             <h2>Most Active</h2>  
  37.             <ol>  
  38.                 <li><a href="">Desperado</a></li>  
  39.                 <li><a href="">From Dusk Till Dawn</a></li>  
  40.                 <li><a href="">Kill Bill Vol.1</a></li>  
  41.                 <li><a href="">Pulp Fiction</a></li>  
  42.                 <li><a href="">Reservior Dogs</a></li>  
  43.             </ol>  
  44.         </div>  
  45.         <div class="clear"></div>  
  46.   
  47.         <div class="copyright">  
  48.             <p>built using <a href="http://www.cakephp.org" target="_blank">CakePHP</a> by   
  49.             <a href="http://www.jamesfairhurst.co.uk" target="_blank">James Fairhurst</a></p>  
  50.         </div>  
  51.     </div>  
  52. </div>  
Currently these elements are static and don't do very much, this will change in my next article when I'll hook up the form functionality and start grabbing DVD's from the database to fill in the footer lists.

DVD's Index

In order to make the main contents work I need to wrap the entire View in my "wrapper" and "contents" divs so that when the View is rendered it will be placed inside the Layout and the CSS will kick in.
  1. <div id="wrapper-contents">  
  2.     <div id="contents">  
  3.         <!-- dvd index page goes here -->  
  4.     </div>  
  5. </div>  
Now I need to deal with looping through all the DVD's and displaying them inside "shelf" divs. I can do this by using some nifty PHP and check if the current DVD's number is divisible by 8, if it is I can assume that this DVD is the last one on the shelf. Basically I'm splitting up the DVDs into blocks of 8. If it is the 8th DVD then I also need to close the current "shelf" div and open up a new one.
  1. <div class="shelf">  
  2.   
  3.     <?php foreach($dvds as $key=>$dvd): ?>  
  4.         <?php  
  5.         // calculate if this dvd is the last on the shelf  
  6.         // if dvd number can be divided by 8 with no remainders  
  7.         $last_dvd = ( (($key+1) % 8 == 0)? 'dvd-last' : '' );  
  8.         ?>  
  9.   
  10.         <div class="dvd <?php echo $last_dvd; ?>">  
  11.   
  12.         </div>  
  13.   
  14.         <?php  
  15.         // if this is the last dvd, close the shelf div and create a new one  
  16.         if(!empty($last_dvd)) {  
  17.             echo '<div class="clear"></div>';  
  18.             echo '</div>';  
  19.             echo '<div class="shelf">';  
  20.         }  
  21.         ?>  
  22.           
  23.     <?php endforeach; ?>  
  24.   
  25.     <div class="clear"></div>  
  26. </div>  
This bit of code is also quite useful for displaying picture galleries by calculating the last one in the row. The DVD index now looks like this:
  1. // file: /app/views/dvds/index.ctp  
  2.   
  3. <div id="wrapper-contents">  
  4.     <div id="contents">  
  5.   
  6.         <div class="dvds index">  
  7.             <?php  
  8.             // check $dvds variable exists and is not empty  
  9.             if(isset($dvds) && !empty($dvds)) :  
  10.             ?>  
  11.             <div class="shelf">  
  12.                   
  13.                 <?php foreach($dvds as $key=>$dvd): ?>  
  14.                     <?php  
  15.                     // calculate if this dvd is the last on the shelf  
  16.                     // if dvd number can be divided by 8 with no remainders  
  17.                     $last_dvd = ( (($key+1) % 8 == 0)? 'dvd-last' : '' );  
  18.                     ?>  
  19.   
  20.                     <div class="dvd<?php echo $last_dvd; ?>">  
  21.                         <a href="/dvds/view/<?php echo $dvd['Dvd']['slug']; ?>">  
  22.                         <img src="/<?php echo $dvd['Dvd']['image']; ?>" alt="DVD Image: <?php echo $dvd['Dvd']['name'] ?>" width="100" height="150" />  
  23.                         </a>  
  24.                     </div>  
  25.   
  26.                     <?php  
  27.                     // if this is the last dvd, close the shelf div and create a new one  
  28.                     if(!empty($last_dvd)) {  
  29.                         echo '<div class="clear"></div>';  
  30.                         echo '</div>';  
  31.                         echo '<div class="shelf">';  
  32.                     }  
  33.                     ?>  
  34.                       
  35.                 <?php endforeach; ?>  
  36.                       
  37.                 <div class="clear"></div>  
  38.             </div>  
  39.           
  40.             <?php  
  41.             else:  
  42.                 echo 'There are currently no DVDs in the database.';  
  43.             endif;  
  44.             ?>  
  45.         </div>  
  46.   
  47.     </div>  
  48. </div>  

CSS File and Images

To successfully reference your CSS and image files in CakePHP you must place the files in the /app/webroot directory, and I've organised the CSS, Images, Javascript into their own folders for organisation sake. You can then link to your images files in CSS as normal using the relative url:
  1. // file: /app/webroot/css/cakecatalog.css  
  2. #wrapper-header     { background:url(../img/bg_header.png) repeat-x;}  
The webroot folder acts as the new root directory of the site and so you can create folders here and place files in and access them directly via the browser using: htpp://dvdcatalog/folder-name.

Wrapping Up

Ok this has been just a quick article and introduces you to Layouts and Elements, pretty simple concepts when you get your head round them but its always good to start at the beginning and hopefully this has been a good example on how to use them.

Source Code

The source code for this article can be downloaded using this link. If these articles are helping you out why not consider donating I can always use a beer! :)

This entry was posted in . Bookmark the permalink.

Leave a Reply