繁体   English   中英

Laravel 联合中的关系冲突

[英]Laravel relationship conflicts in union

我有以下 model:1-用户 model

 /**
 * Define user and functional area relationship
 */
public function functionalAreas()
{
    return $this->belongsToMany('App\FunctionalArea', 'user_functional_areas', 'user_id', 'functional_area_id')->withPivot('id', 'is_primary')->withTimestamps();
}

和业务 model:

 /**
 * Define business and user functional area relationship
 */
public function functionalAreas()
{
    return $this->belongsToMany('App\FunctionalArea', 'business_functional_areas', 'business_id', 'functional_area_id')->withTimestamps();
}

现在我应该将所有企业和用户显示在一个列表中,为此我从联合中使用,以下是我的查询:

public function usersAndOrganizations()
{
    $users = $this->users();

    $organizations = $this->organizations();

    $invitees = $users->union($organizations)->paginate(10);
    
    return response()->json($invitees);
}

private function users()
{
    $users = User::byState($approved = true, 'is_approved')
        ->search()->select([
            'id',
            DB::raw("CONCAT(first_name, ' ', last_name) AS name"),
            'about',
            'address',
            'slug',
            'average_reviews',
            DB::raw("'freelancer' AS type")
        ]);

  $users = $users->with([
        "functionalAreas" => function ($q) {
            $q->select([
                'functional_areas.id',
                DB::raw("functional_areas.name_en AS name"),
            ]);
        }
    ]);
    return $users;
}
 

private function organizations()
{
    $businesses = Business::where('owner_id', '!=', auth()->user()->id)->verified()
        ->active()->search()
        ->select([
            'id',
            'name',
            'about',
            'address',
            'slug',
            'average_reviews',
            DB::raw("'business' AS type")
        ]); 
        $businesses = $businesses
            ->with([
            "functionalAreas" => function ($q) {
                $q->select([
                    'functional_areas.id',
                    DB::raw("functional_areas.name_en AS name"),
                ]);
            }
        ]);
        return $businesses;
} 

但是上面的查询没有返回业务功能区,它的output查询是从用户关系而不是业务中使用的, with section会生成两次如下查询:

select
  `functional_areas`.`id`,
  functional_areas.name_en AS name,
  `user_functional_areas`.`user_id` as `pivot_user_id`,
  `user_functional_areas`.`functional_area_id` as `pivot_functional_area_id`,
  `user_functional_areas`.`id` as `pivot_id`,
  `user_functional_areas`.`is_primary` as `pivot_is_primary`,
  `user_functional_areas`.`created_at` as `pivot_created_at`,
  `user_functional_areas`.`updated_at` as `pivot_updated_at`
from `functional_areas`
inner join `user_functional_areas`
  on `functional_areas`.`id` = `user_functional_areas`.`functional_area_id`
where `user_functional_areas`.`user_id` in (2, 6, 7)

但实际上 6 和 7 是业务 id 而不是用户只有 2 是用户 id,其中一个查询应该使用business_functional_areas而不是user_functional_areas 再发现一件事,结果中所有项目都在App\User model 中,其类似的businesses也为用户 object。

简而言之,目前您无法使用Eloquent Eager Loading with Unions来实现它。 Laravel 尚不支持此功能。 他们作为Non-Fix问题关闭的其中一种情况是Union with Eloquent fail...。

Reason : While calling UNION function only the first model( user ) is considered main model and model type of result set of other model( Business ) passed as argument will be converted to the main one( USER ) only and the main model relationship is called在所有记录上(不是所需的记录)。

由于上述问题,仅在结果集的每条记录上调用user model 的关系。 所以即使business_id = 1,user_id = 1 的functional_area 也会被获取。

您可以从下面的文件和 function 中调试更多信息。

File: 
<your_laravel_project>\vendor\laravel\framework\src\Illuminate\Database\Query\Builder.php
Function: get

替代解决方案您可以按原样获取两个结果集,然后在使用 php 获取数据后将它们合并。

public function usersAndOrganizations()
{
    $users = $this->users()->get();
    $organizations = $this->organizations()->get();
    $invitees =  $users->toBase()->merge($organizations->toBase())->toArray();
    dd($invitees);
}

目前唯一的方法是使用map

public function usersAndOrganizations()
{
    $users = $this->users();

    $organizations = $this->organizations();

    $invitees = $users->union($organizations)->paginate(10);
  
    $invitees = $this->getRelatedData($invitees);

    return response()->json($invitees);
}


private function getRelatedData($invitees)
{
    $invitees->map(function($object) use($functionalAreaName) {
        if($object->type == 'business') {
            $relationName = 'businesses';
            $relationKey = 'business_id';
            $attachableType = Business::MORPHABLE_TYPE;
        }
        if($object->type == 'freelancer') {
            $relationName = 'users';
            $relationKey = 'user_id';
            $attachableType = User::MORPHABLE_TYPE;
        }
        $functionalAreas = FunctionalArea::whereHas($relationName, function($q) use ($object, $relationKey){
            $q->where($relationKey, $object->id);
        })->get([$functionalAreaName.' As name', 'id']);

        $object->functional_areas =  $functionalAreas->toArray();

    });

    return $invitees;
}

并从你的函数中删除with并在你得到分页结果后调用它。

您不能使用联合连接不兼容的查询。 请参阅工会
您的users()方法返回User实体的 eloquent 构建器。 并且organizations()返回Business实体的构建器。
因此,一次查询对 select 用户和组织不正确。
正确的查询是这样的:

SELECT City FROM Customers
UNION
SELECT City FROM Suppliers
ORDER BY City;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM