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)
Related
I am currently facing a problem, I explain myself. For my project I'm trying to make a dynamic connection to a database (I have 2 virtual machines with a different IP but with the same identifiers and tables with MSSQL database engine (SQLSRV)).
I try something like this ->
use Doctrine\DBAL\Driver\SQLSrv\Driver;
/**
* #Route("/testconnection", name="test_connect")
*/
public function testConnection(Driver $Driver){
$connectionParams = array(
'dbname' => 'job',
'user' => 'sa',
'password' => 'Lasernet#2020',
'host' => '192.168.1.34',
'driver' => 'pdo_sqlsrv',
);
$conn = $Driver->connect($connectionParams);
dd($conn);
}
Error message
Cannot autowire argument $Driver of "App\Controller\HomeController:testConnection()": it references class "Doctrine\DBAL\Driver\SQLSrv\Driver" but no such services exists.
Error message
But the problem is that Symfony sends me back an error that I find hard to solve/understand.
If someone has a solution to my problem/success to make a dynamic connection to databases.
If you need more information tell me.
The error message says it. No such service exists.
You must define the Doctrine\DBAL\Driver\SQLSrv\Driver class as a symfony service in your public/services.yaml to autowire it.
Update your public/services.yaml with:
services:
Doctrine\DBAL\Driver\SQLSrv\Driver:
autowire: true
But why you will autowire this class? The same behaviour you can get with
public function testConnection(){
$Driver = new Driver();
$connectionParams = array(
'dbname' => 'job',
'user' => 'sa',
'password' => 'Lasernet#2020',
'host' => '192.168.1.34',
'driver' => 'pdo_sqlsrv',
);
$conn = $Driver->connect($connectionParams);
dd($conn);
}
And if you have no really dynamic values in your connection params like $connectionParams['dbname'] = 'sqldb'.$i, better to use the doctrine dbal config and get the connection with $this->getDoctrine()->getConnection('name'); in your controller.
Symfony Docs
I'm using Cartalyst's Sentinel user package as part of a user login library w/ a gui that I'm making. Sentinel uses Illuminate for the database.
So to set up the connection I have to do something like:
$capsule = new \Illuminate\Database\Capsule\Manager;
$capsule->addConnection($dbInfo = [
'driver' => $package->get('DB.driver'),
'host' => $package->get('DB.host'),
'charset' => $package->get('DB.charset'),
'collation' => $package->get('DB.collation'),
'database' => $package->get('DB.database'),
'username' => $package->get('DB.user'),
'password' => $package->get('DB.password'),
]);
$capsule->bootEloquent()
Where $package is my own thing & is pretty self explanator. Just returns values for keys here.
Instead of using $capsule->addConnection($arrayOfLoginInfo), I'd like to pass a previously instantiated PDO object. Something like:
$pdo = new \PDO($dsn, $username, $password);
$capsule = new \Illuminate\Database\Capsule\Manager;
$capsule->addPdoConnection($pdo);
$capsule->bootEloquent()
But the capsule manager does not appear to have such a method.
I've never used Illuminate before, but I did some research a couple weeks ago & wasn't able to find a solution.
I am developing a project in core PHP and I want to use eloquent query structure in my project to make ease of setting up mySQL connections and executing mySQL queries .
Start by using composer require illuminate/database vlucas/phpdotenv
create a bootstrap file to bootstrap Eloquent's connection string:
//bootstrap.php
<?php
require 'vendor/autoload.php';
use Illuminate\Database\Capsule\Manager as Capsule;
$dotenv = new Dotenv\Dotenv(__DIR__);
$dotenv->load();
$capsule = new Capsule;
$capsule->addConnection([
'driver' => env('DB_CONNECTION'),
'host' => env('DB_HOST'),
'port' => env('DB_PORT'),
'database' => env('DB_DATABASE'),
'username' => env('DB_USERNAME'),
'password' => env('DB_PASSWORD'),
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
]);
$capsule->setAsGlobal();
$capsule->bootEloquent();
Add environment variables!! (.env file)
Create a model file, you can put this anywhere you want
//Models/User.php
<?php
namespace Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
}
Use them!
<?php
require('bootstrap.php');
use Models\User;
use Illuminate\Database\Connection as DB;
$user = User::find(1);
$user2 = User::where('name', 'somename')->first();
You can use opensource project http://www.phptomb.com
You can customise the existing class to meet your requirements.
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.
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.