我有三个模型:Order
、OrderItem
和Product
(为简单起见,仅示出关系):
第一个
使用其各自的DB表:
orders: id, status, subtotal, total
order_items: id, order_id, product_id, qty, price, total
products: id, name, slug, sku, description, price
我只有一个用于Order
和Product
的控制器,但我有用于所有3个控制器的资源:
第一个
当点击我的订单控制器时,我返回如下数据(在本例中用于显示订单):
public function show(Order $order): JsonResponse
{
return (new OrdersResource($order->loadMissing('orderItems')))
->response()
->setStatusCode(Response::HTTP_OK);
}
到此为止就这么走了,返回的顺序是这样的:
{
"data": {
"id": "20d9b0f3-2b32-45a7-8814-12c77210ad50",
"type": "orders",
"attributes": {
"status": "new",
"payment_type": "",
"payment_transaction_no": "",
"subtotal": 71000,
"taxes": 0,
"total": 71000,
"items": [
{
"id": 9,
"product_id": "444b0f3-2b12-45ab-3434-4453121231ad51",
"order_id": "20d9b0f3-2b32-45a7-8814-12c77210ad50",
"qty": 10,
"price": 200,
"total": 2000,
"created_at": "2022-11-05T16:26:07.000000Z",
"updated_at": "2022-11-05T16:28:02.000000Z"
},
{
"id": 10,
"product_id": "324b0f3-2b12-45ab-3434-12312330ad50",
"order_id": "20d9b0f3-2b32-45a7-8814-12c77210ad50",
"qty": 3,
"price": 23000,
"total": 69000,
"created_at": "2022-11-05T16:26:29.000000Z",
"updated_at": "2022-11-05T16:26:29.000000Z"
}
],
"created_at": "2022-11-05T16:26:07.000000Z",
"updated_at": "2022-11-05T16:28:02.000000Z"
}
}
}
但现在我需要返回作为OrderItem
的一部分的实际产品,而不仅仅是产品ID,因此我更新了我的资源以包括:'product' => new ProductsResource($this->whenLoaded('product')),
我资源最终看起来像这样:
public function toArray($request): array
{
return [
'id' => $this->id,
'order_id' => $this->order_id,
'product' => new ProductsResource($this->whenLoaded('product')),
'qty' => $this->qty,
'price' => $this->price,
'total' => $this->total,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
];
}
然而,我的响应中看不到产品,我错过了什么?这不是加载它的正确方式吗?我需要从我的控制器加载它吗?
谢谢
更新
我已经更新了OrderItem
中的关系,现在它看起来如下所示:
public function product(): HasOne
{
return $this->hasOne(Product::class, 'id', 'product_id');
}
其中,id
指向products
表中的id
列,而product_id
是order_item
中的FK。
此时如果我做以下操作:
// just get any orderItem
$orderItem = OrderItem::first();
dd($orderItem->product);
我确实看到关系在工作,因为产品正在打印,但对象仍然不是API响应的一部分,这意味着在我的资源中,此行没有按预期工作:
'product' => new ProductsResource($this->whenLoaded('product')),
更新2
我更新了在资源中加载product
的方式,使其成为以下两种方式之一:
第一个
但这会在已经嵌套的对象上生成一个嵌套对象,如下所示:
{
"data": {
"id": "20d9b0f3-2b32-45a7-8814-12c77210ad50",
"type": "orders",
"attributes": {
"status": "new",
"payment_type": "",
"payment_transaction_no": "",
"subtotal": 71000,
"taxes": 0,
"total": 71000,
"items": [
{
"id": 9,
"order_id": "20d9b0f3-2b32-45a7-8814-12c77210ad50",
"product": {
"id": 9,
"order_id": "20d9b0f3-2b32-45a7-8814-12c77210ad50",
"product_id": "f6bd3290-7748-49fa-8995-e0de47291fc9",
"qty": 10,
"price": 200,
"total": 2000,
"created_at": "2022-11-05T16:26:07.000000Z",
"updated_at": "2022-11-05T16:28:02.000000Z",
"product": {
"id": "f6bd3290-7748-49fa-8995-e0de47291fc9",
"barcode": "010101010101010101",
"name": "Test 5",
"slug": "test-5",
"sku": "t55te345c",
"description": "asd asd asd asd asd",
"type": "goods",
"category_id": 4,
"wholesale_price": 34,
"retail_price": 200,
"base_picture": null,
"current_stock_level": 0,
"active": 1,
"created_at": "2022-09-23T16:29:18.000000Z",
"updated_at": "2022-09-23T22:00:40.000000Z"
}
},
"qty": 10,
"price": 200,
"total": 2000,
"created_at": "2022-11-05T16:26:07.000000Z",
"updated_at": "2022-11-05T16:28:02.000000Z"
}
]
}
}
}
请注意,product
现在如何重新拥有来自items
的数据
3条答案
按热度按时间vngu2lb81#
在控制器中:
chhqkbe12#
有几个问题。
1.您的
Product
模型缺少与OrderItem
的关系。您定义了:而你却缺少了所需的反关系:
1.您的架构似乎不正确。请考虑文档中的
hasOne()
示例。如果User
hasOne()
Phone
,则:在本例中,将自动假定Phone模型具有user_id外键
就模式而言,它意味着
phones
表具有user_id
列。将其与OrderItem
(hasOne()
Product
)进行比较。上面示例中描述的约定意味着products
表应具有order_item_id
列。但实际上没有-您需要添加该列。也许您是以另一种方式(
Product
hasOne
OrderItem
)开始这个相关性,因为您确实有order_items.product_id
数据行,但这不是您所显示相关性的必要项目。您应该移除该字段。1.在
OrderItem
模型中,您已经否决了默认外键并将其指定为id
:这意味着
products
表中的id
列表示OrderItem ID。这没有任何意义,我猜这是不正确的。只要删除关系中的id
,默认约定将意味着Laravel将在products
表中查找order_item_id
字段,完全按照上面2)中的描述。根据我的经验,你几乎不需要覆盖Laravel的默认外键约定,除非你做了一些特别奇怪的事情。即使这样,它也足够复杂,也许值得重新考虑你的模式,只是为了让它匹配预期的约定!
ycl3bljg3#
好的,我终于想通了。感谢@鲍勃和@不要恐慌,他们的答案为我指明了正确的方向。
首先,我需要在
OrderItem
模型中更正我的关系定义,指定当前表和使用相关字段的表中使用的键:但这本身并不足以让我的资源通过以下方式返回预期的数据:
我还需要在控制器中加载关系:
这是最后一步了。再次感谢你们。