# Nettrine ORM

Doctrine/ORM to Nette Framework.

# Content

# Setup

Install package

composer require nettrine/orm
1

Register extension

extensions:
  nettrine.orm: Nettrine\ORM\DI\OrmExtension
1
2

# Relying

Take advantage of enpowering this package with 3 extra packages:

  • doctrine/dbal
  • doctrine/cache
  • symfony/console

# doctrine/dbal

This package relies on doctrine/dbal, use prepared nettrine/dbal integration.

composer require nettrine/dbal
1
extensions:
  nettrine.dbal: Nettrine\DBAL\DI\DbalExtension
1
2

Doctrine ORM needs Doctrine DBAL to be configured. If you register nettrine/dbal extension it will detect it automatically.

Doctrine DBAL provides powerful database abstraction layer with many features for database schema introspection, schema management and PDO abstraction.

# doctrine/cache

This package relies on doctrine/cache, use prepared nettrine/cache integration.

composer require nettrine/cache
1
extensions:
  nettrine.cache: Nettrine\Cache\DI\CacheExtension
1
2

Doctrine ORM needs Doctrine Cache to be configured. If you register nettrine/cache extension it will detect it automatically.

CacheExtension sets up cache for all important parts: queryCache, resultCache, hydrationCache, metadataCache and secondLevelCache.

This is the default configuration, it uses the autowired driver.

extensions:
  nettrine.orm: Nettrine\ORM\DI\OrmExtension
  nettrine.orm.cache: Nettrine\ORM\DI\OrmCacheExtension
1
2
3

You can also specify a single driver ir change the nettrine.orm.cache.defaultDriver for all of them.

nettrine.orm.cache:
  defaultDriver: App\DefaultOrmCacheDriver
  queryCache: App\SpecialDriver
  resultCache: App\SpecialOtherDriver
  hydrationCache: App\SpecialDriver('foo')
  metadataCache: @cacheDriver
1
2
3
4
5
6

secondLevelCache uses autowired driver (or defaultDriver, if specified) for CacheConfiguration setup, but you can also replace it with custom CacheConfiguration

nettrine.orm.cache:
  secondLevelCache: @cacheConfigurationFactory::create('bar')
1
2

# symfony/console

This package relies on symfony/console, use prepared contributte/console integration.

composer require contributte/console
1
extensions:
  console: Contributte\Console\DI\ConsoleExtension(%consoleMode%)

  nettrine.orm: Nettrine\ORM\DI\OrmExtension
  nettrine.orm.console: Nettrine\ORM\DI\OrmConsoleExtension(%consoleMode%)
1
2
3
4
5

Since this moment when you type bin/console, there'll be registered commands from Doctrine DBAL.

Console Commands

# Configuration

Schema definition

nettrine.orm:
 configuration:
   proxyDir: <path>
   autoGenerateProxyClasses: <boolean>
   proxyNamespace: <string>
   metadataDriverImpl: <service>
   entityNamespaces: <string[]>
   customStringFunctions: <mixed[]>
   customNumericFunctions: <mixed[]>
   customDatetimeFunctions: <mixed[]>
   customHydrationModes: <string[]>
   classMetadataFactoryName: <string>
   defaultRepositoryClassName: <string>
   namingStrategy: <class>
   quoteStrategy: <class>
   entityListenerResolver: <class>
   repositoryFactory: <class>
   defaultQueryHints: <mixed[]>

 entityManagerDecoratorClass: <class>
 configurationClass: <class>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

Under the hood

Minimal configuration could looks like this:

nettrine.orm:
  configuration:
    autoGenerateProxyClasses: %debugMode%
1
2
3

Take a look at real Nettrine ORM configuration example at Nutella Project.

Side notes

  1. The compiler extensions would be so big that we decided to split them into more separate files / compiler extensions.

  2. At this time we support only 1 connection, the default connection. If you need more connections (more databases?), please open an issue or send a PR. Thanks.

# Mapping

Doctrine ORM needs to know where are your entities located and how are described (mapping).

You gonna needed to register additional metadata provider. We provide these drivers bridges:

  • annotations (Nettrine\ORM\DI\OrmAnnotationsExtension)
  • xml (Nettrine\ORM\DI\OrmXmlExtension)

# Annotations

Are you using annotations in your entities?

/**
 * @ORM\Entity
 */
class Category
{
}
1
2
3
4
5
6

This feature relies on doctrine/annotations, use prepared nettrine/annotations integration.

composer require nettrine/annotations
1
extensions:
  nettrine.annotations: Nettrine\Annotations\DI\AnnotationsExtension
1
2

You will also appreciate ORM => Annotations bridge, use OrmAnnotationsExtension. This is the default configuration, it uses an autowired cache driver.

extensions:
  nettrine.orm: Nettrine\ORM\DI\OrmExtension
  nettrine.orm.annotations: Nettrine\ORM\DI\OrmAnnotationsExtension

nettrine.orm.annotations:
  paths: []
  excludePaths: []
1
2
3
4
5
6
7

# XML

Are you using XML mapping for your entities?

You will also appreciate ORM => XML bridge, use OrmXmlExtension. This is the default configuration:

extensions:
  nettrine.orm: Nettrine\ORM\DI\OrmExtension
  nettrine.orm.xml: Nettrine\ORM\DI\OrmXmlExtension

nettrine.orm.xml:
  paths: []
  fileExtension: .dcm.xml
1
2
3
4
5
6
7

# Helpers

You can use the predefined TEntityMapping trait in your compiler extensions.

use Nette\DI\CompilerExtension;
use Nettrine\ORM\DI\Traits\TEntityMapping;

class CategoryExtension extends CompilerExtension
{

  use TEntityMapping;

  public function loadConfiguration(): void
  {
    $this->setEntityMappings([
      'Forum' => __DIR__ . '/../Entity',
    ]);
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# Other

This repository is inspired by these packages.

  • https://gitlab.com/Kdyby/Doctrine
  • https://gitlab.com/etten/doctrine
  • https://github.com/DTForce/nette-doctrine
  • https://github.com/portiny/doctrine

Thank you guys.

# Examples

You can find more examples in planette playground repository.