Create A Small Web Application With CakePHP

Download as odt, pdf, or txt
Download as odt, pdf, or txt
You are on page 1of 9

How To Create a Small Web Application with CakePHP on a

VPS (Part 1)

About CakePHP
CakePHP is a powerful and robust PHP framework built around the Model-View-Controller (MVC) programming paradigm.
In addition to the flexible way you can use it to build your application, it provides a basic structure for organising files and
database table names - keeping everything consistent and logical.

In the last tutorial we’ve seen how to install CakePHP onto your VPS and do some initial configuration. Additionally, we

already set up a database that will serve for our small web application we will start in this tutorial and finish in the next. The
purpose is thus to play a bit with CakePHP to better understand how you can use it for building the application you want. We
will go through some of the main concepts (Controllers, Models, Views etc) and use examples in order to demonstrate what
they are. At the end, we will have a small application that performs CRUD (create, read, update, delete) operations on our
database table.

This tutorial assumes that you have followed all the steps covered in the last one. This means having command line access to
your own VPS running the LAMP stack and already having installed and configured CakePHP. In other words, it will
continue from where the previous tutorial ended.

If you remember, the state of our application was a simple CakePHP installation in the /var/www/project folder and a
database called cake which holds a table called posts that currently has one row in it. Let’s get in our mysql command line
and add another row:

INSERT INTO posts (title,body,created)


VALUES ('Another title', 'Another body text', NOW());

Now that we have 2 rows we can go ahead and start using CakePHP to interact with this data. But before, a few words about
naming conventions.

Naming Conventions
CakePHP provides some great features if you follow the naming conventions it proposes. This serves well also for keeping
your application logic and consistent. For instance, Controller names should be CamelCased, should be in plural, end with
the word Controller (for instance PostsController) and be stored in files named the same way (PostsController.php).

Model class names on the other hand are singular and reflect the individual data model (Post). Moreover, the Model class - if
named according to convention - will automatically infer that its data resides in the database table called with the same name
in plural (posts in this case) and that it will be used by the Controller with the same name in plural and with the word
Controller at the end (in our case PostsController).
This is just a short introductory, for more information about conventions in CakePHP, you can visit this page.

The Model
The Model classes are the business layer of your application as they are used to interact with your data. In CakePHP, Models
usually represent a database table, but they can also be used for accessing other kinds of data. In this respect, Models are
your data models (a blog post, a comment, a user are for instance data models) and their declaration go in files located in
the /app/Model folder.

In our application we will follow the naming conventions so we will name our Model class Post and put it in a file
called Post.php located in the app/Model folder. This way, it will automatically know that it should use the posts table in
our database and will be used by the PostsController.

So let’s go ahead and create the file and place inside the following class declaration by which we extend the default
CakePHP Model class to create one for our blog posts (make sure you add the PHP opening tag at the beginning of the file):

class Post extends AppModel {


}

Save the file and exit. By extending the default CakePHP Model class and by following the naming conventions, this is all
we need for simple CRUD operations on this table as CakePHP knows what to do. You should know however the method
names it uses to query the table so you can actually call them in your Controllers. We’ll go through a few next.

The Controller
The Controller is used to route a user request in the browser to an action in the application. It then interprets the request and
makes use of the Models you have to deliver the requested information in a particular format (determined by specific Views).

For our application, we will create a Controller called PostsController in a file called PostsController.php located in the
folder app/Controller. We then initially paste in the following code (make sure you add the PHP opening tag at the
beginning of the file):

class PostsController extends AppController {


public $helpers = array('Form');

public function index() {


$this->set('posts', $this->Post->find('all'));
}
}

This class extends the default CakePHP Controller class and declares an attribute ($helpers) in which it stores some
CakePHP helper libraries that we will use later. Then it creates an index() method (the one that gets called by default if the
Controller does not receive directions as to which method to use). Methods in CakePHP are also called actions.
The index() action we just created uses the set() method inherited from the parent Controller to pass data from the Controller
to a View (that we will create in a minute). This data is stored in the posts variable and is retrieved from the Post Model that
uses the find('all') method to retrieve all the posts from our database table. The reason for which the Model is available to us
using $this->Post is because we followed the CakePHP naming conventions.

Now all we have to do is create a View and we will get a page that displays all our posts.

The View
The purpose of the Views are to display the data requested by the Controller and delivered by the Models. Using Views we
make sure we keep presentation separate from the business logic of our application. The task at hand now is to create a View
file to display the information retrieved by our index() method we declared above.

CakePHP Views are located in the app/View folder inside a folder named after the Controller they belong to. We will then
need to put our View file in a folder called Posts and name it index.ctp (after the method requesting it). Inside, let’s place the
following code:

<h1>Blog posts</h1>

<?php foreach ($posts as $post): ?>


<p><?php echo $post['Post']['title']; ?> | <?php echo $post['Post']['created']; ?>

<?php endforeach; ?>


<?php unset($post); ?>

This will output a very simple and ugly looking page but you’ll get the point. It iterates through the array $posts (that we set
and passed in the set() method of the Controller) and outputs the title and creation date of our posts from the table. So to get

this information, point your browser to www.example.com/project/posts/index or simply

to www.example.com/project/posts (as index() is the default action that gets called if no method is specified).

And as you can see, the application can already perform read operations without you having to write any code for querying
the database.

You’ll notice that your data is presented inside the default CakePHP layout (located in app/View/Layouts). All Views are
part of layouts and you can create as many as you want. Then all you have to do is specify in your Controller which layout
you’ll want to use. We will continue with the default one for the rest of this tutorial as it is used automatically. More

information on layouts you can read here.

Now let’s see how we can display an individual post in a separate View.

For this, we’ll need to add another method to the PostsController. So below where you defined the index() method, paste in
the following code:

public function view($id = null) {


$post = $this->Post->findById($id);
$this->set('post', $post);
}

In here, since we are looking for only one post, the Post model will use the findById() method and pass it the ID we want.
This ID will come from the view() action that gets a parameter handed to it from the URL in the following

way: www.example.com/posts/view/1, 1 being the ID of the post we need. Then the same set() method will pass to the View

a variable called post which contains the retrieved post information from the table. Simple. This method contains really the
bare minimum at this point. It’s recommended you also implement some checks to see if what gets passed to the Controller is
a valid ID etc.

Now let’s create the View itself in the same folder as the one we created earlier, named view.ctp into which we’ll put the
following code:

<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>

Now if you navigate to www.example.com/project/posts/view/1 you’ll get the post with the ID 1 (the title, creation date and

body).

How To Use CakePHP to Create a Small Web Application


(Part 2)

About CakePHP
CakePHP is a powerful and robust PHP framework built around the Model-View-Controller (MVC) programming paradigm.

In addition to the flexible way you can use it to build your application, it provides a basic structure for organizing files and
database table names - keeping everything consistent and logical.

In the last tutorial, we started to create a small application that would perform some basic CRUD (create, read, update,
delete) operations on our database. So far we managed to read the data (the posts) using a Model (Post), request it using a
Controller (PostsController) and created a couple of Views to display the information. In this tutorial we will finish the
application by implementing the other CRUD operations, namely create, update, and delete. For this, we will mainly work
inside our existing Controller and use the Model we created to access our data.

Please go through the previous two tutorials if you have not done so yet before following along this one:

• How To Install CakePHP On An Ubuntu 12.04 VPS


• How To Create a Small Web Application with CakePHP on a VPS (Part 1)
Adding Data
After seeing how we can read the posts in the table, let’s see how we can add new posts. Before creating our Controller
method, let’s first make sure the Controller has all the components we need. In the last tutorial we’ve included only
the Form helper:

public $helpers = array('Form');

Let’s add now the HTML and Session helpers as well by adding to the array:

public $helpers = array('Form', 'Html', 'Session');

Additionally, let’s include the Session component. Below the line we just edited, add the following:

public $components = array('Session');

Now let’s go ahead and create a View that will house our form to add a new post. This will use the Form helper we just
included to make things much easier. So create a file in the app/View/Posts/ folder called add.ctp. Inside, paste the following
code:

<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');
?>

As you can see, we can access the Form helper straight from the View and it allows us to quickly draw our Form. One
important thing here is that if the create() method is not passed any parameters, it will assume that the form submits to itself
(the Controller method loading this View - that we will create in a second). The input() method as you can see is quite self-
explanatory but one cool thing is that it will generate the form elements that match our data in the table. So let’s save the file
and create our method in the PostsController to take care of this.

Add the following code right below the view() method we created earlier in the PostsController:

public function add() {


if ($this->request->is('post')) {
$this->Post->create();
$post_data = $this->request->data;
if ($this->Post->save($post_data)) {
$this->Session->setFlash(__('New post saved successfully to the database'));
return $this->redirect(array('action' => 'index'));
}
$this->Session->setFlash(__('Unable to save the post to the database.'));
}
}

This function (named as the View it corresponds to) first checks if the there is a request of the type POST sent to it and tries
to insert the new data into the table using the Post model if it is. If successful, it will set a flashdata to the current user
session and redirect to the index() method (the one displaying all the posts) which will then display a positive confirmation
message as well. If not, it will set an error message instead. You can go ahead and test it out
at www.example.com/project/posts/add. Fill in the form and it should save the new post, redirect you to the posts index

page and display a confirmation message.

Since PostsController was created by extending the default CakePHP Controller, we have access to a lot of goodies, such as
the request object. Using that, we can check what kind of HTTP request is being made and get access to the POST data as
well. Additionally, we get access to the redirect() method by which we can quickly redirect the user to another method or
Controller.

Validating Data
As I am sure you don’t want posts being submitted without any information, let’s set up a quick rule in our Post Model to
make sure it forces the user to set a title when submitting a new post. Inside the Post Model, add the following property:

public $validate = array('title' => array('rule' => 'notEmpty'));

This will make sure that the title field cannot be empty. Save the Model file and try adding a new post without filling up the
title field. You’ll notice that now you are required to fill the title field but not necessarily the body field.

HTML Helper?
The reason we included the HTML helper into the PostsController is to show you how to put a link on a page in the
CakePHP way. So let’s open the index.ctp View located in the app/View/Posts/ folder and let’s add the following code after
the H1 tag:

<?php echo $this->Html->link(


'Add Post',
array('controller' => 'posts', 'action' => 'add')
); ?>

This will output a link with the anchor Add Post that will go to the add() method of the PostsController. If you want, you
can also further edit the file and using the same technique, turn the post titles on this page into links to their respective pages.
So instead of:

<?php echo $post['Post']['title']; ?>

You can put:

<?php echo $this->Html->link($post['Post']['title'], array('controller' => 'posts', 'action' => 'view',


$post['Post']['id'])); ?>

More information about the HTML helper you can find here.


Editing Data
Now that we saw how to create new posts, let’s see how to edit existing ones. Let’s create the View again next to where we
placed the add.ctp View and call it edit.ctp. Inside, paste the following:

<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');
?>

The main difference between the edit.ctp and add.ctp Views is that in the former, we also included the ID of the post as a
hidden input so that CakePHP knows you want to edit and not add a new post. Save the file and exit. Next, we create
the edit() method in the PostsController:

public function edit($id = null) {


if (!$id) {
throw new NotFoundException(__('Post is not valid!'));
}

$post = $this->Post->findById($id);
if (!$post) {
throw new NotFoundException(__('Post is not valid!'));
}

if ($this->request->is('post') || $this->request->is('put')) {
$this->Post->id = $id;
$post_data = $this->request->data;
if ($this->Post->save($post_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;
}
}

This action first makes sure that the user is trying to access a valid post by checking the ID for validity and whether it exists
in the database. Like in the add() method, it checks whether the request is POST and tries to update the post in the database
if it is. If no data is present in the request object, it will fill the form elements with the data existing in the database. And as in
the add() action, it then redirects the user to the index() method and displays a confirmation message. So go ahead and try it
out.

You can also modify the index.ctp View and add a link to edit individual posts. Add the following code after
the Created field:

<?php echo $this->Html->link('Edit', array('action' => 'edit', $post['Post']['id'])); ?>


Deleting Data
The last thing we need to do is allow users to delete the posts. So let’s add the following action to the PostsController:

public function delete($id) {


if ($this->request->is('post')) {
if ($this->Post->delete($id)) {
$this->Session->setFlash(__('The post number %s has been deleted.', h($id)));
return $this->redirect(array('action' => 'index'));
}
}
}

This method first throws an exception if the request is of a GET type. Then it uses the Post Model like in the actions above
but this time deletes the row in the table with the ID supplied in the request. Lastly, it sets a message to the user and redirects
to the index() method where the message is displayed.

To trigger this delete() method, let’s edit the index.ctp View and use the postLink() function to output a small Form that
will send the POST request to delete the table row. It will use javascript to add a confirmation alert box and will then delete
the post. Inside the index.ctp file after the edit link you can add the following:

<?php echo $this->Form->postLink(


'Delete',
array('action' => 'delete', $post['Post']['id']),
array('confirm' => 'Are you sure you want to delete this post?'));
?>

Save the file and try it out. Now you should be able to delete posts as well.

As a little recap if you followed along, your classes should look like this now:

PostsController.php - The Controller


class PostsController extends AppController {
public $helpers = array('Form', 'Html', 'Session');
public $components = array('Session');

public function index() {


$this->set('posts', $this->Post->find('all'));
}

public function view($id = null) {


$post = $this->Post->findById($id);
$this->set('post', $post);
}

public function add() {


if ($this->request->is('post')) {
$this->Post->create();
$post_data = $this->request->data;
if ($this->Post->save($post_data)) {
$this->Session->setFlash(__('New post saved successfully to the database'));
return $this->redirect(array('action' => 'index'));
}
$this->Session->setFlash(__('Unable to save the post to the database.'));
}
}

public function edit($id = null) {


if (!$id) {
throw new NotFoundException(__('Post is not valid!'));
}

$post = $this->Post->findById($id);
if (!$post) {
throw new NotFoundException(__('Post is not valid!'));
}

if ($this->request->is('post') || $this->request->is('put')) {
$this->Post->id = $id;
$post_data = $this->request->data;
if ($this->Post->save($post_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;
}
}

public function delete($id) {


if ($this->request->is('post')) {
if ($this->Post->delete($id)) {
$this->Session->setFlash(__('The post number %s has been deleted.', h($id)));
return $this->redirect(array('action' => 'index'));
}
}
}
}

Post.php - The Model


class Post extends AppModel {
public $validate = array('title' => array('rule' => 'notEmpty'));
}

You might also like