CakePHP Tutorial No. 1 From IBM
CakePHP Tutorial No. 1 From IBM
Getting started
Quick and easy PHP rapid-development aid
21 Nov 2006
Getting started
© Copyright IBM Corporation 1994, 2006. All rights reserved. Page 1 of 36
developerWorks® ibm.com/developerWorks
• MVC design
• Helpers
• CakePHP data validation
Prerequisites
It is assumed that you are familiar with the PHP programming language, have a
fundamental grasp of database design, and are comfortable getting your hands dirty.
A full grasp of the MVC design pattern is not necessary, as the fundamentals will be
covered during this tutorial. More than anything, you should be eager to learn, ready
to jump in, and anxious to speed up your development time.
System requirements
Before you begin, you need to have an environment in which you can work.
CakePHP has reasonably minimal server requirements:
2. PHP V4.3.2 or later (including PHP V5). This tutorial was written using
Getting started
Page 2 of 36 © Copyright IBM Corporation 1994, 2006. All rights reserved.
ibm.com/developerWorks developerWorks®
PHP V5.0.4
You'll also need a database ready for your application to use. The tutorial will
provide syntax for creating any necessary tables in MySQL.
The simplest way to download CakePHP is to visit CakeForge.org and download the
latest stable version. This tutorial was written using V1.1.8. (Nightly builds and
copies straight from Subversion are also available. Details are in the CakePHP
Manual (see Resources).)
Section 2. Installation
CakePHP wants to make your life easier, regardless of your level of experience, by
making your applications easier to maintain and quicker to write. CakePHP is full of
cool and useful features. CakePHP wants to handle your Ajax, your data validation,
your sessions. It will even slice your bread if you can write a plug-into tell it how. But
you can't use CakePHP yet. You need to install it first.
unzip cake_1.1.8.3544.zip
cd cake_1.1.8.3544
mv * /webroot
Type ls -la /webroot to list the contents of the webroot and verify that the files
have been moved properly. The output should look something like Listing 2.
The directory app/tmp needs to be writable by your Web server. Confirm the
Getting started
© Copyright IBM Corporation 1994, 2006. All rights reserved. Page 3 of 36
developerWorks® ibm.com/developerWorks
permissions on this folder by typing ls -l app. The output will probably look
similar to Listing 3.
The simplest way to accomplish this is probably the most common and least secure:
give write permissions to everyone:
The permissions for the tmp folder should have been updated, as shown below:
Giving write permissions to everyone is not recommended for general use. Ideally,
you should change the ownership of this folder to match the used that the Web
server uses, or add the user that the Web server uses to a the group for the
directory and add group write permissions. This tutorial is intended to demonstrate
how to use CakePHP and is not designed to be a guide for building secure
applications. While security should be at the head of any application development, a
full discussion of secure PHP practices is outside the scope of this tutorial.
For a production installation, change the webroot of the Web server to app/webroot,
which will minimize the amount of code accessible via the Web browser and help
enhance the security of your installation.
Validation 1
In a browser, go to the URL that corresponds with the webroot for your Web server.
For example, if you've installed CakePHP into the webroot of your localhost, go to
http://localhost; you should see the CakePHP default home page.
Getting started
Page 4 of 36 © Copyright IBM Corporation 1994, 2006. All rights reserved.
ibm.com/developerWorks developerWorks®
Note: If the default home page looks more like Figure 2, then mod_rewrite is not
working the way CakePHP requires. This can sometimes be a problem for first-time
users.
Getting started
© Copyright IBM Corporation 1994, 2006. All rights reserved. Page 5 of 36
developerWorks® ibm.com/developerWorks
You should have gotten an .htaccess file in the CakePHP installation directory. On
most *nix systems, this will be hidden from view by default. If you do not have the
file, check the source you downloaded or get a fresh update from CakePHP.org.
Confirm that the file exists and is valid by going to the installation directory and
running cat .htaccess. This will display the file's contents, which should look like
Listing 4.
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteRule ^$ app/webroot/ [L]
RewriteRule (.*) app/webroot/$1 [L]
</IfModule>
Getting started
Page 6 of 36 © Copyright IBM Corporation 1994, 2006. All rights reserved.
ibm.com/developerWorks developerWorks®
Make sure that mod_rewrite is enabled for your Web server. For Apache, there
are two different lines that should appear in the httpd.conf file. In the LoadModule list
you should see the following line (or something very close): LoadModule
rewrite_module libexec/mod_rewrite.so.
In the AddModule list, you should see this line (or something very close):
AddModule mod_rewrite.c.
If you cannot find these lines in your httpd.conf file, mod_rewrite is not enabled.
Consult your server documentation for details on how to do this.
Make sure your Web server is configured to allow .htaccess override. For Apache,
each directory should be defined in the httpd.conf file. These definitions can look
very different from installation to installation, but you should still see the line
AllowOverride All in the definition. Your definition might look something like Listing 5.
<Directory "/webroot">
Options Indexes MultiViews
AllowOverride All
Order allow,deny
Allow from all
</Directory>
Consult your server documentation for more details about .htaccess override.
Getting started
© Copyright IBM Corporation 1994, 2006. All rights reserved. Page 7 of 36
developerWorks® ibm.com/developerWorks
driver
This can be mysql, postgres, sqlite, adodb or pear-drivername. This
tutorial assumes mysql.
connect
This field tells CakePHP whether it should use persistent database
connections. For mysql, the options are mysql_pconnect (persistent) or
mysql_connect (not persistent).
host
This is the hostname of your database server, such as localhost or
mysql.yourdomain.com.
login
This is the username for your database login, such as dbuser.
password
This is the password for your database login, such as secretsecret.
database
This is the name of the database you wish to use, such as cakedev.
prefix
Prefix is a string, such as cp_, that is prepended to table names for any
database call made by CakePHP. Using a prefix may be necessary if the
database is shared among applications to keep tables from stepping on each
other where two or more applications want a table with the same name, such
as users.
Getting started
Page 8 of 36 © Copyright IBM Corporation 1994, 2006. All rights reserved.
ibm.com/developerWorks developerWorks®
Validation 2
Go back to the URL you used to validate the initial installation. You should see that
the CakePHP default home page has changed to indicate the status of your
database configuration.
Getting started
© Copyright IBM Corporation 1994, 2006. All rights reserved. Page 9 of 36
developerWorks® ibm.com/developerWorks
If the default home page says the database configuration file is not present, you may
have put it in the wrong place or misnamed it. Make sure the database configuration
file is app/config/database.php. If the default home page says CakePHP is unable to
connect to the database, confirm that the connection information you entered is valid
and retry.
This table will contain the basic information necessary to identify and interact with a
user. A simple username and password field would probably suffice, but other
information can be useful, such as an e-mail address (for sending password reset
requests), first and last name (for personalization), and last login date (to help track
inactive accounts). You probably want your username and e-mail fields to be unique.
And don't forget the primary key ID field. The SQL to create your table might look
something like Listing 5.
Getting started
Page 10 of 36 © Copyright IBM Corporation 1994, 2006. All rights reserved.
ibm.com/developerWorks developerWorks®
Notice that the username, password, first_name, and last_name fields have a
maximum character length of 40. We will enforce this character length in the user
model. The 40-character maximum length, in this case, is entirely arbitrary.
The MVC design pattern breaks an application into three distinct layers: handling
Data, UI and Logic, respectively. MVC was first described in the book Design
Patterns: Elements of Reusable Object-Oriented Software, also known as the "Gang
Of Four" book. A full discussion of design patterns and MVC is outside the scope of
this tutorial, but it will be helpful to touch on what the three pieces mean --
specifically, in the CakePHP world.
Model
Users, products, prices, messages -- when you boil it all down, it's all just data. You
make sure the data is what you want, it goes into a database, then you have to get it
back out. It will be useful for all the data-handling aspects of Tor to live in one place.
That where model comes in.
Model is primarily concerned with handling data. Getting data from a database,
inserting data into a database, validating data -- all of this takes place within the
Getting started
© Copyright IBM Corporation 1994, 2006. All rights reserved. Page 11 of 36
developerWorks® ibm.com/developerWorks
model.
<?php
class User extends AppModel
{
var $name = 'User';
}
?>
Notice the line var $name = 'User';. It is accepted as best practice to specify
the name of the model in $name.
View
Being able to save, retrieve, and validate your data is pretty useless without some
means of displaying the data. By putting all display and presentation code in one
place, you can change the look and feel of your application without having to work
around application logic and data related code.
View is primarily concerned with formatting data for presentation to the user. The
view represents any and all UI work, including all templates and HTML. CakePHP's
view files are regular HTML files embedded with PHP code.
Ultimately, a view is just a page template. Usually, the view will be named after the
Action associated with it. For example, a display() action would normally have a
display view.
Returning to the sample application, we have created a users table and a user
model to interact with this table. Now we need some views. The user will need to
register an account and log in to the application. This calls for a register and a login
view.
Getting started
Page 12 of 36 © Copyright IBM Corporation 1994, 2006. All rights reserved.
ibm.com/developerWorks developerWorks®
It is important to note that the field names are the same as the column names in
your database. This will come into play when we get to the users controller.
Controller
With data handling all contained within in the model and the presentation layer all
contained within the view, the rest of the application is going to live in the controller.
This is where logic, decision-making, workflow, and generally anything that the
application does will happen. The model manages your data, the view shows it to
you, the controller does everything else.
The controller manages server requests. It accepts user input (URL requests, form
POSTs, GET requests, etc.), applies logic where necessary, invokes models where
data handling is required, and sends output through the appropriate view.
Generally, a controller will manage logic for a single model. A controller contains any
number of functions, referred to as Actions. An action typically applies logic and
displays a view. All user-defined controllers will need to extend the CakePHP
AppController class.
In Tor, you have created a users table, a user model to interact with the table, and
views to present registration and login forms to the user. Those forms will submit to
Getting started
© Copyright IBM Corporation 1994, 2006. All rights reserved. Page 13 of 36
developerWorks® ibm.com/developerWorks
the users controller, invoking the register and login actions, respectively. The users
controller should be created as app/controllers/users_controller.php and should start
out looking something like Listing 8.
<?php
class UsersController extends AppController
{
}
?>
Now you are getting down to the nuts and bolts. The user has filled out a form and
submitted it to the application. We will cover data validation later. For now, we will
just push it into the database. We do this by adding the register action to the users
controller.
<?php
class UsersController extends AppController
{
function register()
{
if (!empty($this->params['form']))
{
if ($this->User->save($this->params['form']))
{
$this->flash('Your registration information was accepted.',
'/users/register');
} else {
$this->flash('There was a problem with your registration',
'/users/register');
}
}
}
}
?>
Once you know the form was submitted with data, the controller calls the save
method on the user model, which is an extension of AppModel. The save method
will, by default, look for a table that's a plural of the model itself. In this case, it is
looking for a users table to go with the user model. If the table is found, the save
method will turn the passed array ($this->params['form']) into an INSERT
statement, using the array keys as column names and the array values as the
INSERT values.
Getting started
Page 14 of 36 © Copyright IBM Corporation 1994, 2006. All rights reserved.
ibm.com/developerWorks developerWorks®
Array
(
[CAKEPHP] => b975a875bdba3bdff38ea0eda8c3375f
[username] => zaphod
[password] => secret
[email] => [email protected]
[first_name] => zaphod
[last_name] => beeblebrox
)
The save method will ignore the CAKEPHP session key and build an INSERT
statement from the rest. It would look something like Listing 11.
INSERT INTO
users
(username, password, email, first_name, last_name)
VALUES
('zaphod', 'secret', '[email protected]', 'zaphod', 'beeblebrox')
It should now be apparent why you used the database column names in the register
view for the register form field names. By doing so, you simplified the process of
saving your data significantly.
To continue, if the data inserts successfully, the register action calls the Flash
method. Flash presents a basic message to the user (in this case, a success or
failure message) with a link away from the message (in this case, back to the
register view, since nothing else has been defined.
Now that you have a user model to interface with your users table, and a register
view to show a registration form, and a users controller with a register action, you
can actually see your application in action.
Try it out
All the pieces have fallen into place. It's time to bring Tor to life. Fire up your browser
and jump in.
Getting started
© Copyright IBM Corporation 1994, 2006. All rights reserved. Page 15 of 36
developerWorks® ibm.com/developerWorks
Fill out and submit the form. You should see your success message.
Getting started
Page 16 of 36 © Copyright IBM Corporation 1994, 2006. All rights reserved.
ibm.com/developerWorks developerWorks®
If you look in your database, you should see a record corresponding to your form
submission, complete with a plaintext password (a terribly bad idea, which we will fix
later).
Try to fill out the form again, using the same information. You should see the failure
message.
Getting started
© Copyright IBM Corporation 1994, 2006. All rights reserved. Page 17 of 36
developerWorks® ibm.com/developerWorks
If you are using a database that supports the UNIQUE field restraint, the registration
will fail. During the creation of the users table, the username and e-mail fields were
defined as UNIQUE, meaning values for those fields cannot be duplicated. CakePHP
recognizes the error when the database throws it and displays an error.
Section 4. Helpers
Helpers in CakePHP exist primarily to help speed up the development of your views.
There are helpers for HTML, Ajax, JavaScript and more. Helpers make it easier to
insert pieces of HTML code you find yourself writing multiple times.
Getting started
Page 18 of 36 © Copyright IBM Corporation 1994, 2006. All rights reserved.
ibm.com/developerWorks developerWorks®
function knownusers()
{
$this->set('knownusers',
$this->User->findAll(null, array('id', 'username', 'first_name',
'last_name'), 'id DESC')
);
}
This calls the built in findAll function on the user model. The findAll function
takes a field containing conditions (in this case, you passed null conditions, which
will return all all users), an array of fields to be returned (we don't want all of the user
information, just what you would want everyone to see), and a sort field and order (in
this case, id DESC to sort the fields in descending order by ID). You can also
specify a limit (maximum rows to return), page (if you are paging the data), and a
recursive option, which can be specified to return models associated with the data
(for example, if you were querying a groups table and several users belong to each
group).
The output from findAll is put into the knownusers variable. The data can now
be accessed from a view.
<pre>
<?php var_dump($knownusers) ?>
</pre>
Getting started
© Copyright IBM Corporation 1994, 2006. All rights reserved. Page 19 of 36
developerWorks® ibm.com/developerWorks
Got a nice big array of users? Good! Time to turn that into a table. Replace the
contents of knownusers.thtml with the following.
<table>
<?php
echo $html->tableHeaders(array_keys($knownusers[0]['User']));
foreach ($knownusers as $thisuser)
{
echo $html->tableCells($thisuser['User'], array('bgcolor' => '#ddd'));
}
?>
</table>
Getting started
Page 20 of 36 © Copyright IBM Corporation 1994, 2006. All rights reserved.
ibm.com/developerWorks developerWorks®
The first helper will create a set of table headers from an array of data -- in this case,
the list of keys for our users.
The second helper will create a set of table cells, wrapped in table row tags, from an
array of data -- in this case, the values for each user. The second parameter,
array('bgcolor' => '#ddd'), tells CakePHP to set the background color for
every odd table for. You could also specify a third parameter containing options for
every even table row.
That's it! Save it, then visit http://localhost/users/knownusers to see the results.
By using the tableCells helper, you have eliminated the need to write your own
code to iterate through the array of user data, and adding different background
colors for the table rows was as simple as specifying the color in the helper. This is
just one example of how to use helpers to make it easier to work with HTML in
CakePHP.
Form generation
Building a Web application without using forms is like milking a chicken: It's
extremely complicated and rarely works. Well-built and maintainable forms are a
foundation to any well-built application. Given how often you will need to build forms,
it only seems natural to look for ways to make the process easier without cutting
corners.
Getting started
© Copyright IBM Corporation 1994, 2006. All rights reserved. Page 21 of 36
developerWorks® ibm.com/developerWorks
Helpers are especially useful when generating forms. You can use them to generate
the HTML for your input fields, as well as placeholders to hold validation error
messages. Using helpers to generate the form fields and error message holders for
Tor, the register view might look more like Listing 15.
You may be looking at this code and comparing it to the hand-built registration form,
and thinking to yourself, "This looks like more code." And it is a little more code. The
real question is what do you gain by doing it this way? And right now, the answer is
nothing -- until you start leveraging the helpers. So, how do you make the most of
them?
function register()
{
if (!empty($this->data))
{
if ($this->User->validates($this->data))
{
$this->User->save($this->data);
$this->flash('Your registration information was accepted.',
'/users/register');
} else {
Getting started
Page 22 of 36 © Copyright IBM Corporation 1994, 2006. All rights reserved.
ibm.com/developerWorks developerWorks®
$this->validateErrors($this->User);
}
}
}
Now open the user model and add a little data validation (covered in detail later). For
now, modify your user model to look like the one below.
<?php
class User extends AppModel
{
var $name = 'User';
var $validate = array(
'username' => VALID_NOT_EMPTY,
'password' => VALID_NOT_EMPTY,
'email' => VALID_EMAIL
);
}
?>
</code>
To break this down briefly, the $validate array contains entries for validation,
consisting of a key (the form field name) and a regular expression used to evaluate
the data. It is not necessary to validate all of the form fields. In Listing 17, last_name
and first_name were left options. CakePHP comes with several predefined regular
expressions for data validation. VALID_NOT_EMPTY is used just to make sure the
field is not empty. VALID_EMAIL is used to verify that a string looks more or less
like an e-mail address.
Now take it for a spin. Try submitting the form with no data, with one or two required
fields empty, with an invalid e-mail address. What do you see?
Getting started
© Copyright IBM Corporation 1994, 2006. All rights reserved. Page 23 of 36
developerWorks® ibm.com/developerWorks
Getting started
Page 24 of 36 © Copyright IBM Corporation 1994, 2006. All rights reserved.
ibm.com/developerWorks developerWorks®
One thing you should notice is that the CakePHP is turning on and turning off your
error messages for you on the fly. Another thing you should notice is that CakePHP
is remembering and populating the values for the form fields, without you having to
do anything.
That's where the big payoff comes in. What didn't you have to do?
For one thing, you didn't have to tell the form fields to repopulate their information
from the _POST array. CakePHP did that for you. You didn't have to check each field
for an error and conditionally display each message individually. CakePHP did that
for you. You didn't have to make sure you formatted your tags into valid xhtml.
CakePHP did that for you, too.
Helper notes
This tutorial barely scratches the surface of helpers. A whole tutorial could probably
be written on the subject. Learning how to use helpers well will go a long way toward
helping speed up your development in CakePHP. To get you started, here are some
Getting started
© Copyright IBM Corporation 1994, 2006. All rights reserved. Page 25 of 36
developerWorks® ibm.com/developerWorks
additional notes.
If all you are ever doing is echoing the output of your helpers, setting AUTO_OUTPUT
to true will help speed things along.
CakePHP uses the file cake/config/tags.ini.php when generating HTML tags. This
file contains template for most common HTML elements. For example, tags.ini.php
contains a template for an input field.
This isn't the end of helpers by a longshot. CakePHP includes helpers for Ajax
(using prototype.js), JavaScript, number conversion, text handling, dates, times, and
more. Review the manual (see Resources) to get more familiar with some of these
helpers.
Getting started
Page 26 of 36 © Copyright IBM Corporation 1994, 2006. All rights reserved.
ibm.com/developerWorks developerWorks®
<?php
class User extends AppModel
{
var $name = 'User';
var $validate = array(
'username' => VALID_NOT_EMPTY,
'password' => VALID_NOT_EMPTY,
'email' => VALID_EMAIL
);
}
?>
This is a good start, but it's not enough. You'll want to make sure the field lengths
are honored and that the username does not already exist. You will accomplish this
by defining your own regular expressions for validation and defining a function to
check the users table for a username before saving the user.
For the username and password fields, you need to validate that the submitted data
is no longer than 40 characters. Though you have specified a maximum length for
the username and password fields in the HTML, it is never safe to assume that the
user is following your rules. For this reason, any client-side data validation should be
verified before use.
It is also helpful to verify that the username and password are at least six characters.
A regular expression to match strings with a length between six and 40 characters
would look something like this: /^.{6,40}$/.
Getting started
© Copyright IBM Corporation 1994, 2006. All rights reserved. Page 27 of 36
developerWorks® ibm.com/developerWorks
<?php
class User extends AppModel
{
var $name = 'User';
var $validate = array(
'username' => '/^.{6,40}$/',
'password' => '/^.{6,40}$/',
'email' => VALID_EMAIL
);
}
?>
Make sure you've saved all your files, go back to http://localhost/users/register, and
try to register a user with a four-character username. You should see something like
Figure 11.
Getting started
Page 28 of 36 © Copyright IBM Corporation 1994, 2006. All rights reserved.
ibm.com/developerWorks developerWorks®
Regular expressions are versatile, but they can't do things like tell you if a username
has already been registered.
function register()
{
$this->set('username_error', 'Username must be between 6 and 40 characters.');
if (!empty($this->data))
{
if ($this->User->validates($this->data))
{
Getting started
© Copyright IBM Corporation 1994, 2006. All rights reserved. Page 29 of 36
developerWorks® ibm.com/developerWorks
if ($this->User->findByUsername($this->data['User']['username']))
{
$this->User->invalidate('username');
$this->set('username_error', 'User already exists.');
} else {
$this->User->save($this->data);
$this->flash('Your registration information was accepted.',
'/users/register');
}
} else {
$this->validateErrors($this->User);
}
}
}
This starts by defining a default value for the username error. You will need to
modify the register view in order to use this.
The action goes on to validate the data using the data validation regular expressions
defined in the model. If any of those validations fail, the form is rejected. If those
validations pass, the built in findByUsername function is called from the user
model. This function will query the User table looking for a value that matches the
passed string (in this case, the value of the username form field) in the username
field. If findByUsername does not find a matching user, a false value will be
returned. In that case, save the data as you normally do.
If a matching user is found, however, the user will be returned. In that case, the
action does two things: $this->User->invalidate('username');.
This invalidates the username field in the form. The tagErrorMsg will then be
automatically triggered: $this->set('username_error', 'User already
exists.');.
The register view will need to be modified to use the value username_error for the
username's tagErrorMsg. Replace the tagErrorMsg line for the username field
with the following.
Getting started
Page 30 of 36 © Copyright IBM Corporation 1994, 2006. All rights reserved.
ibm.com/developerWorks developerWorks®
Good data validation is an important step in creating any secure application. As you
build the Tor application, look for opportunities to improve the data validation. Don't
be afraid to put in more data validation than this tutorial demonstrates. Never
assume your users are sending you the data you asked for. Validate everything.
CakePHP makes it easy.
Login
Getting started
© Copyright IBM Corporation 1994, 2006. All rights reserved. Page 31 of 36
developerWorks® ibm.com/developerWorks
The login view should gather the user login information and submit it to the users
controller. The users controller should look to see if the user is in the database and
verify that the password is correct. If the user has correctly logged in, write the
username to session and send the user to the index action.
Hints:
Index action
The index action should check to see if the user's name has been written to the
session. If the user's name has been written to the session, pull that information from
the database and present the user with a customized greeting. If the user has not
logged in, direct him to the login action.
Logout
The Logout Action should delete the user's username from the session and forward
the user to the login action.
Bonus
Modify the register action to automatically log the user into the system and forward
the user to the index action. Modify the register and login actions to use hashed
passwords, rather than saving your passwords in the database as plaintext.
Don't worry too much if you get stuck. Part 2 provides sample solutions to these
problems. Then you'll jump right in and build out the Tor application product gallery.
Happy coding!
Section 7. Summary
This tutorial has taught you how to install and configure CakePHP, the basics of
MVC design, how to validate user data in CakePHP, how to use CakePHP helpers,
and how to get an application up and running quickly using CakePHP. Part 2 covers
Getting started
Page 32 of 36 © Copyright IBM Corporation 1994, 2006. All rights reserved.
ibm.com/developerWorks developerWorks®
writing plug-ins for your application and using CakePHP's access control lists
(ACLs).
Getting started
© Copyright IBM Corporation 1994, 2006. All rights reserved. Page 33 of 36
developerWorks® ibm.com/developerWorks
Downloads
Description Name Size Download method
Part 1 source code os-php-cake1.source.zip
2KB HTTP
Getting started
Page 34 of 36 © Copyright IBM Corporation 1994, 2006. All rights reserved.
ibm.com/developerWorks developerWorks®
Resources
Learn
• Visit CakePHP.org to learn more about it.
• The CakePHP API has been thoroughly documented. This is the place to get
the most up-to-date documentation for CakePHP.
• There's a ton of information available at The Bakery, the CakePHP user
community.
• CakePHP Data Validation uses PHP Perl-compatible regular expressions.
• Read a tutorial titled "How to use regular expressions in PHP."
• Want to learn more about design patterns? Check out Design Patterns:
Elements of Reusable Object-Oriented Software , also known as the "Gang Of
Four" book.
• Check out some Source material for creating users.
• Check out the Wikipedia Model-View-Controller.
• Here is more useful background on the Model-View-Controller.
• Here's a whole list of different types of software design patterns.
• Read about Design Patterns.
• Visit IBM developerWorks' PHP project resources to learn more about PHP.
• Stay current with developerWorks technical events and webcasts.
• Check out upcoming conferences, trade shows, webcasts, and other Events
around the world that are of interest to IBM open source developers.
• Visit the developerWorks Open source zone for extensive how-to information,
tools, and project updates to help you develop with open source technologies
and use them with IBM's products.
• To listen to interesting interviews and discussions for software developers, be
sure to check out developerWorks podcasts.
Get products and technologies
• Innovate your next open source development project with IBM trial software,
available for download or on DVD.
Discuss
• The developerWorks PHP Developer Forum provides a place for all PHP
developer discussion topics. Post your questions about PHP scripts, functions,
syntax, variables, PHP debugging and any other topic of relevance to PHP
developers.
• Get involved in the developerWorks community by participating in
Getting started
© Copyright IBM Corporation 1994, 2006. All rights reserved. Page 35 of 36
developerWorks® ibm.com/developerWorks
developerWorks blogs.
Getting started
Page 36 of 36 © Copyright IBM Corporation 1994, 2006. All rights reserved.