【问题标题】:How to query dataset with exactly specified relations in Laravel?如何在 Laravel 中查询具有精确指定关系的数据集?
【发布时间】:2022-01-04 09:39:23
【问题描述】:

我有以下情况:

一个表 product_mappings 和一个表 product_mapping_options。我现在想查找所有product_mappings 中的所有条目,其中分配了具有特定ID 的条目product_mapping_options。例如,这可能如下所示:

      "data" => array:4 [
        0 => array:6 [
          "id" => 4
          "product_id" => 1
          "article_number" => null
          "created_at" => "2021-11-26T09:47:25.000000Z"
          "updated_at" => "2021-11-26T09:47:25.000000Z"
          "product_mapping_options" => array:3 [
            0 => array:5 [
              "id" => 4
              "product_mapping_id" => 4
              "product_option_id" => 1
              "created_at" => "2021-11-26T09:47:25.000000Z"
              "updated_at" => "2021-11-26T09:47:25.000000Z"
            ]
            1 => array:5 [
              "id" => 5
              "product_mapping_id" => 4
              "product_option_id" => 3
              "created_at" => "2021-11-26T09:47:25.000000Z"
              "updated_at" => "2021-11-26T09:47:25.000000Z"
            ]
            2 => array:5 [
              "id" => 6
              "product_mapping_id" => 4
              "product_option_id" => 5
              "created_at" => "2021-11-26T09:47:25.000000Z"
              "updated_at" => "2021-11-26T09:47:25.000000Z"
            ]
          ]
        ]
        1 => array:6 [
          "id" => 5
          "product_id" => 1
          "article_number" => null
          "created_at" => "2021-11-26T09:47:25.000000Z"
          "updated_at" => "2021-11-26T09:47:25.000000Z"
          "product_mapping_options" => array:4 [
            0 => array:5 [
              "id" => 7
              "product_mapping_id" => 5
              "product_option_id" => 1
              "created_at" => "2021-11-26T09:47:25.000000Z"
              "updated_at" => "2021-11-26T09:47:25.000000Z"
            ]
            1 => array:5 [
              "id" => 8
              "product_mapping_id" => 5
              "product_option_id" => 3
              "created_at" => "2021-11-26T09:47:25.000000Z"
              "updated_at" => "2021-11-26T09:47:25.000000Z"
            ]
            2 => array:5 [
              "id" => 9
              "product_mapping_id" => 5
              "product_option_id" => 5
              "created_at" => "2021-11-26T09:47:25.000000Z"
              "updated_at" => "2021-11-26T09:47:25.000000Z"
            ]
            3 => array:5 [
              "id" => 10
              "product_mapping_id" => 5
              "product_option_id" => 7
              "created_at" => "2021-11-26T09:47:25.000000Z"
              "updated_at" => "2021-11-26T09:47:25.000000Z"
            ]
          ]
        ]
        2 => array:6 [
          "id" => 6
          "product_id" => 1
          "article_number" => null
          "created_at" => "2021-11-26T09:47:25.000000Z"
          "updated_at" => "2021-11-26T09:47:25.000000Z"
          "product_mapping_options" => array:4 [
            0 => array:5 [
              "id" => 11
              "product_mapping_id" => 6
              "product_option_id" => 1
              "created_at" => "2021-11-26T09:47:25.000000Z"
              "updated_at" => "2021-11-26T09:47:25.000000Z"
            ]
            1 => array:5 [
              "id" => 12
              "product_mapping_id" => 6
              "product_option_id" => 3
              "created_at" => "2021-11-26T09:47:25.000000Z"
              "updated_at" => "2021-11-26T09:47:25.000000Z"
            ]
            2 => array:5 [
              "id" => 13
              "product_mapping_id" => 6
              "product_option_id" => 5
              "created_at" => "2021-11-26T09:47:25.000000Z"
              "updated_at" => "2021-11-26T09:47:25.000000Z"
            ]
            3 => array:5 [
              "id" => 14
              "product_mapping_id" => 6
              "product_option_id" => 8
              "created_at" => "2021-11-26T09:47:25.000000Z"
              "updated_at" => "2021-11-26T09:47:25.000000Z"
            ]
          ]
        ]
        3 => array:6 [
          "id" => 7
          "product_id" => 1
          "article_number" => null
          "created_at" => "2021-11-26T09:47:25.000000Z"
          "updated_at" => "2021-11-26T09:47:25.000000Z"
          "product_mapping_options" => array:4 [
            0 => array:5 [
              "id" => 15
              "product_mapping_id" => 7
              "product_option_id" => 1
              "created_at" => "2021-11-26T09:47:25.000000Z"
              "updated_at" => "2021-11-26T09:47:25.000000Z"
            ]
            1 => array:5 [
              "id" => 16
              "product_mapping_id" => 7
              "product_option_id" => 3
              "created_at" => "2021-11-26T09:47:25.000000Z"
              "updated_at" => "2021-11-26T09:47:25.000000Z"
            ]
            2 => array:5 [
              "id" => 17
              "product_mapping_id" => 7
              "product_option_id" => 5
              "created_at" => "2021-11-26T09:47:25.000000Z"
              "updated_at" => "2021-11-26T09:47:25.000000Z"
            ]
            3 => array:5 [
              "id" => 18
              "product_mapping_id" => 7
              "product_option_id" => 9
              "created_at" => "2021-11-26T09:47:25.000000Z"
              "updated_at" => "2021-11-26T09:47:25.000000Z"
            ]
          ]
        ]
      ]

这里我通过product_mappings搜索,搜索范围如下:

    public function scopeProductOption(Builder $query, ...$productOptionTypeIds): Builder
    {
        foreach($productOptionTypeIds as $productOptionTypeId) {
            $query->whereHas('ProductMappingOptions', function (Builder $query) use ($productOptionTypeId) {
                $query->where('product_option_id', $productOptionTypeId);
            });
        }

        return($query);
    }

在示例中,我指定了值 1,3 和 5(然后将其传递到 $productOptionTypeIds)。

我现在想要什么:我想要 100% 准确地显示 product_mappings 匹配搜索,比如说我想要找到例如只有一个条目恰好映射了 1,3 和 5,而不是 1,3,5 和 7,9 或 11。因此,具有 4 个关系的条目应该消失,因为我不希望条目在某事“结束”了。

你知道我怎样才能“抓住”这个条目吗?所以在上面的例子中,我只想要来自data 的条目0。如果我指定 1、3、5 和 9,我只想要来自 data 的条目 3。

【问题讨论】:

    标签: laravel eloquent eloquent-relationship


    【解决方案1】:

    好的,找到了解决方案,真的很简单:

        public function scopeProductOption(Builder $query, ...$productOptionTypeIds): Builder
        {
            $query->has('ProductMappingOptions', '=', count($productOptionTypeIds));
            foreach($productOptionTypeIds as $productOptionTypeId) {
                $query->whereHas('ProductMappingOptions', function (Builder $query) use ($productOptionTypeId) {
                    $query->where('product_option_id', $productOptionTypeId);
                });
            }
    
            return($query);
        }
    
    

    我添加了关系计数

    【讨论】:

      【解决方案2】:

      你可以使用whereIn函数来代替循环语句

      public function scopeProductOption(Builder $query, ...$productOptionTypeIds): Builder
          {
              //this will parse the values from spread operator
              if ($productOptionTypeIds !== []) {
                  if (count($productOptionTypeIds) !== count($productOptionTypeIds, COUNT_RECURSIVE)) {
                      $productOptionTypeIds = iterator_to_array(new \RecursiveIteratorIterator(new \RecursiveArrayIterator($productOptionTypeIds)));
                  }
      
                  $query->whereHas('ProductMappingOptions', function (Builder $query) use ($productOptionTypeIds) {
                      $query->where('product_option_id', $productOptionTypeIds);
                  });
              }
          
              return ($query);
          }
      

      【讨论】:

      • 感谢您的回答! :-) 我现在还没有和我一起测试你的解决方案是否会导致我想要的,但在我看来它更复杂,乍一看也不是那么逻辑上可以理解。我发现我的解决方案更易于阅读和理解。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-09-14
      • 2021-12-28
      • 1970-01-01
      • 2021-08-31
      • 1970-01-01
      • 1970-01-01
      • 2018-03-01
      相关资源
      最近更新 更多