Laravel:如何通过约定自动获取关联外键
自动获取翻译模型的外键字段名
问题背景
现有两张数据表:
products: id, slug... product_translations: id, product_id, name
当前处理多语言翻译模型(比如ProductTranslation、PostTranslation)的upsert操作时,要么手动指定外键字段(如product_id、post_id),要么在每个翻译模型里定义$foreign_key属性来引用。希望找到更优雅的方式,自动生成这种「单数表名+_id」格式的外键,无需在每个模型里重复定义属性。
优化方案
方案1:利用Eloquent内置属性直接推导
Laravel的Eloquent模型自带可直接利用的方法,不用额外定义属性:
- 从主模型实例推导:如果代码在主模型(如
Product)类中调用翻译模型,直接用$this->getForeignKey()方法,它会自动返回「模型单数名称+_id」格式的外键名:
// 在Product模型类中 $this->translationModel()->upsert($upsertData, ['id', $this->getForeignKey(), 'locale']);
- 从翻译模型反向推导:若需从翻译模型(如
ProductTranslation)获取关联外键,可先获取关联的主模型,再调用getForeignKey():
// 通用逻辑中,假设翻译模型与主模型的关联名为主模型单数名 $baseModelName = Str::singular(Str::replaceLast('_translations', '', $translationModel->getTable())); $foreignKey = $translationModel->{$baseModelName}()->getForeignKey();
方案2:创建翻译模型基类
如果存在多个翻译模型(ProductTranslation、PostTranslation等),可以创建一个基类,在基类中自动计算外键字段,所有翻译模型继承该基类即可:
use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Str; class Translation extends Model { public function getForeignKeyName() { // 从表名推导:去掉_translations后缀,转单数后加_id $baseTableName = Str::replaceLast('_translations', '', $this->getTable()); $baseModelName = Str::singular($baseTableName); return "{$baseModelName}_id"; } }
具体翻译模型只需继承基类,无需再定义$foreign_key:
class ProductTranslation extends Translation { // 无需额外定义属性 }
使用时直接调用基类方法:
$this->translationModel()->upsert($upsertData, ['id', $translationModel->getForeignKeyName(), 'locale']);
方案3:通过关联关系获取
确保翻译模型与主模型定义正确的belongsTo关联:
class ProductTranslation extends Model { public function product() { return $this->belongsTo(Product::class); } }
之后可通过关联实例获取外键:
$foreignKey = $translationModel->product()->getForeignKey();
这种方式贴合Laravel的关联设计规范,逻辑更直观。
内容的提问来源于stack exchange,提问作者ronrun
相关产品推荐
相关产品推荐

