Laravel 5.6 OneToOne 关系不起作用
Posted
技术标签:
【中文标题】Laravel 5.6 OneToOne 关系不起作用【英文标题】:Laravel 5.6 OneToOne relation not working 【发布时间】:2019-04-18 17:39:48 【问题描述】:我有一个 BuildingImage 模型,它与 BuildingType 具有 OneToOne 关系:
BuildImage 模型:
/**
* Get the source type of the Building Image.
*/
public function type()
return $this->hasOne('App\BuildingType');
建筑类型模型:
/**
* Get the Building Image that owns the building type.
*/
public function buildingImage()
return $this->belongsTo('App\BuildingImage');
我的桌子:
building_images 表 -> source 是建筑类型 id
building_types 表
当我尝试在我的控制器中执行此操作只是为了测试时: (一个 ImageRequest 有一个或多个建筑,一个建筑有一个 BuildingType)
$imageRequest = ImageRequest::findOrFail($id);
$buildings = $imageRequest->buildingImages;
foreach ($buildings as $building)
dd($building->type);
我收到此错误:
SQLSTATE[42S22]:未找到列:1054 未知列 “where 子句”中的“building_types.building_image_id”(SQL:选择 * 来自
building_types
其中building_types
.building_image_id
= 45 并且building_types
.building_image_id
不为空限制 1)
我在这里做错了什么?
【问题讨论】:
【参考方案1】:这是因为默认情况下,laravel 会查找一个名为 model_id
的主键,并且鉴于您使用的是不同的列名 (source
),因此您需要在定义关系时指定:
作为文档states:
Eloquent 根据模型名称确定关系的外键。在这种情况下,
Phone
模型被自动假定为具有user_id
外键。如果您希望覆盖此约定,您可以将第二个参数传递给hasOne
方法:return $this->hasOne('App\Phone', 'foreign_key');
此外,Eloquent 假设外键的值应该与父列的
id
(或自定义的$primaryKey
)相匹配。也就是说,Eloquent 会在Phone
记录的user_id
列中查找用户id 列的值。如果您希望关系使用 id 以外的值,您可以将第三个参数传递给hasOne
方法,指定您的自定义键:return $this->hasOne('App\Phone', 'foreign_key', 'local_key');
现在这很清楚了。让我们谈谈关系本身。
您正在定义一个BuildImage
有一个BuildingType
。但是按照这种逻辑,外键应该存储在building_types
表中,而不是相反(source
列出现在building_images
表中)。而且-我只是假设-许多BuildImage
可以属于特定的BuildingType
。所以,如果这个假设是正确的:
BuildImage
属于特定的BuildingType
。
BuildinType
可以在多个BuildImage
s 中指定
所以,你应该这样定义你的关系:
BuildImage.php
public function type()
return $this->belongsTo('App\BuildingType', 'source');
BuildingType.php
public function images()
return $this->hasMany(BuildingImage::class, 'source');
【讨论】:
所以我必须在你的代码示例中的“foreign_key”中填写“source”? @Michael 我会更新的。但我认为你应该对你们的关系有所不同。 您也可以使用类代替字符串,有些人(包括我自己)倾向于使用字符串。return $this->hasOne(App\Phone::class, 'foreign_key', 'local_key');
@JohnHalsey 是的,确实如此。很好的观察,我会把它包括在内。【参考方案2】:
您是否尝试过这样表示索引 ID?
public function buildingImage()
return $this->belongsTo('App\BuildingImage', 'image_request_id');
Eloquent 根据 型号名称。在这种情况下,电话模型被自动假定为 有一个 user_id 外键。如果您希望覆盖此约定, 您可以将第二个参数传递给 hasOne 方法:
return $this->hasOne('App\Phone', 'foreign_key');
https://laravel.com/docs/5.7/eloquent-relationships#one-to-one
【讨论】:
【参考方案3】:你的 BuildImage 模型应该是
/** * 获取建筑物图像的来源类型。 */
public function type()
return $this->hasOne('App\BuildingType',"id","source");
而 BuildingType 模型应该是
/** * 获取拥有该建筑类型的建筑图像。 */
public function buildingImage()
return $this->belongsTo('App\BuildingImage',"source","id");
这应该可行。 欲了解更多信息,请查看 https://laravel.com/docs/5.7/eloquent-relationships#one-to-one
【讨论】:
以上是关于Laravel 5.6 OneToOne 关系不起作用的主要内容,如果未能解决你的问题,请参考以下文章
barryvdh/laravel-cors 配置在 Laravel 5.6 中不起作用;忽略'allowedMethods'
Laravel 5.6 护照 API 身份验证在获取请求中不起作用