【问题标题】:How to mimic Eloquent relationship with comma separated ids如何用逗号分隔的 id 模拟 Eloquent 关系
【发布时间】:2015-03-10 00:57:48
【问题描述】:

我有两个表,订单和层。在我的订单表中,我将一个数组保存在 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');
    }
}

【问题讨论】:

    标签: database laravel eloquent


    【解决方案1】:

    我的第一个建议是标准化您的数据库。在 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);
    }
    

    edit:当然,您可以在您的视图中简单地执行此操作。它符合您当前的代码,但显然与我的建议相去甚远;)

    @foreach (Layer::whereIn('id', explode(',', $order->layer_id))->get() as $layer)
      {{ $layer->whatever }}
    

    【讨论】:

    • 我有同样的情况,在刀片中使用更容易,非常感谢
    【解决方案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');
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2018-10-22
      • 1970-01-01
      • 1970-01-01
      • 2019-08-19
      • 1970-01-01
      • 2013-10-22
      • 2019-03-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多