0

I'm using Doctrine-defined Entity schema as a reference to create a C++/Qt API to access such data.

Is there a way to programmatically iterate through all the fields and their parameters such that there is only one master schema (and the C++ boilerplate headers are generated from it?)

qdot
  • 6,195
  • 5
  • 44
  • 95

1 Answers1

0

To get entities information, such as attributes and their properties you can use Doctrine Metadata Drivers. You just need your entities namespaces, once you have it you can use Doctrine to get their metadata.

I've created a service for this in my application (Posting here just as a usage example):

namespace Acme\Project\ProjectUserBundle\Service\Mapping;

use Doctrine\ORM\EntityManager;
use Doctrine\ORM\EntityNotFoundException;

/**
 * Class EntityService
 */
class EntityService
{
    private $em;

    public function __construct(EntityManager $entityManager)
    {
        $this->em = $entityManager;
    }

    /**
     * Return all Doctrine entities namespaces
     *
     * @return array
     */
    public function getAllEntityClasses()
    {
        $doctrineEntities = array();
        $allEntitiesMetadata = $this->em->getMetadataFactory()->getAllMetadata();

        foreach ($allEntitiesMetadata as $entityMetadata) {
            $doctrineEntities[] = $entityMetadata->getName();
        }

        return $doctrineEntities;
    }

    /**
     * Return all Doctrine entities namespaces in a given base namespace
     *
     * @param $namespace
     * @return array
     * @throws \Doctrine\ORM\EntityNotFoundException
     */
    public function getAllEntityClassesInNamespace($namespace)
    {
        $allEntityClasses = $this->getAllEntityClasses();

        foreach ($allEntityClasses as $entity) {
            preg_match($namespace, $entity, $haveFound);
            if (!empty($haveFound)) {
                $entitiesInNamespace[] = $entity;
            }
        }

        if (!isset ($entitiesInNamespace)) {
            throw new EntityNotFoundException("No entities found in $namespace namespace");
        }

       return $entitiesInNamespace;
    }

    /**
     * Receives a entity namespace and return all entity metadata
     *
     * @param $entityNamespace
     * @return \Doctrine\Common\Persistence\Mapping\ClassMetadata
     */
    public function getEntityMetadata($entityNamespace)
    {
        $metadataFactory = $this->em->getMetadataFactory();
        $entityMetadata = $metadataFactory->getMetadataFor($entityNamespace);

        //Check out, all entity information here;
        var_dump($entityMetadata);

        foreach ($entityMetadata->fieldMappings as $fieldMapping) {
            //Each attribute info;
            var_dump($fieldMapping);
        }

        return $entityMetadata;
    }
}

Register it on your services.yml/xml, it uses Doctrine entity manager as dependency.

services:
    Mapping.EntityService:
        class: Acme\Project\ProjectUserBundle\Service\Mapping\EntityService
        arguments: [ @doctrine.orm.entity_manager ]

Than just use the service on your controller (In my case I was using this service to get entities and apply permissions for users over them (read/write/view):

class UserPermissionController extends Controller
{

    public function yourAction()
    {
        $entityService = $this->get('Mapping.EntityService');

        $entitiesToApplyPermissions = $entityService->getAllEntityClassesInNamespace('/Acme/');

        foreach ($entitiesToApplyPermissions as $entity) {

            $entityService->getEntityMetadata($entity);
            //do whatever you want here
        }
    }
}

Note that this is just an example of usage, take a look at the documentation for more info: http://doctrine-orm.readthedocs.org/en/latest/reference/metadata-drivers.html

To generate the C++ headers you likely could create another service to handle, which btw could use this Mapping.EntityService as dependency.

gritt
  • 78
  • 5