承接 maiscraft/graphql 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

maiscraft/graphql

Composer 安装命令:

composer require maiscraft/graphql

包简介

PHP 8 Attribute + Reflection driven GraphQL Schema auto-generation engine. Framework-agnostic, with strategy pattern type conversion and container DI.

README 文档

README

基于 PHP 8 Attribute + 反射的 GraphQL Schema 自动生成引擎,框架无关。

核心理念

  • 约定优于配置:getter/setter/构造函数自动推导字段,无需手动注册
  • 最小注解设计#[Type]#[Field]#[Query]#[Mutation]#[Arg] 五个注解
  • 反射驱动:PHP 反射自动生成 Schema,减少样板代码
  • 策略模式 + 容器注入:TypeResolver(唯一决策点)→ TypeConverterFactory → 各 TypeConverter,核心服务通过容器单例

架构

Driver(组装容器,注册核心服务)
  └─ TypeResolver(唯一决策点 + 唯一注册入口)
       ├─ enum_exists / class_exists 判断收敛于此
       ├─ TypeKind 分类(SCALAR / ENUM / OBJECT / INPUT_OBJECT)
       └─ TypeConverterFactory → EnumTypeConverter / ObjectTypeConverter / InputTypeConverter
  └─ TypeRegistry(纯存储,零判断)
  └─ PhpTypeMapper(PHP → GraphQL 类型映射)
  └─ RootFieldConverter(Query/Mutation 根字段 + 运行时值转换)

职责边界:

  • TypeResolver:唯一决策点,所有类型判断收敛到这里
  • TypeRegistry:纯存储,只做 get/set/has/mapClassName
  • Converter:纯转换,className → GraphQL Type,零注册逻辑
  • 所有核心服务通过 ContainerInterface 注入,保证单例

安装

composer require maiscraft/graphql
composer require maiscraft/graphql-hyperf  # Hyperf 框架适配

快速开始

1. 定义 Entity(Output Type)

namespace App\Domain\Entity;

use Maiscraft\GraphQL\Annotation\Type;
use Maiscraft\GraphQL\Annotation\Field;

#[Type(description: '文章')]
class Article
{
    public function __construct(
        private readonly ?int $id = null,
        private readonly string $title = '',
        private readonly string $slug = '',
        private readonly string $status = 'draft',
    ) {}

    #[Field(type: 'ID')]
    public function getId(): ?int
    {
        return $this->id;
    }

    public function getTitle(): string
    {
        return $this->title;
    }

    public function getSlug(): string
    {
        return $this->slug;
    }

    // is* 方法 → is_fieldname 布尔字段
    public function isPublished(): bool
    {
        return $this->status === 'published';
    }
}

字段暴露规则:

来源 Output Input
构造函数参数 ✅ 自动收集 ✅ 自动收集
get* 方法 ✅ 自动收集
is* 方法 ✅ → is_fieldname
set* 方法 ✅ 自动收集
public 属性 #[Field] 标注 #[Field] 标注
#[Field(hidden: true)] ❌ 不输出 ❌ 不输出

2. 定义 Enum

namespace App\Domain\ValueObject;

use Maiscraft\GraphQL\Annotation\Type;

#[Type(description: '发布状态')]
enum PublishStatus
{
    case DRAFT;
    case PUBLISHED;
    case ARCHIVED;
}

支持 backed enum 和非 backed enum,运行时值转换统一通过 ReflectionEnum::getCase() 反射获取,无硬编码方法依赖。

3. 定义 DTO(Input Type)

namespace App\DTO;

class CreateArticleDTO
{
    public function __construct(
        public readonly string $title,
        public readonly string $slug,
        public readonly ?string $description = null,
    ) {}
}

构造函数参数自动成为 GraphQL Input 字段,运行时通过反射构造实例(snake_case → camelCase 自动映射)。

4. 定义 Resolver

namespace App\GraphQL;

use App\Domain\Entity\Article;
use App\DTO\CreateArticleDTO;
use Maiscraft\GraphQL\Annotation\Query;
use Maiscraft\GraphQL\Annotation\Mutation;
use Maiscraft\GraphQL\Annotation\Arg;
use Maiscraft\GraphQL\Contract\ResolverInterface;

class ArticleResolver implements ResolverInterface
{
    public function __construct(
        private ArticleRepositoryInterface $repository
    ) {}

    #[Query(description: 'Get an article by ID')]
    public function article(#[Arg(type: 'ID!')] string $id): ?Article
    {
        return $this->repository->findById((int) $id);
    }

    #[Query(description: 'Get paginated articles')]
    public function articles(?int $page = null, ?int $pageSize = null): ArticlePaginator
    {
        return $this->repository->paginate($page ?? 1, $pageSize ?? 10);
    }

    #[Mutation(description: 'Create a new article')]
    public function createArticle(CreateArticleDTO $input): Article
    {
        return $this->repository->save(new Article(
            title: $input->title,
            slug: $input->slug,
            description: $input->description,
        ));
    }

    #[Mutation(description: 'Delete an article')]
    public function deleteArticle(#[Arg(type: 'ID!')] string $id): bool
    {
        return $this->repository->delete((int) $id);
    }
}

5. 配置(Hyperf)

// config/autoload/graphql.php
return [
    'debug' => true,

    // 目录路径扫描(从文件内容解析 namespace 获取类名)
    'scan_paths' => [
        BASE_PATH . '/app',
    ],

    'security' => [
        'max_query_depth' => 15,
        'max_query_complexity' => 1000,
    ],
];

6. 独立使用(无框架)

use Maiscraft\GraphQL\Default\SimpleContainer;
use Maiscraft\GraphQL\Driver\Driver;

$container = new SimpleContainer();
$driver = new Driver($container);

$schema = $driver->buildSchema(
    resolvers: [ArticleResolver::class],
    types: [Article::class, PublishStatus::class],
);

$result = \GraphQL\GraphQL::executeQuery(
    schema: $schema,
    source: '{ articles { items { id title } total } }',
);

7. 查询示例

query {
  article(id: "1") {
    id
    title
    slug
    is_published
  }

  articles(page: 1, pageSize: 10) {
    items {
      id
      title
    }
    total
  }
}
mutation {
  createArticle(input: {
    title: "新文章"
    slug: "new-article"
    description: "描述"
  }) {
    id
    title
  }
}

注解参考

#[Type] — 类级别,标记 GraphQL 类型

#[Type(name: 'CustomName', description: '描述', hidden: false)]
属性 类型 默认值 说明
name string 类名 GraphQL type 名称
description string '' 类型描述
hidden bool false 隐藏,不生成 Schema

#[Field] — 方法/属性/参数,标记字段

#[Field(type: 'ID', description: '描述', hidden: false)]
属性 类型 默认值 说明
type string 自动推导 GraphQL 类型(支持 Article[]ID!JSON
description string null 字段描述
hidden bool false 隐藏,不输出到 Schema

#[Query] / #[Mutation] — 方法,定义根字段

#[Query(description: '描述', type: 'ArticlePaginator')]
属性 类型 默认值 说明
name string 方法名 字段名
description string '' 字段描述
type string 返回类型推导 返回类型名

#[Arg] — 参数,定义字段参数

#[Arg(type: 'ID!')]

项目结构

graphql/src/
├── Annotation/           # 注解定义
│   ├── Arg.php
│   ├── Field.php
│   ├── Mutation.php
│   ├── Query.php
│   └── Type.php
├── Contract/             # 接口契约
│   ├── ContainerInterface.php
│   ├── ResolverInterface.php
│   └── ...
├── Converter/            # 类型转换器(策略模式)
│   ├── TypeConverterInterface.php
│   ├── TypeConverterFactory.php
│   ├── EnumTypeConverter.php
│   ├── ObjectTypeConverter.php
│   ├── InputTypeConverter.php
│   └── RootFieldConverter.php
├── Default/              # 默认实现
│   ├── SimpleContainer.php
│   └── ...
├── Driver/               # 驱动层
│   ├── ClassScanner.php
│   └── Driver.php
├── Engine/               # 引擎
│   ├── EngineConfig.php
│   └── GraphQLEngine.php
├── Mapper/               # 类型映射
│   └── PhpTypeMapper.php
├── Metadata/             # 元数据检查
│   └── MetadataInspector.php
├── Type/
│   └── JsonType.php      # JSON 标量类型
├── ReflectionHelper.php  # 共享工具 trait
├── TypeKind.php          # 类型分类枚举
├── TypeRegistry.php      # 纯存储
└── TypeResolver.php      # 唯一决策点 + 唯一注册入口

API 端点

方法 路径 说明
POST /graphql 执行 GraphQL 查询
GET /graphql Introspection 查询
GET /playground GraphQL Playground 调试界面

统计信息

  • 总下载量: 0
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 2
  • 依赖项目数: 1
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-06-21