Laravel 5 Testing Database MySQL - mysql

In Laravel 4, I could specify the testing database through the config/testing/database file.
This file has, of course, been removed from Laravel 5 just to make things pointlessly more difficult.
So, how do I set up a MySQL test database in Laravel 5.
I do not want to use a SQLite database.
I would suggest some code but there isn't anything on SO or through Google that even attempts to answer this question.
Thank you.

If you check out the documentation Testing - Test Environment this mentions you set environment variables in the phpunit.xml
So for example you would add
<phpunit>
<php>
<env name="DB_CONNECTION" value="sqlite"/>
</php>
</phpunit>
to set the DB_CONNECTION I know you said you don't want to use SQLite but this is just an example you can set any of the values you would normally set in your .env file.
See Using Environment Variables to Add Flexibility to PHPUnit Tests for some more details on the use of environmental variables with PHPUnit.

You could go with the following approach:
Set your default databse connection to 'testing' when the app environment is also 'testing' in your database.php file:
'default' => app()->environment() == "testing" ?
env('DB_CONNECTION_TESTING', 'testing') :
env('DB_CONNECTION', 'mysql'),
Then also in your database.php file add the testing connection:
'testing' => [
'driver' => 'mysql',
'host' => env('DB_HOST_TESTING', 'localhost'),
'database' => env('DB_DATABASE_TESTING', 'forge'),
'username' => env('DB_USERNAME_TESTING', 'forge'),
'password' => env('DB_PASSWORD_TESTING', ''),
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'strict' => false,
],
In your .env file you have to add the corresponding lines:
DB_HOST_TESTING=localhost
DB_DATABASE_TESTING=database_testing
DB_USERNAME_TESTING=username_testing
DB_PASSWORD_TESTING=password_testing
So every time the app environment is testing ( which is the case in phpunit tests for example ) your application uses the testing database connection.
Of course you could also modify the phpunit.xml file like mentioned in the answer of Mark Davidson.

Related

Laravel ignoring multiple database config

(Never write software when you are very tired. Otherwise you ask very nice people on the internet to answer very obvious questions, that you would not ask, if you were not tired, because the principle problem is ... trivial. lol. So, in this case, I had neglected to uniquely rename the connection properties of the alternate database. Sigh....)
PROBLEM:
I can't make Laravel recognize a request for a different connection (database).
As far as I know, I've correctly configured .ENV, config/database.php, config/app.php correctly, and added $connection=myconnection to my models.
But no matter what I do Laravel/Eloquent/Doctrine Ignores all attempts to have some models use the default (common) database, and others use the multi-tenant databases.
Let's distinguish between a physical server, a database server instance running on that server, and a database within that instance, and multi-tenancy within that database.
I should be able to use any of these configurations by modifying the connection at runtime:
Single app/db server, single app, single database, with multi-tenants
Single app/db server, single app, multiple databases, with multi-tenants
Single app/db server, single app, multiple database instances, each with multiple databases, with multi-tenants
Single app server, multiple database servers, multiple databases instances, each with multi-tennants.
Multiple app servers, multiple database servers, multiple databases instances, each with multi-tennants.
And any combination thereof.
And I suspect that the lack of documentation, yet the inclusion of the eloquent/model feature "$connection=connection_configuration" means there is a fairly obvious solution that I don't intuit. (and I don't have a few free days to delve into the source and figure out what's going on there.)
Thanks for any help.
-Cheers
===ENV FILE===
DB_CONNECTION=crunch
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=crunch
DB_USERNAME=myapp
DB_PASSWORD=Nonsense!Talk
DB_CONNECTION=munchdata
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=munchdata
DB_USERNAME=myapp
DB_PASSWORD=Nonsense!Talk
===CONFIG/DATABASE.PHP===
'connections' => [
'crunch' => [
'driver' => 'mysql',
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'crunch'),
'username' => env('DB_USERNAME', 'crunch'),
'password' => env('DB_PASSWORD', 'Nonsense!Talk'),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'strict' => true,
'engine' => null,
'sticky' => true,
],
'munchdata' => [
'driver' => 'mysql',
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'munchdata'),
'username' => env('DB_USERNAME', 'munchdata'),
'password' => env('DB_PASSWORD', 'Nonsense!Talk'),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'strict' => true,
'engine' => null,
'sticky' => true,
],
],
===CONFIG/APP.PHP FILE===
'default' => env('DB_CONNECTION', 'crunch'),
// Default connections work fine
===A MODEL===
class EntityType extends BaseModel
{
use SoftDeletes;
public $connection = 'munchdata';
public $table = 'entity_type';
( ... )
}
// Ignores $connection
===CONSOLE===
>>> DB::connection('crunch')->getDatabaseName()
=> "crunch"
// Uses default connection
>>> DB::connection('munchdata')->getDatabaseName()
=> "crunch"
>>>
// Ignores connection
$result = DB::connection('munchdata')->select('select * from entity_type');
// Ignores the connection, and returns data from default db
$result = DB::connection('munchdata')->select('select munchdata.entity_type.* from munchdata.entity_type');
// Ignores the connection, but returns the right data anyway....
The values in the .ENV file must be unique, because the value "DB_CONNECTION=myDatabaseName" is not an array keyed from "myDatabaseName", but a 'dumb' string value. Meaning all entries in .ENV files must be uniquely named.
In other words, the .ENV files work OPPOSITELY from the Config/App > Connection[] definitions. Which... doesn't make a lot of sense, and isn't necessary.
I'd assumed that .ENV file was brought into an array with myDatabaseName as the key, and that the "DB_*" strings were constants. This seems logical.
This is probably how it SHOULD work, but it is not how it DOES work.
I suppose that since I've seen many other people post questions because of similar suppositions, that either we should request the change, or that I should write a bit of code to allow for multiple configs using the same constants as keys.
SOLUTION:
(1) If you have a small number of relatively invariant databases, continue to use the .ENV file - and give each CONSTANT a different name.
(2) If you dynamically create new databases, use .ENV for your default (boot) database, and then:
Either (a) Use your default (boot) database to store the related database connection configurations and cache them - which exposes your connection data and forces you to replicate that data for new instances,
Or (b) Use the file system to store the related database configurations, and (c) cache them.
In my case I have N (a lot) of databases, and I prefer using the db and then replication (dump and load the table with connection info) rather than a file of unknown size with the chance of 'leaking' into the real world due to dev/IT error or malice...
Cheers

Using SQLite for unit testing a mysql migrations setup

I want to use SQLite for PHPunit tests. We are using the mysql driver, so we have created our migrations based on that... meaning we are using nullables for default values. MYSQL doesn't care about this. SQLite, apparently, does.
Migrations:
Schema::table('users', function ($table) {
$table->string('username', 132)->nullable();
TestCase snippet: configuring phpunit environment
$app['config']->set('database.connections.testbench', [
'driver' => 'sqlite',
'database' => ':memory:',
'prefix' => ''
]
Running phpunit outputs:
Cannot add a NOT NULL column with default value NULL
I noticed there was a "STRICT" mode for mysql in the database.php configuration file that you can set to false which handles invalid or missing data types:
'mysql' => [
'driver' => 'mysql',
...
'strict' => false,
],
So I started looking for a strict mode for SQLite and found Strict Mode here, tried setting PRAGMA strict=ON; to off
$app['config']->set('database.connections.testbench', [
'driver' => 'sqlite',
'database' => ':memory:',
'prefix' => '',
'strict' => false
]
But this did not fix it.
Is there a way to set SQLite to ignore nullable() values set in migrations (aimed at mysql configurations) so I can run my unit tests quickly with SQLite in memory?
My alternatives are:
remove all nullable() options for migrations and add defaults, which will take forever
use mysql instead of sqlite, which will be much slower

lavaral 5 ERROR{ (SQLSTATE[HY000] [1045] Access denied for user 'root'#'localhost' (using password: YES)}

'default' => env('DB_CONNECTION', 'mysql'),
'connections' => [
'sqlite' => [
'driver' => 'sqlite',
'database' => storage_path('database.sqlite'),
'prefix' => '',
],
**JUST CHANGED THE CODE FOR LOCALHOST AND CHANNGED THE NAME TO ROOT AND SET THE PASSWORD OF PHPMYADMIN . **
**WHEN WRITTING THE COMMAND IN XAMPP SHELL ((Php artisan migrate:install)) **
'mysql' => [
'driver' => 'mysql',
'host' => env('DB_HOST', 'localhost'),
'database' => env('DB_DATABASE', 'laravel'),
'username' => env('DB_USERNAME', 'root'),
'password' => env('DB_PASSWORD', 'password'),
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'strict' => false,
],
'pgsql' => [
'driver' => 'pgsql',
'host' => env('DB_HOST', 'localhost'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'password'),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8',
'prefix' => '',
'schema' => 'public',
],
'sqlsrv' => [
'driver' => 'sqlsrv',
'host' => env('DB_HOST', 'localhost'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'password'),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8',
'prefix' => '',
],
],
/*
|--------------------------------------------------------------------------
| Migration Repository Table
|--------------------------------------------------------------------------
|
| This table keeps track of all the migrations that have already run for
| your application. Using this information, we can determine which of
| the migrations on disk haven't actually been run in the database.
|
*/
'migrations' => 'migrations',
/*
|--------------------------------------------------------------------------
| Redis Databases
|--------------------------------------------------------------------------
|
| Redis is an open source, fast, and advanced key-value store that also
| provides a richer set of commands than a typical key-value systems
| such as APC or Memcached. Laravel makes it easy to dig right in.
|
*/
'redis' => [
'cluster' => false,
'default' => [
'host' => '127.0.0.1',
'port' => 6379,
'database' => 0,
],
],
it is showing error SQLSTATE[HY000] [1045] Access denied for user 'root'#'localhost' (using password: YES)
By default laravel assumes that you will want to have different configurations for different environments. E.g. in a testing environment, you might wish to have a different username and password and in a production environment different. Since laravel has so many configuration files, it quickly becomes a nightmare to manage all those. Hence laravel makes use of PHP's environment variables.
See the docs here.
What is basically says is that if you wish to use the "environment" variables, which laravel uses by default, you have to place all your configurations in the env() method as already mentioned.
If you do not wish to do this, e.g. for simple projects, simply remove the env from your code, like this.
'mysql' => [
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'laravel',
'username' => 'root',
'password' => 'password',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'strict' => false,
],
Note that you can mix and match. i.e you can have some of the variables in env and some stand-alone.
So why use env at all?
Lets say your application has 100 testers all placed in different locations. In laravel you have to code approximately 8-10 configuration files. Also you need to version-control those files. So you have two problems at hand:
You do not wish to send all 100 users the same credentials. Also they might use different database, cache server, etc which means that they will have different configurations. So every user has to maintain those 8-10 configuration files by hand.
You do not wish to send these configuration files to version control. Because if you do, whole world will know your API secrets and possibly will take advantage of that (just like password). Also if you look at laravel conf files, you will notice that there are other information such as timezone, debug property, etc that are also in conf files, and you do want to version-control them. So how do you version-control such configuration files and still hide your sensitive information.
The answer is env variables. Laravel uses dotenv whose documentation can be found here. Basically these are variables that live in one file called .env in a key-value pair. E.g.
Sample contents of .env file
APP_DEBUG=false
APP_KEY=ABCDEFGH
...
Once you define your .env file as this, you can get the value using the key as such env('APP_DEBUG').
So this solves the above mentioned problem in following ways:
you keep the .env file to yourself. And you also declare another file called .env.example which is an exact replica of original file except the fact that it contains sample values, not your sensitive values. Then you pass this new example file to everyone. They will replace the sample data with their own sensitive information.
Since you are version-controlling the example file, you can version control all your conf files because they don't contain the secret. The secret is in .env files. All those conf files contain is values like these env('APP_KEY') and the actual value is replaced at run time using your .env file.
Make sure you have to set up right server credentials into .env file on your Laravel project:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=myapp_db
DB_USERNAME=root
DB_PASSWORD=pass
Try to clean up artisan cache and restart the artisan,
php artisan config:clear
restart php artisan

Laravel Migration - Says unknown database, but it is created

when I use php artisan migrate, i get the error SQLSTATE[42000] [1049] Unknown database 'databaseName'.
But the database DOES exists! I even tried going back into terminal, logged into mysql and created the database again, and it said that database already exists!
Why is this giving me this error?
I have the same problem. When I run: php artisan migrate.
In my case I use Vagrant with scotch box.
To solve this, enter:
vagrant ssh
cd /var/www/yourproject
php artisan migrate
And all work well.
In your app/config/database.php file change the default value from databaseName to a real database name that you are trying to use in your application, something like this (for mysql driver):
'mysql' => array(
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'your database name', //<-- put the database name
'username' => 'your user name',
'password' => 'your password',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
),
One thing could be your casing. If you read the docs on case sensitivity it says:
the case sensitivity of the underlying operating system plays a part
in the case sensitivity of database and table names. This means
database and table names are not case sensitive in Windows, and case
sensitive in most varieties of Unix. One notable exception is Mac OS
X, which is Unix-based but uses a default file system type (HFS+) that
is not case sensitive.
Then go and check your application database setting found # app/config/database.php.
Something that looks like this:
'mysql' => array(
'read' => array(
'host' => '192.168.1.1',
),
'write' => array(
'host' => '196.168.1.2'
),
'driver' => 'mysql',
'database' => 'databaseName',
'username' => 'root',
'password' => '',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
),
And double check everything.
Also try using snake_case rather than camelCase for you database name.
In my case I had MySQL installed on this port: 3308, and in Laravel env file there was 3306.

CakePHP 2.1 doesn't work on localhost

I deployed my app on a remote host and everything works as expected. But when I try to test my code on localhost, it gives me the following error, without any change to the code working on the host:
Fatal error: Class 'AppHelper' not found in [path]
I am using CakePHP 2.1 and MySQL as my default datasource.
I connect to my local database just like to the remote one (with authentication changes):
public $default = array(
'datasource' => 'Database/Mysql',
'persistent' => false,
'host' => 'localhost',
'login' => 'root',
'password' => '',
'database' => 'database',
'prefix' => '',
'encoding' => 'utf8',
);
Why isn't this working on my localhost? Thank you
Two possible things:
either you didnt know about the AppHelper requirement for 2.1:
http://book.cakephp.org/2.0/en/appendices/2-1-migration-guide.html
or you forget to declare the helper at the very top of your class:
App::uses('AppHelper', 'View/Helper');
Although the second one is highly unlikely if you are not running any unit tests.
So my bet is on the first one.