zoukankan      html  css  js  c++  java
  • 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请联系本人,转载需注明出处。

  • 相关阅读:
    前端框架AngularJS入门
    springcloud---Eureka yml
    springcloud 的Eureka配置
    虚拟机中文件和目录的相关操作
    SpringBoot整合Redis
    IDEA整合GIT操作
    Ubuntu 安装步骤
    Centos 7 安装
    Centos 6 安装步骤
    防止root口令被破解
  • 原文地址:https://www.cnblogs.com/GaZeon/p/6025736.html
Copyright © 2011-2022 走看看