如何从每个父模型中获取 N 条记录?在 laravel 中雄辩

Posted

技术标签:

【中文标题】如何从每个父模型中获取 N 条记录?在 laravel 中雄辩【英文标题】:how to get N records from a model per parent ? In laravel eloquent 【发布时间】: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 中的实时服务器上,这可能是导致问题的原因吗?如果是这样,你能告诉我如何解决这个问题吗?谢谢 不知道,说实话。对不起。 【参考方案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(); 就可以了.如果我的回答对您有帮助,请不要忘记将其标记为 :)

以上是关于如何从每个父模型中获取 N 条记录?在 laravel 中雄辩的主要内容,如果未能解决你的问题,请参考以下文章

Laravel Eloquent/MySQL 如何从每个父记录的最后一个条目中获取去年的记录?

仅在满足父模型的给定条件时如何获取模型关系

如何从具有父类引用的类中获取记录?

如何从 Azure 表存储中查询最近的 n 条记录?

如何使用Java从mongodb获取最后插入的N条记录?

如何使用Java从mongodb获取最后插入的N条记录?