Laravel API连接到多个数据库 [英] Laravel API connecting to multiple databases

查看:144
本文介绍了Laravel API连接到多个数据库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Laravel(流明)构建REST API.想法是,此API为多个食品订购网站提供了后端.它们共享相同的后端逻辑(模型,控制器等).这样,每个网站只需要它自己的前端应用程序,我打算为此使用Angular.每个网站都会拥有自己的数据(产品,页面等),这些数据必须存储在不同的数据库中.

I'm building a REST API with Laravel (Lumen). The idea is that this API provides the back-end for multiple food-ordering websites. They share the same back-end logic (models, controllers etc.). This way each website only needs it's own front-end application, I'm planning to use Angular for this. Each website will have it's own data (products, pages etc.), which has to be stored in different databases.

为了测试目的,我已经在config/databases.php中定义了多个连接.现在,我可以在查询相应的数据库之前动态设置连接,如下所示:

I've defined multiple connections within config/databases.php for testing purposes. Now I can dynamically set the connection before querying the corresponding database, like this:

class ProductController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return Response
     */
    public function index()
    {   
        $products = new Product;
        $products->setConnection('customer_two'); // <--
        $products = $products->get();

        return response()->json($products);
    }
}

例如,可以通过缓存来完成.

The same can be done with caching, for instance.

让API知道哪个客户的网站发出了请求的最佳方法是什么?我需要指向正确的数据库.另外,这种方法会在性能方面引起任何问题吗?

What's the best way to let the API know which customer's website made the request? I need to point to the right database. Also, could this approach cause any problems performance-wise?

推荐答案

我将使用2分方法来解决此问题,而我会使用第2种方法.

I'd be using a 2 pronged approach to solve this problem and I would use the first without the 2nd.

第一个将基于您使用请求api的路由.例如,您可以使用/api/{site}之类的前缀定义路由.这样,您的所有api端点都将基于请求的站点变量.例如. /api/site1/login将使用数据库site1,而/api/site2/login将使用数据库site2.

The first would be based on the route that you use the request the api. For instance you could define your routes with the prefix like /api/{site}. This way all your api endpoints would be based on the site variable requested. E.g. /api/site1/login would use the database site1 and /api/site2/login would use the database site2.

第二部分是使用JWT像上面提到的那样进行身份验证,并在每个请求上使用中间件检查经过身份验证的用户是否实际上是该特定站点的用户的一部分.这仅对经过身份验证的路由真正有用,但是仍然会使未经身份验证的路由易于滥用,但是,如果您的站点上有合法用户,并且您的站点正在从api请求数据,则应该返回正确的site数据反正任何恶意访问都将获取公共数据.

The second part to this is using JWT to authenticate like you mentioned above and on each request use a Middleware to check if the authenticated user is actually part of the users for that particular site. This is only really good for the authenticated routes however and still leaves your unauthenticated routes open to abuse, however if a legitimate user is on your site and your site is requesting the data from the api you should have the correct site data being returned and any malicious access will just be getting public data anyway.

可能还有第三种选择.使用JWT,您可以创建自定义声明.这些自定义声明可用于存储正在使用的站点以及要访问的数据库.我自己还没有这样做,但是一直在考虑做一些类似的事情来根据我的api对客户端进行身份验证,以及基于此的基于用户的身份验证.这意味着每个端点都至少要经过客户端身份验证,而其他端点也要同时由用户身份验证和客户端身份验证.

There is potentially a third option too. with JWT you can create custom claims. These custom claims could be used to store the site being used and which database to access. I have not done this myself but have been thinking about doing something similar to authenticate the client against my apis as well as user based authentication on top of that. This would mean every endpoint would at least be client authenticated and others would be also user authenticated as well as client authenticated.

使用中间件在运行时轻松更改数据库连接.

Using middleware to easily change the database connection at runtime.

中间件:app/Http/Middleware/DatabaseConnectionChooser.php

Middleware: app/Http/Middleware/DatabaseConnectionChooser.php

<?php namespace App\Http\Middleware;

use Closure;
use Illuminate\Routing\Route;

class DatabaseConnectionChooser
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        /** @var Route $route */
        $route = app('router')->getRoutes()->match($request);

        $connection = $route->getParameter('connection');

        app('db')->setDefaultConnection($connection);

        return $next($request);
    }
}

将此中间件添加到app/Http/Kernel.php类的$ middleware属性中.

Add this middleware to the app/Http/Kernel.php class to the $middleware property.

protected $middleware = [
    ...        
    \App\Http\Middleware\DatabaseConnectionChooser::class,
];

创建路由以指定站点,也就是数据库连接.

Create your routes to specify the site, aka the database connection.

app/Http/routes.php

app/Http/routes.php

app('router')->get('/{connection}/', function () {
    return app('db')->getDefaultConnection();
});

在配置中设置数据库连接.

Setup your database connection in your config.

config/database.php

config/database.php

'connections' => [
    ...

    'site1' => [
        'driver'    => 'mysql',
        'host'      => env('DB_HOST', 'localhost'),
        'database'  => env('DB_DATABASE', 'forge1'),
        'username'  => env('DB_USERNAME', 'forge1'),
        'password'  => env('DB_PASSWORD', ''),
        'charset'   => 'utf8',
        'collation' => 'utf8_unicode_ci',
        'prefix'    => '',
        'strict'    => false,
    ],

    'site2' => [
        'driver'    => 'mysql',
        'host'      => env('DB_HOST', 'localhost'),
        'database'  => env('DB_DATABASE', 'forge2'),
        'username'  => env('DB_USERNAME', 'forge2'),
        'password'  => env('DB_PASSWORD', ''),
        'charset'   => 'utf8',
        'collation' => 'utf8_unicode_ci',
        'prefix'    => '',
        'strict'    => false,
    ],

    ...
]

这篇关于Laravel API连接到多个数据库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆