You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel 8中关联模型在API Resource中的数据返回问题及优化方案咨询

Fixing the "Property [id] does not exist on this collection instance" Error & Optimizing Your Laravel API Resources

Let's break down what's causing your error and refactor your code into a cleaner, more Laravel-idiomatic solution:

Root Cause of the Error

Your lastPrice relationship in the Products model is a hasMany—this returns a collection of ProductPrice models, not a single instance. But in your Products Resource, you used lastPrice::make($this->lastPrice) which is designed for individual models. When the Resource tried to access $this->id, it was trying to fetch that property from the collection itself (which doesn't have an id), hence the error.


Step 1: Fix the Products Resource

Update your Products Resource to use the collection() method for the lastPrice relationship, since it returns multiple items:

public function toArray($request) {
    return [
        'id' => $this->id,
        'prices' => lastPrice::collection($this->lastPrice), // Use collection() instead of make()
        'status' => $this->status,
        'slug' => $this->slug,
        'title' => $this->title,
        'description' => $this->description,
        'txt' => $this->txt,
        'lang' => $this->lang,
        'created_at' => $this->created_at,
        'updated_at' => $this->updated_at,
    ];
}

Step 2: Clean Up the lastPrice Resource

Instead of manual loops and direct database calls, leverage Laravel's relationship features and nested Resources. We'll also keep your caching logic but integrate it more cleanly:

First, (optional but recommended) rename your ProductPrice relationship to follow Laravel conventions for readability:

// ProductPrice model
public function publisher() { // Renamed from getPublisher
    return $this->belongsTo(ProductsPublisher::class, 'publisher_id');
}

Then update your lastPrice Resource:

public function toArray($request) {
    // Cache the publisher data directly using the relationship
    $publisher = Cache::remember(
        'publisher_' . $this->publisher_id,
        env('CACHE_TIME_LONG'),
        fn() => $this->publisher
    );

    return [
        'id' => $this->id,
        'main_price' => $this->main_price,
        'off_price' => $this->off_price,
        'created_at' => $this->created_at,
        'publisher' => SinglePublisher::make($publisher),
    ];
}

If you want to keep the original getPublisher relationship name, just replace $this->publisher with $this->getPublisher.


Step 3: Optimize with Eager Loading

Prevent N+1 database queries by eager loading the lastPrice relationship and its associated publisher in your controller:

$products = Product::where('id', $id)
    ->where('slug', $slug)
    ->where('status', 'confirm')
    ->with(['lastPrice.publisher']) // Eager load related data upfront
    ->first();

Why This Is More Elegant

  • No manual iteration: Laravel Resources handle collection looping automatically when using collection().
  • Encapsulated logic: Caching and relationship access are kept within the Resource where they belong.
  • Better performance: Eager loading cuts down on unnecessary database calls.
  • Readable code: Follows Laravel conventions, making it easier for other developers to understand.

内容的提问来源于stack exchange,提问作者Soroush Tayyebi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 22:02:43