### Install Overblog GraphQL Bundle Source: https://github.com/overblog/graphqlbundle/blob/master/docs/definitions/quick-start.md Use Composer to install the bundle. Refer to the documentation for more details on installation. ```bash composer require overblog/graphql-bundle ``` -------------------------------- ### Install OverblogGraphQLBundle Source: https://context7.com/overblog/graphqlbundle/llms.txt Install the bundle using Composer. The GraphiQL browser UI is optional and requires a separate development dependency. ```bash composer require overblog/graphql-bundle # Optional: GraphiQL browser UI composer require --dev overblog/graphiql-bundle ``` -------------------------------- ### Generated Configuration Example Source: https://github.com/overblog/graphqlbundle/blob/master/docs/definitions/builders/field.md The resulting GraphQL configuration generated from the field builder example. ```yaml Mutation: type: object config: fields: foo: type: 'FooPayload!' resolve: '@=mutation("Mutation.foo", [args["input"]])' args: input: {type: 'FooInput!'} FooInput: type: input-object config: fields: bar: {type: 'String!'} FooPayload: type: union config: types: ['FooSuccessPayload', 'FooFailurePayload'] resolveType: '@=query("PayloadTypeResolver", value, "FooSuccessPayload", "FooFailurePayload")' FooSuccessPayload: type: object config: fields: fooString: {type: 'String!'} FooFailurePayload: type: object config: fields: _error: {type: 'String'} bar: {type: 'String'} ``` -------------------------------- ### Relay Paginator Forward Pagination Example Source: https://context7.com/overblog/graphqlbundle/llms.txt Demonstrates using the `Paginator` class for forward pagination. It takes a callback to fetch data slices and uses `forward()` with `first` and `after` arguments to get a specific page. ```php forward(new Argument([ 'first' => 2, 'after' => base64_encode('arrayconnection:1'), // after "B" ])); // $result->edges[0]->node === 'C' // $result->edges[1]->node === 'D' // $result->pageInfo->hasNextPage === true ``` -------------------------------- ### Field Builder Configuration Example Source: https://github.com/overblog/graphqlbundle/blob/master/docs/definitions/builders/field.md Example of how to configure a field using a builder, specifying the builder class and its configuration. ```yaml Mutation: type: object config: fields: foo: builder: 'Mutation' builderConfig: name: 'Foo' resolver: 'Mutation.foo' inputFields: bar: {type: 'String!'} payloadFields: fooString: {type: 'String!'} ``` -------------------------------- ### Mutation Resolver Example (createShip) Source: https://context7.com/overblog/graphqlbundle/llms.txt Example of a PHP resolver class for handling the 'createShip' mutation. It implements MutationInterface and AliasedInterface. ```APIDOC ## Mutation Resolver: ShipMutation ### Class `App\GraphQL\Mutation\ShipMutation` ### Implements `MutationInterface`, `AliasedInterface` ### Constructor - **factionRepository**: `FactionRepository` ### Method - **createShip**(shipName: String!, factionId: Int!): array - Description: Creates a new ship and associates it with a faction. - Alias: `create_ship` - Returns: An array containing the created `ship` and the `faction`. ``` -------------------------------- ### Query Type Example Source: https://context7.com/overblog/graphqlbundle/llms.txt Example configuration for a Query type, demonstrating the use of built-in functions for field resolution and access control. ```APIDOC ```yaml # config/graphql/types/Query.types.yaml Query: type: object config: fields: me: type: "User!" # Requires authentication; uses current user resolve: "@=getUser()" access: "@=isAuthenticated()" settings: type: "Settings" # Access a Symfony service resolve: "@=service('App\\Service\\SettingsManager').getForUser(getUser())" debugMode: type: "Boolean!" # Read a container parameter resolve: "@=parameter('kernel.debug')" hero: type: "Character" args: episode: { type: "Episode" } # Call resolver alias with argument resolve: "@=query('character_hero', args['episode'])" ``` ``` -------------------------------- ### cURL Example for File Upload Source: https://context7.com/overblog/graphqlbundle/llms.txt Provides a `curl` command example for uploading a file to a GraphQL endpoint, demonstrating how to structure the request with operations and file mapping. ```bash # curl upload example curl 'http://localhost:8000/' \ -F operations='{"query":"mutation($file:Upload!){singleUpload(file:$file)}","variables":{"file":null}}' \ -F map='{"0":["variables.file"]}' \ -F 0=@/path/to/file.png ``` -------------------------------- ### Install GraphiQL Interface Bundle Source: https://github.com/overblog/graphqlbundle/blob/master/docs/index.md If you wish to use the GraphiQL interface for testing your GraphQL API, install this development bundle using Composer. ```bash composer require --dev overblog/graphiql-bundle ``` -------------------------------- ### Equivalent Configuration After Builder Application Source: https://github.com/overblog/graphqlbundle/blob/master/docs/definitions/builders/fields.md This YAML shows the expanded configuration equivalent to the previous example after the `Timestamped` builder has been applied. ```yaml User: type: object config: fields: createdAt: description: The creation date of the object type: Int! resolve: "@=value.dateCreated" updatedAt: description: The update date of the object type: Int! resolve: "@=value.updatedAt" ``` -------------------------------- ### Permission Check Example Source: https://github.com/overblog/graphqlbundle/blob/master/docs/definitions/type-inheritance.md This example shows how to define a permission check using a query function, specifying the attribute and subject for the permission. ```twig resolve: '@=query("Permission.nodeAttribute", "edit", value)' ``` -------------------------------- ### Example GraphQL Query for Relay Connection Source: https://context7.com/overblog/graphqlbundle/llms.txt An example GraphQL query demonstrating how to fetch paginated `friends` data using Relay connection arguments like `first` and `after`, and accessing `edges`, `node`, `cursor`, `pageInfo`, and `totalCount`. ```graphql # Example query { user { friends(first: 2, after: "YXJyYXljb25uZWN0aW9uOjA=") { edges { cursor node { name } friendshipTime } pageInfo { hasNextPage hasPreviousPage } totalCount } } } ``` -------------------------------- ### Define Human and Droid Classes Source: https://github.com/overblog/graphqlbundle/blob/master/docs/definitions/type-system/interface.md Example classes for Human and Droid, which will be used to demonstrate interface implementation. ```php class Human { public $id; public $name; public $friends; public $appearsIn; public $starships; public $totalCredits; // ... } class Droid { public $id; public $name; public $friends; public $appearsIn; public $primaryFunction; // ... } ``` -------------------------------- ### Query Resolver Example (findHuman) Source: https://context7.com/overblog/graphqlbundle/llms.txt Example of a PHP resolver class for handling 'findHuman' query. It implements QueryInterface and AliasedInterface for mapping. ```APIDOC ## Query Resolver: CharacterResolver ### Class `App\GraphQL\Resolver\CharacterResolver` ### Implements `QueryInterface`, `AliasedInterface` ### Constructor - **repo**: `CharacterRepository` ### Methods - **findHuman**(id: String!): ?array - Description: Finds a human by ID. - Alias: `character_human` - **resolveCharacterType**(value: mixed, typeResolver: TypeResolver) - Description: Resolves the GraphQL type for a given value. - Alias: `character_type` ``` -------------------------------- ### Field Builder Implementation Example Source: https://github.com/overblog/graphqlbundle/blob/master/docs/definitions/builders/field.md PHP implementation of a field builder that defines a mutation field with input and payload types. ```php ['type' => 'String'], ]; foreach ( eal_keys($inputFields) as $fieldName) { $failurePayloadFields[$fieldName] = ['type' => 'String']; } $payloadTypeName = $name.'Payload'; $payloadSuccessTypeName = $name.'SuccessPayload'; $payloadFailureTypeName = $name.'FailurePayload'; $inputTypeName = $name.'Input'; $field = [ 'type' => $payloadTypeName.'!', 'resolve' => ".sprintf('@=mutation(\"%s\", args[\"input\"])", $resolver), 'args' => [ 'input' => $inputTypeName.'!', ], ]; $types = [ $inputTypeName => [ 'type' => 'input-object', 'config' => [ 'fields' => $inputFields, ], ], $payloadTypeName => [ 'type' => 'union', 'config' => [ 'types' => [$payloadSuccessTypeName, $payloadFailureTypeName], 'resolveType' => ".sprintf('@=query(\"PayloadTypeResolver\", value, \"%s\", \"%s\")', $payloadSuccessTypeName, $payloadFailureTypeName), ], ], $payloadSuccessTypeName => [ 'type' => 'object', 'config' => [ 'fields' => $successPayloadFields, ], ], $payloadFailureTypeName => [ 'type' => 'object', 'config' => [ 'fields' => $failurePayloadFields, ], ], ]; return ['field' => $field, 'types' => $types]; } } ``` -------------------------------- ### Create Promise with PromiseAdapter Service Source: https://github.com/overblog/graphqlbundle/blob/master/docs/data-fetching/promise.md Use the injected `overblog_graphql.promise_adapter` service to create promises within your resolvers. This example demonstrates creating a promise that resolves with user data. ```php promiseAdapter = $promiseAdapter; } public function resolveQuery() { return $this->promiseAdapter->create(function (callable $resolve) { return $resolve(['name' => 'Luke']); }); } } ``` -------------------------------- ### Custom Relay Connection and Edge Classes Source: https://context7.com/overblog/graphqlbundle/llms.txt Example of using custom connection and edge classes with `ConnectionBuilder`. This allows for more control over the structure and data of the connection and its edges. ```php // Custom connection/edge classes use Overblog\GraphQLBundle\Relay\Connection\ConnectionBuilder; use Overblog\GraphQLBundle\Relay\Connection\Cursor\Base64CursorEncoder; $builder = new ConnectionBuilder( new Base64CursorEncoder(), function (iterable $edges, $pageInfo): FriendsConnection { $conn = new FriendsConnection($edges, $pageInfo); $conn->setTotalCount(count($edges)); return $conn; }, function (string $cursor, UserFriend $friend, int $index): FriendEdge { $edge = new FriendEdge($cursor, $friend->getUser()); $edge->setFriendshipTime($friend->getCreatedAt()); return $edge; } ); $paginator = new Paginator(fn($offset, $limit) => $repo->getSlice($offset), Paginator::MODE_RELAY, $builder); ``` -------------------------------- ### PHP Mutation Resolver Implementation Source: https://github.com/overblog/graphqlbundle/blob/master/docs/definitions/mutation.md Example PHP class implementing the mutation logic for 'create_ship'. It demonstrates how to access input arguments and return a payload conforming to 'IntroduceShipPayload'. ```APIDOC ## PHP Mutation Resolver ### Description Implements the `createShip` method to handle the `create_ship` mutation logic. ### Class ```php factionRepository = $factionRepository; } public function createShip(string $shipName, int $factionId): array { // `$shipName` has the value of `args['input']['shipName']` // `$factionId` has the value of `args['input']['factionId']` // Do something with `$shipName` and `$factionId` ... $ship = new Ship($shipName); $faction = $this->factionRepository->find($factionId); $faction->addShip($ship); // ... // Then returns our payload, it should fits `IntroduceShipPayload` type return [ 'ship' => $ship, 'faction' => $faction, ]; } /** * {@inheritdoc} */ public static function getAliases(): array { return [ // `create_ship` is the name of the mutation that you SHOULD use inside of your types definition // `createShip` is the method that will be executed when you call `@=mutation('create_ship')` 'createShip' => 'create_ship' ]; } } ``` ``` -------------------------------- ### Configure Default Field Resolver Globally Source: https://github.com/overblog/graphqlbundle/blob/master/UPGRADE.md Example of configuring a custom default field resolver service globally within the bundle configuration. ```yaml overblog_graphql: definitions: default_field_resolver: 'App\GraphQL\CustomResolver' ``` -------------------------------- ### Initialize rootValue with Current User Source: https://github.com/overblog/graphqlbundle/blob/master/docs/events/index.md Use the `graphql.pre_executor` event to set the `rootValue` argument before execution, for example, by providing the authenticated user. ```yaml App\EventListener\RootValueInitialization: tags: - { name: kernel.event_listener, event: graphql.pre_executor, method: onPreExecutor } ``` ```php token = $token; } public function onPreExecutor(ExecutorArgumentsEvent $event) { $event->setRootValue($this->token->getUser()); } } ``` -------------------------------- ### Configure Default Field Resolver Per Type Source: https://github.com/overblog/graphqlbundle/blob/master/UPGRADE.md Example of configuring a specific field resolver for a particular type within the bundle configuration. ```yaml MyType: type: object config: resolveField: 'App\GraphQL\MyTypeResolver::defaultFieldResolver' fields: name: {type: String} email: {type: String} ``` -------------------------------- ### Example: GraphQL Type with Annotations Source: https://github.com/overblog/graphqlbundle/blob/master/docs/attributes/index.md Define a GraphQL type and field using annotations. The `/** @GQL ype */` annotation marks the class, and `/** @GQL ield */` defines a field. ```php use Overblog\GraphQLBundle\Annotation as GQL; /** * @GQL\Type */ class MyType { /** * @GQL\Field(type="Int") */ protected $myField; } ``` -------------------------------- ### Equivalent Schema Definition Without Args Builder Source: https://github.com/overblog/graphqlbundle/blob/master/docs/definitions/builders/args.md This example shows the expanded schema definition that the 'Pager' args builder generates, illustrating the equivalent arguments for 'limit' and 'offset'. ```yaml foo: type: "object" config: fields: categories: type: "[String!]!" args: limit: type: "Int!" defaultValue: 20 offset: type: "Int!" defaultValue: 0 categories2: type: "[String!]!" args: limit: type: "Int!" defaultValue: 50 offset: type: "Int!" defaultValue: 0 ``` -------------------------------- ### GraphQL Response with Debug Information Source: https://github.com/overblog/graphqlbundle/blob/master/docs/definitions/debug/index.md This is an example of a GraphQL response when debug information is enabled, including execution time and memory usage. ```json { "data": [{"isEnabled": true}], "extensions": { "debug": { "executionTime": "40 ms", "memoryUsage": "1.00 MiB" } } } ``` -------------------------------- ### Custom isTypeOf Logic with Expression Language Source: https://github.com/overblog/graphqlbundle/blob/master/docs/definitions/type-system/interface.md Examples of using custom logic within the `isTypeOf` option, including calling static methods or service methods. ```yaml Human: type: object config: # Call a static method and pass the 'value' param to check its type isTypeOf: '@=call("App\\GraphQL\\TypeResolver::isHuman", [value])' # ... or even use a service isTypeOf: '@=service("my_service").isTypeOfHuman(value)' ``` -------------------------------- ### Timestamp Fields Builder Class Implementation Source: https://github.com/overblog/graphqlbundle/blob/master/docs/definitions/builders/fields.md Implement the `MappingInterface` to create a custom fields builder. This example defines `createdAt` and `updatedAt` fields, allowing configuration for property names. ```php [ 'description' => 'The creation date of the object', 'type' => 'Int!', 'resolve' => "@=value.$propertyCreatedAt", ], 'updatedAt' => [ 'description' => 'The update date of the object', 'type' => 'Int!', 'resolve' => "@=value.$propertyUpdatedAt", ], ]; } } ``` -------------------------------- ### Set Root Value Before Execution Source: https://context7.com/overblog/graphqlbundle/llms.txt Listen to the `graphql.pre_executor` event to set the root value before GraphQL execution. This example sets the authenticated user as the root value. ```php setRootValue($this->token->getUser()); } } ``` ```yaml App\EventListener\RootValueInitialization: tags: - { name: kernel.event_listener, event: graphql.pre_executor, method: onPreExecutor } ``` -------------------------------- ### Explicitly Defining Input Argument with Expression Language Source: https://github.com/overblog/graphqlbundle/blob/master/docs/attributes/arguments-transformer.md Manually define a mutation field and its arguments using annotations. This example demonstrates how to use the `call` expression function to invoke a service method, specifying the input argument type and using `arg` to pass the raw argument data. ```php namespace App\GraphQL\Type; use Overblog\GraphQLBundle\Annotation as GQL; class RootMutation { #[GQL\Field(type: "User", resolve: "@=call(service('UserRepository').createUser, arguments({input: 'UserRegisterInput'}, arg))")] #[GQL\Arg(name: "input", type: "UserRegisterInput")] public $createUser; } ``` -------------------------------- ### Creating a Custom Expression Function (json_decode) Source: https://github.com/overblog/graphqlbundle/blob/master/docs/definitions/expression-language.md Provides an example of creating a custom expression function equivalent to PHP's `json_decode`. This involves extending `ExpressionFunction` and registering the service with the `overblog_graphql.expression_function` tag. ```php forward( new Argument( [ 'first' => 1, 'after' => base64_encode('arrayconnection:2') ] ) ); var_dump($result->edges); ``` -------------------------------- ### Linking Validation Constraints to a Class (Doctrine Entity Example) Source: https://github.com/overblog/graphqlbundle/blob/master/docs/validation/index.md Demonstrates linking validation constraints to a Doctrine entity class. Note that validation context is not inherited, and validation methods will be called on ValidationNode objects. ```php namespace App\Entity; /** * @Assert\Callback("validate") */ class User { public static function validate() { // ... } } ``` -------------------------------- ### Defining GraphQL Type and Input with Fields Source: https://github.com/overblog/graphqlbundle/blob/master/docs/attributes/attributes-reference.md Demonstrates how to define a class as both a GraphQL Type and Input, with fields supporting different configurations. Fields on input types may be ignored if they are incompatible. ```php connectionFromArray([]); ``` -------------------------------- ### File Upload Scalar Type Source: https://context7.com/overblog/graphqlbundle/llms.txt Details the setup and usage of the `Upload` scalar type for handling file uploads in GraphQL mutations. ```APIDOC ## File Uploads ### Description The Overblog GraphQL bundle provides a scalar type `Upload` compatible with `apollo-upload-client`. Uploaded files are accessible as `Symfony\Component\HttpFoundation\File\UploadedFile` instances within your resolvers. ### Configuration 1. **Register the scalar type:** ```yaml Upload: type: custom-scalar config: scalarType: '@=newObject("Overblog\\GraphQLBundle\\Upload\\Type\\GraphQLUploadType")' ``` 2. **Use the `Upload` scalar in mutations:** ```yaml Mutation: type: object config: fields: singleUpload: type: "String!" resolve: "@=args['file'].getClientOriginalName()" args: file: { type: "Upload!" } multipleUpload: type: "[String!]!" resolve: "@=query('upload_handler', args['files'])" args: files: { type: "[Upload!]!" } ``` ### cURL Example for Single Upload ```bash curl 'http://localhost:8000/' \ -F operations='{"query":"mutation($file:Upload!){singleUpload(file:$file)}","variables":{"file":null}}' \ -F map='{"0":["variables.file"]}' \ -F 0=@/path/to/file.png ``` ``` -------------------------------- ### Configure Custom Promise Adapter Source: https://github.com/overblog/graphqlbundle/blob/master/docs/data-fetching/promise.md Configure the bundle to use a custom promise adapter service. Ensure the service implements the required PromiseAdapterInterface. ```yaml overblog_graphql: services: promise_adapter: "my.promise_adapter" ``` -------------------------------- ### Define Schema with YAML Configuration Source: https://context7.com/overblog/graphqlbundle/llms.txt Configure the main schema, specifying the root Query and Mutation types. List any types that cannot be auto-detected to ensure they are included in the schema. ```yaml overblog_graphql: definitions: schema: query: Query mutation: Mutation # Types unreachable by static analysis must be listed explicitly types: [Human, Droid] ``` -------------------------------- ### Get Current User Source: https://github.com/overblog/graphqlbundle/blob/master/docs/definitions/expression-language.md The `getUser` function retrieves the current user object from the security token storage. It can be used to access user properties. ```yaml @=getUser() ``` ```yaml @=getUser().firstName === 'adam' ``` -------------------------------- ### Configure Annotation Mapping Source: https://github.com/overblog/graphqlbundle/blob/master/docs/attributes/index.md Use the `annotation` mapping type in `graphql.yaml` for annotation-based definitions. Ensure `symfony/cache` and `doctrine/annotation` are installed. Note: Annotations are deprecated. ```yaml overblog_graphql: definitions: mappings: types: - type: annotation dir: "%kernel.project_dir%/src/GraphQL" suffix: ~ ``` -------------------------------- ### Configure Type Mappings (YAML) Source: https://github.com/overblog/graphqlbundle/blob/master/docs/definitions/type-system/index.md Define custom directories and file suffixes for YAML type definitions. Supports multiple types from the same directory. ```yaml overblog_graphql: definitions: mappings: # auto_discover: false # to disable bundles and root dir auto discover types: - type: yaml # or graphql or annotation null dir: "%kernel.root_dir%/.../mapping" # sub directories are also searched # suffix: .types # use to change default file suffix - types: [yaml, graphql] # to include different types from the same dir dir: "%kernel.root_dir%/.../mapping" ``` -------------------------------- ### Validation Translation Resource (Structured) Source: https://github.com/overblog/graphqlbundle/blob/master/docs/validation/index.md Provide translations for validation messages in a structured YAML format. This example shows translations for username and password validation rules. ```yaml # translations\validators.en.yaml register: username: length: min: "The username should have {{ length }} characters or more" max: "The username should have {{ length }} characters or less" password: identical: "The passwords are not equal." length: min: "The password should have {{ length }} characters or more" max: "The password should have {{ length }} characters or less" ``` -------------------------------- ### Registering Private Services for Expression Language Source: https://github.com/overblog/graphqlbundle/blob/master/docs/definitions/expression-language.md Demonstrates how to tag a private service to make it accessible via the expression language's `service` function. This is necessary because private services are not directly retrievable from the service container. ```yaml App\MyPrivateService: public: false tags: - { name: overblog_graphql.service, alias: my_private_service } ``` ```yaml MyType: type: object config: fields: name: type: String! resolve: "@=service('my_private_service').formatName(value)" ``` -------------------------------- ### Implement Args Builder Class Source: https://github.com/overblog/graphqlbundle/blob/master/docs/definitions/builders/args.md Create a PHP class that implements the `MappingInterface` to define the structure and default values for your custom arguments. ```php [ 'type' => 'Int!', 'defaultValue' => $defaultLimit, ], 'offset' => [ 'type' => 'Int!', 'defaultValue' => 0, ], ]; } } ``` -------------------------------- ### Customize Field Complexity Source: https://github.com/overblog/graphqlbundle/blob/master/docs/security/query-complexity-analysis.md Define custom complexity for specific fields within your GraphQL schema. This example adds a base complexity of 1000 to the `droid` field. ```yaml #src/MyBundle/Resources/config/graphql/Query.types.yml Query: type: object config: fields: droid: type: "Droid" complexity: '@=1000 + childrenComplexity' args: id: description: "id of the droid" type: "String!" resolve: "@=query('character_droid', args)" ``` -------------------------------- ### Define Custom Field Builder in YAML Source: https://context7.com/overblog/graphqlbundle/llms.txt Configure a custom field builder in `graphql.yaml` to automatically add fields to your GraphQL types. This example adds timestamp fields. ```yaml overblog_graphql: definitions: builders: fields: - alias: "Timestamped" class: "App\GraphQL\Builder\TimestampFields" ``` -------------------------------- ### Basic Resolver Usage Source: https://github.com/overblog/graphqlbundle/blob/master/docs/helpers/relay-paginator.md Integrate the Paginator within a resolver to handle data fetching and pagination logic. It requires a data backend and a callback for counting total items. ```php getData($offset, $limit); }); return $paginator->auto($args, function() use ($backend) { return $backend->countAll(); }); } } ``` -------------------------------- ### GraphQL Schema Definition Source: https://context7.com/overblog/graphqlbundle/llms.txt Defines GraphQL types, interfaces, enums, and inputs. This example includes a Character interface, Human type, Episode enum, and a CreateCharacterInput for mutations. ```APIDOC ## GraphQL Schema Definition ### Interface: Character - **id**: ID! - **name**: String! - **friends**: [Character] - **appearsIn**: [Episode]! ### Type: Human (implements Character) - **id**: ID! - **name**: String! - **friends**: [Character] - **appearsIn**: [Episode]! - **totalCredits**: Int ### Enum: Episode - NEWHOPE - EMPIRE - JEDI ### Input: CreateCharacterInput - **name**: String! ### Mutation: RootMutation - **createCharacter**(character: CreateCharacterInput!): Character! ``` -------------------------------- ### GraphQL Schema Compiled Event Subscriber Source: https://github.com/overblog/graphqlbundle/blob/master/docs/events/index.md Implement `EventSubscriberInterface` to listen for the `SchemaCompiledEvent` and perform actions when the schema is newly compiled. This example shows a subscriber for schema dumping. ```php newObject(string $className, array $args = []): object ### Examples ```yaml @=newObject("App\\Entity\\User", ["John", 15]) # Using inside another function (query) @=query("myResolver", newObject("App\\User\\User", [args])) ``` ``` -------------------------------- ### Define a Mutation with Arguments Source: https://github.com/overblog/graphqlbundle/blob/master/docs/attributes/attributes-reference.md Define a mutation field within a provider class using `#[GQL ield]` and specify its arguments with `#[GQL ield]`. ```php repository->find($id); $user->setEmail($newEmail); $this->repository->save($user); return $user; } ``` -------------------------------- ### Implement Custom Scalar Logic in PHP Source: https://github.com/overblog/graphqlbundle/blob/master/docs/definitions/type-system/scalars.md Implement the serialize, parseValue, and parseLiteral methods for a custom scalar type in PHP. This example demonstrates handling DateTime objects. ```php format('Y-m-d H:i:s'); } /** * @param mixed $value * * @return \DateTimeInterface */ public static function parseValue($value) { return new \DateTimeImmutable($value); } /** * @param Node $valueNode * * @return \DateTimeInterface */ public static function parseLiteral(Node $valueNode) { return new \DateTimeImmutable($valueNode->value); } } ``` -------------------------------- ### Configure GraphiQL JavaScript Libraries Source: https://github.com/overblog/graphqlbundle/blob/master/UPGRADE.md When migrating from the old GraphiQL integration, move the JavaScript library versions from `overblog_graphql` to `overblog_graphiql` configuration. ```yaml overblog_graphql: - versions: - graphiql: "0.11" - react: "15.6" - fetch: "2.0" - relay: "classic" overblog_graphiql: + javascript_libraries: + graphiql: "0.11" + react: "15.6" + fetch: "2.0" ``` -------------------------------- ### Equivalent Schema Definition (Simple) Source: https://github.com/overblog/graphqlbundle/blob/master/docs/definitions/builders/field.md This YAML demonstrates the expanded schema definition equivalent to using the 'RawId' builder without specific configuration, showing the default 'id' name and 'Int!' type. ```yaml User: type: object config: fields: rawId: description: 'The user raw id' type: 'Int!' resolve: '@=value.id' ``` -------------------------------- ### Configure GraphQL Bundle (Attribute Mapping) Source: https://context7.com/overblog/graphqlbundle/llms.txt Configure the bundle to use PHP attributes for defining GraphQL types. Specify the directory where your annotated classes are located. ```yaml overblog_graphql: definitions: mappings: types: - type: attribute dir: "%kernel.project_dir%/src/GraphQL" suffix: ~ ``` -------------------------------- ### Mutation Configuration (IntroduceShip) Source: https://context7.com/overblog/graphqlbundle/llms.txt YAML configuration for the 'IntroduceShip' mutation, defining its payload, input type, and resolver. ```APIDOC ## Mutation Configuration ### Mutation: IntroduceShip - **Type**: IntroduceShipPayload! - **Resolver**: `@=mutation('create_ship', args['input']['shipName'], args['input']['factionId'])` - **Arguments**: - **input**: IntroduceShipInput! ### Type: IntroduceShipPayload - **ship**: Ship - **faction**: Faction ### Input: IntroduceShipInput - **shipName**: String! - **factionId**: String! ``` -------------------------------- ### Registering and Using the Upload Scalar Type Source: https://context7.com/overblog/graphqlbundle/llms.txt Details the steps to register the `Upload` scalar type for handling file uploads and demonstrates its usage in mutations for single and multiple file uploads. ```yaml # 1. Register the upload scalar Upload: type: custom-scalar config: scalarType: '@=newObject("Overblog\\GraphQLBundle\\Upload\\Type\\GraphQLUploadType")' # 2. Use the scalar in your mutation Mutation: type: object config: fields: singleUpload: type: "String!" resolve: "@=args['file'].getClientOriginalName()" args: file: { type: "Upload!" } multipleUpload: type: "[String!]!" resolve: "@=query('upload_handler', args['files'])" args: files: { type: "[Upload!]!" } ``` -------------------------------- ### GraphQL Configuration for Validation Linking (Doctrine Entity) Source: https://github.com/overblog/graphqlbundle/blob/master/docs/validation/index.md Configure GraphQL to link validation constraints from a Doctrine entity. This example shows linking to the User class, which has a static 'validate' method. ```yaml Mutation: type: object config: fields: createUser: validation: App\Entity\User # linking resolve: "@=res('createUser', [args])" # ... ``` -------------------------------- ### Access Service with Expression Language Source: https://github.com/overblog/graphqlbundle/blob/master/docs/definitions/expression-language.md Use the 'service' function to retrieve a service from the container. The 'serv' alias can also be used. Ensure private services are explicitly tagged if needed. FQCN usage requires careful quoting. ```yaml @=service('my_service').customMethod() ``` ```yaml # Using the 'serv' alias @=serv('my_service').customMethod() ``` ```yaml # Using the FQCN for the service name (only works for public services). # Note the double quotes. @=serv("App\\Manager\\UserManager").someMethod() ``` ```yaml # If using single quotes, you must use 4 slashes @=serv('App\\\\Manager\\\\UserManager').someMethod() ``` -------------------------------- ### GraphQL Configuration for Validation Linking (Explicit) Source: https://github.com/overblog/graphqlbundle/blob/master/docs/validation/index.md Configure GraphQL fields to link to validation constraints defined in a PHP class. This example shows explicit linking to the class, a property, and a getter. ```yaml Mutation: type: object config: fields: editPost: type: Post resolve: "@=mutation('edit_post', [args])" validation: link: App\Entity\Post # targeting the class args: title: type: String! validation: link: App\Entity\Post::title # property and getters text: type: String! validation: link: App\Entity\Post::$text # only property ``` -------------------------------- ### Manual Validation in Resolver Source: https://context7.com/overblog/graphqlbundle/llms.txt Demonstrates how to manually inject and use the `InputValidator` service within a mutation resolver to perform validation. ```APIDOC ## Manual Validation Example ### Description This example shows how to use the `InputValidator` service within a mutation resolver to validate input arguments. The validator can be configured to validate specific groups or all default constraints. Validation failures will result in an `ArgumentsValidationException`. ### Resolver Signature `register(Argument $args, InputValidator $validator): User` ### Validation Usage - `$validator->validate('registration');` : Validates constraints in the 'registration' group. - `$validator->validate();` : Validates constraints in the default group. - `$validator->validate(null, false);` : Returns a `ConstraintViolationList` instead of throwing an exception. ``` -------------------------------- ### Apply Timestamped Builder to a GraphQL Type Source: https://context7.com/overblog/graphqlbundle/llms.txt Configure a GraphQL `Post` type in YAML to use the `Timestamped` builder. This example shows how to specify custom property names for `createdAt` and `updatedAt`. ```yaml # Generates createdAt and updatedAt fields on Post Post: type: object config: builders: - builder: Timestamped builderConfig: propertyCreatedAt: created propertyUpdatedAt: updated fields: title: { type: "String!" } ``` -------------------------------- ### Use Upload Scalar in Schema (YAML) Source: https://github.com/overblog/graphqlbundle/blob/master/docs/definitions/upload-files.md Utilize the defined upload scalar type in your GraphQL schema mutations. This example shows how to define arguments for single and multiple file uploads. ```yaml Mutation: type: object config: fields: singleUpload: type: String! resolve: '@=args["file"].getBasename()' args: file: MyUpload! multipleUpload: type: '[String!]' resolve: '@=[args["files"][0].getBasename(), args["files"][1].getBasename()]' args: files: '[MyUpload!]!' ``` -------------------------------- ### Create New Object Instance Source: https://github.com/overblog/graphqlbundle/blob/master/docs/definitions/expression-language.md Use `newObject` to create a new class instance with specified arguments. This function utilizes PHP's Reflection API. ```yaml @=newObject("App\\Entity\\User", ["John", 15]) ``` ```yaml @=query("myResolver", newObject("App\\User\\User", [args])) ``` -------------------------------- ### Define a Custom Resolver Map Source: https://github.com/overblog/graphqlbundle/blob/master/docs/definitions/resolver-map.md Extend the ResolverMap class to define custom resolvers for your GraphQL schema. This example shows how to map fields for Query, Object, and custom scalar types. ```php [ self::RESOLVE_FIELD => function ($value, ArgumentInterface $args, \ArrayObject $context, ResolveInfo $info) { if ('baz' === $info->fieldName) { $id = (int) $args['id']; return findBaz('baz', $id); } return null; }, 'bar' => [Bar::class, 'getBar'], ], 'Foo' => [ self::RESOLVE_TYPE => function ($value) { return isset($value['user']) ? 'Bar' : null; }, ], // enum internal values 'User' => [ 'TATA' => 1, 'TITI' => 2, 'TOTO' => 3, ], // custom scalar 'Baz' => [ self::SERIALIZE => function ($value) { return sprintf('%s Formatted Baz', $value); }, self::PARSE_VALUE => function ($value) { if (!is_string($value)) { throw new Error(sprintf('Cannot represent following value as a valid Baz: %s.', Utils::printSafeJson($value))); } return str_replace(' Formatted Baz', '', $value); }, self::PARSE_LITERAL => function ($valueNode) { if (!$valueNode instanceof StringValueNode) { throw new Error('Query error: Can only parse strings got: '.$valueNode->kind, [$valueNode]); } return str_replace(' Formatted Baz', '', $valueNode->value); }, ], // or reuse an existing scalar (note: description and name will be override by decorator) //'Baz' => [self::SCALAR_TYPE => function () { return new FooScalarType(); }], ]; } } ``` -------------------------------- ### Enrich Error Objects with Custom Codes Source: https://context7.com/overblog/graphqlbundle/llms.txt Listen to the `graphql.error_formatting` event to modify how errors are formatted in the response. This example adds a custom 'code' field to errors, derived from the previous exception or the error itself. ```php getError(); $code = $error->getPrevious() ? $error->getPrevious()->getCode() : $error->getCode(); $event->getFormattedError()->offsetSet('code', $code); } } // Response errors[]: { "message": "...", "code": 404, "category": "user" } ``` ```yaml App\EventListener\ErrorCode: tags: - { name: kernel.event_listener, event: graphql.error_formatting, method: onErrorFormatting } ``` -------------------------------- ### Configure GraphQL Bundle (Single Endpoint) Source: https://context7.com/overblog/graphqlbundle/llms.txt Configure the bundle to use YAML for schema definitions and set up a single GraphQL endpoint in your Symfony application. ```yaml overblog_graphql: definitions: schema: query: Query mutation: Mutation mappings: types: - type: yaml dir: "%kernel.project_dir%/config/graphql/types" suffix: ~ ``` ```yaml overblog_graphql_single_endpoint: resource: "@OverblogGraphQLBundle/Resources/config/routing/single.yaml" prefix: / ``` -------------------------------- ### Create Promise with ReactPHP/Promise Source: https://github.com/overblog/graphqlbundle/blob/master/docs/data-fetching/promise.md Instantiate a native ReactPHP Promise directly within your resolver. This approach is suitable when using the ReactPHP/Promise adapter. ```php 'Luke']); }); } } ``` -------------------------------- ### Update Resolver Interface Import Source: https://github.com/overblog/graphqlbundle/blob/master/UPGRADE.md Shows the necessary change in import statements when renaming ResolverInterface to QueryInterface. ```diff - use Overblog\GraphQLBundle\Definition\Resolver\ResolverInterface; + use Overblog\GraphQLBundle\Definition\Resolver\QueryInterface; - class UserResolver implements ResolverInterface + class UserQuery implements QueryInterface { // ... } ```