stechstudio/laravel-record

如果 Laravel 的 Collection 和 Model 类结合会怎么样呢?

1.9 2024-03-12 23:30 UTC

This package is auto-updated.

Last update: 2024-09-13 00:41:35 UTC


README

Latest Version on Packagist Total Downloads Software License

我将假设您已经非常了解 Laravel 的强大 Collection 类,并且希望您已经阅读了 Refactoring to Collections。(如果您还没有,请停止您正在做的事情,并去购买那份PDF。您将来会感谢我的。)

我也假设您已经非常了解 Eloquent 模型

但您是否曾想要将模型的一些功能合并到集合中?

这是一个非常小巧的单一类库,将它们结合在一起。

优点

从 Collection 类开始,我想添加

  1. 属性魔术获取器。如果您在集合中有键值对,Collection 类确实提供了 get 方法。但我很懒。我喜欢使用普通的对象表示法访问我的集合,就像一个模型。Record 允许您这样做 $collection->attribute

  2. 新的子数组集合。如果您将一个多维数组传递给 collect() 并访问嵌套数组,它仍然只是一个数组。就像 $collection->get('attribute')['subattribute']。我希望所有的集合都可以一直深入下去!这将把任何子数组转换成 Record 的新实例,让您可以做 $record->attribute->subattribute->as->deep->as->your->array->goes。而且因为您在每个级别都有一个真正的集合,您可以使用所有的优点,比如 $record->attribute->subattribute->count()

  3. 自定义访问器。就像 Eloquent 一样,您可以扩展 Record 类并定义一个自定义访问器。创建一个 getFooAttribute() 方法,然后只需使用 $collection->foo 来获取您的自定义计算属性。

快速示例:处理丰富的数组

我发现我经常需要处理多维数组,通常是远程 Web 服务的响应。这个数组可能包含属性(如 'name' 或 'id'),以及嵌套集合(如 'data' 或 'rows')。

考虑这个

{
  "name" : "My Blog",
  "url" : "http://foo.dev",
  "posts" : [
    {
      "id" : 1,
      "title" : "Hello World",
      "content" : "...",
      "comments" : [
        {
          "name" : "John Doe",
          "email" : "john@example.com",
          "content": "..."
        }
      ]
    },
    {
      "id" : 2,
      "title" : "My second post",
      "content" : "...",
      "comments" : [
        ...
      ]
    }
  ]
}

我们可以用 Record 很好地导航整个负载

$record = record(json_decode($webServiceResponse, true));

echo $record->name; // My Blog
echo $record->posts->count(); // 2
echo $record->posts->first()->title; // Hello World
echo $record->posts->first()->comments->count(); // 1

太棒了!在每个级别,我都得到了 Laravel 的 Collection 类和从 Model 借来的某些属性优点的组合。

此外,我可能还会扩展 Record 并创建一个具有自定义访问器的类,用于清理 content,或将 name 分割成首尾,或者……您知道意思。

安装

您知道下一步是什么。

composer require stechstudio/laravel-record

然后您可以选择

$record = new STS\Record\Record([...]);

或者您可以使用 record 辅助方法

$record = record([...]);