Skip to main content
Version: Next

Inheritance and interfaces

Modeling inheritance

Some of your entities may extend other entities. GraphQLite will do its best to represent this hierarchy of objects in GraphQL using interfaces.

Let's say you have two classes, Contact and User (which extends Contact):

#[Type]
class Contact
{
// ...
}

#[Type]
class User extends Contact
{
// ...
}

Now, let's assume you have a query that returns a contact:

class ContactController
{
#[Query]
public function getContact(): Contact
{
// ...
}
}

When writing your GraphQL query, you are able to use fragments to retrieve fields from the User type:

contact {
name
... User {
email
}
}

Written in GraphQL type language, the representation of types would look like this:

interface ContactInterface {
// List of fields declared in Contact class
}

type Contact implements ContactInterface {
// List of fields declared in Contact class
}

type User implements ContactInterface {
// List of fields declared in Contact and User classes
}

Behind the scene, GraphQLite will detect that the Contact class is extended by the User class. Because the class is extended, a GraphQL ContactInterface interface is created dynamically.

The GraphQL User type will also automatically implement this ContactInterface. The interface contains all the fields available in the Contact type.

Mapping interfaces

If you want to create a pure GraphQL interface, you can also add a #[Type] attribute on a PHP interface.

#[Type]
interface UserInterface
{
#[Field]
public function getUserName(): string;
}

This will automatically create a GraphQL interface whose description is:

interface UserInterface {
userName: String!
}

Implementing interfaces

You don't have to do anything special to implement an interface in your GraphQL types. Simply "implement" the interface in PHP and you are done!

#[Type]
class User implements UserInterface
{
public function getUserName(): string;
}

This will translate in GraphQL schema as:

interface UserInterface {
userName: String!
}

type User implements UserInterface {
userName: String!
}

Please note that you do not need to put the #[Field] attribute again in the implementing class.

Interfaces without an explicit implementing type

You don't have to explicitly put a #[Type] attribute on the class implementing the interface (though this is usually a good idea).

/**
* Look, this class has no #Type attribute
*/
class User implements UserInterface
{
public function getUserName(): string;
}
class UserController
{
#[Query]
public function getUser(): UserInterface // This will work!
{
// ...
}
}
If GraphQLite cannot find a proper GraphQL Object type implementing an interface, it will create an object type "on the fly".

In the example above, because the User class has no #[Type] attribute, GraphQLite will create a UserImpl type that implements UserInterface.

interface UserInterface {
userName: String!
}

type UserImpl implements UserInterface {
userName: String!
}