sunrise / doctrine-bridge
Sunrise // Bridge to Doctrine for PHP 7.2+
v2.4.0
2022-02-15 00:34 UTC
Requires
- php: ^7.2|^8.0
- symfony/string: ^5.1
Requires (Dev)
- doctrine/annotations: ~1.13.0
- doctrine/dbal: ~2.13.0
- doctrine/migrations: ~3.2.0
- doctrine/orm: ~2.10.0
- phpunit/phpunit: ^8.5|^9.5
- sunrise/coding-standard: 1.0.0
- symfony/cache: ~5.3.0
- symfony/validator: ~5.3.0
- dev-master
- v2.4.0
- v2.3.1
- v2.3.0
- v2.2.1
- v2.2.0
- v2.1.0
- v2.0.1
- v2.0.0
- v1.19.0
- v1.18.0
- v1.17.0
- v1.16.0
- v1.15.0
- v1.14.0
- v1.13.0
- v1.12.0
- v1.11.0
- v1.10.1
- v1.10.0
- v1.9.0
- v1.8.1
- v1.8.0
- v1.7.0
- v1.6.0
- v1.5.0
- v1.4.0
- v1.3.0
- v1.2.0
- v1.1.0
- v1.0.0
- dev-release/v2.4.0
- dev-release/v2.3.1
- dev-release/v2.3.0
- dev-release/v2.2.1
- dev-release/v2.2.0
- dev-release/v2.1.0
- dev-release/v2.0.1
- dev-release/v2.0.0
- dev-release/v1.19.0
This package is auto-updated.
Last update: 2024-12-04 04:20:21 UTC
README
Installation
composer require 'sunrise/doctrine-bridge:^2.0'
Entity Manager Registry
Quick start
use Sunrise\Bridge\Doctrine\EntityManagerRegistry; // Minimal configuration (see below for details) $configuration = [ 'master' => [ 'dbal' => [ 'connection' => [ 'url' => 'sqlite:///{app.root}/master.sqlite', ], ], 'orm' => [ 'entity_locations' => [ '{app.root}/Entity', ], 'metadata_driver' => 'annotations', 'proxy_dir' => '{app.root}/var/cache/doctrine', ], 'migrations' => [ 'migrations_paths' => [ 'App\Migrations' => '{app.root}/resources/migrations', ], ], 'types' => [ ], ], ]; $doctrine = new EntityManagerRegistry($configuration, $registryName = 'ORM');
Configuration
DBAL configuration
ORM configuration
Migrations configuration
More details at: Official Documentation
Hydrator
The hydrator NEVER affects properties, it only calls setters and adders.
use Doctrine\ORM\Mapping as ORM; use Sunrise\Bridge\Doctrine\Annotation\Unhydrable; #[Entity] class Post { #[ORM\Id] #[ORM\Column(type: 'string')] private $id; #[ORM\Column(type: 'string')] private $name; #[ORM\ManyToOne(targetEntity: Category::class)] private $category; #[ORM\ManyToMany(targetEntity: Tag::class)] private $tags; #[ORM\ManyToOne(targetEntity: User::class)] #[Unhydrable] private $updatedBy // set + name (field name) public function setName(string $value) { // some code } // set + category (field name) public function setCategory(Category $value) { // some code... } // add + tag (singular field name) public function addTag(Tag $tag) { // some code... } // the setter will not be called because its property was marked as unhydrable public function setUpdatedBy(User $user) { // some code } }
$data = [ 'name' => 'New post', 'category' => [ 'name' => 'New category' ], 'tags' => [ [ 'name' => 'New tag 1', ], [ 'name' => 'New tag 2', ], ], ]; // or $data = [ 'name' => 'New post', 'category' => 1, // existing category ID 'tags' => [1, 2], // existing tag IDs ]; $hydrator = $doctrine->getHydrator($managerName = null); $someEntity = $hydrator->hydrate(Post::class, $data);
Query Filter
use App\Doctrine\QueryFilter; // initializes the filter with the specified data, // which can be, for example, the request query parameters. $filter = new QueryFilter([ // some user data... ]); // ['disabled' => 'yes'] // WHERE post.isDisabled = :p0 (true) // More details at: https://github.com/php/php-src/blob/b7d90f09d4a1688f2692f2fa9067d0a07f78cc7d/ext/filter/logical_filters.c#L273 $filter->allowFilterBy('disabled', 'post.isDisabled', $filter::TYPE_BOOL); // ['hits' => '100'] // WHERE post.hits = :p0 (100) $filter->allowFilterBy('hits', 'post.hits', $filter::TYPE_NUM); // ['hits' => [min => '100']] // WHERE post.hits >= :p0 (100) $filter->allowFilterBy('hits', 'post.hits', $filter::TYPE_NUM); // ['hits' => [max => '100']] // WHERE post.hits <= :p0 (100) $filter->allowFilterBy('hits', 'post.hits', $filter::TYPE_NUM); // ['hits' => [min => '50', max => '150']] // WHERE post.hits >= :p0 (50) AND post.hits <= :p1 (150) $filter->allowFilterBy('hits', 'post.hits', $filter::TYPE_NUM); // ['name' => 'Hello'] // WHERE post.id = :p0 ("Hello") $filter->allowFilterBy('name', 'post.name'); // ['name' => 'Hello'] // WHERE post.id LIKE :p0 ("%Hello") $filter->allowFilterBy('name', 'post.name', $filter::TYPE_STR, $filter::MODE_LIKE|$filter::STARTS_WITH); // ['name' => 'Hello'] // WHERE post.id LIKE :p0 ("Hello%") $filter->allowFilterBy('name', 'post.name', $filter::TYPE_STR, $filter::MODE_LIKE|$filter::ENDS_WITH); // ['name' => 'Hello'] // WHERE post.id LIKE :p0 ("%Hello%") $filter->allowFilterBy('name', 'post.name', $filter::TYPE_STR, $filter::MODE_LIKE|$filter::CONTAINS); // ['name' => 'Hello*Something%Something'] // WHERE post.id LIKE :p0 ("%Hello%Something\%Something%") // Note that asterisks will be converted to percentages... $filter->allowFilterBy('name', 'post.name', $filter::TYPE_STR, $filter::MODE_LIKE|$filter::CONTAINS|$filter::WILDCARDS); // ['created' => '2004-01-10'] // WHERE post.createdAt = :p0 (2004-01-10) $filter->allowFilterBy('created', 'post.createdAt', $filter::TYPE_DATE); // ['created' => [from => '1970-01-01']] // WHERE post.createdAt >= :p0 (1970-01-01) $filter->allowFilterBy('created', 'post.createdAt', $filter::TYPE_DATE); // ['created' => [until => '2038-01-19']] // WHERE post.createdAt <= :p0 (2038-01-19) $filter->allowFilterBy('created', 'post.createdAt', $filter::TYPE_DATE); // ['created' => [from => '1970-01-01', until => '2038-01-19']] // WHERE post.createdAt >= :p0 (1970-01-01) AND post.createdAt <= :p1 (2038-01-19) $filter->allowFilterBy('created', 'post.createdAt', $filter::TYPE_DATE); // Note that the DATE type also work with time and can accept a timestamp. // ['created' => '1073741824'] // work with the timestamp... // WHERE post.createdAt = :p0 (2004-01-10) $filter->allowFilterBy('created', 'post.createdAt', $filter::TYPE_DATE); // Note that the DATE type also work with time and can accept a timestamp. // ['created' => '12:00'] // work with the time... // WHERE post.createdAt = :p0 (12:00) $filter->allowFilterBy('opens', 'post.opensAt', $filter::TYPE_DATE); // ['sort' => 'name'] // ORDER BY post.name ASC $filter->allowSortBy('name', 'post.name' /* default is ascending direction */); // ['sort' => 'created'] // ORDER BY post.createdAt DESC $filter->allowSortBy('created', 'post.createdAt', $filter::SORT_DESC /* specified default sort direction */); // ['sort' => ['name' => 'asc', 'created' => desc]] // ORDER BY post.name ASC, post.createdAt DESC $filter->allowSortBy('name', 'post.name' /* default is ascending direction */); $filter->allowSortBy('created', 'post.createdAt', $filter::SORT_DESC /* specified default sort direction */); // If an user data doesn't contain sort fields, // then will be applied the default sort logic. $filter->defaultSortBy('post.name', $filter::SORT_ASC); $filter->defaultSortBy('post.createdAt', $filter::SORT_DESC); // Sets the default limit: $filter->defaultLimit(100); // Sets the maximum limit value: $filter->maxLimit(100); // For rows limiting, you can pass the following: // ['limit' => 100] // ['offset' => 0] // ... or: // ['page' => 1] // ['pagesize' => 100] // Create your QueryBuilder instance... $qb = $this->createQueryBuilder('post'); // ... and apply the filter to it: $filter->apply($qb); // ... and now you can run your query!
Maintainer
$maintainer = $doctrine->getMaintainer(); // closes all active connections $maintainer->closeAllConnections(); // clears all managers $maintainer->clearAllManagers(); // reopens all closed managers $maintainer->reopenAllManagers(); // recreates all schemas $maintainer->recreateAllSchemas(); // recreates the specified schema $maintainer->recreateSchema($managerName = null);
CLI commands
$application->addCommands( $doctrine->getCommands() );
PSR-3 logger
use Sunrise\Bridge\Doctrine\Logger\SqlLogger; $sqlLogger = new SqlLogger($psrLogger);
Unique Entity Validator
use Sunrise\Bridge\Doctrine\Validator\Constraint\UniqueEntity; #[UniqueEntity(['field'])] class SomeEntity { }
Example for your CLI application
declare(strict_types=1); use Symfony\Component\Console\Application; require __DIR__ . '/../config/bootstrap.php'; $container = require __DIR__ . '/../config/container.php'; $application = new Application( $container->get('app.name'), $container->get('app.version') ); $application->addCommands( $container->get('commands') ); $application->addCommands( $container->get('doctrine')->getCommands() ); $application->run();
PHP-DI definition examples
Doctrine
declare(strict_types=1); use App\Bundle\Security\Password\Type\PasswordType; use Doctrine\Persistence\ManagerRegistry; use Sunrise\Bridge\Doctrine\EntityManagerRegistry; use Sunrise\Bridge\Doctrine\Logger\SqlLogger; use Symfony\Component\Cache\Adapter\ArrayAdapter; use function DI\create; use function DI\env; use function DI\get; use function DI\string; return [ 'doctrine' => create(EntityManagerRegistry::class) ->constructor( get('doctrine.configuration'), ), 'doctrine.configuration' => [ 'master' => [ 'dbal' => [ 'connection' => get('doctrine.configuration.master.dbal.connection'), 'sql_logger' => get('doctrine.configuration.master.dbal.sql_logger'), ], 'orm' => [ 'entity_locations' => get('doctrine.configuration.master.orm.entity_locations'), 'entity_namespaces' => get('doctrine.configuration.master.orm.entity_namespaces'), 'metadata_driver' => get('doctrine.configuration.master.orm.metadata_driver'), 'metadata_cache' => get('doctrine.configuration.master.orm.metadata_cache'), 'query_cache' => get('doctrine.configuration.master.orm.query_cache'), 'result_cache' => get('doctrine.configuration.master.orm.result_cache'), 'proxy_dir' => get('doctrine.configuration.master.orm.proxy_dir'), 'proxy_auto_generate' => get('doctrine.configuration.master.orm.proxy_auto_generate'), ], 'migrations' => [ 'logger' => get('doctrine.configuration.default.migrations.logger'), 'migrations_paths' => get('doctrine.configuration.default.migrations.migrations_paths'), ], 'types' => get('doctrine.configuration.types'), ], ], 'doctrine.configuration.master.dbal.connection' => ['url' => env('DATABASE_MASTER_URL')], 'doctrine.configuration.master.dbal.sql_logger' => get('doctrine.configuration.default.dbal.sql_logger'), 'doctrine.configuration.master.orm.entity_locations' => get('doctrine.configuration.default.orm.entity_locations'), 'doctrine.configuration.master.orm.entity_namespaces' => get('doctrine.configuration.default.orm.entity_namespaces'), 'doctrine.configuration.master.orm.metadata_driver' => get('doctrine.configuration.default.orm.metadata_driver'), 'doctrine.configuration.master.orm.metadata_cache' => get('doctrine.configuration.default.orm.metadata_cache'), 'doctrine.configuration.master.orm.query_cache' => get('doctrine.configuration.default.orm.query_cache'), 'doctrine.configuration.master.orm.result_cache' => get('doctrine.configuration.default.orm.result_cache'), 'doctrine.configuration.master.orm.proxy_dir' => get('doctrine.configuration.default.orm.proxy_dir'), 'doctrine.configuration.master.orm.proxy_auto_generate' => get('doctrine.configuration.default.orm.proxy_auto_generate'), 'doctrine.configuration.default.dbal.sql_logger' => create(SqlLogger::class)->constructor(get('logger')), 'doctrine.configuration.default.orm.entity_locations' => [string('{app.root}/src/Entity')], 'doctrine.configuration.default.orm.entity_namespaces' => ['App' => 'App\Entity'], 'doctrine.configuration.default.orm.metadata_driver' => 'annotations', 'doctrine.configuration.default.orm.metadata_cache' => create(ArrayAdapter::class), 'doctrine.configuration.default.orm.query_cache' => create(ArrayAdapter::class), 'doctrine.configuration.default.orm.result_cache' => create(ArrayAdapter::class), 'doctrine.configuration.default.orm.proxy_dir' => string('{app.root}/var/cache/doctrine/proxies'), 'doctrine.configuration.default.orm.proxy_auto_generate' => true, 'doctrine.configuration.default.migrations.logger' => get('logger'), 'doctrine.configuration.default.migrations.migrations_paths' => [ 'App\Migrations' => string('{app.root}/resources/migrations'), ], 'doctrine.configuration.types' => [ PasswordType::NAME => PasswordType::class, ], // autowiring... ManagerRegistry::class => get('doctrine'), EntityManagerRegistry::class => get('doctrine'), ];
Validator
declare(strict_types=1); use DI\Container; use Symfony\Component\Validator\ContainerConstraintValidatorFactory; use Symfony\Component\Validator\Validation; use Symfony\Component\Validator\Validator\ValidatorInterface; return [ /** * The application validator * * @link https://symfony.com/doc/current/validation.html * * @var ValidatorInterface */ ValidatorInterface::class => function (Container $container) : ValidatorInterface { return Validation::createValidatorBuilder() ->enableAnnotationMapping(true) ->addDefaultDoctrineAnnotationReader() ->setConstraintValidatorFactory(new ContainerConstraintValidatorFactory($container)) ->getValidator(); }, ];