Laravel php script DB class not found - php

I'm trying to write a script for laravel that queries
my database and fetches tables, but I'm not sure what to include
in the file in order to get the DB class to work.
Thus far my code looks like:
$tables = DB::query("SHOW TABLES");
foreach ($tables as $table) {
print $table . "\n";
}
I've tried using require "../../vendor/autoload.php" but that doesn't help.
So for instance, the DB class works fine if I call it within a controller, but not
if I create a directory, say /application/scripts and create a file test.php .
If I try to call DB in that file, the DB class isn't defined (for good reason).
I'm wondering what I need to require in that file in order for that class to be defined.

I would suggest using the Illuminate/Database package (part of Laravel 4). You won't get the DB interface, because that's a special facade provided by the Laravel Framework, but all the query builder functionality is available through the capsule.
Install illuminate/database using composer and then follow the included readme notes (included below for completeness).
Illuminate Database
Usage Outside Of Laravel 4
$config = array(
'fetch' => PDO::FETCH_CLASS,
'default' => 'mysql',
'connections' => array(
'mysql' => array(
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'laravel',
'username' => 'root',
'password' => 'password',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
),
),
);
$capsule = new Illuminate\Database\Capsule($config);
// If you want to use the Eloquent ORM...
$capsule->bootEloquent();
// Making A Query Builder Call...
$capsule->connection()->table('users')->where('id', 1)->first();
// Making A Schema Builder Call...
$capsule->connection()->schema()->create('users', function($t)
{
$t->increments('id');
$t->string('email');
$t->timestamps();
});

You do not need to include anything. Laravel will include what it needs and setup the system itself. You are using a variable called $db but it is not defined and means/does nothing. What you are looking for is the DB class. Try this:
$tables = DB::query('SHOW TABLES');
foreach ($tables as $table)
{
echo $table.PHP_EOL;
}
Also, check out the Fluent DB class documentation:
http://laravel.com/docs/database/fluent

...Isn't it DB::query()? A call to the database engine is through a class, not a variable, for scoping issues.

Related

How to create a new database by Yii2 migration, when I have to use it by default?

I have a task which is described like "Creating a new database with Yii2 migration, and use it by default". But I have some collusion: I have to set up at lest one default database in my main-local.php file to start migration. But also I have to create this database with initial migration.
return [
'db' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=default_base',
'username' => 'root',
'password' => '',
'charset' => 'utf8',
],
];
How can I deal with it? To create a database with migration and set up as default one.
When I execute my migration (there is code from my migration file):
public function safeUp()
{
$this->execute("CREATE DATABASE default_base");
}
I have an exception:
General error: 1007 Can't create database 'default_base'; database exists
I realize that is because I have already created default_base in phpmyadmin (click button "created database"), and connected it with app in my main-local.php file.
But I need this base to be created only when I execute yii migrate.
UPD
I have tried the way rob006 recommended but I get connection error
Exception 'yii\db\Exception' with message 'SQLSTATE[HY000] [1049] Unknown database 'default_base''
My main-local.php looks like the way exactly rob006 recommends, but I still can`t migrate. It works only if I set:
'preinstallDb' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost',
'username' => 'root',
'password' => '',
'charset' => 'utf8',
],
'db' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=already_exists_db',
'username' => 'root',
'password' => '',
'charset' => 'utf8',
],
With the already exists database. What do I do wrong again?
You can define DSN without database name:
'dsn' => 'mysql:host=localhost',
And use this connection to create database.
Yii::$app->preinstallDb->createCommand('CREATE DATABASE default_base')->execute();
However you can't really create database in migration - MigrateController needs database for migration table to save migrations history. You would need to create database before MigrateController will try to access migration table. You can do this by overriding MigrateController::getMigrationHistory():
class MigrateController extends \yii\console\controllers\MigrateController {
protected function getMigrationHistory($limit) {
Yii::$app->preinstallDb->createCommand('CREATE DATABASE IF NOT EXISTS default_base')->execute();
return parent::getMigrationHistory($limit);
}
}
And use your controller in console app config:
'controllerMap' => [
'migrate' => [
'class' => MigrateController::class,
],
],
But honestly, it is ugly solution with a lot of hardcoding, it may be better to create some setup utility which will perform database creation outside of main app. Also usually for security reasons DB user used by application should not even have privileges to create database, so you may reconsider your use case - do you really need to create database by app?
I find the only way make it work for me. Just overriding init() in MigrateController.
First I added controllerMap in main-local.php file:
'controllerMap' => [
'migrate' => [
'class' => 'console\controllers\MigrateController',]]
Then put new controller in console\controllers:
namespace console\controllers;
use yii\console\controllers\MigrateController as BasicMigrateController;
use Yii;
class MigrateController extends BasicMigrateController
{
public function init()
{
Yii::$app->preinstallDb->createCommand('CREATE DATABASE IF NOT EXISTS default_base')->execute();
parent::init();
}
}

How to test MySQL connection in PHP and Laravel? [duplicate]

This question already has answers here:
How to connect to mysql with laravel?
(6 answers)
Closed 8 years ago.
I'm making a PHP application installer (something like Wordpress installation script) and I need to check mysql connection using host name, username, password and database provided by user during installation.
I'm using this code as a Laravel controller method to test connection:
public function TestDatabaseConnection(){
try {
$database_host = Config::get('config.database_host');
$database_name = Config::get('config.database_name');
$database_user = Config::get('config.database_user');
$database_password = Config::get('config.database_password');
$connection = mysqli_connect($database_host,$database_user,$database_password,$database_name);
if (mysqli_connect_errno()){
return false;
} else {
return true;
}
} catch (Exception $e) {
return false;
}
}
This code doesn't seem to properly test the connection. Function return value (true/false) doesn't depend whether user supplies db data at all, or if db data is correct/incorrect..
Fils /app/config/config.php contains the following array:
<?php return array('database_host' => 'localhost', 'database_name' => 'dbasename', 'database_user' => 'dbuser', 'database_password' => 'pass');
and it's being updated via form during installation process.
Is there any way to modify this code or maybe you have some other code suggestions?
Your question is:
How to test MySQL connection in PHP and Laravel?
But then you are setting up a standard PHP MySQLi connection like this:
$connection = mysqli_connect($database_host,$database_user,$database_password,$database_name);
Why would you do that? The whole purpose of using a framework is to work within the framework. And something that encompasses these two basic systems concepts:
Read a configuration file.
Establish a database connection.
Doing those things is something that pretty much every capable—and widely adopted—programming framework should be able to handle within it’s own structure & using it’s own methods.
So that said, looking at the Laravel documentation on “Basic Database Usage” shows the following. This is placed in your DB configuration file located in app/config/database.php.:
'mysql' => array(
'read' => array(
'host' => '192.168.1.1',
),
'write' => array(
'host' => '196.168.1.2'
),
'driver' => 'mysql',
'database' => 'database',
'username' => 'root',
'password' => '',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
),
The example has two distinct DB connections: One for read and the other for write, but that is not how most DB connections for simple projects work. So you can set this instead also using your settings:
'mysql' => array(
'host' => Config::get('config.database_host'),
'driver' => 'mysql',
'database' => Config::get('config.database_name'),
'username' => Config::get('config.database_user'),
'password' => Config::get('config.database_password'),
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
),
Then to test that connection, you would just do this:
if(DB::connection()->getDatabaseName())
{
echo "Yes! successfully connected to the DB: " . DB::connection()->getDatabaseName();
}
But that said you are also saying:
I'm making a PHP application installer…
Why reinvent the wheel when PHP build systems such as Phing exist?
You can simply check whether the connection is made or not using this:
if(DB::connection()) {
// connection is made
}
Because you don't need to make connection manually. If the user provided right credentials in the app/config/database.php then the user will be able to query in the database but if you need to check the connection then given code above is able to check because if the connection is not made then an error will be thrown and on a valid connection the Illuminate\Database\MySqlConnection object will be returned. So, in this case it's also possible to use:
if(DB::connection() instanceof Illuminate\Database\MySqlConnection) {
// connection is made
}
So, according to your example of TestDatabaseConnection method you can do something like this:
public function TestDatabaseConnection(){
// Returns Illuminate\Database\MySqlConnection on successful
// connection; otherwise an exception would be thrown if failed
return DB::connection();
}
If you really want to catch the error of laravel db connection failure,
you can define this:
App::error(function(PDOException $exception, $code)
{
die('do what you want here');
});
I defined it inside:
/app/start/global.php
you can define it where ever you like.

How to use Illuminate database instance throughout required PHP files

I am trying to setup a restful API using Slim PHP. This is my first time using a microframework and I am trying to structure an application with it so it remains maintainable.
I am trying to structure my application like so:
root
- index.php
- composer.json
- app
- - routes
- - - session.php
- - lib
- - - functions.php
- - vendor
- - - Composer Vendor dirs and files
I am using illuminate to access my MySQL database and while I had all my code in just the index.php file everything worked. When I tried to split up my authentication functions into the session.php I was no longer able to access the illuminate instance. I followed the standard setup from the github page
use \Slim\Slim;
use Illuminate\Database\Capsule\Manager as Capsule;
$capsule = new Capsule;
$capsule->addConnection([
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'database',
'username' => 'root',
'password' => 'password',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
]);
// Set the event dispatcher used by Eloquent models... (optional)
use Illuminate\Events\Dispatcher;
use Illuminate\Container\Container;
$capsule->setEventDispatcher(new Dispatcher(new Container));
// Make this Capsule instance available globally via static methods... (optional)
$capsule->setAsGlobal();
// Setup the Eloquent ORM... (optional; unless you've used setEventDispatcher())
$capsule->bootEloquent();
$app = new Slim();
//get login routes
require 'app/routes/session.php';
$app->get("/", function() use ($app){
$app->render(200,array(
'msg' => 'welcome',
));
});
Here is my session.php:
$app->post("/login", function() use ($app){
$postVarsAll = $app->request->post();
if( isset($postVarsAll['password']) && isset($postVarsAll['username']))
{
//Get associated user
$app->render(200,array(
'msg' => print_r(Capsule,true)
));
$user = Capsule::table('user')->where('username','=',$postVarsAll['username'])- >first();
}else{
$app->render(200, array(
"msg" => "no params",
"params" => $postVarsAll
));
}
});
This throws a 500 error and tells me:
"msg": "NOTICE: Use of undefined constant Capsule - assumed 'Capsule'",
I am looking to just use the Capsule instance inside my session.php. Does anyone know how to do this?
If I take out the Capsule calls the route works.
Thanks for your help!
Edit
$app->post("/login", function() use ($app,$capsule){
$postVarsAll = $app->request->post();
if( isset($postVarsAll['password']) && isset($postVarsAll['username']))
{
//Get associated user
$app->render(200,array(
'msg' => print_r($capsule,true)
));
return;
...
with this I get the full capsule object.
Edit 2
Thank you volkinc for finding the answer.
I can use $capsule->table("user")->... for my query needs.
'msg' => print_r(Capsule,true)
try
'msg' => print_r($capsule,true)

Laravel 4.2 dynamic database connection

I am trying to setup connections to multiple database under the same instance for correlation data analysis
Here is the basic idea of the connection code
$a = array('a','b','c');
$b = array('a','b','c');
foreach($a as $ac){
foreach($b as $bc){
Config::set('database.connections.'.$ac.'_'.$bc, array(
'driver' => 'mysql',
'host' => 'somehost',
'port' => '3306',
'database' => $ac.'_'.$bc,
'username' => 'user',
'password' => 'user',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => ''
));
}
}
There are about 40 different db in that instance, and could change rapidly, so I want to avoid permanently create the connection in the config file and generate the connection on the fly with user input. And from what I gather, the above code should auto append the array to database.connections (see laravel github ), but I am getting this error.
SQLSTATE[HY000] [2002] No such file or directory
if I change database.connections.".$ac.'_'.$bc to database.connections.mysql the code runs okay. So what am I missing here :( , I am calling that piece of code under the constructor of the first controller the input will hit.
Thank you very much for the help in advance
After playing around a bit, found out what's the problem.
After calling the code above in controller,
in model, not only you have to make the initial connection but also you have to include a table in that statement in order to divert the connection to the specific DB, otherwise it will fall back to default connection if you use the way that builder query example from Laravel documentation. So instead of doing
$this->query = DB::connection($ac.'_'.$bc);
$this->query = DB::table('sometable');
do it like
$this->query = DB:connection($ac.'_'.$bc)->table('sometable');
Then connection for $this->query will lock to the new database pointed.

Laravel 4 - Connect to other database

I want to connect to another database sometimes.
I created a config.php with the database connection data.
But how can i tell laravel to connect to this database insted of using the config/database.php?
For example when using the Schema class.
Since no one seems to understand what i want.
I DON'T want to use the config/database.php, i want to use a different config file on a different location.
It sounds like you figured this out. Here's how I'd accomplish it anyway for other people coming in, or in case something useful is here for you.
First, Add a second connection in app/config/database.php. Note: That file path may change depending on your environment.
<?php
return array(
'connections' => array(
'mysql' => array(
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'database1',
'username' => 'user1',
'password' => 'pass1'
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
),
'mysql2' => array(
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'database2',
'username' => 'user2',
'password' => 'pass2'
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
),
),
);
Second, in your code, you can use (as mentioned) the 2nd connection where you would like:
Schema::connection('mysql2')->create('users', function($table) {})
There's more documentation on this - see Accessing Connections.
Eloquent ORM
You can define the variable for "connection" in an eloquent class to set which connection is used. That's noted in the Basic Usage section.
See that variable on here on Github and the method which you can set to set the connection dynamically here.
Edit
The OP has made it clear that they do not wish to use the config/database.php file for config.
However without explaining further, I can't comment. I'm happy to help - sounds like it would be useful to know why the config/database.php file can't/shouldn't be used, as this can help us ascertain the problem and create a useful solution.
I believe you want to implement some kind of logical sharding where databases would be dynamically created.
In such scenario in laravel you can dynamically add a database config, like below
$conn = array(
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'DATABASE',
'username' => 'USERNAME',
'password' => 'SOME_PASSWORD',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
);
Config::set('database.connections.DB_CONFIG_NAME', $conn);
Now to connect via eloquent
MODEL::on('DB_CONFIG_NAME')->WHAT_EVER('1');
Incase of Query Builder you can do
$DB = DB::connection('DB_CONFIG_NAME');
use $DB->select() for querying now.
Hope this would help devs looking for a possible solution for this question
Remember that Laravel 4 is actually a collection of components, and you can use these components solo.
https://github.com/illuminate/database
There is an example here that shows off how interacting with the Capsule class works:
use Illuminate\Database\Capsule\Manager as Capsule;
$capsule = new Capsule;
$capsule->addConnection([
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'database',
'username' => 'root',
'password' => 'password',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
]);
// Set the event dispatcher used by Eloquent models... (optional)
use Illuminate\Events\Dispatcher;
use Illuminate\Container\Container;
$capsule->setEventDispatcher(new Dispatcher(new Container));
// Set the cache manager instance used by connections... (optional)
$capsule->setCacheManager(...);
// Make this Capsule instance available globally via static methods... (optional)
$capsule->setAsGlobal();
// Setup the Eloquent ORM... (optional; unless you've used setEventDispatcher())
$capsule->bootEloquent();
This is a bunch of bootstrapping that you'll need to run, so tuck it away somewhere in a function or method.
But, its absolutely possible.
There is a simpler solution. If you are using Larave 4 there is an option that worked for me. Recently they added $table variable that you can specify in your model. Refer to this link.
class User extends Eloquent {
protected $table = 'my_users';
}
If you are using MySQL, you can do the following:
class User extends Eloquent {
protected $table = 'mydbname.my_users';
}
If you are using SQL Server, you can do this:
class User extends Eloquent {
protected $table = 'mydatabase..my_users';
}
My Config file had DB1 specified but I created a model which wants to access DB2 in the same MySQL host. So this was a quick and dirty way to accomplish this.
Now I don't fully leverage Eloquent ORM all the time so this "hack" may not work with Many to Many or one to Many Eloquent methods.
One another idea I had but I didn't actually try was creating a stored procedure (routine) in DB1 and inside of that routine I can access DB2 tables by querying link this:
SELECT * from db2.mytable where id = 1;
To use a config file in another location, say src/config:
use Config;
$this->dbConfig = Config::get('appname::dbInfo.connections.test');
$this->database = $this->dbConfig['database'];
$this->username= $this->dbConfig['username'];
$this->password= $this->dbConfig['password'];
Where dbInfo is a simple php file in your app's src/config directory returning an array containing the element connections which is an array of database properties.
You can tell Laravel to use an external config file using:
Config::set("database.connections.test", $this->dbConfig);
DB::connection("test");
Edit bootstrap/start.php file and add your machine name (open terminal: hostname).
Add your machine to $env,
$env = $app->detectEnvironment(array(
'mymachine' => array('mymachine.local'),
));
Create a new path at 'app/config/mymachine'
Add a copy of database.php with new config params.

Categories