Defining the Schema for Events: Type, Query, Pagination Following the Connection Pattern
Defining the Schema for Events: Type, Query, Pagination Following the Connection Pattern
~8 Min. Lesezeit Zuletzt aktualisiert am August 9, 2026
This chapter fills the Event module's etc/schema.graphqls with real content for the first time: the Event type and a list query that uses the same pagination structure as Magento's own products query.
Why not just return a list?
A query that directly returns [Event] would be the obvious solution - and exactly the wrong one for anything that potentially spans many records. Without pagination information, a client can neither know how many events exist in total, nor selectively load "the next 20". Magento solves this consistently across all of core through the connection pattern: a wrapper type with items, page_info, and total_count.
Declaring the Event type
type Event @doc(description: "A single event") {
event_id: Int!
identifier: String!
title: String!
description: String
location: String!
start_at: String!
end_at: String
capacity: Int
}The non-null markers follow the rule of thumb from chapter 7: columns with nullable="false" in db_schema.xml (chapter 11) get declared as !, optional columns like capacity stay nullable. Date/time fields are deliberately String, not a custom scalar (chapter 6).
The wrapper type for the list: Events
type Events @doc(description: "A paginated list of events") {
items: [Event]
page_info: SearchResultPageInfo
total_count: Int
}SearchResultPageInfo isn't a custom type - it's an already-existing core type from Magento_CatalogGraphQl (page_size, current_page, total_pages) - the same kind of reuse as FilterTypeInput in chapters 3 and 6. It can be referenced directly, as long as the module dependency on Magento_CatalogGraphQl set in chapter 4 is in place.
The query with pagination arguments
type Query {
events(
pageSize: Int = 20
currentPage: Int = 1
): Events
@resolver(class: "Mironsoft\\Event\\Model\\Resolver\\Events")
@doc(description: "Returns a paginated list of active events")
}pageSize and currentPage are deliberately optional with sensible defaults (chapter 7) instead of mandatory arguments - a client that just wants to see "the first few events" doesn't need to supply any pagination arguments at all.
query {
events(pageSize: 5) {
items {
identifier
title
start_at
}
page_info {
current_page
page_size
total_pages
}
total_count
}
}Achtung: At this point, the query is already declared in the schema, but still has no working resolver - Mironsoft\Event\Model\Resolver\Events doesn't exist until chapter 13. Testing it now returns a "class does not exist" error instead of data. That's expected at this stage, not a bug.
Tipp: The wrapper type's name (Events) and the query field's name (events) differ only in the capitalization of the first letter - GraphQL is case-sensitive, so a type name and a field name can easily share the same word stem without colliding, just like Magento's own products/Products pair.
Chapter 13 brings this query to life: a DataProvider and resolver that deliver real event data from the database.