Symfony 1.2 Reference Guide, il nuovo libro su Symfony

symfony_reference_mini E’ stato realizzato un nuovo libro su Symfony, si tratta della Symfony Reference Guide. Il testo in questione è liberamente consultabile dal sito del progetto, ed a breve lo sarà anche in italiano grazie ai prodi traduttori della community italiana, o acquistabile tramite Amazon a soli 19.90 dollari.

Soldi che verranno utilizzati come donazione alla comunità di Symfony per portare avanti nuovi progetti.

La Reference Guide spiega come gestire ogni tipo di configurazione e da accesso immediato ad ogni sua sezione grazie ad una serie di accorgimenti (indici correlati, cross-reference all’interno dei capitoli e molto altro).

Deselezionare le opzioni di una select multipla in un test funzionale

Mi è capitato questa mattina di dover fare un test funzionale in cui avevo bisogno di deselezionare una serie di opzioni da una select (all’interno di una form) lasciandone però alcuni selezionati. Guardando sulla documentazione dell’sfTestBrowser ho trovato un metodo per il select e deselect di radiobutton o checkbox. Sfortunatamente non ho trovato un metodo per deselezionare le opzioni di una select senza dover passare un array in post.

Con il mio “pair” mattutino abbiamo quindi deciso di creare un nuovo metodo che sfruttasse il DOM di una pagina html e che potesse rimuovere la selezione di una opzione dato il nome o l’id della select e il valore dell’option.

Abbiamo aperto anche un ticket sul track di Symfony dove potete trovare il nuovo metodo e il test unitario che ne verifica la correttezza!

Buon testing a tutti!!

Usando symfony 1.2 e Doctrine 1.0 problemi con le equal nested relation

Non so se vi è mai capitato di avere a che fare con le cosiddette “equal nested relation”. Queste relazioni tra oggetti sono quelle relazioni che possono essere tradotte (per quanto riguarda il database) con un “auto join” su una stessa tabella.

Un esempio pratico lo potete trovare fra gli esempi del sito dell’ORM Doctrine : Equal Nested Relation.

In uno dei miei progetti (Symfony 1.2, Doctrine 1.0) ho dovuto usare un esempio analogo, ma invece che utenti collegati fra loro con una relazione molti a molti, dovevo collegare più ticket. Una volta messo tutto in piedi e creato le classi necessarie ho fatto qualche prova e mi è spuntato questo errore:

500 | Internal Server Error
Doctrine_Connection_Mysql_Exception SQLSTATE23000: Integrity constraint violation: 1062 Duplicate entry 'N-N' for key 1

Inizialmente ho cercato una soluzione che potesse dipendere dalle configurazioni del file schema.yml che usavo e poi soluzioni che potessero riguardare qualsiasi altra cosa. Dopo quasi due giorni a sbattere la testa su questo problema sono andato al PHPDay2009 a cui avrebbe partecipato anche Jonathan Wage, ovviamente ripromettendomi di chiedere direttamente a lui!!

Fortunatamente c’è stata occasione di parlargli e Jonathan è stato più che gentile tanto da aiutarmi e mettersi a provare a trovare una soluzione lì per lì per il mio problema. Dopo circa un’ora siamo arrivati a capire dov’era il problema. Poi a pezzi e bocconi siamo arrivati ad una soluzione nelle successive 24 ore!

La patch da utilizzare è scaricabile da qui. Ricordo che questa NON È UNA SOLUZIONE DEFINITIVA. E’ piuttosto un workaround al problema!! Un ticket relativo a questa soluzione è stato aperto qui.

Sembra che questo problema sia risolto utilizzando symfony 1.3 e doctrine 1.1, quindi aspettiamo con ansia la prossima uscita di symfony che include sfDoctinePlugin con doctrine 1.1!

group by

Quante volte vi è capitato di dover fare una semplice group by per contare le righe di una tabella raggruppate per una data colonna? Per intenderci, quello che si fa in maniera semplicissima in SQL con

SELECT TYPE,COUNT(*) AS num FROM card GROUP BY TYPE;

Purtroppo con Propel la cosa non appare subito immediata. Ecco quindi un prezioso metodo da aggiungere alla vostra classe Peer per poterlo fare in modo semplice. Prima di tutto occorre inserire una nuova proprietà $count nel vostro modello (che nel mio esempio si chiama “Card”), con relativi getter e setter:

1
2
3
4
5
6
7
8
9
10
11
protected $count;
 
public function getCount()
{
  return $this->count;
}
 
public function setCount($count)
{
  $this->count = $count;
}

Ecco quindi il pezzo forte, in CardPeer (ricordate sempre che va adattato secondo il nome del vostro modello):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
 * grouped select
 * @param  Criteria $c
 * @param  string   $column
 * @return array
 */
public static function doSelectGroupBy(Criteria $c = null, $column)
{
  if (empty($c))
  {
    $c = new Criteria;
  }
  self::addSelectColumns($c);
  $c->addGroupByColumn($column);
  $c->addAsColumn('cnt', 'COUNT(*)');
  $stmt = self::doSelectStmt($c);
  $cards = array();
  while ($row = $stmt->fetch(PDO::FETCH_NUM))
  {
    $card = new Card;
    $col = $card->hydrate($row);
    $card->setCount(($row[$col] !== null) ? (int) $row[$col] : null);
    $cards[] = $card;
  }
  return $cards;
}

Ecco infine un esempio di utilizzo:

1
$cards = CardPeer::doSelectGroupBy(null, CardPeer::TYPE);