I am using mongodb in yii2 and I want to use it's migration.
this is my model class .
namespace app\models;
use yii\mongodb\ActiveRecord;
class Company extends ActiveRecord
{
/**
* #return array
*/
public static function collectionName()
{
return ['cafegardesh','companies'];
}
/**
* #return array
*/
public function attributes()
{
return ['_id', 'name', 'address', 'status'];
}
/**
* #return array
*/
public function rules()
{
return [
[['name'], 'required'],
];
}
and this is my migration file :
use yii\mongodb\Migration;
class m160904_053937_create_companies_collection extends Migration
{
public function up()
{
}
public function down()
{
echo "m160904_053937_create_companies_collection cannot be reverted.\n";
return false;
}
/*
// Use safeUp/safeDown to run migration code within a transaction
public function safeUp()
{
}
public function safeDown()
{
}
*/
}
and this is my console config file :
Yii::setAlias('#tests', dirname(__DIR__) . '/tests/codeception');
$params = require(__DIR__ . '/params.php');
$db = require(__DIR__ . '/db.php');
$config = [
'id' => 'basic-console',
'basePath' => dirname(__DIR__),
'bootstrap' => ['log'],
'controllerNamespace' => 'app\commands',
'components' => [
'cache' => [
'class' => 'yii\caching\FileCache',
],
'log' => [
'targets' => [
[
'class' => 'yii\log\FileTarget',
'levels' => ['error', 'warning'],
],
],
],
'db' => $db,
'mongodb' => [
'class' => \yii\mongodb\Connection::class,
'dsn' => 'mongodb://cafegardesh:12345#localhost:27017/cafegardesh',
]
],
'modules' => [
'taxonomy-term'=>[
'class'=> \mhndev\yii2TaxonomyTerm\Module::class
]
],
'params' => $params,
/*
'controllerMap' => [
'fixture' => [ // Fixture generation command line.
'class' => 'yii\faker\FixtureController',
],
],
*/
];
if (YII_ENV_DEV) {
// configuration adjustments for 'dev' environment
$config['bootstrap'][] = 'gii';
$config['modules']['gii'] = [
'class' => 'yii\gii\Module',
];
}
return $config;
and this is the command I execute :
php yii migrate/up --db=mongodb
and I get following error:
Exception 'yii\base\InvalidConfigException' with message '"mongodb" refers to a yii\mongodb\Connection component. yii\db\Connection is expected.'
in /home/majid/Projects/Gardesh-Tour-Backend/vendor/yiisoft/yii2/di/Instance.php:135
MongoDB component has got it's own migration controller. Use it instead.
In your console configuration add
'controllerMap' => [
'mongodb-migrate' => 'yii\mongodb\console\controllers\MigrateController'
],
Now you can use php yii mongodb-migrate/up.
It takes mongodb component for db as default.
Related
I am using frontend module in yii2 framework for my website, and so far the website is working good for all things especially the session of login from web interface.
The model handling the login is the LoginForm model
namespace app\models;
use Yii;
use yii\base\Model;
/**
* Login form
*/
class LoginForm extends Model {
public function login()
{
if ($this->validate()) {
return Yii::$app->user->login($this->getUser(), $this->rememberMe ? 7200 * 24 * 30 : 7200 * 24 * 30);
}
return false;
}
For website the default file for login is in SiteCotroller.php
use yii\web\Controller;
use frontend\models\ContactForm;
/**
* Site controller
*/
class SiteController extends Controller {
/**
* #inheritdoc
*/
public function behaviors() {
return [
'access' => [
'class' => AccessControl::className(),
'only' => ['logout', 'signup', 'index'],
'rules' => [
[
'actions' => ['signup'],
'allow' => true,
'roles' => ['?'],
],
[
'actions' => ['logout', 'index'],
'allow' => true,
'roles' => ['#'],
],
],
],
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'logout' => ['post'],
],
],
];
}
public function actionLogin() {
$this->layout = 'main';
if (!Yii::$app->user->isGuest) {
return $this->goHome();
}
$model = new LoginForm();
if ($model->load(Yii::$app->request->post()) && $model->login()) {
return $this->goBack();
} else {
return $this->render('login', [
'model' => $model,
]);
}
}
}
The login controller is working great for its own interface in the view file.
Now that I want to access login from app (ionic/angular), I copied this controller for login to AppController.php in the similar frontend folder:
class AppController extends \yii\rest\Controller {
public function actions()
{
$actions = parent::actions();
$actions['options'] = [
'class' => 'yii\rest\OptionsAction',
// optional:
'collectionOptions' => ['GET', 'POST', 'HEAD', 'OPTIONS'],
'resourceOptions' => ['GET', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'],
];
return $actions;
}
public function actionIndex() {
echo json_encode("hi");
}
public static function allowedDomains() {
return [
'*', // star allows all domains
'http://localhost:8100',
//'http://test2.example.com',
];
}
public function init()
{
parent::init();
\Yii::$app->user->enableSession = false;
}
public function beforeAction($action)
{
$this->enableCsrfValidation = false;
return parent::beforeAction($action);
}
public function behaviors()
{
$behaviors = parent::behaviors();
unset($behaviors['authenticator']);
// add CORS filter
$behaviors['corsFilter'] = [
'class' => \yii\filters\Cors::className(),
'cors' => [
'Origin' => ['*'],
'Access-Control-Request-Method' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'],
'Access-Control-Request-Headers' => ['*'],
'Access-Control-Allow-Credentials' => true,
],
];
$behaviors['contentNegotiator'] = [
'class' => \yii\filters\ContentNegotiator::className(),
'formats' => [
'application/json' => \yii\web\Response::FORMAT_JSON,
],
];
$behaviors['authenticator'] = [
'class' => HttpBearerAuth::className(),
'except' => ['login', 'checkuser'],
/*
'class' => CompositeAuth::className(),
'authMethods' => [
HttpBasicAuth::className(),
],
'except' => ['login', 'checkuser'],
*/
];
return $behaviors;
}
public function actionLogin() {
$model = new LoginForm();
$params = Yii::$app->request->post();
$model->username = $params['username'];
$model->password = $params['password'];
if ($model->login()) {
$user = User::findByUsername($model->username);
$response['success'] = Yii::$app->user->login($user);
$response['SessionID'] = Yii::$app->session->getId();
return $response;
} else {
$response['errors'] = $model->getErrors();
return $response;
}
}
The strange is, the action login in this AppController.php is working if I tried to login from app/postman, it returns true. However, the session is not saved, and SessionID is empty.
I have been exploring this for three days but still cant figure it out what is the problem.
This is my frontend/config/main.php file
$params = array_merge(
require __DIR__ . '/../../common/config/params.php',
require __DIR__ . '/../../common/config/params-local.php',
require __DIR__ . '/params.php',
require __DIR__ . '/params-local.php'
);
return [
'id' => 'app-frontend',
'defaultRoute' => 'site/index',
'basePath' => dirname(__DIR__),
'bootstrap' => ['log', 'gii'],
'controllerNamespace' => 'frontend\controllers',
'layout' => 'admin',
'components' => [
'request' => [
'parsers' => [
'application/json' => 'yii\web\JsonParser',
],
'csrfParam' => '_csrf-frontend',
],
'user' => [
'identityClass' => 'app\models\User',
'enableAutoLogin' => false,
'enableSession' => true,
'identityCookie' => ['name' => '_identity-frontend', 'httpOnly' => true, 'lifetime' => 3600 * 4],
'loginUrl' => ['site/login'],
],
'session' => [
'name' => 'advanced-frontend',
],
When I access the url directly into the yii2 web domain, I got this _csrf-frontend and advanced-frontend value in browser Cookies. But from app I dont get any.
Please I really appreciate the help. Many thanks in advance.
You cannot retrieve session from another app it is bound to domain. So what should you probably do is to handle that logic separate in your Ionic application which I think is preferred way. Or you can do it by storing sessions in DB (there is Yii class for that) and than handle it through extra requests (which is bad approach).
I am trying to check for a cookie on Application::EVENT_BEFORE_REQUEST. What I did is overriding the events function from Behavior model and return a custom function checkLanguage on the event that I mentioned above. I am triggering as beforeRequest in my controller ( in first I tried in the backend/config/main.php but it seems that the CheckIfLoggedIn class can't be reached from there ) and the request goes e to the public function events() in the CheckIfLoggedIn class but doesn't go on to the checkLanguage function.
This is my SiteController behaviors:
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'rules' => [
[
'actions' => ['login', 'error'],
'allow' => true,
],
[
'actions' => ['logout', 'index', 'language'],
'allow' => true,
'roles' => ['#'],
],
],
],
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'logout' => ['post'],
],
],
'as beforeRequest' => [
'class' => 'backend\components\CheckIfLoggedIn'
]
];
}
and CheckIfLoggedIn.php class:
<?php
namespace backend\components;
use yii\base\Behavior;
use yii\web\Application;
class CheckIfLoggedIn extends Behavior
{
public function events()
{
return [
Application::EVENT_BEFORE_REQUEST => "changeLanguage"
];
}
public function changeLanguage()
{
if(\Yii::$app->getRequest()->getCookies()->has('lang')){
\Yii::$app->language = \Yii::$app->getRequest()->getCookies()->getValue('lang');
}
}
}
The thing is you are trying to attach an Application event at controller level inside the behavior whereas the documentation says you should use the Application config .
Make the following updates, remove the events() function from your class.
backend/components/CheckIfLoggedIn.php
namespace backend\components;
use yii\base\Behavior;
class CheckIfLoggedIn extends Behavior
{
public function changeLanguage()
{
if(\Yii::$app->getRequest()->getCookies()->has('lang')){
\Yii::$app->language = \Yii::$app->getRequest()->getCookies()->getValue('lang');
}
}
}
and add the following to the common/config or backend/config if you want it for backend only
'on '.yii\web\Application::EVENT_BEFORE_REQUEST => [
'backend\components\CheckIfLoggedIn','changeLanguage'
] ,
remember to add it at the same level where id or components index is defined like this
return [
'id' => 'app-backend' ,
'on '.yii\web\Application::EVENT_BEFORE_REQUEST => [
'backend\components\CheckIfLoggedIn','changeLanguage'
] ,
For the first try add a die("hello world"); in the start of changeLanguage so you can confirm it is entering the function changeLanguage.
Hope it helps
I tried to install RESTful API module from this http://budiirawan.com/setup-restful-api-yii2/ and I am getting error
Object not found!
I tried setting mod_rewrite and also AllowOverride All configuration.
I also have connected it to correct database and that database has country table in it.
I also have .htaccess file and here is my api/config/main.php file
<?php
$params = array_merge(
require(__DIR__ . '/../../common/config/params.php'),
require(__DIR__ . '/../../common/config/params-local.php'),
require(__DIR__ . '/params.php'),
require(__DIR__ . '/params-local.php')
);
return [
'id' => 'app-api',
'basePath' => dirname(__DIR__),
'bootstrap' => ['log'],
'modules' => [
'v1' => [
'basePath' => '#app/modules/v1',
'class' => 'api\modules\v1\Module'
]
],
'components' => [
'user' => [
'identityClass' => 'common\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/country',
'tokens' => [
'{id}' => '<id:\\w+>'
]
]
],
]
],
'params' => $params,
];
Here is the model Country
<?php
namespace api\modules\v1\models;
use yii\db\ActiveRecord;
/**
* Country Model
*
* #author Budi Irawan <deerawan#gmail.com>
*/
class Country extends ActiveRecord
{
/**
* #inheritdoc
*/
public static function tableName()
{
return 'country';
}
/**
* We use the primary function because we don't use integer auto increment as a primary key.
* #inheritdoc
*/
public static function primaryKey()
{
return ['code'];
}
/**
* To let Yii know what fields exist on the table.
* Define rules for validation
*/
public function rules()
{
return [
[['code', 'name', 'population'], 'required']
];
}
}
I still get the same error while accessing it through http://localhost/yii2-api/api/v1/countries.
According to tutorial you have to use url :
http://localhost/yii2-api/api/web/v1/countries
Instead of
http://localhost/yii2-api/api/v1/countries
In my case,
the mysql table had compound primary key (made by mistake),
and only GET /v1/othertable/1 failed with this error, while other routes are working.
When I sorted that indexes through PhpMyAdmin it started to work.
I can trying simple code.
I have an AccessController which having behaviors():
class AccessController extends BackendController
{
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'rules' => [
[
'allow' => true,
'roles' => ['#'],
],
]
],
];
}
/*public function init()
{
parent::init();
if( Yii::$app->getUser()->getIsGuest() )
{
return $this->redirect('/auth');
}
return true;
}*/
public function actions()
{
return [
'WysiwygUpload' => [
'class' => WysiwygUpload::className(),
]
];
}
}
AS I understand, if I didn't declare 'only' key, that is mean to all actions and controllers.
But nothing happen: no one error, nothing
Your controller AccessController work only for yourApp/backend/access request not for all controllerAction..
If you want deny the access to guest in AdminController you shuold apply the behavior of AdminController
class AdminController extends Controller
{
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'rules' => [
[
'allow' => true,
'roles' => ['#'],
],
]
],
];
}
........
Then when a guest try accessing to yourApp/backend/admin this is not permitted
I am trying to follow the Yii2.0 example as found here with my simple product table
instead of User.
http://www.yiiframework.com/doc-2.0/guide-rest-quick-start.html
I'm using the basic package, not advanced.
When I try to access localhost/product
I get a 404 error.
When I use localhost/index.php or localhost/index.php/gii
I get the expected result (the default homepage, and the gii tool).
Here is what I'm working with.
The config file web.php
$params = require(__DIR__ . '/params.php');
$config = [
'id' => 'basic',
'basePath' => dirname(__DIR__),
'bootstrap' => ['log'],
'components' => [
'request' => [
// !!! insert a secret key in the following (if it is empty) - this is required by cookie validation
'cookieValidationKey' => 'xxx',
'parsers' => [
'application/json' => 'yii\web\JsonParser',
],
],
'urlManager' => [
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [
['class' => 'yii\rest\UrlRule', 'controller' => 'product'],
],
],
'cache' => [
'class' => 'yii\caching\FileCache',
],
'user' => [
'identityClass' => 'app\models\User',
'enableAutoLogin' => true,
],
'errorHandler' => [
'errorAction' => 'site/error',
],
'mailer' => [
'class' => 'yii\swiftmailer\Mailer',
// send all mails to a file by default. You have to set
// 'useFileTransport' to false and configure a transport
// for the mailer to send real emails.
'useFileTransport' => true,
],
'log' => [
'traceLevel' => YII_DEBUG ? 3 : 0,
'targets' => [
[
'class' => 'yii\log\FileTarget',
'levels' => ['error', 'warning'],
],
],
],
'db' => require(__DIR__ . '/db.php'),
],
'params' => $params,
];
if (YII_ENV_DEV) {
// configuration adjustments for 'dev' environment
$config['bootstrap'][] = 'debug';
$config['modules']['debug'] = 'yii\debug\Module';
config['bootstrap'][] = 'gii';
$config['modules']['gii'] = 'yii\gii\Module';
}
return $config;
The Model Product.php
namespace app\models;
use yii\db\ActiveRecord;
/**
* This is the model class for table "product".
*
* #property integer $ProductID
* #property string $Name
* #property double $Price
* #property string $ShortDesc
* #property string $LongDesc
* #property string $PicUrl
*/
class Product extends ActiveRecord
{
/**
* #inheritdoc
*/
public static function tableName()
{
return 'product';
}
/**
* #inheritdoc
*/
public function rules()
{
return [
[['Price'], 'number'],
[['ShortDesc', 'LongDesc', 'PicUrl'], 'string'],
[['Name'], 'string', 'max' => 60]
];
}
/**
* #inheritdoc
*/
public static function primaryKey()
{
return ['ProductID'];
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'ProductID' => 'Product ID',
'Name' => 'Name',
'Price' => 'Price',
'ShortDesc' => 'Short Desc',
'LongDesc' => 'Long Desc',
'PicUrl' => 'Pic Url',
];
}
}
The controller ProductController.php
use yii\rest\ActiveController;
class ProductController extends ActiveController
{
public $modelClass = 'app\models\Product';
}
I have tried to turn off 'enableStrictParsing' and set $pluralize to false, with no luck.
I have also tried adding this .htaccess file which gave me a 500 rather than a 404.
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.php
I'm sure I've done something silly here, but anyone willing to point that out will be a huge help.
Thanks!
Just set enableStrictParsing to false in urlManager array.
Scallopboat - I had the same issue. I raised it on the Yii2 forum and got the answer. The url you should use is http://localhost/basic/web/index.php/products.
I was also advised to change 'showScriptName' to true. The advise was that otherwise the links won't generate ok.
It was also suggested I could write some rewrite rules to use a cleaner url.
#scallopboat - I too have a similar problem. I got 404 response for view action.
Solved by following the instruction from,
How to configure urlManager to use rest api with string id
'rules' => [
[
'class' => 'yii\rest\UrlRule',
'controller' => 'region',
'pluralize'=>false,
'tokens' => [ '{id}' => '<id:\\w+>' ]
],
],
Accessed the view action using the below url:
http://localhost/icdp-service/region/[mongo-id]
Hope this helps.
Scallopboat. You can try this way while you do not solve your problem yet.
If you are using Apache as your web server,you should
edit the Apache config file httpd.conf and find blocks like
<Directory>****</Directory> and <Directory "your web root
dir">****</Directory>,modify the AllowOverride None to
AllowOverride All
uncomment the #LoadModule rewrite_module modules/ApacheModuleRewrite.dll
place the .hataccess file in your the base directory of your index.php