Skip to content

Commit e76a4a6

Browse files
authored
Added option to use lazyNativeObjects (#125)
1 parent 71d2b66 commit e76a4a6

File tree

4 files changed

+69
-0
lines changed

4 files changed

+69
-0
lines changed

.docs/README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ nettrine.orm:
6666
entityManagerDecoratorClass: <class>
6767
configurationClass: <class>
6868
69+
lazyNativeObjects: <bool>
6970
proxyDir: <path>
7071
autoGenerateProxyClasses: <boolean>
7172
proxyNamespace: <string>
@@ -151,6 +152,19 @@ By default, this extension will try to autoconfigure itself.
151152
- `3` means that the proxy classes are generated automatically using `eval()` (useful for debugging).
152153
- `4` means that the proxy classes are generated automatically when the proxy file does not exist or when the proxied file changed.
153154

155+
### Lazy Native Objects
156+
157+
> [!WARNING]
158+
> Requires PHP >= 8.4 and doctrine/orm >= 3.4.0
159+
160+
This setting will override any of the proxy settings and doctrine will use [native lazy objects](https://www.php.net/manual/en/language.oop5.lazy-objects.php) that were added to PHP in version 8.4. No proxies are generated and stored on the disk. This also works with new [property hooks](https://www.php.net/manual/en/language.oop5.property-hooks.php).
161+
162+
This will be required by default in version 4.0.0.
163+
164+
> [!TIP]
165+
> Take a look at more information in official Doctrine documentation:
166+
> - https://www.doctrine-project.org/projects/doctrine-orm/en/3.4/reference/advanced-configuration.html#native-lazy-objects-optional
167+
154168
### EntityManager
155169

156170
EntityManager is a central access point to ORM functionality. It is a wrapper around ObjectManager and holds the metadata and configuration of the ORM.

src/DI/OrmExtension.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
* @phpstan-type TManagerConfig object{
2424
* entityManagerDecoratorClass: string,
2525
* configurationClass: string,
26+
* lazyNativeObjects: bool|null,
2627
* proxyDir: string|null,
2728
* autoGenerateProxyClasses: int|bool|Statement,
2829
* proxyNamespace: string|null,
@@ -98,6 +99,7 @@ public function getConfigSchema(): Schema
9899
'connection' => Expect::string()->required(),
99100
'entityManagerDecoratorClass' => Expect::string()->assert(fn ($input) => is_a($input, EntityManagerDecorator::class, true), 'EntityManager decorator class must be subclass of ' . EntityManagerDecorator::class),
100101
'configurationClass' => Expect::string(Configuration::class)->assert(fn ($input) => is_a($input, Configuration::class, true), 'Configuration class must be subclass of ' . Configuration::class),
102+
'lazyNativeObjects' => Expect::bool(),
101103
'proxyDir' => Expect::string()->default($proxyDir)->before(fn (mixed $v) => $v ?? $proxyDir)->assert(fn (mixed $v) => !($v === null || $v === ''), 'proxyDir must be filled'),
102104
'autoGenerateProxyClasses' => Expect::anyOf(Expect::int(), Expect::bool(), Expect::type(Statement::class))->default($autoGenerateProxy),
103105
'proxyNamespace' => Expect::string('Nettrine\Proxy')->nullable(),

src/DI/Pass/ManagerPass.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,11 @@ public function loadManagerConfiguration(string $managerName, mixed $managerConf
6767
->addTag(OrmExtension::CONFIGURATION_TAG, ['name' => $managerName])
6868
->setAutowired(false);
6969

70+
// Configuration: enabling lazy native objects
71+
if ($managerConfig->lazyNativeObjects !== null && method_exists($managerConfig->configurationClass, 'enableNativeLazyObjects')) {
72+
$configuration->addSetup('enableNativeLazyObjects', [$managerConfig->lazyNativeObjects]);
73+
}
74+
7075
// Configuration: proxy dir
7176
if ($managerConfig->proxyDir !== null) {
7277
$configuration->addSetup('setProxyDir', [Helpers::expand($managerConfig->proxyDir, $builder->parameters)]);

tests/Cases/DI/OrmExtension.proxy.phpt

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use Contributte\Tester\Toolkit;
44
use Contributte\Tester\Utils\ContainerBuilder;
55
use Contributte\Tester\Utils\Neonkit;
6+
use Doctrine\ORM\Configuration;
67
use Doctrine\ORM\EntityManager;
78
use Doctrine\ORM\Proxy\ProxyFactory;
89
use Nette\DI\Compiler;
@@ -134,3 +135,50 @@ Toolkit::test(function (): void {
134135

135136
Assert::equal(ProxyFactory::AUTOGENERATE_NEVER, $entityManager->getConfiguration()->getAutoGenerateProxyClasses());
136137
});
138+
139+
// Native Objects
140+
Toolkit::test(function (): void {
141+
// Skip on PHP < 8.4 OR doctrine/orm < v3.4.0
142+
if (PHP_VERSION_ID < 80400 || !method_exists(Configuration::class, 'enableNativeLazyObjects')) {
143+
Assert::true(true);
144+
return;
145+
}
146+
147+
$builder = ContainerBuilder::of()
148+
->withCompiler(function (Compiler $compiler): void {
149+
$compiler->addExtension('nettrine.dbal', new DbalExtension());
150+
$compiler->addExtension('nettrine.orm', new OrmExtension());
151+
$compiler->addConfig([
152+
'parameters' => [
153+
'tempDir' => Tests::TEMP_PATH,
154+
],
155+
]);
156+
$compiler->addConfig(Neonkit::load(
157+
<<<'NEON'
158+
nettrine.dbal:
159+
connections:
160+
default:
161+
driver: pdo_sqlite
162+
password: test
163+
user: test
164+
path: ":memory:"
165+
nettrine.orm:
166+
managers:
167+
default:
168+
connection: default
169+
lazyNativeObjects: true
170+
mapping:
171+
App:
172+
type: attributes
173+
directories: [app/Database]
174+
namespace: App\Database
175+
NEON
176+
));
177+
})
178+
->build();
179+
180+
/** @var EntityManager $entityManager */
181+
$entityManager = $container->getService('nettrine.orm.managers.default.entityManager');
182+
183+
Assert::true($entityManager->getConfiguration()->isNativeLazyObjectsEnabled());
184+
});

0 commit comments

Comments
 (0)