phalcon/cphalcon · error · Phalcon\Mvc\Model\Exceptions\RelationRequiresObjectOrArray
Only objects/arrays can be stored as part of has-many/has-on
Error message
Only objects/arrays can be stored as part of has-many/has-one/has-one-through/has-many-to-many relations on model {className} on Relation {relationName} What it means
Thrown by Model::postSaveRelatedRecords() (phalcon/Mvc/Model.zep:5575): a has-one, has-many, has-one-through or has-many-to-many relation was assigned something that is neither an object nor an array. These relations accept one instance or an array/Resultset of instances because each related record is saved after the master. The exception class is Phalcon\Mvc\Model\Exceptions\RelationRequiresObjectOrArray; the implicit transaction is rolled back first.
Source
Thrown at phalcon/Mvc/Model.zep:5575
* Try to get a relation with the same name
*/
let relation = <RelationInterface> manager->getRelationByAlias(
className,
name
);
if typeof relation === "object" {
/**
* Discard belongsTo relations
*/
if relation->getType() == Relation::BELONGS_TO {
continue;
}
if unlikely (typeof record !== "object" && typeof record !== "array") {
connection->rollback(nesting);
throw new RelationRequiresObjectOrArray(className, name);
}
let columns = relation->getFields(),
referencedModel = relation->getReferencedModel(),
referencedFields = relation->getReferencedFields();
/**
* Create an implicit array for has-many/has-one records
*/
if typeof record === "object" {
let relatedRecords = [record];
} else {
let relatedRecords = record;
}
let isThrough = (bool) relation->isThrough();
/**View on GitHub (pinned to b7419de9cd)
Solutions
- Assign an instance or an array of instances: $invoice->items = [new Item([...]), new Item([...])];
- To clear a has-many relation, assign an empty array or use the relation's sync/clear mechanism, not null or false
- Filter incoming payload keys so only scalar FK fields and known relation shapes reach the model
Example fix
// before
$invoice = new Invoice([...]);
$invoice->items = 3; // RelationRequiresObjectOrArray
$invoice->save();
// after
$invoice->items = [
new Item(['title' => 'A'),
new Item(['title' => 'B'),
];
$invoice->save(); Defensive patterns
Strategy: type-guard
Validate before calling
$value = $payload['items'] ?? null;
$ok = $value instanceof \Phalcon\Mvc\ModelInterface
|| (is_array($value) && array_reduce($value, fn($c, $i) => $c && $i instanceof \Phalcon\Mvc\ModelInterface, true));
if (!$ok) {
// refuse before save(): has-one/has-many relations need instance(s)
unset($payload['items']);
} Type guard
function isRelationValue($value): bool
{
if ($value instanceof \Phalcon\Mvc\ModelInterface) {
return true;
}
if (!is_array($value)) {
return false;
}
foreach ($value as $item) {
if (!$item instanceof \Phalcon\Mvc\ModelInterface) {
return false;
}
}
return true;
} Try / catch
try {
$invoice->save();
} catch (\Phalcon\Mvc\Model\Exceptions\RelationRequiresObjectOrArray $e) {
// relation property holds a scalar; drop it and report a validation error
// (the implicit transaction was already rolled back by Phalcon)
$messages = new Validation();
// surface 'items must be a model or list of models' to the client
} Prevention
- Bind request data to explicit model fields; never pass raw arrays to relation properties
- To clear a has-many relation assign [] (empty array), not null or false
- Validate relation payloads with the type guard above before save()
When it happens
Trigger: Assigning scalars to relation properties before save: $invoice->items = 5, $invoice->details = 'none', or $invoice->tags = null. Also assigning nested arrays of plain values (['a','b']) instead of arrays of model objects.
Common situations: Form/request data bound blindly to the model so numeric strings end up in relation properties; partial updates that set relations to null to clear them; mixing FK assignment with relation assignment conventions.
Related errors
- Only objects can be stored as part of belongs-to relations i
- Class '{className}' is not an ADR Action.
- Service '{name}' not registered
- A dependency which implements CryptInterface is required to
- Identity column '{identityField}' isn't part of the column m
AI-assisted analysis of phalcon/cphalcon@b7419de9cd (2026-08-21).
Data as JSON: /api/errors/046c125d81f744f8.
Report an issue: GitHub.