graphql skill
GraphQL経由でAPI Platformのリソースを公開し、クエリ、ミューテーション、カスタムリゾルバー、およびRelayカーソルページネーションをサポートします。
- GitHubスター
- 29
- ファイル
- 1
- 最終コミット
- 2026年10月22日
- ライセンス
- —
- 許可されたツール
- —
graphql skillは何をしますか
graphqlはAgent Skillsです。 GraphQL経由でAPI Platformのリソースを公開し、クエリ、ミューテーション、カスタムリゾルバー、およびRelayカーソルページネーションをサポートします。.
skillのSKILL.mdから生成された要約。
graphql skill について
API PlatformのリソースをGraphQLエンドポイント経由で公開することで、フィールド選択やラウンドトリップの削減といったクライアント固有の要件に対応できます。このSKILLは、単一のリクエストで複雑なデータ構造をナビゲートする必要があるRelayやApolloフロントエンドを構築する際に使用することを想定しています。ユーザーがGraphQL操作の実装、カスタムリゾルバーの管理、または既存のリソースに対するRelayカーソルページネーションの設定を行う際に、エージェントはこのSKILLをロードする必要があります。
ユーザーは、専用のメタデータクラスを使用して、Query、QueryCollection、Mutation、DeleteMutationなどの特定の操作を定義できます。このツールは、QueryItemResolverInterfaceやMutationResolverInterfaceなどのリゾルバーインターフェースを通じてカスタムロジックをサポートしており、データの拡充やカスタムフェッチが可能です。SymfonyにおけるRelayスタイルのコネクションやMercureベースのサブスクリプションなどの高度な機能を提供しますが、これはRESTを置き換えるものではなく、特にHTTPキャッシュや操作コストの予測可能性を優先する場合に、RESTを補完するように設計されています。
エージェントができること
- 1GraphQL操作の実装リソースクラスに対して、ミューテーションやクエリなどの特定のGraphQL操作を作成します。
- 2カスタムデータロジックの設定単純なID取得以上の処理が必要な複雑なクエリを処理するために、カスタムリゾルバーを開発します。
skill の SKILL.md から作成されています。すべてのユースケースは、その引用と照合されています。
graphql skillのインストール方法
各コマンドはskillフォルダをクライアントのskillsディレクトリにコピーします。読み込むには、クライアントを再起動するか新しいセッションを開始してください。プラグインにgraphql skillをインストールする
/plugin marketplace add api-platform/skillset /plugin install api-platform@api-platform-skillset
Claude Codeにgraphql skillをインストールする
~/.claude/skills/graphql/SKILL.md
$ npx degit api-platform/skillset/skills/graphql ~/.claude/skills/graphqlClaude Code (project)にgraphql skillをインストールする
.claude/skills/graphql/SKILL.md
$ npx degit api-platform/skillset/skills/graphql .claude/skills/graphqlCodexにgraphql skillをインストールする
~/.agents/skills/graphql/SKILL.md
$ npx degit api-platform/skillset/skills/graphql ~/.agents/skills/graphqlGemini CLIにgraphql skillをインストールする
~/.gemini/skills/graphql/SKILL.md
$ npx degit api-platform/skillset/skills/graphql ~/.gemini/skills/graphqlClaude.aiにgraphql skillをインストールする
npx degit api-platform/skillset/skills/graphql graphql && zip -r graphql.zip graphql # claude.ai → Customize → Skills → + → Create skill → Upload a skill → graphql.zip
SKILL.md
GitHubで表示GraphQL
Default to REST. GraphQL trades away things API Platform gives you for free over REST: HTTP cache semantics (ETag, Cache-Control, invalidation), one URL per resource, simple CDN/proxy caching, and predictable per-operation cost. A single GraphQL query can fan out into arbitrarily deep/expensive resolution. Reach for GraphQL when it is a hard client requirement (e.g. a Relay/Apollo frontend, or clients that genuinely need to select fields and avoid round-trips) — not as a default. The same resource class can serve both; you don't have to choose globally.
Enabling GraphQL
Install api-platform/graphql (composer require api-platform/graphql), then it's
on. A /graphql endpoint and the GraphiQL playground (/graphql/graphiql) appear.
Disable globally or per resource as needed:
# config/packages/api_platform.yaml
api_platform:
graphql:
enabled: true
graphiql:
enabled: true
Declaring GraphQL operations
GraphQL operations live in graphQlOperations and are separate classes from the
REST ones, under ApiPlatform\Metadata\GraphQl\. A resource with no
graphQlOperations still gets a default set (item query, collection query, create /
update / delete mutations) once GraphQL is enabled.
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\GraphQl\DeleteMutation;
use ApiPlatform\Metadata\GraphQl\Mutation;
use ApiPlatform\Metadata\GraphQl\Query;
use ApiPlatform\Metadata\GraphQl\QueryCollection;
#[ApiResource(graphQlOperations: [
new Query(),
new QueryCollection(),
new Mutation(name: 'create'),
new Mutation(name: 'update'),
new DeleteMutation(name: 'delete'),
])]
class Book {}
Mutation and DeleteMutation require a name — it becomes the GraphQL field
name (createBook, updateBook, deleteBook). Query and QueryCollection only
need a name when you declare more than one of the same kind (e.g. a custom query
alongside the default).
Security on GraphQL operations
Same ExpressionLanguage as REST (see operations), set per GraphQl operation:
new Query(security: "is_granted('ROLE_USER')")
new Mutation(name: 'update', security: "object.getOwner() == user")
new Mutation(name: 'update', securityPostDenormalize: "object.getOwner() == user")
Because one GraphQL query can traverse relations, securing only the top-level operation is not enough — guard the related resources' operations too, or a nested field becomes an unguarded read path.
Custom resolvers
Use a resolver when a query/mutation needs logic beyond fetch-by-id. Resolvers are services implementing one of:
QueryItemResolverInterface—__invoke(?object $item, array $context): objectQueryCollectionResolverInterface—__invoke(iterable $collection, array $context): iterableMutationResolverInterface—__invoke(?object $item, array $context): ?object
Query arguments arrive in $context['args'].
use ApiPlatform\GraphQl\Resolver\QueryItemResolverInterface;
final class BookResolver implements QueryItemResolverInterface
{
public function __invoke(?object $item, array $context): object
{
// $item is the fetched Book (or null if read: false); enrich or replace it
return $item;
}
}
With Symfony autoconfiguration the resolver is wired automatically. Without it, tag
the service api_platform.graphql.query_resolver (or ..._mutation_resolver). Then
reference it by class name on the operation, and set read: false when the
resolver should fetch the data itself rather than receiving a hydrated item:
new Query(name: 'recommended', resolver: BookResolver::class, read: false)
new Query(
name: 'search',
resolver: BookResolver::class,
args: [
'query' => ['type' => 'String!', 'description' => 'Full-text search'],
'limit' => ['type' => 'Int'],
],
)
args overrides the auto-generated argument set — define it when the query takes
parameters that aren't resource fields.
Relations and the N+1 trap
GraphQL embeds related resources by selecting nested fields:
{
book(id: "/books/1") {
title
author { name }
}
}
Relations resolve through the same providers as REST. A deeply nested query can trigger many small queries (the classic N+1). API Platform mitigates common cases, but verify against real queries and add Doctrine joins / a custom collection provider where a hot path fans out. This open-ended cost is the main reason REST is the safer default for cache-sensitive APIs.
Pagination: Relay cursor connections
Collection queries return Relay-style cursor connections by default
(edges { node { ... } cursor }, pageInfo, totalCount), driven by first/
after/last/before arguments:
{
books(first: 10, after: "endCursor") {
totalCount
edges { node { title } cursor }
pageInfo { endCursor hasNextPage }
}
}
To use simple page-based pagination instead, set paginationType: 'page' on the
resource or the QueryCollection:
use ApiPlatform\Metadata\GraphQl\QueryCollection;
#[ApiResource(graphQlOperations: [
new QueryCollection(paginationType: 'page'),
])]
class Book {}
All the pagination* controls from pagination (items per page, max, partial)
apply to GraphQL collections too.
Real-time subscriptions
When a resource has mercure: true, GraphQL subscription operations push updates
through the Mercure hub — see mercure.
Laravel
GraphQL is supported on Laravel. The operation classes (Query, QueryCollection,
Mutation, DeleteMutation), security expressions, Relay connections,
paginationType, custom resolvers and the N+1 caveats are all the same. Differences:
- Install
composer require api-platform/graphql, then enable it inconfig/api-platform.phpundergraphql('enabled' => true) — not YAML. Depth/ complexity limits andgraphiqllive in the same config block. - Resolvers implement the same
QueryItemResolverInterface/QueryCollectionResolverInterface/MutationResolverInterfaceand are referenced by class-string on the operation; Laravel's container resolves them — there are noapi_platform.graphql.*_resolvertags to apply. - Real-time
subscriptionoperations depend on Mercure, which has no Laravel integration (see mercure), so GraphQL subscriptions are effectively Symfony-only.
Checklist
- GraphQL chosen for a real client requirement, not as a REST default
- Every
Mutation/DeleteMutationhas aname -
securityset on nested resources, not just the entry-point operation - Custom resolvers tagged (or autoconfigured) and referenced by class name
-
read: falseset when the resolver fetches its own data - Deep/nested queries checked for N+1; joins added on hot paths
-
paginationType: 'page'set only if the client doesn't want Relay connections
このスキルのファイル
1graphql skillに関する質問
Claude Codeにgraphql skillをインストールするには
npx degit api-platform/skillset/skills/graphql ~/.claude/skills/graphqlを実行してください。Claude Codeは~/.claude/skills(すべてのプロジェクト)または.claude/skills(単一プロジェクト)からskillsを読み込み、説明がタスクに一致する場合にskillを使用します。
graphql skillはどのクライアントで使用できますか
Agent Skills形式を読み込むすべてのクライアントで使用できます: Claude Code、Codex、Gemini CLI、claude.ai(ZIPとしてアップロード)。skill内のスクリプトは、クライアントがコード実行を許可した場合にのみ実行されます。
API PlatformでGraphQLを有効にするにはどうすればよいですか?
composer require api-platform/graphql を使用してパッケージをインストールし、設定ファイル(Symfonyの場合はYAML、Laravelの場合はPHP)で有効にします。
API PlatformにおけるGraphQLとRESTの違いは何ですか?
RESTは組み込みのHTTPキャッシュセマンティクス、操作ごとの予測可能なコスト、シンプルなCDNキャッシュを提供します。一方、GraphQLはクライアントが特定のフィールドを選択できますが、コストの高い深いリゾルバークエリにつながる可能性があります。
GraphQL操作にカスタムロジックを使用できますか?
はい、QueryItemResolverInterface、QueryCollectionResolverInterface、またはMutationResolverInterfaceを実装するサービスを作成することで、カスタムリゾルバーを実装できます。