Skip to content

Wire up orm:mapping:describe command #1883

@stlgaits

Description

@stlgaits

Feature Request / RFC

Not sure whether this belongs here in DoctrineBundle or in ORM repo but I was wondering whether people were interested in adding a simple debug / info console command which prints out Doctrine Entities field mapping.

As far as I'm aware, the only related debug commands currently available are :

Proposal

I would like to add an 'in-between' command which would return a simplified list of entity field mappings - i.e. field names and their types, as I find the orm:mapping:describe command way too verbose for my use case and would prefer a lighter alternative.

Motivation

I originally came up with this idea while frequently switching between files in my project just to check an entity's fields when writing Doctrine queries (especially with QueryBuilder), which becomes cumbersome when working with value objects, embedded fields, etc.
Having a lightweight console command would be a quick win to enhance DX and save time.

Implementation

I've implemented a prototype for this command (with some inspiration from the 2 commands mentioned above) in a work project. It allows you to pass a specific entity class name as an argument, or list all entities if no argument is given. Here is my current implementation :

use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Console\Attribute\Argument;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Style\SymfonyStyle;

#[AsCommand(
    name: 'app:debug-doctrine-mapping',
    description: 'Displays mapped fields of a Doctrine entity.',
)]
final class DebugDoctrineEntitiesCommand extends Command
{
    public function __construct(
        private readonly EntityManagerInterface $entityManager
    ) {
        parent::__construct();
    }

    public function __invoke(
        SymfonyStyle $io,
        #[Argument(description: 'The fully qualified class name of the entity', name: 'entity')]
        string|null $entityClass = null,
    ): int {
        $io->title('Debug Doctrine Entity Field Mapping');

        if (null !== $entityClass) {
            if (!class_exists($entityClass)) {
                $io->error(sprintf('Class: %s does not exist', $entityClass));

                return Command::FAILURE;
            }
            $io->text(sprintf('Listing properties for entity: %s', $entityClass));

            $this->renderEntityMapping($io, $entityClass);

            return Command::SUCCESS;
        }

        $driver = $this->entityManager->getConfiguration()->getMetadataDriverImpl();

        if (null === $driver) {
            $io->error('No metadata driver configured.');

            return Command::FAILURE;
        }

        $io->text('Listing properties for all mapped Doctrine entities...');

        $entityClasses = $driver->getAllClassNames();

        if (!$entityClasses) {
            $io->getErrorStyle()->caution(
                [
                    'You do not have any mapped Doctrine ORM entities according to the current configuration.',
                    'If you have entities or mapping files you should check your mapping configuration for errors.',
                ],
            );

            return Command::FAILURE;
        }

        foreach ($entityClasses as $entityClass) {
            try {
                $this->renderEntityMapping($io, $entityClass);
            } catch (\Exception $exception) {
                $io->error($exception->getMessage());
            }
        }

        return Command::SUCCESS;
    }

    private function renderEntityMapping(SymfonyStyle $io, string $entityClass): void
    {
        /** @var class-string<object> $entityClass */
        $metadata = $this->entityManager->getClassMetadata($entityClass);

        $io->section(sprintf('Entity: %s', $entityClass));

        $rows = [];
        foreach ($metadata->fieldMappings as $field => $mapping) {
            $rows[] = [
                $field,
                $mapping['type'] ?? 'N/A',
            ];
        }

        $io->table(['Field', 'Type'], $rows);
    }
}

Example outputs

  • List all :
    Image
  • Describe one :
    Image
  • Entity does not exist error :
    Image

I would love people's thoughts and suggestions on this idea.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions