laravel whereHas 多数据库跨库查询问题 各位大佬快看看

使用版本 laravel8+

A 数据库

namespace App\Models\User;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class User extends Model{
    use HasFactory;

    protected $connection = 'a';
    protected $table = 'users';
}

B 数据库

namespace App\Models\Order;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Order extends Model{
    use HasFactory;

    protected $connection = 'b';
    protected $table = 'order';

    public function user()
    {
      return $this->belongsTo(User::class);

    }
}

查询

use Illuminate\Database\Eloquent\Builder;

$query = Order::query()->where('goods_id',2);
$query->whereHas('user',functon(Builder $builder) use ($data){
    $builder->where('mobile','LIKE','%'.$data['mobile].'%');
})
$query->paginate();

以上应用场景 及代码

A 库 有 表前缀 B库 也有表前缀

A库前缀 a_
B库前缀 b_

问题 进行 whereHas 的时候 会走 A 库的连接 不会走B 库的 及表前缀

敢问各位大佬 有何方法解决

查询会失败

(SQL: select count(*) as aggregate from `b_order` where b_order.goods_id = 2 and exists (select * from `b_users` where `b_order`.`user_id` = `b_users`.`id` and `mobile` LIKE %153%)

laravel 会自动使用B的前缀
预期 sql

SELECT * FROM b.b_order  WHERE b.b_order.goods_id = 2 EXISTS(SELECT * FROM a.a_users WHERE b.b_order.user_id = a.a_user_id AND a.a_user.`mobile` LIKE %153%)
自由与温暖是遥不可及的梦想
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 20

我的表前缀都直接写在 $table 里,所以没这问题,不过我想说的主要是 whereHas 效率很低,推荐用 whereHasIn

给 Eloquent 的 whereHas 加个 where in 的优化

扩展包

3年前 评论
自由与温暖是遥不可及的梦想 (楼主) 3年前

whereHasfrom 指定数据库连接名,像这样

$query->whereHas('user',functon(Builder $builder) use ($data){
    $builder->from(DB::raw("b.b_users"))->where('mobile','LIKE','%'.$data['mobile].'%');
});
3年前 评论
自由与温暖是遥不可及的梦想 (楼主) 3年前

子查询是在同数据库内,垮库用不了子查询,你跨库难不成还能连表么?

3年前 评论
自由与温暖是遥不可及的梦想 (楼主) 3年前

有过这个跨库连表查询的场景,当时用的 LEFT JOIN 查的

Order::query()->leftJoin("a.users", "b.order.user_id", "=", "a.users.id")
    ->where("b.order.goods_id", 2)
    ->where("a.users.mobile",'LIKE','%'.$mobile.'%')
    ->paginate();
3年前 评论

没试过这种连表,但是我联想到两种方案:

一、在模型里重写 $table ,代码如下:

class ActivityRegistration extends Model
{
    protected $table = 'abc_activity_registrations';

    protected $guarded = [];
}

二、在模型中使用构造函数,使用父类 ModelsetTable 方法设置表名,代码如下:

class ActivityRegistration extends Model
{
    protected $guarded = [];

    /**
     * Create a new Eloquent model instance.
     *
     * @param array $attributes
     */
    public function __construct(array $attributes = [])
    {
        $this->setTable('abc_activity_registrations');

        parent::__construct($attributes);
    }
3年前 评论
自由与温暖是遥不可及的梦想 (楼主) 3年前
犯二青年 (作者) 3年前
circle 3年前

我也遇见了这个问题哈哈。

3年前 评论

我也遇见这个问题了,请问解决了吗?

3年前 评论
自由与温暖是遥不可及的梦想 (楼主) 3年前
巴啦啦小仙女 (作者) 3年前

怎么解决的呀,我也遇到了这个问题

2年前 评论
自由与温暖是遥不可及的梦想 (楼主) 2年前

A.php

<?php

namespcae App\A;

class A extends model
{
    public function b()
    {
        return $this->morphToMany(B::class);
    }
}

B.php

<?php

namespcae App\B;

class B extends model
{
    protected $connect = 'db2';
}

使用

A::whereHas('b', function ($query) { 
    $query->from('db2.b')->where(....); 
});
2年前 评论

遇到相同的问题,不同的是我的结构是

 ->when(!empty($data['order_no'] ?? ''), function ($q) use ($data) {
  $q->whereHas('productWarehousing.produceSchedule.order', function ($query) use ($data) {
        $query->where('order_no', 'like', '%' . $data['order_no'] . '%');
      });
   })

其中order是属于database2。楼上的答案都不行,最后看了这个解决了stackoverflow.com/questions/273946...

解决办法增加order类的构造方法

    protected $table = 'orders';

    public function __construct(array $attributes = [])
    {
        $this->table = env('xxx_DB_DATABASE') .'.'. $this->table;
        parent::__construct($attributes);
    }
1周前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!