首页 > 解决方案 > 雄辩的碰撞列名称

问题描述

我有以下表格:

用户:id, name, ...

公司:id, name, ...

我有一个scopeLIKE运算符,我用它来搜索两者users.namecompanies.name如下所示:

public function scopeSearch(Builder $query, string $term = null)
{
    $query->join('companies', 'companies.id', '=', 'users.company_id');

    $term = $term.'%';

    $query->where('users.name', 'like', $term)
        ->orWhere('companies.name', 'like', $term);
}

行动:

$users = User::query()
    ->search($request->input('q'))
    ->with('company')
    ->paginate();
// ...

由于name在两个表中都使用了,Laravel 无法区分它们,所以它最终users.name用 a填充companies.name

视图如下所示:

 @foreach($users as $user)
    // ...
        <th scope="row">{{ $user->id }}</th>
        <td>{{ $user->name }}</td> // wrong: this gives the company.name
        <td>{{ $user->company->name }}</td>
        <td>{{ $user->email }}</td>
    // ...
@endforeach

解决此问题的一种解决方案是使用select和一些别名,但这将是一个讨厌的解决方案。

有什么好的解决办法吗?

更新 1:我不想使用whereHas,因为在使用运算符时它比加入要慢LIKE

更新 2:另一种解决方案是别名 thecompanies.nameusers.name如下:

public function scopeSearch(Builder $query, string $term = null)
{
    $query->join('companies', 'companies.id', '=', 'users.company_id')
        ->select(['*', 'companies.name as company_name', 'users.name as user_name']);
}
<td>{{ $user->user_name }}</td>
<td>{{ $user->company_name }}</td>

这工作正常,但是如果(出于任何原因)我想摆脱搜索能力,我还需要修改视图,所以这里引入了一个依赖项。

标签: phplaraveleloquent

解决方案


我可能会重写搜索范围以通过关系和使用搜索公司名称whereHas(),而不是加入它。这样,在使用该范围时,您永远不会有模棱两可的列名。

它会生成不同的查询,但最终会得到相同的结果。

public function scopeSearch(Builder $query, string $term = null)
{
    $term = $term.'%';

    return $query->where('name', 'like', $term)
        ->orWhereHas('company', function($query) use ($term) {
            return $query->where('name', 'like', $term);
        });
}

推荐阅读