Fork me on GitHub

Model Definition

Model is the central manager for ORM repositories, it provides them and manages their loading. Model requires a repository loader. Orm comes with OrmExtension that will help you integrate all needed services with Nette\DI component.

PhpDoc repository definition#

The most common usecase is to define available repositories as PhpDoc annotations of your model class. Orm extension will take care of your repositories and automatically creates their definition for DI container. Also, a lazy loader will be injected into model. The loader will provide repositories directly from your DI container.

To define model repository use PhpDoc @property-read annotation:

namespace MyApp;

/**
 * @property-read PostsRepository $posts
 * @property-read UsersRepository $users
 * @property-read TagsRepository $tags
 */
class Orm extends \Nextras\Orm\Model\Model
{
}

Then configure Orm extension in your application config.neon:

extensions:
    nextras.orm: Nextras\Orm\Bridges\NetteDI\OrmExtension

nextras.orm:
    model: MyApp\Orm

services:
    nextras.orm.metadataParserFactory: MyApp\MyMetadataParserFactory
    nextras.orm.dependencyProvider: MyApp\DependencyProvider

The key model accepts class name of your project's model. Optionally, you may redefine other orm's services, such as metadata parser factory or dependency provider.

You can easily inject the model class into your services and use property access to get needed repositories:

namespace MyApp;

class MyService
{
    /** @var Orm */
    private $orm;

    public function __construct(Orm $orm)
    {
        $this->orm = $orm;
    }

    public function doSomething(int $postId)
    {
        $post = $this->orm->posts->getById($postId);
        // ...
    }
}

DI Repository Definition#

You may want to define all your repositories (dynamically) in your DI config. Orm provides different repository finder for such use-case. Orm will not create any other DIC's repository definitions and will reuse all IRepository instances in your DIC config.

extensions:
    nextras.orm: Nextras\Orm\Bridges\NetteDI\OrmExtension

nextras.orm:
    repositoryFinder: Nextras\Orm\Bridges\NetteDI\DIRepositoryFinder

services:
    - MyApp\PostsRepository(MyApp\PostsMapper(..., @nextras.orm.cache))
namespace MyApp;

class MyService
{
    /** @var Orm */
    private $orm;

    public function __construct(Orm $orm)
    {
        $this->orm = $orm;
    }

    public function doSomething($postId)
    {
        $post = $this->orm->getRepository(PostsRepository::class)->getById($postId);
        // ...
    }
}

Repositories are registered also with their names that are generated from the repository classname. If you want a different behavior, you may override DIRepositoryFinder::getRepositoryName() method.


Model with simple loader#

If you do not use Nette\DI, you can use predefined SimpleRepositoryLoader. This loader requires already instantiated array of repositories. For creating the stack easily, you can use SimpleLoaderFactory. You have to create instances of repositories and mappers on your own.

$cache = new Nette\Caching\Cache(...);
$connection = new Nextras\Dbal\Connection(...);
$mapperCoordinator = new Nextras\Orm\Mapper\Dbal\DbalMapperCoordinator($connection);
$metadataParserFactory = new Nextras\Orm\Entity\Reflection\MetadataParserFactory();

$simpleModelFactory = new SimpleModelFactory($cache, [
    'posts' => new MyApp\PostsRepository(new MyApp\PostsMapper($connection, $mapperCoordinator, $cache)),
    'users' => new MyApp\UsersRepository(new MyApp\UsersMapper($connection, $mapperCoordinator, $cache)),
    'tags' => new MyApp\TagsRepository(new MyApp\TagsMapper($connection, $mapperCoordinator, $cache)),
], $metadataParserFactory);

$model = $simpleModelFactory->create();

Of course, you can create your own repository loader by implementing Nextras\Orm\Model\IRepositoryLoader interface. Metadata parser factory optional dependency.