composer require dualmedia/disable-orm-bundle
config/bundles.php:
DualMedia\DisableORMBundle\DisableORMBundle::class => ['all' => true],
config/packages/doctrine.yaml:
doctrine:
orm:
entity_managers:
default:
class_metadata_factory_name: DualMedia\DisableORMBundle\Metadata\Factory\DisableORMMetadataFactory
#[DisableORM] attribute to the field in your entity:
#[ORM\Entity]
class User
{
#[DisableORM]
#[ORM\Column]
private ?string $legacyField = null;
}
Scenario: You need to remove a field (legacyField) from your User entity but cannot do so immediately due to legacy systems still using it. Use this bundle to:
#[DisableORM].Gradual Field Removal:
#[DisableORM] to the field in the new codebase.Conditional Disabling:
disable_on_commands config to exclude specific Doctrine commands (e.g., doctrine:schema:validate) from the bundle’s logic:
dm_disable_orm:
disable_on_commands:
- 'doctrine:schema:validate'
- 'doctrine:migrations:diff'
PHPStan Integration:
includes:
- vendor/dualmedia/disable-orm-bundle/extension.neon
CI/CD Validation:
/scripts/gitlab-ci.job.yml) to detect incorrect field removals (e.g., removing a field without first marking it with #[DisableORM]).Feature Deprecation Workflow:
#[DisableORM] and deploy.#[DisableORM] attribute.Multi-Version Deployment:
Legacy System Migration:
$legacyData = $entityManager->getConnection()->fetchAssociative(
'SELECT legacy_field FROM users WHERE id = ?',
[$userId]
);
Avoid in Critical Queries:
WHERE, JOIN, or ORDER BY clauses in Doctrine queries. These will break silently or throw errors.Default Values:
#[DisableORM]
#[ORM\Column(options: ['default' => null])]
private ?string $legacyField = null;
Testing:
find() or findBy() results.Documentation:
/**
* @DisableORM This field will be removed in a future migration.
*/
private ?string $legacyField = null;
Silent Failures:
getLegacyField()) will throw PropertyAccessException. Always use raw SQL for legacy access.Query Builder Issues:
QueryBuilder methods like where(), join(), or select() will result in errors or unexpected behavior. Example:
// This will fail if $legacyField is disabled
$qb->where('u.legacyField = :value');
Schema Validation:
doctrine:schema:validate by default. If you need to validate the schema with disabled fields, remove the command from the disable_on_commands config.Performance Overhead:
No Re-enabling:
Check Metadata:
$metadata = $entityManager->getClassMetadata(User::class);
var_dump($metadata->getFieldNames()); // Should not include 'legacyField'
Raw SQL Access:
$result = $entityManager->getConnection()->executeQuery(
'SELECT legacy_field FROM users WHERE id = ?',
[$userId]
);
PHPStan Errors:
extension.neon file is included in your PHPStan config and that the bundle is installed.Doctrine Events:
prePersist, preUpdate), ensure they are not relying on disabled fields.Metadata Factory Name:
class_metadata_factory_name is case-sensitive and must match exactly:
class_metadata_factory_name: DualMedia\DisableORMBundle\Metadata\Factory\DisableORMMetadataFactory
Bundle Order:
DisableORMBundle is loaded after the DoctrineBundle in config/bundles.php to avoid initialization issues.Doctrine Extensions:
Custom Metadata Factory:
DisableORMMetadataFactory to add custom logic for disabling fields based on environment variables or other conditions:
class CustomDisableORMMetadataFactory extends DisableORMMetadataFactory
{
public function getMetadataFor($className, Doctrine\Common\Persistence\Mapping\ClassMetadataFactory $factory)
{
$metadata = parent::getMetadataFor($className, $factory);
// Add custom logic here
return $metadata;
}
}
doctrine:
orm:
entity_managers:
default:
class_metadata_factory_name: App\Metadata\CustomDisableORMMetadataFactory
Dynamic Field Disabling:
#[DisableORM] attribute.Event Listeners:
$eventManager->addEventListener(
KernelEvents::CONTROLLER,
function (ControllerEvent $event) {
$request = $event->getRequest();
if ($request->attributes->has('legacy_field_accessed')) {
Logger::warning('Access to disabled field detected!');
}
}
);
How can I help you explore Laravel packages today?