mysql 2个数据库关联查询,在Laravel 5.2中使用多个MySQL数据库连接查询关系存在

I am dealing with the following situation: I have two models, an Employee with id and name fields and a Telephone with id, employee_id and flag fields. There is also an one-to-many relationship between these two models, that is an employee may have many telephones and a telephone may belong to a single employee.

class Employee extends Model

{

public function telephones()

{

return $this->hasMany(Telephone::class);

}

}

class Telephone extends Model

{

public function employee()

{

return $this->belongsTo(Employee::class);

}

}

The Employee model references a table employees that exists in database schema named mydb1, while the Telephone model is related to a telephones table that exists in a different database schema named mydb2.

What I want is to fetch only the employees with at least one telephone of a specific flag eager loaded, using Eloquent and (if possible) not the query builder

What I tried so far without success is:

1) use the whereHas method in the Controller

$employees = Employee::whereHas('telephones', function ($query) {

$query->where('flag', 1); //Fetch only the employees with telephones of flag=1

})->with([

'telephones' => function ($query) { //Eager load only the telephones of flag=1

$query->where('flag', 1);

}

])->get();

What I try to do here is first to retrieve only the employees that have telephones with flag=1 and second to eager load only these telephones, but I get the following query exception because of the different db connections used:

Base table or view not found: Table mydb1.telephones doesn't exist (this is true, telephones exists in mydb2)

2) Eager load with constrains in the Controller

$employees = Employee::with([

'telephones' => function ($query) {

$query->where('flag', 1);

},

])->get();

This method eager loads the telephones with flag=1, but it returns all the employee instances, which is not what I really want. I would like to have a collection of only the employee models that have telephones with flag = 1, excluding the models with telephones = []

解决方案

Taking into account this post, this post and @Giedrius Kiršys answer below, I finally came up with a solution that fits my needs, using the following steps:

create a method that returns a Relation object in the Model

eager load this new relationship in the Controller

filtered out the telephones of flag != 1 using a query scope in the Model

In Employee model

/**

* This is the new relationship

*

*/

public function flaggedTelephones()

{

return $this->telephones()

->where('flag', 1); //this will return a relation object

}

/**

* This is the query scope that filters the flagged telephones

*

* This is the raw query performed:

* select * from mydb1.employees where exists (

* select * from mydb2.telephones

* where telephones.employee_id = employee.id

* and flag = 1);

*

*/

public function scopeHasFlaggedTelephones($query, $id)

{

return $query->whereExists(function ($query) use ($id) {

$query->select(DB::raw('*'))

->from('mydb2.telephones')

->where('telephones.flag', $flag)

->whereRaw('telephones.employee_id = employees.id');

});

}

In the Controller

Now I may use this elegant syntax a’la Eloquent

$employees = Employee::with('flaggedTelephones')->hasFlaggedTelephones()->get();

which reads like "Fetch all the employees with flagged telephones eager loaded, and then take only the employees that have at least one flagged telephone"

EDIT:

After dealing with the Laravel framework for a while (current version used 5.2.39), I figured, that in fact, whereHas() clauses do work in case of the relationship model exists in a different database using the from() method, as it is depicted below:

$employees = Employee::whereHas('telephones', function($query){

$query->from('mydb2.telephones')->where('flag', 1);

})->get();

@Rob Contreras credits for stating the use of the from() method, however it looks like the method requires to take both the database and the table as an argument.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值