You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在League Fractal中使用?include=参数包含多嵌套子关系?

在League Fractal中使用?include参数同时包含多个嵌套子关系

刚好我之前在项目里折腾过League Fractal的嵌套关联加载,你提到的通过?include参数同时加载多个嵌套子关系的需求完全可以实现,下面给你拆解具体步骤:

1. 先搞懂Fractal的Include语法规则

Fractal的include参数支持两种关键符号:

  • 用.表示嵌套关联(比如books.author表示加载books关联下的author)
  • 用,或者:表示同级关联(两种符号都支持,比如books.author:books.downloads或者books.author,books.downloads,都表示同时加载books下的author和downloads)

你的示例请求/store/1?include=books.author:downloads,如果是想加载store下的books,同时每个book加载author和downloads,更清晰的写法是books.author,books.downloads,不过Fractal也能识别:分隔的写法。

2. 配置对应的Transformer类

每个资源都需要创建Transformer,并且在里面定义可包含的关联关系:

首先是DownloadsTransformer(处理下载统计数据)

class DownloadsTransformer extends TransformerAbstract
{
    public function transform(Downloads $downloads)
    {
        return [
            'weekly'  => $downloads->weekly,
            'monthly' => $downloads->monthly,
        ];
    }
}

然后是AuthorTransformer(处理作者数据)

class AuthorTransformer extends TransformerAbstract
{
    public function transform(Author $author)
    {
        return [
            'id'   => $author->id,
            'name' => $author->name,
        ];
    }
}

核心的BookTransformer(定义可包含的author和downloads关联)

class BookTransformer extends TransformerAbstract
{
    // 声明当前资源支持哪些可包含的关联
    protected $availableIncludes = ['author', 'downloads'];

    public function transform(Book $book)
    {
        return [
            'id'   => $book->id,
            'name' => $book->name,
        ];
    }

    // 处理author关联的加载逻辑
    public function includeAuthor(Book $book)
    {
        $author = $book->author;
        // 返回单个关联资源
        return $this->item($author, new AuthorTransformer());
    }

    // 处理downloads关联的加载逻辑
    public function includeDownloads(Book $book)
    {
        $downloads = $book->downloads;
        return $this->item($downloads, new DownloadsTransformer());
    }
}

最后是StoreTransformer(关联到books资源)

class StoreTransformer extends TransformerAbstract
{
    protected $availableIncludes = ['books'];

    public function transform(Store $store)
    {
        return [
            'id'   => $store->id,
            'name' => $store->name,
        ];
    }

    // 处理store下的books集合
    public function includeBooks(Store $store)
    {
        $books = $store->books;
        // 返回集合类型的关联资源
        return $this->collection($books, new BookTransformer());
    }
}

3. 在控制器中处理Include参数

在接口控制器里,需要把请求中的include参数传递给Fractal Manager,让它自动处理关联加载:

use League\Fractal\Manager;
use League\Fractal\Resource\Item;

public function show($id)
{
    // 获取目标store数据(这里假设用Eloquent ORM,你可以替换成自己的数据源)
    $store = Store::with(['books.author', 'books.downloads'])->findOrFail($id);

    $fractal = new Manager();
    // 解析请求中的include参数
    $includeParam = request()->get('include');
    if ($includeParam) {
        $fractal->parseIncludes($includeParam);
    }

    // 包装资源并生成响应
    $resource = new Item($store, new StoreTransformer());
    return response()->json($fractal->createData($resource)->toArray());
}

注意:这里用with(['books.author', 'books.downloads'])是为了提前预加载关联,避免N+1查询问题,如果你用的不是Eloquent,记得自己处理关联数据的预加载逻辑。

4. 请求示例与返回结果

当你调用接口/store/1?include=books.author,books.downloads时,返回的简化结构会和你期望的一致:

{
    "data": {
        "id": 1,
        "name": "My Book Store",
        "books": {
            "data": [
                {
                    "id": 1,
                    "name": "Book Name",
                    "author": {
                        "data": {
                            "id": 1,
                            "name": "Author name"
                        }
                    },
                    "downloads": {
                        "data": {
                            "weekly": 100,
                            "monthly": 1000
                        }
                    }
                }
            ]
        }
    }
}

如果你的接口是直接返回单本图书(而非store下的图书集合),只需要把顶层Transformer换成BookTransformer,并使用?include=author,downloads即可。

内容的提问来源于stack exchange,提问作者Ryan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 06:46:23