Laravel - Join tables across 2 databases (same server) - php

I'm trying to join 2 tables in 2 databases. But using the common solutions don't seem to be working and I can't figure out why. Here is what I have:
My connections:
'pgsql' => [
'driver' => 'pgsql',
'host' => env('DB_HOST', 'localhost'),
'database' => env('DB_DATABASE', 'data'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8',
'prefix' => '',
'schema' => env('DB_SCHEMA', 'public'),
],
'auth' => [
'driver' => 'pgsql',
'host' => env('DB_HOST', 'localhost'),
'database' => env('DB_DATABASE_AUTH', 'authentication'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8',
'prefix' => '',
'schema' => env('DB_SCHEMA', 'public'),
]
The Laravel query I'm trying to run:
Files::where('sender_id',$userId)
->join('authentication.users as users','Policies.sender_id','=','users.id')
->select('*')
->get();
The table Files belong to database data.
But this gives me an error SQLSTATE[42P01]: Undefined table: 7 ERROR: relation "authentication.users" does not exist
I know the connection to the authentication table works since I can do this
DB::connection('auth')->table('users')->whereIn('id', '123')->first();
I've tried replacing authentication with auth but to no avail.
What am I doing wrong? Thanks.

Using query builder :
$query = DB::table('database1.table1 as dt1')->leftjoin('database2.table2 as dt2', 'dt2.ID', '=', 'dt1.ID');
$output = $query->select(['dt1.*','dt2.*'])->get();
using Eloquent model option:
Model1::where('postID',$postID)
->join('database2.table2 as db2','Model1.id','=','db2.id')
->select(['Model1.*','db2.firstName','db2.lastName'])
->orderBy('score','desc')
->get();
This might be a duplicate ask. Pls refer Join two MySQL tables in different databases on the same server with Laravel Eloquent

Related

Run specific select raw queries on write database in order to have fresh data due to replication lag

I use my Laravel 5.7 application a master-slave database replication scheme using postgresql:
'mydb' => [
'driver' => 'pgsql',
'read' => [
'host' => env('DB_HOST_READ', '192.168.2.3'),
],
'write' => [
'host' => env('DB_HOST_WRITE', '192.168.2.5'),
],
'port' => env('DB_PORT', '5432'),
'database' => env('DB_DATABASE', 'mydb'),
'username' => env('DB_USERNAME', ''),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8',
'prefix' => '',
'schema' => 'public',
'sslmode' => 'prefer',
],
And I was provided some raw queries to run (the query was provided as is into my Jira ticket). These queries are reporting queries that need fresh data hence I do not want to tinker them a lot.
The Laravel itself provides ways to do so but either requires to create a model for example:
MyModel::limit(10)->useWritePdo()->get();
Or the query builder:
DB::connection("mydb")->table('user')->select("*")->limit(10)->useWritePdo()->get();
But I want to do the following:
DB::connection("mydb")->useWritePdo()->select("SELECT * from et_user");
Is there a way to do so?

how can i use laravel multi-database?

I want to know about the laravel multiple databases. is it possible to use a default database which use only user login and after login separate group by group and every group use independent database. such as 'db' is the default database it's only for the all user login.
Example: Now 'John' is login using default database 'db'. John is the member of group1 after login john use 'db1' where stored John's all type of data. Other side Now 'Alex' login using default database 'db'. Alex is the member of group2 after login Alex use 'db2' where stored Alex's all type of data. After login default db connection no need so i want to replace 'bd' to 'db1' or 'db' to 'db2'. Please provide code for laravel
Define a separate database connection in config/database.php.
'mysql' => [ // default
'driver' => 'mysql',
'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', ''),
...
],
'db1' => [ // another
'driver' => 'mysql',
'host' => env('DB_HOST_ONE', '127.0.0.1'),
'port' => env('DB_PORT_ONE', '3306'),
'database' => env('DB_DATABASE_ONE', 'forge'),
'username' => env('DB_USERNAME_ONE', 'forge'),
'password' => env('DB_PASSWORD_ONE', ''),
...
]
Note that you have to define respective config in your .env.
Then when you want to use db1 connection it, use Config::set('database.default', 'db1'). However, it only works when you have known amount of database connections(that you can define in config/database.php), if you have unknown amount of databases, then you should change the config directly instead of the name of the connection only.
Example:
Config::set('database.connections.mysql.database', 'db1')
Config::set('database.connections.mysql.username', 'admin');
Config::set('database.connections.mysql.password', 'secret');
You can see my another answer to know how does it work underhood.
In this case, I presume you are building a system that is connecting to various existing databases possibly from different applications.
You can define as many DB connections as you want in your config/database.php
'mysql' => [
'driver' => 'mysql',
'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' => '',
'strict' => true,
'engine' => null,
],
'mysql2' => [
'driver' => 'mysql',
'host' => env('DB_HOST_2', '127.0.0.1'),
'port' => env('DB_PORT_2', '3306'),
'database' => env('DB_DATABASE_2', 'forge'),
'username' => env('DB_USERNAME_2', 'forge'),
'password' => env('DB_PASSWORD_2', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'strict' => true,
'engine' => null,
],
...
You would however also need a way to specify for each user which other external DB from which their details are going to be fetched from, for instance a column db_name on the users table.
At the point of fetching the data of say 'Alex' User model, you can do something like
$user = User::find(1); //if Alex has user_id 1 and where $user->db_name is 'mysql2' as is in the config/database.php file
$userDetails = DB::connection($user->db_name)->where('username',$user->name)->where('other_details','some details')->get();
Make sure to specify this in your .env too, to match what's defined in config/database.php
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret
DB_HOST_2=127.0.0.1
DB_PORT_2=3306
DB_DATABASE_2=db2_name_here
DB_USERNAME_2=db2_username_here
DB_PASSWORD_2=db2_password_here
...

Laravel groupBy not working , version 5.4.24

Here is my query, it works on all older versions.
$data = DB::table('applicant')
->groupBy('AppAffID')
->get();
Error i get is :
SQLSTATE[42000]: Syntax error or access violation: 1055 'comloant_loantreeAPI.applicant.AppID' isn't in GROUP BY (SQL: select * from `applicant` group by `AppAffID`)
I have tried the database change :
I added 'strict' => false, to database config.
'mysql' => [
'driver' => 'mysql',
'host' => env('DB_HOST', 'localhost'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'strict' => false,
'engine' => null,
],
What is it that you want to achieve with the groupBy? If you want to sort on the AppAffID you should use the orderBy instead done like so:
$data = DB::table('applicant')
->orderBy('AppAffID', 'desc') //can also use 'asc' for ascending
->get();

Remote MySQL database connection Laravel 5 not working

I'm using laravel 5. i need to get some data from a remote MySQL database.
i've already set up my database connection in config/database.php.
This is how it looks:
'connections' => [
'mysql' => [
'driver' => 'mysql',
'host' => env('DB_HOST', 'localhost'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'strict' => false,
],
'remotemysql' => [
'driver' => 'mysql',
'host' => env('DB_HOST', '************'),
'database' => env('DB_DATABASE', 'osys'),
'username' => env('DB_USERNAME', 'Syn'),
'password' => env('DB_PASSWORD', '****************'),
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'strict' => false,
],
],
The connection info is correct, i already tested it and i'm able to connect to the remote database.
To test it out i just fetched the database connection and the data in my controller to send it to a view to check whether or not everything is working alright. This is my controller:
...
use DB;
...
public function item()
{
$items = DB::connection('remotemysql')
->table('ip_products')
->get();
return view('admin.item', compact('items'));
}
and this is my view:
...
<tbody>
#foreach ($items as $item)
<tr>
<td>{{$item->id}}</td>
</tr>
#endforeach
</tbody>
...
When i try to load my view i get this error message:
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'dvs.ip_products' >doesn't exist (SQL: select * from ip_products)
The error shows me that Laravel tries to get the table form the dvs database (wich is the main site database). So it isn't using the connection 'remotemysql'. If it couldn't connect to the remote database it would have got a connection error but i think its not using the remote connection at all.
What can i do to fix this issue ?
As You can see from error:
Table 'dvs.ip_products' >doesn't exist
where dvs is database name.
so according to Your config files:
'remotemysql' => [
'driver' => 'mysql',
'host' => env('DB_HOST', '************'),
'database' => env('DB_DATABASE', 'osys'),
'username' => env('DB_USERNAME', 'Syn'),
'password' => env('DB_PASSWORD', '****************'),
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'strict' => false,
],
env() method has 2 args: $key, $default
so it looks first to .env file to find $key in You case DB_HOST, DB_DATABASE... and if it's not defined will use $default that You define as second argument.
You can read about it here

Using multiple databases for different endpoints

I have API written in lumen(laravel). I am using Eloquent for my models.
What I need to do is to use different databases based on url (endpoint).
For example I have http://apiprovider.com/api/v1/ as base API url and it connects to the api_v1 database, but I need to use another database if v2 is used http://apiprovider.com/api/v2 for instance api_v2 database.
All classes and laravel application should be the same, only different database according to version.
Database settings is stored in .env file.
Please suggest the right way to implement this ? Or at least possible ways.
Thanks.
It's just an idea, i haven't tried it but a simple way would be switching between the two databases from a middleware.
For example you could define the two connections available in database.php :
'connections' => [
'mysql1' => [
'driver' => 'mysql',
'host' => env('DB_HOST', 'localhost'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'strict' => false,
],
'mysql2' => [
'driver' => 'mysql',
'host' => env('DB_HOST_2', 'localhost'),
'database' => env('DB_DATABASE_2', 'forge'),
'username' => env('DB_USERNAME_2', 'forge'),
'password' => env('DB_PASSWORD_2', ''),
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'prefix' => '',
'strict' => false,
]
Then create a middleware and switch the DB in the handle method
public function handle($request, Closure $next)
{
//check the request URL and decide what DB to use
//set the DB for this request
Config::set('database.default', $dbname );
}
I think that Config::set('database.default', $dbname); will work only for the current request, but it would do what you need

Categories