MySQL - Deux clés étrangères pointant vers la même table

Faire pointer deux clés étrangères vers une seule table est un cas limite. Si possible, il est préférable de modifier la structure de votre base de données. Sinon, vous devrez modifier votre code READ list.


A propos des structures utilisant deux joints pour une seule table

L'utilisation de deux jointures vers la même table est une structure parfaitement logique dans certains cas, mais ce type de structure est souvent peu pratique à l'usage.

Prenons un exemple simple :

MySQL two joins to the same table example
Exemple d'une table MySQL avec deux jointures vers la même table

Pour sélectionner des enregistrements dans la table des projets, nous devons utiliser ce type de requête :

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

Cette requête utilise des alias à la fois pour les champs de la table des personnes, mais aussi pour le nom de la table elle-même, car elle est interrogée deux fois (une fois pour chaque jointure).

Ce n'est pas la bonne solution. L'ASPC utilise un système de filtre avancé qui vous permet de rechercher et de filtrer les enregistrements dans vos listes, mais il ne prend pas en charge l'utilisation d'alias pour les tables.

Il existe deux solutions alternatives.


Première solution : modifier la structure de votre base de données

Dans l'exemple ci-dessus, le tableau des personnes regroupe deux entités différentes dans le même tableau : les cadres et les employés.

Ce n'est pas une bonne idée. Il est toujours préférable de créer une table pour chaque type de données (chaque entité).

MySQL two joins to two distinct tables
Exemple d'une table MySQL avec deux jointures vers deux tables distinctes

Deuxième solution : modifiez manuellement la requête SQL READ list

Prenons une structure légèrement différente :

MySQL two joins to the same table example 2
Table MySQL avec deux jointures vers la même table - Exemple 2

Dans ce deuxième cas, la table des projets fait référence à deux employés.
Il ne serait pas cohérent de créer deux tables pour les employés, car les employés représentent une entité unique.

La solution consiste à modifier la classe PHP qui crée les employés et à remplacer la requête générée par le générateur par deux requêtes distinctes.

Voici comment procéder :

  1. Ouvrez le fichier admin/class/crud/Projects.php dans votre éditeur de code
    (remplacez Projets par le nom de votre table)
  2. Recherchez la requête dans le code et supprimez les champs et la jointure qui font référence à la deuxième jointure.
    La partie jointure de la requête commence par $this->join_query = ' LEFT JOIN ...' et la partie champs commence par $qry_start = 'SELECT ...'
  3. Trouvez la partie du code où les enregistrements sont enregistrés. Elle commence par while (!$db->endOfSeek()) { ...
  4. Dans cette boucle, supprimez les résultats qui se réfèrent à la deuxième jointure.
  5. Après la boucle, ajoutez-en une nouvelle pour boucler à l'intérieur de tous les enregistrements et récupérer les enregistrements de la deuxième jointure.
    Dans notre exemple, ce serait :
    for ($i=0 ; $i < $this->records_count ; $i++) { $qry = 'SELECT `employees`.`id` AS `employees_id`, `employees`.`name` AS `employees_name` FROM projects LEFT JOIN `employees` ON `projects`.`employees2_id`=`employees`.`id` WHERE projects.id = ' . $this->id[$i] . ' LIMIT 1' ; $db = new Mysql() ; $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[] = '' ; } }.

Après avoir apporté ces modifications personnalisées au code, si vous devez par la suite reconstruire votre liste READ à partir du générateur, n'oubliez pas que l'outil de comparaison de fichiers est disponible :
Régénérer la liste et les formulaires qui ont été personnalisés (Comment utiliser l'outil de comparaison de fichiers du générateur CRUD)

Bien sûr, cette solution nécessite quelques compétences en codage, si vous avez besoin d'aide, contactez-nous et nous ferons de notre mieux.

Page principale du tutoriel CRUD PHP