1.问题背景
在我们的工作需求中,一般一个项目一份代码,链接一个数据库就足够了。
但是如果我们有多个车辆系统A,车辆系统B,车辆系统C,虽然名称不通,在客户眼中也是两个项目,但是其实这些项目在程序员的眼中是几乎相同的,可以复用同样的代码,只是一些参数不通,数据存储的配置不通,甚至表结构 字段都是相同的。
如果我们还是创建了A,B,C.....项目那么以后的维护成本也会越来越大,同步一个功能,就更改N份代码,是不是很累?
我们是否可以在一套代码内通过某个参数来区分数据库的链接?是否可以通过这个参数,切换某些配置项?
2.通过Laravel框架尝试
大概流程就是,我们可以通过设置一个全局的中间件,去做配置。
(1)新建一个不同数据库配置方法
首先新建一个放置公共函数的文件
touch app/helpers.php
然后,修改composer.json文件
"autoload": {
...
"files": [
"app/helpers.php"
]
}
修改保存后运行以下命令进行重新加载文件即可
composer dump-autoload
然后在其中增加一下配置方法
if(!function_exists("databaseConnection")){
function databaseConnection($airportIata){
$connections = [
'd1'=>[
'driver' => 'mysql',
'host' => 'xxxxxxxx',
'port' => 'xxx',
'database' => 'xxxx',
'username' => 'xxxxx',
'password' => 'xxxx',
'prefix' => 'xxx',
],
'd2'=>[
'driver' => 'mysql',
'host' => 'xxxxxxxx',
'port' => 'xxx',
'database' => 'xxxx',
'username' => 'xxxxx',
'password' => 'xxxx',
'prefix' => 'xxx',
],
'd3'=>[
'driver' => 'mysql',
'host' => 'xxxxxxxx',
'port' => 'xxx',
'database' => 'xxxx',
'username' => 'xxxxx',
'password' => 'xxxx',
'prefix' => 'xxx',
],
];
if(isset($connections[$airportIata])){
return $connections[$airportIata];
}else{
return [];
}
}
(2)创建中间件
php artisan make:middleware ChangeDatabase
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Config;
class ChangeDatabase
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
/**
* 根据传递参数的参数 链接不同的数据库
*/
if (!$request->para) {
return response()->json(['msg'=>'缺少参数']);
}
$con = databaseConnection($request->airportIata);
if (!$con) {
return response()->json(['msg'=>'缺少参数']);
}
Config::set('database.connections.mysql', $con);
return $next($request);
}
}
并将该中间件注册到 kernel.php
protected $routeMiddleware = [
....
'db.change'=>ChangeDatabase::class
]
(3)建立路由,以及控制器
Route::get('user/{user}',"UsersController@user")->name('user');
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Auth\ResetPasswordController;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class UsersController extends Controller
{
public function __construct()
{
$this->middleware('db.change');
}
public function user(Request $request){
$user = DB::table('user')->where('uid','=',$request->user)->first();
dd($user);
}
}
https://laravel6.test/user/234?pa=d1
访问本地环境地址,通过改变pa的值,即可链接不同的数据库。