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.
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);
// ...
}
}
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.
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.