Download the PHP package le0daniel/graphql-tools without Composer

On this page you can find all versions of the php package le0daniel/graphql-tools. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package graphql-tools

GraphQl Tools

This is a simple opinionated toolkit for writing scalable code first GraphQL applications in PHP.

Main Features

Installation

Install via composer

Basic Usage

The usage is similar to how you would use webonyx/graphql and define object types. Instead of extending the default classes, you extend the abstract classes provided. Every resolve function is wrapped by the ProxyResolver class, which provides support for extensions.

At the core, we start with a schema registry. There you register types and register extensions to types.

Schema Registry

The schema registery is the central entity that contains all type definitions for a graphql schema.

You register types, extend types and then create a schema variation. Internally, a TypeRegistry is given to all types and fields, allowing you to seamlessly refer to other types in the schema. The type registry solves the problem that each type class is only instanced once per schema and lazily for best performance.

Loading all types in a directory

To simplify type registration, you can use the TypeMap utility to load all types in a directory. It uses Glob to find all PHP files. In production, you should cache those.

Aliases

In GraphQL, all types have a name. In a code first approach as described here, you define a class, which then creates a name. So in code, you have both the classname and the type name which is used in GraphQL. We automatically create aliases for the classnames. This allows you to reference other types either by their class name or the type name which is used in GraphQL.

Class names can be better to work with inside a module, as you can now statically analyse the class usages.

Creating a schema from the registry

The schema registries task is to create a schema from all registered types dynamically. You can hide and show schema variants by using schema rules. Rules are mostly based on tags. In contrast to using the visibility function, this is more transparent. You can print different Schema variants and use tools to verify the schema or breaking changes. A hidden field can not be queried by any user. This prevents data leakage.

Provided Rules:

You can define your own rules by implementing the SchemaRules interface.

Define Types

In a code first approach to graphql, each type is represented by a class in code.

Naming conventions and classes to extend:

Type ClassName Extends Example
Object Type [Name]Type GraphQlType AnimalType => type Animal
Input Type [Name]InputType GraphQlInputType CreateAnimalInputType => input type CreateAnimalInput
Interface Type [Name]Interface GraphQlInterface MammalInterface => interface Mammal
Union Type [Name]Union GraphQlUnion SearchResultUnion => union SearchResult
Scalar Type [Name]Scalar GraphQlScalar ByteScalar => scalar Byte
Directive Type [Name]Directive GraphQlDirective ExportVariablesDirective => directive ExportVariables

You can overwrite this behaviour by overwriting the getName function.

Defining Fields and InputFields

In a code first approach, the field definition and the resolve function live in the same place. The field builders allow you to easily construct fields with all required and possible attributes, combined with their resolvers, all in code directly.

Field builders are immutable, and thus flexible to use and reuse.

It attaches a ProxyResolver class to decorate your resolve function under the hood for extensions and Middlewares to work correctly.

To declare types and reference other types, a Type Registry is given to each instance where fields are defined. This allows you to reference other types that exist in your schema. The type registry itself takes care of lazy loading and ensures that every only one instance of a type is created in a schema.

Additionally, you can define Tags, which can be used to define visibility of fields in different schema variations. This is automatically created for you when you create a schema from the schema registry.

By default, the resolver is using the default resolve function from Webonyx (Executor::getDefaultFieldResolver()).

In its simplest form:

Broader Usage:

Reuse Fields

Creating reusable fields are easy. Create a function or method that returns a field, then it can be used everywhere.

When creating shared fields it is useful to use ofTypeResolver(). You can define a closure, taking the type registry as a first argument. This way, you don't need to pass the type registry down.

Cost

In GraphQL, a query can quickly be really expensive to compute, as you can navigate through deep relationships. To prevent users exceeding certain limits, you can limit the complexity a query can have.

Webonyx provides a way to calculate complexity ahead of executing the query. This is done via the MaxComplexityRule. For it to work, each field needs to define a complexity function.

We use the concept of cost, where each field defines its own cost statically and provide a helper to compute variable complexity based on arguments.

In this example we see both components:

As in the worst case, all 5 entities are loaded from a DataBase, this needs to be taken into account when determining the max cost of the query. Example:

To represent such dynamic costs, you can pass a closure as a second parameter. The return of it will be used to multiply the cost of all children by.

Note: Cost is used to determine the worst case cost of a query. If you want to collect the actual cost, use the ActualCostExtension. It hooks into resolvers and aggregates the cost of fields that were actually present in the query.

Middleware

A middleware is a function that is executed before and after the real resolve function is called. It follows an onion principle. Outer middlewares are called first and invoke the level deeper. You can define multiple middleware functions to prevent data leakage on a complete type or on specific fields.

Middlewares can be defined for a type (applying to all fields) or to a fields. You need to call $next(...) to invoke the next layer.

Middlewares allow you to manipulate data that is passed down to the actual field resolver and then the actual result of the resolver. For example, you can use a middleware to validate arguments before the actual resolve function is called.

Signature

Usage You can define multiple middleware for a type (Those middlewares are then pretended to all Fields of that type) or only specific fields.

Extending Types

Extending types and interfaces allows you to add one or many fields to a type outside from its base declaration. This is usually the case when you don't want to cross domain boundaries, but need to add additional fields to another type. This allows you to stitch a schema together.

The simplest way is to use the schema registry and extend an object type or interface, passing a closure that declares additional fields.

Using Classes

Our approach allows to use classes, similar to types, that define type extensions.

ClassName naming patterns for lazy registration to work correctly: Extends[TypeOrInterfaceName](Type|Interface) Examples:

Federation Middleware

To decouple and remove references to the complete data object in the resolver, a Federation middleware is provided.

2 Middlewares are provided:

  1. Federation::key('id'), extracts the id property of the data object/array
  2. Federation::field('id'), runs the resolver of the field id

Query execution (QueryExecutor)

The query executor is used to execute a query. It attaches Extensions and Validation Rules, handles error mapping and logging.

Extensions: Classes that can drop in to the execution of the query and listen to events. They do not change the result of the query but can collect valuable telemetry data. They are contextual and a new instance is created for each query that is executed. Validation Rules: They validate the query before it is executed. They are not necessarily contextual. If a factory or classname is provided, a new instance is created for each query that is executed. Error Mapper: Receives an instance of Throwable and the corresponding GraphQl Error. It is tasked to map this to a Throwable that potentially implements ClientAware. This allows you to disconnect your internal exceptions from exceptions that you use in GraphQL. Error Logger: Receives an instance of Throwable before it is mapped. This allows you to log errors that occurred.

Extensions and ValidationRules

If you define a factory, it will get the context as argument. This allows you to dynamically create or attach them based on the user that is executing your query. If an extension of validation rule implements GraphQlTools\Contract\ProvidesResultExtension, you can add data to the extensions array of the result, according to the graphql spec.

Defer (@defer directive)

You can use and enable @defer extension by adding DeferExtension to your Query executor. It is highly recommended to also add the ValidateDeferUsageOnFields validation rule to limit how many defers are allowed per query.

To use it, behind the scenes, the query is run multiple times with cached results. This enables us to defer resolution of some fields to the consequent execution.

ValidationRules

We use the default validation rules from webonyx/graphql with an additional rule to collect deprecation notices.

You can define custom validation rules, by extending the default ValidationRule class from webonyx/graphql. If you additionally implement the ProvidesResultExtension, rules can add an entry to the extensions field in the result. Validation rules are executed before the query is actually run.

Extensions

Extensions are able to hook into the execution and collect data during execution. They allow you to collect traces or telemetry data. Extensions are not allowed to manipulate results of a field resolver. If you want to manipulate results, you need to use middlewares. Extensions are contextual and a new instance is created each time a query is run. You can define extensions by passing a classname to the query executor or a factory. To each factory, the current Context is passed in.

To define an extension, a class needs to implement the ExecutionExtension interface. Extensions can additionally implement ProvidesResultExtension and add entries to the extensions field in the result. The abstract class Extension implements some helper and general logic to build extensions easily.

Following events are provided:

Each event contains specific properties and the time of the event in nanoseconds.

During execution, extensions can hook into the resolve function of each resolver using the visitField hook. You can pass a closure back, which is executed once resolution is done. This is then executed after all promises are resolved, giving you access to the actual data resolved for a field. In case of a failure, a throwable is returned.


All versions of graphql-tools with dependencies

PHP Build Version
Package Version
Requires php Version ^8.2
webonyx/graphql-php Version ^15
google/protobuf Version ^3.19
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package le0daniel/graphql-tools contains the following files

Loading the files please wait ....