posted by jwerner on Wednesday, January 28, 2015 3:50 PM

If you want to create a REST API for your Yii2 existing web app which uses the basic template and don't want to mess up your web app routes, continue reading.

Directory Structure

This is the basic template's directory structure, after having installed the template (see Yii2 Basic Template):

yourapp
+ assets
+ config
+ controllers
+ models
+ views
+ web
...

Add a new directory structure api in the root folder:

yourapp
+ web
+ config
+ controllers
...
+ api
  + config
  + modules
    + v1
      + controllers
  .htaccess
  index.php

Entry Script

api/index.php

<?php
 
// comment out the following two lines when deployed to production
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');
 
// Use a distinct configuration for the API
$config = require(__DIR__ . '/config/api.php');
 
(new yii\web\Application($config))->run();

Webserver Configuration

In order to enable pretty URLs, create a .htaccess file.

api/.htaccess

Options +FollowSymLinks
IndexIgnore */*

RewriteEngine on

# if a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

# otherwise forward it to index.php
RewriteRule . index.php

API Configuration

We want to keep configuration settings for the API apart from the web app configuration.

  • Create the file api/config/api.php:
<?php
 
$db     = require(__DIR__ . '/../../config/db.php');
$params = require(__DIR__ . '/params.php');
 
$config = [
    'id' => 'basic',
    'name' => 'TimeTracker',
    // Need to get one level up:
    'basePath' => dirname(__DIR__).'/..',
    'bootstrap' => ['log'],
    'components' => [
        'request' => [
            // Enable JSON Input:
            'parsers' => [
                'application/json' => 'yii\web\JsonParser',
            ]
        ],
        'log' => [
            'traceLevel' => YII_DEBUG ? 3 : 0,
            'targets' => [
                [
                    'class' => 'yii\log\FileTarget',
                    'levels' => ['error', 'warning'],
                     // Create API log in the standard log dir
                     // But in file 'api.log':
                    'logFile' => '@app/runtime/logs/api.log',
                ],
            ],
        ],
        'urlManager' => [
            'enablePrettyUrl' => true,
            'enableStrictParsing' => true,
            'showScriptName' => false,
            'rules' => [
                ['class' => 'yii\rest\UrlRule', 'controller' => ['v1/project','v1/time']],
            ],
        ], 
        'db' => $db,
        'user' => [
            'identityClass' => 'app\models\User',
            'enableAutoLogin' => false,
        ], 
    ],
    'modules' => [
        'v1' => [
            'class' => 'app\api\modules\v1\Module',
        ],
    ],
    'params' => $params,
];
 
return $config;

Module

api/modules/v1/Module.php

<?php
// Check this namespace:
namespace app\api\modules\v1;
 
class Module extends \yii\base\Module
{
    public function init()
    {
        parent::init();
 
        // ...  other initialization code ...
    }
}

Controllers

api/modules/v1/controllers/ProjectController.php

<?php
namespace app\api\modules\v1\controllers;
 
use yii\rest\ActiveController;
 
class ProjectController extends ActiveController
{
    // We are using the regular web app modules:
    public $modelClass = 'app\models\Project';
}

Comments

  • raghav agarwal (raghav.agarwal.05@gmail.com) Sep 7, 2016 12:47:51 PM
    Hi,

    I am using the same approach. But I am facing this issue.
    Here is the link.

    http://www.yiiframework.com/forum/index.php/topic/71575-yii2-rest-api-call-multiple-methods

    Any help would be appriciated.
  • Dharmesh (dharmeshkashyap143@gmail.com) Mar 12, 2016 6:12:35 AM
    can any one tell me how to run this? please provide me simple steps
  • Anushka (vishal.dj.fa9@gmail.com) Oct 28, 2015 11:11:03 AM
    Hi Guy i made solutions for this issue
    i am using basic template.
    This is my files
    api.php
    <?php

    $db = require(__DIR__ . '/../../config/db.php');
    $params = require(__DIR__ . '/params.php');

    $config = [
    'id' => 'basic',
    'name' => 'TimeTracker',
    // Need to get one level up:
    'basePath' => dirname(__DIR__).'/..',
    'bootstrap' => ['log'],
    'components' => [
    'request' => [
    // Enable JSON Input:
    'parsers' => [
    'application/json' => 'yii\web\JsonParser',
    ]
    ],
    'log' => [
    'traceLevel' => YII_DEBUG ? 3 : 0,
    'targets' => [
    [
    'class' => 'yii\log\FileTarget',
    'levels' => ['error', 'warning'],
    // Create API log in the standard log dir
    // But in file 'api.log':
    'logFile' => '@app/runtime/logs/api.log',
    ],
    ],
    ],
    'urlManager' => [
    'enablePrettyUrl' => true,
    'enableStrictParsing' => true,
    'showScriptName' => false,
    'rules' => [
    ['class' => 'yii\rest\UrlRule', 'controller' => ['v1/user','v1/time']],
    ],
    ],
    'urlManager' => [
    'class' => 'yii\web\UrlManager',
    // Disable index.php
    'showScriptName' => false,
    // Disable r= routes
    'enablePrettyUrl' => true,
    'enableStrictParsing' => true,
    'rules' => [
    ['class' => 'yii\rest\UrlRule', 'controller' => ['v1/user']],
    '<controller:\w+>/<id:\d+>' => '<controller>/view',
    '<controller:\w+>/<action:\w+>/<id:\d+>' => '<controller>/<action>',
    '<controller:\w+>/<action:\w+>' => '<controller>/<action>',
    ],
    ],

    'db' => $db,
    ],
    'modules' => [
    'v1' => [
    'class' => 'app\api\modules\v1\Module',
    ],
    ],


    'params' => $params,
    ];

    return $config;
    make sure you copy and past params.php to api/config folder
    Then add this libraries to your controller
    (I am using usercontroller)
    namespace app\api\modules\v1\controllers;
    use Yii;
    use yii\rest\ActiveController;
    use app\models\User;
    use yii\data\ActiveDataProvider;
    use yii\web\Controller;
    use yii\web\NotFoundHttpException;
    use yii\filters\VerbFilter;
    use yii\db\Query;
    use yii\helpers\ArrayHelper;
    class UserController extends ActiveController
    {
    public $modelClass = 'app\models\User';

    public function behaviors()
    {
    return [
    'verbs' => [
    'class' => VerbFilter::className(),
    'actions' => [
    'index'=>['get'],
    'view'=>['get'],
    'create'=>['post'],
    'update'=>['post'],
    'delete' => ['delete'],
    'deleteall'=>['post'],
    ],

    ]
    ];
    }
    //Other functions after that
    }
    Your model add this libraries

    namespace app\models;
    use yii\base\Model;
    use yii\db\ActiveRecord;

    class User extends ActiveRecord implements \yii\web\IdentityInterface
    {
    }
    Then please add this line to every function in your controller
    "\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;"
    This will help you to make proper json response.
    Example (This is my view function in usercontroller)
    public function actionView($id)
    {
    \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
    $model=$this->findModel($id);
    //print_r($model);die;
    $this->setHeader(200);
    echo json_encode(array('status'=>1,'data'=>array_filter($model->attributes)),JSON_PRETTY_PRINT);

    //echo json_encode(array('status'=>1,'data'=>$_GET['id']),JSON_PRETTY_PRINT);

    }
    I hope you can get solution for using these things
  • Anushka (vishal.dj.fa9@gmail.com) Oct 28, 2015 3:37:21 AM
    i am creating all files same like this, Only change i made
    1. User Controller
    and api.php file like this
    <?php

    $db = require(__DIR__ . '/../../config/db.php');
    $params = require(__DIR__ . '/params.php');

    $config = [
    'id' => 'basic',
    'name' => 'TimeTracker',
    // Need to get one level up:
    'basePath' => dirname(__DIR__).'/..',
    'bootstrap' => ['log'],
    'components' => [
    'request' => [
    // Enable JSON Input:
    'parsers' => [
    'application/json' => 'yii\web\JsonParser',
    ]
    ],
    'log' => [
    'traceLevel' => YII_DEBUG ? 3 : 0,
    'targets' => [
    [
    'class' => 'yii\log\FileTarget',
    'levels' => ['error', 'warning'],
    // Create API log in the standard log dir
    // But in file 'api.log':
    'logFile' => '@app/runtime/logs/api.log',
    ],
    ],
    ],
    'urlManager' => [
    'enablePrettyUrl' => true,
    'enableStrictParsing' => true,
    'showScriptName' => false,
    'rules' => [
    ['class' => 'yii\rest\UrlRule', 'controller' => ['v1/user','v1/time']],
    ],
    ],
    'db' => $db,
    ],
    'modules' => [
    'v1' => [
    'basePath' => '@app/api/modules/v1',
    'class' => 'app\api\modules\v1\Module' // here is our v1 modules
    ],
    ],
    'params' => $params,
    ];

    return $config;
    Please give me instructions to fix this issue.
    if access
    rest.local/api/vi/user/
    i get blank page and postman app get (No response received, in json)
    Thanks
  • Anushka (vishal.dj.fa9@gmail.com) Oct 28, 2015 3:29:43 AM
    i am creating all files same like this, Only change i made
    1. User Controller
    and api.php file like this
    <?php

    $db = require(__DIR__ . '/../../config/db.php');
    $params = require(__DIR__ . '/params.php');

    $config = [
    'id' => 'basic',
    'name' => 'TimeTracker',
    // Need to get one level up:
    'basePath' => dirname(__DIR__).'/..',
    'bootstrap' => ['log'],
    'components' => [
    'request' => [
    // Enable JSON Input:
    'parsers' => [
    'application/json' => 'yii\web\JsonParser',
    ]
    ],
    'log' => [
    'traceLevel' => YII_DEBUG ? 3 : 0,
    'targets' => [
    [
    'class' => 'yii\log\FileTarget',
    'levels' => ['error', 'warning'],
    // Create API log in the standard log dir
    // But in file 'api.log':
    'logFile' => '@app/runtime/logs/api.log',
    ],
    ],
    ],
    'urlManager' => [
    'enablePrettyUrl' => true,
    'enableStrictParsing' => true,
    'showScriptName' => false,
    'rules' => [
    ['class' => 'yii\rest\UrlRule', 'controller' => ['v1/user','v1/time']],
    ],
    ],
    'db' => $db,
    ],
    'modules' => [
    'v1' => [
    'basePath' => '@app/api/modules/v1',
    'class' => 'app\api\modules\v1\Module' // here is our v1 modules
    ],
    ],
    'params' => $params,
    ];

    return $config;
    Please give me instructions to fix this issue.
    if access
    rest.local/api/vi/user/
    i get blank page and postman app get (No response received, in json)
    Thanks
  • Hugo (hugotruffegm@gmail.com) Jul 23, 2015 1:22:57 AM
    How would the url to access the service?
  • M Shahid (mshahid85@gmail.com) Jun 1, 2015 8:16:35 AM
    Please send the path of the api also.. I am trying http://localhost:8888/yii2test/basic/api/v1/project but it is not working for me.
  • Salem Ouerdani (tunecino@gmail.com) May 31, 2015 1:16:59 PM
    Great structure thanks !
    now you can keep using /web to get to your models & take profit of the great debugger tool before moving your code to the api's controllers
    Thanks @Narayana for those fixes, it would not work without them.
    I also changed one more thing, i placed the config file api.php inside app/config, it make more since to me having all app configurations in one folder, why separate them while we are using global models any way.
  • jwerner (joachim.werner@diggin-data.de) May 21, 2015 2:12:26 PM
    @Narayana Swamy: Thanks for this additional information
  • asolorzano (abdsp22@gmail.com) May 7, 2015 9:39:12 AM
    alguna guia para generar el RestFull
  • Narayana Swamy (kswamy15@hotmail.com) May 3, 2015 4:57:36 AM
    I found this code very useful in setting up the api for Basic Template but I had to modify a few things to make it work. I used the concepts outlined in this blog http://budiirawan.com/setup-restful-api-yii2/ to make it work.
    A few things. In the api.php, I had to add this line
    'user' => [
    'identityClass' => 'app\models\User',
    'enableAutoLogin' => false,
    ],
    had to change module section to following:
    'modules' => [
    'v1' => [
    'basePath' => '@app/api/modules/v1',
    'class' => 'app\api\modules\v1\Module' // here is our v1 modules
    ],
    ],

    Had to add a params.php file. I also built a separate Model file within api/modules/v1/models folder and referred to it in the $modelClass. I am not sure if I could have used the model file in the app/models/ folder.


Please enter the letters as they are shown in the image above.
Letters are not case-sensitive.

Add comment

Change Log

Created OnJan 28, 2015 3:50:49 PM CET
Created ByJoachim Werner (jwerner)
Updated OnJan 9, 2017 3:04:40 PM CET
Updated ByJoachim Werner (jwerner)