Laravel Eloquent与keyBy建立关系

时间:2015-06-30 19:44:02

标签: laravel eloquent

我的Product模型与hasMany关系

public function pricing()
    {
        return $this->hasMany('App\ProductPrice', 'prod_id', 'id');
    }

然后我得到了关系

Product::with('pricing')->all();

如何以pricing作为密钥检索id关系。我知道我可以使用CollectionkeyBy('id)上执行此操作,但它不适用于查询。

我希望获得与以下相同的结果,但我希望从Product关系中获得结果。

ProductPrice::keyBy('id')

4 个答案:

答案 0 :(得分:3)

一种快速的解决方法是使用setRelation方法替换数组中的当前关系。就您而言:

$product = Product::with('pricing')->all();
$product->setRelation('pricing', $product->pricing->keyBy('id'));

答案 1 :(得分:2)

您必须创建自己的关系:

<?php

namespace App\Helpers\Classes;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;

class HasManyKeyBy extends HasMany
{
    private $keyBy;

    public function __construct($keyBy, Builder $query, Model $parent, string $foreignKey, string $localKey)
    {
        $this->keyBy = $keyBy;
        parent::__construct($query, $parent, $foreignKey, $localKey);
    }

    public function getResults()
    {
        return parent::getResults()->keyBy($this->keyBy);
    }

    protected function getRelationValue(array $dictionary, $key, $type)
    {
        return parent::getRelationValue($dictionary, $key, $type)->keyBy($this->keyBy);
    }
}

为简单起见,我还建议您创建一个特征:

<?php

namespace App\Helpers\Traits;

use Illuminate\Database\Eloquent\Relations\HasMany;

trait HasManyKeyBy
{
    /**
     * @param $keyBy
     * @param $related
     * @param null $foreignKey
     * @param null $localKey
     * @return HasMany
     */
    protected function hasManyKeyBy($keyBy, $related, $foreignKey = null, $localKey = null)
    {
        // copied from \Illuminate\Database\Eloquent\Concerns\HasRelationships::hasMany

        $instance = $this->newRelatedInstance($related);
        $foreignKey = $foreignKey ?: $this->getForeignKey();
        $localKey = $localKey ?: $this->getKeyName();

        return new \App\Helpers\Classes\HasManyKeyBy($keyBy, $instance->newQuery(),
            $this, $instance->getTable().'.'.$foreignKey, $localKey);
    }
}

现在,您可以将此特征包括到模型中,并使用受$this->hasManyKeyBy保护的方法:

[...]
class Product extends Model
{
    use HasManyKeyBy;

    public function pricing()
    {
        return $this->hasManyKeyBy('id', ProductPrice::class, 'prod_id', 'id');
    }

    [...]
}

答案 2 :(得分:1)

您还可以做的是定义一个DataFrame.groupby

{
  "vertragsdetails" : {
  "deckungen" : [ {
        "bezeichnung" : "A",
        "kondition" : "something"
   }, {
       "bezeichnung" : "B"
   } ]
  }
}

然后在集合中返回的每个产品上,您都可以使用以下代码通过ID获得定价:

/**
 * @return Collection|null
 */
public function getPricingByIdAttribute() : ?Collection
{
    return $this->pricing->keyBy('id');
}

如果需要,请确保仍然渴望加载价格

$pricing = $product->pricing_by_id;

此外,例如在退还产品时使用json的API,您可以使用accessor

$products = Product::query()->with('pricing')->get();

答案 3 :(得分:0)

问题是你不能'keyBy'现有的关系。

但是,您可以创建一个可以键入的“假”属性。所以相反:

$products = Product::with('pricing') -> all();
$products -> keyedPricing = $products -> pricing -> keyBy('id');
$products -> addVisible('keyedPricing');