2016-06-29 38 views
7

Sto usando Propel 2. Sono oggetti idratanti attraverso i rapporti, in questo modo:E 'possibile rimuovere campi con * RECURSION * quando si usa toArray() in Propel?

$return = OrderQuery::create() 
    ->joinWith('Customer') 
    ->joinWith('Status') 
    ->find() 
    ->toArray(TableMap::TYPE_PHPNAME, true, [], true); 

L'array risultante sarebbe simile a questa:

{ 
    "Id": 1, 
    "CustomerId": 1, 
    "StatusId": 1, 
    "Initiated": "2016-01-01T01:01:01+00:00", 
    "Customer": { 
    "Id": 1, 
    "Forname": "Test", 
    "Surname": "Smith", 
    "Orders": [ 
     "*RECURSION*" 
    ] 
    } 
    "Status": { 
    "Id": 1, 
    "Title": "title 1", 
    "Priority": 1, 
    "Orders": [ 
     "*RECURSION*" 
    ] 
    }, 
} 

Voglio rimuovere i campi in cui il il valore è *RECURSION*. Ho provato a utilizzare il parametro $alreadyDumpedObjects (3rd) su toArray() ma questo non sembra essere d'aiuto. Potrei anche fare qualche forma di array walking con le chiamate unset(), ma spero che ci sia un modo migliore, magari con un formattatore o qualcosa del genere?

Per i punti bonus, vorrei rimuovere le colonne che definiscono la relazione di chiave esterna. Ad esempio, sarebbe CustomerId, ma resterebbe Customer.

risposta

1

La risposta, a quanto pare, sembra essere molto semplice.

Se uso uno standard ArrayFormatter come questo:

$return = OrderQuery::create() 
    ->setFormatter('Propel\Runtime\Formatter\ArrayFormatter'); 
    ->joinWith('Customer') 
    ->joinWith('Status') 
    ->find() 
    ->toArray(); 

cosa viene restituito è un ArrayCollection che, quando toArray() è chiamato, è esattamente lo stesso che la mia uscita originale a parte la ricorsione campi mancanti.

Nota: quando si ottiene un risultato, ad esempio con ->findPk(1), viene restituito un array associativo, pertanto non è necessario utilizzare ->toArray() in modo esplicito.

0

Forse provare a chiamare:

unset($return['Customer']['Orders']); 
unset($return['Status']['Orders']); 
+0

Sì, quando ho parlato di array walking intendevo usare unset: ora mi viene specificato più esplicitamente nella mia domanda. Ma mi piacerebbe ancora qualcosa di meglio, che non avrei bisogno di hard-code per colonne specifiche – LeonardChallis

3

Nota per brevità: Questa risposta ha alcune informazioni davvero utili, ma non v'è una soluzione, nonostante questa risposta dicendo che non c'è.


ricorsione stringa è praticamente codificato a Propel (in src/Propel/Generator/Builder/Orm/ObjectBuilder.php):

if (isset(\$alreadyDumpedObjects['$objectClassName'][\$this->hashCode()])) { 
    return '*RECURSION*'; 
} 

suppongo che si possa ignorare l'oggetto costruttore, ma dubito che sia quello che stai cercando. Quindi, l'unico altro modo percorribile è quello che non volevi fare, il looping sull'array e l'utilizzo di unset. Qualcosa di simile a questo:

$array = StudyQuery::create() 
    ->leftJoinWithInstitute() 
    ->find() 
    ->toArray(); 

var_dump($array); 
echo PHP_EOL . PHP_EOL . PHP_EOL; 
var_dump(cleanupData($array)); 

/** 
* @param array $array 
* 
* @return array 
*/ 
function cleanupData(array $array) 
{ 
    $relationsFound = []; 
    foreach ($array as $key => $item) { 
     if ($item === ["*RECURSION*"] || $item == "*RECURSION*") { 
      unset($array[$key]); 
     } elseif (is_array($item)) { 
      $array[$key] = cleanupData($item); 
      $relationsFound[] = $key; 
     } 
    } 

    foreach ($relationsFound as $relation) { 
     $key = $relation . 'Id'; 
     if (isset($array[$key])) { 
      unset($array[$key]); 
     } 
    } 

    return $array; 
} 

Questo dovrebbe anche filtrare i *** Id-campi, se quel rapporto è presente (a condizione che il phpName per la relazione corrisponde al nome di colonna).

+0

Sembra che * ci sia * un modo per farlo dopo tutto. Vedi qualche problema con la mia soluzione alla tua conoscenza? – LeonardChallis

+1

Penso che tu abbia ragione, sì. La tua risposta è la migliore :) – chocochaos

2

Quando si chiama il metodo toArray su un oggetto PropelCollection chiamerà il toArray su ogni elemento della raccolta (il risultato della query). Quindi ci sono due modi per ottenere ciò che si sta cercando di fare: 1) sovrascrivere il metodo di toArray nelle classi Customer e Status modello o nei CustomerCollection e StatusCollection quelli (una rapida & soluzione sporca dal momento che viene applicata ogni volta che si utilizzare il metodo toArray ...). 2) Estendere la classe ArrayFormatter per definire una "strategia di salto Customer e Status" nel metodo format e quindi aggiungerla come formattatore da utilizzare (con il metodo setFormatter nella raccolta) solo quando è necessario questo particolare comportamento.

Alcuni arbitri: http://propelorm.org/documentation/reference/model-criteria.html#using-an-alternative-collection-class

http://propelorm.org/documentation/reference/model-criteria.html#using-an-alternative-formatter

+0

Grazie, anche se non ho bisogno di estendere 'ArrayFormatter' perché sembra funzionare da solo, come ho mostrato nella mia risposta. Apprezzo che tu mi abbia impostato sulla strada giusta! – LeonardChallis