Yii2 Failing to instantiate component or class "db" - yii2

I use a Yii2 console application to run migrations. It's a very basic app, that goes like this (yii.php in the / folder of the project):
<?php
require __DIR__ . '/vendor/autoload.php';
require __DIR__ . '/vendor/yiisoft/yii2/Yii.php';
$config = require __DIR__ . '/config/console.php';
(new yii\console\Application($config))->run();
?>
So when i run
php yii.php
Everything's fine, but when i run
php yii.php migrate/create create_user_table
I am getting an error message:
Error: Failed to instantiate component or class "db".
My Yii is v2.0.15.1
UPD 19:32 30/12/2018
When I add a db config to a config/console.php like this:
return [
'id' => 'school-console',
'basePath' => dirname(__DIR__),
'db' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=school',
'username' => 'root',
'password' => 'Taras1love',
'charset' => 'utf8',
]
];
I get this:
Error: Setting read-only property: yii\console\Application::db

You are missing the database component configurations for the console application you need to add the following inside the config/console.php file. As you are usign the basic-app for Yii2 you must have a db.php file with the database configurations, you need to include it like below
//this goes on the top of your `console.php` file
$db = require __DIR__ . '/db.php',
return [
'id' => 'myapp-console',
'basePath' => dirname(__DIR__)
//add the db component
'components' => [
'db' => $db,
]
];
Your db.php should be like below inside the config folder, change the values for the username, password and dbname.
<?php
return [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=YOUR_DB_NAME',
'username' => 'DB_USER',
'password' => 'DB_PASS',
'charset' => 'utf8',
];
or you can assign it inside the config/console.php if you dont want to create a separate file
return [
'id' => 'myapp-console',
'basePath' => dirname(__DIR__)
//add the db component
'components' => [
'db' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=YOUR_DB_NAME',
'username' => 'DB_USER',
'password' => 'DB_PASS',
'charset' => 'utf8',
]
]
];

I found that I got this problem if I ran yii directly from vendor/bin.
If I went to the console directory and ran it from there using ./yii, I did not get this error and was able to create the migration.
In other words:
cd <project-root>/vendor/bin
yii migrate/create xxx
did not work
But:
cd <project-root>/console
./yii migrate/create xxx
did work

this happened to me because I accidentally renamed my migration and it was not matching the file name

Related

I cannot create new tables for migration

I am running
./yii migrate/create create_junction_table_for_sales_and_branch_tables --fields="created_at:dateTime"
and I get the following error:
Error: SQLSTATE[HY000] [2002] php_network_getaddresses: getaddrinfo failed: nodename nor servname provided, or not known.
Trying to create an ordinary table also gives the same error. I cannot solve this issue.
This is part of my code in common/config/main.php:
'components' => [
'db' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=' . getenv('DB_HOST') . ';port='.
getenv('DB_PORT', 3306) .';dbname=' . getenv('DB_NAME'),
'username' => getenv('DB_USERNAME'),
'password' => getenv('DB_PASSWORD'),
'charset' => 'utf8',
],
The best way to configure your db connection is:
return [
'class' => \yii\db\Connection::class,
'dsn' => 'mysql:host=address:port;dbname=mydatabase',
'username' => 'admin',
'password' => '123321',
'charset' => 'utf8',
];
Also you can define variables in yor cfg file, and use them, don't forget, that env.variables, which you are using, must be defined in your environment
// You may define env.variable in your system.
$host = 'localhost';
$port = '3306';
$dbname = 'mydatabase';
$username = 'admin';
$password = '123321';
$charset = 'utf8';
return [
'class' => \yii\db\Connection::class,
'dsn' => "mysql:host={$host}:{$port};dbname={$dbname}",
'username' => $username,
'password' => $password,
'charset' => $charset,
];
You can customize variables as you want, also you may write methods, before returning connection class, to get all needed variables.

How can I use an existing database with the advanced template of Yii2?

I installed the yii2 advanced template, and I'm now at migration point where I should create a new database and migrate the app to it.
but I already have a database full of data and I want to use it with yii2 without modifying anything
Open the file
common/config/main.php
and add the parameters for your database connection
<?php
return [
'components' => [
'db' => [
'class' => 'yii\db\Connection',
'dsn' => '',
'username' => '',
'password' => '',
'charset' => 'utf8',
],
],
];

Send message over SMTP using Swiftmailer and Yii2

I need some advice over the following case:
I have configured the config/web.php file as follows
'components' => [
...
'mailer' => [
'class' => 'yii\swiftmailer\Mailer',
'useFileTransport' => false,
'transport' => [
'class' => 'Swift_SmtpTransport',
'host' => 'smtp.gmail.com',
'username' => 'myusername',
'password' => 'mypassword',
'port' => '587',
'encryption' => 'tls',
],
],
Also in the Controller:
$message = Swift_Message::newInstance()
->setSubject('...')
->setFrom(['mymail'])
->setTo(['recipient'])
->setBody('......');
$transport = Swift_SmtpTransport::newInstance();
$mailer = Swift_Mailer::newInstance($transport);
$mailer->send($message);
I get the Error: 'Connection could not be established with host ' (Swift_TransportException)
Any ideas? Thank you.
Since you have got this configured as Yii component use it properly.
See documentation example:
Yii::$app->mailer->compose('contact/html', ['contactForm' => $form])
->setFrom('from#domain.com')
->setTo($form->email)
->setSubject($form->subject)
->send();
Also: see this SO question.
In your config set it as
'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.
'transport' => [
'class' => 'Swift_SmtpTransport',
'host' => 'smtp.gmail.com',
'username' => 'yourusername',
'password' => 'yourpassword',
'port' => '587',
'encryption' => 'tls',
]
],
In your controller you can compose the email.
Yii::$app->mailer->compose('#app/mail/layouts/reset',['model' =>$model])
->setTo('to#example.com')
->setFrom('from#example.com')
->setSubject('Subject Here')
->setTextBody('You can either render the layout or declare your body here')
->send();
In the above code I am using layouts. You can use layouts and pass variables to the layout and use them. If you dont want to use layouts that works as well just call the compose method
Yii::$app->mailer->compose()
I did the following and worked:
$transport = Swift_SmtpTransport::newInstance(Yii::$app->components['mailer']['transport']['host'], Yii::$app->components['mailer']['transport']['port']);
$transport->setUsername(Yii::$app->components['mailer']['transport']['username']);
$transport->setPassword(Yii::$app->components['mailer']['transport']['password']);

Setting up a database for Yii 2

I need to install an app written in Yii 2 on my local computer. I installed composer and initiated the app with:
php /path/to/yii-application/init
Now I need to "create a new database and adjust the components['db'] configuration in common/config/main-local.php accordingly."
I have no clue how to do that.
1) Create database on your server.
2) Open common/config/main-local.php
Edit components to:
'components' => [
'db' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=DATABASE_NAME',
'username' => 'DATABASE_USER',
'password' => 'DATABASE_PASSWORD',
'charset' => 'utf8',
],
If using MAMP with mac then edit dsn line to :
'dsn' => 'mysql:unix_socket=/Applications/MAMP/tmp/mysql/mysql.sock;dbname=DATABASE_NAME'

How to replace environment-specific config, not cascade

I want to have a local development environment configuration for my database.php. I've created a new config director in my app and copied the database.php file into it. I'm using MongoDB and on production, I'm using a replica set with multiple servers, but locally, I'm just running a single server, so my connection info for production has more options:
Production:
...
'connections' => array(
'mongodb' => array(
'driver' => 'mongodb',
'host' => array('mongoDBA', 'mongoDBB'),
'port' => 27017,
'username' => 'myUserName',
'password' => 'myPassword',
'database' => 'theDatabase',
'options' => array('replicaSet' => 'myReplicaSet')
)
),
Local:
...
'connections' => array(
'mongodb' => array(
'driver' => 'mongodb',
'host' => 'localhost',
'port' => 27017,
'database' => 'theDatabase'
)
),
The problem is, when my local environment config loads, it merges the "connections" array. I want a way to completely replace the "mongodb" connection, so it's either one or the other, not both.
How can I accomplish this?
Create different set of configuration files:
app/config/local/database.php
app/config/production/database.php
And delete the file (or what you don't want of it):
app/config/database.php
And the you have to set your environment as
local
development
EDIT
This is how I do set my environment flawlessly, so I don't have to deal with hostnames and still don't get my local environment conflict with staging and production.
Create a .environment file in the root of your application and define your environment and add your sensitive information to it:
<?php
return array(
'APPLICATION_ENV' => 'development', /// this is where you will set your environment
'DB_HOST' => 'localhost',
'DB_DATABASE_NAME' => 'laraveldatabase',
'DB_DATABASE_USER' => 'laraveluser',
'DB_DATABASE_PASSWORD' => '!Bassw0rT',
);
Add it to your .gitignore file, so you don't risk having your passwords sent to Github or any other of your servers.
Right before $app->detectEnvironment, in the file bootstrap/start.php, load your .environment file to PHP environment:
foreach(require __DIR__.'/../.environment' as $key => $value)
{
putenv(sprintf('%s=%s', $key, $value));
}
And then you just have to use it:
$env = $app->detectEnvironment(function () {
return getenv('APPLICATION_ENV'); // your environment name is in that file!
});
And it will work everywhere, so you don't need to have separate dirs for development and production anymore:
<?php
return array(
'connections' => array(
'postgresql' => array(
'driver' => 'pgsql',
'host' => getenv('DB_HOST'),
'database' => getenv('DB_DATABASE_NAME'),
'username' => getenv('DB_DATABASE_USER'),
'password' => getenv('DB_DATABASE_PASSWORD'),
'charset' => 'utf8',
'prefix' => '',
'schema' => 'public',
),
),
);
Note that I don't set a fallback:
return getenv('APPLICATION_ENV') ?: 'local';
Because, if I don't set the file, I want it to fail on every server I deploy my app to.