Laravel Eloquent:关联查询结果中用Collection重命名关联表字段
Great question! When you're using Laravel's API Resources to transform your Properties data but need to also rename fields from related models like city, category, and neighborhood, the cleanest approach is to create dedicated Resource classes for each related model, then reference those within your main PropertyResource. This keeps your code organized and reusable across your application.
Step 1: Create Resource Classes for Related Models
First, generate a Resource class for each of your related models. These classes will handle the field renaming for their respective models.
Example: CityResource
<?php namespace App\Http\Resources; use Illuminate\Http\Resources\Json\JsonResource; class CityResource extends JsonResource { /** * Transform the resource into an array. * * @param \Illuminate\Http\Request $request * @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable */ public function toArray($request) { return [ 'city_id' => $this->id, // Rename original `id` to `city_id` 'city_name' => $this->name, // Rename original `name` to `city_name` // Add any other fields you need to rename or include here ]; } }
Example: CategoryResource
<?php namespace App\Http\Resources; use Illuminate\Http\Resources\Json\JsonResource; class CategoryResource extends JsonResource { public function toArray($request) { return [ 'category_id' => $this->id, 'category_label' => $this->label, // Rename original `label` to `category_label` // Additional fields... ]; } }
Example: NeighborhoodResource
<?php namespace App\Http\Resources; use Illuminate\Http\Resources\Json\JsonResource; class NeighborhoodResource extends JsonResource { public function toArray($request) { return [ 'neighborhood_id' => $this->id, 'neighborhood_title' => $this->title, // Rename original `title` to `neighborhood_title` // Additional fields... ]; } }
Step 2: Update PropertyResource to Use Related Resources
Now, modify your existing PropertyResource to reference these new Resource classes when including related data. Use the whenLoaded method to ensure you only include the related data if it was preloaded (which you're already doing with the with method in your query).
<?php namespace App\Http\Resources; use Illuminate\Http\Resources\Json\JsonResource; class PropertyResource extends JsonResource { public function toArray($request) { return [ // Rename fields from the Properties table as before 'property_id' => $this->id, 'property_title' => $this->title, 'property_description' => $this->description, // Other Properties fields... // Include related models using their dedicated Resources 'city' => new CityResource($this->whenLoaded('city')), 'category' => new CategoryResource($this->whenLoaded('category')), 'neighborhood' => new NeighborhoodResource($this->whenLoaded('neighborhood')), ]; } }
Step 3: Use Your Resource Collection as Before
You don't need to change how you're using PropertyResource::collection() in your controller. Your existing code will now automatically transform both the main Properties data and all related models into your desired friendly field names:
$properties = Property::with(['city', 'category', 'neighborhood']) ->paginate(10); return PropertyResource::collection($properties);
Note for One-to-Many Relationships
If any of your relationships are one-to-many (e.g., a property has multiple amenities), use the collection() method on the related Resource instead:
'amenities' => AmenityResource::collection($this->whenLoaded('amenities'))
This approach keeps your code DRY (Don't Repeat Yourself) and makes it easy to update field transformations for related models across your entire API.
内容的提问来源于stack exchange,提问作者Marcelo Agimóvel

