waaseyaa/graphql
Composer 安装命令:
composer require waaseyaa/graphql
包简介
GraphQL endpoint + schema introspection for Waaseyaa — optional/experimental L6 surface; see README for the primary JSON:API framing.
README 文档
README
Alternative protocol — not the primary API surface.
Per the framework's API-surface consolidation (mission
api-surface-consolidation-jsonapi-primary-01KSEFTV), the framework's primary API surface is JSON:API inpackages/api/.waaseyaa/graphqlremains supported as an optional / experimental L6 protocol adapter for distributions whose consumers need GraphQL. It is not bundled bywaaseyaa/full; install it explicitly when your distribution chooses GraphQL.
Layer 6 — Interfaces
GraphQL endpoint for Waaseyaa with auto-generated schema from registered entity types.
GraphQlEndpoint accepts queries at the configured route (registered via GraphQlRouteProvider) and resolves them against EntityTypeManagerInterface-derived schemas. Connection-style pagination follows the Relay spec: totalCount reflects the full unfiltered dataset (matching JSON:API semantics — see #436), while items returns only the access-filtered subset. Field resolvers honour FieldAccessPolicyInterface so attribute-level access control matches the JSON:API surface.
Key classes: GraphQlEndpoint, GraphQlRouteProvider, GraphQlServiceProvider.
Status
- Stability: optional / experimental. The public API surface (
GraphQlServiceProvider, the/graphqlendpoint, the schema-loading mechanism, any documented resolvers / mutations) is frozen at its current shape. The framework cadence ships no new feature work for this package; community contributions are accepted under the same review bar. - Bundle membership: suggested by
waaseyaa/full(not required). To install:composer require waaseyaa/graphql. - Decision provenance: API-surface consolidation by mission
api-surface-consolidation-jsonapi-primary-01KSEFTV. JSON:API is declared the framework's primary API surface indocs/specs/jsonapi.md.
Implementation gotchas
- Reference fields keep storage field names: A field defined as
author_idwith typeentity_referenceproduces a GraphQL field namedauthor_id(notauthor). It resolves to the nested entity object but the field name includes the_idsuffix. - List filter/sort fields are gated through field-level access (R14, audit A11):
EntityResolver::resolveList()applies caller-supplied filter/sort arguments as raw storage conditions. Previouslytotalanditemswere gated only by the entity-levelguard->canView()predicate, so a field restricted per row by a dynamicFieldAccessPolicy(a classification/clearance field) was a presence/ordering oracle: filteringfilter: [{field: "classification_field", value: "secret"}]returned that value's row count even though the caller could not read the field.resolveList()now excludes a row from BOTH the count loop and the item loop when any caller-supplied filter/sort field is view-Forbiddenfor it (GraphQlAccessGuard::isFieldViewForbidden()), value-independently (dropped because the caller may not READ the queried field, never because of its value), matching the RESTJsonApiController::index()fix. BecauseQueryApplierruns sort+pagination in storage before that drop, a sort on a field view-Forbiddenon any viewable matched row is additionally REJECTED (EntityResolver::rejectForbiddenSort()throws aUserError), so a Forbidden row can never occupy an observable pagination rank (the empty-vs-populated-page ordering oracle). Gated to the bound-account path; the system-context bypass keeps the raw storageCOUNT. Structural allowlist (R15, audit A11): the residual the R14 entry flagged is now closed —EntityResolver::assertQueryableFields()runs at the top ofresolveList()(before any storage query, unconditionally) and throws aUserErrorfor any filter/sort field that is not a declared field or entity key, is inALWAYS_INTERNAL_FIELDS(pass/password/password_hash), or is a declared field flaggedsettings['internal'] => true. This mirrors REST'sJsonApiController::validateQueryFields()and closes the undeclared-_data-key oracle (which reachedjson_extract('$.<field>')) and theinternal-flagged-secret oracle (e.g.User.two_factor_secret), both of which R14's per-policy gate could not see. Seedocs/specs/api-layer.md"Field-access gate on filter/sort fields (audit R14)". Pinned byEntityResolverFieldFilterOracleTest(R14) andEntityResolverStructuralFieldAllowlistTest(R15). - Mutations require an authenticated account (R11):
GraphQlEndpoint::handle()rejects any mutation operation (create{Type}/update{Type}/delete{Type}, any alias oroperationName-selected mutation) for an unauthenticated (AccountInterface::isAuthenticated() === false) caller, for every HTTP method, BEFORE building the schema or invoking a resolver: a uniform error message"Authentication required for mutation operations."(no entity id/type ever named) and the mutation never executes. Queries are unaffected. This closes an anonymous existence oracle:update{Type}/delete{Type}distinguished "entity absent" ("Entity not found: {type}/{id}") from "entity exists but access denied", an anonymous or otherwise-unauthorized caller could enumerate entity ids by diffing the two messages even though every per-entityAccessPolicyInterfacewas itself correct. As defense-in-depth for the authenticated-but-unauthorized case (not blocked by the gate above),EntityResolver::resolveUpdate()/resolveDelete()collapse an access-denied outcome, at BOTH the entity level AND the per-fieldeditlevel (theassertFieldEditAccess()loop is inside the collapse), into the SAME "Entity not found" error the absent-entity branch throws, mirroringresolveSingle(), which has always returnednulluniformly for both cases.GraphQlRouterpropagates the endpoint's HTTP status. A custom update/delete resolver registered throughwithMutationOverrides()replaces the generated resolver and MUST preserve the same absent/access-denied collapse, preferably by delegating toEntityResolver. Seedocs/specs/api-layer.mdfor the full writeup.
waaseyaa/graphql 适用场景与选型建议
waaseyaa/graphql 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 7.92k 次下载、GitHub Stars 达 0, 最近一次更新时间为 2026 年 03 月 14 日, 在 PHP 生态内属于活跃度较高的组件。
我们在过去多个企业项目中使用过 waaseyaa/graphql 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 waaseyaa/graphql 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 waaseyaa/graphql 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
This module allows drag & drop grouping of items in a GridField
Adds text size controls and text-to-speech controls to Flarum discussion content.
Native Blade date, datetime, and date range pickers.
Symfony and Flysystem integration for the maintained KCFinder continuation.
Laravel integration for the maintained KCFinder continuation.
PHPStan rules shared across KnpLabs organization projects
统计信息
- 总下载量: 7.92k
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 41
- 依赖项目数: 1
- 推荐数: 1
其他信息
- 授权协议: GPL-2.0-or-later
- 更新时间: 2026-03-14