Skip to content
hantsy edited this page Nov 10, 2013 · 4 revisions

#Bake backend REST API

We will reuse the database scheme of the CakePHP Blog tutorial.

Use the following scripts to create a posts table in your MySQL 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());

Use bake command line to generate model, controller for posts table.

 Vendor\pear-pear.cakephp.org\CakePHP\bin\cake.bat bake model Post

This command will generate a Model named Post, it is under Model folder.

class Post extends AppModel {

}

A model class must extend AppModel which is a base class for your application.

The following command will generate the controller.

 Vendor\pear-pear.cakephp.org\CakePHP\bin\cake.bat bake controller posts

After it is executed and a file named PostsController will be generated in the Controller folder.

class PostsController extends AppController {
	public $scaffold;
}

The naming of table, model and controller follows the CakePHP naming convention.

If you want to generate the codes interactively, ignore the name argument in the bake command line.

For example,

 Vendor\pear-pear.cakephp.org\CakePHP\bin\cake.bat bake controller 

The bake command will guide you to generate the PostsController step by step, you can also generate the CRUD dummy codes instead of the default public $scaffold;.

You can also use cake bake all to generate model, controller and view together. Of course, I do not need the view in this project, as described formerly, we will use AngularJS to build the frontend UI.

Add basic CRUD restful APIs now. Open PostsController and add the CRUD methods for model Post.

public function index() {
        $posts = $this->Post->find('all');
        $this->set(array(
            'posts' => $posts,
            '_serialize' => array('posts')
        ));
    }

    public function view($id) {
        $post = $this->Post->findById($id);
        $this->set(array(
            'post' => $post,
            '_serialize' => array('post')
        ));
    }

    public function add() {
        //$this->Post->id = $id;
        if ($this->Post->save($this->request->data)) {
            $message = array(
                'text' => __('Saved'),
                'type' => 'success'
            );
        } else {
            $message = array(
                'text' => __('Error'),
                'type' => 'error'
            );
        }
        $this->set(array(
            'message' => $message,
            '_serialize' => array('message')
        ));
    }

    public function edit($id) {
        $this->Post->id = $id;
        if ($this->Post->save($this->request->data)) {
            $message = array(
                'text' => __('Saved'),
                'type' => 'success'
            );
        } else {
            $message = array(
                'text' => __('Error'),
                'type' => 'error'
            );
        }
        $this->set(array(
            'message' => $message,
            '_serialize' => array('message')
        ));
    }

    public function delete($id) {
        if ($this->Post->delete($id)) {
            $message = array(
                'text' => __('Deleted'),
                'type' => 'success'
            );
        } else {
            $message = array(
                'text' => __('Error'),
                'type' => 'error'
            );
        }
        $this->set(array(
            'message' => $message,
            '_serialize' => array('message')
        ));
    }

As you see, we must use _serialize as the key of the associated array of the returned result.

Besides these, RequestHandler component is required to process the request and response.

public $components = array('RequestHandler');

Open Config/routes.php, add the following lines before require CAKE . 'Config' . DS . 'routes.php';.

Router::mapResources("posts");
Router::parseExtensions();

mapResources indicates which posts will be mapped as REST resources, and parseExtensions will parse the resources according to the file extension, XML and JSON are native supported.

Now navigate to http://localhost/posts.json, you will get the following JSON string.

{
    "posts": [
        {
            "Post": {
                "id": "1",
                "title": "The title",
                "body": "This is the post body.",
                "created": "2013-10-22 16:10:53",
                "modified": null
            }
        },
        {
            "Post": {
                "id": "2",
                "title": "A title once again",
                "body": "And the post body follows.",
                "created": "2013-10-22 16:10:53",
                "modified": null
            }
        },
        {
            "Post": {
                "id": "3",
                "title": "Title strikes back",
                "body": "This is really exciting! Not.",
                "created": "2013-10-22 16:10:53",
                "modified": null
            }
        }
    ]
}

By the /posts.json will call the index method of PostsController. CakePHP follows the following rules to map REST resources to controllers. Here use Post as example to describe it.

URL HTTP Method PostsController method Description
/posts.json GET index Get the list of Posts
/posts.json POST add Create a new Post
/posts/:id.json GET view Get the details of a Post
/posts/:id.json PUT edit Update Post
/posts/:id.json DELETE delete Delete Post

If you want to change the resource mapping, you can define your rules via Route::resourceMap in Config/routes.php.

Router::resourceMap(array(
	array(’action’ => ’index’, ’method’ => ’GET’, ’id’ => false),
	array(’action’ => ’view’, ’method’ => ’GET’, ’id’ => true),
	array(’action’ => ’add’, ’method’ => ’POST’, ’id’ => false),
	array(’action’ => ’edit’, ’method’ => ’PUT’, ’id’ => true),
	array(’action’ => ’delete’, ’method’ => ’DELETE’, ’id’ => true),
	array(’action’ => ’update’, ’method’ => ’POST’, ’id’ => true)
));

Alternatively, you can use Route::connect to define the route rule directly.

Clone this wiki locally