File Under: Databases, Programming

Cake and Trax for Beginners

In my last article, Building With Ajax and Rails I made a faintly disparaging joke about some new web frameworks that have been created in fond imitation of Rails. I got a lot of feedback about that joke. I’m not allowed to comment here about the pending lawsuits, but I would ask that the drive-by eggings of my house and threats to my family please cease. (They’ve been relocated to a secret Webmonkey farm anyway.)

Today we’re going to take a look at a couple of those frameworks for PHP:Trax and Cake. Both attempt to bring the quick, easy, helpful tools and easily understood, easily maintained structure of Rails to PHP — a boon to web developers who know PHP and perhaps have some keeper code in that language, but can’t resist the Rails buzz. Both Trax and Cake use the same model-view-controller pattern and Active Record ways of addressing data that Rails does. Makes one curious, no? I don’t have time to get deeply into them today, but both stress “rapid development,” so let’s see if I, your average not-too-bright web developer, can get a little app off the ground before the end of this article.


Contents

  1. Cutting into Cake
  2. Makin’ Trax
  3. Hardly the End of the Story
  4. Helpful Links



Cutting into Cake

This is 100 percent true:At lunch yesterday, my fortune cookie said “A nice cake is waiting for you.” So, I am going to start with Cake first and try Trax later.

I go to the Cake site and download the latest stable release (discouragingly called 1.1.19.6305) onto my Debian web server running Apache and PHP 5. Unzipping the tarchive, I immediately see some names that look familiar from Rails:app, config and something called dispatcher.php. The app directory looks even friendlier. It contains views, controllers, model – just like Rails!

There’s also a webroot directory, which I assume is going to be the root of my application. Indeed, look at that! If I browse to http://my.web.server/trax_and_cake_playground/cake/app/webroot, I see a friendly boilerplate intro page. Later, if I decide I want to use Cake full time, I’ll add a line to my Apache configuration to set that directory as the whole server’s root directory. At the moment, the page is extolling Cake’s coolness and warning me, “Your database configuration file is not present.”

Correct, it’s not. I find a sample database configuration in app/config/database.php.default. I’ll copy that sample to an actual working file, database.php, in the same directory. The file includes an array of settings, which I change to suit my own environment:


var $default = array('driver'   => 'mysql',



                  'connect'  => 'mysql_pconnect',



                  'host'     => 'localhost',



                  'login'    => 'paul',



                  'password' => 'passw0rd',



                  'database' => 'bookmarker' );




Now, when I reload the intro page, it tells me, “Your database configuration file is present. Cake is able to connect to the database.” Yay!

Now, I’ve told it I have a MySQL database called “bookmarker,” but that’s not true yet. I still have to create it. I’m eager to get rolling, so I’ll just recycle the code from Webmonkey’s Ruby on Rails for Beginners article in which I built a bookmarking app. This time I also want to populate the table with a little starter data, to give us something to work with. So I type:

 $mysql



 mysql> CREATE DATABASE bookmarker;



 mysql> USE bookmarker;



 mysql> CREATE TABLE bookmarks (



    ->  id SMALLINT (5) NOT NULL auto_increment,



    ->  url VARCHAR (255),



    ->  name VARCHAR (100),



    ->  description VARCHAR (255),



    ->  PRIMARY KEY (id)



    -> );



 mysql> INSERT INTO bookmarks (url, name, description) VALUES



 ('http://webmonkey.com/', 'Webmonkey', 'Not the only monkey that makes



 websites, but the best!');



 mysql> INSERT INTO bookmarks (url, name, description) VALUES



 ('http://ubuntu.com/', 'Ubuntu', 'Linux for human beings (no monkeys



 please!)');



 mysql> exit;



At this point in developing a Rails app, I’d run the built-in scaffold-generating tool. Here in Cakeland, I see a file called bake.php in cake/scripts, and instantly I pick up on the metaphor – bake a cake, get it? Turns out that’s a false start, as bake.php doesn’t seem to work in the pre-beta. It’s giving me all sorts of fatal errors and files not found. I’m going to have to create my model, view and controller by hand-editing code.

The app/models directory contains an empty file called put_models_here. So, I do just that, creating a file in that directory called bookmark.php:

 <?php



 class Bookmark extends AppModel



 {



     var $name = 'Bookmarks';



    function display()



     {



         $this->set('data',$this->Bookmark->findAll());



     }



 }



 ?>

That puts the data from the table in $data, using the built-in set method. You might want to read along in the Cake API documentation – I certainly am!

Then I create a controller, app/controllers/bookmarks_controller.php:

 <?php



 class BookmarksController extends AppController



 {



     var $name = 'Bookmarks';



 }



 ?>

I will also need to create a view. In the app/views directory, I create a subdirectory called bookmarks and a file called index.thtml inside of the subdirectory. The “t” in the file extension is for template, I assume. Note that I have had to scratch around in some slightly opaque documentation to glean all this – not as polished as Rails, not yet at least! In index.thtml I just put together a little foreach loop to display my content:

<?php



 echo "<p><table>";



 foreach ($data as $bookmark):



      echo "<tr><td>";



      echo $html->link($bookmark['Bookmark']['name'],



 $bookmark['Bookmark']['url']);



      echo "</td><td><b>";



      echo $bookmark['Bookmark']['description'];



      echo "</b></td></tr>";



 endforeach;



 echo "</table><p>";



 ?>




Finally, I need to add routing in order to tell Cake where my little app is and what to do with it. In app/config/routes.php I add a line:

 $Route->connect ('/bookmarks/*', array('controller'=>'bookmarks',



 'action'=>'display'));

Note that the action, “display”, corresponds to the method I defined in my controller.

Now all the pieces are in place at last. I browse to http://my.web.server/trax_and_cake_playground/cake/index.php/ bookmarks (I can clean up that ugly URL later) and lo! The boilerplate page is now displaying the preliminary bookmarks I put in my table! I am up and running. In Rails, at this point, I would have some nice auto-generated methods to add and delete bookmarks. Hopefully Cake’s auto-bake feature will come together soon.

Next, let’s take a look at Trax.


Makin’ Trax

Quick now, we know the drill. Go to the Trax site, download the archive, untar it. Like all of these prima-donna frameworks, Trax wants to be the top level of my web hierarchy, or rather it wants its public directory to be, and its trax directory to be parallel at the same level, out of sight of prying eyes. If my web server were publicly accessible, I’d put it up there, or find a way around that limitation. For now I’ll just unzip it in my playground (so to speak). Whoo!

Already now, if I go to http://my.web.server/trax_and_cake_playground/trax/public/, I have a page telling me “Congratulations, you’ve put PHP on Trax!” I feel good.

Trax does have a working auto-generate function, which is very nice, because I am getting tired of hand-editing all these files. If I wanted to do that, I’d be writing Perl or something. Still, there are a few more steps. I need to install the PEAR modules that Trax requires, which I do on the command-line:

 pear install Mail_Mime

I’ll use the same database and table I created back at the beginning, so long ago. I need to configure trax/config/database.ini to tell the application where they are:

    phptype = mysql



    database = bookmarker



    hostspec = localhost



    username = paul



    password = passw0rd



    persistent = 1

And then I need to edit public/.htaccess to tell the application where in my file system its own configuration is. The start of that file reads:

 # php include path for Trax ( Pear & Trax config dir )



 php_value include_path



 .:/usr/local/lib/php:/home/<username>/trax/config

I change it to suit my Debian setup:

 # php include path for Trax ( Pear & Trax config dir )



 php_value include_path .:/usr/share/php:/var/www/html/trax/trax/config

Now I am ready to — make Trax? Lay down Trax? There doesn’t seem to be a catchy verb for auto-generating models and controllers and views here. I, um, look both ways and prepare to cross the Trax.

The script that does the work is trax/script/generate.php. First, I need to edit the first line of that file to point to where my PHP executable actually is. Not /usr/local/bin/php, as the default has it. Mine is at /usr/bin/php. Also, the script seems to be happiest if I add my path information there as well, so toward the beginning of the file I enter the following:

 ini_set("include_path", ".:/usr/share/php:/var/www/html/trax/trax/config"); 

While I’m at it, I’ll add the same line to public/dispatch.php.

Then I need to make generate.php executable with a deft chmod a+x.

Now I’m ready to run the generate script, which I do from the command line. If your server doesn’t like PHP scripts to be run from the command line, you’ll have to open the script in a browser. I type this:

 ./trax/script/generate.php model Bookmark 

and Trax replies:

 created /var/www/html/trax/trax/app/models/bookmark.php 

Then I type:

 ./trax/script/generate.php controller bookmark display add 

and Trax replies:

created /var/www/html/trax/trax/app/controllers/bookmark_controller.php



 created /var/www/html/trax/trax/app/helpers/bookmark_helper.php



 created /var/www/html/trax/trax/app/views/bookmark/display.phtml



 created /var/www/html/trax/trax/app/views/bookmark/add.phtml


“Display” and “add” are the initial views I want. Finally (I hope), I just need to add routing, so I can view my views in a browser. I add the following to trax/config/routes.php:

 $router->connect( "", array(":controller" => "bookmark") ); 

and voila! I can see a page! True, it’s blank, which means that I need to flesh out my actions and views. But it is a page! Let me just put in a couple of basics.

In trax/app/controllers/bookmark_controller.php, there’s an empty definition of the view() method. I’ll put this in:

 function view() {



        $bookmark = new Bookmark();



        $this->bookmarks = $bookmark->find_all();



    }




and in app/views/bookmark/display.phtml I put a PHP table similar to the one I used for Cake, to loop through the bookmarks table and display each one.

Whew. Two starter semi-apps built in as many hours. Not too bad.


Hardly the End of the Story

Would I do it again? Are either of the frameworks are 100 percent ready for prime time? Documentation is getting better every day, but neither framework has anything like the whopping user community of Rails.

I was able to iron out my own snags — several had to do with permissions, Apache directory overrides, and stuff like that – but if I couldn’t, it would be nice to have more resources to turn to. Conversely, PHP has a considerably larger support community on the Web than Ruby does, although that tide may slowly be turning.

Trax and Cake aren’t the end of the PHP dev framework story:there’s Symfony; Zend has a framework and a quick trawl of the web turns up things like PHP2Go, Qcodo and doubtless many more.

Rails is a pleasure to use, while Trax and Cake combine pleasure with a bit of effort. If you’re a PHP wiz, though, the fact that they’re based in a language you know should more than outweigh any difficulties brought on by the frameworks’ immaturity. It’s easier to debug a stuck app than to learn a whole new language, even one as perspicuous and enjoyable as Ruby.

So tune in next time when we cover Brails, the new web programming framework for the visually impaired! That’s a joke. Don’t sue.


Helpful Links