Plain PHP Classes
For most cases, a class with public typed properties is all you need:Supported Response Model Shapes
Instructor accepts several forms as theresponseModel parameter:
| Shape | Example | When to use |
|---|---|---|
| Class string | Person::class | Most common path |
| Object instance | new Person() | When you need to pre-populate defaults |
| JSON Schema array | ['type' => 'object', ...] | Dynamic or externally defined schemas |
Scalar helper | Scalar::integer('age') | Single value extraction |
Sequence helper | Sequence::of(Person::class) | Lists of objects |
Maybe helper | Maybe::is(Person::class) | Optional data that might not exist |
Type Hints
Use standard PHP type hints to specify the type of each field. Instructor supports all common types:string, int, float, bool, array, objects, and enums.
Use nullable types to indicate that a field is optional:
Instructor only sets public fields. Private and protected fields are ignored unless the class defines matching setter methods or constructor parameters.
DocBlock Type Hints
When you cannot or prefer not to use PHP type hints, DocBlock comments work as well. This is particularly useful for typed arrays, since PHP does not support generic array type hints natively:Typed Collections And Arrays
PHP does not support generics, so you need DocBlock comments to specify array element types. Instructor reads these annotations and includes them in the schema:Sequence helper instead:
Nested Objects And Enums
Nested objects and backed enums are part of the normal path. If your class graph is simple and typed, it works out of the box:Describing Your Model To The LLM
You can guide the model by adding descriptions and instructions to your classes and properties. Instructor includes these in the schema sent to the LLM.PHP DocBlocks
DocBlock comments on classes and properties are automatically extracted:Attributes
The#[Description] and #[Instructions] attributes provide a structured alternative
to DocBlocks:
Optional Data With Maybe
The Maybe helper wraps any response model to handle cases where the requested data
might not be present in the input:
Maybe asks the model to set a hasValue boolean and, when the data is missing, to
explain why in an error string. This is more reliable than using nullable types when
you need to distinguish “data not found” from “data is null.”
Best Practices
- Use public typed properties. They give Instructor the clearest possible schema.
- Keep names descriptive. Property names like
$customerEmailproduce better results than$e. - Put validation close to the model. Use Symfony constraints or
ValidationMixindirectly on the response class. - Prefer small, focused models. A
ContactInfoclass with three fields extracts more reliably than a catch-allDocumentclass with twenty. - Use enums for constrained values. Backed enums produce an
enumconstraint in the schema, which dramatically improves accuracy for categorical fields.