Order
有许多订购商品
Order
的订购商品可以是User
或Product
我正在寻找的是一种将所有变形对象检索到Order
的方法。而不是$order->users
或$order->products
我想$order->items
。
到目前为止,我的进展涉及Many To Many Polymorphic Relationship。
我的表格:
orders
id - integer
orderables (the order items)
order_id - integer
orderable_id - integer
orderable_type - string
quantity - integer
price - double
-----------
users
id - integer
name - string
products
id - integer
name - string
这是我创建订单并添加用户和产品的方式:
/**
* Order
* @var Order
*/
$order = new App\Order;
$order->save();
/**
* Add user to order
* @var [type]
*/
$user = \App\User::find(1);
$order->users()->sync([
$user->id => [
'quantity' => 1,
'price' => $user->price()
]
]);
/**
* Add product to order
* @var [type]
*/
$product = \App\product::find(1);
$order->products()->sync([
$product->id => [
'quantity' => 1,
'price' => $product->price()
]
]);
Order.php
/**
* Ordered users
* @return [type] [description]
*/
public function users() {
return $this->morphedByMany('Athliit\User', 'orderable');
}
/**
* Ordered products
*/
public function products() {
return $this->morphedByMany('Athliit\Product', 'orderable');
}
目前我可以做到
foreach($order->users as $user) {
echo $user->id;
}
或..
foreach($order->products as $product) {
echo $product->id;
}
但我希望能够按照......的方式做点什么。
foreach($order->items as $item) {
// $item is either User or Product class
}
我发现了this问题,这是我能找到的最接近我想要做的事情,但我不能让它在我的需求方面发挥作用,它已经过时了,也似乎是一个非常讨厌的解决方案。
有不同的方法吗?
如果您的方法与多态关系不同,请告诉我。
答案 0 :(得分:3)
就个人而言,我的Order
模型有很多OrderItems
,OrderItems
具有多态关系。这样,我可以获取订单的所有项目,无论它们是什么类型的模型:
class Order extends Model
{
public function items()
{
return $this->hasMany(OrderItem::class);
}
public function addItem(Orderable $item, $quantity)
{
if (!is_int($quantity)) {
throw new InvalidArgumentException('Quantity must be an integer');
}
$item = OrderItem::createFromOrderable($item);
$item->quantity = $quantity;
$this->items()->save($item);
}
}
class OrderItem extends Model
{
public static function createFromOrderable(Orderable $item)
{
$this->orderable()->associate($item);
}
public function order()
{
return $this->belongsTo(Order::class);
}
public function orderable()
{
return $this->morphTo('orderable');
}
}
然后我将创建一个界面和特征,我可以应用于使其“可订购”的Eloquent模型:
interface Orderable
{
public function getPrice();
}
trait Orderable
{
public function orderable()
{
return $this->morphMany(OrderItem::class, 'orderable');
}
}
use App\Contracts\Orderable as OrderableContract; // interface
use App\Orderable; // trait
class Product extends Model implements OrderableContract
{
use Orderable;
}
class EventTicket extends Model implements OrderableContract
{
use Orderable;
}
如您所见,我的OrderItem
实例可以是Product
,EventTicket
,也可以是实现Orderable
接口的任何其他模型。然后,您可以获取所有订单的商品,如下所示:
$orderItem = Order::find($orderId)->items;
OrderItem
实例变换为什么类型并不重要。
编辑:要向订单添加商品:
// Create an order instance
$order = new Order;
// Add an item to the order
$order->addItem(User::find($userId), $quantity);
答案 1 :(得分:0)
我认为您的解决方案很好。我只是添加这个辅助方法:
Order.php
public function items() {
return collect($this->products)->merge($this->users);
}
然后你可以用以下内容遍历项目:
foreach ($order->items() as $item) {