MySQL - Due chiavi esterne che puntano alla stessa tabella

Puntare due chiavi esterne ad un'unica tabella è un caso limite. Se possibile, è meglio modificare la struttura del database. Altrimenti dovrà modificare il codice dell'elenco READ.


Riguardo alle strutture che utilizzano due giunti su un unico tavolo

L'utilizzo di due join alla stessa tabella è una struttura perfettamente logica in alcuni casi, ma questo tipo di struttura è spesso poco pratica nell'uso.

Facciamo un semplice esempio:

MySQL two joins to the same table example
Esempio di una tabella MySQL con due join alla stessa tabella

Per selezionare i record dalla tabella dei progetti, dobbiamo utilizzare questo tipo di query:

SELECT
    projects.name,
    manager.name AS manager_name,
    manager.firstname AS manager_firstname,
    employee.name AS employee_name,
    employee.firstname AS employee_firstname
FROM
    projects
    LEFT JOIN persons AS manager ON projects.manager_id = manager.id
    LEFT JOIN persons AS employee ON projects.employee_id = employee.id

Questa query utilizza gli alias sia per i campi della tabella Persone, sia per il nome della tabella stessa, poiché viene interrogata due volte (una volta per ogni join).

Questa non è la soluzione giusta. PHPCG utilizza un sistema di filtri avanzato che le consente di cercare e filtrare i record nelle sue liste, ma non supporta l'uso di alias per le tabelle.

Ci sono due soluzioni alternative.


Prima soluzione: cambiare la struttura del suo database

Nell'esempio precedente, la tabella Persone raggruppa due entità diverse nella stessa tabella: dirigenti e dipendenti.

Questa non è una buona idea. È sempre meglio creare una tabella per ogni tipo di dati (ogni entità).

MySQL two joins to two distinct tables
Esempio di una tabella MySQL con due join a due tabelle distinte

Seconda soluzione: modificare la query SQL dell'elenco READ manualmente

Prendiamo una struttura leggermente diversa:

MySQL two joins to the same table example 2
Tabella MySQL con due join alla stessa tabella - Esempio 2

In questo secondo caso, la tabella dei progetti si riferisce a due dipendenti.
Non sarebbe coerente creare due tabelle per i dipendenti, in quanto i dipendenti rappresentano un'entità unica.

La soluzione è modificare la classe PHP che crea i dipendenti e sostituire la query generata dal generatore con due query separate.

Ecco come fare:

  1. Apra il file admin/class/crud/Projects.php nel suo editor di codice
    (sostituisca Progetti con il nome della sua tabella)
  2. Trovi la query nel codice ed elimini i campi e il join che si riferiscono al secondo join.
    La parte di join della query inizia con $this->join_query = ' LEFT JOIN ...' e la parte relativa ai campi inizia con $qry_start = 'SELECT ...'
  3. Trovi la parte di codice in cui vengono registrati i record. Inizia con while (!$db->endOfSeek()) { ...
  4. In questo ciclo, rimuova i risultati che si riferiscono al secondo join
  5. Dopo il ciclo, ne aggiunga uno nuovo per eseguire il ciclo all'interno di tutti i record e ottenere i record dal secondo join.
    Nel nostro esempio questo sarebbe:
    for ($i=0; $i < $this->records_count; $i++) { $qry = 'SELECT `employees`.`id` COME `employees_id`, `employees`.`name` COME `employees_name` FROM projects LEFT JOIN `employees` ON `projects`.`employees2_id`=`employees`.`id` WHERE projects.id = ' . $this->id[$i] . ' LIMIT 1'; $db = new DB(); $db->query($qry); $db_count = $db->rowCount(); if (!empty($db_count)) { $row = $db->fetch();; $this->employees2_id[] = $row->employees_id . '[|]' . $row->employees_name; } else { $this->employees2_id[] = ''; } }

Dopo aver apportato queste modifiche personalizzate al codice, se in seguito deve ricostruire il suo elenco READ dal generatore, non dimentichi che è disponibile lo strumento di confronto file:
Rigenerare l'elenco e i moduli che sono stati personalizzati (Come utilizzare lo strumento di confronto file del Generatore CRUD)

Naturalmente questa soluzione richiede alcune competenze di codifica, se ha bisogno di aiuto ci contatti e faremo del nostro meglio.

Pagina principale del tutorial PHP CRUD