【问题标题】:Laravel Eloquent: How to pass connection name to relationship modelLaravel Eloquent:如何将连接名称传递给关系模型
【发布时间】:2018-08-20 06:04:28
【问题描述】:

我有两个模型,一个是扩展 Jenssegers\Model 的 mongo 模型,另一个是扩展 Illuminate\Model 的 sql 模型。此 sql 模型没有定义连接名称,因为我们有多个数据库连接,每个数据库中都有相同的表。

Mongo 模型 Comment.php

<?php
namespace App\Models\Mongo;

use Jenssegers\Mongodb\Eloquent\Model as Eloquent;

class Comment extends Eloquent
{
    /** @var string Mongo Connection Name */
    protected $connection = 'mongodb';

    /** @var string Mongo Collection Name */
    protected $collection = 'comments';

    /** @var bool Enable/Disable Timestamp */
    public $timestamps = true;

    /** @var date Date format */
    protected $dateFormat = 'Y-m-d H:i:s';

    public function userProfile()
    {
        return $this->belongsTo('\\App\\Models\\Sql\\UserDefaultProfile', 'created_by', 'user_code');
    }
}

Sql 模型 UserProfile.php

<?php
namespace App\Models\Sql;

use Illuminate\Database\Eloquent\Model;
use Jenssegers\Mongodb\Eloquent\HybridRelations;

class UserDefaultProfile extends Model
{
    use HybridRelations;

    /** @var string Table Name */
    protected $table = 'user_default_profile';

    /** @var bool Enable/Disable Timestamp */
    public $timestamps = false;
}

我有多个数据库连接添加到 Capsule

try {
    $getDatabaseList = StoreDatabaseCredential::all();
} catch (Exception $exception) {

}

foreach ($getDatabaseList as $database) {
    if (strtolower($database->database_type) == 'mysql') {
        $db->addConnection([
            'driver'    => 'mysql',
            'host'      => $database->database_router_read_host,
            'port' => $database->database_router_read_port,
            'database'  => $database->database_name,
            'username'  => $database->database_user,
            'password'  => $database->database_password,
            'charset'   => 'utf8',
            'collation' => 'utf8_general_ci',
            'prefix'    => '',
        ], $database->connection_name);
    }
}

所以有多个数据库连接可用

现在的问题是,当我用关系调用 eloquent 时,我得到了Database [Default] not configured。我收到此错误是因为 UserProfile 模型没有定义任何连接。所以,请谁能告诉如何将连接名称传递给关系模型。

try {    
    $comments = Comment::where([
        'in_reply_to_content_id' => $contentId,
        'super_store_id' => $superStoreId,
        'is_deleted' => 0
    ])->with([
        'userProfile' => function ($query)  use ($dbConnectionName) {   
            $query->select('id', 'user_code', 'mobile', 'name', 'profile_pic_url');
        }
    ])->skip($offset)->take($itemsPerPage)->orderBy('created_at', 'desc')->get();

    Utils::printData($contentComments);
    exit();
} catch (\Throwable $exception) {
    Utils::printData($exception->getMessage());
    exit();
}

那么,有没有可能用关系做这样的事情

with([
    'userProfile' => function ($query)  use ($dbConnectionName) {   
        $query->setConnection($dbConnectionName)->select(
            'id', 'user_code', 'mobile', 'name', 'profile_pic_url'
        );
    }
])->skip($offset)->take($itemsPerPage)->orderBy('created_at', 'desc')->get();

【问题讨论】:

标签: eloquent laravel-5.3 jenssegers-mongodb


【解决方案1】:

您可以为您的UserProfile 模型扩展Model 基类,覆盖getConnectionName 方法并从您使用static 方法设置的static 类变量中获取连接名称

例如:

use Illuminate\Database\Eloquent\Model;

class RelationWithChangingConnection extends Model
{
    static $connectionName;

    static public function setConnectionNameForRelation($connectionName)
    {
        static::$connectionName = $connectionName;
    }

    public function getConnectionName()
    {
        $this->connection = static::$connectionName;
        return parent::getConnectionName();
    }
}

class UserDefaultProfile extends RelationWithChangingConnection
{
    //...
}

然后

with([
    'userProfile' => function ($query)  use ($dbConnectionName) {              
        UserDefaultProfile::setConnectionNameForRelation($dbConnectionName);

        $query->setConnection($dbConnectionName)->select(
            'id', 'user_code', 'mobile', 'name', 'profile_pic_url'
        );
    }
])...

但是,这看起来很难看。 你也可以按照here的建议通过切换配置文件来切换数据库连接

UPD:Here 我遇到了另一种可能的解决方案,但尚未检查 - 您可以像这样编写关系子查询:

...
->with([
    'userProfile' => function ($query)  use ($dbConnectionName) {  
        $query->from('[yourdatabase].[dbtable]')->select('id','user_code', 'mobile', 'name', 'profile_pic_url');
}
...

它将连接到您设置的数据库和数据库表。

【讨论】:

  • 但是在使用with 关系时如何在运行时传递连接名称。
【解决方案2】:

是的,如果您的模型扩展到 Illuminate\Database\Eloquent\Model,则可以设置连接名称;

$profile = UserDefaultProfile::setConnection('your_connection_name_goes_here')->where('','')->select('');

【讨论】:

  • 我想你没有注意到 with 关系我需要传递连接名称。
  • 在一个查询中不能使用多个连接。
  • 在上面提到的,我使用的是带有 MySql 混合关系的 Mongo 数据库,所以很有可能有多个数据库连接
猜你喜欢
  • 2020-06-18
  • 2019-05-22
  • 1970-01-01
  • 1970-01-01
  • 2016-02-26
  • 2021-01-05
  • 1970-01-01
  • 1970-01-01
  • 2022-07-07
相关资源
最近更新 更多