Views: collegare una tabella con una chiave multipla

3 contenuti / 0 new
Ultimo contenuto
Views: collegare una tabella con una chiave multipla

Salve,
sto scrivendo l'hook_views_data del mio modulo ma ho un problema cui non vengo a capo.
Vediamo il panorama completo.
Ho creato il mio modulo xyz che si appoggia ad una sua tabella tipo questa:

create table xyzdata (
nid int(10) not null,
vid int(10) not null,
delta int(10) not null,
campo1 tinytext,
campo2 tinytext,
campo3 tinytext,
created int(11),
PRIMARY KEY (nid,vid,delta)
) ;

Il modulo xyz svolge egregiamente tutte le sue funzioni integrando i nodi con le sue informazioni.

A questo punto ho assoluta necessita' di includere il supporto per views in modo da poter integrare le viste con i campi di questo modulo.
Ho aggiunto xyz_views_api() a xyz.module e ho creato xyz.views.inc nel quale ho creato l'hook xyz_views_data() in modo da interfacciare la mia tabella. Il codice attuale e' questo:

function xyz_views_data() {
$data['xyzdata']['table']['group'] = t('dati xyz');
$data['xyzdata']['table']['join'] = array(
  'node' => array(
    'left_field' => 'vid',
    'field' => 'vid',
  ),
);
$data['xyzdata']['nid'] = array(
  'title' => t('campo nid'),
  'help' => t('Testo di aiuto di nid.'),
  'relationship' => array(
    'base' => 'node',
    'field' => 'nid',
    'handler' => 'views_handler_relationship',
    'label' => t('relazione con nid.'),
  ),
);
$data['xyzdata']['vid'] = array(
  'title' => t('campo vid'),
  'help' => t('Testo di aiuto di vid.'),
  'relationship' => array(
    'base' => 'node',
    'field' => 'vid',
    'handler' => 'views_handler_relationship',
    'label' => t('relazione con vid'),
  ),
);
...seguono gli altri campi...
}

Il punto e' che non so come definire la mia chiave multipla. Attualmente ho provato a fare il join con vid poiche' e' "piu' univoco" di nid ma mi sembra una soluzione sporchissima... anche perche' se creo una view (sui nodi) e attivo la relazione con vid la query esce fuori cosi':
SELECT
  node.nid AS nid,
  node.title AS node_title,
  node_xyzdata__xyzdata.campo1 AS node_xyzdata__xyzdata_campo1,
  node_xyzdata__xyzdata.campo2 AS node_xyzdata__xyzdata_campo2
FROM
  node node
    LEFT JOIN xyzdata xyzdata ON
      node.vid = xyzdata.vid
    INNER JOIN approv_node node_xyzdata ON
      xyzdata.vid = node_xyzdata.nid
    LEFT JOIN approv_xyzdata node_xyzdata__xyzdata ON
      node_xyzdata.vid = node_xyzdata__xyzdata.vid

La relazione e' richiesta e per i campi campo1 e campo2 e' richiesto l'uso della relazione.
Il problema, come si vede, e' che l'INNER JOIN mette in equivalenza il nid con il vid... problema che immagino provenga dalla definizione del join.

Questa la panoramica sul codice. Ora vorrei capire come e' possibile definire una chiave multipla (nid + vid) in modo da sincronizzare in modo completo la query. Ad esempio quando definisco l'array per node c'e' una maniera per definire piu' campi di collegamento?
O forse ho sbagliato ad usare una chiave multipla? :(

Attendo fiducioso (ma anche un filino preoccupato) qualche suggerimento di come procedere... anche perche' xyzdata e' solo la master di una struttura dati sottostante (che ovviamente viaggia a chiavi multiple :D ).

Ciao
Jenner

Drupal Version:

Qualche avanzamento l'ho fatto ma mi trovo un altro intoppo.
Innanzitutto non c'e' bisogno di relazioni ma solo di definire meglio la sezione "join" nel modo che segue:

$data['xyzdata']['table']['join'] = array(
  'node' => array(
    'left_table' => 'node_revisions',
    'left_field' => 'vid',
    'field' => 'vid',
  ),
);

In questo modo il join della vista viene fatto fra node e node_revisions via vid e poi con xyzdata sempre via vid. Il collegamento, cosi', e' coerente. Mancano le chiavi multiple.

Leggo nella documentazione che posso usare un handler personalizzato per supportare le chiavi multiple. La modifica va fatta sempre nella sezione "join" in questo modo:

$data['xyzdata']['table']['join'] = array(
  'node' => array(
    'handler' => 'xyz_views_join_multikey',
    'left_table' => 'node_revisions',
    'left_field' => 'vid',
    'field' => 'vid',
  ),
);

ho poi aggiunto l'hook apposito per rendere noto a views che ho degli handles personalizzati:

function xyz_views_handlers() {
  return array(
    'info' => array(
      'path' => drupal_get_path('module', 'xyz'),
    ),
    'handlers' => array(
      'xyz_views_join_multikey' => array(
        'parent' => 'views_join',
      ),
    ),
  );
}

Ho quindi creato il file xyz_views_join_multikey.inc, ho creato la classe xyz_views_join_multikey derivata da views_join e dentro la classe ho reimplementato il metodo join() in modo da smazzarmi le chiavi multiple tramite informazioni aggiuntive che includero' nella sezione "join".
E qui arriva l'intoppo: la classe non viene chiamata e io non so perche'. Ho provato a tracciare come view lavora con gli handlers ma - a parte la difficolta' del capire il funzionamento del codice di view - comincio a pensare che il problema non sta dalla mia parte.
Qualcuno di voi ha mai usato gli handlers sul tipo di join da effettuare? Se si, sto sbagliando qualcosa?

Grazie
Jenner

Risolto!!!
Il bug e' sul modulo views che non include il mio .inc dove c'e' l'implementazione dell'handler.
Quindi se dovete personalizzare l'handler della sezione "join" (perche' gli handler di tipo "relationship" non sembrano avere questo problema) per ora vi conviene mettere l'oggetto relativo all'interno del file modulo.views.inc.

Nel mio handler ho implementato il metodo join() che si occupa di interpretare un extra chiamato multikey dove specifico le coppie di campi da aggiungere alla relazione... una cosa di questo tipo:

$data['xyzdata']['table']['join'] = array(
  'node' => array(
    'handler' => 'xyz_views_join_multikey',
    'left_table' => 'node_revisions',
    'left_field' => 'vid',
    'field' => 'vid',
    'extra' => array(
      array(
        'multikey' => array(
          array(
            'left_field' => 'nid',
            'field' => 'nid',
          ),
        ),
      ),
    ),
  ),
);

In questo modo mi aggiunge node_revision.nid = xyzdata.nid (ovviamente con il supporto dei table alias di view).

Scusate se vi ho tediato con sta roba... ;)

Ciao
Jenner