Yii provides a whole set of tools to simplify the task of implementing RESTful Web Service APIs. In particular, Yii supports the following features about RESTful APIs:
OPTIONS
and HEAD
verbs;In the following, we use an example to illustrate how you can build a set of RESTful APIs with some minimal coding effort.
Assume you want to expose the user data via RESTful APIs. The user data are stored in the user
DB table,
and you have already created the active record class app\models\User
to access the user data.
First, create a controller class app\controllers\UserController
as follows:
namespace app\controllers;
use yii\rest\ActiveController;
class UserController extends ActiveController
{
public $modelClass = 'app\models\User';
}
The controller class extends from yii\rest\ActiveController, which implements a common set of RESTful actions.
By specifying modelClass
as app\models\User
, the controller knows which model can be used for fetching and manipulating data.
Then, modify the configuration of the urlManager
component in your application configuration:
'urlManager' => [
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [
['class' => 'yii\rest\UrlRule', 'controller' => 'user'],
],
]
The above configuration mainly adds a URL rule for the user
controller so that the user data
can be accessed and manipulated with pretty URLs and meaningful HTTP verbs.
Note: Yii will automatically pluralize controller names for use in endpoints (see Trying it Out section below). You can configure this using the yii\rest\UrlRule::$pluralize property.
To let the API accept input data in JSON format, configure the parsers property of
the request
application component to use the yii\web\JsonParser for JSON input:
'request' => [
'parsers' => [
'application/json' => 'yii\web\JsonParser',
]
]
Info: The above configuration is optional. Without the above configuration, the API would only recognize
application/x-www-form-urlencoded
andmultipart/form-data
input formats.
With the above minimal amount of effort, you have already finished your task of creating the RESTful APIs for accessing the user data. The APIs you have created include:
GET /users
: list all users page by page;HEAD /users
: show the overview information of user listing;POST /users
: create a new user;GET /users/123
: return the details of the user 123;HEAD /users/123
: show the overview information of user 123;PATCH /users/123
and PUT /users/123
: update the user 123;DELETE /users/123
: delete the user 123;OPTIONS /users
: show the supported verbs regarding endpoint /users
;OPTIONS /users/123
: show the supported verbs regarding endpoint /users/123
.You may access your APIs with the curl
command like the following,
$ curl -i -H "Accept:application/json" "http://localhost/users"
HTTP/1.1 200 OK
...
X-Pagination-Total-Count: 1000
X-Pagination-Page-Count: 50
X-Pagination-Current-Page: 1
X-Pagination-Per-Page: 20
Link: <http://localhost/users?page=1>; rel=self,
<http://localhost/users?page=2>; rel=next,
<http://localhost/users?page=50>; rel=last
Transfer-Encoding: chunked
Content-Type: application/json; charset=UTF-8
[
{
"id": 1,
...
},
{
"id": 2,
...
},
...
]
Try changing the acceptable content type to be application/xml
, and you will see the result
is returned in XML format:
$ curl -i -H "Accept:application/xml" "http://localhost/users"
HTTP/1.1 200 OK
...
X-Pagination-Total-Count: 1000
X-Pagination-Page-Count: 50
X-Pagination-Current-Page: 1
X-Pagination-Per-Page: 20
Link: <http://localhost/users?page=1>; rel=self,
<http://localhost/users?page=2>; rel=next,
<http://localhost/users?page=50>; rel=last
Transfer-Encoding: chunked
Content-Type: application/xml
<?xml version="1.0" encoding="UTF-8"?>
<response>
<item>
<id>1</id>
...
</item>
<item>
<id>2</id>
...
</item>
...
</response>
The following command will create a new user by sending a POST request with the user data in JSON format:
$ curl -i -H "Accept:application/json" -H "Content-Type:application/json" \
-XPOST "http://localhost/users" \
-d '{"username": "example", "email": "user@example.com"}'
HTTP/1.1 201 Created
...
Location: http://localhost/users/1
Content-Length: 99
Content-Type: application/json; charset=UTF-8
{"id":1,"username":"example","email":"user@example.com","created_at":1414674789,"updated_at":1414674789}
Tip: You may also access your APIs via Web browser by entering the URL
http://localhost/users
. However, you may need some browser plugins to send specific request headers.
As you can see, in the response headers, there is information about the total count, page count, etc.
There are also links that allow you to navigate to other pages of data. For example, http://localhost/users?page=2
would give you the next page of the user data.
Using the fields
and expand
parameters, you may also specify which fields should be included in the result.
For example, the URL http://localhost/users?fields=id,email
will only return the id
and email
fields.
Info: You may have noticed that the result of
http://localhost/users
includes some sensitive fields, such aspassword_hash
,auth_key
. You certainly do not want these to appear in your API result. You can and should remove these fields from result as described in the Resources section.
Additionally, you can sort collections like http://localhost/users?sort=email
or
http://localhost/users?sort=-email
. Filtering collections like http://localhost/users?filter[id]=10
or
http://localhost/users?filter[email][like]=gmail.com
could be implemented using
data filters. See Filtering Collections section for details.
In order to change the default pagination and sorting of the model list you can configure the yii\rest\IndexAction in your controller. For example:
<?php
namespace app\controllers;
use yii\rest\ActiveController;
use yii\helpers\ArrayHelper;
class UserController extends ActiveController
{
public $modelClass = 'app\models\User';
public function actions()
{
return ArrayHelper::merge(parent::actions(), [
'index' => [
'pagination' => [
'pageSize' => 10,
],
'sort' => [
'defaultOrder' => [
'created_at' => SORT_DESC,
],
],
],
]);
}
}
Please see Extending ActiveController for more information on how to configure actions of the ActiveController.
Using the Yii RESTful API framework, you implement an API endpoint in terms of a controller action, and you use a controller to organize the actions that implement the endpoints for a single type of resource.
Resources are represented as data models which extend from the yii\base\Model class. If you are working with databases (relational or NoSQL), it is recommended you use ActiveRecord to represent resources.
You may use yii\rest\UrlRule to simplify the routing to your API endpoints.
While not required, it is recommended that you develop your RESTful APIs as a separate application, different from your Web front end and back end for easier maintenance.
Found a typo or you think this page needs improvement?
Edit it on github !
to return json add this in the response add
**components' => [
*//other config...* 'response' => [ 'format' => yii\web\Response::FORMAT_JSON, 'charset' => 'UTF-8', // ... ],** * //other config...*
default configs return xml or json based on request header, when you open from browser - you'll get xml, with following header you'll get json: Accept: application/json; q=1.0, /; q=0.1
It is better practice, because gives more freedom in choosing format for third party developer
404 error - when I follow this tutorial.
The requested URL was not found on this server.
More specific code examples and information should be added, for the N00bs.
This example isn't the best, because it uses
app\models\User
model while in basic Yii2 app (and in the app created when going through this tutorial) theapp\models\User
model is used asidentityClass
in app's configuration.Maybe we should rather base this tutorial on app\models\Country model, developed as a part of Working with Databases section instead? Or at least warn user about the above?
As @hawkwynd says, this tutorial has a bug. Enabling
'enableStrictParsing' => true
causes the entire application to stop working and throwing 404 on virtually every request (including http://localhost/). Not only REST-related requests fails, but entire application is not working.If you set
'enableStrictParsing' => false
(or simply remove this line as this configuration item default tofalse
) then both REST examples and the remaining application will be working without any problems.I have tried to figure out why enabling
'enableStrictParsing' => true
causes these problems, but I failed and ended up with commenting out that line.@Trejder The Reason it stops working is because this option means it will only parse URL routes that are explicitly declared. Since you probably have none declared, then nothing works. This option would be used for instance when all you want to allow is specific API calls and nothing else.
If you have placed your REST API as a module, e.g. api/users, then the URL rule needs to be:
['class' => 'yii\rest\UrlRule', 'controller' => ['api/user']]
Otherwise you might get errors like 'Method not allowed' for POST or GET users/ID requests.
If your model name ist not suitable for a cplural form (here: user => users), put it like this:
['class' => 'yii\rest\UrlRule', 'controller' => ['api/user'], 'pluralize'=>false]
Signup or Login in order to comment.