DEV Community

Cover image for Implementando MongoDB no Symfony
Natanael Alves
Natanael Alves

Posted on

Implementando MongoDB no Symfony

Eaí! Estava estudando mais sobre NoSQL com o MongoDB e decidi implementar o Mongo como banco de dados na API de um projeto que eu havia feito anteriormente com o Symfony.

Explicando rapidamente o projeto: é um compartilhador de arquivos. O usuário envia um arquivo e recebe um link de compartilhamento. Assim, qualquer pessoa com acesso a esse link pode visualizar o arquivo.

Nesse fluxo do projeto, o Mongo será utilizado para armazenar dados importantes do arquivo enviado pelo usuário, como id, nome, extensão e data de upload. Quando alguém acessar o link de compartilhamento, a API poderá recuperar o arquivo do serviço onde está armazenado (no caso, o Cloudflare R2) e retornar o arquivo correto para o usuário.

Requisitos

Antes de trabalhar com o Mongo no projeto, precisamos preparar o PHP para dar suporte ao Mongo. Para isso, a própria documentação do PHP tem instruções de como fazer isso: https://www.php.net/manual/en/mongodb.installation.php

Também precisamos de um servidor com o Mongo rodando. Existem várias formas de obter isso, e eu utilizei um serviço do próprio Mongo chamado MongoDB Atlas Cluster, que possui um tier gratuito para testes.

Importante

A implementação do Mongo em um projeto Symfony é bem simples, mas existem algumas considerações importantes:

  • Não existe mais ORM, agora é ODM (sigla para Object-Document Mapper)
  • Por isso, não existe EntityManager, agora é DocumentManager
  • Enfim, não existem mais Entidades, agora são Documentos, assim, criamos os documentos na pasta src/Document

Implementação

Agora sim, vamos para a implementação.

  1. Instale o módulo do mongo no projeto

    composer require doctrine/mongodb-odm-bundle
    # Do you want to execute this recipe? 'yes'
    
  2. Em config/packages/doctrine_mongodb.yaml, apague tudo e cole

    doctrine_mongodb:
      auto_generate_proxy_classes: true
      auto_generate_hydrator_classes: true
      connections:
        default:
          server: "%env(resolve:MONGODB_URL)%"
      default_database: "%env(resolve:MONGODB_DB)%"
      document_managers:
        default:
          auto_mapping: true
          mappings:
            App:
              dir: "%kernel.project_dir%/src/Document"
              mapping: true
              type: attribute
              prefix: 'App\Document'
              is_bundle: false
              alias: App
    
  3. Crie as variáveis de ambiente MONGODB_URL e MONGODB_DB, depois coloque respectivamente a conexão com seu servidor MongoDB e o nome do Database que você criou para o projeto. Também comentei a conexão do sqlite que havia antes.

  4. Crie os documentos do seu projeto. É bem parecido com criar uma entidade, exceto que:

    1. Invés de ORM é ODM
    2. Invés de "table" é "colletion"
    3. Invés de "Entity" é "Document"
    4. Invés de "Column" é "Field"
    5. Meu exemplo:

      <?php
      
      namespace App\Document;
      
      use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
      
      #[ODM\Document(collection: 'files')]
      class File
      {
        #[ODM\Id]
        public ?string $id = null;
      
        public function __construct(
            #[ODM\Field]
            private ?string $name = null,
            #[ODM\Field]
            private ?int $size = null,
            #[ODM\Field]
            private ?string $type = null,
            #[ODM\Field]
            private ?string $key = null,
        ) {
        }
      
        public function getId(): ?string
        {
            return $this->id;
        }
      }
      
  5. Crie o repository do documento

    <?php
    
    namespace App\Repository;
    
    use App\Document\File;
    use Doctrine\Bundle\MongoDBBundle\ManagerRegistry;
    use Doctrine\Bundle\MongoDBBundle\Repository\ServiceDocumentRepository;
    
    class FileRepository extends ServiceDocumentRepository
    {
        public function __construct(ManagerRegistry $registry)
        {
            parent::__construct($registry, File::class);
        }
    
        public function add(File $entity): File
        {
            $this->getDocumentManager()->persist($entity);
    
            $this->getDocumentManager()->flush();
    
            return $entity;
        }
    }
    
    
  6. Onde utilizava App\Entity\File troque para App\Document\File

  7. A utilização do document para inserir, atualizar etc. é a mesma como era com as entidades. Pode ver um exemplo no método upload do FileController:

    // ...
    $file = new File($fileDTO->name, $fileDTO->size, $fileDTO->type, $fileKey);
    $file = $this->fileRepository->add($file);
    
  8. Agora é só testar

Conclusão

Decidi utilizar o Mongo neste projeto mais por estudo. Tanto as tecnologias SQL quanto NoSQL serviriam para este projeto. No entanto, cada caso é um caso. É necessário avaliar qual tipo de banco é mais adequado para resolver o problema em questão. Às vezes os bancos relacionais são a opção certa, outras vezes armazenar em documentos é melhor. DEPENDE.

Top comments (0)