2015-12-03 4 views
5

Questo è il mio ambiente:Escludere un risultato entità all'interno di un controller

Ho un'entità:

Object 
|____ id (integer) 
|____ foo (string) 
|____ configurations (collection)  

La proprietà configurations è una raccolta di Configuration entità mappate con un oneToMany. In ogni caso, che assomiglia a questo:

Configuration 
|____ id (integer) 
|____ bar (string) 
|____ name (string, nullable) 

Ho un servizio per ottenere un unico object:

  • Questo servizio è in un bundle che gestiscono oggetti di molti progetti.

  • Questo servizio non è a conoscenza di quale progetto lo chiama.

  • Questo servizio è un set di filtri, listener di eventi e query SQL. (qualcosa su linee 2K)

  • Considerare I non può/non voglio per aggiornare il processo di acquisizione per ciò che voglio fare qui.

ho la sola azione che voglio agire su nel mio controller come questo:

$objMgr = $this->get('objectManager'); //get my service I talked before 
$object = $objMgr->findOneById(); //get my object 

return array('object' => $object);// render template 

ho un sacco di temi di gestione dello schermo dell'utente finale con un file ramoscello in ciascuna:

theme1 
|____ object_details.html.twig 
theme2 
|____ object_details.html.twig 
themeX 
|____ object_details.html.twig 

Questi object_details.html.twig dispongono di questo codice per stampare le configurazioni.

{% for config in object.configurations %} 
    {# div config.blablabla etc. #} 
{% endfor %} 

La mia domanda:

Secondo il contesto di cui sopra, posso escludere tutte le configurazioni con una proprietà name non nullo?

requisiti Risposta:

  • La risposta non fa modificare i file ramoscello (so come fare ^^)

  • io voglio essere sicuro che l'esclusione di a configuration, non verrà rilevato da doctrine e cancella questo config del mio database su una cancellazione casuale da qualche parte nel codice.

  • La risposta può essere: "Amico, non possiamo farlo". In effetti, sono molto curioso di sapere se è possibile. Non ne ho idea al momento.

  • La risposta deve rispettare alcune best practice :)

Commenti anticipazione: Perché non modificare i file ramoscello?: Ho molti temi, voglio sapere se è possibile farlo una volta.

Perché non escludere i risultati nella query db?: Perché voglio queste configurazioni nelle altre mie pagine e progetti usando questo getter.

+50 per la migliore prova :)

+0

Non capisco davvero cosa stai cercando di realizzare, ma se non vuoi un determinato risultato, puoi usare 'Eccetto (...)'? https://msdn.microsoft.com/library/bb300779(v=vs.100).aspx –

+1

Grazie per il tuo commento. Ma mi dispiace, penso di aver sbagliato a leggere un tag proposto da Stack quando ho creato il post. In realtà sto lavorando con Symfony2 e non con entity-framework. –

+0

Vuoi rimuoverlo solo dai risultati o anche dal DB? – gvf

risposta

2

edificio sulla mia commenti sopra:

Un'opzione, che non si rifletterebbe su nulla tranne la vista, sarebbe quella di implementare uno (configurabile) decorator che espone la stessa api dell'oggetto originale.

In questo modo la vista, o forse anche altri consumatori, non saprebbero nemmeno di avere a che fare con un caso speciale.

Ad esempio:

<?php 
namespace App\Something; 

use Doctrine\Common\Collections\Criteria; 

class ObjectDecorator /* implement ObjectInterface // if needed */ 
{ 
    public function __construct(Object $object) 
    { 
     $this->base = $object; 
    } 

    public function getConfigurations() 
    { 
     //Using Criteria to make it cleaner than a loop. 
     $criteria = Criteria::create(); 
     $criteria->where(Criteria::expr()->isNull('name')); 

     return $this->base->getConfigurations()->matching($criteria); 
    } 

    /* 
    Override all your decorated entity getters with 
    public function getFoo() 
    { 
     return $this->base->getFoo(); 
    } 
    */ 
} 

e nel vostro uso del controller:

return array('object' => new ObjectDecorator($object)); 

Si potrebbe estendere questo un certo numero di modi:

  • estratto di creazione/configurazione un decoratore-fabbrica-servizio.
  • creare un'interfaccia che segua entrambi gli oggetti (in cemento e decorati), in modo che possano essere tranquillamente passati in giro.
+0

Ho provato la tua soluzione con quella dei criteri. Funziona davvero alla grande per la mia configurazione, ma non ho trovato un modo per idratare il mio oggetto decoratore con l'iniziale 'Object' passato nel costruttore (per accedere alle altre proprietà senza ridefinire tutti i getter). Ho provato ad estendere il mio decoratore con l'entità 'Object'. Ma solo il mio 'base' contiene il valore di ogni proprietà. –

+0

@JulienBourdic Proprio così, l'uso del pattern decoratore implica che è necessario aggiungere tutti i metodi pubblici dell'oggetto decorato. Questo sembra ingombrante, ma in realtà se il tuo oggetto non cambia costantemente questo è un compito di una volta. Se questo non è ancora accettabile, puoi implementare [metodi magici] (https://secure.php.net/manual/language.oop5.overloading.php#object.call) per gestire automaticamente la delega (con eccezioni per i metodi decorati naturalmente). Questo non è intrinsecamente male, ma potrebbe essere un problema di prestazioni. – Yoshi

+0

Grazie per la risposta. Mi hai aiutato bene e penso che sia il modo migliore per fare ciò che volevo fare. Ho più di 100 getters nell'oggetto che si sta evolvendo. Ma mi fai scoprire qualcosa di molto bello. Grazie. –

1

Io non capisco tutto il problema, ma capisco che si desidera ottenere alcuni elementi da un elenco in un'entità e non voglio per rimuovere dall'oggetto per qualche ragione. Quindi, creare una nuova funzione direttamente nell'entità, in questa funzione è possibile filtrare l'elenco e quindi restituire la nuova raccolta. In questo modo non comprometti l'oggetto.

/** 
* Object 
* 
* @ORM\Table() 
* @ORM\Entity 
*/ 
class Object 
{ 
    /** 
    * @var Collection 
    * 
    * @ORM\OneToMany(targetEntity="Configuration", mappedBy="object")   
    */ 
    private $configurations 
    //... 
    public function getConfigurationsWithName() 
    { 
     $subResult = new ArrayCollection(); 
     foreach ($this->configurations as $configuration) { 
      if ($configuration->getName() != null) { 
       $subResult.add($configuration); 
      } 
     } 
     return $subResult; 
    } 
    //... 
} 

Poi nel ramoscello

{% for filteredObject in object.configurationsWithName %} 
... 
{% endfor %} 

Quindi, l'aspetto quadro per qualsiasi getConfigurationsWithName all'interno dell'ente e trovare la nuova funzione. Spero che questo sia ciò di cui hai bisogno.

+0

Grazie, hai un'idea piuttosto interessante e pulita. Ma è lo stesso che ho fatto nel mio ramoscello. Devo modificare tutti i miei file di ramoscello. Modificherò la mia domanda. –

4

quello che vuoi è di filtraggio per criteri:

http://doctrine-orm.readthedocs.org/projects/doctrine-orm/en/latest/reference/working-with-associations.html#filtering-collections

E un esempio:

// Entity class 
class Department 
{ 
    public function getEmployeesByEmployeeTypeId($employeeTypeId) 
    { 
     $criteria = Criteria::create(); 
     $criteria->where(Criteria::expr()->eq('employeeType', $employeeTypeId)); 

     return $this->employees->matching($criteria); 
    } 
} 

nei criteri caso sarebbe come

$criteria->where("name is not null");  
return $this->configurations->matching($criteria); 
+0

Questa soluzione sembra fantastica e mi sta godendo, la testerò al più presto e tornerò da te. –

+0

Grazie ancora per il tuo tempo, è stato utile e ho aggiunto la tua soluzione nella risposta accettata. –

Problemi correlati