2012-08-14 1 views
5

Ho scoperto che i tipi di array di Doctrine utilizzano serialize/unserialize e memorizzano i dati all'interno di campi "semplici" come testo, intero.Matrici di Doctrine e Postgres

Ma ho un progetto con un database postgres con alcuni campi come array (principalmente testo). Voglio usare quel database con Doctrine. C'è un modo per gestirlo?

Grazie

EDIT:

PS: ora sanno che gli array SQL può essere una buona pratica, grazie a Craig Ringer.

Forse posso creare un tipo personalizzato. C'è qualcuno che l'ha già fatto?

EDIT 2:

Problema metà risolto:

<?php 
namespace mysite\MyBundle\Types; 

use Doctrine\DBAL\Types\Type; 
use Doctrine\DBAL\Platforms\AbstractPlatform; 

/** 
    * My custom postgres text array datatype. 
*/ 
class TEXTARRAY extends Type 
{ 
    const TEXTARRAY = 'textarray'; // modify to match your type name 

    public function getSqlDeclaration(array $fieldDeclaration, AbstractPlatform $platform) 
    { 
     return $platform->getDoctrineTypeMapping('TEXTARRAY'); 
    } 

    public function convertToPHPValue($value, AbstractPlatform $platform) 
    { 
    // This is executed when the value is read from the database. Make your conversions here, optionally using the $platform. 
     return explode('","', trim($value, '{""}')); 
    } 

    public function convertToDatabaseValue($value, AbstractPlatform $platform) 
    { 
    // This is executed when the value is written to the database. Make your conversions here, optionally using the $platform. 

     settype($value, 'array'); // can be called with a scalar or array 
     $result = array(); 
     foreach ($set as $t) { 
      if (is_array($t)) { 
       $result[] = to_pg_array($t); 
      } else { 
       $t = str_replace('"', '\\"', $t); // escape double quote 
       if (! is_numeric($t)) // quote only non-numeric values 
        $t = '"' . $t . '"'; 
       $result[] = $t; 
      } 
     } 
     return '{' . implode(",", $result) . '}'; // format  

    } 

    public function getName() 
    { 
     return self::TEXTARRAY; // modify to match your constant name 
    } 
} 

e il controller

<?php 

namespace mysite\MyBundle; 

use Symfony\Component\HttpKernel\Bundle\Bundle; 
use Doctrine\ORM\EntityManager; 
use Doctrine\DBAL\Types\Type; 

class mysiteMyBundle extends Bundle 
{ 
    public function boot() { 
     Type::addType('textarray', 'mysite\MyBundle\Types\TextArray'); 
     $em = $this->container->get('doctrine.orm.default_entity_manager'); 
     $conn = $em->getConnection(); 
     $conn->getDatabasePlatform()->registerDoctrineTypeMapping('TEXTARRAY', 'textarray'); 
    } 
} 

So voglia di cercare all'interno di questi array con le query come 'myword' = ANY (myarrayfield) ... Qualcuno ha un indizio?

Qualcuno sul canale # Doctrine2 detto il mio per costruire una funzione DQL personalizzato, ecco che è:

<?php 
use Doctrine\ORM\Query\Lexer; 
use Doctrine\ORM\Query\AST\Functions\FunctionNode; 

class ANY extends FunctionNode { 

    public $field; 


    public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) { 
     return 'ANY(' . 
      $this->field->dispatch($sqlWalker) . ')'; 
    } 

    public function parse(\Doctrine\ORM\Query\Parser $parser) { 
     $parser->match(Lexer::T_IDENTIFIER); 
     $parser->match(Lexer::T_OPEN_PARENTHESIS); 
     $this->field = $parser->StringPrimary(); 
     $parser->match(Lexer::T_CLOSE_PARENTHESIS); 
    } 
} 

Ma, io costruisco le mie domande con un generatore di query, con matrice contenente le cose come

$arr[] = $qb->expr()->like($alias.".".$field, $qb->expr()->literal('%'.trim($val).'%')); 

e unendoli con

if(count($arr) > 0) $qb->Where(new Expr\Orx($arr)); 
else unset($arr); 

Così, come utilizzare la mia funzione? : \

+2

Gli array SQL sono in realtà una * normale * denormalizzazione utile che può essere un enorme incremento delle prestazioni se usato con saggezza e attenzione. Non dovrebbero essere usati senza buoni motivi, sono meno portabili, ecc. –

risposta

4

All'interno del QueryBuilder è possibile utilizzare le funzioni personalizzate semplicemente scrivendoli:

$qb->where("ANY(a.b)"); 

Alcuni ulteriori informazioni:

  1. È possibile aggiungere tipi personalizzati alla sezione di configurazione "dottrina" in la tua applicazione Symfony.
  2. Lo stesso vale per la funzione DQL personalizzata.

Vedere il comando "config: dump-reference DoctrineBundle" sulla CLI per la sintassi in Symfony 2.1, altrimenti sul sito Web symfony.com.