【问题标题】:Laravel Eloquent get relationship with keyByLaravel Eloquent 获取与 keyBy 的关系
【发布时间】:2015-09-17 18:30:54
【问题描述】:

我有一个Product 模型与hasMany 关系

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

然后我得到了关系

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

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

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

ProductPrice::keyBy('id')

【问题讨论】:

    标签: laravel eloquent


    【解决方案1】:

    一种快速的解决方法是使用 setRelation 方法替换数组中的当前关系。在你的情况下:

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

    【讨论】:

      【解决方案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-&gt;hasManyKeyBy protected 方法:

      [...]
      class Product extends Model
      {
          use HasManyKeyBy;
      
          public function pricing()
          {
              return $this->hasManyKeyBy('id', ProductPrice::class, 'prod_id', 'id');
          }
      
          [...]
      }
      

      【讨论】:

      • 这个答案被严重低估了
      【解决方案3】:

      你还可以定义一个accessor:

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

      然后在 Collection 中返回的每个产品上,您可以使用以下方式通过 id 获取定价:

      $pricing = $product->pricing_by_id;
      

      如有必要,请确保仍然急切加载定价:

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

      此外,当退回产品时,例如一个使用 json 的 API,你可以使用 appending to json:

      $products->each->append('pricing_by_id');
      

      【讨论】:

        【解决方案4】:

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

        但是,您可以创建一个返回的“假”属性,该属性可以键入。所以改为:

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

        【讨论】:

          猜你喜欢
          • 2018-02-09
          • 2016-11-21
          • 2013-12-14
          • 2017-01-12
          • 2017-05-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-10
          • 2020-12-23
          相关资源
          最近更新 更多