Thứ Tư, 15 tháng 7, 2015

Hưỡng dẫn lập trình yii -Hướng dẫn viết API bằng Yii2

Yii cung cấp một tập hợp toàn bộ các công cụ để đơn giản hóa các nhiệm vụ thực hiện RESTful API dịch vụ Web. Đặc biệt, Yii hỗ trợ các tính năng sau đây về các API RESTful:
Tạo mẫu nhanh chóng với hỗ trợ API phổ biến cho Active Record;
Đàm phán định dạng phản ứng (hỗ trợ JSON và XML theo mặc định);
Tùy chỉnh đối tượng serialization với sự hỗ trợ cho các lĩnh vực sản xuất lựa chọn;
Định dạng phù hợp các dữ liệu thu thập và lỗi xác nhận;
Hỗ trợ cho HATEOAS;
Định tuyến hiệu quả với hợp HTTP động từ séc;
Built-in hỗ trợ cho các OPTIONS và động từ TRỤ;
Xác thực và ủy quyền;
Bộ nhớ đệm dữ liệu và HTTP bộ nhớ đệm;
Tỷ lệ hạn chế;
Sau đây, chúng tôi sử dụng một ví dụ để minh họa làm thế nào bạn có thể xây dựng một tập các API RESTful với một số công sức viết mã tối thiểu.
Demo: APi YII2
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..

1 nhận xét


EmoticonEmoticon