Skip to content

Conversation

@huangdijia
Copy link
Contributor

@huangdijia huangdijia commented May 13, 2025

Summary by CodeRabbit

  • 新功能

    • 新增用于判断值是否可被视为数组的功能。
    • 新增支持多种类型对象(如数组、可遍历对象、可序列化对象等)转换为数组的功能。
    • 将多个类型检查方法由静态方法改为实例方法,增强灵活性。
  • 测试

    • 增加了对新功能的测试用例,覆盖数组转换和数组能力检测的多种场景。
    • 新增多种用于测试的模拟对象,便于验证不同类型的数据结构转换和序列化行为。

@coderabbitai
Copy link

coderabbitai bot commented May 13, 2025

## Walkthrough

此次更新为 `Arr` 工具类及其 Mixin 增加了两个新方法:`arrayable` 用于判断值是否可视为数组,`from` 用于将多种类型(数组、可遍历对象、可序列化对象等)统一转换为数组。相关测试用例与测试桩类也同步补充。

## Changes

| 文件/分组                                            | 变更摘要 |
|------------------------------------------------------|----------|
| src/macros/output/Hyperf/Collection/Arr.php          | 新增静态方法 `arrayable($value): bool` 和 `from($items): array`,分别用于判断是否“可数组化”及多类型转数组。|
| src/macros/src/ArrMixin.php                          | 所有静态方法改为实例方法,新增 `arrayable()` 和 `from()` 方法,分别返回判断/转换闭包。|
| tests/Macros/ArrTest.php                             | 新增 `test arrayable` 和 `test from` 测试用例,覆盖新方法的多种输入场景与异常情况。|
| tests/Macros/Stubs/Common.php                        | 新增多个测试桩类,分别实现 `Arrayable`、`Jsonable`、`JsonSerializable`、`IteratorAggregate` 等接口,便于测试多种对象的数组化和序列化行为。|

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant 调用者
    participant Arr
    participant 各类对象/值

    调用者->>Arr: arrayable($value)
    Arr->>各类对象/值: 检查是否为数组/实现Arrayable等接口
    Arr-->>调用者: 返回布尔值

    调用者->>Arr: from($items)
    Arr->>各类对象/值: 判断类型并转换为数组
    Arr-->>调用者: 返回数组或抛出异常

Poem

小兔写代码,数组化真妙,
新增 arrayable,类型一眼瞧。
from 能变换,万物皆可套,
测试桩齐全,转换不动摇。
代码更灵巧,兔子乐逍遥! 🐇✨


<!-- walkthrough_end -->

<!-- announcements_start -->

> [!TIP]
> <details>
> <summary>⚡️ Faster reviews with caching</summary>
> 
> - CodeRabbit now supports caching for code and dependencies, helping speed up reviews. This means quicker feedback, reduced wait times, and a smoother review experience overall. Cached data is encrypted and stored securely. This feature will be automatically enabled for all accounts on May 16th. To opt out, configure `Review - Disable Cache` at either the organization or repository level. If you prefer to disable all data retention across your organization, simply turn off the `Data Retention` setting under your Organization Settings.
> 
> Enjoy the performance boost—your workflow just got faster.
> 
> </details>

<!-- announcements_end -->

---

<details>
<summary>📜 Recent review details</summary>

**Configuration used: .coderabbit.yaml**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 337a8ab4446aa9970c1a65ae4d693d0084c18db9 and b4be761950617a933642dc9893e841645ff03f77.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `src/macros/src/ArrMixin.php` (5 hunks)

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (1)</summary>

* src/macros/src/ArrMixin.php

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (12)</summary>

* GitHub Check: Test on PHP 8.1 with Swoole 6.0.2
* GitHub Check: Test on PHP 8.3 with Swoole 5.1.7
* GitHub Check: Test on PHP 8.2 with Swoole 6.0.2
* GitHub Check: Test on PHP 8.1 with Swoole 5.1.7
* GitHub Check: Test on PHP 8.2 with Swoole 5.1.7
* GitHub Check: Test on PHP 8.3 with Swoole 6.0.2
* GitHub Check: Test on PHP 8.1 with Swoole 5.1.7
* GitHub Check: Test on PHP 8.2 with Swoole 5.1.7
* GitHub Check: Test on PHP 8.1 with Swoole 6.0.2
* GitHub Check: Test on PHP 8.3 with Swoole 5.1.7
* GitHub Check: Test on PHP 8.2 with Swoole 6.0.2
* GitHub Check: Test on PHP 8.3 with Swoole 6.0.2

</details>

</details>
<!-- internal state start -->


<!-- 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= -->

<!-- internal state end -->
<!-- finishing_touch_checkbox_start -->

<details open="true">
<summary>✨ Finishing Touches</summary>

- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> 📝 Generate Docstrings

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---



<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=friendsofhyperf/components&utm_content=860):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Explain this complex logic.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai explain this code block.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and explain its main purpose.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

### Support

Need help? Create a ticket on our [support page](https://www.coderabbit.ai/contact-us/support) for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (7)
tests/Macros/ArrTest.php (3)

13-14: 建议改用 Composer autoload 代替 require_once 手动引入

直接 require_once __DIR__ . '/Stubs/Common.php'; 会绕过 Composer 的自动加载,
导致 IDE 静态分析无法追踪类引用,也容易在文件移动/命名空间调整时遗漏更新。

可将 tests/Macros/Stubs 目录加入 autoload-dev.psr-4,然后删除手动 require_once。这样:

-require_once __DIR__ . '/Stubs/Common.php';

改为在 composer.json

"autoload-dev": {
    "psr-4": {
        "FriendsOfHyperf\\Tests\\Macros\\": "tests/Macros/"
    }
}

执行 composer dump-autoload 即可。
这样既保持测试代码整洁,又避免因路径硬编码带来的维护成本。


15-31: 测试用例重复断言较多,可用数据集精简

当前对 Arr::arrayable() 的正、负用例分别写了 5+ 条 assertTrue/False
考虑使用 Pest 的 dataset() 或 PHPUnit 的 dataProvider,用循环一次性覆盖,
减少重复代码并提高可读性。例如:

dataset('arrayables', [
    [[]],
    [new TestArrayableObject()],
    ...
]);

test('arrayable positive', function ($value) {
    expect(Arr::arrayable($value))->toBeTrue();
})->with('arrayables');

同理可对负用例和 Arr::from() 做类似处理。
非功能性改进,但能让测试文件更简洁。


108-115: WeakMap 场景下建议增加 PHP 版本判断

WeakMap 仅在 PHP 8.0+ 可用,虽然项目最低版本大概率 ≥8.0,但为了向后兼容或防止意外降级环境运行测试,可在用例前加:

if (!class_exists(WeakMap::class)) {
    $this->markTestSkipped('WeakMap not supported on this PHP version.');
}

避免老版本 CI 直接失败。
若项目已锁定 8.1+ 可忽略此建议。

tests/Macros/Stubs/Common.php (2)

21-27: 可考虑将桩类声明为 final 并补全类型提示

这些 Stub 仅用于测试,不需要被继承。将其标记为 final 能减少误用并提升 opcache 最佳化效果;同时为构造函数参数、属性及返回值增加显式类型,有助于静态分析。

示例:

-final class TestArrayableObject implements Arrayable
+final class TestArrayableObject implements Arrayable
 {
     public function toArray(): array
     {
         return ['foo' => 'bar'];
     }
 }

同理可应用于其他 Stub 类。


42-48: jsonSerialize() 返回类型建议显式标注 mixed 以兼容 PHP 8.1+

PHP 8.1 起 JsonSerializable::jsonSerialize(): mixed
虽然省略类型不会报错,但显式声明更清晰,亦可避免 Psalm/PhpStan 提示。

-    public function jsonSerialize(): array
+    public function jsonSerialize(): array

如果未来打算让方法可能返回非数组(例如标量),可直接使用 mixed

src/macros/src/ArrMixin.php (2)

29-36: 建议为 arrayable() 方法添加文档注释

arrayable() 方法的实现逻辑正确,能有效判断值是否可转为数组。与类中的其他方法相比,该方法缺少文档注释来说明其功能和用途。

+/**
+ * Determine if the given value is arrayable.
+ */
 public function arrayable()
 {
     return fn ($value) => is_array($value)
         || $value instanceof Arrayable
         || $value instanceof Traversable
         || $value instanceof Jsonable
         || $value instanceof JsonSerializable;
 }

89-102: 建议为 from() 方法添加文档注释并说明 WeakMap 的特殊处理

from() 方法实现全面,使用了 PHP 8 的 match 表达式处理多种类型转换,代码简洁高效。有两点建议:

  1. 添加文档注释说明方法功能
  2. 解释为什么 WeakMap 使用 iterator_to_array($items, false) 与其他 Traversable 不同的处理方式
+/**
+ * Convert the given value to an array.
+ *
+ * @param mixed $items
+ * @return array
+ * @throws \InvalidArgumentException
+ */
 public function from()
 {
     return fn ($items) => match (true) {
         is_array($items) => $items,
         $items instanceof Enumerable => $items->all(),
         $items instanceof Arrayable => $items->toArray(),
+        // WeakMap 使用对象作为键,不能保存键值,因此使用 false 参数
         $items instanceof WeakMap => iterator_to_array($items, false),
         $items instanceof Traversable => iterator_to_array($items),
         $items instanceof Jsonable => json_decode($items->toJson(), true),
         $items instanceof JsonSerializable => (array) $items->jsonSerialize(),
         is_object($items) => (array) $items,
         default => throw new InvalidArgumentException('Items cannot be represented by a scalar value.'),
     };
 }
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 51d88fe and 337a8ab.

📒 Files selected for processing (4)
  • src/macros/output/Hyperf/Collection/Arr.php (2 hunks)
  • src/macros/src/ArrMixin.php (5 hunks)
  • tests/Macros/ArrTest.php (2 hunks)
  • tests/Macros/Stubs/Common.php (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/macros/output/Hyperf/Collection/Arr.php (1)
src/macros/src/ArrMixin.php (2)
  • arrayable (29-36)
  • from (89-102)
⏰ Context from checks skipped due to timeout of 90000ms (12)
  • GitHub Check: Test on PHP 8.1 with Swoole 6.0.2
  • GitHub Check: Test on PHP 8.1 with Swoole 5.1.7
  • GitHub Check: Test on PHP 8.3 with Swoole 5.1.7
  • GitHub Check: Test on PHP 8.2 with Swoole 5.1.7
  • GitHub Check: Test on PHP 8.2 with Swoole 6.0.2
  • GitHub Check: Test on PHP 8.3 with Swoole 6.0.2
  • GitHub Check: Test on PHP 8.1 with Swoole 6.0.2
  • GitHub Check: Test on PHP 8.2 with Swoole 6.0.2
  • GitHub Check: Test on PHP 8.1 with Swoole 5.1.7
  • GitHub Check: Test on PHP 8.3 with Swoole 6.0.2
  • GitHub Check: Test on PHP 8.3 with Swoole 5.1.7
  • GitHub Check: Test on PHP 8.2 with Swoole 5.1.7
🔇 Additional comments (8)
src/macros/output/Hyperf/Collection/Arr.php (2)

56-69:

Details

❌ Incorrect review comment

from() 同样为空实现,建议与上文一致处理

同样出于防御性编程考虑,建议为 from() 增加占位实现或抛出异常,避免误用造成“空数组/null”一类难以排查的问题;并在注释中指明真正逻辑来源(ArrMixin::from() 动态宏)。
参见上一条建议,可一并处理。


为验证 Arr::from() 的真实实现来源及与其他静态方法的一致性,请运行以下脚本:


🏁 Script executed:

#!/bin/bash
# 查找 ArrMixin 类及其 from 方法定义
rg -n "class ArrMixin" -C2 .
rg -n "function from" -C3 .

# 列出 Arr.php 中所有静态方法,实现空方法的模式
rg -n "public static function" -C1 src/macros/output/Hyperf/Collection/Arr.php

Length of output: 13903


无需为 Arr::from() 添加占位实现或抛出异常

src/macros/output/Hyperf/Collection/Arr.php 中所有静态方法(包括 from)均为自动生成的宏声明(空方法),真正的实现逻辑由 ArrMixin::from() 在运行时动态注入。保持空实现可确保与其他方法保持一致,并由宏机制接管方法调用,无需额外抛出异常或实现占位。

  • 文件:src/macros/output/Hyperf/Collection/Arr.php
  • 方法:public static function from($items) { }

Likely an incorrect or invalid review comment.


19-27:

Details

✅ Verification successful

静态桩方法缺少任何实现,可能导致运行时误调用隐患

目前 arrayable() 只有签名,没有函数体。一旦该桩文件被实际加载(例如误被 autoload 进生产环境),调用 Arr::arrayable() 会得到 null,从而破坏业务逻辑或导致类型错误。
如果此文件仅用于 IDE-stub/静态分析而绝不会被执行,建议:

  1. 在文件或目录层面通过 composer.jsonexclude-from-classmap 明确排除,确保运行时永远不会加载到。
  2. 在方法体中显式抛出异常或加入注释说明其纯粹的 stub 性质,以便后续维护者快速理解意图,减少踩坑概率。示例 diff:
     public static function arrayable($value)
     {
-    }
+        // This is an analysis-only stub. Real logic is provided at runtime by ArrMixin.
+        throw new \LogicException('Stub – should never be executed.');
+    }

🏁 Script executed:

#!/bin/bash
# List the stub file content (first 200 lines)
if [ -f src/macros/output/Hyperf/Collection/Arr.php ]; then
  echo "---- src/macros/output/Hyperf/Collection/Arr.php ----"
  sed -n '1,200p' src/macros/output/Hyperf/Collection/Arr.php
else
  echo "File src/macros/output/Hyperf/Collection/Arr.php not found."
fi

# Show composer.json autoload and autoload-dev sections
echo "---- composer.json autoload sections ----"
grep -R -n "\"autoload" -n composer.json -A 10

# Check for exclude-from-classmap usage
echo "---- composer.json exclude-from-classmap ----"
grep -R -n "exclude-from-classmap" composer.json || echo "No exclude-from-classmap found."

Length of output: 4201


确认:IDE Stub 文件不在运行时 Autoload 范围,无需改动

经检查,src/macros/output/Hyperf/Collection/Arr.php 所在目录并未在 composer.json 的 PSR-4 或 classmap autoload 中声明,因此这些空方法仅用于 IDE 提示/静态分析,不会在生产环境被加载或调用。

• 无需在 composer.json 中额外添加 exclude-from-classmap
• 如有必要,可在文件注释中说明仅为 Stub,或在项目文档里集中说明此目录用途,避免维护者误解。
• 建议保持当前空方法实现,不做抛错处理,以免影响静态分析工具对方法签名的识别。

src/macros/src/ArrMixin.php (6)

16-22: 新导入的依赖项与添加的功能匹配

添加了多个关于可数组化接口的导入,这些都是为了支持新增的 arrayable()from() 方法所需的,导入的依赖项选择恰当。


38-39: 方法从静态改为实例方法符合 Mixin 模式

将之前的静态方法改为实例方法,符合该类作为 Mixin 的设计模式,这是一个良好的变更。


56-57: 方法从静态改为实例方法符合 Mixin 模式

将之前的静态方法改为实例方法,符合该类作为 Mixin 的设计模式,这是一个良好的变更。


74-75: 方法从静态改为实例方法符合 Mixin 模式

将之前的静态方法改为实例方法,符合该类作为 Mixin 的设计模式,这是一个良好的变更。


107-108: 方法从静态改为实例方法符合 Mixin 模式

将之前的静态方法改为实例方法,符合该类作为 Mixin 的设计模式,这是一个良好的变更。


125-126: 方法从静态改为实例方法符合 Mixin 模式

将之前的静态方法改为实例方法,符合该类作为 Mixin 的设计模式,这是一个良好的变更。

@huangdijia huangdijia marked this pull request as ready for review May 13, 2025 04:39
@huangdijia huangdijia merged commit a15d0a1 into main May 13, 2025
16 checks passed
@huangdijia huangdijia deleted the add-arr-helpers branch May 13, 2025 04:39
@coderabbitai coderabbitai bot mentioned this pull request Oct 29, 2025
3 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants