Getting Started
The CakePHP framework provides a robust base for your application. It can handle every aspect, from the user’s initial request all the way to the final rendering of a web page. And since the framework follows the principles of MVC, it allows you to easily customize and extend most aspects of your application.The framework also provides a basic organizational structure, from filenames to database table names, keeping your entire application consistent and logical. This concept is simple but powerful. Follow the conventions and you’ll always know exactly where things are and how they’re organized.
The best way to experience and learn CakePHP is to sit down and build something. To start off we’ll build a simple blog application.
Blog Tutorial
Welcome to CakePHP. You’re probably checking out this tutorial because you want to learn more about how CakePHP works. It’s our aim to increase productivity and make coding more enjoyable: we hope you’ll see this as you dive into the code.This tutorial will walk you through the creation of a simple blog application. We’ll be getting and installing Cake, creating and configuring a database, and creating enough application logic to list, add, edit, and delete blog posts.
Here’s what you’ll need:
- A running web server. We’re going to assume you’re using Apache, though the instructions for using other servers should be very similar. We might have to play a little with the server configuration, but most folks can get Cake up and running without any configuration at all. Make sure you have PHP 5.2.8 or greater.
- A database server. We’re going to be using MySQL server in this tutorial. You’ll need to know enough about SQL in order to create a database: Cake will be taking the reins from there. Since we’re using MySQL, also make sure that you have pdo_mysql enabled in PHP.
- Basic PHP knowledge. The more object-oriented programming you’ve done, the better: but fear not if you’re a procedural fan.
- Finally, you’ll need a basic knowledge of the MVC programming pattern. A quick overview can be found in Understanding Model-View-Controller. Don’t worry, it’s only a half a page or so.
Getting Cake
First, let’s get a copy of fresh Cake code.To get a fresh download, visit the CakePHP project on GitHub: https://github.com/cakephp/cakephp/tags and download the latest release of 2.0
You can also clone the repository using git. git clone git://github.com/cakephp/cakephp.git
Regardless of how you downloaded it, place the code inside of your DocumentRoot. Once finished, your directory setup should look something like the following:
/path_to_document_root
/app
/lib
/plugins
/vendors
.htaccess
index.php
README
Creating the Blog Database
Next, let’s set up the underlying database for our blog. If you haven’t already done so, create an empty database for use in this tutorial, with a name of your choice. Right now, we’ll just create a single table to store our posts. We’ll also throw in a few posts right now to use for testing purposes. Execute the following SQL statements into your database:/* First, create our posts table: */
CREATE TABLE posts (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(50),
body TEXT,
created DATETIME DEFAULT NULL,
modified DATETIME DEFAULT NULL
);
/* Then insert some posts for testing: */
INSERT INTO posts (title,body,created)
VALUES ('The title', 'This is the post body.', NOW());
INSERT INTO posts (title,body,created)
VALUES ('A title once again', 'And the post body follows.', NOW());
INSERT INTO posts (title,body,created)
VALUES ('Title strikes back', 'This is really exciting! Not.', NOW());
Check out CakePHP Conventions for more information, but suffice it to say that naming our table ‘posts’ automatically hooks it to our Post model, and having fields called ‘modified’ and ‘created’ will be automagically managed by Cake.
Cake Database Configuration
Onward and upward: let’s tell Cake where our database is and how to connect to it. For many, this is the first and last time you configure anything.A copy of CakePHP’s database configuration file is found in /app/Config/database.php.default. Make a copy of this file in the same directory, but name it database.php.
The config file should be pretty straightforward: just replace the values in the $default array with those that apply to your setup. A sample completed configuration array might look something like the following:
public $default = array(
'datasource' => 'Database/Mysql',
'persistent' => false,
'host' => 'localhost',
'port' => '',
'login' => 'cakeBlog',
'password' => 'c4k3-rUl3Z',
'database' => 'cake_blog_tutorial',
'schema' => '',
'prefix' => '',
'encoding' => 'utf8'
);
Note
Remember that you’ll need to have PDO, and pdo_mysql enabled in
your php.ini.
Optional Configuration
There are three other items that can be configured. Most developers complete these laundry-list items, but they’re not required for this tutorial. One is defining a custom string (or “salt”) for use in security hashes. The second is defining a custom number (or “seed”) for use in encryption. The third item is allowing CakePHP write access to its tmp folder.The security salt is used for generating hashes. Change the default salt value by editing /app/Config/core.php line 187. It doesn’t much matter what the new value is, as long as it’s not easily guessed:
/**
* A random string used in security hashing methods.
*/
Configure::write('Security.salt', 'pl345e-P45s_7h3*S@l7!');
/**
* A random numeric string (digits only) used to encrypt/decrypt strings.
*/
Configure::write('Security.cipherSeed', '7485712659625147843639846751');
$ chown -R www-data app/tmp
A Note on mod_rewrite
Occasionally a new user will run into mod_rewrite issues. For example if the CakePHP welcome page looks a little funny (no images or css styles), it probably means mod_rewrite isn’t functioning on your system. Please refer to one of the sections below about url rewriting for your webserver to get you up and running:Blog Tutorial - Adding a layer
Create a Post Model
The Model class is the bread and butter of CakePHP applications. By creating a CakePHP model that will interact with our database, we’ll have the foundation in place needed to do our view, add, edit, and delete operations later.CakePHP’s model class files go in /app/Model, and the file we’ll be creating will be saved to /app/Model/Post.php. The completed file should look like this:
class Post extends AppModel {
}
Note
CakePHP will dynamically create a model object for you if it
cannot find a corresponding file in /app/Model. This also means
that if you accidentally name your file wrong (i.e. post.php or
posts.php), CakePHP will not recognize any of your settings and will
use the defaults instead.
Create a Posts Controller
Next, we’ll create a controller for our posts. The controller is where all the business logic for post interaction will happen. In a nutshell, it’s the place where you play with the models and get post-related work done. We’ll place this new controller in a file called PostsController.php inside the /app/Controller directory. Here’s what the basic controller should look like:class PostsController extends AppController {
public $helpers = array('Html', 'Form');
}
class PostsController extends AppController {
public $helpers = array('Html', 'Form');
public function index() {
$this->set('posts', $this->Post->find('all'));
}
}
Warning
You may be tempted to name your controllers and actions a certain
way to obtain a certain URL. Resist that temptation. Follow CakePHP
conventions (plural controller names, etc.) and create readable,
understandable action names. You can map URLs to your code using
“routes” covered later on.
To learn more about Cake’s controllers, check out the Controllers chapter.
Creating Post Views
Now that we have our data flowing to our model, and our application logic and flow defined by our controller, let’s create a view for the index action we created above.Cake views are just presentation-flavored fragments that fit inside an application’s layout. For most applications they’re HTML mixed with PHP, but they may end up as XML, CSV, or even binary data.
Layouts are presentation code that is wrapped around a view, and can be defined and switched between, but for now, let’s just use the default.
Remember in the last section how we assigned the ‘posts’ variable to the view using the set() method? That would hand down data to the view that would look something like this:
// print_r($posts) output:
Array
(
[0] => Array
(
[Post] => Array
(
[id] => 1
[title] => The title
[body] => This is the post body.
[created] => 2008-02-13 18:34:55
[modified] =>
)
)
[1] => Array
(
[Post] => Array
(
[id] => 2
[title] => A title once again
[body] => And the post body follows.
[created] => 2008-02-13 18:34:56
[modified] =>
)
)
[2] => Array
(
[Post] => Array
(
[id] => 3
[title] => Title strikes back
[body] => This is really exciting! Not.
[created] => 2008-02-13 18:34:57
[modified] =>
)
)
)
<!-- File: /app/View/Posts/index.ctp -->
<h1>Blog posts</h1>
<table>
<tr>
<th>Id</th>
<th>Title</th>
<th>Created</th>
</tr>
<!-- Here is where we loop through our $posts array, printing out post info -->
<?php foreach ($posts as $post): ?>
<tr>
<td><?php echo $post['Post']['id']; ?></td>
<td>
<?php echo $this->Html->link($post['Post']['title'],
array('controller' => 'posts', 'action' => 'view', $post['Post']['id'])); ?>
</td>
<td><?php echo $post['Post']['created']; ?></td>
</tr>
<?php endforeach; ?>
<?php unset($post); ?>
</table>
You might have noticed the use of an object called $this->Html. This is an instance of the CakePHP HtmlHelper class. CakePHP comes with a set of view helpers that make things like linking, form output, JavaScript and Ajax a snap. You can learn more about how to use them in Helpers, but what’s important to note here is that the link() method will generate an HTML link with the given title (the first parameter) and URL (the second parameter).
When specifying URLs in Cake, it is recommended that you use the array format. This is explained in more detail in the section on Routes. Using the array format for URLs allows you to take advantage of CakePHP’s reverse routing capabilities. You can also specify URLs relative to the base of the application in the form of /controller/action/param1/param2.
At this point, you should be able to point your browser to http://www.example.com/posts/index. You should see your view, correctly formatted with the title and table listing of the posts.
If you happened to have clicked on one of the links we created in this view (that link a post’s title to a URL /posts/view/some_id), you were probably informed by CakePHP that the action hasn’t yet been defined. If you were not so informed, either something has gone wrong, or you actually did define it already, in which case you are very sneaky. Otherwise, we’ll create it in the PostsController now:
class PostsController extends AppController {
public $helpers = array('Html', 'Form');
public function index() {
$this->set('posts', $this->Post->find('all'));
}
public function view($id = null) {
if (!$id) {
throw new NotFoundException(__('Invalid post'));
}
$post = $this->Post->findById($id);
if (!$post) {
throw new NotFoundException(__('Invalid post'));
}
$this->set('post', $post);
}
}
Notice that our view action takes a parameter: the ID of the post we’d like to see. This parameter is handed to the action through the requested URL. If a user requests /posts/view/3, then the value ‘3’ is passed as $id.
We also do a bit of error checking to ensure a user is actually accessing a record. If a user requests /posts/view, we will throw a NotFoundException and let the CakePHP ErrorHandler take over. We also perform a similar check to make sure the user has accessed a record that exists.
Now let’s create the view for our new ‘view’ action and place it in /app/View/Posts/view.ctp
<!-- File: /app/View/Posts/view.ctp -->
<h1><?php echo h($post['Post']['title']); ?></h1>
<p><small>Created: <?php echo $post['Post']['created']; ?></small></p>
<p><?php echo h($post['Post']['body']); ?></p>
Adding Posts
Reading from the database and showing us the posts is a great start, but let’s allow for the adding of new posts.First, start by creating an add() action in the PostsController:
class PostsController extends AppController {
public $helpers = array('Html', 'Form', 'Session');
public $components = array('Session');
public function index() {
$this->set('posts', $this->Post->find('all'));
}
public function view($id) {
if (!$id) {
throw new NotFoundException(__('Invalid post'));
}
$post = $this->Post->findById($id);
if (!$post) {
throw new NotFoundException(__('Invalid post'));
}
$this->set('post', $post);
}
public function add() {
if ($this->request->is('post')) {
$this->Post->create();
if ($this->Post->save($this->request->data)) {
$this->Session->setFlash(__('Your post has been saved.'));
return $this->redirect(array('action' => 'index'));
}
$this->Session->setFlash(__('Unable to add your post.'));
}
}
}
Note
You need to include the SessionComponent - and SessionHelper - in
any controller where you will use it. If necessary, include it in
your AppController.
Every CakePHP request includes a CakeRequest object which is accessible using $this->request. The request object contains useful information regarding the request that was just received, and can be used to control the flow of your application. In this case, we use the CakeRequest::is() method to check that the request is a HTTP POST request.
When a user uses a form to POST data to your application, that information is available in $this->request->data. You can use the pr() or debug() functions to print it out if you want to see what it looks like.
We use the SessionComponent’s SessionComponent::setFlash() method to set a message to a session variable to be displayed on the page after redirection. In the layout we have SessionHelper::flash which displays the message and clears the corresponding session variable. The controller’s Controller::redirect function redirects to another URL. The param array('action' => 'index') translates to URL /posts i.e the index action of posts controller. You can refer to Router::url() function on the API to see the formats in which you can specify a URL for various Cake functions.
Calling the save() method will check for validation errors and abort the save if any occur. We’ll discuss how those errors are handled in the following sections.
Data Validation
Cake goes a long way in taking the monotony out of form input validation. Everyone hates coding up endless forms and their validation routines. CakePHP makes it easier and faster.To take advantage of the validation features, you’ll need to use Cake’s FormHelper in your views. The FormHelper is available by default to all views at $this->Form.
Here’s our add view:
<!-- File: /app/View/Posts/add.ctp -->
<h1>Add Post</h1>
<?php
echo $this->Form->create('Post');
echo $this->Form->input('title');
echo $this->Form->input('body', array('rows' => '3'));
echo $this->Form->end('Save Post');
?>
<form id="PostAddForm" method="post" action="/posts/add">
The $this->Form->input() method is used to create form elements of the same name. The first parameter tells CakePHP which field they correspond to, and the second parameter allows you to specify a wide array of options - in this case, the number of rows for the textarea. There’s a bit of introspection and automagic here: input() will output different form elements based on the model field specified.
The $this->Form->end() call generates a submit button and ends the form. If a string is supplied as the first parameter to end(), the FormHelper outputs a submit button named accordingly along with the closing form tag. Again, refer to Helpers for more on helpers.
Now let’s go back and update our /app/View/Posts/index.ctp view to include a new “Add Post” link. Before the <table>, add the following line:
<?php echo $this->Html->link(
'Add Post',
array('controller' => 'posts', 'action' => 'add')
); ?>
class Post extends AppModel {
public $validate = array(
'title' => array(
'rule' => 'notEmpty'
),
'body' => array(
'rule' => 'notEmpty'
)
);
}
Now that you have your validation rules in place, use the app to try to add a post with an empty title or body to see how it works. Since we’ve used the FormHelper::input() method of the FormHelper to create our form elements, our validation error messages will be shown automatically.
Editing Posts
Post editing: here we go. You’re a CakePHP pro by now, so you should have picked up a pattern. Make the action, then the view. Here’s what the edit() action of the PostsController would look like:public function edit($id = null) {
if (!$id) {
throw new NotFoundException(__('Invalid post'));
}
$post = $this->Post->findById($id);
if (!$post) {
throw new NotFoundException(__('Invalid post'));
}
if ($this->request->is('post') || $this->request->is('put')) {
$this->Post->id = $id;
if ($this->Post->save($this->request->data)) {
$this->Session->setFlash(__('Your post has been updated.'));
return $this->redirect(array('action' => 'index'));
}
$this->Session->setFlash(__('Unable to update your post.'));
}
if (!$this->request->data) {
$this->request->data = $post;
}
}
Next the action checks that the request is a POST request. If it is, then we use the POST data to update our Post record, or kick back and show the user validation errors.
If there is no data set to $this->request->data, we simply set it to the previously retrieved post.
The edit view might look something like this:
<!-- File: /app/View/Posts/edit.ctp -->
<h1>Edit Post</h1>
<?php
echo $this->Form->create('Post');
echo $this->Form->input('title');
echo $this->Form->input('body', array('rows' => '3'));
echo $this->Form->input('id', array('type' => 'hidden'));
echo $this->Form->end('Save Post');
?>
One thing to note here: CakePHP will assume that you are editing a model if the ‘id’ field is present in the data array. If no ‘id’ is present (look back at our add view), Cake will assume that you are inserting a new model when save() is called.
You can now update your index view with links to edit specific posts:
<!-- File: /app/View/Posts/index.ctp (edit links added) -->
<h1>Blog posts</h1>
<p><?php echo $this->Html->link("Add Post", array('action' => 'add')); ?></p>
<table>
<tr>
<th>Id</th>
<th>Title</th>
<th>Action</th>
<th>Created</th>
</tr>
<!-- Here's where we loop through our $posts array, printing out post info -->
<?php foreach ($posts as $post): ?>
<tr>
<td><?php echo $post['Post']['id']; ?></td>
<td>
<?php echo $this->Html->link($post['Post']['title'], array('action' => 'view', $post['Post']['id'])); ?>
</td>
<td>
<?php echo $this->Html->link('Edit', array('action' => 'edit', $post['Post']['id'])); ?>
</td>
<td>
<?php echo $post['Post']['created']; ?>
</td>
</tr>
<?php endforeach; ?>
</table>
Deleting Posts
Next, let’s make a way for users to delete posts. Start with a delete() action in the PostsController:public function delete($id) {
if ($this->request->is('get')) {
throw new MethodNotAllowedException();
}
if ($this->Post->delete($id)) {
$this->Session->setFlash(__('The post with id: %s has been deleted.', h($id)));
return $this->redirect(array('action' => 'index'));
}
}
Because we’re just executing some logic and redirecting, this action has no view. You might want to update your index view with links that allow users to delete posts, however:
<!-- File: /app/View/Posts/index.ctp -->
<h1>Blog posts</h1>
<p><?php echo $this->Html->link('Add Post', array('action' => 'add')); ?></p>
<table>
<tr>
<th>Id</th>
<th>Title</th>
<th>Actions</th>
<th>Created</th>
</tr>
<!-- Here's where we loop through our $posts array, printing out post info -->
<?php foreach ($posts as $post): ?>
<tr>
<td><?php echo $post['Post']['id']; ?></td>
<td>
<?php echo $this->Html->link($post['Post']['title'], array('action' => 'view', $post['Post']['id'])); ?>
</td>
<td>
<?php echo $this->Form->postLink(
'Delete',
array('action' => 'delete', $post['Post']['id']),
array('confirm' => 'Are you sure?'));
?>
<?php echo $this->Html->link('Edit', array('action' => 'edit', $post['Post']['id'])); ?>
</td>
<td>
<?php echo $post['Post']['created']; ?>
</td>
</tr>
<?php endforeach; ?>
</table>
Note
This view code also uses the FormHelper to prompt the user with a
JavaScript confirmation dialog before they attempt to delete a
post.
Routes
For some, CakePHP’s default routing works well enough. Developers who are sensitive to user-friendliness and general search engine compatibility will appreciate the way that CakePHP’s URLs map to specific actions. So we’ll just make a quick change to routes in this tutorial.For more information on advanced routing techniques, see Routes Configuration.
By default, CakePHP responds to a request for the root of your site (i.e. http://www.example.com) using its PagesController, rendering a view called “home”. Instead, we’ll replace this with our PostsController by creating a routing rule.
Cake’s routing is found in /app/Config/routes.php. You’ll want to comment out or remove the line that defines the default root route. It looks like this:
Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));
Router::connect('/', array('controller' => 'posts', 'action' => 'index'));
Note
CakePHP also makes use of ‘reverse routing’ - if with the above
route defined you pass
array('controller' => 'posts', 'action' => 'index') to a
function expecting an array, the resultant URL used will be ‘/’.
It’s therefore a good idea to always use arrays for URLs as this
means your routes define where a URL goes, and also ensures that
links point to the same place too.
Conclusion
Creating applications this way will win you peace, honor, love, and money beyond even your wildest fantasies. Simple, isn’t it? Keep in mind that this tutorial was very basic. CakePHP has many more features to offer, and is flexible in ways we didn’t wish to cover here for simplicity’s sake. Use the rest of this manual as a guide for building more feature-rich applications.Now that you’ve created a basic Cake application you’re ready for the real thing. Start your own project, read the rest of the Cookbook and API.
If you need help, there are many ways to get the help you need - please see the Where to Get Help page. Welcome to CakePHP!
Thank you.Well it was nice post and very helpful information on Ruby on Rails Online Training
ReplyDelete