Building a REST API in Yii2.0

This is wiki page is useful if you are trying to build a customized REST API in Yii2.0

Note: Yii 2 includes a generic REST feature (ActiveController class) that implements a basic REST API for one of your models that you may be able to easily use and not have to write all the below code. http://www.yiiframework.com/doc-2.0/guide-rest-quick-start.html

Github:

https://github.com/sirinibin/yii2rest

Note:This example is based on the table: user(id(PK AI),name,age,createdAt,updatedAt)

1.Action index

  Request:
  ========
           URL: api/user/index
        method:GET           
params:
                {
	              "page":1,
	              "limit":5,
	              "sort":"id",
	              "order":false,
	              "filter":{}
                      "dateFilter":{"from":"2014-09-04","to":"2014-09-05"}  
	             }
       Note1: "page"=>is the current page number
       Note2: "limit"=>no.of records in a single page
       Note3: "sort"=>sort field(ie this can be id,name,age createdAt or updatedAt)
       Note4: "order"=>This can be true/false. true=>ascending order while false=>descending order
       Note5: filter=>is a json object to pass any filter elements. eg:{name:'abc',age:20} 
       
 
	   

Response:

  1. 1.Action index
  2. 2.Action View
  3. 3.Action Create
  4. 4.Action Update
  5. 5.Action Delete
  6. 6.Action DeleteAll
{
			  "status": 1,
			  "data": [
			      {
				  "id": 30,
				  "name": "john",
				  "age": 78,
				  "createdAt": "2014-09-05 01:53:31",
				  "updatedAt": "2014-09-05 01:53:51"
			      },
			      {
				  "id": 29,
				  "name": "ben",
				  "age": 23,
				  "createdAt": "2014-09-05 01:53:28",
				  "updatedAt": "2014-09-05 01:54:00"
			      },
			      {
				  "id": 28,
				  "name": "rahul",
				  "age": 72,
				  "createdAt": "2014-09-05 01:53:25",
				  "updatedAt": "2014-09-05 01:54:09"
			      },
			      {
				  "id": 27,
				  "name": "shafeeque",
				  "age": 76,
				  "createdAt": "2014-09-05 01:53:21",
				  "updatedAt": "2014-09-05 01:54:24"
			      },
			      {
				  "id": 26,
				  "name": "sirin",
				  "age": 73,
				  "createdAt": "2014-09-04 19:51:49",
				  "updatedAt": "2014-09-05 01:54:32"
			      }
			  ],
			  "totalItems": "8"
		      }

Action Source code:

public function actionIndex()
    {
     
          $params=$_REQUEST;
          $filter=array();
          $sort="";
         
          $page=1;
          $limit=10;
             
           if(isset($params['page']))
             $page=$params['page'];
              
               
           if(isset($params['limit']))
              $limit=$params['limit'];
               
            $offset=$limit*($page-1);
             
             
            /* Filter elements */
           if(isset($params['filter']))
            {
             $filter=(array)json_decode($params['filter']);
            }
            
             if(isset($params['datefilter']))
            {
             $datefilter=(array)json_decode($params['datefilter']);
            }
            
             
            if(isset($params['sort']))
            {
              $sort=$params['sort'];
		 if(isset($params['order']))
		{  
		    if($params['order']=="false")
		     $sort.=" desc";
		    else
		     $sort.=" asc";
		 
		}
            }
         
                
               $query=new Query;
               $query->offset($offset)
	             ->limit($limit)
	             ->from('user')
	             ->andFilterWhere(['like', 'id', $filter['id']])
	             ->andFilterWhere(['like', 'name', $filter['name']])
	             ->andFilterWhere(['like', 'age', $filter['age']])
	             ->orderBy($sort)
	             ->select("id,name,age,createdAt,updatedAt");
	             
	       if($datefilter['from'])
	       {
	        $query->andWhere("createdAt >= '".$datefilter['from']."' ");
	       }
	       if($datefilter['to'])
	       {
	        $query->andWhere("createdAt <= '".$datefilter['to']."'");
	       }
	       $command = $query->createCommand();
               $models = $command->queryAll();
               
               $totalItems=$query->count();
          
          $this->setHeader(200);
         
          echo json_encode(array('status'=>1,'data'=>$models,'totalItems'=>$totalItems),JSON_PRETTY_PRINT);
       
    }
	      /* Functions to set header with status code. eg: 200 OK ,400 Bad Request etc..*/	    
private function setHeader($status)
  {
      
      $status_header = 'HTTP/1.1 ' . $status . ' ' . $this->_getStatusCodeMessage($status);
      $content_type="application/json; charset=utf-8";
    
      header($status_header);
      header('Content-type: ' . $content_type);
      header('X-Powered-By: ' . "Nintriva <nintriva.com>");
  }
  private function _getStatusCodeMessage($status)
  {
      $codes = Array(
	  200 => 'OK',
	  400 => 'Bad Request',
	  401 => 'Unauthorized',
	  402 => 'Payment Required',
	  403 => 'Forbidden',
	  404 => 'Not Found',
	  500 => 'Internal Server Error',
	  501 => 'Not Implemented',
      );
      return (isset($codes[$status])) ? $codes[$status] : '';
  }	   

2.Action View

       Request:
           URL: api/user/view/30
    method:GET
    
       Note1: "30"=>is the Pk of a record in the user table
       

Response:

{
				"status": 1,
				"data": {
				    "id": 30,
				    "name": "john",
				    "age": 78,
				    "createdAt": "2014-09-05 01:53:31",
				    "updatedAt": "2014-09-05 01:53:51"
				}
			  }

Action Source code:

public function actionView($id)
  {

    $model=$this->findModel($id);
    
    $this->setHeader(200);
    echo json_encode(array('status'=>1,'data'=>array_filter($model->attributes)),JSON_PRETTY_PRINT);
      
  } 
  /* function to find the requested record/model */
  protected function findModel($id)
  {
      if (($model = User::findOne($id)) !== null) {
	  return $model;
      } else {
      
	$this->setHeader(400);
	echo json_encode(array('status'=>0,'error_code'=>400,'message'=>'Bad request'),JSON_PRETTY_PRINT);
	exit;
      }
  }

3.Action Create

       Request:
       
            URL:  api/user/create
     method:POST
		
params:
             {
			  "name":"abc",
			  "age":20,
			}

Response:

{
			      "status": 1,
			      "data": {
				  "id": 32,
				  "name": "abc",
				  "age": "20",
				  "createdAt": "2014-09-05 02:35:18",
				  "updatedAt": "2014-09-05 02:35:18"
			      }
			 }

Action Source code:

public function actionCreate()
  {
    
      $params=$_REQUEST;
      
      $model = new User();
      $model->attributes=$params;
      
      
      if ($model->save()) {
      
	  $this->setHeader(200);
	  echo json_encode(array('status'=>1,'data'=>array_filter($model->attributes)),JSON_PRETTY_PRINT);
	
      } 
      else
      {
	  $this->setHeader(400);
	  echo json_encode(array('status'=>0,'error_code'=>400,'errors'=>$model->errors),JSON_PRETTY_PRINT);
      }
  
  }

4.Action Update

       Request:
       
            URL: api/user/update/32
             
              
            Note1:"32"=>id(PK) of the record we are going to update
            
            
     method: POST
     

params:

params:
           {
			  "name":"efg",
			  "age":25,
			}

Response:

{
			      "status": 1,
			      "data": {
				  "id": 32,
				  "name": "efg",
				  "age": "25",
				  "createdAt": "2014-09-05 02:35:18",
				  "updatedAt": "2014-09-05 02:45:55"
			      }
			 }

Action Source code:

public function actionUpdate($id)
  {
      $params=$_REQUEST;
  
      $model = $this->findModel($id);
  
      $model->attributes=$params;

      if ($model->save()) {
      
	  $this->setHeader(200);
	  echo json_encode(array('status'=>1,'data'=>array_filter($model->attributes)),JSON_PRETTY_PRINT);
	
      } 
      else
      {
	  $this->setHeader(400);
	  echo json_encode(array('status'=>0,'error_code'=>400,'errors'=>$model->errors),JSON_PRETTY_PRINT);
      }
      
  }

5.Action Delete

       Request:
       
            URL: api/user/update/32
         method:DELETE 
              
            Note1:"32"=>id(PK) of the record we are going to delete
     
            
Response:
                {
			      "status": 1,
			      "data": {
				  "id": 32,
				  "name": "efg",
				  "age": 20,
				  "createdAt": "2014-09-05 02:40:44",
				  "updatedAt": "2014-09-05 02:40:44"
			      }
			  }

Action Source code:

public function actionDelete($id)
  {
      $model=$this->findModel($id);
      
      if($model->delete())
      { 
	  $this->setHeader(200);
	  echo json_encode(array('status'=>1,'data'=>array_filter($model->attributes)),JSON_PRETTY_PRINT);
      
      }
      else
      {
	
	  $this->setHeader(400);
	  echo json_encode(array('status'=>0,'error_code'=>400,'errors'=>$model->errors),JSON_PRETTY_PRINT);
      }

  }

6.Action DeleteAll

Used to delete multiple records at a time.

       Request:
       
            URL: api/user/deleteall
         method:POST

params:

{
                       "ids":"[27,28]"
                     }
            Note1:"ids"=>a list of id(Pk)'s to be deleted
     
             

Response:

{
			    "status": 1,
			    "data": [
				{
				    "id": 27,
				    "name": "shafeeque",
				    "age": 76,
				    "createdAt": "2014-09-05 01:53:21",
				    "updatedAt": "2014-09-05 01:54:24"
				},
				{
				    "id": 28,
				    "name": "rahul",
				    "age": 72,
				    "createdAt": "2014-09-05 01:53:25",
				    "updatedAt": "2014-09-05 01:54:09"
				}
			    ]
			}

Action Source code:

public function actionDeleteall()
  {
      $ids=json_decode($_REQUEST['ids']);
    
      $data=array();
      
      foreach($ids as $id)
      {
	$model=$this->findModel($id);
	
	if($model->delete())
	  $data[]=array_filter($model->attributes);
	else
	{
	  $this->setHeader(400);
	  echo json_encode(array('status'=>0,'error_code'=>400,'errors'=>$model->errors),JSON_PRETTY_PRINT);
	  return;
	}  
      }
      
      $this->setHeader(200);
      echo json_encode(array('status'=>1,'data'=>$data),JSON_PRETTY_PRINT);

  }

7.Behaviour to fileter action methods

public function behaviors()
{
    return [
	'verbs' => [
	    'class' => VerbFilter::className(),
	    'actions' => [
		'index'=>['get'],
		'view'=>['get'],
		'create'=>['post'],
		'update'=>['post'],
		'delete' => ['delete'],
		'deleteall'=>['post'],
	    ],
	  
	]
    ];
}

  /* This will execute before  any action */
public function beforeAction($event)
{
    $action = $event->id;
    if (isset($this->actions[$action])) {
	$verbs = $this->actions[$action];
    } elseif (isset($this->actions['*'])) {
	$verbs = $this->actions['*'];
    } else {
	return $event->isValid;
    }
    $verb = Yii::$app->getRequest()->getMethod();
  
  $allowed = array_map('strtoupper', $verbs);
  
  if (!in_array($verb, $allowed)) {
	
	$this->setHeader(400);
	echo json_encode(array('status'=>0,'error_code'=>400,'message'=>'Method not allowed'),JSON_PRETTY_PRINT);
	exit;
	
    }  
    
  return true;  
}

Controller source code:UserController.php

namespace app\modules\api\controllers;

use Yii;
use app\models\User;
use yii\data\ActiveDataProvider;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
use yii\db\Query;

/**
* UserController implements the CRUD actions for User model.
*/
class UserController extends Controller
{
  
    public function behaviors()
    {
	return [
	    'verbs' => [
		'class' => VerbFilter::className(),
		'actions' => [
		    'index'=>['get'],
		    'view'=>['get'],
		    'create'=>['post'],
		    'update'=>['post'],
		    'delete' => ['delete'],
		    'deleteall'=>['post'],
		],
	      
	    ]
	];
    }
    
  
    public function beforeAction($event)
    {
	$action = $event->id;
	if (isset($this->actions[$action])) {
	    $verbs = $this->actions[$action];
	} elseif (isset($this->actions['*'])) {
	    $verbs = $this->actions['*'];
	} else {
	    return $event->isValid;
	}
	$verb = Yii::$app->getRequest()->getMethod();
      
      $allowed = array_map('strtoupper', $verbs);
      
      if (!in_array($verb, $allowed)) {
	    
	    $this->setHeader(400);
	    echo json_encode(array('status'=>0,'error_code'=>400,'message'=>'Method not allowed'),JSON_PRETTY_PRINT);
	    exit;
	    
	}  
	
      return true;  
    }
  
    /**
    * Lists all User models.
    * @return mixed
    */
    public function actionIndex()
    {
     
          $params=$_REQUEST;
          $filter=array();
          $sort="";
         
          $page=1;
          $limit=10;
             
           if(isset($params['page']))
             $page=$params['page'];
              
               
           if(isset($params['limit']))
              $limit=$params['limit'];
               
            $offset=$limit*($page-1);
             
             
            /* Filter elements */
           if(isset($params['filter']))
            {
             $filter=(array)json_decode($params['filter']);
            }
            
             if(isset($params['datefilter']))
            {
             $datefilter=(array)json_decode($params['datefilter']);
            }
            
             
            if(isset($params['sort']))
            {
              $sort=$params['sort'];
		 if(isset($params['order']))
		{  
		    if($params['order']=="false")
		     $sort.=" desc";
		    else
		     $sort.=" asc";
		 
		}
            }
         
                
               $query=new Query;
               $query->offset($offset)
	             ->limit($limit)
	             ->from('user')
	             ->andFilterWhere(['like', 'id', $filter['id']])
	             ->andFilterWhere(['like', 'name', $filter['name']])
	             ->andFilterWhere(['like', 'age', $filter['age']])
	             ->orderBy($sort)
	             ->select("id,name,age,createdAt,updatedAt");
	             
	       if($datefilter['from'])
	       {
	        $query->andWhere("createdAt >= '".$datefilter['from']."' ");
	       }
	       if($datefilter['to'])
	       {
	        $query->andWhere("createdAt <= '".$datefilter['to']."'");
	       }
	       $command = $query->createCommand();
               $models = $command->queryAll();
               
               $totalItems=$query->count();
          
          $this->setHeader(200);
         
          echo json_encode(array('status'=>1,'data'=>$models,'totalItems'=>$totalItems),JSON_PRETTY_PRINT);
       
    }
      

    /**
    * Displays a single User model.
    * @param integer $id
    * @return mixed
    */
    public function actionView($id)
    {
  
      $model=$this->findModel($id);
      
      $this->setHeader(200);
      echo json_encode(array('status'=>1,'data'=>array_filter($model->attributes)),JSON_PRETTY_PRINT);
	
    }

    /**
    * Creates a new User model.
    * @return json
    */
    public function actionCreate()
    {
      
	$params=$_REQUEST;
	
	$model = new User();
	$model->attributes=$params;
	
	

	if ($model->save()) {
	
	    $this->setHeader(200);
	    echo json_encode(array('status'=>1,'data'=>array_filter($model->attributes)),JSON_PRETTY_PRINT);
	  
	} 
	else
	{
	    $this->setHeader(400);
	    echo json_encode(array('status'=>0,'error_code'=>400,'errors'=>$model->errors),JSON_PRETTY_PRINT);
	}
    
    }

    /**
    * Updates an existing User model.
    * @param integer $id
    * @return json
    */
    public function actionUpdate($id)
    {
	$params=$_REQUEST;
    
	$model = $this->findModel($id);
    
	$model->attributes=$params;

	if ($model->save()) {
	
	    $this->setHeader(200);
	    echo json_encode(array('status'=>1,'data'=>array_filter($model->attributes)),JSON_PRETTY_PRINT);
	  
	} 
	else
	{
	    $this->setHeader(400);
	    echo json_encode(array('status'=>0,'error_code'=>400,'errors'=>$model->errors),JSON_PRETTY_PRINT);
	}
	
    }

    /**
    * Deletes an existing User model.
    * @param integer $id
    * @return json
    */
    public function actionDelete($id)
    {
	$model=$this->findModel($id);
	
	if($model->delete())
	{ 
	    $this->setHeader(200);
	    echo json_encode(array('status'=>1,'data'=>array_filter($model->attributes)),JSON_PRETTY_PRINT);
	
	}
	else
	{
	  
	    $this->setHeader(400);
	    echo json_encode(array('status'=>0,'error_code'=>400,'errors'=>$model->errors),JSON_PRETTY_PRINT);
	}

    }
    /**
    * Deletes an existing multiple User models at a time.
    * @return json
    */
    public function actionDeleteall()
    {
	$ids=json_decode($_REQUEST['ids']);
      
	$data=array();
	
	foreach($ids as $id)
	{
	  $model=$this->findModel($id);
	  
	  if($model->delete())
	    $data[]=array_filter($model->attributes);
	  else
	  {
	    $this->setHeader(400);
	    echo json_encode(array('status'=>0,'error_code'=>400,'errors'=>$model->errors),JSON_PRETTY_PRINT);
	    return;
	  }  
	}
	
	$this->setHeader(200);
	echo json_encode(array('status'=>1,'data'=>$data),JSON_PRETTY_PRINT);

    }

    /**
    * Finds the User model based on its primary key value.
    * If the model is not found, a 404 HTTP exception will be thrown.
    * @param integer $id
    * @return User the loaded model
    */
    protected function findModel($id)
    {
	if (($model = User::findOne($id)) !== null) {
	    return $model;
	} else {
	
	  $this->setHeader(400);
	  echo json_encode(array('status'=>0,'error_code'=>400,'message'=>'Bad request'),JSON_PRETTY_PRINT);
	  exit;
	}
    }
    
    private function setHeader($status)
      {
	  
	  $status_header = 'HTTP/1.1 ' . $status . ' ' . $this->_getStatusCodeMessage($status);
	  $content_type="application/json; charset=utf-8";
	
	  header($status_header);
	  header('Content-type: ' . $content_type);
	  header('X-Powered-By: ' . "Nintriva <nintriva.com>");
      }
    private function _getStatusCodeMessage($status)
    {
	// these could be stored in a .ini file and loaded
	// via parse_ini_file()... however, this will suffice
	// for an example
	$codes = Array(
	    200 => 'OK',
	    400 => 'Bad Request',
	    401 => 'Unauthorized',
	    402 => 'Payment Required',
	    403 => 'Forbidden',
	    404 => 'Not Found',
	    500 => 'Internal Server Error',
	    501 => 'Not Implemented',
	);
	return (isset($codes[$status])) ? $codes[$status] : '';
    }
}

Happy coding..

Sirin

4 0
16 followers
Viewed: 149 064 times
Version: 2.0
Category: Tutorials
Written by: sirin k
Last updated by: Maurizio Domba Cerin
Created on: Sep 5, 2014
Last updated: 6 years ago
Update Article

Revisions

View all history

Related Articles