2012-08-14 17 views
5

He encontrado que los tipos de matrices de Doctrine están usando serializar/deserializar y almacenar datos dentro de campos "simples" como texto, entero.Matrices de Doctrine y Postgres

Pero tengo un proyecto con una base de datos postgres con algunos campos como matrices (principalmente texto). Quiero usar esa base de datos con Doctrine. ¿Hay alguna manera de manejar eso?

Gracias

EDIT:

PD: ahora saben que las matrices de SQL puede ser una buena práctica, gracias a Craig Ringer.

Tal vez puedo crear un tipo personalizado. ¿Hay alguien que ya haya hecho eso?

EDIT 2:

problema medio resuelto:

<?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 
    } 
} 

y el controlador

<?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'); 
    } 
} 

Sé que desea buscar en el interior de estas matrices con preguntas como 'myword' = CUALQUIER (myarrayfield) ... ¿Hay alguien que tenga una pista?

Alguien en el canal # Doctrine2 dijo a mi para construir una función DQL encargo, así que aquí está:

<?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); 
    } 
} 

Pero, yo construyo mis consultas con un generador de consultas, con las cosas de la matriz que contiene como

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

y unirse a ellos con

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

Por lo tanto, la forma de usar mi función? : \

+2

Las matrices SQL son en realidad una denormalización * realmente * útil que puede ser una gran mejora en el rendimiento cuando se usa con prudencia y cuidado. Simplemente no deberían usarse sin buenas razones, son menos portátiles, etc. –

Respuesta

4

Dentro de la QueryBuilder puede utilizar sus funciones personalizadas con sólo escribir ellos:

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

Algunos más información:

  1. Puede añadir tipos personalizados a la sección de configuración "doctrina" en tu aplicación Symfony.
  2. Lo mismo vale para la función DQL personalizada.

Ver "config: volcar referencia DoctrineBundle" comando en la CLI para la sintaxis en Symfony 2.1, de lo contrario en el sitio web symfony.com.