Model Morph Addon
Model Morph Addon lets the model that declares a morphTo relationship resolve its own morph aliases instead of relying only on the global morph map.
Requirements
- Hyperf 3.2
hyperf/database~3.2hyperf/di~3.2
Installation
composer require friendsofhyperf/model-morph-addonThe package's ConfigProvider automatically registers its two AOP aspects. It has no configuration file to publish and no optional integration dependencies.
Define a Model-Local Morph Map
Override getActualClassNameForMorph() on the model that declares morphTo(). Each related model should return the stored alias from getMorphClass().
namespace App\Model;
use Hyperf\Database\Model\Model;
class Image extends Model
{
public function imageable()
{
return $this->morphTo();
}
public static function getActualClassNameForMorph($class)
{
$morphMap = [
'user' => User::class,
'book' => Book::class,
];
return $morphMap[$class] ?? $class;
}
}
class Book extends Model
{
public function images()
{
return $this->morphMany(Image::class, 'imageable');
}
public function getMorphClass()
{
return 'book';
}
}
class User extends Model
{
public function images()
{
return $this->morphMany(Image::class, 'imageable');
}
public function getMorphClass()
{
return 'user';
}
}The resolver should return a valid model class for every input. Returning the original value for unknown aliases preserves Hyperf's default fallback.
Query All Morph Types
The component also applies the model-local resolver when hasMorph() receives the wildcard type list ['*']. Methods that delegate to hasMorph(), such as whereHasMorph() and doesntHaveMorph(), receive the same behavior.
$images = Image::query()
->whereHasMorph('imageable', ['*'])
->get();For ['*'], Hyperf discovers the distinct, non-empty morph type values stored in the model's table. The component resolves each value through Image::getActualClassNameForMorph() before Hyperf builds the relationship queries.
Behavior
- Loading an
Image::imageablerelation resolves its stored type throughImage::getActualClassNameForMorph(). - Morph aliases are local to the model that declares
morphTo(); different models can resolve the same alias differently. - Explicit type lists passed to morph query methods keep Hyperf's default behavior. The query aspect changes only the exact wildcard list
['*'].