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

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

本算法规则:

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

 

算法如下:

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

 1 function findRelation($db=['dbname','user','pwd','host'],$current,$father='')
 2 {
 3     static $pdo;
 4     if(empty($father))
 5     {
 6         $pdo=new PDO("mysql:host=".(isset($db[3])?$db[3]:'localhost').";dbname={$db[0]}",$db[1],(isset($db[2])?$db[2]:''));
 7         $pdo->exec('set names utf8');
 8     }
 9     
10     //临时数组,保存下面运行得出的数据
11     $tp=[];
12     
13     //当前表的所有字段信息
14     $self=$pdo->query('show full columns from '.$current);
15     
16     //当前表是否中间表
17     $is_middle=0;
18     
19     //检查当前表是否有附表id字段
20     while($row = $self -> fetch())
21     {
22         //如果有发现以xxx_id命名的外键
23         if(stripos($row['Field'],'_id')!==FALSE)
24         {
25             //获取附表名
26             $extName=str_ireplace('_id','',$row['Field']);
27             
28             //如果当前的”附表“ 名是父表名,记录保存字段
29             if($extName==$father)
30             {
31                 $tp['_field'][$row['Field']]=[$row['Type'],$row['Default'],$row['Comment'],'parent_index'];
32     
33                 continue;
34             }
35             else
36             {
37                 //当前表包含有 当前表外键中的附表名(即main_extName 包含有 extName_id),则此表为中间表
38                 if(strpos($current,$extName)!==FALSE)
39                     $is_middle=1;
40                 
41                 //记录字段信息
42                 $tp['_field'][$row['Field']]=[$row['Type'],$row['Default'],$row['Comment'],'next_index'];
43     
44                 //继续往下寻找附表关系        
           $tp[$extName]=findRelation($db,$extName,$current);
45 46 47 } 48 } 49 else//没发现外键,记录当前字段 50 { 51 $tp['_field'][$row['Field']]=[$row['Type'],$row['Default'],$row['Comment'],$row['Key']]; 52 } 53 } 54 55 //记录当前表是否中间表 56 if($is_middle) 57 $tp['_type']='middle'; 58 else 59 $tp['_type']='content'; 60 61 //获取当前表注释 62 $cms=$pdo->query("show table status from {$db[0]} where name='{$current}'"); 63 $one=$cms->fetch(); 64 $tp['_comment']=$one['Comment']; 65 66 //扫描以【当前表】_为开头的附表 67 $exts=$pdo->query('show tables like "'.$current.'_%"'); 68 while($ext = $exts -> fetch()) 69 { 70 //往下寻找当前表与每个附表的关系 71 $tp[$ext[0]]=findRelation($db,$ext[0],$current); 72 } 73 74 return $tp;//返回已记录的关联关系和字段信息 75 } 76 77 echo '<pre>'; 78 print_r(['movie'=>findRelation(['movieshop','root'],'movie')]); 79 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请联系本人,转载需注明出处。

 

posted @ 2016-11-03 10:57  GaZeon  阅读(984)  评论(0编辑  收藏  举报