README.md 5.63 KB

Yii Rest Extension

Extension organize REST API on Yii app

Weavora's Git Repo - https://github.com/weavora/wrest

Features:

  • Fast configuration
  • Provide simple REST CRUD interface (get, list, update, create, delete actions)
  • CRUD actions integrate with Model scenarios

Configuration

1) Download and extract source into protected/extensions/ folder.

2) There are config settings for import section below:

<?php
// main.php
return array(
    ...
    'import' => array(
        ...
        'ext.wrest.*',
    ),
    ...
);

3) Add REST routes

<?php
// main.php
...
'urlManager'=>array(
    'urlFormat'=>'path',
    'rules'=>array(
        ...
        //rest url patterns
        array('api/<model>/delete', 'pattern'=>'api/<model:\w+>/<_id:\d+>', 'verb'=>'DELETE'),
        array('api/<model>/update', 'pattern'=>'api/<model:\w+>/<_id:\d+>', 'verb'=>'PUT'),
        array('api/<model>/list', 'pattern'=>'api/<model:\w+>', 'verb'=>'GET'),
        array('api/<model>/get', 'pattern'=>'api/<model:\w+>/<_id:\d+>', 'verb'=>'GET'),
        array('api/<model>/create', 'pattern'=>'api/<model:\w+>', 'verb'=>'POST'),
        ...
    ),
),
...

4) All your models must use WRestModelBehavior:

<?php
// /models/User.php
class User extends CActiveRecord{
    ...
    public function behaviors()
    {
        return array(
            ...
            'RestModelBehavior' => array(
                'class' => 'WRestModelBehavior',
            )
            ...
        );
    }
    ...
}

5) Create 'api' folder in /protected/controllers/. Here will be determined all your REST API controllers.

6) Extend all your REST controlles from WRestController instead of Controller.

Usage

1) Create model, determine relations, behavior etc.

<?php
// /models/User.php
class User extends CActiveRecord
{

    public function tableName()
    {
        return "user";
    }

    public static function model($className = __CLASS__)
    {
        return parent::model($className);
    }

    public function behaviors()
    {
        return array(
            'RestModelBehavior' => array(
                'class' => 'WRestModelBehavior',
            )
        );
    }

    public function rules(){
        return array(
            array('username, password', 'required'),
            array('email', 'safe'),
        );
    }

}

2) Create controller in /protected/controllers/api folder, extend it's from WRestController and define allow rest actions

<?php 
// api/UserController.php

class UserController extends WRestController{

    protected $_modelName = "user"; //model to be used as resource


    public function actions() //determine which of the standard actions will support the controller
    {
        return array(
            'list' => array( //use for get list of objects
                'class' => 'WRestListAction',
                'filterBy' => array( //this param user in `where` expression when forming an db query
                    'account_id' => 'account_id', // 'name_in_table' => 'request_param_name'
                ),
                'limit' => 'limit', //request parameter name, which will contain limit of object
                'page' => 'page', //request parameter name, which will contain requested page num
                'order' => 'order', //request parameter name, which will contain ordering for sort
            ),
            'delete' => 'WRestDeleteAction',
            'get' => 'WRestGetAction',
            'create' => 'WRestCreateAction', //provide 'scenario' param
            'update' => array(
                'class' => 'WRestUpdateAction',
                'scenario' => 'update', //as well as in WRestCreateAction optional param
        );
    }
}

REST API call samples

If you use RestClient class, then you can call api next way:

<?php
// apiCallSample.php

require 'RestClient.php';
$client = new RestClient('http://api_url/api/', '', '');

$response = $client->get('user'); //return the list of objects {{id:1, username:'Jack'}, {id:2, username:'Nick'}}
$response = $client->get('user/1'); //return single object with requested id, for example {id:1, username:'Jack'}
$response = $client->update('user/1', array('username' => 'new user name')); //update user data
$response = $client->delete('user/1'); //delete user with requested id
$response = $client->post('user', array('username'=>'name', 'password' => 'pass', 'email' => 'email@email.com'));//create new user

Custom action sample

<?php
// api/UserController.php

class UserController extends WRestController{

    protected $_modelName = "user"; //model to be used as resource

    ...

    public function actionFriends($id)
    {
        $user = User::model()->findByPk($id);
        $friends = $user->findFriends();

        if(empty($user))
            $this->sendResponse(404);

        $users = array();
        foreach($friends as $friend){
            $users = $friend->getAllAttributes();
        }
        $this->sendResponse(200, $users);
    }

    ...

}

Use with Access layer filter

For provide access layer for REST actions use wacf

<?php
// api/UserController.php

class UserController extends WRestController
{

    protected $modelName = "user";

    public function filters()
    {
        return array(
            'accessControl',
        );
    }

    public function accessRules()
    {
        return array(
            array(
                'allow',
                'actions' => array('get', 'list', 'create'),
                'roles' => array('member'),
            ),
            array(
                'allow',
                'roles' => array('member'),
                'actions' => array('delete', 'update'),
                'resource' => array(
                    'model' => 'User',
                    'params' => 'id',
                    'ownerField' => 'account_id',
                ),
            ),
            array(
                'deny',
            ),
        );
    }

    public function actions()
    {
        return array(
            'list' => array(
                'class' => 'WRestListAction',
                'filterBy' => array(
                    'account_id' => 'account_id',
                ),
                'limit' => 'limit',
            ),
            'delete' => 'WRestDeleteAction',
            'get' => 'WRestGetAction',
            'create' => 'WRestCreateAction',
            'update' => 'WRestUpdateAction',
        );
    }
}