- DOCUMENTATION
Yii 2.0: Building a REST API in Yii2.0
15 followers
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.
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:
{ "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"); } 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"); } 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
Total 6 comments
at 2015/12/24 03:42am
Video upload
hi,
can you tell me how can i upload a video using POST request?
at 2014/12/13 10:10am
Overried action
It is great tutorial, but how to override action? I've tried it like this just to test it but it doesn't work
public function actionIndex(){ echo json_encode(['test'=>'aaa']);}
at 2014/11/30 03:51am
Suggestions
Wouldn't it be better if you utilized DELETE verb for delete all like this:
DELETE /contacts = delete all
at 2014/09/15 03:24am
I'll just leave this here.
DEMO REST Yii2 with AngularJS
at 2014/09/06 10:17am
yes but
Yes yii is restful by default..but I was trying to override all actions with all possible api features like sort,pagination and filter needed for my angularjs front end.
at 2014/09/05 06:18pm
Why so dificult?
Yii2 has native rest api tools.
Leave a comment
Please to leave your comment.