我在laravel框架中使用雄辩。我想通过表B和表C从表D中获得与表A相关的模型。
有办法做到这一点吗?
这是数据库的示例数据:
INSERT INTO A (idA) VALUES(1);
INSERT INTO A (idA) VALUES(2);
INSERT INTO A (idA) VALUES(3);
INSERT INTO B (idB, A_idA) VALUES(1, 1);
INSERT INTO B (idB, A_idA) VALUES(2, 2);
INSERT INTO C (idC, A_idA) VALUES(1, 1);
INSERT INTO C (idC, A_idA) VALUES(2, 2);
INSERT INTO C (idC, A_idA) VALUES(3, 3);
INSERT INTO D (idD, B_idB, C_idC) VALUES(1, 1, 1);
INSERT INTO D (idD, B_idB, C_idC) VALUES(2, 2, 2);
INSERT INTO D (idD, B_idB, C_idC) VALUES(3, 2, 3);
以下是模型:
class A extends Model
{
protected $table = "A";
protected $primaryKey = "idA";
public $timestamps = false;
public function B()
{
return $this->hasMany("App\B", "A_idA");
}
public function C()
{
return $this->hasMany("App\C", "A_idA");
}
}
class B extends Model
{
protected $table = "B";
protected $primaryKey = "idB";
public $timestamps = false;
public function D()
{
return $this->hasMany("App\D", "B_idB");
}
public function A()
{
return $this->belongsTo("App\A", "A_idA");
}
}
class C extends Model
{
protected $table = "C";
protected $primaryKey = "idC";
public $timestamps = false;
public function D()
{
return $this->hasMany("App\D", "C_idC");
}
public function A()
{
return $this->belongsTo("App\A", "A_idA");
}
}
class D extends Model
{
protected $table = "D";
protected $primaryKey = "idD";
public $timestamps = false;
public function B()
{
return $this->belongsTo("App\B", "B_idB");
}
public function C()
{
return $this->belongsTo("App\C", "C_idC");
}
}
这是控制器
class TestController extends Controller
{
public function test()
{
$aWithRelatedDs = A::with(['B.D'])->whereHas("B.D")->whereHas("C.D")->get();
dd($aWithRelatedDs);
}
}
这是输出:
Collection {#380 ▼
#items: array:2 [▼
0 => A {#390 ▶}
1 => A {#388 ▼
#table: "A"
... snip ...
#relations: array:1 [▼
"B" => Collection {#387 ▼
#items: array:1 [▼
0 => B {#398 ▼
#table: "B"
... snip ...
#relations: array:1 [▼
"D" => Collection {#395 ▼
#items: array:2 [▼
0 => D {#407 ▼
#table: "D"
... snip ...
#attributes: array:3 [▼
"idD" => 2
"B_idB" => 2
"C_idC" => 2
]
... snip ...
}
1 => D {#408 ▼
#table: "D"
... snip ...
#attributes: array:3 [▼
"idD" => 3
"B_idB" => 2
"C_idC" => 3
]
... snip ...
}]}]
... snip ...
问题:A#2没有两个D通过B和C关联,它只有D#2通过两个中间表关联,但在上面的结果中它仍然被列出。我如何限制这一点,因此两个关联必须属于同一模型?
答案 0 :(得分:0)
对每个关系使用while应该有效,例如:
D::whereHas('B', function ($query) {
$query->whereExists(function ($query) {
$query->select(DB::raw(1))
->from('B')
->whereRaw('B.A_id = A.id');
});
})->whereHas('C', function ($query) {
$query->whereExists(function ($query) {
$query->select(DB::raw(1))
->from('C')
->whereRaw('C.A_id = A.id');
});
})->get();
完全未经测试,祝你好运。
答案 1 :(得分:0)
如果您希望通过A
和D
获得至少有A
个与B
相关联的所有C
,那么原始SQL查询看起来像这样:
SELECT *
FROM A
WHERE EXISTS (
SELECT D.id
FROM D
INNER JOIN B ON D.b_id = B.id
INNER JOIN C ON D.c_id = C.id
WHERE B.a_id = A.id
AND C.a_id = A.id
)
我还为此准备了SQL Fiddle。
我的建议是在A
上创建一个新关系,找到所有D
到B
,我们发现C
也连接回A
{1}}。听起来很奇怪,但很容易看起来像这样:
public function doubleLinkedDs(): HasManyThrough
{
return $this->hasManyThrough(D::class, B::class)
->whereHas('C', function ($q) {
$q->where('a_id', $this->id);
});
}
顺便说一下,这需要你设置适当的关系。但就我的问题而言,这应该没问题。
如果我们定义了关系,我们应该能够执行以下非常简单的查询:
A::has('doubleLinkedDs')
->with('doubleLinkedDs')
->get();