Creating a controller

Yii provides two base classes: yii estController and yii estActiveController that we can extend when we are creating a new controller for RESTful web services.

Both of these classes contain the following useful common features, in execution order:

  1. The response output as required from the request (content negotiator).
  2. The HTTP method validation.
  3. Authentication.
  4. Rate limiting.

The second class yii estActiveController adds more functionalities through ActiveRecord, such as handling user authorization and a set of already existing actions: index, view, create, update, delete, and options.

We will see that Yii provides all the necessary information to get the response status and content through the body and HTTP header.

Let's create a controller to extend yii estController or rather without ActiveRecord. Create a new controller in api/controllers/TestRestController.php:

<?php
namespace apicontrollers;

use yii
estController;

class TestRestController extends Controller
{
    private function dataList()
    {
        return [
            [ 'id' => 1, 'name' => 'Albert', 'surname' => 'Einstein' ],
            [ 'id' => 2, 'name' => 'Enzo', 'surname' => 'Ferrari' ],
            [ 'id' => 4, 'name' => 'Mario', 'surname' => 'Bros' ]
        ];
    }
    
    
    public function actionIndex()
    {
            return $this->dataList();
    }
}

In the preceding code, we have a method dataList, which returns an array of objects, and an actionIndex method that provides the index action for TestRestController and returns that list.

Note

Many examples can be executed using a web browser (requested by employing the GET verb). Generally, however, we need a specific tool to test RESTful web services, such as Postman for example, an excellent extension for the Chrome browser or the curl command for advanced users.

The first feature of yii estController is to arrange the response output format, dynamically based on the request, which is also called content negotiation.

Indeed, we can try to launch this request through http://hostname/yiiadv/api/web/test-rest/index in our browser, or through specific tools using the GET verb and the Accept HTTP header set to application/xml, or by using curl, as follows:

$ curl -H "Accept: application/xml" http://hostname/yiiadv/api/web/test-rest/index
<?xml version="1.0" encoding="UTF-8"?>
<response><item><id>1</id><name>Albert</name><surname>Einstein</surname></item><item><id>2</id><name>Enzo</name><surname>Ferrari</surname></item><item><id>4</id><name>Mario</name><surname>Bros</surname></item></response>

In these cases, we will get a response based on the XML data:

Creating a controller

The XML data response to test-rest/index

However, if we change the Accept header to application/json, we will get a response based on the JSON data:

$ curl -H "Accept: application/json" http://hostname/yiiadv/api/web/test-rest/index

[{"id":1,"name":"Albert","surname":"Einstein"},{"id":2,"name":"Enzo","surname":"Ferrari"},{"id":4,"name":"Mario","surname":"Bros"}]

In these cases, we will get a response based on the JSON data:

Creating a controller

The JSON data response to test-rest/index

The same data will be rendered in different ways according to the Accept header sent from the client.

The second feature, HTTP method validation, allows you to specify which verbs are available for a resource. Verbs are defined in the behaviors() method, which must be extended to modify this setting:

    public function behaviors()
    {
        $behaviors = parent::behaviors();
        $behaviors['verbs'] = [
                'class' => yiifiltersVerbFilter::className(),
                'actions' => [
                    'index'  => ['get'],
                ],
        ];
        return $behaviors;
    }

In this case, we only set the GET verb to the index action, because keys of the actions attribute of behaviors['verbs'] are the actions and the value is an array containing supported HTTP methods.

If we launch http://hostname/yiiadv/api/web/test-rest/index using the GET verb (as a browser request), we will continue to display the result. However, if we change the HTTP method to the POST verb, for example, we will get an exception error:

Creating a controller

An exception error using the wrong verb

This is because only the GET verb is supported by the index action.

In the next sections, we will explain the third and fourth features, authentication and rate limiting.

Example – creating a controller to manage rooms

With this example, we will apply the concepts dealt with in the previous chapter, in this case using yii estActiveController as the base class instead of yii estController, since we are going to employ an ActiveRecord class to manipulate data.

Create a new controller in api/controllers/RoomsController.php:

<?php
namespace apicontrollers;

use yii
estActiveController;

class RoomsController extends ActiveController
{
    public $modelClass = 'commonmodelsRoom';
}

This controller implicitly contains these actions:

  • actionIndex that returns a list of models, accessible only with GET and HEAD HTTP methods
  • actionView that returns details about the mode, accessible only with the GET and HEAD HTTP methods by passing the id parameter
  • actionCreate that creates a new model, accessible only with the POST HTTP methods
  • actionUpdate that updates an existing model, accessible only with the PUT and PATCH HTTP methods
  • actionDelete that deletes an existing model, accessible only with the DELETE HTTP method
  • actionOptions that returns the allowed HTTP methods

Now, let's try to launch all these methods.

Launch actionIndex at http://hostname/yiiadv/api/web/rooms using the GET method:

[
{
    "id": 1,
    "floor": 1,
    "room_number": 101,
    "has_conditioner": 1,
    "has_tv": 0,
    "has_phone": 1,
    "available_from": "2015-05-20",
    "price_per_day": "120.00",
    "description": "description 1"

},

    {
        "id": 2,
        "floor": 2,
        "room_number": 202,
        "has_conditioner": 0,
        "has_tv": 1,
        "has_phone": 1,
        "available_from": "2015-05-30",
        "price_per_day": "118.00",
        "description": "description 2"
    }
]

We will get all the records in the database as an array of the JSON object and HTTP header, along with the successful status code and pagination details:

X-Pagination-Current-Page: 1
X-Pagination-Page-Count: 1
X-Pagination-Per-Page: 20
X-Pagination-Total-Count: 2

If we launch the same URL using the HEAD HTTP method, we will only get the HTTP HEADER response without a body, so we will get only the pagination information.

Finally, if we launch the same URL with an unsupported HTTP method, for example the PUT method, we will get two important HTTP headers:

  • The status code header set to 405 Method Not Allowed
  • The Allow header set to GET, HEAD

The status code header says that a method is not supported, and the Allow header returns a list of supported HTTP methods for that action.

Now, launch actionView on http://hostname/yiiadv/api/web/rooms/view?id=1 using the GET method:

{
  "id": 1,
  "floor": 1,
  "room_number": 101,
  "has_conditioner": 1,
  "has_tv": 0,
  "has_phone": 1,
  "available_from": "2015-05-20",
  "price_per_day": "120.00",
  "description": "description 1"
}

If we try to launch a nonexistent ID, for example http://hostname/yiiadv/api/web/rooms/view?id=100, using the GET method, we will get this body response:

{
  "name": "Not Found",
  "message": "Object not found: 100",
  "code": 0,
  "status": 404,
  "type": "yii\\web\\NotFoundHttpException"
}

The HTTP status code header will be set to 404 Not Found to specify that the requested item (id=100) does not exist. Using only the HEAD HTTP method, we will get information from the HTTP status code set to 404. The Create and Update actions require that the client sends body content of the object to be created or updated.

By default, Yii recognizes only the application/x-www-form-urlencoded and multipart/form-data input formats. In order to enable the JSON input format, we need to configure the parsers property of the request's application component in the api/config/main.php file:

'request' => [
    'parsers' => [
        'application/json' => 'yiiwebJsonParser',
    ]
]

After configuring the JSON input parser, we can call http://hostname/yiiadv/api/web/rooms/create using the POST HTTP method to create a new room and pass, for example, this JSON:

    {
        "floor": 99,
        "room_number": 999,
        "has_conditioner": 1,
        "has_tv": 1,
        "has_phone": 1,
        "available_from": "2015-12-30",
        "price_per_day": "48.00",
        "description": "description room 999"
    }

If no error occurred, we will get:

201 Created as HTTP Header Status Code
Object just created as body content

If we are missing some required fields and there are validation errors, we will get:

422 Data Validation Failed
An array of field-message to indicate which validation errors occurred

The same thing needs to be done for an update action, in this case, however, we will call http://hostname/yiiadv/api/web/rooms/update and pass the id URL parameter using the PUT or PATCH HTTP method. In this case, only the HTTP header status code 200 OK will be a successful response and the update object will be returned as body content.

Finally, actionDelete is used by calling http://hostname/yiiadv/api/web/rooms/delete, by passing the id URL parameter, and using the DELETE HTTP method. A successful execution will return 204 No Content as the HTTP status code; otherwise, it will be 404 Not Found.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.135.183.89