【问题标题】:how to get N records from a model per parent ? In laravel eloquent如何从每个父模型中获取 N 条记录?在 laravel 中雄辩
【发布时间】:2018-11-18 13:52:19
【问题描述】:

如何在 laravel eloquent 中从每个父级的模型中获取 n 条记录。

例如,假设我有 products 表和 categories 表。我想要一个名称以A 开头的所有产品的列表,但每个category 不超过 10 个产品。

我的表结构是这样的。

产品表

---------------------------------
id  | title | slug | category_id
----------------------------------

分类表

--------------
id  | title |
--------------

我试图遵循这个例子,这正是我想要的 https://softonsofa.com/tweaking-eloquent-relations-how-to-get-n-related-models-per-parent/

但是当我在 product model 添加范围后尝试像链接中的示例一样查询时。它抛出和 sql 错误说。

SQLSTATE[HY000]:一般错误:1267 非法混合排序规则 (utf8mb4_unicode_ci,IMPLICIT) 和 (utf8mb4_0900_ai_ci,IMPLICIT) operation '=' (SQL: select count(*) as aggregate from...

谁能告诉我如何获得每个相关模型的 n 个结果或如何修复此错误。

【问题讨论】:

  • 什么 MySQL 版本?因为 MySQL 8.0 有比使用 MySQL 的用户变量更好的方法。
  • @RaymondNijland 我正在开发最新的 Xamp 服务器。在 phpmyadmin 中显示服务器版本:10.1.25-MariaDB。我猜那个
  • 基本上,错误已经在告诉您该怎么做:检查表的排序规则。如果您故意将它们设置为不同的类型,那么您会很倒霉,因为那样这些类型的查询将不起作用。如果不是这种情况,请确保所有表和列的排序规则都相同。有很多资源可以解释如何去做。
  • @Namoshek,可能是因为我的类别位于 mariadb 的 xamp 服务器上,而我的产品位于 inodb 中的实时服务器上,这可能是导致问题的原因吗?如果是这样,你能告诉我如何解决这个问题吗?谢谢
  • 不知道,说实话。对不起。

标签: php mysql laravel laravel-5 eloquent


【解决方案1】:

Laravel 对此没有原生支持。

我为它创建了一个包:https://github.com/staudenmeir/eloquent-eager-limit

在父模型和相关模型中使用 HasEagerLimit 特征。

class Category extends Model {
    use \Staudenmeir\EloquentEagerLimit\HasEagerLimit;
}

class Product extends Model {
    use \Staudenmeir\EloquentEagerLimit\HasEagerLimit;
}

然后您可以将limit()/take() 应用于您的关系:

Category::with(['products' => function($query) {
    $query->where('name', 'LIKE', 'A%')->limit(10);
}])->get();

【讨论】:

    【解决方案2】:

    调用关系时传递查询:

    Category::with(['products' => function($query){
        $query->take(10)->skip(0);
    }])->get();
    

    假设您的 Category 模型中有一个关系。

    public function products()...
    

    【讨论】:

    • 这将为您获取的所有类别总共加载10 产品。这意味着您最终可能会发现某些类别加载了零个产品,而其他类别加载了多个产品。
    • 可以这样做,但我不想这样做有几个原因,其中之一是我无法对产品价格进行排序,并且应用与产品直接相关的其他过滤器会有点困难
    • 为什么不呢? $query->where('price', '>', 0)->take(10)->skip(0);你可以在'with'关系中使用几个雄辩的函数......在'with'之前你也可以使用'has'。这么多选择。干净简单。
    • 在这一切之后,您仍然可以过滤收藏。
    【解决方案3】:

    在我看来,对于每个 categoryID,您需要列出一个包含 10 个产品的数组。使用 Eloquent,这就是我想出的

    $categories = Category::all()
    productsArray = array();
    foreach($categories as $category) {
            $products = Product::where('category_id', $category->id)->where('title', 'LIKE', 'A%')->get();
            if(sizeof($products)) {
                $products = $products->take(10);
                $productsArray[$category->id] = $products;
            }
        }
    return $productsArray;
    

    我看到的唯一缺点是每个类别 ID 的循环,如果您有数千条记录,这可能需要更多时间。如果你想在你的刀片文件中显示它,你可以有任何其他的键,除了 $category->id。

    【讨论】:

    • 口才的效率在哪里?
    【解决方案4】:

    首先让我们创建模型:

    class Category extends Model
    {
        public $timestamps = false;
    
        protected $fillable = [
    
           'title'];
    
        public function products(){
        return $this->hasMany(\App\Products::class)->limit(10);
    }
    }
    

    第二个:

    class Products extends Model
    {
        public $timestamps = false;
    
        protected $casts = [
            'category_id' => 'int',
        ];
    
        protected $fillable = [
    
           'title',
            'slug'
        ];
    
        public function category()
        {
            return $this->belongsTo(\App\Category::class);
        }
    }
    

    使用 eloquent 如下:

    $Category = Category::get();
    

    也可以使用starts_with()来定义列、字

    【讨论】:

    • 嗨,这可能是根据类别过滤选择产品的正确方法。但我想要的是其他方式,即基于类别的产品,以便我可以轻松地对产品应用过滤器。此外,我在每个表中都有超过 250 万条记录,这样会占用大量时间和服务器资源。但你的答案很棒:))
    • 实际上这是基于类别的产品,使用 foreach 您只需执行 $Category->product->name 并且您已经获得了所有类别,每个类别都有 10 个产品,如果您想应用过滤器,您只需应用 $Category->products->where()->otherfilters()->get(); 就可以了.如果我的回答对您有帮助,请不要忘记将其标记为 :)
    猜你喜欢
    • 2016-03-09
    • 2019-07-16
    • 2021-08-11
    • 2017-07-25
    • 2021-09-28
    • 1970-01-01
    • 2016-04-15
    • 2021-05-07
    • 2022-01-06
    相关资源
    最近更新 更多