如何模仿 Eloquent 与逗号分隔的 id 的关系
How to mimic Eloquent relationship with comma separated ids
我有两个 table,订单和图层。在我的订单 table 中,我将一个数组保存在 layer_id 中,并将其设置为 varchar。我先把它炸开,然后显示记录。我想做的是显示层 table 中的记录,例如 layer_name 列中的名称。我也设置了他们的关系。如果有任何建议,我将不胜感激。
我的控制器:
public function getCheckout(){
$orders = Order::get();
return View::make('checkout')->with('orders', $orders);
}
我的看法:
@forelse($orders as $order)
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{{ $order->style_id }}</h3>
</div>
<div class="panel-body">
<p>Layers you chose</p>
<table class="table">
<tr>
<td>ID</td>
@foreach(explode(',', $order->layer_id) as $layer)
<td>{{ $layer }}</td>
@endforeach
</tr>
</table>
</div>
<div class="panel-footer"><button class="btn btn-primary">Confirm</button></div>
</div>
@empty
<p>Nothing to display</p>
@endforelse
我的模型
Class Order extends Eloquent {
public function layer() {
return $this->belongsTo('Layer', 'layer_id');
}
}
我的第一个建议是标准化你的数据库。在 Eloquent ORM 的上下文中,您不能为此使用内置关系。
但是出于好奇,您应该这样做:
通过以下设置,您可以:
// 1. Use layers like eloquent dynamic property
$order->layers; // collection of Layer models
// 2. Call the query to fetch layers only once
$order->layers; // query and set 'relation'
// ... more code
$order->layers; // no query, accessing relation
// 3. Further query layers like you would with relationship as method:
$order->layers()->where(..)->orderBy(..)->...->get();
// 4. Associate layers manually providing either array or string:
$order->layer_ids = '1,5,15';
$order->layer_ids = [1,5,15];
但你不能:
// 1. Eager/Lazy load the layers for multiple orders
$orders = Order::with('layers')->get(); // WON'T WORK
// 2. Use any of the relationship methods for associating/saving/attaching etc.
$order->layers()->associate(..); // WON'T WORK
但您可以执行以下操作(我建议将 layer_id
重命名为 layer_ids
,这样不言自明,我的示例涵盖了该更改):
/**
* Accessor that mimics Eloquent dynamic property.
*
* @return \Illuminate\Database\Eloquent\Collection
*/
public function getLayersAttribute()
{
if (!$this->relationLoaded('layers')) {
$layers = Layer::whereIn('id', $this->layer_ids)->get();
$this->setRelation('layers', $layers);
}
return $this->getRelation('layers');
}
/**
* Access layers relation query.
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function layers()
{
return Layer::whereIn('id', $this->layer_ids);
}
/**
* Accessor for layer_ids property.
*
* @return array
*/
public function getLayerIdsAttribute($commaSeparatedIds)
{
return explode(',', $commaSeparatedIds);
}
/**
* Mutator for layer_ids property.
*
* @param array|string $ids
* @return void
*/
public function setLayersIdsAttribute($ids)
{
$this->attributes['layers_ids'] = is_string($ids) ? $ids : implode(',', $ids);
}
编辑:当然,您可以在您看来简单地这样做。它符合您当前的代码,但显然与我的建议相去甚远;)
@foreach (Layer::whereIn('id', explode(',', $order->layer_id))->get() as $layer)
{{ $layer->whatever }}
我创建了一个包,允许您使用 JSON 数组定义多对多关系:
https://github.com/staudenmeir/eloquent-json-relations
你可以这样使用它:
class Order extends Model {
use \Staudenmeir\EloquentJsonRelations\HasJsonRelationships;
protected $casts = [
'layer_id' => 'json',
];
public function layers() {
return $this->belongsToJson(Layer::class, 'layer_id');
}
}
class Layer extends Model {
use \Staudenmeir\EloquentJsonRelations\HasJsonRelationships;
public function orders() {
return $this->hasManyJson(Order::class, 'layer_id');
}
}
我有两个 table,订单和图层。在我的订单 table 中,我将一个数组保存在 layer_id 中,并将其设置为 varchar。我先把它炸开,然后显示记录。我想做的是显示层 table 中的记录,例如 layer_name 列中的名称。我也设置了他们的关系。如果有任何建议,我将不胜感激。
我的控制器:
public function getCheckout(){
$orders = Order::get();
return View::make('checkout')->with('orders', $orders);
}
我的看法:
@forelse($orders as $order)
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{{ $order->style_id }}</h3>
</div>
<div class="panel-body">
<p>Layers you chose</p>
<table class="table">
<tr>
<td>ID</td>
@foreach(explode(',', $order->layer_id) as $layer)
<td>{{ $layer }}</td>
@endforeach
</tr>
</table>
</div>
<div class="panel-footer"><button class="btn btn-primary">Confirm</button></div>
</div>
@empty
<p>Nothing to display</p>
@endforelse
我的模型
Class Order extends Eloquent {
public function layer() {
return $this->belongsTo('Layer', 'layer_id');
}
}
我的第一个建议是标准化你的数据库。在 Eloquent ORM 的上下文中,您不能为此使用内置关系。
但是出于好奇,您应该这样做:
通过以下设置,您可以:
// 1. Use layers like eloquent dynamic property
$order->layers; // collection of Layer models
// 2. Call the query to fetch layers only once
$order->layers; // query and set 'relation'
// ... more code
$order->layers; // no query, accessing relation
// 3. Further query layers like you would with relationship as method:
$order->layers()->where(..)->orderBy(..)->...->get();
// 4. Associate layers manually providing either array or string:
$order->layer_ids = '1,5,15';
$order->layer_ids = [1,5,15];
但你不能:
// 1. Eager/Lazy load the layers for multiple orders
$orders = Order::with('layers')->get(); // WON'T WORK
// 2. Use any of the relationship methods for associating/saving/attaching etc.
$order->layers()->associate(..); // WON'T WORK
但您可以执行以下操作(我建议将 layer_id
重命名为 layer_ids
,这样不言自明,我的示例涵盖了该更改):
/**
* Accessor that mimics Eloquent dynamic property.
*
* @return \Illuminate\Database\Eloquent\Collection
*/
public function getLayersAttribute()
{
if (!$this->relationLoaded('layers')) {
$layers = Layer::whereIn('id', $this->layer_ids)->get();
$this->setRelation('layers', $layers);
}
return $this->getRelation('layers');
}
/**
* Access layers relation query.
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function layers()
{
return Layer::whereIn('id', $this->layer_ids);
}
/**
* Accessor for layer_ids property.
*
* @return array
*/
public function getLayerIdsAttribute($commaSeparatedIds)
{
return explode(',', $commaSeparatedIds);
}
/**
* Mutator for layer_ids property.
*
* @param array|string $ids
* @return void
*/
public function setLayersIdsAttribute($ids)
{
$this->attributes['layers_ids'] = is_string($ids) ? $ids : implode(',', $ids);
}
编辑:当然,您可以在您看来简单地这样做。它符合您当前的代码,但显然与我的建议相去甚远;)
@foreach (Layer::whereIn('id', explode(',', $order->layer_id))->get() as $layer)
{{ $layer->whatever }}
我创建了一个包,允许您使用 JSON 数组定义多对多关系:
https://github.com/staudenmeir/eloquent-json-relations
你可以这样使用它:
class Order extends Model {
use \Staudenmeir\EloquentJsonRelations\HasJsonRelationships;
protected $casts = [
'layer_id' => 'json',
];
public function layers() {
return $this->belongsToJson(Layer::class, 'layer_id');
}
}
class Layer extends Model {
use \Staudenmeir\EloquentJsonRelations\HasJsonRelationships;
public function orders() {
return $this->hasManyJson(Order::class, 'layer_id');
}
}