Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Brand12's avatar

Can a base repository return the specific model type (like Category) instead of just Model?

I’m working with a base repository in Laravel that handles generic operations like create, find, and update.

The structure looks like this:

abstract class BaseRepository {
    protected Model $model;

    public function __construct(Model $model) {
        $this->model = $model;
    }

    public function create(array $data): Model {
        return $this->model->create($data);
    }
}

Then I extend it like this:

class CategoryRepository extends BaseRepository {
    public function __construct(Category $model) {
        parent::__construct($model);
    }
}

In my service, I do something like:

public function createCategory(array $data): Category
{
    return $this->categoryRepository->create($data); // <-- returns Model, not Category
}

My Question: Is there any way to make the base create() method return the actual model type like Category, not just Model?

I don't want to have to rewrite the same create() method in every child repository just to fix the return type.

Is this possible in PHP? Or is there some pattern or trick people use to solve this?

Thanks in advance!

0 likes
9 replies
jlrdw's avatar

In my opinion, just use laravel conventions and MVC.

I suggest a search of past discussions on the repository pattern by me and others on the forum.

1 like
Snapey's avatar

Ill never understand why people use repository pattern. Especially like this;

$this->categoryRepository->create($data);

instead of

Category::create($data);
1 like
Glukinho's avatar

@Snapey what if you have to do something like this in several places?

$category = Category::create($data);
$category->managers()->attach(Auth::user());

if ( $category->isRoot() ) {
    $category->managers()->attach($some_other_user);

    $category->slug .= '_root';
}

$category->save();

Maybe you can put all this to static::creating() model event, but maybe you would want to have one explicit place for this logic, which may be a repository.

1 like
krisi_gjika's avatar

@Glukinho a repository is mostly used to detach the business logic of your application from the storage operations layer like dbs, caches, but this is too much of a hassle and is often implemented wrong. If you just want to organize logic you have many other options.

martinbean's avatar

@Glukinho If I need to re-use business logic somewhere then I’d put it in a service class; not a repository.

krisi_gjika's avatar

altho I don't recommend the repository pattern, since 99% of the time you would use eloquent models even if you change databases. The way I would go about it would be:

abstract class BaseEloquentRepository implements Repository
{
    abstract protected function model();

    public function create(array $data): Model
    {
        return $this->model()->create($data);
    }
}

this way you can have an interface that defines what is a repository, and a base repository for your eloquent operations. Since this class in dependent on eloquent models still, it's a good idea to note that.

Please or to participate in this conversation.