API Platform version(s) affected: 4.1.26+ (tested with 4.3.3)
Description
RelationMetadataLoader crashes with Cannot instantiate abstract class when an API resource model extends an abstract base model class.
The Symfony serializer's ClassMetadataFactory walks up the full class hierarchy when building metadata. So if you have ItemTranslation extends AbstractModel extends Model, the loader gets called for AbstractModel too. Since AbstractModel is still a subclass of Model, the guard check on line 40 passes — and then line 46 tries to instantiate it without a constructor, which PHP refuses because the class is abstract.
How to reproduce
- Create an abstract base Eloquent model:
abstract class AbstractModel extends \Illuminate\Database\Eloquent\Model
{
use HasUuids;
}
- Create a concrete model that extends it and is exposed as an API resource:
#[ApiResource]
class ItemTranslation extends AbstractModel
{
public function item(): MorphTo
{
return $this->morphTo();
}
}
- Boot the application — it crashes during route registration.
Possible Solution
Add an isAbstract() check in RelationMetadataLoader::loadClassMetadata() before attempting to instantiate the class:
// RelationMetadataLoader.php
$refl = $classMetadata->getReflectionClass();
if ($refl->isAbstract()) {
return false;
}
$model = $refl->newInstanceWithoutConstructor();
Additional Context
Full stack trace (trimmed to relevant frames):
Cannot instantiate abstract class CommonApi\Models\AbstractModel
#0 RelationMetadataLoader.php(46): ReflectionClass->newInstanceWithoutConstructor()
#1 LoaderChain.php(51): RelationMetadataLoader->loadClassMetadata(...)
#2 ClassMetadataFactory.php(46): LoaderChain->loadClassMetadata(...)
#3 ClassMetadataFactory.php(52): ClassMetadataFactory->getMetadataFor('CommonApi\Models\AbstractModel')
#4 ClassMetadataFactory.php(35): ClassMetadataFactory->getMetadataFor('App\Models\ItemTranslation')
The concrete model (ItemTranslation) is a valid, non-abstract class. The crash happens because the serializer's metadata factory recurses into parent classes, and the loader doesn't guard against abstract ones.
API Platform version(s) affected: 4.1.26+ (tested with 4.3.3)
Description
RelationMetadataLoadercrashes withCannot instantiate abstract classwhen an API resource model extends an abstract base model class.The Symfony serializer's
ClassMetadataFactorywalks up the full class hierarchy when building metadata. So if you haveItemTranslation extends AbstractModel extends Model, the loader gets called forAbstractModeltoo. SinceAbstractModelis still a subclass ofModel, the guard check on line 40 passes — and then line 46 tries to instantiate it without a constructor, which PHP refuses because the class is abstract.How to reproduce
Possible Solution
Add an
isAbstract()check inRelationMetadataLoader::loadClassMetadata()before attempting to instantiate the class:Additional Context
Full stack trace (trimmed to relevant frames):
The concrete model (
ItemTranslation) is a valid, non-abstract class. The crash happens because the serializer's metadata factory recurses into parent classes, and the loader doesn't guard against abstract ones.