2012-07-10 12 views

Odpowiedz

13

Istnieje możliwość posiadania tylu repozytoriów, ile chcesz. Jednak tylko jedno repozytorium może być połączone z menedżerem encji.

Musisz zdefiniować kilka usług, aby dodać niestandardowe repozytorium.

<!-- My custom repository --> 
<service id="acme.repository.my_entity" class="Acme\FQCN\MyEntityRepository" > 
    <argument type="service" id="doctrine.orm.entity_manager" /> 
    <argument type="service" id="acme.metadata.my_entity" /> 
</service> 

<!-- MyEntity metadata --> 
<service id="acme.metadata.my_entity" class="Doctrine\ORM\Mapping\ClassMetaData"> 
    <argument>Acme\FQCN\MyEntity</argument> 
</service> 

Klasa repozytorium musiałaby dziedziczą EntityRepository.

namespace Acme\FQCN; 

use Doctrine\ORM\EntityRepository; 

class MyEntityRepository extends EntityRepository 
{ 
    /** 
    * If you want to inject any custom dependencies, you'd have either have to 
    * add them to the construct or create setters. I'd suggest using setters 
    * in which case you wouldn't need to use the constructor in this class. 
    * 
    * public function __construct($em, Doctrine\ORM\Mapping\ClassMetadata $class, $custom_dependency) 
    * { 
    *  parent::__construct($em, $class); 
    * } 
    * 
    */ 
} 

Niestety, nie będziesz w stanie odzyskać go za pośrednictwem usługi doktryny. Zamiast pobierać je prosto z pojemnika:

$this->get('acme.repository.my_entity'); 

EDIT

Jeśli tworzysz repozytorium, które nie powinny być powiązane z żadnymi jednostkami, wystarczy utworzyć usługę i wstrzyknąć niezbędne zależności.

<!-- Repository for misc queries --> 
<service id="acme.repository.misc" class="Acme\FQCN\MiscRepsitory"> 
    <argument type="service" id="database_connection" /> 
</service> 

Ponieważ nie używasz żadnego z funkcji ORM doktryny w niestandardowym repozytorium, nie ma potrzeby, aby przedłużyć EntityManager.

namespace Acme\FQCN; 

use \Doctrine\DBAL\Connection; 

class MiscRepository 
{ 
    protected $conn; 

    public function __construct(Connection $conn) 
    { 
     $this->conn = $conn; 
    } 
} 
+0

Przepraszam, miałem na myśli, że repozytorium nie powinno być powiązane z żadnym podmiotem. Dlaczego więc chodzi o metadane? – gremo

+0

@Gremo w takim przypadku byłoby sensowne utworzenie dodatkowej usługi i wstrzyknięcie samego połączenia z bazą danych. – gilden

+0

po wstrzyknięciu database_connection powinienem utworzyć tylko klasę dziedziczącą z EntityRepository, czy mam rację? – gremo

1

Moja sugestia to utworzenie prostej klasy PHP z wymaganymi zależnościami w konstruktorze i przeniesienie jej przez kontener usługi.

4

Przyjęłam nieco inne rozwiązanie, korzystając z usług macierzystych Symfony2.

Przede wszystkim stworzyłem usługę rodzica, klasę GenericRepository, która udostępnia kilka metod i ułatwia życie w przypadku, gdybyśmy chcieli w przyszłości zmienić kod.

services.yml

acme_core.generic_repository: 
    abstract: true 
    class: Acme\Bundle\CoreBundle\Repository\GenericRepository 
    arguments: [@doctrine.orm.entity_manager] 

Acme\Bundle\CoreBundle\Repository\GenericRepository

<?php 

namespace Acme\Bundle\CoreBundle\Repository; 

use Doctrine\ORM\EntityManager; 

/** 
* Class GenericRepository 
* @package Acme\Bundle\CoreBundle\Repository 
*/ 
abstract class GenericRepository { 
    /** 
    * @var EntityManager 
    */ 
    private $entityManager; 

    /** 
    * @param EntityManager $entityManager 
    */ 
    public function __construct(EntityManager $entityManager) { 
     $this->entityManager = $entityManager; 
    } 

    /** 
    * @return EntityManager 
    */ 
    public function getEntityManager() { 
     return $this->entityManager; 
    } 

    /** 
    * @return \Doctrine\DBAL\Connection 
    */ 
    public function getConnection() { 
     return $this->getEntityManager()->getConnection(); 
    } 

    /** 
    * @return string 
    */ 
    abstract function getTable(); 
} 

Teraz chcemy definiować nowe repozytorium:

services.yml

# Repositories 
acme_product.repository.product_batch: 
    parent: acme_core.generic_repository 
    class: Acme\Bundle\ProductBundle\Repository\ProductBatchRepository 

Acme\Bundle\ProductBundle\Repository\ProductBatchRepository

<?php 

namespace Acme\Bundle\ProductBundle\Repository; 

use Acme\Bundle\CoreBundle\Repository\GenericRepository; 

/** 
* Class ProductBatchRepository 
* @package Acme\Bundle\ProductBundle\Repository 
*/ 
class ProductBatchRepository extends GenericRepository { 
    /** 
    * @param int $batchId 
    * @return integer The number of affected rows. 
    */ 
    public function deleteBatch($batchId) { 
     $table = $this->getTable(); 

     return $this->getConnection()->delete($table, [ 
      'id' => $batchId 
     ]); 
    } 

    /** 
    * {@inheritdoc} 
    */ 
    public function getTable() { 
     return 'product_batch'; 
    } 
} 

Sposób deleteBatch() tworzy i wykonuje następujące zapytanie:

DELETE FROM product_batch WHERE id = ?

Wreszcie w naszym Kontroler:

public function deleteAction() { 
    $batchId = $this->getRequest()->get('batchId'); 

    $affectedRows = $this->get('acme_product.repository.product_batch')->deleteBatch($batchId); 

    return $this->render(/**/); 
} 

W celu uzyskania dalszych informacji i kierownika jednostki/połączenie użycie proszę odnieść się do oficjalnej dokumentacji: http://doctrine-orm.readthedocs.org/en/latest/reference/native-sql.html

Powiązane problemy