Yii 2 RESTful API Setup
- Download and setup
advanced
Yii 2 application. - Download https://github.com/deerawan/yii2-advanced-api, and extract and copy
[app]/api
folder to our application (at the same folder level).- Advanced App: The ideas is to create API folder at same level as
frontend
andbackend
folders. Eg:backend common frontend ... api -- common ------ controllers ------ models -- config -- modules ------ v1 ---------- controllers ---------- models ------ v2 ---------- controllers ---------- models -- runtime -- tests -- web
- Basic App: The ideas is to create API folder at same level as
controllers
andmodels
folders. Eg:controllers models views ... api -- config -- modules ------ v1 ---------- controllers ---------- models ------ v2 ---------- controllers ---------- models -- runtime -- tests -- web
Create Models
Create the table distributor
. Eg:
CREATE TABLE `distributor` ( `id` INT(11) NOT NULL AUTO_INCREMENT, `first_name` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8_bin', `last_name` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8_bin', `name_prefix` VARCHAR(50) NULL DEFAULT NULL COLLATE 'utf8_bin', `occupation` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8_bin', `company_name` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8_bin', `address` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8_bin', `city` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8_bin', `state_prov` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8_bin', `postal_code` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8_bin', `country` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8_bin', `latitude` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8_bin', `longitude` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8_bin', `phone` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8_bin', `fax` VARCHAR(50) NULL DEFAULT NULL COLLATE 'utf8_bin', `email` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8_bin', `website` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8_bin', `services` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8_bin', `hours` TEXT NULL COLLATE 'utf8_bin', `instructions` TEXT NULL COLLATE 'utf8_bin', `status` SMALLINT(6) NOT NULL DEFAULT '1', `created_by` INT(11) NOT NULL, `created_at` DATETIME NOT NULL, `updated_by` INT(11) NOT NULL, `updated_at` DATETIME NOT NULL, PRIMARY KEY (`id`) ) COLLATE='utf8_unicode_ci' ENGINE=InnoDB AUTO_INCREMENT=27 ;
For our table distributor
, we create the following model in [app]/api/modules/v1/models
:
<?php namespace api\modules\v1\models; use \yii\db\ActiveRecord; /** * Distributor Model */ class Distributor extends ActiveRecord { /** * @inheritdoc */ public static function tableName() { return 'distributor'; } /** * @inheritdoc */ public static function primaryKey() { return ['id']; } /** * Define rules for validation */ public function rules() { return [ [['id', 'company_name', 'address'], 'required'] ]; } }
Create Controllers
For our model distributor
, we create the controller in [app]/api/modules/v1/controllers
:
<?php namespace api\modules\v1\controllers; use yii\rest\ActiveController; /** * Distributor Controller API */ class DistributorController extends ActiveController { public $modelClass = 'api\modules\v1\models\Distributor'; }
Setup Configuration
We need to add references to our API v1
module in the configuration file in [app]/api/config/main.php
:
<?php $params = array_merge( //require(__DIR__ . '/../../config/params.php'), // Basic app //require(__DIR__ . '/../../config/params-local.php'), // Basic app require(__DIR__ . '/../../common/config/params.php'), // Advanced app require(__DIR__ . '/../../common/config/params-local.php'), // Advanced app require(__DIR__ . '/params.php'), // API params require(__DIR__ . '/params-local.php') // API params ); return [ 'id' => 'app-api', 'basePath' => dirname(__DIR__), // equivalent to [app]\api 'bootstrap' => ['log'], // // Define modules API // 'modules' => [ // API v1 'v1' => [ 'basePath' => '@app/modules/v1', 'class' => 'api\modules\v1\Module' ], // API v2 'v2' => [ 'basePath' => '@app/modules/v2', 'class' => 'api\modules\v2\Module' ] ], 'components' => [ 'user' => [ //'identityClass' => 'common\models\User', 'identityClass' => 'api\modules\v1\models\User', 'enableAutoLogin' => false, ], 'log' => [ 'traceLevel' => YII_DEBUG ? 3 : 0, 'targets' => [ [ 'class' => 'yii\log\FileTarget', 'levels' => ['error', 'warning'], ], ], ], // NOTE: If strict parsing is enabled, the incoming requested URL must match // at least one of the rules in order to be treated as a valid request, // or a yii\web\NotFoundHttpException will be thrown. If strict parsing // is disabled, when none of the rules matches the requested URL, // the path info part of the URL will be treated as the requested route. 'urlManager' => [ 'enablePrettyUrl' => true, 'enableStrictParsing' => true, 'showScriptName' => false, 'rules' => [ ['class' => 'yii\rest\UrlRule', 'controller' => 'v1/item-product'], [ 'class' => 'yii\rest\UrlRule', 'controller' => 'v1/distributor', //'tokens' => [ // '{id}' => '<id:\\w+>' //], //'except' => ['delete', 'create', 'update'], ], //[ // //----------------------------------------------------------------------------- // // LEGEND: 'pattern' => 'route' // // See more: http://www.yiiframework.com/doc-2.0/guide-runtime-routing.html // // RegEx notation in use: // // \d Any digit. // // \d+ One or more of a digit. // // \w Any word/alphanumeric character (letter, number, underscore). // // - Literal dash in controller name. // // [\w-]+ One or more alphanumeric or dash characters. // //----------------------------------------------------------------------------- // 'dashboard' => 'site/index', // // // RESTful rules (Examples) // 'entry/<id:\d+>' => 'entry/view', // same as 'GET entry/<id:\d+>' => 'entry/view', // 'PUT entry/<id:\d+>' => 'entry/update' // 'POST,PUT entry/index' => 'entry/create' // 'POST <controller:[\w-]+>s' => '<controller>/create', // '<controller:[\w-]+>s' => '<controller>/index', // 'PUT <controller:[\w-]+>/<id:\d+>' => '<controller>/update', // 'DELETE <controller:[\w-]+>/<id:\d+>' => '<controller>/delete', // '<controller:[\w-]+>/<id:\d+>' => '<controller>/view', // // '<controller:(entry|comment)>/create' => '<controller>/create', // '<controller:(entry|comment)>/<id:\d+>/<action:(update|delete)>' => '<controller>/<action>', // '<controller:(entry|comment)>/<id:\d+>' => '<controller>/view', // '<controller:(entry|comment)>s' => '<controller>/index', //], // //['class' => 'yii\rest\UrlRule', 'controller' => 'user'], is equivalent to: //[ // 'PUT,PATCH users/<id>' => 'user/update', // 'DELETE users/<id>' => 'user/delete', // 'GET,HEAD users/<id>' => 'user/view', // 'POST users' => 'user/create', // 'GET,HEAD users' => 'user/index', // 'users/<id>' => 'user/options', // 'users' => 'user/options', //], ], ], 'formatter' => [ 'class' => 'yii\i18n\Formatter', 'dateFormat' => 'php:M d, Y', //'datetimeFormat' => 'php:M d, Y H:i:s', 'timeFormat' => 'php:H:i:s', 'defaultTimeZone' => 'America/New_York' ], 'request' => [ 'parsers' => [ 'application/json' => 'yii\web\JsonParser', ] ] ], 'params' => $params, ];
Include local configuration settings for the database in [app]/api/config/main-local.php
:
<?php return [ 'components' => [ 'db' => [ 'class' => 'yii\db\Connection', 'dsn' => 'mysql:host=localhost;dbname=acme_website', 'username' => 'acmeusr', 'password' => 'acmepass', 'charset' => 'utf8', ], 'mailer' => [ 'class' => 'yii\swiftmailer\Mailer', 'viewPath' => '@common/mail', ], ], ];
Add any global params in configuration file [app]/api/config/params.php
:
<?php return [ 'adminEmail' => 'admin@example.com', ];
Add any local params in configuration file [app]/api/config/params-local.php
:
<?php return [ ];
Add API Alias
Create file and add an alias in [app]/common/config/aliases.php
(Advanced app) or [app]/config/aliases.php
(Basic app):
<?php // for system-wide aliases require(__DIR__ . '/bootstrap.php'); // add API alias //Yii::setAlias('@api', __DIR__ . '/api'); // for Basic app Yii::setAlias('@api', dirname(dirname(__DIR__)) . '/api'); // for Advanced app ?>
Or simply add the following line to the file [app]/common/config/bootstrap.php
(Advanced app) or [app]/config/web.php
(Basic app):
... // Method 1: //Yii::setAlias('@api', dirname(__DIR__) . '/api'); // for Basic app //Yii::setAlias('@api', dirname(dirname(__DIR__)) . '/api'); // for Advanced app // Method 2: $config = [ //... 'aliases' => [ //... '@api'=> dirname(__DIR__) . '/api', ], ];
Setup Web Folder
Create file [app]/api/web/.htaccess
(very important!!):
# use mod_rewrite for pretty URL support RewriteEngine on # If a directory or a file exists, use the request directly RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d # Otherwise forward the request to index.php RewriteRule . index.php
Create [app]/api/web/index.php
. For Advanced app:
<?php defined('YII_DEBUG') or define('YII_DEBUG', true); defined('YII_ENV') or define('YII_ENV', 'dev'); require(__DIR__ . '/../../vendor/autoload.php'); require(__DIR__ . '/../../vendor/yiisoft/yii2/Yii.php'); require(__DIR__ . '/../../common/config/aliases.php'); $config = yii\helpers\ArrayHelper::merge( require(__DIR__ . '/../../common/config/main.php'), require(__DIR__ . '/../../common/config/main-local.php'), require(__DIR__ . '/../config/main.php'), require(__DIR__ . '/../config/main-local.php') ); $application = new yii\web\Application($config); $application->run();
For Basic app:
<?php defined('YII_DEBUG') or define('YII_DEBUG', true); defined('YII_ENV') or define('YII_ENV', 'dev'); require(__DIR__ . '/../../vendor/autoload.php'); require(__DIR__ . '/../../vendor/yiisoft/yii2/Yii.php'); $config = yii\helpers\ArrayHelper::merge( require(__DIR__ . '/../../config/web.php'), // Basic app config file require(__DIR__ . '/../../config/web-local.php'), // Basic app config file require(__DIR__ . '/../config/main.php'), // API config file require(__DIR__ . '/../config/main-local.php') // API config file ); $application = new yii\web\Application($config); $application->run();
Create file [app]/api/web/robots.txt
:
User-Agent: * Disallow: /
Create file [app]/api/web/css/site.css
:
html, body { height: 100%; } .wrap { min-height: 100%; height: auto; margin: 0 auto -60px; padding: 0 0 60px; } .wrap > .container { padding: 70px 15px 20px; } .footer { height: 60px; background-color: #f5f5f5; border-top: 1px solid #ddd; padding-top: 20px; } .jumbotron { text-align: center; background-color: transparent; } .jumbotron .btn { font-size: 21px; padding: 14px 24px; } .not-set { color: #c55; font-style: italic; } /* add sorting icons to gridview sort links */ a.asc:after, a.desc:after { position: relative; top: 1px; display: inline-block; font-family: 'Glyphicons Halflings'; font-style: normal; font-weight: normal; line-height: 1; padding-left: 5px; } a.asc:after { content: /*"\e113"*/ "\e151"; } a.desc:after { content: /*"\e114"*/ "\e152"; } .sort-numerical a.asc:after { content: "\e153"; } .sort-numerical a.desc:after { content: "\e154"; } .sort-ordinal a.asc:after { content: "\e155"; } .sort-ordinal a.desc:after { content: "\e156"; } .grid-view th { white-space: nowrap; } .hint-block { display: block; margin-top: 5px; color: #999; } .error-summary { color: #a94442; background: #fdf7f7; border-left: 3px solid #eed3d7; padding: 10px 20px; margin: 0 0 15px 0; }
Using HTTP Basic Authentication
When using the Basic application template: Eg:
... api -- config -- modules ------ v1 ---------- controllers ---------- models ------ v2 ---------- controllers ---------- models -- runtime ------ cache ------ debug ------ logs -- web ------ assets ------ css assets commands config controllers mail migrations models runtime tests vendor views web
[app]/api/config/main-local.php
<?php return [ 'components' => [ 'db' => [ 'class' => 'yii\db\Connection', 'dsn' => 'mysql:host=localhost;dbname=acme_productionlog', 'username' => 'root', 'password' => '', 'charset' => 'utf8', ], 'mailer' => [ 'class' => 'yii\swiftmailer\Mailer', //'viewPath' => '@common/mail', 'viewPath' => '@app/mail', ], ], ];
[app]/api/config/main.php
<?php $params = array_merge( require(__DIR__ . '/../../config/params.php'), require(__DIR__ . '/../../config/params-local.php'), require(__DIR__ . '/params.php'), require(__DIR__ . '/params-local.php') ); return [ 'id' => 'app-api', 'basePath' => dirname(__DIR__), // equivalent to [app]\api 'bootstrap' => ['log'], 'modules' => [ // API v1 'v1' => [ 'basePath' => '@app/modules/v1', 'class' => 'api\modules\v1\Module' ], // API v2 'v2' => [ 'basePath' => '@app/modules/v2', 'class' => 'api\modules\v1\Module' ] ], 'components' => [ 'user' => [ //'identityClass' => 'app\models\User', 'identityClass' => 'api\modules\v1\models\User', 'enableAutoLogin' => false, ], 'log' => [ 'traceLevel' => YII_DEBUG ? 3 : 0, 'targets' => [ [ 'class' => 'yii\log\FileTarget', 'levels' => ['error', 'warning'], ], ], ], 'urlManager' => [ 'enablePrettyUrl' => true, 'enableStrictParsing' => true, 'showScriptName' => false, 'rules' => [ ['class' => 'yii\rest\UrlRule', 'controller' => 'v1/item-product'], [ 'class' => 'yii\rest\UrlRule', 'controller' => 'v1/entry', //'tokens' => [ // '{id}' => '<id:\\w+>' //] ], ], ], 'formatter' => [ 'class' => 'yii\i18n\Formatter', 'dateFormat' => 'php:M d, Y', //'datetimeFormat' => 'php:M d, Y H:i:s', 'timeFormat' => 'php:H:i:s', 'defaultTimeZone' => 'America/New_York' ], 'request' => [ // Required for JSON input for API 'parsers' => [ 'application/json' => 'yii\web\JsonParser', ] ], 'response' => [ // Required for JSON output for API 'formatters' => [ \yii\web\Response::FORMAT_JSON => [ 'class' => 'yii\web\JsonResponseFormatter', 'prettyPrint' => true, //YII_DEBUG, // use "pretty" output in debug mode 'encodeOptions' => JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE ], ], ], ], 'params' => $params, ];
[app]/api/config/params-local.php
<?php return [ ];
[app]/api/config/params.php
<?php return [ 'adminEmail' => 'admin@example.com', ];
[app]/api/modules/v1/Module.php
<?php namespace api\modules\v1; class Module extends \yii\base\Module { public $controllerNamespace = 'api\modules\v1\controllers'; public function init() { parent::init(); \Yii::$app->user->enableSession = false; // required for API authentication //\Yii::$app->user->loginUrl = ['site/login']; // default to use without API authentication \Yii::$app->user->loginUrl = null; // required for API authentication // Authentication example: // http://100-token@localhost:8080/production-log/api/web/v1/entries/1 // http://[access_token]@localhost:8080/production-log/api/web/v1/entries/1 } }
[app]/api/modules/v1/controllers/EntryController.php
<?php namespace api\modules\v1\controllers; use api\modules\v1\models\Entry; use yii\rest\ActiveController; use yii\filters\auth\CompositeAuth; use yii\filters\auth\HttpBasicAuth; use yii\filters\auth\HttpBearerAuth; use yii\filters\auth\QueryParamAuth; /** * EntryController implements the CRUD actions for Entry model. */ class EntryController extends ActiveController { public $modelClass = 'api\modules\v1\models\Entry'; public function behaviors() { $behaviors = parent::behaviors(); // Required for API authentication $behaviors['authenticator'] = [ // HTTP Basic Authentication 'class' => HttpBasicAuth::className(), // Composite Authentication //'class' => CompositeAuth::className(), //'authMethods' => [ // HttpBasicAuth::className(), // HttpBearerAuth::className(), // QueryParamAuth::className(), //], ]; return $behaviors; } }
[app]/api/modules/v1/models/Entry.php
<?php namespace api\modules\v1\models; use \yii\db\ActiveRecord; use \yii\behaviors\TimestampBehavior; use \yii\behaviors\BlameableBehavior; use \yii\db\Expression; /** * This is the model class for table "entry". * * @property integer $id * @property string $serial_number * @property string $product_code * @property string $product_data * @property string $workstation * @property string $created_at */ class Entry extends \yii\db\ActiveRecord { /** * @inheritdoc */ public static function tableName() { return 'entry'; } /** * @inheritdoc */ public static function primaryKey() { return ['id']; } /** * @inheritdoc */ public function rules() { return [ //[['id', 'serial_number', 'product_code', 'workstation', 'product_data', 'created_at'], 'required'] [['serial_number', 'product_code'], 'required'], [['workstation', 'product_data', 'created_at'], 'safe'] ]; } /** * @inheritdoc */ public function behaviors() { date_default_timezone_set('America/New_York'); $formattedCurDateTime = date('Y-m-d H:i:s'); // same format as NOW() return [ [ 'class' => TimestampBehavior::className(), 'createdAtAttribute' => 'created_at', // OR 'create_time', to override default field name 'updatedAtAttribute' => 'updated_at', // OR 'update_time', to override default field name 'value' => new \yii\db\Expression('NOW()'), //'value' => new \yii\db\Expression($formattedCurDateTime), ], //[ // 'class' => BlameableBehavior::className(), // 'createdByAttribute' => 'created_by', // OR 'author_id', to override default field name // 'updatedByAttribute' => 'updated_by', // OR 'updater_id', to override default field name //], ]; } }
[app]/api/modules/v1/models/User.php
<?php //namespace app\models; namespace api\modules\v1\models; class User extends \yii\base\Object implements \yii\web\IdentityInterface { public $id; public $username; public $password; public $authKey; public $accessToken; private static $users = [ '100' => [ 'id' => '100', 'username' => 'admin', 'password' => 'admin', 'authKey' => 'test100key', 'accessToken' => '100-token', ], '101' => [ 'id' => '101', 'username' => 'demo', 'password' => 'demo', 'authKey' => 'test101key', //'accessToken' => '101-token', // For more security, use a token with a GUID. // Generate GUID: C:\> php -r "echo com_create_guid();" 'accessToken' => 'B34D5EFE-924B-4BCC-883C-AC22B47E4CD4-token', ], ]; /** * @inheritdoc */ public static function findIdentity($id) { return isset(self::$users[$id]) ? new static(self::$users[$id]) : null; } /** * @inheritdoc */ public static function findIdentityByAccessToken($token, $type = null) { foreach (self::$users as $user) { if ($user['accessToken'] === $token) { return new static($user); } } return null; } /** * Finds user by username * * @param string $username * @return static|null */ public static function findByUsername($username) { foreach (self::$users as $user) { if (strcasecmp($user['username'], $username) === 0) { return new static($user); } } return null; } /** * @inheritdoc */ public function getId() { return $this->id; } /** * @inheritdoc */ public function getAuthKey() { return $this->authKey; } /** * @inheritdoc */ public function validateAuthKey($authKey) { return $this->authKey === $authKey; } /** * Validates password * * @param string $password password to validate * @return boolean if password provided is valid for current user */ public function validatePassword($password) { return $this->password === $password; } }
Add additional files in [app]/api/web
:
- .htaccess
- index.php
- robots.txt
- css/site.css
[app]/api/web/index.php
<?php defined('YII_DEBUG') or define('YII_DEBUG', true); defined('YII_ENV') or define('YII_ENV', 'dev'); require(__DIR__ . '/../../vendor/autoload.php'); require(__DIR__ . '/../../vendor/yiisoft/yii2/Yii.php'); //require(__DIR__ . '/../../config/aliases.php'); $config = yii\helpers\ArrayHelper::merge( //require(__DIR__ . '/../../config/main.php'), // Advanced app config file //require(__DIR__ . '/../../config/main-local.php'), // Advanced app config file require(__DIR__ . '/../../config/web.php'), // Basic app config file require(__DIR__ . '/../../config/web-local.php'), // Basic app config file require(__DIR__ . '/../config/main.php'), // API config file require(__DIR__ . '/../config/main-local.php') // API config file ); $application = new yii\web\Application($config); $application->run();
Test API
Call the API using the following URLs (assuming acme
is the application name):
- View distributor index: http://localhost:8080/acme/api/web/v1/distributors
- View distributor 3: http://localhost:8080/acme/api/web/v1/distributors/3
- View distributor index (using HTTP Basic authentication): https://my_access_token@localhost:8080/acme/api/web/v1/distributors
Use CURL to test API calls. Eg: In Windows:
Create record
C:\> curl -i -H "Accept:application/json" -H "Content-Type:application/json" -X POST "http://123-token@localhost/acme/api/web/v1/entries" -d "{\"serial_number\": \"0\", \"product_code\": \"prod_AcmeJewels\", \"product_data\": \"<data>None</data>\", \"workstation\": \"John-laptop\"}"
NOTE: In Windows, for JSON data, always use double quotes (no single quotes), and escape them with a backslash if any quotes are embedded in a string.
List all records
C:\> curl -i -H "Accept:application/json" "http://123-token@localhost/acme/api/web/v1/entries"
Modifying JSON Response
There are several ways to impact the formatting of the JSON (or whatever method used) reponse.
Using configuration in [app]/config/web.php
(Basic app), [app]/common/config/main.php
(Advanced app), or [app]/api/config/main.php
:
... $config = [ //... 'components' => [ //... 'response' => [ // Required for JSON output for API 'formatters' => [ \yii\web\Response::FORMAT_JSON => [ 'class' => 'yii\web\JsonResponseFormatter', 'prettyPrint' => true, //YII_DEBUG, // use "pretty" output in debug mode 'encodeOptions' => JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE ], ], ], //... ], 'params' => $params, ]; ...
Using modified JSON response after a search. Edit your model to include:
<?php namespace app\models; use Yii; class MyModel extends \yii\db\ActiveRecord { //... public function afterFind() { $this->data = $this->sanitizeStringForJson($this->data); parent::afterFind(); } //------------------------------------------------------------------------- // description: Strip extra characters, and quote string for JSON use. // Usage: Tool::sanitizeStringForJson($str); // parameters : $str // return : $str (formatted string) //------------------------------------------------------------------------- private function sanitizeStringForJson($str) { $str = str_replace("\\", "\\\\", $str); $str = str_replace('/', "\\/", $str); $str = str_replace('"', "\\".'"', $str); $str = str_replace("\b", "\\b", $str); $str = str_replace("\t", "\\t", $str); $str = str_replace("\n", "\\n", $str); $str = str_replace("\f", "\\f", $str); $str = str_replace("\r", "\\r", $str); $str = str_replace("\u", "\\u", $str); return '"'.$str.'"'; } } ?>
See also:
Override an Action
In an API controller, you can override an action by disabling the default one, and creating a comparable action. Eg:
//... use app\models\Entry; class ApiEntryController extends ActiveController { //... public function actions() { //$actions = parent::actions(); //// disable actions if needed //unset($actions['delete'], $actions['create']); // disable the "delete" and "create" actions //return $actions; return array_merge(parent::actions(), [ 'create' => null, // Disable create, to override it later with actionCreate() 'delete' => null, // Disable delete, to block access to it //... ]); } // Override default Create action with this implementation public function actionCreate() { $model = new Entry(); //if ($model->load(Yii::$app->request->post())) { if ($model->load(Yii::$app->getRequest()->getBodyParams(), '')) { $model->product_data_hash = md5($model->product_data); // massage some data before saving, if needed if ($model->save()) { return $model; } else { throw new ServerErrorHttpException('Failed to save the Entry object for unknown reason.'); } } return $model; } }
Add a Custom Action
In the API controller, add the action and findModel()
functions. Eg:
//... use app\models\Entry; use app\models\EntrySearch; use app\models\Raw; class ApiEntryController extends ActiveController { //... // Flag the specified record as "Processed" public function actionFlagProcessed($id) { $model = $this->findModel($id); $model->processed = true; if ($model->save()) { return $model; } else { throw new ServerErrorHttpException('Failed to save the Entry object for unknown reason.'); } return $model; } /** * Finds the Raw model based on its primary key value. * If the model is not found, a 404 HTTP exception will be thrown. * @param integer $id * @return Raw the loaded model * @throws NotFoundHttpException if the model cannot be found */ protected function findModel($id) { if (($model = Raw::findOne($id)) !== null) { return $model; } else { throw new NotFoundHttpException('The requested page does not exist.'); } } }
Add rules
to the urlManager
component in the [app]/config/web.php
(Basic app), or [app]/common/config/main.php
(Advanced app). Eg:
//... $config = [ 'id' => 'basic', 'basePath' => dirname(__DIR__), 'bootstrap' => ['log'], 'components' => [ //... 'urlManager' => [ 'enablePrettyUrl' => true, 'showScriptName' => false, 'enableStrictParsing' => false, 'rules' => [ [ 'class' => 'yii\rest\UrlRule', 'controller' => 'api-entry', // or 'v1/api-entry' when in /api/modules/v1/controllers/api-entry 'extraPatterns' => [ 'GET flag-printed/<id>' => 'flag-printed', // action flag-printed 'GET flag-processed/<id>' => 'flag-processed', ], ], ] ], ], 'params' => $params, ]; //...