PHP获取某个表与其他表的关联关系算法
如图 电影movie有多个附表,如果通过movie表来找出多个与之关联的表。

本算法规则:
- 外键写法必须是X_id;
- 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请联系本人,转载需注明出处。
PHP获取某个表与其他表的关联关系算法的更多相关文章
- [js开源组件开发]query组件,获取url参数和form表单json格式
query组件,获取url参数和form表单json格式 距离上次的组件[js开源组件开发]ajax分页组件一转眼过去了近二十天,或许我一周一组件的承诺有了质疑声,但其实我一直在做,只是没人看到……, ...
- 获取SQLSERVER所有库 所有表 所有列 所有字段信息
最近想起来做一个项目代码生成器,直接生成底层代码.. 这免不了要先行读取数据库已有的信息.. 废话不多说..开整.. SELECT NAME FROM MASTER..SYSDATABASES --读 ...
- SQL获取所有数据库名、表名、储存过程以及参数列表
SQL获取所有数据库名.表名.储存过程以及参数列表 1.获取所有用户名:SELECT name FROM Sysusers where status='2' and islogin='1'islogi ...
- sql 2000以及2005以上获取数据库中所有的表(不包括系统表)
---------------------------------------------------------------------------- --sql 2005以上数据库 --- 获取数 ...
- jquery不能是使用普通的for循环 因为普通的for循环通过下表获取对象 如果通过下表获取对象的话 会转成dom对象
jquery不能是使用普通的for循环 因为普通的for循环通过下表获取对象 如果通过下表获取对象的话 会转成dom对象
- Oracle 获取 某个表的建表SQL
获取A表的创表SQL select dbms_metadata.get_ddl('TABLE','A') from dual
- Sqlserver获取所有数据库名,表信息,字段信息,主键信息,以及表结构等。
--获取所有数据库名: SELECT name FROM master..sysdatabases WHERE name NOT IN ( 'master', 'model', 'msdb', 'te ...
- sql脚本来获取数据库中的所有表结构了
sql脚本来获取数据库中的所有表结构了,代码如下: use AdventureWorks2008 go SELECT (case when a.colorder=1 then d.name else ...
- SqlServer中获取所有数据库,所有表,所有字段
原文:SqlServer中获取所有数据库,所有表,所有字段 一.获取所有数据库 select * from master.dbo.SysDatabases 二.获取某个库中所有表 SELECT * F ...
随机推荐
- HTML5+CSS3+Jquery实现纯手工的垂直时光轴【附源码】
前言 由于工作中需要,系统中需要记录不同时间发生的事件,为了提升用户体验,决定用时光轴来实现.[据说这个东西挺火的,QQ空间和FB都在用...] 这个时光轴是在 三生石上 这位博主的时光轴基础上修改的 ...
- BZOJ 3105 [CQOI2013]新Nim游戏 ——线性基
[题目分析] 神奇的题目,两人都可以第一次取走足够多堆的石子. nim游戏的规则是,如果异或和为0,那么就先手必输,否则先手有必胜策略. 所以只需要剩下一群异或和为0就可以了. 先排序,线性基扫一遍即 ...
- EF中执行sql语句,以及事务
EF to sql string sql = "select T_Task.BSID,T_Task.CloseDate,T_Task.CompleteDate,T_Task.CloseUse ...
- JavaScript变量和作用域
认识JavaScript中的变量 JavaScript中的变量有两种类型,一种是基本类型.一种是引用类型. 基本数据类型:Defined,Null,Boolean,Number,String.注意St ...
- bzoj4364: [IOI2014]wall砖墙
线段树打标记的好(luo)题 打打标记,记得下移 = =听说2000000是用来卡线段树的 = =怎么办呢,,, = =打个读入优化看看能不能卡过去吧 #include<cstdio> # ...
- BICEP单元测试——随机四则运算升级版
一.测试方法 6个值得测试的具体部位: Right-结果是否正确? B-是否所有的边界条件都是正确的? I-能查一下反向关联吗? C-能用其他手段交叉检查一下结果吗? E-你是否可以强制错误条件发生? ...
- java 将一张图片拷贝到另外一个地方。(IO流)
package com.beiwo.inputstream; import java.io.FileInputStream; import java.io.FileOutputStream; impo ...
- oracle优化
sql语句 优化方式: 1select 语句中避免用"*" oracle在解析时,会将“*”依次转换成所有的列名(数据字典完成)耗时 2尽量多用commit语句 及时提交,释放资源 ...
- mount windows-linux文件共享
. (2)在linux下访问windows共享: smbclient -L 192.168.2.12 -U admin //查看共享了那些目录,由此知道主机名为XIAOXING-PC smbcli ...
- struts基于ognl的自动类型转换需要注意的地方
好吧,坎坷的过程我就不说了,直接上结论: 在struts2中使用基于ognl的自动类型转换时,Action中的对象属性必须同时添加get/set方法. 例如: 客户端表单: <s:form ac ...