I am trying to do something very simple a REST response using json format.
I created a simple model:
Model
<?php
namespace app\models;
use Yii;
use yii\db\ActiveRecord;
class Post extends ActiveRecord
{
/**
* #inheritdoc
*/
public static function tableName()
{
return 'posts';
}
public function rules()
{
return [
[['title', 'content'], 'required'],
];
}
}
And a simple controller:
Controller
namespace app\controllers;
use Yii;
use yii\rest\ActiveController;
class PostsController extends ActiveController
{
public $modelClass = "app\models\Post";
}
?>
It is the configuration of my web.php file:
$config = [
'id' => 'basic',
'basePath' => dirname(__DIR__),
'bootstrap' => ['log'],
'components' => [
'request' => [
'cookieValidationKey' => 'wcHYBrv4bXfLJYnWzrpJz_5vARaAeE9U',
'parsers' => [
'application/json' => 'yii\web\JsonParser',
],
],
'urlManager' => [
'class' => 'yii\web\UrlManager',
'enablePrettyUrl' => true,
'enableStrictParsing' => false,
//'showScriptName' => false,
'rules' => [
'class' => 'yii\rest\UrlRule',
'controller' => 'posts',
]
],
Other attributes...
The most important part (I think so) is the urlManager configuration, maybe I am missing something but I don't know where is the error below.
The error
When I execute a request with method GET, everything is Ok, but with any other method it fail. It is the error:
{
"name": "Method Not Allowed",
"message": "Method Not Allowed. This url can only handle the following request methods: GET, HEAD.",
"code": 0,
"status": 405,
"type": "yii\web\MethodNotAllowedHttpException"
}
I want to get a simple response like this guy got in this video I just did the same configuration, step by step.
Thank you.
UPDATE
There is more information, when I using Postman, I got this Headers result.
I don't understand why only ALLOW -> GET, HEAD
It is the Body result:
Try this configuration:
'urlManager' => [
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [
['class' => 'yii\rest\UrlRule', 'controller' => 'post'],
],
],
See config and full list of available requests in official docs.
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
[
'class' => 'yii\rest\UrlRule',
'controller' => 'author',
'pluralize' => false
],
],
],
When I have to do something like that, I have it a little different. Try to change class in urlManager to "yii\rest\UrlRule"
Exemple (this code works for me ) :
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
['class' => 'yii\rest\UrlRule',
'controller' => [
'post']
]
],
]
Now try to acces to this url POST frontend.dev/basic/web/post whit Postman
namespace app\controllers;
use Yii;
use yii\rest\ActiveController;
class PostsController extends ActiveController
{
public $modelClass = "app\models\Post";
//uncomment actions allowed
public function actions()
{
$actions = parent::actions();
// unset($actions['create']);
// unset($actions['update']);
// unset($actions['delete']);
// unset($actions['view']);
// unset($actions['index']);
return $actions;
}
//setup verb allowed
protected function verbs()
{
return [
'create' => ['POST'],
'update' => ['PUT', 'PATCH', 'POST'],
'delete' => ['DELETE'],
'view' => ['GET'],
'index' => ['GET'],
];
}
}
or setup in config file
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'enableStrictParsing' => true,
'rules' => [
[
'class' => 'yii\rest\UrlRule',
'controller' => ['post', 'user', 'etc', 'etc2'],
'pluralize' => false,
'extraPatterns' => [
'POST' => 'create', // 'xx' refers to 'actionXx'
'PUT {id}' => 'update',
'PATCH {id}' => 'update',
'DELETE {id}' => 'delete',
'GET {id}' => 'view',
'GET {count}' => 'index',
],
],
'<controller:\w+>/<action:\w+>' => '<controller>/<action>',
],
Related
Good morning,
I dont get any further in this Topic so i am writing a Question here.
First of all i created a DB Table with Data from the Tutorial: https://www.yiiframework.com/doc/guide/2.0/en/start-databases
Then i created a Rest Controller from that Tutorial with the Data above: https://www.yiiframework.com/doc/guide/2.0/en/rest-quick-start
The first example GET Request from the Tutorial works fine and gives me all of the data from the DB.
My Request URL: http://XX.X.X.12:XX90/country/
Now we come to my Error when trying to create a new Country in the DB via a POST Request.
When using the CURL Command from underneath the Tutorial with my Test-Data i get following error:
SQLSTATE[HY000]: General error: 1364 Field 'code' doesn't have a default value**strong text**
(
[0] => HY000
[1] => 1364
[2] => Field 'code' doesn't have a default value
)
My standard logging from rest api says that the POST Var is empty, but why?
I also tested sending POST Request via a Tool (Postman) but i get the same error.
$_GET = []
$_POST = []
$_FILES = []
$_COOKIE = []
$_SERVER = [....]
My Model:
<?php
namespace app\models;
use yii\db\ActiveRecord;
class Country extends ActiveRecord
{
}
My Controller:
<?php
namespace app\controllers;
use yii\rest\ActiveController;
class CountryController extends ActiveController
{
public $modelClass = 'app\models\Country';
}
My CURL Request:
curl -i -H "Accept:application/json" -H "Content-Type:application/json" \
-XPOST "http://XX.X.X.12:XX90/countries/" \
-d '{"code": "TEST", "name": "TestCountry", "population": 01}'
My web.php Config:
<?php
$params = require __DIR__ . '/params.php';
$db = require __DIR__ . '/db.php';
$config = [
'id' => 'basic',
'basePath' => dirname(__DIR__),
'bootstrap' => ['log'],
'aliases' => [
'#bower' => '#vendor/bower-asset',
'#npm' => '#vendor/npm-asset',
],
'name' => 'Yii2-ExtJS Rest API',
'modules' => [
'user' => [
'class' => Da\User\Module::class,
// ...other configs from here: [Configuration Options](installation/configuration-options.md), e.g.
'administrators' => ['admin'], // this is required for accessing administrative actions
// 'generatePasswords' => true,
// 'switchIdentitySessionKey' => 'myown_usuario_admin_user_key',
],
'debug' => [
'class' => 'yii\debug\Module',
'allowedIPs' => ['XX.X.X.XXX', 'XX.XXX.XXX.XXX', '127.0.0.1', '::1']
],
],
'components' => [
'request' => [
// !!! insert a secret key in the following (if it is empty) - this is required by cookie validation
'cookieValidationKey' => 'XXXXXXXXXXXXXXXX',
'parsers' => [
'application/json' => 'yii\web\JsonParser',
]
],
'cache' => [
'class' => 'yii\caching\FileCache',
],
'errorHandler' => [
'errorAction' => 'site/error',
],
'mailer' => [
'class' => \yii\symfonymailer\Mailer::class,
'viewPath' => '#app/mail',
// send all mails to a file by default.
'useFileTransport' => true,
],
'authManager' => [
'class' => 'yii\rbac\DbManager',
],
'log' => [
'traceLevel' => YII_DEBUG ? 3 : 0,
'targets' => [
[
'class' => 'yii\log\FileTarget',
// 'levels' => ['error', 'warning', 'trace', 'info'],
],
],
],
'db' => $db,
'urlManager' => [
'enablePrettyUrl' => true,
'enableStrictParsing' => false,
'showScriptName' => false,
'rules' => [
['class' => 'yii\rest\UrlRule',
'controller' => 'country'],
],
],
],
'params' => $params,
];
if (YII_ENV_DEV) {
// configuration adjustments for 'dev' environment
$config['bootstrap'][] = 'debug';
$config['modules']['debug'] = [
'class' => 'yii\debug\Module',
// uncomment the following to add your IP if you are not connecting from localhost.
'allowedIPs' => ['XX.X.X.XX', '::1'],
];
$config['bootstrap'][] = 'gii';
$config['modules']['gii'] = [
'class' => 'yii\gii\Module',
// uncomment the following to add your IP if you are not connecting from localhost.
//'allowedIPs' => ['127.0.0.1', '::1'],
];
}
return $config;
Suggestions?
You need to declare validation rules for working with the Rest API
Thanks to #Bizley
My Country Model now:
<?php
namespace app\models;
use yii\db\ActiveRecord;
class Country extends ActiveRecord
{
public function rules()
{
return [
[['code', 'name', 'population'], 'required']
];
}
}
I need to give access to home page for full access with out login ex http://www.example.com/
but it works when only http://www.example.com/site/index because site/index is set as default route
how to give permission to site/index with out in url in yii2
'as beforeRequest' => [
'class' => 'yii\filters\AccessControl',
'rules' => [
[
'allow' => true,
'actions' => ['login','site/index'],
],
[
'allow' => true,
'roles' => ['#'],
],
],
'denyCallback' => function () {
return Yii::$app->response->redirect(['site/login']);
},
First of all you should include these lines in your config frontend/config/main.php in to components section:
...
'baseUrl' => '/',
...
'request' => [
//...
'baseUrl' => '',
//...
],
Next is to configure UrlManager to react on such request:
'rules' => [
'' => 'site/index',
//...
],
After that try to go to your http://your_url.local
It should work.
Problem
Every custom action redirects back to the login page.
My code
I've extended my custom controller from the dektrium\user\controllers\RegistrationController
My web.php
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
],
],
...
'modules' => [
'user' => [
'class' => 'dektrium\user\Module',
'controllerMap' => [
'registration' => 'app\controllers\user\RegistrationController'
],
],
],
Custom controller
namespace app\controllers\user;
use dektrium\user\controllers\RegistrationController as BaseAdminController;
class RegistrationController extends BaseAdminController
{
public function actionPlan()
{
echo 'Test';
}
}
Overrode methods works good, but each custom action (site.com/user/registration/plan) redirects back to the login page.
If you want change the access control rules you should change properly eg: in your site controller add plan to the rules accessible without authenctication
class SiteController extends Controller
{
/**
* #inheritdoc
*/
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'rules' => [
[
'actions' => ['login','plan', 'error'],
'allow' => true,
],
[
'actions' => ['logout', 'index'],
'allow' => true,
'roles' => ['#'],
],
],
],
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'logout' => ['post'],
],
],
];
}
see this for more http://www.yiiframework.com/doc-2.0/guide-security-authorization.html
http://www.yiiframework.com/doc-2.0/yii-filters-accesscontrol.html
Another implementation
class SiteController extends Controller
{
/**
* #inheritdoc
*/
public function behaviors()
{
$behaviors = [
'access' => [
'rules' => [
[
'actions' => ['login', 'plan', 'error'],
'allow' => true,
],
],
],
];
return ArrayHelper::merge($behaviors, parent::behaviors());
}
}
i'm adding a verb to the verbs behaviors to only allow POST request for some action and if the request not a POST it should return method not allowed but this is not working it return 404 not found response not 405 Not allowed response when i'm sending a GET request instead of POST please any help
i set in my REST control the behaviors like this
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['authenticator'] = [
'class' => CompositeAuth::className(),
'except' => ['login'],
'authMethods' => [
HttpBearerAuth::className(),
],
];
$behaviors['verbs'] = [
'class' => \yii\filters\VerbFilter::className(),
'actions' => [
//'index' => ['get'],
'login' => ['post', 'put'],
'view' => ['get'],
//'create' => ['get', 'post'],
'update' => ['put'],
//'delete' => ['post', 'delete'],
'delete' => [''],
'test', ['post']
],
];
return $behaviors;
}
in the main.php
'urlManager' => [
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [
[
'class' => 'yii\rest\UrlRule',
'controller' => ['v1/vendor'],
'extraPatterns' => [
'POST,PUT login' => 'login',
'POST logout' => 'logout',
'POST test' => 'test'
],
'tokens' => [
'{id}' => '<id:\\w+>'
]
],
],
]
so when i test and sent GET request to
GET localhost/mywebsite/api/web/v1/vendors/test
it return 404 not 405 status please any help
'extraPatterns' => [
...
'test' => 'test'
]
From Yii2 guideline routing: pretty url, strict parsing always throw \yii\web\NotFound\HttpException.
You can update the controller's beforeAction:
public function beforeAction() {
if (Yii::$app->getRequest()->getMethod() != 'POST') {
throw new \yii\web\MethodNotAllowedHttpException('Only allow POST request');
}
}
How to navigate to index method without automatic login in frontend contoller ?
Extends behaviors method in SiteController:
use yii\filters\AccessControl;
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'rules' => [
[
'actions' => ['index'],
'allow' => true,
],
[
'allow' => true,
'roles' => ['#'],
],
],
],
];
}
So index action will be available to everyone, instead other pages will require authentication