P4A framework: utilizzo di multicheckbox e multiselect con tabelle di relazione N:N

screenshot della multicheckboxUn tipico esempio di utilizzo di un multicheckbox o di una multiselect si ha quando è necessario creare una maschera per una tabella di relazione N:N. Nel framework P4A è possibile implementare entrambi i tipi di oggetto.

Il problema è che, come detto in precedenti post, la documentazione non è completa, si rende necessario quindi fare una una ricerca nel forum. In questo thread e in quest’altro, viene spiegato il funzionamento. Sperando di fare cosa gradita, ho cercato di riassumere la procedura in questo esempio pratico.

 

schema del database Dunque, ammettiamo di avere tre tabelle relazionate come nella figura a fianco. L’obiettivo è di poter associare ad ogni fascia uno o più colori. Nella tabella di relazione possono essere presenti N fasce e per ogni fascia N colori. Per prima cosa creaiamo le tre tabelle:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
CREATE TABLE `colori` (
  `idcolori` BIGINT(20) NOT NULL AUTO_INCREMENT,
  `nome` VARCHAR(255) NOT NULL,
  `note` VARCHAR(255) DEFAULT NULL,
  PRIMARY KEY  (`idcolori`),
  UNIQUE KEY `colori_index_nome` (`nome`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1;
-- -----------------------------------------------
CREATE TABLE `fasce` (
  `idfasce` BIGINT(20) NOT NULL AUTO_INCREMENT,
  `descrizione` VARCHAR(255) DEFAULT NULL,
  PRIMARY KEY  (`idfasce`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1;
-- -----------------------------------------------
CREATE TABLE `fasce_colori` (
  `colori_idcolori` BIGINT(20) NOT NULL,
  `fasce_idfasce` BIGINT(20) NOT NULL,
  PRIMARY KEY  (`colori_idcolori`,`fasce_idfasce`),
  KEY `fasce_colori_FKIndex1` (`colori_idcolori`),
  KEY `fasce_colori_FKIndex2` (`fasce_idfasce`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

A questo punto è necessario creare le due classi e le maschere per la gestione delle tabelle fasce e colori nel modo standard, che non illustro ma sono presenti nel pacchetto scaricabile.
Possiamo finalmente creare la maschera per la tabella di relazione: fasce_colori nel seguente modo:

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
class P4A_Fasce_colori extends P4A_Mask
{
 function P4A_Fasce_colori()
 {
 $this->P4A_Mask();
 $p4a = & P4A::singleton();
 // DB Source
 $this->build("p4a_db_source","fasce");
 $this->fasce->setTable("fasce");
 $this->fasce->setPk("idfasce");
 //Filtro il record con idfasce=0 che indica
 //tutti i colori e non deve essere modificato
 $this->fasce->setWhere("idfasce > 0");
 $this->fasce->setPageLimit(15);
 $this->fasce->addMultivalueField("fld_fasce_colori",
  "fasce_colori","fasce_idfasce", "colori_idcolori");
 $this->fasce->load();
 $this->setSource($this->fasce);
 $this->setTitle('Gestione fasce colore');
 $this->fasce->firstRow();
 $this->build("p4a_db_source","colori");
 $this->colori->setTable("colori");
 $this->colori->setPk("idcolori");
 $this->colori->load();
 $this->fields->fld_fasce_colori->setType("multicheckbox");
 // Oppure se si preferisce la multiselect
 //$this->fields->fld_fasce_colori->setType("multiselect");
 $this->fields->fld_fasce_colori->setSource($this->colori);
 $this->fields->fld_fasce_colori->label->setVisible(false);
 //Fieldset con l'elenco dei campi
 $this->build("p4a_fieldset", "fset");
 $this->fset->setWidth(590);
 $this->fset->setTitle("Selezione colori");
 $this->fset->anchor($this->fields->fld_fasce_colori);
 // Toolbar
 $this->build("p4a_simple_toolbar", "toolbar");
 $this->toolbar->setMask($this);
 $this->toolbar->buttons->new->disable();
 // Table
 $table = & $this->build("p4a_table", "table");
 $table->setWidth(600);
 $table->setSource($this->fasce);
 $table->setVisibleCols(array("descrizione"));
 $table->showNavigationBar();
 // Message
 $message = & $this->build("p4a_message", "message");
 $message->setWidth("300");
 // Frame
 $frm= & $this->build("p4a_frame", "frm");
 $frm->setWidth(600);
 $frm->anchorCenter($message);
 $frm->anchorCenter($table);
 $frm->anchorCenter($this->fset);
 // Display
 $this->display("main", $frm);
 $this->display("menu", $p4a->menu);
 $this->display("top", $this->toolbar);
 }
}

Notate che la sorgente dati principale è quella della tabella dove agisce il selettore dei record,
nel nostro caso: fasce. L’azione chiave di tutta la procedura è la costruzione
di un campo attraverso il metodo addMultivalueField(),
i quattro parametri passati nell’ordine a questo metodo sono:

  • Il nome del nuovo campo
  • Il nome della tabella di relazione
  • Il nome della chiave esterna che lega la tabella dove agisce il selettore record
  • Il nome della chiave esterna che lega la tabella che funge da sorgente dati per il nuovo campo

Richiamando il metodo saveRow() le query di aggiornamento e inserimento verranno automaticamente eseguite dal P4A framework engine senza dover scrivere ulteriori righe di codice!

Download:

Il pacchetto completo è scaricabile qui

Conclusioni:

Il setup del codice necessario all’utilizzo di multicheckbox e multiselect è semplice ma poco documentato, il suo utilizzo è potente e fa risparmiare parecchio tempo.

Riferimenti ed approfondimenti: