PHPackages                             rdx/graphql-framework - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. rdx/graphql-framework

ActiveLibrary

rdx/graphql-framework
=====================

GraphQL framework layer on top of webonyx/graphql-php

0463[1 issues](https://github.com/rudiedirkx/graphql-framework/issues)PHP

Since Mar 9Pushed 2mo ago1 watchersCompare

[ Source](https://github.com/rudiedirkx/graphql-framework)[ Packagist](https://packagist.org/packages/rdx/graphql-framework)[ RSS](/packages/rdx-graphql-framework/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependenciesVersions (1)Used By (0)

This is a simple way to make `webonyx/graphql-php` more readable.

Set-up
------

[](#set-up)

You need to make a handler class:

```
class MyHandler extends GraphQLHandler {

	public function makeSchema() : Schema {
		return new \GraphQL\Type\Schema([
			'query' => GraphQLFactory::type(MyQueryType::class),
			'mutation' => GraphQLFactory::type(MyMutationType::class),
		]);
	}

	protected function isDebug() : bool {
		// Whether you want extra debug in your GraphQL response (next to `data` + `extensions`)
		return app()->ip() == '127.0.0.1';
	}

	protected function logInputError(string $label, string $input) : void {
		// Client sent invalid JSON: $input
	}

	protected function logInputQuery(string $label, array $input) : void {
		// Client sent correct JSON: $input
	}

	protected function getDebugQueries() : array {
		// If you want the response to contain runtime db queries
		return app()->queries();
	}

}
```

And if you want eager loading (you do), you need to define your framework/app's strategy:

```
class MyEager extends DeferredEager {

	protected function doLoadAll() : void {
		// Laravel:
		ModelCollection::make($this->queue)->load($this->field);

		// Other framework:
		$class = get_class($this->queue[0]);
		call_user_func([$class, 'eager'], $this->queue, $this->field);
	}

}
```

Controller
----------

[](#controller)

And then you can call it in the controller:

```
$context = new GraphQLContext();
$handler = new MyHandler($context);
$handler->execute();

return new JsonResponse($handler->getResult());
```

Types
-----

[](#types)

GraphQL is about types, and `webonyx/graphql-php` is not very user-friendly by default, so this is how you make types. It does help if you know how webonyx works.

Everything starts with `MyQueryType` from `MyHandler`:

```
class MyQueryType extends ParentObjectType {

	public function fields() : array {
		$fields = [];

		// Simple field:
		$fields['user'] = [
			'type' => GraphQLFactory::type(UserType::class),
			'resolve' => function() {
				return app()->user();
			},
		];

		// Complex field:
		$fields['users'] = GraphQLFactory::field(MyQueryUsersField::class);

		return $fields;
	}

}

class MyQueryUsersField extends ParentField {

	static public function type() : Type {
		return GraphQLFactory::type(UsersPagerType::class);
	}

	static public function args() : array {
		// All of these are optional:
		return [
			'ids' => Type::listOf(Type::nonNull(Type::int())),
			'organization' => Type::int(),
			'emails' => Type::listOf(Type::nonNull(Type::string())),
			'changed_after' => Type::int(),
			'status' => Type::int(),
		];
	}

	static public function argsMapper(array $args) : mixed {
		// If you want the above args to be a nice DTO, use argsMapper()
		return new UsersPagerArgs(...$args);
	}

	/**
	 * @return AssocArray
	 */
	static public function resolve(null $source, UsersPagerArgs $args, BrContext $context) : array {
		// $source is null, because this is a root field. Deeper fields have a mixed or YourDbalObject etc $source.

		// Use $args to make cool query
		$query = ...;

		// Return fields according to `UsersPagerType`.
		// Use fn() to lazy load: only execute if queried.
		return [
			'total' => fn() => $query->getCount(),
			'nodes' => fn() => $query->getRecords(),
		];
	}

}

class UsersPagerArgs {

	public function __construct(
		/** @var list */
		public array $ids = [],
		public int $organization = 0,
		/** @var list */
		public array $emails = [],
		public int $changed_after = 0,
		public int $status = 0,
	) {}

}
```

`UserType` and `UsersPagerType` are `ParentObjectType` again, with the same logic. Because `UserType`is so much simpler, another example:

```
class UserType extends ParentObjectType {

	public function fields() : array {
		// No resolvers, so webonyx's default resolver is used.
		return [
			'id' => Type::nonNull(Type::int()),
			'name' => Type::nonNull(Type::string()),
			'email' => Type::nonNull(Type::string()),
			'status' => Type::nonNull(Type::int()),
			'fav_color' => Type::string(),
		];
	}

}
```

`MyMutationType` works exactly the same as Query types.

###  Health Score

23

—

LowBetter than 27% of packages

Maintenance57

Moderate activity, may be stable

Popularity16

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity11

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

### Community

Maintainers

![](https://www.gravatar.com/avatar/78549c1dc5c83ec0201c9afc66762c6d5bbf770291b12bae5a7a65350f950dba?d=identicon)[rudiedirkx](/maintainers/rudiedirkx)

---

Top Contributors

[![rudiedirkx](https://avatars.githubusercontent.com/u/168024?v=4)](https://github.com/rudiedirkx "rudiedirkx (26 commits)")

### Embed Badge

![Health badge](/badges/rdx-graphql-framework/health.svg)

```
[![Health](https://phpackages.com/badges/rdx-graphql-framework/health.svg)](https://phpackages.com/packages/rdx-graphql-framework)
```

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
