Using the Bake code generator
It's not necessary to completely throw away everything scaffolding gives you. By using Bake, the CakePHP code generator, you can generate a controller that contains functions that represent the scaffolding functionality and the views to go with it. For the products-related parts of Tor, this will be a huge time-saver.
In CakePHP V1.1, Bake was a PHP script that you called directly. Starting
with CakePHP V1.2, the Bake functionality moved to the Cake
Console, which you will learn about through the rest of
this tutorial. You can simplify your life if you add the path
/webroot/app/Console to your environment's
PATH variable.
This will allow you to call
the Cake Console without specifying path information. You don't need
to do this, and the tutorial will assume you have not.
Additionally,
you should run the Cake Console from your application's app
directory—in this case, /webroot/app—or the Cake Console will
think you are trying to do something new.
Before you proceed, make a copy of your existing app directory. Bake
will overwrite the products controller, and you should always back up
your files when an operation involves the word "overwrite" (or the
words "copy," "delete," "format," or "voodoo").
If you have problems
getting this to run, make sure the php
executable is in your environment's PATH
variable, and that you have the PHP Command Line Interface installed.
Baking your products controller
To use Bake, cd into the /webroot/app
directory and launch the Cake Console:
../cake/Console/cake bake. You should be
presented with a screen that looks like Figure 2.
Figure 2. Bake menu
For the Tor application, the models you've written should be fine, so let's start with the controller. Press C to select the controller. The Cake Console will look at the application as it stands, ask you which database config you want to use, and present a list of possible controllers you might want to bake (see Figure 3).
Figure 3. Controller name
In this case, you are baking the Products controller, which should be controller No. 2. Bake will ask if you want to build the controller interactively. For now, press N to let Bake make all the decisions on its own, but later on, you should try building a controller interactively to get a feel for what Bake can do for you beyond this. Bake will then ask if you want to include some basic class methods (see Figure 4). Press Y—getting this code is the whole reason you are here. Next, Bake will ask if you want to create methods for admin routing. Press N—you don't need these right now. Bake will ask you to confirm the controller before continuing. When you continue, Bake will make sure you want to overwrite the existing controller (in this case, you do). Bake should then inform you that it's created the file /webroot/app/Controller/ProductsController.php and ask if you want to bake some unit test files. You can skip these for now. Once you are done, you will be returned to the Bake menu (see Figure 4).
Figure 4. Controller created
That's all there is to it. Exit the Cake Console, open up app/Controller/ProductsController.php and look at what Bake did for you. It should look something like Listing 9.
Listing 9. ProductsController.php after Bake
<?php
App::uses('AppController', 'Controller');
/**
* Products Controller
*
* @property Product $Product
*/
class ProductsController extends AppController {
/**
* index method
*
* @return void
*/
public function index() {
$this->Product->recursive = 0;
$this->set('products', $this->paginate());
}
/**
* view method
*
* @param string $id
* @return void
*/
public function view($id = null) {
$this->Product->id = $id;
if (!$this->Product->exists()) {
throw new NotFoundException(__('Invalid product'));
}
$this->set('product', $this->Product->read(null, $id));
}
/**
* add method
*
* @return void
*/
public function add() {
if ($this->request->is('post')) {
$this->Product->create();
if ($this->Product->save($this->request->data)) {
$this->Session->setFlash(__('The product has been saved'));
$this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('The product could not be saved.
Please, try again.'));
}
}
$dealers = $this->Product->Dealer->find('list');
$this->set(compact('dealers'));
}
/**
* edit method
*
* @param string $id
* @return void
*/
public function edit($id = null) {
$this->Product->id = $id;
if (!$this->Product->exists()) {
throw new NotFoundException(__('Invalid product'));
}
if ($this->request->is('post') || $this->request->is('put')) {
if ($this->Product->save($this->request->data)) {
$this->Session->setFlash(__('The product has been saved'));
$this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('The product could not be saved.
Please, try again.'));
}
} else {
$this->request->data = $this->Product->read(null, $id);
}
$dealers = $this->Product->Dealer->find('list');
$this->set(compact('dealers'));
}
/**
* delete method
*
* @param string $id
* @return void
*/
public function delete($id = null) {
if (!$this->request->is('post')) {
throw new MethodNotAllowedException();
}
$this->Product->id = $id;
if (!$this->Product->exists()) {
throw new NotFoundException(__('Invalid product'));
}
if ($this->Product->delete()) {
$this->Session->setFlash(__('Product deleted'));
$this->redirect(array('action' => 'index'));
}
$this->Session->setFlash(__('Product was not deleted'));
$this->redirect(array('action' => 'index'));
}
}
|
This controller that you generated using the Cake Console contains the same basic functionality you got from scaffolding, but now you can tweak it to fit your needs. Pretty slick. Ready to go again?
Now that you've baked the products controller, all Tor needs is some
product views. Bake will do those for you, too.
Start as before in
your /webroot/app directory:
../cake/Console/cake bake.
The initial Bake menu should look just like it did when you baked the controller. This time, though, it's time to bake some views. Press V to select views. You will get another list of possible views to be baked. Products should still be No. 2 on the list. Bake will ask if you want to build your views interactively (No). You can come back later and play around with the different baking options.
Once you get past the options, Bake should inform you that it created the views (see Figure 5).
Figure 5. Bake informs you that it has created the views
Exit the Cake Console, open the app/views/products/index.ctp view, and take a look. It should look something like Listing 10.
Listing 10. The index
<div class="products index">
<h2><?php echo __('Products');?></h2>
<table cellpadding="0" cellspacing="0">
<tr>
<th><?php echo $this->Paginator->sort('id');?></th>
<th><?php echo $this->Paginator->sort('title');?>
</th>
<th><?php echo $this->Paginator->sort('dealer_id');?>
</th>
<th><?php echo $this->Paginator->sort('description');?>
</th>
<th class="actions"><?php echo __('Actions');?></th>
</tr>
<?php
foreach ($products as $product): ?>
<tr>
<td><?php echo h($product['Product']['id']); ?> </td>
<td><?php echo h($product['Product']['title']); ?>&snbsp;</td>
<td>
<?php echo $this->Html->link($product['Dealer']['title'],
array('controller' => 'dealers', 'action' => 'view', $product['Dealer']
['id'])); ?>
</td>
<td><?php echo h($product['Product']['description']); ?>
</td>
<td class="actions">
<?php echo $this->Html->link(__('View'), array('action' =>
'view', $product['Product']['id'])); ?>
<?php echo $this->Html->link(__('Edit'), array('action' =>
'edit', $product['Product']['id'])); ?>
<?php echo $this->Form->postLink(__('Delete'),
array('action' => 'delete', $product['Product']['id']), null, __('Are you sure you
want to delete # %s?', $product['Product']['id'])); ?>
</td>
</tr>
<?php endforeach; ?>
</table>
<p>
<?php
echo $this->Paginator->counter(array(
'format' => __('Page {:page} of {:pages}, showing {:current} records out
of {:count} total, starting on record {:start}, ending on {:end}')
));
?> </p>
<div class="paging">
<?php
echo $this->Paginator->prev('< ' . __('previous'), array(), null,
array('class' => 'prev disabled'));
echo $this->Paginator->numbers(array('separator' => ''));
echo $this->Paginator->next(__('next') . ' >', array(), null,
array('class' => 'next disabled'));
?>
</div>
</div>
<div class="actions">
<h3><?php echo __('Actions'); ?></h3>
<ul>
<li><?php echo $this->Html->link(__('New Product'),
array('action' => 'add')); ?></li>
<li><?php echo $this->Html->link(__('List Dealers'),
array('controller' => 'dealers', 'action' => 'index')); ?> </li>
<li><?php echo $this->Html->link(__('New Dealer'),
array('controller' => 'dealers', 'action' => 'add')); ?> </li>
</ul>
</div>
|
Take a look in the those other views, as well. That's a whole lot of writing you didn't have to do. You'll be tweaking these views later to help lock down Tor.
You've baked a controller and the necessary views for the products
functionality. Take it for a spin. Start at
http://localhost/products and walk through
the various parts of the application. Add a product. Edit one. Delete
another. View a product.
It should look exactly like it did when you
used scaffolding.
This isn't the end of what Bake can do for you. There will be a couple exercises at the end of the tutorial to let you venture out on your own. Keep in mind that the code generated by Bake is intended to be your starting point, not the end of your development work. But it's a tremendous time-saver if used properly.




