@danielroenfeldt Anything wrong with using select()?
$photos = $car->photos()->select('a', 'b', ...)->get();
// or
$photos = $car->photos()->get(['a', 'b', ...]);
Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.
As the title says, I need to filter out certain attributes on the related model after querying it via a hasManyThrough relationship.
More specifically, when querying all the Photos of the PhotoGallery that belongs to a specific Car, I'm getting a Collection of Photos, each of which with extra attributes that I'd prefer not to retrieve. Here are my models.
<?php
// app/Car.php
namespace App;
use Illuminate\Database\Eloquent;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
use Illuminate\Database\Eloquent\Relations\HasOne;
class Car extends Model
{
protected $fillable = ['make', 'model', 'year', 'price'];
public function photoGallery() : HasOne {
return $this->hasOne( PhotoGallery::class );
}
public function photos() : HasManyThrough {
return $this->hasManyThrough( Photo::class, PhotoGallery::class );
}
}
<?php
// app/PhotoGallery.php
namespace App;
use Illuminate\Database\Eloquent;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
class PhotoGallery extends Model
{
protected $fillable = ['car_id', 'max_photos'];
public function photos() : HasMany {
return $this->hasMany( Photo::class );
}
public function car() : BelongsTo {
return $this->belongsTo( Car::class );
}
}
<?php
// app/Photo.php
namespace App;
use Illuminate\Database\Eloquent;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class Photo extends Model
{
protected $fillable = ['photo_gallery_id', 'title', 'order'];
public function photoGallery() : BelongsTo {
return $this->belongsTo( PhotoGallery::class );
}
}
The show() method of the CarController looks like this.
<?php
// app/Http/Controllers/CarController.php
// namespace, imports etc omitted for brevity
class CarController extends Controller
{
public function show( Car $car ) {
$make = $car->make;
$model = $car->model;
$year = $car->year;
$price = $car->price;
$photos = $car->photos; // HasManyThrough relationship on Car model
dd( $photos ); // >>>>>> returns a collection of Photos, as expected, but each Photo has too many attributes
return view( 'cars.show', compact([
'make',
'model',
'year',
'price',
'photos',
]) );
}
}
And here's the result of dumping of the $photos Collection.
Illuminate\Database\Eloquent\Collection {#1538 ▼
#items: array:4 [▼
0 => App\Photo {#1539 ▼
#fillable: array:3 [▶]
#connection: "mysql"
#table: "photos"
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:8 [▼
"id" => 113
"photo_gallery_id" => 3 // <<<<< This must be gone from the result
"filename" => "1611828914_HVqrHEKJxtonghqNotcVJFxq2LAxmPXTDSZUa43r.jpg"
"title" => "A temporary title here. Needs to be handled later."
"order" => 1
"created_at" => "2021-01-28 10:15:15" // <<<<< This must be gone from the result
"updated_at" => "2021-01-28 10:15:15" // <<<<< This must be gone from the result
"laravel_through_key" => 35 // <<<<< This must be gone from the result
]
#original: array:8 [▶]
#changes: []
#casts: []
#dates: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: []
#touches: []
+timestamps: true
#hidden: []
#visible: []
#guarded: array:1 [▶]
}
1 => App\Photo {#1540 ▶}
2 => App\Photo {#1541 ▶}
3 => App\Photo {#1542 ▶}
]
}
Hope I'm making sense. Any thoughts?
Oddly enough, using a PhotoResource did not fix the issue. I just ended up "spoofing" the car identifier by simply iterating over the collection's items with the help of the each() method of the Collection class, and simply setting the laravel_through_key field's value to an empty string. Obviously not the most elegant solution, but who cares, as long as it's removing the potentially vulnerable data 😁
$car_photos = $car->photos()->get([ 'photos.id as id', 'filename', 'title', 'order' ]);
$car_photos->each(function( $photo ) {
$photo->laravel_through_key = '';
});
dd( $car_photos );
Illuminate\Support\Collection {#1583 ▼
#items: array:4 [▼
0 => App\Photo {#1535 ▼
#fillable: array:3 [▶]
#hidden: array:2 [▶]
#connection: "mysql"
#table: "photos"
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:5 [▼
"id" => 113
"filename" => "1611828914_HVqrHEKJxtonghqNotcVJFxq2LAxmPXTDSZUa43r.jpg"
"title" => "A temporary title here. Needs to be handled later."
"order" => 1
"laravel_through_key" => "" // <<<<< UNSAFE DATA REMOVED
]
#original: array:5 [▶]
#changes: []
#casts: []
#dates: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: []
#touches: []
+timestamps: true
#visible: []
#guarded: array:1 [▶]
}
1 => App\Photo {#1536 ▶}
2 => App\Photo {#1537 ▶}
3 => App\Photo {#1538 ▶}
]
}
@nimrod many thanks for your help! It's much appreciated.
Please or to participate in this conversation.