Skip to content

BUG: passing array of Models causes an error #96

@pjadanowski

Description

@pjadanowski

Bug: Attaching an array of models causes TypeError: Illegal offset type

When passing an array of model instances to attach, it throws:

TypeError: Illegal offset type

Example:

$user->rights()->attach([Right::find(1), Right::find(2)]);

Cause

The issue lies in the getIdsWithAttributes method:

elseif (is_array($id)) {
    foreach ($id as $key => $attributesArray) {
        if (is_array($attributesArray)) {
            $ids[$key] = array_merge($attributes, $attributesArray);
        } else {
            $ids[$attributesArray] = $attributes;
        }
    }
} 

Here, $id is an array of models, so $attributesArray is actually a model instance of Right.
When the code runs:

$ids[$attributesArray] = $attributes;

it fails because $attributesArray is an object, not a scalar key.


Suggested Fix

Before using $attributesArray as an array key, you should check whether it’s a Model instance and extract its key.

Alternatively, consider adapting Laravel’s own implementation from parseIds($value):

private function parseIds($value)
{
    if ($value instanceof Model) {
        return [$value->{$this->relatedKey}];
    }

    if ($value instanceof EloquentCollection) {
        return $value->pluck($this->relatedKey)->all();
    }

    if ($value instanceof BaseCollection || is_array($value)) {
        return (new BaseCollection($value))
            ->map(fn ($item) => $item instanceof Model ? $item->{$this->relatedKey} : $item)
            ->all();
    }

    return (array) $value;
}

This approach gracefully handles model instances, arrays, or collections.
A small tweak like this inside getIdsWithAttributes() would solve the problem entirely.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions