Skip to main content
Version: 4.1

Custom Queries / Mutations

CoreShop Headless abstracts away the complexity of GraphQL and provides a simple API for developers to use. However, there are cases where you might want to write your own queries. For example, you might want to fetch custom entities or extend the default queries.

Extending Queries

CoreShop Headless provides a simple way to extend the default queries. You can extend the default queries by creating a new class that implements the CoreShop\Bundle\HeadlessBundle\Query\CommandQueryInterface Interface. For example:

CoreShop Headless uses Symfony Command Bus to execute the queries. So we need several things to make this work:

  1. A Command that gets the input parameters from the query
  2. A CommandHandler that handles the Command
  3. A CommandQuery that instantiates the Command and returns the result
  4. (Optional) if your query is a Mutation Query, add the Interface CoreShop\Bundle\HeadlessBundle\Query\CommandMutationQueryInterface.

Command

<?php

declare(strict_types=1);

namespace App\CoreShop\Headless\Command;

use CoreShop\Bundle\HeadlessBundle\Command\CommandInterface;

class MyCustomCommand implements CommandInterface
{
public function __construct(
public readonly string myArgument,
) {
}
}

Command Handler

<?php

declare(strict_types=1);

namespace App\CoreShop\Headless\CommandHandler;

use CoreShop\Bundle\HeadlessBundle\Command\MyCustomCommand;

class MyCustomHandler
{
public function __invoke(MyCustomCommand $myCustomCommand): string
{
return 'Hello World ' . $myCustomCommand->myArgument;
}
}

The handler needs to be registered as a service and tagged with messenger.message_handler and bus: coreshop_headless.bus:

services:
App\CoreShop\Headless\CommandHandler\MyCustomHandler:
tags:
- { name: messenger.message_handler, bus: coreshop_headless.bus }

Command Query

Lastly, we need to create the Command Query that creates the GraphQL Query, instantiates the Command and returns the result:

<?php

declare(strict_types=1);

namespace App\CoreShop\Headless\Query;

use CoreShop\Bundle\HeadlessBundle\Command\MyCustomCommand;
use CoreShop\Bundle\HeadlessBundle\Command\CommandInterface;
use CoreShop\Bundle\HeadlessBundle\InputType\ActiveOrderInputType;
use CoreShop\Bundle\HeadlessBundle\InputType\InputTypeFactoryInterface;
use CoreShop\Bundle\HeadlessBundle\Query\ClassRestrictedCommandQueryInterface;
use CoreShop\Bundle\HeadlessBundle\Query\CommandQueryInterface;
use CoreShop\Bundle\HeadlessBundle\Query\QueryHelper;
use GraphQL\Type\Definition\Type;

class MyCustomQuery implements CommandQueryInterface, ClassRestrictedCommandQueryInterface
{
public function getName(array $context, array $config): string
{
return 'MyCustomQuery';
}

public function getCommand(array $args, array $context, array $config): CommandInterface
{
return new MyCustomCommand($context['configuration']->getConfiguration()['general']['store']);
}

public function configureInputArguments(array $context, array $config): array
{
return [
'myArgument' => [
'type' => Type::string(),
],
];
}

public function configureResultFields(array $context, array $config): array
{
return ['myResult' => Type::string()];
}

public function prepareResult(mixed $result, array $context, array $config): array
{
return [
'myResult' => $result,
];
}
}

The Query needs to be registered as a service and tagged with coreshop.headless.command_query:

services:
App\CoreShop\Headless\Query\MyCustomQuery:
tags:
- { name: coreshop.headless.command_query }

Usage

query {
MyCustomQuery(myArgument: ":) My Argument") {
myResult
}
}

Voila, you have successfully extended the default queries.