Yii2 Rest URL Routing for Regular Controllers - rest

How is it possible to extend yii\rest\UrlRule in a way I can rewrite rules for actions of a controller? For example, I want to generate the following URIs:
/user/[username]
/user/keywords
/user/keyword/[key1]/[key2]/[...]
...
Every above actions are rendering their own view too.

You don't need to extend yii\rest\UrlRule. Just add your rules to routes of UrlManager by putting them on extraPatterns property of yii\rest\UrlRule.
For example suppose You defined a list action in your controller:
class BarController extends Controller
{
public $modelClass = 'app\models\Foo';
public function actionList()
{
return ['id' => 1];
}
}
Then in configuration file add extra route:
<?php
// some configs are here
'urlManager' => [
'class' => 'yii\web\UrlManager',
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [
[
'class' => 'yii\rest\UrlRule',
'controller' => [
'v1/bar',
],
'extraPatterns' => [
'GET list' => 'list',
],
],
],
],
// and some other configs are here
Now you can browse the api with /v1/bars/list. Read Yii2 Documentations for more examples.

you must change the extends of Controller in ActiveController
class ArticleController extends ActiveController

Related

OPTION verb is not working for a list of all records in Yii 2 app

I have created a blank Yii 2 project that have created a REST UserController for already existing User model:
namespace app\controllers;
use yii\rest\ActiveController;
class UserController extends ActiveController
{
public $modelClass = 'app\models\User';
}
I have modified the model to have all fields safe:
public function rules()
{
return [
['status', 'default', 'value' => self::STATUS_INACTIVE],
['status', 'in', 'range' => [self::STATUS_ACTIVE, self::STATUS_INACTIVE, self::STATUS_DELETED]],
[['username', 'email'], 'required'],
[['username', 'email'], 'unique'],
['email', 'email'],
[['password_hash', 'password_reset_token', 'verification_token', 'auth_key', 'status,created_at', 'updated_at', 'password'], 'safe'],
];
}
I have configured URL rules to have both pluralized and non-pluralized paths:
'urlManager' => [
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [
[
'class' => 'yii\rest\UrlRule',
'controller' => 'user',
'pluralize' => false,
'except' => ['index'],
],
[
'class' => 'yii\rest\UrlRule',
'controller' => 'user',
'patterns' => [
'GET,HEAD,OPTIONS' => 'index',
],
],
],
I have enabled JSON input, if that matters:
'request' => [
'parsers' => [
'application/json' => 'yii\web\JsonParser',
]
]
All the verbs are processed correctly except for OPTIONS /users:
When I execute OPTIONS /user/20 then I am getting:
200 OK
Empty content
List of allowed methods
But, when I execute OPTIONS users then I am getting 405 Method not Allowed.
What can be wrong or what am I missing?
You are getting 405 Method Not Allowed not because of routing but because of yii\filters\VerbFilter.
The yii\rest\Controller uses verbs() method to set up VerbFilter.
The yii\rest\ActiveController overrides verbs() method and sets VerbFilter to only allow GET and HEAD requests for index action.
It uses options action for OPTIONS method.
If you really want to use index action for OPTIONS method. You have to override verbs() method yourself and add OPTIONS as allowed method for that action. For example like this:
protected function verbs()
{
$verbs = parent::verbs();
$verbs['index'][] = 'OPTIONS';
return $verbs;
}
Or if you want to use options action you have to modify patterns settings as suggested by #Bizley in comments.

Yii2 advanced change views default path (theming)

I would like for my application to automatically change template
so i created this structure frontend/web/themes/myTheme
following http://www.yiiframework.com/doc-2.0/guide-output-theming.html i added this code in frontend/config/main.php
'components' => [
'view' => [
'theme' => [
'basePath' => '#app/themes/myTheme',
'baseUrl' => '#web/themes/myTheme',
'pathMap' => [
'#app/views' => '#app/themes/myTheme',
],
],
],
],
however i kept getting the error that " /var/www/html/myProject/app/frontend/views/site/index.php" The view file does not exist???
i also tried to put this function inside the controller based on How to change default view path in Yii2?
public function getViewPath()
{
return Yii::getAlias('#web/themes/myTheme/site');
}
so my question is:
1. how can I change the views default path?
2. how can i do it automatically since i can not change the common/config/main.php settings during a session?
site controller
class SiteController extends Controller
{
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'rules' => [
[
'actions' => ['index'],
'allow' => true,
'roles' => ['?'],
],
[
'actions' => ['index'],
'allow' => true,
'roles' => ['#'],
],
],
],
];
}
public function actions()
{
return [
'error' => [
'class' => 'yii\web\ErrorAction',
],
'captcha' => [
'class' => 'yii\captcha\CaptchaAction',
'fixedVerifyCode' => YII_ENV_TEST ? 'testme' : null,
],
];
}
/**
* Displays homepage.
*
* #return mixed
*/
public function actionIndex()
{
$searchModel = new ProductSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
}
I think you are configuring the wrong file.Don't configure themes in the common/config
Try this:
in frontend/config/main.php
'components' => [
'view' => [
'theme' => [
'pathMap' => [
'#frontend/views'=>'#frontend/themes/myTheme',
],
],
],
],
if you need to configure the backend then in the backend/config/main.php
'components' => [
'view' => [
'theme' => [
'pathMap' => [
'#backend/views'=>'#backend/themes/myTheme',
],
],
],
],
The common folder is has to contain the files that are required by both
frontend and backend.
Hope this helps.
First question:
I think than you have a common mistake in yii when used advanced app: the alias #app references root directory of frontend, backend, or common depending on where you access it from View documentation here.
You would used the solution proposed by ovicko.
Second question:
You can change the theme configuration dynamically in controller through view object:
$this->view->theme->pathMap =['#app/views' => '#app/themes/myTheme/',];
EDIT
According to Documentation:
Theming is a way to replace a set of views with another without the need of touching the original view rendering code.
What means that the original view file must exist and theming simply replace it in during rendering. So you must create a file in /var/www/html/myProject/app/frontend/views/site/index.php (a empty file is valid) in order to theming works.
This sounds quite ridiculous, I Know, but it works.
But I think that is much better and easier the use of differents layouts, again, to change dinamically the layout in your controller:
$this->layout = 'route/yourlayout';

yii2 with mongodb not working for login or signup

we follow this youtube link to create yii2+mongodb connection but not working. check this link: https://www.youtube.com/watch?v=1msu95ZkRe8
gives an error Object configuration must be an array containing a "class" element.
in video user.php model copy paste from doc file what is that file please help me.
I successfully realized the login service at my own project using MongoDB. But I didn't use video tutorial you pointed out.
It looks like you have an error in your configuration file. I would first check the config for mongodb component. It must be something like following (yii2-mongodb project README)
return [
//....
'components' => [
'mongodb' => [
'class' => '\yii\mongodb\Connection',
'dsn' => 'mongodb://developer:password#localhost:27017/mydatabase',
],
],
];
Other component is worth checking out is the user component:
return [
//....
'components' => [
'user' => [
'identityClass' => 'frontend\models\User', // This is your class with IdentityInterface
'enableAutoLogin' => true,
'identityCookie' => ['name' => '_identity-frontend', 'httpOnly' => true],
],
];
But in fact, similar error may appear for any configuration element of YII2.
as per video change below function behaviors in comman/models/User.php
public function behaviors()
{
return [
'timestamp' => [
'class' => 'yii\behaviors\TimestampBehavior',
'attributes' => [
ActiveRecord::EVENT_BEFORE_INSERT => ['created_at', 'updated_at'],
ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'],
]
]
];
}

Hide controller and action in pretty URL with Yii2

I need to change a URL in Yii2 using the URL Manager from
http://www.domain.com/index.php?r=tamil-article/articles&categ=Innovation&id=44
to
http://www.domain.com/44/Innovation.html
How can this be done?
You can resolve this by configuring your UrlManager to use prettyUrls.
After that you can add a custom url rule to the rules array (in config/main.php):
'urlManager' => [
'class' => 'yii\web\UrlManager',
// Disable index.php
'showScriptName' => false,
// Add the .html suffix
'suffix' => '.html',
// Disable r= routes
'enablePrettyUrl' => true,
'rules' => [
'<id:\d+>/<categ:\w+>' => 'tamil-article/articles',
],
],

How to debug Yii REST controller file with xdebug and Netbeans (where to put breakpoint and what url use)?

I have installed Netbenas, XAMPP, xdebug and Yii2 and I have simple REST controller:
<?php
namespace app\controllers;
use yii\rest\ActiveController;
class ContractController extends ActiveController
{
public $modelClass = 'app\models\Contract';
}
which connects to the Firebird 2.1 database (WIN1257) and gives error:
error on line 2 at column 431: Encoding error
I want to debug this error to determine how can I improve Yii-Firebird plugin but where can I put breakpoint if this controller has no action (action from base class is used). In run congfiguration I have Project URL:
http://localhost:8081/myproject/
and index file:
web/index.php
My intention was to put here url that gives error:
http://localhost:8081/myproject/web/index.php/contract
But Netbeans does not accept /contract part in index file field.
So - which file should I open in Netbenas and how to indicate that I want to debug url http://localhost:8081/myproject/web/index.php/contract?
Your
class ContractController extends ActiveController
is an extension of ActiveController
So you could place your breakpoint to the proper ActiveController action ..
in
vendor/yiisoft/yii2/rest/ActionController
you can find
public function actions()
{
return [
'index' => [
'class' => 'yii\rest\IndexAction',
'modelClass' => $this->modelClass,
'checkAccess' => [$this, 'checkAccess'],
],
'view' => [
'class' => 'yii\rest\ViewAction',
'modelClass' => $this->modelClass,
'checkAccess' => [$this, 'checkAccess'],
],
'create' => [
'class' => 'yii\rest\CreateAction',
'modelClass' => $this->modelClass,
'checkAccess' => [$this, 'checkAccess'],
'scenario' => $this->createScenario,
],
'update' => [
'class' => 'yii\rest\UpdateAction',
'modelClass' => $this->modelClass,
'checkAccess' => [$this, 'checkAccess'],
'scenario' => $this->updateScenario,
],
'delete' => [
'class' => 'yii\rest\DeleteAction',
'modelClass' => $this->modelClass,
'checkAccess' => [$this, 'checkAccess'],
],
'options' => [
'class' => 'yii\rest\OptionsAction',
],
];
}
where you can see that for each action you have a proper class eg:..
'class' => 'yii\rest\IndexAction',
In the same dir vendor/yiisoft/yii2/rest/ActionController you can find the class code
Then you could place the breakpoint on the related class run function
public function run()
{
if ($this->checkAccess) {
call_user_func($this->checkAccess, $this->id);
}
return $this->prepareDataProvider();
}