Cannot use DB::select in public folder in laravel - laravel

TestModel.php
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;;
class TestModel extends Model
{
protected $table = 'test';
public static function index() {
$configs = DB::select('select * from tests');
}
}
This is my code. I have a file in /public folder name Test.php and want to use DB. But when i call the index() function in Test.php, it returns error.
PHP Fatal error: Uncaught RuntimeException: A facade root has not been set
Test.php saved in public folder
use App\Http\Models\TestModel;
$configs = TestModel::index();
Please help. Thank you!

When you are using anything in public folder without calling index.php it will not initiate the database so to overcome this issue :
/**
* Using For Database Configuration
*/
define('DB_TYPE', 'mysql');
define('DB_USER', 'username');
define('DB_HOST', 'localhost');
define('DB_PORT', '3306');
define('DB_PASSWORD', '');
define('DB_NAME', 'db-name');
$test = new TestModel;
$test->addConnection([
'driver' => DB_TYPE,
'host' => DB_HOST,
'port' => DB_PORT,
'database' => DB_NAME,
'username' => DB_USER,
'password' => DB_PASSWORD,
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'strict' => false,
'engine' => null,
]);
$test->setAsGlobal();
$test->bootEloquent();
$configs = $test->index();
Also, you have to replace one line in TestModel.php
replace use Illuminate\Support\Facades\DB;; with use Illuminate\Database\Capsule\Manager as DB;
Now when you run this command this will be working for you.

Related

i'm connect multiple Database and i use Laravel Excel I can'n export. This is error "Database [mysql] not configured."

i'm connect multiple Database and i use Laravel Excel I can'n export. This is error "Database [mysql] not configured."
i'm use laravel 6.0 and phpmyadmin version 4.4.15.10
controller
public function exportExcel()
{
return Excel::download(new merakiExport, 'MerakiBluetooth.xlsx');
}
app/Exports
namespace App\Exports;
use App\MerakiBluetoothTemp;
use Maatwebsite\Excel\Concerns\FromCollection;
class merakiExport implements FromCollection
{
/**
* #return \Illuminate\Support\Collection
*/
public function collection()
{
return MerakiBluetoothTemp::all();
}
}
config/database
'meraki' => [
'driver' => 'mysql',
'host' => env('DB_HOST5', ''),
'port' => env('DB_PORT5', ''),
'database' => env('DB_DATABASE5', 'forge'),
'username' => env('DB_USERNAME5', 'forge'),
'password' => env('DB_PASSWORD5', ''),
'unix_socket' => env('DB_SOCKET5', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'prefix_indexes' => true,
'strict' => true,
'engine' => null,
'options' => extension_loaded('pdo_mysql') ? array_filter([
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
]) : [],
],
env
DB_HOST5=sql.laravel.com
DB_PORT5=3306
DB_DATABASE5=time_sheet
DB_USERNAME5=*****
DB_PASSWORD5=*****
I succeeded too.
app/Exports
namespace App\Exports;
use App\MerakiBluetoothTemp;
use Maatwebsite\Excel\Concerns\FromCollection;
use App\Http\Controllers\Controller;
class merakiExport extends Controller implements FromCollection
{
/**
* #return \Illuminate\Support\Collection
*/
public function collection()
{
return MerakiBluetoothTemp::all();
}
}

How to use Multiple Databases based on subdomein in Laravel

What I want, is to access a separate database, based on the subdomain.
All other settings keep the same: username, password etc. Only database name needs to change.
I add This to database.php file
'subdomain' => [
'driver' => 'mysql',
'host' => '',
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'strict' => true,
'engine' => null,
],
I also created Middleware
`$subdomain = $request->route()->account;
$customer = Customer::where( 'sub_domain', $subdomain )->first();
if( ! $customer ) {
// account not found, do something else
} else {
Config::set('database.connections.subdomain.host', 'testdomain');
}
return $next($request);`
this is in route.php
Route::group(['domain' => $domain, 'middleware' => 'subdomain'],function () {});
Use protected $connection = 'subdomain'; in Model
in .env I use default database for check customer database name
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=ispsoft
DB_USERNAME=root
DB_PASSWORD=
I got subdomain user database name. But not connected sudomain database And I did not get value from subdomain database
Try setting your model's $table, based on the subdomain. If it's merely a different mysql schema, you should be able to do something like this:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Widget extends Model
{
/**
* The table associated with the model.
*
* #var string
*/
$subdomain = Config::get('database.connections.subdomain.host', 'testdomain');
protected $table = $subdomian.'.widgets';
}

Laravel with multiple database

I have laravel project used for apis(Passport). It uses multiple databases one database stores user information and the database name for that user. I created a BaseController, all the other controllers extends from this controller. But I am not able to fetch Auth::id(); from the BaseController. How can I get the Auth::id in the constructor?
class BaseController extends Controller
{
protected $companySchema;
public function __construct() {
$user = \App\User::where('user_id', Auth::id())->first();
$company = $user->company;
$this->companySchema = $company->cmp_Schema;
}
}
After laravel 5.3.4 you can't use Auth::user() in the constructor because the middleware isn't run yet.
class BaseController extends Controller {
public function __construct() {
$this->middleware(function ($request, $next) {
$this->companySchema = Auth::user()->company->cmp_Schema;
return $next($request);
});
}
}
try this code and tell me if it works
You cannot use Auth in constructor, because middleware is not run yet. its from 5.3
check this link : https://laravel.com/docs/5.3/upgrade#5.3-session-in-constructors
First you should setup a connection in config/database.php:
'my_new_connection' => [
'driver' => 'mysql',
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => $your_db_name,
'username' => $your_db_username,
'password' => $your_db_password,
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'strict' => true,
'engine' => null,
],
Then you can change default database connection dynamically by this:
Config::set('database.default', 'my_new_connection');
You should first call
$user = Auth::user();
which is returning you the current user model associated, which is normally User. Then following should work:
$user->id

Unable to connect with database in laravel

I am trying to connect with database on runtime in which i am setting connection settings from session like following. first connection (weserach) was successful but the connection from session variable(wesearch_barcode) wasn't.
this is database.php
'wesearch' => [
'driver' => 'mysql',
'host' => 'waev.in',
'port' => env('DB_PORT', '3306'),
'database' => 'wesearch_waev_user',
'username' => '******',
'password' => '******',
'charset' => 'latin1',
'collation' => 'latin1_swedish_ci',
'prefix' => '',
'strict' => true,
'engine' => null,
],
'wesearch_barcodedb' => [
'driver' => 'mysql',
'host' => 'waev.in',
'port' => env('DB_PORT', '3306'),
'database' => $_SESSION['dbname'],
'username' => $_SESSION['username'],
'password' => $_SESSION['password'],
'charset' => 'latin1',
'collation' => 'latin1_swedish_ci',
'prefix' => '',
'strict' => true,
'engine' => null,
],
this is my controller:
namespace App\Http\Controllers;
session_start();
use Illuminate\Http\Request;
use Illuminate\Database\DatabaseManager;
use Illuminate\Support\Facades\DB;
use App\Http\Requests;
use App\central_db;
use App\barcodedb;
class check_subsController extends Controller
{
public function fetch(Request $request){
if($db=\App\central_db::select(['db_name', 'password', 'first_name', 'last_name'])->where('device_srno','=',$request->srno)->get()){
foreach ($db as $record) {
$_SESSION['dbname'] = $record->db_name;
$_SESSION['username'] = $record->last_name;
$_SESSION['password'] = $record->first_name;
}
if($users=\App\barcodedb::where('park','=','1')->get()){
return $users;
}
}
}
}
This is my central_db model:
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
class central_db extends Model
{
protected $connection ='wesearch';
protected $table = 'usr_waev';
}
And this is another one model:
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
class barcodedb extends Model
{
protected $connection ='wesearch_barcodedb';
protected $table = 'user';
}
And the error is something like this
"PDOException in Connector.php line 119:
SQLSTATE[HY000] [1045] Access denied for user ''#'139.59.29.54' (using password: NO)"

laravel BelongsTo relationship with different databases not working

I've seen in several places to "stay away" from this, but alas - this is how my DB is built:
class Album extends Eloquent {
// default connection
public function genre() {
return $this->belongsTo('genre');
}
and the Genre table:
class Genre extends Eloquent {
protected $connection = 'Resources';
}
My database.php:
'Resources' => array(
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'resources',
'username' => 'user',
'password' => 'password',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
),
'mysql' => array(
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'my_data',
'username' => 'user',
'password' => 'password',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
),
and when I try to run
Album::whereHas('genre', function ($q) {
$q->where('genre', 'German HopScotch');
});
it doesn't select properly (doesn't add the database name to the table "genres"):
Next exception 'Illuminate\Database\QueryException' with message 'SQLSTATE[42S02]: Base table or view not found: 1146 Table 'my_data.genres' doesn't exist
Its important to note that this works perfectly:
Album::first()->genre;
Update
The best I've found so far is to use the builder's "from" method to specifically name the correct connection.
I've discovered that the builder inside the query can receive "from"
Album::whereHas('genre', function ($q) {
$q->from('resources.genres')->where('genre', 'German HopScotch');
});
This is a decent solution but it requires me to dig in the database php and find a good way to get the proper table and database name from the relation 'genre'.
I will appreciate if anyone else can build on this solution and make it more general.
Solution for laravel v5.7 and above
class Album extends Eloquent {
// default connection
public function genre() {
return $this->setConnection('Resources')->belongsTo('genre');
}
...
}
This is the way it worked for me:
In my .env and config/database.php i have defined my other connection => How to use multiple databases in Laravel
I updated my model this way:
class MyOtherDBModel extends Model
{
protected $table = 'tablename';
protected $connection = 'mysql2';
public function __construct(array $attributes = [])
{
$this->table = env('DB_DATABASE_2').'.'.$this->table;
parent::__construct($attributes);
}
}
class MyModel extends Model
{
public function myOtherModel()
{
return $this->belongsTo(MyOtherDBModel::class, 'field', 'field');
}
}
Now i can call
$query = MyModel::whereHas('myOtherModel');
This is my own solution and it works in general for me but its mega-complicated.
I'm using the builder "from" method to set the table and database correctly inside the subquery. I just need to pass the correct information inside.
Assume the subquery can be as complicated as "genres.sample" or even deeper (which means albums has a relation to genres, and genres has a relation to samples)
this is how
$subQuery = 'genres.samples';
$goDeep = (with (new Album));
$tableBreakdown = preg_split('/\./', $subQuery); // = ['genres', 'samples']
// I recurse to find the innermost table $album->genres()->getRelated()->sample()->getRelated()
foreach ($tableBreakdown as $table)
$goDeep = $goDeep->$table()->getRelated();
// now I have the innermost, get table name and database name
$alternativeConnection = Config::get("database.connections." . $goDeep->getConnectionName() . ".database"); // should be equal to the correct database name
$tableName = $goDeep->getTable(); // I have to use the table name in the "from" method below
Album::whereHas($subQuery, function ($q) use ($alternativeConnection, $tableName) {
$q->from("$alternativeConnection.$tableName");
$q->where(....... yadda yadda);
});
tl:dr;
Album::whereHas('genres', function ($q) {
$q->from('resources.genres')->where(....);
});
It looks like Eager Loading will do what you want to do
Album::with(['genre' => function ($q) {
$q->connection('Resources')
->where('genre', 'German HopScotch');
}]);
you should clone before otherwise you're changing the default connection of the model. it creates side effect.
class Album extends Eloquent {
public function genre() {
$newResource = clone $this;
return $newResource->setConnection('Resources')->belongsTo('genre');
}
}
Add the connection variable with the default connection on the genre model:
protected $connection = 'mysql';
I had some problems with the relationships by not adding this.
I was facing the same issue on Laravel 5.6. On a Many-to-Many scenario, and supposing the connection from my ModelA was the default one, what I did was the following:
1.- Prefix the schema name in the relationships:
// From ModelA and default connection (a.k.a connection1)
$this->belongsToMany('ModelB', 'schema.pivot-table-name');
// From ModelB and connection2
$this->belongsToMany('ModelA', 'schema.pivot-table-name');
2.- Overwrite connection parameter within the ModelB class and also specify the schema as a prefix in the overwritten $table attribute e.g.
protected $connection = 'connection2';
protected $table = 'connection2-schema-name.table';
3.- In case of requiring a custom behavior for the pivot table, what I did was just to implement the required model and specify it via the ->using('PivotModel'); function on the models relationships (as stated in the documentation). Finally I did the same as in the point 2 above, but on the pivot model
I haven't tried it yet, but I guess the same can be done for other kind of relationships, at least for the basic ones (One-to-One, One-to-Many, etc)
Just in case someone reaches here.
When you are fetching data using a relationship from different database connections, make sure that your related table has the $connection property defined even if it's the default connection.
Account Model:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Account extends Model {
protected $connection = 'different_connection';
public function verifiedBy()
{
return $this->belongsTo(User::class, 'verified_by');
}
}
User Model:
<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable {
// this one uses the default - `database.default` connection
public function approved()
{
return $this->hasMany(Account::class, 'verified_by');
}
}
As soon as I do Account:find($id)->verifiedBy, it will throw error. Look at the database name and you'll find. But if you do, User::find($id)->approved, it will work fine, because the Account model has the connection defined. And not the vice-versa.
So, just to be safe, if you deal with multiple database connections, put the $connection property in the models.
Laravel's implementation
I had the same issue when relationship wasn't working off the model connection.
My solution was to override the belongsToMany method on the model trying to establish. See example below.
<?php
namespace App\Model;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
class ConnectionModel extends Model
{
/**
* Override method to allow inheriting connection of parent
*
* Define a many-to-many relationship.
*
* #param string $related
* #param string $table
* #param string $foreignKey
* #param string $otherKey
* #param string $relation
* #return \Illuminate\Database\Eloquent\Relations\BelongsToMany|BelongsToMany
*/
public function belongsToMany($related, $table = null, $foreignKey = null, $otherKey = null, $relation = null)
{
// If no relationship name was passed, we will pull backtraces to get the
// name of the calling function. We will use that function name as the
// title of this relation since that is a great convention to apply.
if (is_null($relation)) {
$relation = $this->getBelongsToManyCaller();
}
// First, we'll need to determine the foreign key and "other key" for the
// relationship. Once we have determined the keys we'll make the query
// instances as well as the relationship instances we need for this.
$foreignKey = $foreignKey ?: $this->getForeignKey();
$instance = new $related;
// get connection from parent
$instance->setConnection(parent::getConnectionName());
$otherKey = $otherKey ?: $instance->getForeignKey();
// If no table name was provided, we can guess it by concatenating the two
// models using underscores in alphabetical order. The two model names
// are transformed to snake case from their default CamelCase also.
if (is_null($table)) {
$table = $this->joiningTable($related);
}
// Now we're ready to create a new query builder for the related model and
// the relationship instances for the relation. The relations will set
// appropriate query constraint and entirely manages the hydrations.
$query = $instance->newQuery();
return new BelongsToMany($query, $this, $table, $foreignKey, $otherKey, $relation);
}
}
1: This is my .env with two database connection
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=foreign_key_test
DB_USERNAME=root
DB_PASSWORD=
DB_CONNECTION_SECOND=mysql
DB_HOST_SECOND=127.0.0.1
DB_PORT_SECOND=3306
DB_DATABASE_SECOND=foreign_key_test_2
DB_USERNAME_SECOND=root
DB_PASSWORD_SECOND=
2: in my config/database.php
'mysql' => [
'driver' => 'mysql',
'url' => env('DATABASE_URL'),
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'prefix_indexes' => true,
'strict' => true,
'engine' => null,
'options' => extension_loaded('pdo_mysql') ? array_filter([
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
]) : [],
],
'mysql2' => [
'driver' => env('DB_CONNECTION_SECOND'),
'host' => env('DB_HOST_SECOND', '127.0.0.1'),
'port' => env('DB_PORT_SECOND', '3306'),
'database' => env('DB_DATABASE_SECOND', 'forge'),
'username' => env('DB_USERNAME_SECOND', 'forge'),
'password' => env('DB_PASSWORD_SECOND', ''),
'unix_socket' => '',
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'prefix_indexes' => true,
'strict' => true,
'engine' => null,
],
3: State model from other database
class State extends Model
{
use HasFactory;
protected $table = 'foreign_key_test_2.states';
protected $connection = 'mysql2';
protected $primaryKey = 'id';
protected $fillable = [
'name'
];
}
4: Country model from 1st database where i made my relation with other database table
class Country extends Model
{
use HasFactory;
protected $connection = 'mysql';
protected $table = 'countries';
protected $primaryKey = 'id';
protected $fillable = [
'name',
'state_id'
];
public function state()
{
return $this->belongsTo(State::class);
}
}
5: Final step is my route
Route::get('city', function(){
return $country = Country::with('state')->get();
});
6: this is working fine for me. Let me know with your experience.
I found a really good article for this here: http://fideloper.com/laravel-multiple-database-connections
You basically have to specify your two connections in your config file like so:
<?php
return array(
'default' => 'mysql',
'connections' => array(
# Our primary database connection
'mysql' => array(
'driver' => 'mysql',
'host' => 'host1',
'database' => 'database1',
'username' => 'user1',
'password' => 'pass1'
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
),
# Our secondary database connection
'mysql2' => array(
'driver' => 'mysql',
'host' => 'host2',
'database' => 'database2',
'username' => 'user2',
'password' => 'pass2'
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
),
),
);
So your two connections are aliased to mysql and mysql2.
Then you can tell eloquent which 'alias' to use like so:
<?php
class SomeModel extends Eloquent {
protected $connection = 'mysql2';
}
Then you can setup your relationships like normal.
tl;dr: Basically instead of specifying the table name as $connection in eloquent, specify the connection alias in your configuration and it should work.
I used the following method to use the default connection.
use Illuminate\Database\Eloquent\Model as MainModel;
use Illuminate\Support\Facades\Config;
class BaseModel extends MainModel
{
function __construct(array $attributes = [])
{
// laravel bug
// in belongsTo relationship, default connection not used
$this->connection = Config::get('database.default');
parent::__construct($attributes);
}
}
To start change 'Resources' in database.php by 'resources', will be better !
I'm curious, can you try that ?
Album::whereHas('genre', function ($q) {
$q->setConnection('resources')->where('genre', 'German HopScotch');
});

Resources