【问题标题】:How to change result of laravel relationship如何更改laravel关系的结果
【发布时间】:2020-07-31 18:20:27
【问题描述】:

我在 laravel 中有一个一对一的关系,如下所示:

public function Category()
{
    return $this->belongsTo(Categories::class);
}

并运行这个雄辩的查询:

Product::with('category')->first();

这个查询返回:

{
    "name": "Green Book",
    "category": {
        "id": 1,
        "name": "Book"
    }
}

但我去了这个数据:

{
    "name": "Green Book",
    "category": "Book"
}

是否可以不使用循环来做到这一点?

【问题讨论】:

  • 你可以试试Product::with('category:name')->first();。它可能会失败,因为它需要 id 来建立关系,或者它可能工作,但仍然是一个带有名称的数组。在这种情况下,您可以映射数据。如果您为您的问题提供更多背景信息,也许可以提供更好的解决方案。
  • Categories::class 不应该是复数。关系方法有问题。

标签: laravel eloquent relationship


【解决方案1】:

我得到相同的结果 所以,我尝试了但没有得到正确的结果。 如何改变 laravel 雄辩关系的结果。 我找到了一种方法并使用了变压器。 我们可以在转换器中改变结果。

 $result = Event::with(['eventType'])
        ->where('id', $id)
        ->where('user_id', auth()->user()->id)
        ->first();
    return $this->trans->transform($result);

这是结果,我使用了如下的转换器。

 public function transform(Event $Event)
{
    return [
        'id' => $Event->id,
        'company_id' => $Event->company_id,
        'calendar_id' => $Event->calendar_id,
        'case_id' => $Event->case_id,
        'user_id' => $Event->user_id,
        'title' => $Event->title,
        'description' => $Event->description,
        'duration' => $Event->duration,
        'alert_at' => $Event->alert_at,
        'alert_email' => $Event->alert_email,
        'email_sent' => $Event->email_sent,
        'alert_popup' => $Event->alert_popup,
        'popup_triggered' => $Event->popup_triggered,
        'created_by' => $Event->created_by,
        'completed' => $Event->completed,
        'alert_offset' => $Event->alert_offset,
        'icon' => $Event->icon,
        'color' => $Event->color,
        'snoozed' => $Event->snoozed,
        'type_id' => $Event->type_id,
        'datetime' => $Event->at,
        'endtime' => $Event->end_time,
        'event_type_name'=>$Event->eventType->name,
    ];
}

然后,我们可以得到正确的结果。关注'event_type_name'=>$Event->eventType->name, 但我还有一个问题。 现在,结果只有 1 行。它只是first()。 但如果我使用get(),我就不能使用变压器。 当然,我可以使用foreach() 循环结果。 但我认为这不是正确的方法。 什么是更好的方法? 请回答。

【讨论】:

    【解决方案2】:

    根据 Laravel Doc 急切加载特定列

    你可以使用以下

    Product::with('category:id,name')->first();
    

    或者你可以自己做:

    $product = Product::with('category')->first();
    $product->category = $product->category->name;
    

    【讨论】:

    • 在急切加载特定列时需要包含idProduct::with('category:id,name')->first();
    【解决方案3】:

    您可以使用leftJoin

    return \App\Product::leftJoin('categories', 'products.category_id', '=', 'categories.id')
    ->select('products.*', 'categories.title as category')->get();
    

    【讨论】:

      【解决方案4】:

      首先,您似乎有一个 1-X 关系,但您错误地将其用作多对一。您的 belongsTo 应该是 hasOne,因为您的项目有一个类别,而不是相反。

      您可以使用$appends 属性来附加自定义字段并使其表现得好像它是您模型的一部分:

      重命名您的关系并添加修改器和访问器:

      public function categoryRelationship()
      {
          return $this->hasOne(Categories::class);
      }
      
      public function getCategoryAttribute() {
          return $this->categoryRelationship->name;
      }
      
      public function setCategoryAttribute($value) {
         $this->categoryRelationship->name = $value;
      }
      

      您还可以选择添加一个事件以在保存模型时自动保存您的关系,以确保它透明地工作:

      protected static function booted()
          {
              static::saving(function ($myModel) {
                  $myModel->categoryRelationship->save();
              });
          }
      }
      

      最后,您添加 $appends 属性以确保您的新属性始终包含在模型中,就好像它是原生属性一样。

      protected $appends = [ 'category' ];
      
      // This is so you don't end up also showing the relationship
      protected $hidden = [ 'categoryRelationship' ];
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-01-26
        • 2019-05-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-27
        • 2018-01-11
        相关资源
        最近更新 更多