如何模仿与逗号分隔的ID的雄辩关系

时间:2015-01-12 09:37:57

标签: database laravel eloquent

我有两个表,订单和图层。在我的订单表中,我在layer_id中保存了一个数组,我已将其设置为varchar。我先爆炸它然后显示记录。我想做的是显示层表中的记录,例如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');
    }
}

2 个答案:

答案 0 :(得分:11)

我的第一个建议是规范化数据库。在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 }}

答案 1 :(得分:2)

我创建了一个程序包,可让您使用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');
    }
}