PHP获取某个表与其他表的关联关系算法

时间:2023-03-09 16:14:20
PHP获取某个表与其他表的关联关系算法

如图 电影movie有多个附表,如果通过movie表来找出多个与之关联的表。

PHP获取某个表与其他表的关联关系算法

本算法规则:

  1. 外键写法必须是X_id;
  2. A与B 1对多关系,中间表表名必须是A_B,且A_B,必须包含A_id,B_id外键;

算法如下:

---------------------更新-----------------------------------------------

 function findRelation($db=['dbname','user','pwd','host'],$current,$father='')
{
static $pdo;
if(empty($father))
{
$pdo=new PDO("mysql:host=".(isset($db[3])?$db[3]:'localhost').";dbname={$db[0]}",$db[1],(isset($db[2])?$db[2]:''));
$pdo->exec('set names utf8');
} //临时数组,保存下面运行得出的数据
$tp=[]; //当前表的所有字段信息
$self=$pdo->query('show full columns from '.$current); //当前表是否中间表
$is_middle=0; //检查当前表是否有附表id字段
while($row = $self -> fetch())
{
//如果有发现以xxx_id命名的外键
if(stripos($row['Field'],'_id')!==FALSE)
{
//获取附表名
$extName=str_ireplace('_id','',$row['Field']); //如果当前的”附表“ 名是父表名,记录保存字段
if($extName==$father)
{
$tp['_field'][$row['Field']]=[$row['Type'],$row['Default'],$row['Comment'],'parent_index']; continue;
}
else
{
//当前表包含有 当前表外键中的附表名(即main_extName 包含有 extName_id),则此表为中间表
if(strpos($current,$extName)!==FALSE)
$is_middle=1; //记录字段信息
$tp['_field'][$row['Field']]=[$row['Type'],$row['Default'],$row['Comment'],'next_index']; //继续往下寻找附表关系
           $tp[$extName]=findRelation($db,$extName,$current); }
}
else//没发现外键,记录当前字段
{
$tp['_field'][$row['Field']]=[$row['Type'],$row['Default'],$row['Comment'],$row['Key']];
}
} //记录当前表是否中间表
if($is_middle)
$tp['_type']='middle';
else
$tp['_type']='content'; //获取当前表注释
$cms=$pdo->query("show table status from {$db[0]} where name='{$current}'");
$one=$cms->fetch();
$tp['_comment']=$one['Comment']; //扫描以【当前表】_为开头的附表
$exts=$pdo->query('show tables like "'.$current.'_%"');
while($ext = $exts -> fetch())
{
//往下寻找当前表与每个附表的关系
$tp[$ext[0]]=findRelation($db,$ext[0],$current);
} return $tp;//返回已记录的关联关系和字段信息
} echo '<pre>';
print_r(['movie'=>findRelation(['movieshop','root'],'movie')]);
echo '</pre>';

上述算法得出的数据格式如下:

/*

([主表]=>)[
[_field]=>[
[字段名] => [
[0] => 字段类型
[1] => 默认值
[2] => 字段注释
[3] => 字段索引
],
.....
]
, [_type]=>middle/content(多对多中间表/1对多内容表,不是中间表可忽略)
,
[_comment]=>表注释
,
[附表名]=>[
[_field]=>[
[字段名] => [
[0] => 字段类型
[1] => 默认值
[2] => 字段注释
[3] => 字段索引
],
.....
],
[_type]=>middle/content(多对多中间表/1对多内容表,不是中间表可忽略)
,
[_comment]=>表注释
,
[附表名]=>[
.............
]
,
...............
]
,
..........
] */

------------------------------------------------------------------------------旧版---------------------------------------------------------------------------------------

<?php

/*
2016-11-03
GaZeon -------------寻找表关系方法--------------- 主表:main 附表格式:main_extName 可能存在的表:extName 判断主附的对应关系方法: 如果main 有 extName_id 则 main与main_extName 为1对1关系 如果main_extName 【有 且只有 main_id外键】或 【main_extName 有其他外键但不包含extName_id外键 】 则 main与main_extName 为1对多关系 如果main_extName 有 main_id外键,且有 extName_id 外键,则 main与 extName为多对多关系 ,main_extName为中间表 与main为1对多关系 1,获取【当前表】的所有字段,并循环字段查找_id结尾的外键
{
2,如果查找到【当前表】的外键,则判断【外键所在的表】是否【当前表】的【上一级表】:
[如果是,则【外键所在的表】为中间表,【当前表】与【外键所在的表】为1对多关系,跳过本次进入下次循环];
[如果不是,则【当前表】与【外键所在的表】为1对多关系,查找这个【外键所在的表】],
}
3,【当前表】外键查找完后,扫描以【当前表】_为开头的表:
[如果有,则循环轮流进入1程序];
4,没有,当前关联关系到达最终点,返回本次运行得出的关系信息。 -----------------------------------------------------
如果一个表没有任何外键
如果这个表没有附表,则为最终表
如果这个表有附表,则查找其附表,继续寻找其表的关联关系 */
$pdo=new PDO('mysql:host=localhost;dbname=MovieShop','root','');
$pdo->exec('set names utf8');
$relation=[]; function findRelation($current,$father='')
{
global $pdo;
global $relation; //临时数组,保存下面运行得出的数据
$tp=[]; //当前表的所有字段信息
$self=$pdo->query('show full columns from '.$current); //当前表是否中间表
$is_middle=0; //检查当前表是否有附表id字段
while($row = $self -> fetch())
{
//如果有发现以xxx_id命名的外键
if(stripos($row['Field'],'_id')!==FALSE)
{
//获取附表名
$extName=str_ireplace('_id','',$row['Field']); //如果当前的”附表“ 名是父表名,记录保存字段
if($extName==$father)
{
$tp['_field'][$row['Field']]=[$row['Type'],$row['Default'],'parent_index']; continue;
}
else
{
//当前表包含有 当前表外键中的附表名(即main_extName 包含有 extName_id),则此表为中间表
if(strpos($current,$extName)!==FALSE)
$is_middle=1; //记录字段信息
$tp['_field'][$row['Field']]=[$row['Type'],$row['Default'],'next_index']; //继续往下寻找附表关系
$tp[$extName]=findRelation($extName,$current); }
}
else//没发现外键,记录当前字段
{
$tp['_field'][$row['Field']]=[$row['Type'],$row['Default'],$row['Key']];
}
} //记录当前表是否中间表
if($is_middle)
$tp['_type']='middle';
else
$tp['_type']='content'; //扫描以【当前表】_为开头的附表
$exts=$pdo->query('show tables like "'.$current.'_%"');
while($ext = $exts -> fetch())
{
//往下寻找当前表与每个附表的关系
$relation[$current][$ext[0]]=findRelation($ext[0],$current);
} return $tp;//返回已记录的关联关系和字段信息
} findRelation('movie'); echo '<pre>';
print_r($relation);
echo '</pre>';

有bug请联系本人,转载需注明出处。