# Eloquent: Getting Started

Lighthouse makes it easy for you to perform queries and mutations on your Eloquent models.

# Defining Models

Eloquent models usually map directly to GraphQL types.

type User {
  id: ID!
  name: String!
}

It is strongly advised to name the field that corresponds to your primary key id. Popular client libraries such as Apollo provide out-of-the-box caching if you follow that convention.

# Retrieving Models

Instead of defining your own resolver manually, you can just rely on Lighthouse to build the Query for you.

type Query {
  users: [User!]! @all
}

The @all directive will assume the name of your model to be the same as the return type of the Field you are trying to resolve and automatically uses Eloquent to resolve the field.

The following query:

{
  users {
    id
    name
  }
}

Will return the following result:

{
  "data": {
    "users": [
      { "id": 1, "name": "James Bond" },
      { "id": 2, "name": "Madonna" }
    ]
  }
}

# Pagination

You can leverage the @paginate directive to query a large list of models in chunks.

type Query {
  posts: [Post!]! @paginate
}

The schema definition is automatically transformed to this:

type Query {
  posts(first: Int!, page: Int): PostPaginator
}

type PostPaginator {
  data: [Post!]!
  paginatorInfo: PaginatorInfo!
}

And can be queried like this:

{
  posts(first: 10) {
    data {
      id
      title
    }
    paginatorInfo {
      currentPage
      lastPage
    }
  }
}

# Adding Query Constraints

Lighthouse provides directives such as @eq to enhance your queries with additional constraints.

The following field definition allows clients to find a user by their email:

type Query {
  user(email: String! @eq): User @find
}

Query the field like this:

{
  user(email: "chuck@nor.ris") {
    id
    name
  }
}

If found, the result will look like this:

{
  "data": {
    "user": {
      "id": "69420",
      "name": "Chuck Norris"
    }
  }
}

# Ordering

Use the @orderBy directive to sort a result list by one or more given columns.

# Local Scopes

Local scopes (opens new window) are commonly used in Eloquent models to specify reusable query constraints.

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;

final class User extends Model
{
    public function scopeVerified(Builder $query): Builder
    {
        return $query->whereNotNull('email_verified_at');
    }
}

Directives that query models, such as @all or @first, allow you to re-use those scopes:

type Query {
  users: [User]! @all(scopes: ["verified"])
}

This query will produce the following SQL:

SELECT * FROM `users` WHERE `email_verified_at` IS NOT NULL

# Create

The easiest way to create data on your server is to use the @create directive.

type Mutation {
  createUser(name: String!): User! @create
}

This mutation will use the arguments passed to the field to create a new model instance:

mutation {
  createUser(name: "Donald") {
    id
    name
  }
}

The newly created user is returned as a result:

{
  "data": {
    "createUser": {
      "id": "123",
      "name": "Donald"
    }
  }
}

To create multiple models at once, use the @createMany directive.

# Update

You can update a model with the @update directive.

type Mutation {
  updateUser(id: ID!, name: String): User! @update
}

Since GraphQL allows you to update just parts of your data, it is best to have all arguments except id as optional.

mutation {
  updateUser(id: "123", name: "Hillary") {
    id
    name
  }
}
{
  "data": {
    "updateUser": {
      "id": "123",
      "name": "Hillary"
    }
  }
}

The update may fail to find the model you provided and return null:

{
  "data": {
    "updateUser": null
  }
}

To update multiple models at once, use the @updateMany directive.

# Upsert

Use the @upsert directive to update a model with a given id or create it if it does not exist.

type Mutation {
  upsertUser(id: ID, name: String!, email: String): User! @upsert
}

Since upsert can create or update your data, your input should mark the minimum required fields as non-nullable.

mutation {
  upsertUser(id: "123", name: "Hillary") {
    id
    name
    email
  }
}
{
  "data": {
    "upsertUser": {
      "id": "123",
      "name": "Hillary",
      "email": null
    }
  }
}

To upsert multiple models at once, use the @upsertMany directive.

# Delete

Deleting models is a breeze using the @delete directive. Dangerously easy.

type Mutation {
  deleteUser(id: ID! @whereKey): User @delete
}

Simply call it with the ID of the user you want to delete.

mutation {
  deleteUser(id: "123") {
    secret
  }
}

This mutation will return the deleted object, so you will have a last chance to look at the data. Use it wisely.

{
  "data": {
    "deleteUser": {
      "secret": "Pink is my favorite color!"
    }
  }
}