Contributte Doctrine-orm
Doctrine/ORM (opens new window) to Nette Framework.
# Content
# Setup
Install package
composer require nettrine/orm
Register extension
extensions:
nettrine.orm: Nettrine\ORM\DI\OrmExtension
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 (opens new window) integration.
composer require nettrine/dbal
extensions:
nettrine.dbal: Nettrine\DBAL\DI\DbalExtension
2
Doctrine ORM (opens new window) needs Doctrine DBAL (opens new window) 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 (opens new window) integration.
composer require nettrine/cache
extensions:
nettrine.cache: Nettrine\Cache\DI\CacheExtension
2
Doctrine ORM (opens new window) needs Doctrine Cache (opens new window) 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
2
3
You can also specify a single driver or 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
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')
2
# symfony/console
This package relies on symfony/console
, use prepared contributte/console (opens new window) integration.
composer require contributte/console
extensions:
console: Contributte\Console\DI\ConsoleExtension(%consoleMode%)
nettrine.orm: Nettrine\ORM\DI\OrmExtension
nettrine.orm.console: Nettrine\ORM\DI\OrmConsoleExtension(%consoleMode%)
2
3
4
5
Since this moment when you type bin/console
, there'll be registered commands from Doctrine DBAL.
# Configuration
Schema definition
nettrine.orm:
configuration:
proxyDir: <path>
autoGenerateProxyClasses: <boolean>
proxyNamespace: <string>
metadataDriverImpl: <service>
entityNamespaces: <mixed[]>
customStringFunctions: <mixed[]>
customNumericFunctions: <mixed[]>
customDatetimeFunctions: <mixed[]>
customHydrationModes: <string[]>
classMetadataFactoryName: <string>
defaultRepositoryClassName: <string>
namingStrategy: <class>
quoteStrategy: <class>
entityListenerResolver: <class>
repositoryFactory: <class>
defaultQueryHints: <mixed[]>
filters:
<string>:
class: <string>
enabled: <boolean>
entityManagerDecoratorClass: <class>
configurationClass: <class>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Under the hood
Minimal configuration could look like this:
nettrine.orm:
configuration:
autoGenerateProxyClasses: %debugMode%
2
3
Take a look at real Nettrine ORM configuration example at contributte/webapp-project (opens new window).
Side notes
The compiler extensions would be so big that we decided to split them into more separate files / compiler extensions.
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.
Are you looking for custom types? You can register custom types in DBAL, see Nettrine DBAL (opens new window).
You have to configure entity mapping (see below), otherwise you will get
It's a requirement to specify a Metadata Driver
error.
# Mapping
Doctrine ORM needs to know where your entities are located and how they are described (mapping).
Additional metadata provider needs to be registered. We provide bridges for these drivers:
- attributes (
Nettrine\ORM\DI\OrmAttributesExtension
) - annotations (
Nettrine\ORM\DI\OrmAnnotationsExtension
) - xml (
Nettrine\ORM\DI\OrmXmlExtension
)
# Attributes
Since PHP 8.0, we can use #[attributes] (opens new window) for entity mapping.
<?php
namespace App\Model\Database;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity]
#[ORM\Table(name: 'customer')]
class Customer
{
#[ORM\Column(length: 32, unique: true, nullable: false)]
protected string $username;
#[ORM\Column(columnDefinition: 'CHAR(2) NOT NULL')]
protected string $country;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Use OrmAttributesExtension
as the bridge to the AttributeDriver. This is the default configuration.
extensions:
nettrine.orm: Nettrine\ORM\DI\OrmExtension
nettrine.orm.attributes: Nettrine\ORM\DI\OrmAttributesExtension
nettrine.orm.attributes:
mapping: [
namespace: path
]
excluded: []
2
3
4
5
6
7
8
9
Example configuration for entity located at app/Model/Database
folder.
nettrine.orm.attributes:
mapping:
App\Model\Database: %appDir%/Model/Database
2
3
# Annotations
Are you using @annotations (opens new window) in your entities?
<?php
namespace App\Model\Database;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name="customer")
*/
class Customer
{
/**
* @ORM\Column(length=32, unique=true, nullable=false)
*/
protected string $username;
/**
* @ORM\Column(columnDefinition="CHAR(2) NOT NULL")
*/
protected string $country;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
This feature relies on doctrine/annotations
, use prepared nettrine/annotations (opens new window) integration.
composer require nettrine/annotations
extensions:
nettrine.annotations: Nettrine\Annotations\DI\AnnotationsExtension
2
You will also appreciate ORM => Annotations bridge, use OrmAnnotationsExtension
. This is the default configuration, it uses an autowired cache driver.
Please note that OrmAnnotationsExtension
must be registered after AnnotationsExtension
. Ordering is crucial!
extensions:
# Common
nettrine.annotations: Nettrine\Annotations\DI\AnnotationsExtension
# ORM
nettrine.orm: Nettrine\ORM\DI\OrmExtension
nettrine.orm.annotations: Nettrine\ORM\DI\OrmAnnotationsExtension
nettrine.orm.annotations:
mapping: [
namespace: path
]
excluded: []
2
3
4
5
6
7
8
9
10
11
12
13
Example configuration for entity located at app/Model/Database
folder.
nettrine.orm.annotations:
mapping:
App\Model\Database: %appDir%/Model/Database
2
3
# XML
Are you using XML mapping (opens new window) for your entities?
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
...
</doctrine-mapping>
2
3
4
5
6
7
8
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:
mapping: [
namespace: path
]
fileExtension: .dcm.xml
simple: false
2
3
4
5
6
7
8
9
10
Using simple you will enable SimplifiedXmlDriver
(opens new window).
# Helpers
MappingHelper
You can use the predefined MappingHelper
helper class in your compiler extensions. Be careful, you have to call it in beforeCompile
phase.
use Nette\DI\CompilerExtension;
use Nettrine\ORM\DI\Helpers\MappingHelper;
class CategoryExtension extends CompilerExtension
{
public function beforeCompile(): void
{
MappingHelper::of($this)
->addAnnotation('App\Model\Database', __DIR__ . '/../app/Model/Database')
->addAnnotation('Forum\Modules\Database', __DIR__ . '/../../modules/Forum/Database')
->addXml('Gallery1\Modules\Database', __DIR__ . '/../../modules/Gallery1/Database')
->addXml('Gallery2\Modules\Database', __DIR__ . '/../../modules/Gallery2/Database', $simple = TRUE)
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Examples
# 1. Manual example
composer require nettrine/annotations nettrine/cache nettrine/migrations nettrine/fixtures nettrine/dbal nettrine/orm
# Extension > Nettrine
# => order is crucial
#
extensions:
# Common
nettrine.annotations: Nettrine\Annotations\DI\AnnotationsExtension
nettrine.cache: Nettrine\Cache\DI\CacheExtension
nettrine.migrations: Nettrine\Migrations\DI\MigrationsExtension
nettrine.fixtures: Nettrine\Fixtures\DI\FixturesExtension
# DBAL
nettrine.dbal: Nettrine\DBAL\DI\DbalExtension
nettrine.dbal.console: Nettrine\DBAL\DI\DbalConsoleExtension
# ORM
nettrine.orm: Nettrine\ORM\DI\OrmExtension
nettrine.orm.cache: Nettrine\ORM\DI\OrmCacheExtension
nettrine.orm.console: Nettrine\ORM\DI\OrmConsoleExtension
nettrine.orm.annotations: Nettrine\ORM\DI\OrmAnnotationsExtension
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 2. Example projects
We've made a few skeletons with preconfigured Nettrine nad Contributte packages.
- https://github.com/contributte/webapp-skeleton (opens new window)
- https://github.com/contributte/apitte-skeleton (opens new window)
# 3. Example playground
- https://github.com/contributte/playground (opens new window) (playground)
- https://contributte.org/examples.html (opens new window) (more examples)
# Other
This repository is inspired by these packages.
- https://github.com/doctrine (opens new window)
- https://gitlab.com/Kdyby/Doctrine (opens new window)
- https://gitlab.com/etten/doctrine (opens new window)
- https://github.com/DTForce/nette-doctrine (opens new window)
- https://github.com/portiny/doctrine (opens new window)
Thank you folks.