MySQL - Duas chaves estrangeiras apontando para a mesma tabela

Apontar duas chaves estrangeiras para uma única tabela é um caso limite. Se possível, é melhor modificar a estrutura do seu banco de dados. Caso contrário, o senhor terá de editar o código da lista READ.


Sobre estruturas que usam duas juntas em uma única mesa

Usar duas uniões para a mesma tabela é uma estrutura perfeitamente lógica em alguns casos, mas esse tipo de estrutura geralmente não é prático.

Vamos dar um exemplo simples:

MySQL two joins to the same table example
Exemplo de uma tabela MySQL com duas uniões para a mesma tabela

Para selecionar registros da tabela de projetos, precisamos usar esse tipo de consulta:

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

Essa consulta usa aliases nos campos da tabela de pessoas, mas também para o nome da própria tabela, pois ela é consultada duas vezes (uma para cada união).

Essa não é a solução correta. O PHPCG usa um sistema de filtro avançado que permite pesquisar e filtrar registros nas suas listas, mas não suporta o uso de aliases para tabelas.

Há duas soluções alternativas.


Primeira solução: alterar a estrutura do seu banco de dados

No exemplo acima, a tabela de pessoas agrupa duas entidades diferentes na mesma tabela: gerentes e funcionários.

Essa não é uma boa ideia. É sempre melhor criar uma tabela para cada tipo de dados (cada entidade).

MySQL two joins to two distinct tables
Exemplo de uma tabela MySQL com duas uniões a duas tabelas distintas

Segunda solução: editar manualmente a consulta SQL da lista READ

Vamos usar uma estrutura um pouco diferente:

MySQL two joins to the same table example 2
Tabela MySQL com duas junções para a mesma tabela - Exemplo 2

Nesse segundo caso, a tabela de projetos se refere a dois funcionários.
Não seria coerente criar duas tabelas para os funcionários, pois eles representam uma entidade única.

A solução é editar a classe PHP que cria os funcionários e substituir a consulta gerada pelo gerador por duas consultas separadas.

Veja como fazer isso:

  1. Abra o arquivo admin/class/crud/Projects.php em seu editor de código
    (substitua Projects pelo nome da tabela)
  2. Localize a consulta no código e exclua os campos e a união que se referem à segunda união.
    A parte da junção da consulta começa com $this->join_query = ' LEFT JOIN ...' e a parte dos campos começa com $qry_start = 'SELECT ...'
  3. Localize a parte do código em que os registros são registrados. Ela começa com while (!$db->endOfSeek()) { ...
  4. Nesse loop, remova os resultados que se referem à segunda união
  5. Após o loop, adicione um novo loop dentro de todos os registros e obtenha os registros da segunda união.
    Em nosso exemplo, isso seria:
    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 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[] = ''; } }

Depois de fazer essas alterações personalizadas no código, se mais tarde o senhor tiver que reconstruir sua lista READ a partir do gerador, não se esqueça de que a ferramenta de comparação de arquivos está disponível:
Regenerate list & forms that have been customized (Como usar a ferramenta de comparação de arquivos do CRUD Generator)

É claro que essa solução requer algumas habilidades de codificação. Se o senhor precisar de ajuda, entre em contato conosco e faremos o possível.

Página principal do tutorial PHP CRUD