mouf / schema-analyzer
一个提供分析数据库模式(基于Doctrine DBAL)实用工具的包
v2.0.0-beta.2
2024-02-01 11:52 UTC
Requires
- php: ^7.4 || ^8.0
- clue/graph: ~0.9.0
- doctrine/cache: ^1.4.1
- doctrine/dbal: ^3.0
- graphp/algorithms: ~0.8.0
Requires (Dev)
- php-coveralls/php-coveralls: ^2.7.0
- phpunit/phpunit: ^9.6.16
README
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
接收一个表名作为参数,并返回代表此表与其父表之间关系的DBALForeignKeyConstraint
。getChildrenRelationships
接收一个表名作为参数,并返回一个数组,其中包含代表此表与其子表之间关系的DBALForeignKeyConstraint
。
$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);