remove data from laravel fractal - laravel

I'm using laravel-fractal to transform my data and here is a response
how can I delete data;
I made a search and I realized I need to use a Serializer;
But I just want to remove data for all includes(relations)
{
"data": [
{
"id": 1,
"name": "test name",
"status": null,
"tags": [
"first",
"second"
],
"created_at": "1396/9/3",
"contacts": {
"data": [
{
"value": "test#test.com",
"type": "email",
"icon": "fa fa-email"
}
]
}
},
{
"id": 2,
"name": "name test 2",
"status": null,
"tags": [],
"created_at": "1396/9/3",
"contact": {
"data": []
}
}
]

I found my answer at GitHub. The following answer is copied from thephpleague/fractal on GitHub:
You can write your own serializer for that.
class YourDataSerializer extends ArraySerializer
{
public function collection($resourceKey, array $data)
{
if ($resourceKey) {
return [$resourceKey => $data];
}
return $data;
}
public function item($resourceKey, array $data)
{
if ($resourceKey) {
return [$resourceKey => $data];
}
return $data;
}
}
Register your serializer with manager
$manager = new Manager();
$manager->setSerializer(new YourDataSerializer());
and when you want to have data or anything else you can pass in resourceKey to your Item or Collection as a third param.
$resource = new Collection($folders, new AccountFolderTransformer(), 'data');

use array serializer:
Fractal::create()
->item($item, new MyTransformer())
->serializeWith(new ArraySerializer())

Related

Laravel 9 Rest API - pagination meta tag unavaible when return it with response()

Controllers/Komic Controller
public function search($value)
{
// Query Wildcards and Resources
$result = new KomikCollection(Komik::where('judul', 'like', '%'. $value .'%')->paginate(2));
return $result;
}
its fine when i directly return the $result
{
"data": [],
"links": {
"first": "http://localhost:8000/api/komik/a?page=1",
"last": "http://localhost:8000/api/komik/a?page=2",
"prev": null,
"next": "http://localhost:8000/api/komik/a?page=2"
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 2,
"links": [
{
"url": null,
"label": "« Previous",
"active": false
},
{
"url": "http://localhost:8000/api/komik/a?page=1",
"label": "1",
"active": true
},
{
"url": "http://localhost:8000/api/komik/a?page=2",
"label": "2",
"active": false
},
{
"url": "http://localhost:8000/api/komik/a?page=2",
"label": "Next »",
"active": false
}
],
"path": "http://localhost:8000/api/komik/a",
"per_page": 2,
"to": 2,
"total": 4
}
}
but when i'll return it using helpers/response
public function search($value)
{
// Query Wildcards and Resources
$result = new KomikCollection(Komik::where('judul', 'like', '%'. $value .'%')->paginate(2));
// send response
return response()->json($result, 200);
}
the meta and link on the json response will be disapppear and return result like this
{
"id": 1,
"title": "Spare me, Great Lord !"
},
{
"id": 2,
"title": "I'm An Evil God"
}
I want the response include the meta and link tags, how do i fix this?
If you want to meta data with response then you must need to add ->response()->getData(true) in collection results.
So your final function looks like :
public function search($value)
{
// Query Wildcards and Resources
$result = new KomikCollection(Komik::where('judul', 'like', '%'. $value .'%')->paginate(2))->response()->getData(true);
// send response
return response()->json($result, 200);
}

data limiting global scope with laravel model

i have a model named "Page" and
I want the first of my model's image arm data to be written, I wonder how can I do it?
public function index($lang)
{
$data = Page::where('language', $lang)->orderBy('order', 'ASC')->with('categori')->get();
if ($data) {
return response()->json($data);
}
return response()->json(['message' => 'Record not found.'], 404);
}
{
"id": 3,
"title": "Conporta",
"contents": "<p>Conporta</p>",
"slug": "hakkimizda",
"image": [
"/storage/page/Conporta/40-banner-1659203850.jpg",
"/storage/page/Conporta/40-banner-small-1659203850.jpg",
"/storage/page/Conporta/40-banner-medium-1659203850.jpg"
],
"language": "en",
"is_home": "false",
"status": "on",
"seo": null,
"order": "0",
"category_id": 2,
"created_at": "2022-07-30T17:57:30.000000Z",
"updated_at": "2022-07-30T17:57:30.000000Z",
}
You can hide the image attribute from model and create new attribute that should hold one image.
...
protected $hidden = ['image'];
protected $appends = ['img'];
...
public function getImgAttribute(){
return $this->image[0];
}

How to make attributes in Laravel API resource dynamically?

I want make the values in one collection to be attributes in my resource.
{
"data": {
"import_type": "Material",
"id": "1178d470-85b6-4594-9bb4-e9e17b9d9104",
"tabs": [
{
...
}
],
"graphics": {
"render": "",
"shading_colour": "",
}
"identity": {
"render": "",
"shading_colour": "",
}
}
}
Unfortunately I get that json code:
{
"data": {
"import_type": "Material",
"id": "1178d470-85b6-4594-9bb4-e9e17b9d9104",
"tabs": [
{
...
}
],
"0": [
{
"graphics": {
"render": "",
"shading_colour": "",
}
},
{
"identity": {
"render": "",
"shading_colour": "",
}
},
]
}
}
Because I have more attributes like "graphics", "identity" I want to display them dynamically, but I dont know how to achieve that.
Here is my PHP code:
class MaterialResource extends JsonResource
{
public function toArray($request)
{
return [
'import_type' => 'Material',
'id' => $this->uuid,
'tabs' => MaterialTabsResource::collection($this->tabs),
MaterialExtensionResource::collection($this->extensions),
];
}
}

change hasManyThrough() relation attribute name through accessor

I have 3 Models
Campaign PK(id)
CampaignMedium FK(campaign_id)
AccountReceivable FK(campaign_medium_id) (has an amount column)
Controller function:
public function all()
{
return Campaign::with(['customer', 'receivedPayments'])->get();
}
In Campaign Model relationships are defined as follows:
public function customer()
{
return $this->belongsTo(Customer::class);
}
public function accountReceivable()
{
return $this->hasManyThrough(AccountReceivable::class, CampaignMedium::class);
}
public function receivedPayments()
{
return $this->accountReceivable()
->selectRaw('sum(account_receivables.amount) as total')
->groupBy('campaign_id');
}
public function getReceivedPaymentsAttribute()
{
if (!array_key_exists('receivedPayments', $this->relations)) {
$this->load('receivedPayments');
}
$relation = $this->getRelation('receivedPayments')->first();
return ($relation) ? $relation->total : 0;
}
Final Output:
{
"data": [
{
"id": 8,
"name": "example",
"image": "campaign/90375849f6c3cc6b0e542a0e3e6295b890375849f6c3cc6b0e542a0e3e6295b8.jpeg",
"amount": 10,
"description": "saddsa",
"start_at": "2019-02-12 00:00:00",
"end_at": "2019-02-12 00:00:00",
"due_at": "2019-02-12 00:00:00",
"status": "active",
"customer": {
"id": 1,
"name": "test",
"email": "info#test.com",
"image": "customer/ec812116705ff3ae85298234fe6c4e97ec812116705ff3ae85298234fe6c4e97.jpeg",
"address": "sample address"
},
"received_payments": [
{
"total": "700",
"laravel_through_key": 8
}
]
},
{
"id": 9,
"name": "example",
"image": "campaign/fff9fadc92a809513dc28134379851aafff9fadc92a809513dc28134379851aa.jpeg",
"amount": 10,
"description": "saddsa",
"start_at": "2019-02-12 00:00:00",
"end_at": "2019-02-12 00:00:00",
"due_at": "2019-02-12 00:00:00",
"status": "active",
"customer": {
"id": 1,
"name": "test",
"email": "info#test.com",
"image": "customer/ec812116705ff3ae85298234fe6c4e97ec812116705ff3ae85298234fe6c4e97.jpeg",
"address": "sample address"
},
"received_payments": []
}
]
}
summary: trying to get the sum of AccountReceivable amount attribute, which is working fine but the getReceivedPaymentsAttribute() isn't working which needs to return the total value only. also can anyone please help me to explain why laravel_through_key is added with received_payments?
I've never tried to use an attribute modifier to modify a relation this way. You are overriding the expected result of receivedPayments(). You might be better off to define a separate attribute like so:
public function getSumReceivedPaymentsAttribute()
{
// ...your code...
}
Now you can access the attribute using $model->sum_received_payments or always preload it using:
// model.php
protected $appends = ['sum_received_payments'];

Transform Laravel Eloquent result

When I execute this in my Controller
$data = User::with('teams')->find(2);
return response(['data' => $data]);
I get this as result
{
"id": 2,
"country_id": 1,
"first_name": "John",
"last_name": "Doe",
"created_at": "-0001-11-30 00:00:00",
"updated_at": "2015-02-02 23:08:21",
"full_name": "John Doe",
"teams": [
{
"id": 1,
"name": "Helpdesk medewerker",
"description": ""
},
{
"id": 2,
"name": "Retentie",
"description": ""
}
]
}
Im not interested in the full teams data, but only interested in the teamNames of the user.
I've done this by adding this
$data->each(function($user) {
$user->team_names = $user->teams->lists('name');
unset($user->teams);
});
I was wondering if this is the correct way of modifying the Eloquent result.
You can use an attribute accessor for that. Add this to your model:
protected $hidden = ['teams']; // hide teams relation in JSON output
protected $appends = ['team_names']; // add custom attribute to JSON output
public function getTeamNamesAttribute(){
return $this->teams->lists('name');
}
To change hidden and appends dynamically you can use the setter methods:
$data = User::with('teams')->find(2);
$data->setHidden(['teams']);
Filter out the columns you want in your first build.
$data = User::with(['teams' => function($query){
return $query->select('name');
}])->find(2);
Will output:
{
...
"teams": [
{
"name": "Helpdesk medewerker"
},
{
"name": "Retentie"
}
]
}
You can also use the lists method.
$data = User::with(['teams' => function($query){
return $query->lists('name');
}])->find(2);
Will output:
{
...
"teams": ["Helpdesk medewerker", "Retentie"]
}

Resources