π πΈοΈ TuskLang PHP GraphQL Guide
πΈοΈ 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! π