php Laravel whereHas跨两个独立的数据库

smdncfj3  于 2023-03-07  发布在  PHP
关注(0)|答案(8)|浏览(269)

问题:我只想获取已下了当年订单的客户。客户和订单位于两个独立的数据库中(这不能改变).关系都设置和工作正常,但当我尝试以下我一直得到一个SQL错误,因为它是试图搜索'订单'上的'客户'数据库.在这种情况下,是否有办法强制Laravel使用正确的数据库?

$customers = $customers->whereHas('orders', function($query){
    $query->where('academic_year_id', '=', $this->current_academic_year->id);
});

$customers = $customers->orderBy('DFKEY','ASC')->get();

订单型号:

public function customer()
{
    return $this->belongsTo('Customer','dfkey');
}

客户型号:

protected $connection = 'mysql2';

public function orders()
{
    return $this->hasMany('Order','dfkey','DFKEY');
}

先谢了!

uoifb46i

uoifb46i1#

迟到了,但对于其他任何人谁有类似的问题,下面应该工作(只要两个数据库都在一个服务器上)。
显式设置连接和表。

protected $connection = 'mysql2';
protected $table_name = 'mysql2.orders';

或者,如果您愿意,动态设置表如下:

protected $table = 'orders';
public function __construct() {
    $this->table = DB::connection($this->connection)->getDatabaseName() . '.' . $this->table_name;
}

甚至

public function __construct() {
    $this->table = DB::connection($this->connection)->getDatabaseName() . '.' . $this->getTable();
}
des4xlb0

des4xlb02#

已通过使用筛选器解决此问题:

public function index()
{   
    $customers = new Customer;
    // Make sure customers are current parents of students
    $customers = $customers->whereHas('students', function($q) {
        $q->where('STATUS', '=', 'FULL');
    });

    //Filter results
    if(Input::get('academic_year') == 'ordered'){
        $customers = $customers->orderBy('DFKEY','ASC')->get();
        $filtered = $customers->filter(function($customer)
        {
            if ($customer->orders()->where('academic_year_id','=',$this->current_academic_year->id)->first()) {
                return true;
            }
        });
        $customers = $filtered;
        return View::make('admin.customers.index',compact('customers'));
    }

    $customers = $customers->orderBy('DFKEY','ASC')->get();

    return View::make('admin.customers.index',compact('customers'));
}
xzabzqsa

xzabzqsa3#

这是一个非常好的问题!直接在该模型上进行简单查询不会有问题,因为Laravel使用来自该模型的默认连接,但如果您在另一个数据库中有一个相关模型,并且您执行一些高级查询,例如:whereHas('relationName'),Laravel将使用父连接,这将导致关于不存在列的SQL错误(因为它在错误的数据库中查找)。
这是此问题的最佳解决方案:
在你的相关模型中,创建一个如下的构造函数:

public function __construct(array $attributes = [])
{
    $this->table = 'db_name.'.$this->table;
    parent::__construct();
}
vlurs2pr

vlurs2pr4#

unfurtanelly没有直接的方法,但你可以做2个步骤,这是一种相同的方式,拉拉维尔做它正常。
它的简单,干净,有效,你也不搞核心Laravel功能,可能会改变更新

$orders = Order::where('academic_year_id', $this->current_academic_year->id)
                     ->select('id')
                     ->pluck('id');

    $customers = $customers->whereIn('order_id', $orders)
                           ->orderBy('DFKEY','ASC')
                           ->get();

希望这对你有用。
你可以跳过等号

nhaq1z21

nhaq1z215#

包hoyvoy/laravel-cross-database-subqueries允许你在同一个服务器上为数据库做这些。你还需要指定所有的数据库连接和与它们相关的模型,如Agus Tromboto所指定的。最后,引用另一个数据库的模型必须从Hoyvoy\CrossDatabase\Eloquent\Model扩展,而不是Illuminate\Database\Eloquent\Model。

piwo6bdm

piwo6bdm6#

更安全的做法是只修改原始的getTable函数而不覆盖构造函数:

public function getTable()
{
    return join('.', [
        $this->getConnection()->getDatabaseName(),
        Str::snake(Str::pluralStudly(class_basename($this))) // original function
    ]);
}

这样,动态数据库切换功能就可以正常工作,就像Model::on($connection)一样。

waxmsbnn

waxmsbnn7#

试着像这样写查询,并把你的数据库和tablename,因为它是-〉

$customers = Schema::connection('your_database_name')::table('respective_table_name')
->where('academic_year_id', '=', $this->current_academic_year->id)
->orderBy('DFKEY','ASC')
->get();
z9gpfhce

z9gpfhce8#

我已经通过添加“连接”和“表”变量模型来解决这个问题,这些变量模型指定了保存模型的数据库。
例如,我在表users中名为“core_database”的数据库中有一个名为“User”的模型。在另一侧,我在表user_events中名为“logs_database”的数据库中有一个名为“UserEvents”的模型
因此,我将有一个config/database.php文件的两个连接:

'core_db_connection' => [
        'driver' => 'mysql',
        'host' => host_ip,
        'port' => port,
        'database' => 'core_database',
        'username' => username,
        'password' => password,
        ....
    ],

'logs_db_connection' => [
        'driver' => 'mysql',
        'host' => host_ip,
        'port' => port,
        'database' => 'logs_database',
        'username' => username,
        'password' => password,
        ....
    ],

模特们会说:

class User extends Authenticatable {
  protected $table = 'core_database.users';
  protected $connection = 'core_db_connection';
  ...
}

class UserEvents extends Model {
  protected $table = 'logs_database.user_events';
  protected $connection = 'logs_db_connection';
  ...
}

这是在同一数据库服务器的数据库中测试的。数据库连接具有相同的主机IP。我没有尝试过其他方法
使用此配置,我可以跨同一数据库服务器(在我的例子中为RDS)中的两个或多个独立数据库进行任何查询。
希望这对你有帮助!

相关问题