I have this model:
App\Controllers\ImageController.php
.....
$image = new Image;
$image->id = "pre_" . (string) Str::ulid()->toBase58();
$image->filename = $filename
$image->post_id= $post_id;
$image->save();
return $image->load("post:id,status,subject,body");
it is working fine, it returns the following:
{
"id": "pre_1BzVrTK8dviqA9FGxSoSnU",
"type": "document",
"filename": "v1BzVc3jJPp64e7bQo1drmL.jpeg",
"post_id": "post_1BzVc3jJPp64e7bQo1drmL",
"post": {
"id": "post_1BzVc3jJPp64e7bQo1drmL",
"status": "active"
....
}
....
}
App\Models\Image.php
class Image extends Model
{
use HasFactory;
public $incrementing = false;
public function post()
{
return $this->belongsTo(Post::class);
}
}
The issue here is that I don't want it returns the "post_id" field, I would like to get the following:
{
"id": "pre_1BzVrTK8dviqA9FGxSoSnU",
"type": "document",
"filename": "v1BzVc3jJPp64e7bQo1drmL.jpeg",
"post": {
"id": "post_1BzVc3jJPp64e7bQo1drmL",
"status": "active"
....
}
....
}
I tried this:
return $image->select(["id", "type", "filename"])->load("post:id,status,subject,body");
and it returns an error:
"message": "Call to undefined method Illuminate\Database\Eloquent\Builder::load()",
What can I do?
The code you've tried
has actually multiple issues and is mixing a few things up.
The first issue is that you are already have an image model and try to select only a few columns, which will actually create a new query for another image. What you can do instead is select only the required columns before loading the image, e.g.:
The problem with this solution leads us to the second problem though: When you don't select the
post_id, Laravel won't be able to load the relationship due to the missing foreign key.If the query statement was correct, it would actually execute two queries:
But since you've not included the
post_idin the first query, it is not available as parameter for the second query and it fails to load the relationship data.Possible solution #1: API resources
Use an API resource to transform the image before returning it. This is best practice as it allows you to decouple the internal data structure from the public data structure. It will also prevent unwanted API changes when the internal data structure changes (new column is added, a column is renamed, a column is deleted, ...).
In your case, the solution could be as simple as:
Possible solution #2: Hide fields
You can define hidden fields in your models using the
$hiddenproperty. These fields will not be serialized to JSON:Alternatively, you can use
$visibleto define a whitelist instead of a blacklist. Only the properties in the$visiblearray will be serialized:This solution will obviously affect the entire application and may therefore be not ideal.
Possible solution #3: Temporarily set hidden/visible properties
Instead of permanently setting
$hiddenor$visible, you can also temporarily set them in your controller: