Part 2: The Cake Code
this content element requires the Flash 7.0 player. You can download it here
written by: gwoo aka Garrett Woodworth
The database is now setup so lets begin creating the code to connect the bulletin board.
The Model
First we create the Models so we can use Cake methods to access the db.
in /app/models/bulletin_board.php
<?php
class BulletinBoard extends AppModel {
var $name ='BulletinBoard';
var $belongsTo = 'User';
}
?>
in /app/models/user.php
<?php
class User extends AppModel {
var $name ='User';
}
?>
From these models we see that BulletinBoard is associated with User. You may have noticed the user_id field in the bullentin_boards table. This is the foreignKey for the association and makes it easier to access the User data from the BulletinBoard.
The Controller
Now we create the BulletinBoardsController to handle all the fun stuff.
in /app/controllers/bulletin_boards_controller.php
<?php
class BulletinBoardsController extends AppController {
var $name ='BulletinBoards';
var $scaffold;
}
?>
The above code is the basic CakePHP class with scaffolding enabled. There is more example Cake code on the Cake Wiki
Check your Scaffolding
- Check out the Scaffolding index for this example.
- Now check your own:
http://localhost/amfBB/bulletin_boards/index
- if you are not seeing the scaffolded controller, then you most likely need to enable mod_rewrite and set AllowOverride ALL for the Document Root in your apache config
- Or the best place to ask a question and problem solve is to the Cake IRC chat channel: #cakphp at irc.freenode.net
- Check out your cakebrowser to see your CakeAmfPhp classes. http://localhost/amfBB/app/vendors/cakeamfphp/cakebrowser/
Now that Scaffolding is working, we can add some code to the Controller and tell AMFPHP about our Cake Controller class. This code is sectioned into parts to describe each function. If you would like the whole class, scroll to the bottom.
<?php
class BulletinBoardsController extends AppController {
var $name ='BulletinBoards';
var $scaffold;
var $methodTable;
function BulletinBoardsController() {
//Define the methodTable
$this->methodTable = array(
"amfCreate" => array(
"description" => "Inserts data from flash into DB",
"access" => "remote"
),
"amfRead" => array(
"description" => "Read data from DB and pass back recordset",
"access" => "remote",
)
);
parent::__construct();
}
}
?>
We just added a constructor used by amfphp to determine the methods it has available.
*Make sure to call Cake's parent constructor.
You see that we defined two methods, amfCreate and amfRead. We provided some nice descriptions to know what they are going to do.
We will look at the amfCreate method first. This method looks a bit
muddied because we wanted to show how associations in CakeAMFPHP can work.
The first things to notice are *$this->autoRender = false;* and the *$this->constructClasses();*. You can see the code
comments, but basically, these two things should be done for every method that will connect to via amf.
So, in this method I want to add the user to the users table and the message
to the bulletin_boards table. So, first we check if the user exists by doing a *findByName*.
*findBy
function amfCreate($message, $user)
{
$this->autoRender = false;//make sure cake does not want to render a view, cause this is a amf method
$this->constructClasses();//this will create the models needed for this method
$this->params['data']['BulletinBoard'] = $message;//set the cake data for the bulletin board
//see if the user name exists
$oldUser = $this->BulletinBoard->User->findByName($user['name']);//User is associated with BulletinBoard
//if not then insert a new user
if(empty($oldUser))
{
$this->params['data']['User'] = $user;
if(!$this->BulletinBoard->User->save($this->params['data']['User']))
{
return array("status" => "fail");
}
$this->params['data']['BulletinBoard']['user_id'] = $this->BulletinBoard->User->getLastInsertId();
}
else//use the old user
{
$this->params['data']['BulletinBoard']['user_id'] = $oldUser['User']['id'];
}
//save the message
if($this->BulletinBoard->save($this->params['data']['BulletinBoard']))
{
return array("status" => "success");
}
else
{
return array("status" => "fail");
}
}
Now that we can insert data, we need a way to read it back. We want to use recordsets so that large chunks of data will get to flash quickly. In reality, I think any time we can use recordsets, we should. So, below is the amfRead method add to the bottom of our BulletinBoardsController.
function amfRead($offset = '0', $limit='10')
{
$this->autoRender = false;
$this->constructClasses();
$page = intval($offset / $limit) + 1;//cake uses pages not offsets
$this->BulletinBoard->findAll(null,null,'BulletinBoard.created DESC',$limit,$page);
$db = &ConnectionManager::getDataSource($this->BulletinBoard->useDbConfig);//get the db object so amfphp can pack it and send it
return $db;
}
Looking up at the amfRead method, we see two params coming in from flash. The offset or starting point for getting the records and the limit to the number that will be returned. As, the code comment tells us Cake uses pages instead of offsets, so we need to convert the data coming from flash. Of course, we could have change our flash code, but we didn't. So, we do the findAll, get the newest records. Then we return the *db* object. You could of course return the full array, but that would be too slow. In some instances just returning the find directly will be suitable. But here we want amfphp via the CakeMySqlAdapter to pick up the db object and pack things nicely into a recordset.
Wow, we got amf creating and reading pretty fast. Now we just need to setup a simple template for the view. First, we will add the helpers that we are going to use. You can see the var $helpers in the properties of the class. In this array we put Html, which is used a the layout along with Javascript, which is used to include the UFO.js file, and lastly we have the Cakeamfphp helper, which is a wrapper for the UFO.js. Then, we add the *view* method to the bottom of the BulletinBoardsController and the class will be complete.
<?php
class BulletinBoardsController extends AppController {
var $name ='BulletinBoards';
var $scaffold;
var $methodTable;
var $helpers = array('Html','Javascript','Cakeamfphp');
function BulletinBoardsController() {
//Define the methodTable
$this->methodTable = array(
"amfCreate" => array(
"description" => "Inserts data from flash into DB",
"access" => "remote"
),
"amfRead" => array(
"description" => "Read data from DB and pass back recordset",
"access" => "remote",
)
);
parent::__construct();
}
function amfCreate($message, $user)
{
$this->autoRender = false;//mae sure cake does not want to render a view, cause this is a amf method
$this->constructClasses();//build the models here since we are not going through cake's dispather
$this->params['data']['BulletinBoard'] = $message;//set the cake data for the bulletin board
//see if the user name exists
$oldUser = $this->BulletinBoard->User->findByName($user['name']);
//if not then insert a new user
if(empty($oldUser))
{
$this->params['data']['User'] = $user;
if(!$this->BulletinBoard->User->save($this->params['data']['User']))
{
return array("status" => "fail");
}
$this->params['data']['BulletinBoard']['user_id'] = $this->BulletinBoard->User->getLastInsertId();
}
else//use the old user
{
$this->params['data']['BulletinBoard']['user_id'] = $oldUser['User']['id'];
}
//save the message
if($this->BulletinBoard->save($this->params['data']['BulletinBoard']))
{
return array("status" => "success");
}
else
{
return array("status" => "fail");
}
}
function amfRead($offset = '0', $limit='10')
{
$this->autoRender = false;
$this->constructClasses();
$page = intval($offset / $limit) + 1;//cake uses pages not offsets
$this->BulletinBoard->findAll(null,null,'BulletinBoard.created DESC',$limit,$page);
$db = &ConnectionManager::getDataSource($this->BulletinBoard->useDbConfig);//get the db object so amfphp can pack it and send it
return $db;
}
function view(){}
}
?>
Yeah, its cool, only one line: function view(){} in the controller. Not much more to display the movie using the cakeamfphp helper.
Layout
Before getting into the view, we want to make sure we have the proper layout.
Create a default.thtml- copy and paste the code below into /app/views/layouts/default.thtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>CakePHP : A Rapid Development Framework :: <?php echo $title_for_layout?></title>
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" />
<?php echo $html->charset('UTF-8')?>
<?php echo $html->css('cake.default')?>
<!--[if lt IE 7]>
<?php echo $html->css('cake.ie');?>
<![endif]-->
<?php
if(isset($javascript))
echo $javascript->link('ufo');
?>
</head>
<body>
<div id="wrapper">
<div id="header">
<?php echo $html->image('cake.logo.png', array('alt'=>'CakePHP : Rapid Development Framework', 'border'=>"0"))?>
</div>
<div id="content">
<?php if (isset($this->controller->Session)) $this->controller->Session->flash(); ?>
<?php echo $content_for_layout?>
</div>
<?php echo $cakeDebug;?>
<div id="footer">
<p>CakePHP ::
<a href="http://www.cakefoundation.org/pages/copyright/">© 2006 Cake Software Foundation, Inc.</a>
</p>
<br />
<p>
<!--PLEASE USE ONE OF THE POWERED BY CAKEPHP LOGO-->
<a href="http://www.cakephp.org/" target="_new">
<?php echo $html->image('cake.power.png', array('alt'=>'CakePHP : Rapid Development Framework',
'height' => "15",
'width' => "80"))?>
</a>
</p>
</div>
</div>
</body>
</html>
The above layout is basically a copy of the default cake layout. But we added the javascript call so the ufo.js will be included. This allows us to use the cakeamfphp helper to display our flash movies. Check out the CakePHP manual for more info.
The View
After we add the method to the controller, we need to create the corresponding view template
Create a view.thtml
- copy and paste the code below into /var/www/amfBB/app/views/bulletin_boards/view.thtml
<?php
echo $cakeamfphp->placeFlash('/swf/BulletinBoard-flash7.swf', '540' , '460' , '7');
?>
we are calling the location, setting the width, then height and the minimum version of the flash player.
Done.
That's all we need on the PHP side of things, so move on to step three if you are ready.
- Part 1: Getting Setup
- Part 3: The AS Code
