In my controller:
namespace app\api\modules\v1\controllers;
use yii\rest\ActiveController;
use yii\filters\VerbFilter;
use yii\web\Response;
class CountryController extends ActiveController
{
public $modelClass = 'app\models\Country';
public function behaviors()
{
return [
[
'class' => 'yii\filters\ContentNegotiator',
'only' => ['index', 'view','create','update','search'],
'formats' => ['application/json' =>Response::FORMAT_JSON,],
],
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'index'=>['get'],
'view'=>['get'],
'create'=>['post'],
'update'=>['PUT'],
'delete' => ['delete'],
'deleteall'=>['post'],
'search' => ['get']
],
]
];
}
}`
I try from my POSTMAN App
For create I use POST http://localhost/myapp/api/v1/countries Works fine.But For Update I use PUT http://localhost/myapp/api/v1/countries/16 it returns 16 the record as JSON output not updating as expected.
What was wrong? Thanks!!
In POSTMAN App, open the Request body tab and select x-www-form-urlencoded instead of form-data. That worked for me.
Here is another option if you feel comfortable using it. Instead of behaviors() you can add something like this and it will serve the same purpose and you wont have any problem.
public function actions()
{
$actions = parent::actions();
unset($actions['index']);
unset($actions['create']);
unset($actions['delete']);
unset($actions['update']);
unset($actions['view']);
return $actions;
}
Related
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.
I installed dektrium user but when override the AdminController.php and tried to reach admin/index what I get is Forbidden(403). After overriding the behaviors to:
'rules' => [
[
'allow' => true,
'roles' => ['?'],
],
],
the error is still the same. Did this because I still don't have any roles. What can cause this behavior ? I am aiming at the origin index.php ( the one in the dektrium\yii2-user module). Thank you!
You need to follow these rules to override controllers for dektrium-user
directory structure
You can change the following if you want it into the frontend, only starting folder needs to be changed
- backend
- controllers
- user
- AdminController
Your config for the user module under the module section should look like following
'modules' => [
..............
'user' => [
'controllerMap' => [
'admin' => 'backend\controllers\user\AdminController' ,
] ,
For overriding the controller with a new action index your minimum code should look like below
AdminController
<?php
namespace backend\controllers\user;
use dektrium\user\controllers\AdminController as BaseAdmin;
class AdminController extends BaseAdmin {
public function behaviors() {
$behaviours = parent::behaviors ();
$behaviours['access']['rules'][] = [
'allow' => true ,
'actions' => [ 'index' ] ,
'roles' => [ '?' ]
];
return $behaviours;
}
public function actionIndex(){
return $this->render('index');
}
}
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
my controller file inside api/v1/controller/
class ProfileController extends ActiveController
{
public $modelClass = 'app\models\Profile';
public function behaviors()
{
return [
[
'class' => 'yii\filters\ContentNegotiator',
'only' =>
['index', 'view', 'createnew','update','search'],
'formats' =>
['application/json' => Response::FORMAT_JSON,],
],
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'index' => ['get'],
'view' => ['get'],
'createnew' => ['post'],
'update' => ['put'],
'delete' => ['delete'],
'deleteall' => ['post'],
'search' => ['get']
],
]
];
}
public function actionCreatenew() {
$model = new Profile();
$model->load(Yii::$app->request->post());
$model->asset = UploadedFile::getInstance($model, 'asset');
$name = $model->user_id;
if($model->asset) {
$model->asset->saveAs('uploads/'.$name.'.
'.$model->asset->extension);
$model->asset = $model->asset->name.'.'.
$model->asset->extension;
}
if($model->save()) {
echo json_encode(array('status'=>"Success",
'data'=>$model->attributes),JSON_PRETTY_PRINT);
} else {
echo json_encode(array('status'=>"Failure",
'error_code'=>400,
'errors'=>$model->errors),JSON_PRETTY_PRINT);
}
}
}
When I try to use access this from Postman like:
POST http://localhost/myapp/api/v1/profiles
I get Invalid Parameter – yii\base\InvalidParamException
Response content must not be an array.
What is the issue?? help would be grateful!! Thanks
You can easily receive single / multi-uploaded files using HTTP POST with form-data encoding in Yii2, directly in your Yii2 Controller / action.
Use this code:
$uploads = UploadedFile::getInstancesByName("upfile");
if (empty($uploads)){
return "Must upload at least 1 file in upfile form-data POST";
}
// $uploads now contains 1 or more UploadedFile instances
$savedfiles = [];
foreach ($uploads as $file){
$path = //Generate your save file path here;
$file->saveAs($path); //Your uploaded file is saved, you can process it further from here
}
If you use Postman API client to test how your API is working, you can configure the upload endpoint to work like this for multi-file uploads:
Note: The upfile[] square brackets are important! Postman will happily let you select multiple files for upload in one slot, but this will not actually work. Doing it the way shown in the screenshot makes an array of files available to the Yii2 action, through the UploadedFile mechanism. This is roughly equivalent to the standard PHP $_FILES superglobal variable but with easier handling.
Single files can be uploaded with or without the [] square brackets after the key name. And of course you can name upfile whatever you like, for your convention.
You should use \yii\web\UploadedFile::getInstanceByName('asset'); instead of getInstance() checkout this Link
Like in the guide, I have created RESTful controller UserController.
namespace app\controllers;
use yii\rest\ActiveController;
class UserController extends ActiveController
{
public $modelClass = 'app\models\User';
}
And when I make request GET /users, it works.
But I have no idea what queries does Yii2 execute behind the scene, and I do not know how long do they last.
Can I somehow use Yii2 debugger to debug and profile queries ? If not, what is the alternative for this ?
To see requests in Debugger for APIs
Add this in you API config file -
$config = [
'id' => 'app-api',
'basePath' => dirname(__DIR__),
'bootstrap' => ['log'],
......
....
]
if (YII_ENV_DEV) {
// configuration adjustments for 'dev' environment
$config['bootstrap'][] = 'debug';
$config['modules']['debug'] = [
'class' => 'yii\debug\Module',
'allowedIPs' => ['your_ip_address'], // accessible to this ip address only
];
$config['bootstrap'][] = 'gii';
$config['modules']['gii'] = [
'class' => 'yii\gii\Module',
];
}
return $config;
In web/index.php of API folder -
defined('YII_DEBUG') or define('YII_DEBUG', true);
defined('YII_ENV') or define('YII_ENV', 'dev');
Access debugger by below URL-
http://localhost/yii2-app/api/web/debug/default/view
To change API's default actions like - create,update,view,index,delete write below code in controller
/* Declare actions supported by APIs (Added in api/modules/v1/components/controller.php too) */
public function actions(){
$actions = parent::actions();
unset($actions['create']);
unset($actions['update']);
unset($actions['delete']);
unset($actions['view']);
unset($actions['index']);
return $actions;
}
/* Declare methods supported by APIs */
protected function verbs(){
return [
'create' => ['POST'],
'update' => ['PUT', 'PATCH','POST'],
'delete' => ['DELETE'],
'view' => ['GET'],
'index'=>['GET'],
];
}
public function actionCreate(){echo "in create action";die;}