Custom Repositories

Keep your custom queries for a particular entity in one place.

A plain ObjectRepository class can be used for reading and writing objects of any type. For simple use cases, you can just use an instance of ObjectRepository directly; you don't need a custom repository class of your own. There are advantages to having a custom repository class though, especially if you write a lot of custom queries - ie. you can keep all your queries in the repository class, and just call methods on that custom repository, rather than littering your service classes with queries.

Some people like to have a custom repository class for every entity, which can result in hundreds of repository classes in a large application. Often, these classes are left completely empty, and just extend the base repository class - they are unnecessary, but are there 'just in case' you want to add methods later.

There is some rationale behind this - the class is ready for you to add your own methods without needing to change any dependency wiring, and you could use code generation to create entities and repositories, so that there is no great development burden in doing so. However, it does introduce code bloat, and not everyone likes to rely on code generation. Also, Objectiphy does not have any code generation features, and Doctrine's code generation will not create Objectiphy repository classes, so you would have to create your own. You might therefore prefer to mainly use plain ObjectRepository instances, and only create custom repositories where necessary. Or create custom repositories for every entity - it is up to you.

To create a custom repository class, extend the ObjectRepository class, and add your own methods as required, for example:

<?php

namespace \MyProject\Repositories;

use Objectiphy\Objectiphy\Orm\ObjectRepository;
use Objectiphy\Ojbectiphy\Query\QB;

class ContactRepository extends ObjectRepository
{
    public function findSmithsInDept(int $departmentId)
    {
        $query = QB::create()
            ->where('surname', '=', 'Smith')
            ->and('department', '=', $departmentId);
        
        return $this->findBy($query);
    }
}

You still need to use the repository factory to create custom repositories - if you try to create them or autowire them without using the factory, you will have problems!

Forcing the use of a custom repository

Typically, all you need to do to use a custom repository is tell the repository factory the class name of your repository and let it create it for you. However, if you are intercepting calls to the repository and need to make sure that your custom repository is always used for a particular entity - even if the entity is being loaded as a child of a parent entity which does not use your repository, you can do one of two things:

  • Use the repositoryClassName attribute of the @Table annotation to specify the fully qualified class name of the custom repository.

  • Override the mapping for the @Table annotation to specify a repository class name if it is not specified on the entity.

Where a custom repository has been specified for an entity, Objectiphy will defer to that custom repository class every time it tries to load an entity of that type. However, if the entity is loaded via a join (due to an eager loaded one-to-one or many-to-one relationship), the parent entity's repository will still be used. If you want to ensure that your custom repository is used even for eager loaded one-to-one and many-to-one relationships, you can set the alwaysLateBind attribute to true. If you do this though, a separate database call has to be made using a new instance of the custom repository, so performance will suffer.

Last updated