如何在不修改Laravel模型的前提下获取其关联的所有外键字段?
Laravel无需修改模型获取外键的实现方案
提供两种不需要改动原有模型代码的实现思路,可根据实际场景选择:
方案1:读取数据库物理外键约束
直接从数据库层读取已经创建的外键约束,不依赖模型关联定义:
use Illuminate\Database\Eloquent\Model; function getModelForeignKeys(Model $model): array { $tableName = $model->getTable(); $schemaManager = $model->getConnection()->getDoctrineSchemaManager(); $foreignKeyObjects = $schemaManager->listTableForeignKeys($tableName); $foreignKeys = []; foreach ($foreignKeyObjects as $foreignKey) { $foreignKeys[] = $foreignKey->getLocalColumns()[0]; } return array_unique($foreignKeys); }
调用方式:
$grades = new Grades(); return getModelForeignKeys($grades); // 输出:['student_id', 'subject_id']
如果运行时报错缺少依赖,执行composer require doctrine/dbal安装对应组件即可。
方案2:解析模型关联定义提取外键
如果项目只在模型中定义了关联、没有创建数据库物理外键,可以通过反射解析模型的belongsTo关联提取外键:
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use ReflectionClass; use ReflectionMethod; function getModelForeignKeysFromRelations(Model $model): array { $modelClass = get_class($model); $reflection = new ReflectionClass($modelClass); $publicMethods = $reflection->getMethods(ReflectionMethod::IS_PUBLIC); $foreignKeys = []; foreach ($publicMethods as $method) { // 过滤Laravel框架自带的方法、带参数的方法,只保留用户自定义的无参方法 if ($method->class !== $modelClass || $method->getNumberOfParameters() > 0) { continue; } try { $relation = $method->invoke($model); if ($relation instanceof BelongsTo) { $foreignKeys[] = $relation->getForeignKeyName(); } } catch (\Throwable $e) { // 忽略非关联类型的普通方法 } } return array_unique($foreignKeys); }
调用方式和返回结果和方案1完全一致。
两种方案的差异:
- 方案1拿到的是数据库真实存在的物理外键,哪怕模型没有写关联也能正常获取
- 方案2拿到的是模型中定义的关联对应的外键,哪怕数据库没有建物理外键也能识别
内容的提问来源于stack exchange,提问作者stefvandentempel
相关产品推荐
相关产品推荐

