来自加入的Eloquent Model ID错配

时间:2014-02-18 12:16:24

标签: laravel-4 eloquent

我有以下数据库架构: 人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();

1 个答案:

答案 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模型的查询范围的一部分。

很好地封装。我不知道为什么我没想到那个。我在某种程度上专注于将它全部放在一个查询中。这解决了我的问题。