mouf/schema-analyzer

一个提供分析数据库模式(基于Doctrine DBAL)实用工具的包

v2.0.0-beta.2 2024-02-01 11:52 UTC

README

Latest Stable Version Latest Unstable Version License Scrutinizer Code Quality Build Status Coverage Status

DBAL模式分析器

本包提供分析数据库模式的实用函数。它基于Doctrine DBAL构建。

在本包中,您可以找到

  • 自动检测 连接表 的函数
  • 基于模式中存储的关系计算两个表之间最短路径的函数

安装

您可以通过Composer安装此包

{
    "require": {
        "mouf/schema-analyzer": "~1.0"
    }
}

该包遵循 SemVer 规范,并且次要版本之间将保持完全向后兼容。

检测连接表

起点始终是DBAL模式。将模式管理器传递给SchemaAnalyzer,然后,简单地调用函数。

// $conn is the DBAL connection.
$schemaAnalyzer = new SchemaAnalyzer($conn->getSchemaManager());

// Let's detect all junctions tables
$tables = $schemaAnalyzer->detectJunctionTables();
// This will return an array of Doctrine\DBAL\Schema\Table objects

一个 连接表 是一个表

  • 它恰好有 两个外键
  • 它只有 两列(如果其中一个是 自增主键,则可以是 三列)。

您可以使用可选参数与 detectJunctionTables 一起使用,以自动忽略由其他表的外键引用的任何连接表。

// Get all junction tables except the ones that are references by a foreign key.
$tables = $schemaAnalyzer->detectJunctionTables(true);

检测表之间的继承关系

关于继承关系

如果“用户”表的主键也是一个指向“联系”表的外键,则“用户”表被认为是“联系”表的子表。这是因为您不能在“用户”表中创建没有与“联系”表中具有相同ID的行的行。

因此,“用户”ID必须匹配“联系”,但“联系”不一定有一个“用户”相关联。

检测继承关系

您可以使用 SchemaAnalyzer 来检测父子关系。

  • getParentRelationship 接收一个表名作为参数,并返回代表此表与其父表之间关系的DBAL ForeignKeyConstraint
  • getChildrenRelationships 接收一个表名作为参数,并返回一个数组,其中包含代表此表与其子表之间关系的DBAL ForeignKeyConstraint
$parentKeyConstraint = $schemaAnalyzer->getParentRelationship("user");
/* @var $parentKeyConstraint ForeignKeyConstraint */
$parent = $parentKeyConstraint->getForeignTableName();
// This will return the "contact" table (as a string)

$childrenKeyConstraints = $schemaAnalyzer->getChildrenRelationships("contact");
/* @var $childrenKeyConstraints ForeignKeyConstraint[] */
$children = array_map(function($item) { return $item->getLocalTableName(); }, $childrenKeyConstraints);
// This will return an array of tables whose parent is contact: ["user"]

计算两个表之间的最短路径

根据外键,getShortestPath 函数将尝试找到两个表之间的最短路径。它将返回它用来链接两个表的外键列表。

内部机制

  • 每个外键有一个 成本 为 1
  • 连接表有一个 成本 为 1.5,而不是 2(每个外键一个)
  • 代表继承关系的外键(即绑定两个表主键的外键)有一个 成本 为 0.1
// $conn is the DBAL connection.
$schemaAnalyzer = new SchemaAnalyzer($conn->getSchemaManager());

// Let's detect the shortest path between 2 tables:
$fks = $schemaAnalyzer->getShortestPath("users", "rights");
// This will return an array of Doctrine\DBAL\Schema\ForeignKeyConstraint objects
请注意!最短路径基于外键的 成本。可能存在多个最短路径(如果有几个路径具有相同的总成本)。如果有多个最短路径,SchemaAnalyzer 将抛出 ShortestPathAmbiguityException。异常消息详细说明了所有可能的最短路径。

缓存结果

分析完整数据模型和查找最短路径可能需要很长时间。对于应在生产环境中运行的内容,建议缓存结果。SchemaAnalyzer 可以传递 Doctrine 缓存和缓存前缀。缓存前缀是一个字符串,将用作所有缓存键的前缀。这有助于避免多个数据库之间的缓存冲突。

使用方法

// $conn is the DBAL connection.
// Let's use the ApcCache (or any other Doctrine cache...)
$cache = new ApcCache();
$schemaAnalyzer = new SchemaAnalyzer($conn->getSchemaManager(), $cache, "my_prefix");

改变外键的成本以更改最短路径

如果您遇到歧义异常或最短路径根本不适合您,您可以更改外键的成本。

$schemaAnalyzer->setForeignKeyCost($tableName, $columnName, $cost);

$cost 可以是任何数字。请记住,外键的默认成本为 1

SchemaAnalyzer 包含一组默认常量,以帮助您处理成本

  • SchemaAnalyzer::WEIGHT_IMPORTANT (0.75) 用于应优先跟随的外键
  • SchemaAnalyzer::WEIGHT_IRRELEVANT (2) 用于应一般避免的外键
  • SchemaAnalyzer::WEIGHT_IGNORE (无穷大) 用于不应作为最短路径一部分使用的外键

另一种选择是向表中添加成本修饰符。这将更改指向或来自此表的所有外键的成本。

$schemaAnalyzer->setTableCostModifier($tableName, $cost);