🐘 πŸ•ΈοΈ TuskLang PHP GraphQL Guide

PHP Documentation

πŸ•ΈοΈ TuskLang PHP GraphQL Guide

"We don't bow to any king" - PHP Edition

Master TuskLang GraphQL in PHP! This guide covers schema definition, resolvers, mutations, subscriptions, and GraphQL patterns that will make your APIs flexible, efficient, and developer-friendly.

🎯 GraphQL Overview

TuskLang provides sophisticated GraphQL features that transform your REST APIs into flexible, type-safe query systems. This guide shows you how to implement enterprise-grade GraphQL while maintaining TuskLang's power.

<?php
// config/graphql-overview.tsk
[graphql_features]
schema_definition: @graphql.schema.define(@request.schema_config)
resolver_registration: @graphql.resolver.register(@request.resolver_config)
subscription_setup: @graphql.subscription.setup(@request.subscription_config)
introspection: @graphql.introspection.enable(@request.introspection_config)

πŸ“‹ Schema Definition

Basic Schema

<?php
// config/graphql-schema-basic.tsk
[graphql_schema]

Basic GraphQL schema definition

schema: @graphql.schema({ "query": "Query", "mutation": "Mutation", "subscription": "Subscription" })

[type_definitions]

Type definitions

user_type: @graphql.type("User", { "fields": { "id": "ID!", "name": "String!", "email": "String!", "created_at": "DateTime!", "posts": "[Post!]!" } })

post_type: @graphql.type("Post", { "fields": { "id": "ID!", "title": "String!", "content": "String!", "author": "User!", "created_at": "DateTime!", "comments": "[Comment!]!" } })

comment_type: @graphql.type("Comment", { "fields": { "id": "ID!", "content": "String!", "author": "User!", "post": "Post!", "created_at": "DateTime!" } })

Advanced Schema

<?php
// config/graphql-schema-advanced.tsk
[advanced_schema]

Advanced schema with interfaces and unions

node_interface: @graphql.interface("Node", { "fields": { "id": "ID!" } })

search_result_union: @graphql.union("SearchResult", { "types": ["User", "Post", "Comment"] })

[input_types]

Input types

user_input: @graphql.input("UserInput", { "fields": { "name": "String!", "email": "String!", "password": "String!" } })

post_input: @graphql.input("PostInput", { "fields": { "title": "String!", "content": "String!", "author_id": "ID!" } })

[enums]

Enums

user_role: @graphql.enum("UserRole", { "values": ["ADMIN", "MODERATOR", "USER", "GUEST"] })

post_status: @graphql.enum("PostStatus", { "values": ["DRAFT", "PUBLISHED", "ARCHIVED", "DELETED"] })

πŸ” Query Resolvers

Basic Query Resolvers

<?php
// config/graphql-query-resolvers.tsk
[query_type]

Query type definition

query_type: @graphql.type("Query", { "fields": { "user": "User", "users": "[User!]!", "post": "Post", "posts": "[Post!]!", "search": "[SearchResult!]!" } })

[query_resolvers]

Query resolvers

user_resolver: @graphql.resolver("Query.user", { "args": {"id": "ID!"}, "resolve": @php("UserResolver::getUser"), "cache": true, "cache_ttl": 300 })

users_resolver: @graphql.resolver("Query.users", { "args": { "limit": "Int", "offset": "Int", "role": "UserRole" }, "resolve": @php("UserResolver::getUsers"), "pagination": true })

post_resolver: @graphql.resolver("Query.post", { "args": {"id": "ID!"}, "resolve": @php("PostResolver::getPost"), "cache": true, "cache_ttl": 600 })

posts_resolver: @graphql.resolver("Query.posts", { "args": { "limit": "Int", "offset": "Int", "status": "PostStatus", "author_id": "ID" }, "resolve": @php("PostResolver::getPosts"), "pagination": true })

Advanced Query Resolvers

<?php
// config/graphql-query-resolvers-advanced.tsk
[advanced_resolvers]

Advanced query resolvers

search_resolver: @graphql.resolver("Query.search", { "args": { "query": "String!", "types": "[String!]", "limit": "Int" }, "resolve": @php("SearchResolver::search"), "complexity": @graphql.complexity({ "multiplier": 10, "field": "results" }) })

[field_resolvers]

Field resolvers

user_posts_resolver: @graphql.resolver("User.posts", { "args": { "limit": "Int", "status": "PostStatus" }, "resolve": @php("UserResolver::getUserPosts"), "dataloader": "user_posts" })

post_comments_resolver: @graphql.resolver("Post.comments", { "args": { "limit": "Int", "order_by": "CommentOrderBy" }, "resolve": @php("PostResolver::getPostComments"), "dataloader": "post_comments" })

✏️ Mutation Resolvers

Basic Mutations

<?php
// config/graphql-mutation-resolvers.tsk
[mutation_type]

Mutation type definition

mutation_type: @graphql.type("Mutation", { "fields": { "createUser": "User!", "updateUser": "User!", "deleteUser": "Boolean!", "createPost": "Post!", "updatePost": "Post!", "deletePost": "Boolean!", "createComment": "Comment!", "updateComment": "Comment!", "deleteComment": "Boolean!" } })

[mutation_resolvers]

Mutation resolvers

create_user_mutation: @graphql.resolver("Mutation.createUser", { "args": {"input": "UserInput!"}, "resolve": @php("UserMutation::createUser"), "auth": "required", "validation": @graphql.validation({ "rules": { "input.name": "required|min:2|max:50", "input.email": "required|email|unique:users,email", "input.password": "required|min:8" } }) })

update_user_mutation: @graphql.resolver("Mutation.updateUser", { "args": { "id": "ID!", "input": "UserInput!" }, "resolve": @php("UserMutation::updateUser"), "auth": "required", "permission": "users:write" })

delete_user_mutation: @graphql.resolver("Mutation.deleteUser", { "args": {"id": "ID!"}, "resolve": @php("UserMutation::deleteUser"), "auth": "required", "permission": "users:delete" })

Advanced Mutations

<?php
// config/graphql-mutation-resolvers-advanced.tsk
[advanced_mutations]

Advanced mutation resolvers

bulk_create_users: @graphql.resolver("Mutation.bulkCreateUsers", { "args": {"inputs": "[UserInput!]!"}, "resolve": @php("UserMutation::bulkCreateUsers"), "auth": "required", "permission": "users:write", "transaction": true })

upload_user_avatar: @graphql.resolver("Mutation.uploadUserAvatar", { "args": { "id": "ID!", "file": "Upload!" }, "resolve": @php("UserMutation::uploadAvatar"), "auth": "required", "file_upload": true, "max_file_size": "5MB" })

[subscription_mutations]

Subscription-related mutations

publish_post: @graphql.resolver("Mutation.publishPost", { "args": {"input": "PostInput!"}, "resolve": @php("PostMutation::publishPost"), "auth": "required", "publish_event": "post.published" })

πŸ“‘ Subscription Resolvers

Basic Subscriptions

<?php
// config/graphql-subscription-resolvers.tsk
[subscription_type]

Subscription type definition

subscription_type: @graphql.type("Subscription", { "fields": { "userCreated": "User!", "userUpdated": "User!", "userDeleted": "ID!", "postPublished": "Post!", "commentAdded": "Comment!" } })

[subscription_resolvers]

Subscription resolvers

user_created_subscription: @graphql.resolver("Subscription.userCreated", { "resolve": @php("UserSubscription::userCreated"), "subscribe": @php("UserSubscription::subscribeToUserCreated"), "filter": @php("UserSubscription::filterUserCreated") })

user_updated_subscription: @graphql.resolver("Subscription.userUpdated", { "resolve": @php("UserSubscription::userUpdated"), "subscribe": @php("UserSubscription::subscribeToUserUpdated"), "filter": @php("UserSubscription::filterUserUpdated") })

post_published_subscription: @graphql.resolver("Subscription.postPublished", { "resolve": @php("PostSubscription::postPublished"), "subscribe": @php("PostSubscription::subscribeToPostPublished"), "filter": @php("PostSubscription::filterPostPublished") })

Advanced Subscriptions

<?php
// config/graphql-subscription-resolvers-advanced.tsk
[advanced_subscriptions]

Advanced subscription resolvers

user_activity_subscription: @graphql.resolver("Subscription.userActivity", { "args": {"user_id": "ID!"}, "resolve": @php("UserSubscription::userActivity"), "subscribe": @php("UserSubscription::subscribeToUserActivity"), "auth": "required", "rate_limit": 100 })

[real_time_subscriptions]

Real-time subscriptions

live_chat_subscription: @graphql.resolver("Subscription.liveChat", { "args": {"room_id": "ID!"}, "resolve": @php("ChatSubscription::liveChat"), "subscribe": @php("ChatSubscription::subscribeToLiveChat"), "websocket": true, "persistent": true })

πŸ”„ Data Loaders

Basic Data Loaders

<?php
// config/graphql-dataloaders.tsk
[data_loaders]

Data loaders configuration

user_loader: @graphql.dataloader({ "name": "user_loader", "batch_load": @php("UserDataLoader::batchLoad"), "cache": true, "cache_ttl": 300 })

post_loader: @graphql.dataloader({ "name": "post_loader", "batch_load": @php("PostDataLoader::batchLoad"), "cache": true, "cache_ttl": 600 })

comment_loader: @graphql.dataloader({ "name": "comment_loader", "batch_load": @php("CommentDataLoader::batchLoad"), "cache": true, "cache_ttl": 300 })

Advanced Data Loaders

<?php
// config/graphql-dataloaders-advanced.tsk
[advanced_data_loaders]

Advanced data loaders

user_posts_loader: @graphql.dataloader({ "name": "user_posts_loader", "batch_load": @php("UserPostsDataLoader::batchLoad"), "cache": true, "cache_ttl": 300, "cache_key": @php("UserPostsDataLoader::getCacheKey") })

post_comments_loader: @graphql.dataloader({ "name": "post_comments_loader", "batch_load": @php("PostCommentsDataLoader::batchLoad"), "cache": true, "cache_ttl": 300, "cache_key": @php("PostCommentsDataLoader::getCacheKey") })

[optimized_loaders]

Optimized data loaders

nested_loader: @graphql.dataloader.nested({ "name": "nested_loader", "loaders": ["user_loader", "post_loader", "comment_loader"], "optimize_queries": true, "batch_size": 100 })

πŸ” Authentication and Authorization

Authentication

<?php
// config/graphql-auth.tsk
[authentication]

Authentication configuration

jwt_auth: @graphql.auth.jwt({ "secret": @env("JWT_SECRET"), "algorithm": "HS256", "expiration": 3600, "refresh_token": true })

oauth2_auth: @graphql.auth.oauth2({ "provider": "google", "client_id": @env("GOOGLE_CLIENT_ID"), "client_secret": @env("GOOGLE_CLIENT_SECRET"), "scopes": ["email", "profile"] })

[authorization]

Authorization configuration

rbac: @graphql.auth.rbac({ "roles": { "admin": ["users:read", "users:write", "users:delete"], "moderator": ["users:read", "users:write"], "user": ["users:read", "posts:write"], "guest": ["users:read"] }, "permissions": { "users:read": ["admin", "moderator", "user", "guest"], "users:write": ["admin", "moderator"], "users:delete": ["admin"], "posts:write": ["admin", "moderator", "user"] } })

Field-Level Authorization

<?php
// config/graphql-field-auth.tsk
[field_authorization]

Field-level authorization

sensitive_fields: @graphql.auth.field({ "User.email": { "permission": "users:read_email", "roles": ["admin", "moderator"] }, "User.password_hash": { "permission": "users:read_password", "roles": ["admin"] }, "User.payment_info": { "permission": "users:read_payment", "roles": ["admin"], "owner_only": true } })

πŸ“Š Caching and Performance

Query Caching

<?php
// config/graphql-caching.tsk
[query_caching]

Query caching configuration

query_cache: @graphql.cache({ "enabled": true, "driver": "redis", "ttl": 300, "max_size": 1000, "invalidation": { "automatic": true, "patterns": [ "user:*", "post:*", "comment:*" ] } })

[field_caching]

Field-level caching

field_cache: @graphql.cache.field({ "User.posts": { "ttl": 600, "tags": ["user_posts"] }, "Post.comments": { "ttl": 300, "tags": ["post_comments"] } })

Performance Optimization

<?php
// config/graphql-performance.tsk
[performance_optimization]

Performance optimization

query_complexity: @graphql.complexity({ "max_complexity": 1000, "field_complexity": { "User.posts": 10, "Post.comments": 5, "Query.search": 20 } })

[query_analysis]

Query analysis

query_analysis: @graphql.analysis({ "depth_limit": 10, "cost_analysis": true, "query_logging": true, "slow_query_threshold": 1000 })

πŸ”„ Error Handling

Error Types

<?php
// config/graphql-errors.tsk
[error_types]

GraphQL error types

validation_error: @graphql.error("ValidationError", { "code": "VALIDATION_ERROR", "message": "Validation failed", "extensions": { "field": "String", "value": "String", "rule": "String" } })

authentication_error: @graphql.error("AuthenticationError", { "code": "UNAUTHENTICATED", "message": "Authentication required", "extensions": { "required_scopes": "[String!]" } })

authorization_error: @graphql.error("AuthorizationError", { "code": "FORBIDDEN", "message": "Insufficient permissions", "extensions": { "required_permissions": "[String!]", "user_permissions": "[String!]" } })

Error Handling

<?php
// config/graphql-error-handling.tsk
[error_handling]

Error handling configuration

global_error_handler: @graphql.error.handler({ "catch_all": @php("GraphQLErrorHandler::handle"), "log_errors": true, "include_stack_trace": @if(@env("APP_DEBUG") == "true", true, false) })

[field_error_handling]

Field-level error handling

field_error_handler: @graphql.error.field({ "User.posts": @php("UserErrorHandler::handlePostsError"), "Post.comments": @php("PostErrorHandler::handleCommentsError") })

πŸ“š Best Practices

GraphQL Best Practices

<?php
// config/graphql-best-practices.tsk
[best_practices]

GraphQL best practices

schema_design: @graphql.best_practice("schema_design", { "use_interfaces": true, "versioning": "field_level", "backward_compatibility": true })

naming_conventions: @graphql.best_practice("naming", { "types": "PascalCase", "fields": "camelCase", "enums": "SCREAMING_SNAKE_CASE" })

[anti_patterns]

GraphQL anti-patterns

avoid_over_fetching: @graphql.anti_pattern("over_fetching", { "use_pagination": true, "limit_field_selection": true, "implement_cursor_pagination": true })

avoid_under_fetching: @graphql.anti_pattern("under_fetching", { "use_data_loaders": true, "batch_queries": true, "optimize_resolvers": true })

πŸ“š Next Steps

Now that you've mastered TuskLang's GraphQL features in PHP, explore:

1. Advanced GraphQL Patterns - Implement sophisticated GraphQL patterns 2. Real-Time Subscriptions - Build real-time applications with GraphQL subscriptions 3. Schema Federation - Implement GraphQL schema federation 4. Performance Optimization - Advanced GraphQL performance techniques 5. Security Hardening - Advanced security patterns for GraphQL

πŸ†˜ Need Help?

- Documentation: https://tuskt.sk/documents/php/graphql - Examples: https://github.com/tusklang/php-examples - Community: https://community.tuskt.sk

---

Ready to build GraphQL APIs with TuskLang? You're now a TuskLang GraphQL master! πŸš€