- Tutorials
- Blog_tutorial_-_1
- Migration
- Blog_tutorial_-_2
- Book_titles
- Pagination
- Debugging_your_code
- Extending_cake
- Multiple_applications
- Sending_email
- Scaffolding_a_blog
- Sample_layout
- Image_gallery
- Dynamic-image
- Online_editor-fckeditor
- Using_cake_with_drupal
- Cake_with_smarty
- Testing_cake_apps
- Howto_use_rdauth
- Dynamic-menu
- Your_tutorial
- Creating_pdfs
- Creating_pdfs_easy
- Cake_on_ubuntu
- Hello_world
- Complex_model_validation_routines
- User_permissions
- Cake_under_iis
- Advanced_validation
- Sending_email_with_phpmailer
- Change_database_config
- Alternative_installation_locations
- Css_in_ajax
- Css_menus
- Flashing
- Alternate_advanced_validation
- Deep_cakephp
- I18n_v2
- Building_a_cakephp_site_part_-_1
- Loading_sql_with_prefixes
- Building_a_cakephp_site_part_-_2
- Creating_a_dragglable_element
- I18n
- Online_editor-xinha
- Image_gallery_2
- Cake_migrations
- Beginners_only
- Cake_under_iis_without_rewrite
- Acl-access-checking
- Simple_pagination_helper
- Ajax_sortable_list
- Building_a_web_wizard
- Url_rewrite_without_apache
- Duplicate_record_validation
- Litte_german_example
- Authentication_with_rdsimpleauth
- Simple_contextual_help
- Passing_named_parameters
- Advanced_validation
- Calendar_pagination
- Config_in_database
- How_to_toggle_expand-collapse_with_javascript
- Xampp_vhost_config_on_windows
- Time_helper_other_languages
- Routing_for_multilanguage
- How_to_implement_single_table_inheritance
- Thumbnails_with_phpthumb
- Syncronised_session_using_cakeamfphp
- Secure_logins_with_challenge_response
- Config_in_database_2
- Installing_on_macosx
- Tinymce_with_cake
- Persistent_data
- Functional_testing_cake_apps
- Getting_paths_right
Cake Tutorial: Books Title Example (With hasOne)
This tutorial shows a little bit about using Cake’s automatic associations.
Requires
RC5 ready- gwoo
Create database
Here’s the SQL:
CREATE TABLE `categories` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(250) NOT NULL DEFAULT '', `parent_id` int(11) NOT NULL DEFAULT '0', `created` DATETIME DEFAULT NULL, `modified` DATETIME DEFAULT NULL, PRIMARY KEY (`id`) ); INSERT INTO `categories` (`id`, `name`, `parent_id`, `created`) VALUES (1, 'Business', 0, NOW()); INSERT INTO `categories` (`id`, `name`, `parent_id`, `created`) VALUES (2, 'Modern Cookbook', 0, NOW()); INSERT INTO `categories` (`id`, `name`, `parent_id`, `created`) VALUES (3, 'Popular Computing', 0, NOW()); INSERT INTO `categories` (`id`, `name`, `parent_id`, `created`) VALUES (4, 'Psychology', 0, NOW()); INSERT INTO `categories` (`id`, `name`, `parent_id`, `created`) VALUES (5, 'Undecided', 0, NOW()); CREATE TABLE `publishers` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(250) NOT NULL DEFAULT '', `created` DATETIME DEFAULT NULL, `modified` DATETIME DEFAULT NULL, PRIMARY KEY (`id`) ); INSERT INTO `publishers` (`id`, `name`, `created`) VALUES (1, 'New Moon Books', NOW()); INSERT INTO `publishers` (`id`, `name`, `created`) VALUES (2, 'Binnet & Hardley', NOW()); INSERT INTO `publishers` (`id`, `name`, `created`) VALUES (3, 'Algodata Infosystems', NOW()); INSERT INTO `publishers` (`id`, `name`, `created`) VALUES (4, 'Five Lakes Publishing', NOW()); INSERT INTO `publishers` (`id`, `name`, `created`) VALUES (5, 'Ramona Publishers', NOW()); INSERT INTO `publishers` (`id`, `name`, `created`) VALUES (6, 'GGG&G', NOW()); INSERT INTO `publishers` (`id`, `name`, `created`) VALUES (7, 'Scootney Books', NOW()); INSERT INTO `publishers` (`id`, `name`, `created`) VALUES (8, 'Lucerne Publishing', NOW()); CREATE TABLE `titles` ( `id` varchar(250) NOT NULL DEFAULT '', `title` varchar(250) NOT NULL DEFAULT '', `category_id` int(11) NOT NULL DEFAULT '0', `price` decimal(19,8) NOT NULL DEFAULT '0.00000000', `publisher_id` int(11) NOT NULL DEFAULT '0', `created` DATETIME DEFAULT NULL, `modified` DATETIME DEFAULT NULL, PRIMARY KEY (`id`) ); INSERT INTO `titles` (`id`, `title`, `category_id`, `price`, `publisher_id`, `created`) VALUES ('BU1032', 'The Busy Executives Database Guide', 1, 19.99000000, 3, NOW()); INSERT INTO `titles` (`id`, `title`, `category_id`, `price`, `publisher_id`, `created`) VALUES ('BU1111', 'Cooking with Computers', 1, 11.95000000, 3, NOW()); INSERT INTO `titles` (`id`, `title`, `category_id`, `price`, `publisher_id`, `created`) VALUES ('BU2075', 'You Can Combat Computer Stress', 1, 2.99000000, 1, NOW()); INSERT INTO `titles` (`id`, `title`, `category_id`, `price`, `publisher_id`, `created`) VALUES ('BU7832', 'Straight Talk About Computers', 2, 19.99000000, 3, NOW()); INSERT INTO `titles` (`id`, `title`, `category_id`, `price`, `publisher_id`, `created`) VALUES ('MC2222', 'Silicon Valley Gastronmic Treats', 2, 19.99000000, 2, NOW()); INSERT INTO `titles` (`id`, `title`, `category_id`, `price`, `publisher_id`, `created`) VALUES ('MC3021', 'The Gourmet Microwave', 2, 2.99000000, 2, NOW()); INSERT INTO `titles` (`id`, `title`, `category_id`, `price`, `publisher_id`, `created`) VALUES ('MC3026', 'The Psychology of Computer Cooking', 5, 9.99000000, 2, NOW()); INSERT INTO `titles` (`id`, `title`, `category_id`, `price`, `publisher_id`, `created`) VALUES ('PC1035', 'But Is It User Friendly', 3, 22.95000000, 3, NOW()); INSERT INTO `titles` (`id`, `title`, `category_id`, `price`, `publisher_id`, `created`) VALUES ('PC8888', 'Secrets Of Silicon Valley', 3, 20.99000000, 3, NOW()); INSERT INTO `titles` (`id`, `title`, `category_id`, `price`, `publisher_id`, `created`) VALUES ('PC9999', 'Net Etiquette', 3, 5.99000000, 3, NOW()); INSERT INTO `titles` (`id`, `title`, `category_id`, `price`, `publisher_id`, `created`) VALUES ('PS2091', 'Is Anger the Enemy', 4, 10.95000000, 1, NOW());
Create Models
The model in app/models/title.php sports the new $belongsTo property, which notes what associations this model has.
<?php class Title extends AppModel { var $name = 'Title'; // required for php4 installs var $belongsTo = 'Category,Publisher'; } ?>
And we just start with empty models for Publisher and Category.
app/models/publisher.php
<?php class Publisher extends AppModel { var $name = 'Publisher'; // required for php4 installs var $hasMany = 'Title'; } ?>
app/models/category.php
<?php class Category extends AppModel { var $name = 'Category'; // required for php4 installs var $hasMany = 'Title'; } ?>
Create Controllers
Note how set() methods are used in the add() method; two local variables ($cats and $pubs) are filled with data in array shape for use in the view; afterwards, these are set() to actually be passed on.
The set() approach is also used in the edit() method.
app/controllers/titles_controller.php
<?php class TitlesController extends AppController { var $name = 'Titles'; // required for PHP4 installs function index() { $this->set('data', $this->Title->findAll()); } function view($id) { $this->set('data', $this->Title->read()); } function add() { $this->set('cats', $this->Title->Category->generateList()); $this->set('pubs', $this->Title->Publisher->generateList()); if(empty($this->params['data'])) { $this->render(); } else { if($this->Title->save($this->params['data'])) { $this->flash('Your title has been saved.','/titles'); } else { $this->render(); } } } function delete($id) { if ($this->Title->del($id)){ $this->flash('The title with id: '.$id.' has been deleted.', '/titles'); } } function edit($id=null) { if (empty($this->params['data'])) { $this->params['data'] = $this->Title->read(); $this->set('cats', $this->Title->Category->generateList()); $this->set('pubs', $this->Title->Publisher->generateList()); $this->render(); } else { if ( $this->Title->save($this->params['data'])) { $this->flash('The title has been updated.','/titles'); } else { $this->render(); } } } } ?>
and the beginning of app/controllers/categories_controller.php
<?php class CategoriesController extends AppController { var $name='Categories'; } ?>
and app/controllers/publishers_controller.php
<?php class PublishersController extends AppController { var $name='Publishers'; } ?>
Create Views
Great! Let’s create a table View - to display the, above, controller $data!
app/views/titles/index.thtml
<h1>Titles</h1>
<table>
<tr>
<th>Id</th>
<th>Title</th>
<th>Category</th>
<th>Price</th>
<th>Publisher</th>
</tr>
<?php foreach ($data as $output): ?>
<tr>
<td>
<?php echo $output['Title']['id']?>
</td>
<td>
<?php echo $html->link($output['Title']['title'], "/titles/view/{$output['Title']['id']}/{$output['Publisher']['id']}/{$output['Category']['id']}")?>
<?php echo $html->link('Delete',"/titles/delete/{$output['Title']['id']}/{$output['Publisher']['id']}/{$output['Category']['id']}"); ?>
<?php echo $html->link('Edit',"/titles/edit/{$output['Title']['id']}/{$output['Publisher']['id']}/{$output['Category']['id']}")?></td>
</td>
<td>
<?php echo $output['Category']['name']?>
<?php // not implemented echo $html->link('Edit',"/categories/edit/{$output['Category']['id']}")?></td>
</td>
<td>
<?php //echo $output['Title']['price']; ?>
<?php echo number_format($output['Title']['price'],2); ?>
</td>
<td>
<?php echo $output['Publisher']['name']; ?>
<?php // not implemented echo $html->link('Edit',"/publishers/edit/{$output['Publisher']['id']}")?></td>
</td>
</tr>
<?php endforeach; ?>
<tr>
<td colspan="3">
<?php echo $html->link('Add a new Book Title', '/titles/add') ?>
</td>
</tr>
</table>
Change notice: Note that all the information in $data is put into an array where the model name is a sub-array which holds an array with its properties. $data[’Title’][’price’] for instance.
Change notice: number_format() added to price display for readability in output - dingonv
app/views/titles/add.thtml
<h2>Add Title</h2>
<?php echo $html->formTag('/titles/add')?>
<p>SKU: <?php echo $html->input('Title/id'); ?>
<?php //echo $html->tagErrorMsg('Title/id', 'Sku is required.'); ?>
</p>
<p>Title: <?php echo $html->input('Title/title'); ?>
<?php //echo $html->tagErrorMsg('Title/title', 'Title is required.'); ?>
</p>
<p>Price: <?php echo $html->input('Title/price'); ?>
<?php //echo $html->tagErrorMsg('Title/price', 'price is required.'); ?>
</p>
<p>Category: <?php echo $html->selectTag('Title/category_id', $cats,$html->tagValue('Title/category_id')); ?>
</p>
<p>Publisher: <?php echo $html->selectTag('Title/publisher_id', $pubs, $html->tagValue('Title/publisher_id')); ?>
</p>
<p><?php echo $html->submit('Save'); ?>
</p>
</form>
app/views/titles/edit.thtml
<h2>Edit Title</h2>
<?php echo $html->formTag('/titles/edit'); ?>
<?php echo $html->hidden('Title/id'); ?>
<p>Title: <?php echo $html->input('Title/title'); ?>
<?php echo $html->tagErrorMsg('Title/title', 'Title is required.'); ?>
</p>
<p>Price: <?php echo $html->input('Title/price'); ?>
<?php echo $html->tagErrorMsg('Title/price', 'price is required.'); ?>
</p>
<p>Category: <?php echo $html->selectTag('Title/category_id', $cats, $html->tagValue('Title/category_id')); ?>
</p>
<p>Publisher: <?php echo $html->selectTag('Title/publisher_id', $pubs, $html->tagValue('Title/publisher_id')); ?>
</p>
<p><?php echo $html->submit('Save'); ?></p>
</form>
app/views/titles/view.thtml
<h1><?php echo $data['Title']['title']; ?></h1>
<p><small>Cost: <?php echo $data['Title']['price']; ?></small></p>
<p><small>Publisher: <?php echo $data['Publisher']['name']; ?></small></p>
<p><small>Category: <?php echo $data['Category']['name']; ?></small></p>
As you can see, the $data array has an added dimension now. Each view table (using the model $hasOne association) has its own sub-arrays with table field elements.
(Will update more at a later date.)