You are viewing revision #8 of this wiki article.
This version may not be up to date with the latest version.
You may want to view the differences to the latest version or see the changes made in this revision.
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: ¶
{
"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
Why so dificult?
Yii2 has native rest api tools.
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.
I'll just leave this here.
DEMO REST Yii2 with AngularJS
https://github.com/githubjeka/angular-yii2
Suggestions
Wouldn't it be better if you utilized DELETE verb for delete all like this:
DELETE /contacts = delete all
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']); }
Video upload
hi,
can you tell me how can i upload a video using POST request?
If you have any questions, please ask in the forum instead.
Signup or Login in order to comment.