我有以下数据库架构: 人1 - 1联系人1 - *地址
还有另一个实体是联系人,因此表联系是必要的。
我访问这样的人员列表:
$persons = Person::with('contact.addresses')
->filter($string)
->withoutCompany()
->orderBy('persons.surname', 'ASC')
->get();
问题是返回的雄辩模型会覆盖具有表联系人ID的人的id字段。这是由于查询范围过滤器($ string)可以在下面看到:
public function scopeFilter($query, $parameter) {
return $query
->join('contacts', 'persons.contact_id', '=', 'contacts.id')
->join('addresses', 'addresses.contact_id', '=', 'contacts.id')
->where(function($q) use($parameter) {
$q->where('addresses.city', 'like', $parameter)
->orWhere('persons.surname', 'like', '%' . $parameter . '%')
->orWhere('persons.name', 'like', '%' . $parameter . '%')
->orWhere('addresses.postcode', 'like', $parameter . '%');
});
}
public function scopeWithoutCompany($query) {
return $query->whereRaw('persons.id not in (select company_person.person_id from company_person)');
}
此问题已解决here
它声明应该使用select语句,因为如果多次选择相同的列名,则最后一个将在使用连接填充一个雄辩的模型时覆盖先例。
但是当我在查询范围中使用select语句时,例如仅选择persons.*
和addresses.*
- 我从另一个模型中得到Cardinality violation: 1241 Operand should contain 23 column(s)
错误,我在一个急切的加载约束中使用范围(人和地址共有23列)。
我通过一个丑陋的解决方法修复了这个问题,再次加入Persons表作为最后一个连接,用person id覆盖id。但这不能解决我的问题。有谁知道如何解决这个问题?
这是我的Person :: filter($ string)查询范围的解决方法:
return $query
->select(array('persons.*', 'addresses.*'))
->join('contacts', 'persons.contact_id', '=', 'contacts.id')
->join('addresses', 'addresses.contact_id', '=', 'contacts.id')
->join('persons as p', 'p.id', '=', 'persons.id')
->where(function($q) use($parameter) {
$q->where('addresses.city', 'like', $parameter)
->orWhere('persons.surname', 'like', '%' . $parameter . '%')
->orWhere('persons.name', 'like', '%' . $parameter . '%')
->orWhere('addresses.postcode', 'like', $parameter . '%');
});
供参考:
这是导致基数违规错误的代码(数据库sehcma是公司* - *人):
$companies = Company::with(array('persons' => function($q) use ($string)
{
$q->filter($string);
})
)->whereHas('persons', function($q) use ($string)
{
$q->filter($string);
})
->orderBy('name', 'ASC')
->get();
答案 0 :(得分:1)
感谢Laravel.io的用户Kindari,我现在有一个解决方案。 我没有直接在我的地址表上添加条件,但是我的地址模型中的查询范围中有where子句。
在我的查询范围的Persn模型中,我首先检索所有相关地址。我将ID放在列表中,并将我的人员限制为仅存在于地址的人员。有了这个,我还有一个查询,但根本没有联接。请参阅下面的解决方案
public function scopeFilter($query, $parameter) {
$contact_ids = Address::filter($parameter)->lists('contact_id');
$query->with('contact')
->where(function($q) use ($parameter, $contact_ids) {
$q->where('persons.surname', 'like', '%' . $parameter . '%')
->orWhere('persons.name', 'like', '%' . $parameter . '%');
if($contact_ids) {
$q->orWhereIn('contact_id', $contact_ids);
}
});
return $query;
}
这部分
$q->where('addresses.city', 'like', $parameter)
->orWhere('addresses.postcode', 'like', $parameter . '%');
现在是Address模型的查询范围的一部分。
很好地封装。我不知道为什么我没想到那个。我在某种程度上专注于将它全部放在一个查询中。这解决了我的问题。