Full CakePHP Application Part 3


CakePHP 1.2 Full Application

Welcome to the 3rd article in a series on creating a full CakePHP 1.2 Application. If your new and interested in the project then check out part 1 and part 2 to get fully up to speed on the application in question and see what I've done so far. Just quickly, last time I went through creating the Controller and Views for the Formats table in the database and at the end I could view / add / edit and delete formats using the application.
In this article I'm going to create the Controllers and Views for the Types and Locations. This is going to be pretty simple because they include the exact same functionality as the Formats that was created previously. At the end of the article I will be able to start adding even more data to the database and have a strong understanding of the way CakePHP deals with data.

Types and Locations

I'll concentrate on the Controllers first so create two new files named types_controller.php and locations_controller.php respectively. Each file will contain the same methods as the formats_controller.php which include index(), view(), admin_index(), admin_add(), admin_edit() and admin_delete().
  1. /** 
  2.  * Types Controller 
  3.  * 
  4.  * file: /app/controllers/types_controller.php 
  5.  */  
  6. class TypesController extends AppController {  
  7.     // good practice to include the name variable  
  8.     var $name = 'Types';  
  9.       
  10.     // load any helpers used in the views  
  11.     var $helpers = array('Html''Form');  
  12.   
  13.     /** 
  14.      * index() 
  15.      * main index page of the types page 
  16.      * url: /types/index 
  17.      */  
  18.     function index() {  
  19.   
  20.     }  
  21.   
  22.     /** 
  23.      * view() 
  24.      * displays a single Type and all related dvds 
  25.      * url: /types/view/type_slug 
  26.      */  
  27.     function view($slug = null) {  
  28.   
  29.     }  
  30.   
  31.     /** 
  32.      * admin_index() 
  33.      * main index for admin users 
  34.      * url: /admin/types/index 
  35.      */  
  36.     function admin_index() {  
  37.   
  38.     }  
  39.   
  40.     /** 
  41.      * admin_add() 
  42.      * allows an admin to add a type 
  43.      * url: /admin/types/add 
  44.      */  
  45.     function admin_add() {  
  46.   
  47.     }  
  48.   
  49.     /** 
  50.     * admin_edit() 
  51.     * allows an admin to edit a type 
  52.     * url: /admin/types/edit/1 
  53.     */  
  54.     function admin_edit($id = null) {  
  55.   
  56.     }  
  57.   
  58.     /** 
  59.      * admin_delete() 
  60.      * allows an admin to delete a Type 
  61.      * url: /admin/Types/delete/1 
  62.      */  
  63.     function admin_delete($id = null) {  
  64.   
  65.     }  
  66.   
  67. }  
Instead of coding the two files from scratch I simply copied and pasted the code from my Formats Controller into the newly created files and changed all the references from the plural Formats to Types/Locations and I also changed the singular Format to Type/Location. This will ensure that the correct Model will be used and thus the correct table in the database.
  1. /** 
  2.  * index() 
  3.  * main index page of the types page 
  4.  * url: /types/index 
  5.  */  
  6. function index() {  
  7.     // this tells cake to ignore related type data such as dvds  
  8.     $this->Type->recursive = 0;  
  9.   
  10.     // get all types from database where status = 1  
  11.     $types = $this->Type->findAll("status=1");  
  12.   
  13.     // save the types in a variable for the view  
  14.     $this->set('types'$types);  
  15. }  
The 3 Controllers Formats, Types and Locations have the exact same functionality so copying and pasting code is the most efficient way of getting up and running.
Next up are the View files, I created two new folders called types and locations inside the /app/views folder and the View files from the formats directory were copied over and all references of Formats was changed to Types and Locations respectively.
  1. <?php  
  2.   
  3. // file: /app/views/types/admin_index.ctp  
  4.   
  5. ?>  
  6. <div class="types index">  
  7.   
  8.     <h2>Types Admin Index</h2>  
  9.     <p>Currently displaying all types in the application.</p>  
  10.   
  11.     <?php  
  12.     // check $types variable exists and is not empty  
  13.     if(isset($types) && !empty($types)) :  
  14.     ?>  
  15.   
  16.     <table>  
  17.         <thead>  
  18.             <tr>  
  19.                 <th>Id</th>  
  20.                 <th>Name</th>  
  21.                 <th>Slug</th>  
  22.                 <th>Description</th>  
  23.                 <th>Created</th>  
  24.                 <th>Modified</th>  
  25.                 <th>Actions</th>  
  26.             </tr>  
  27.         </thead>  
  28.         <tbody>  
  29.             <?php  
  30.             // initialise a counter for striping the table  
  31.             $count = 0;  
  32.   
  33.             // loop through and display format  
  34.             foreach($types as $type):  
  35.                 // stripes the table by adding a class to every other row  
  36.                 $class = ( ($count % 2) ? " class='altrow'"'' );  
  37.                 // increment count  
  38.                 $count++;  
  39.             ?>  
  40.             <tr<?php echo $class; ?>>  
  41.                 <td><?php echo $type['Type']['id']; ?></td>  
  42.                 <td><?php echo $type['Type']['name']; ?></td>  
  43.                 <td><?php echo $type['Type']['slug']; ?></td>  
  44.                 <td><?php echo $type['Type']['desc']; ?></td>  
  45.                 <td><?php echo $type['Type']['created']; ?></td>  
  46.                 <td><?php echo $type['Type']['modified']; ?></td>  
  47.                 <td>  
  48.                 <?php echo $html->link('Edit'array('action'=>'admin_edit'$type['Type']['id']) );?>  
  49.                 <?php echo $html->link('Delete'array('action'=>'admin_delete'$type['Type']['id']), null, sprintf('Are you sure you want to delete Type: %s?'$type['Type']['name']));?>  
  50.                 </td>  
  51.             </tr>  
  52.             <?php endforeach; ?>  
  53.         </tbody>  
  54.     </table>  
  55.       
  56.     <?php  
  57.     else:  
  58.         echo 'There are currently no Types in the database.';  
  59.     endif;  
  60.     ?>  
  61.       
  62.     <ul class="actions">  
  63.         <li><?php echo $html->link('Add a Type'array('action'=>'add')); ?></li>  
  64.     </ul>  
  65.   
  66. </div>  
To test that everything is working correctly add / edit / delete some types and locations at http://dvdcatalog/admin/types and http://dvdcatalog/admin/locations and if everything was copied successfully you should have no problems.
CakePHP 1.2 Full Application Image 3 CakePHP 1.2 Full Application Image 4 CakePHP 1.2 Full Application Image 5

CakePHP Data

I think that the single most useful feature of CakePHP is how it deals with data and the ease with which it handles associations. If the Model's are setup correctly with relationships between tables in the database then retrieving and adding related data is all handled by the framework and is one less thing that I need to worry about.
In the index() method of the Controllers there is a assignment of the recursive variable, this tells Cake how deep you want associated data to be processed. For example by setting the value to be 0 no associated data will be fetched in this case no DVDs associated with a type will be retreived from the database:
  1. // $this->Type->recursive = 0;  
  2. // $types = $this->Type->findAll("status=1");  
  3. Array  
  4. (  
  5.     [0] => Array  
  6.         (  
  7.             [Type] => Array  
  8.                 (  
  9.                     [id] => 1  
  10.                     [name] => Film  
  11.                     [...] => ...  
  12.                 )  
  13.         )  
  14.   
  15.     [1] => Array  
  16.         (  
  17.             [Type] => Array  
  18.                 (  
  19.                     [id] => 2  
  20.                     [name] => TV Show  
  21.                     [...] => ...  
  22.                 )  
  23.         )  
  24. )  
If I change this value to 1 then the DVDs will be processed, a sample of the data is below. If I changed this value to 2 then the associated data of DVDs will be fetched from the database. Its a hierarchy and allows us to drill down into the associated data which is extremely helpful but not always needed and thats why it's set to 0 in the index() methods.
  1. // $this->Type->recursive = 1;  
  2. // $types = $this->Type->findAll("status=1");  
  3. Array  
  4. (  
  5.     [0] => Array  
  6.         (  
  7.             [Type] => Array  
  8.                 (  
  9.                     [id] => 1  
  10.                     [name] => Film  
  11.                 )  
  12.   
  13.             [Dvd] => Array  
  14.                 (  
  15.                 )  
  16.         )  
  17.     [1] => Array  
  18.         (  
  19.             [Type] => Array  
  20.                 (  
  21.                     [id] => 2  
  22.                     [name] => TV Show  
  23.                 )  
  24.             [Dvd] => Array  
  25.                 (  
  26.                 )  
  27.         )  
  28. )  
For more info check out the manual on the recursive variable. As you can see from the retrieved data CakePHP works on a series of Conventions and will always retrieve data in an array whose array key is the Model name of the data being processed and any related data will by seperated into its own array, also by Model name.

Wrapping Up

This has been a pretty quick article as I've just duplicated code across the Controllers and Views. The application is slowly taking shape and you should now be able to add / edit / delete Formats, Items and Locations. I've also quickly looked at how CakePHP deals with data but if you are in doubt about what Cake is returning then print out the data using the pr() function and experiment yourself.

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