I want to load my childrens categories in the parent with Laravel Resource.
My json is like that :
"data": [
{
"id": 2,
"slug": "child-categorie-0",
"name": "Child Catégorie 0",
"parent_id": 1
},
{
"id": 3,
"slug": "child-categorie-1",
"name": "Child Catégorie 1",
"parent_id": 1
},
{
"id": 1,
"slug": "parent-categorie-0",
"name": "Parent Catégorie 0",
"parent_id": null
},
],
I would like to be like that :
"data": [
{
"id": 1,
"slug": "parent-categorie-0",
"name": "Parent Catégorie 0",
"childrens": [
{
"id": 2,
"slug": "child-categorie-0",
"name": "Child Catégorie 0",
},
{
"id": 3,
"slug": "child-categorie-1",
"name": "Child Catégorie 1",
}
]
}
],
App\Http\Resources\Category.php
public function toArray($request)
{
return [
'id' => $this->id,
'slug' => $this->slug,
'name' => $this->name,
'parent_id' => $this->parent_id
];
}
Controller
$categories = Category::orderBy('name', 'asc')->get();
return new CategoryCollection($categories);
I'm new with Laravel Resource so if someone have a path for solving this problem, thanks !
I solve my problem !
I create a relationship in my Category Model.
public function childrens()
{
return $this->hasMany('App\Category', 'parent_id', 'id');
}
In my Category Resource
public function toArray($request)
{
return [
'slug' => $this->slug,
'name' => $this->name,
'childrens' => self::collection($this->whenLoaded('childrens'))
];
}
In my Controller
$categories = Category::with('childrens')->parents()->orderBy('name','asc')->get();
Related
I am working with php in laravel, in this case I have 2 collections of objects, one of them looks like this:
[
{
"id": 1,
"name": "product x",
"quantity": "100",
},
{
"id": 2,
"codProd": "product y",
"quantity": "200",
},
{
"id": 3,
"name": "product a.",
"quantity": "30",
}
]
and the other looks like this:
[
{
"reference": 1,
"quantity": "80",
},
{
"reference": 2,
"quantity": "50",
},
]
What I need is to keep the first collection but adding the value of the quantity key from the second collection, using the reference key as a relationship with the id of the first collection, the final result should look like this:
[
{
"id": 1,
"name": "product x",
"quantity": "180",
},
{
"id": 2,
"codProd": "product y",
"quantity": "250",
},
{
"id": 3,
"name": "product a.",
"quantity": "30",
}
]
so how can I do this?, any guide or help I am grateful
You can use a collection method for this, the map method:
$collection_one = collect([
[
'id' => 1,
'name' => 'product x',
'quantity' => 100,
],
[
'id' => 2,
'name' => 'product y',
'quantity' => 100,
],
[
'id' => 1,
'name' => 'product a.',
'quantity' => 30,
],
]);
$collection_two = collect([
[
'reference' => 1,
'quantity' => 80,
],
[
'reference' => 2,
'quantity' => 50,
],
]);
For you to get the collection what you want:
$collect = [];
$collect = $collection_one->map(function ($value_one) use ($collection_two) {
if ($search = $collection_two->firstWhere('reference', '=', $value_one['id'])) {
$value_one['quantity'] += $search['quantity'];
}
return $value_one;
});
Ready, that worked for me. :)
Relation method
User model:
public function children()
{
return $this->hasMany(self::class, 'referrer_id')->with('children');
}
Controller Method:
$user = User::with('children')->where('id',$this->request->UserId)->get();
Response
{
"status": true,
"status_code": "Success",
"message": true,
"payload": {
"profile": [
{
"id": 1,
"referrer_id": null,
"name": "beciwerugy",
"username": "lahaky",
"email": "figo#mailinator.com",
"children": [
{
"id": 3,
"referrer_id": 1,
"name": "asd",
"username": "asde",
"email": "asda#asd.com",
"children": [
{
"id": 4,
"referrer_id": 3,
"name": "asd",
"username": "asde12",
"email": "as12a#asd.com",
]
}
]
}
]
}
]
}
]
}
}
I want to count all nestedchild at once
Currently im getting all nested child in ther list
but i just want count
I have tables, users, profiles, contacts. 1 user has 1 profile, 1 profile has many contacts, I want to get profile with filtered contact and selected column (I don't want get all column). I success with coding below
UserController.php
$profile = $user->with(['profile.emails', 'profile.phones'])->first();
User.php
public function profile()
{
return $this->hasOne(Profile::class);
}
Profile.php
public function emails()
{
return $this->hasMany(Contact::class)
->where('type', 'email');
}
public function phones()
{
return $this->hasMany(Contact::class)
->where('type', 'phone');
}
result data like this
{
"username": "user",
"email": "user#mail.com",
"profile": {
"first_name": "Alex",
"last_name": "Ariana",
"emails": [
{
"id": 1,
"profile_id": 1,
"type": "email",
"prefix": "Personal",
"value": "alex#mail.com",
"is_primary": 0,
},
{
"id": 2,
"profile_id": 1,
"type": "email",
"prefix": "Business",
"value": "business#mail.com",
"is_primary": 1,
}
],
"phones": [
{
"id": 3,
"profile_id": 1,
"type": "phone",
"prefix": "45",
"value": "564637345345",
"is_primary": 1,
}
]
}
}
but then I add select on the relation like this
public function emails()
{
return $this->hasMany(Contact::class)
->select([DB::raw('IFNULL(prefix, "Email") AS type'), 'value AS url', 'is_primary'])
->where('type', 'email');
}
public function phones()
{
return $this->hasMany(Contact::class)
->select(['prefix', 'value AS number', 'is_primary'])
->where('type', 'phone');
}
then I got empty contact data like this
{
"id": 1,
"username": "user",
"email": "user#mail.com",
"profile": {
"first_name": "Alex",
"last_name": "Ariana",
"emails": [ ],
"phones": [ ]
}
}
Why this is happen?, if I access from user via hasManyThrough it works, but when I use hasMany, it result empty.
I have categories with id, parent_id, slug , pivot table category_language which columns are id,category_id,language_id,value
As you can see I can translate parent category, but can't send desired $lang_id to children translations, so each children having all translations
here is what I get:
{
"id": 1,
"parent_id": 0,
"slug": "personal-computers",
"created_at": "2019-12-27 15:05:31",
"updated_at": "2019-12-27 15:05:31",
"children": [
{
"id": 3,
"parent_id": 1,
"slug": "accessories-for-pc",
"created_at": "2019-12-27 15:05:32",
"updated_at": "2019-12-27 15:05:32",
"translations": [
{
"id": 1,
"code": "en",
"name": "English",
"pivot": {
"category_id": 3,
"language_id": 1,
"value": "Acc for PC",
"id": 7
}
},
{
"id": 2,
"code": "ru",
"name": "Русский",
"pivot": {
"category_id": 3,
"language_id": 2,
"value": "Аксессуары для ноутбуков и ПК",
"id": 8
}
},
{
"id": 3,
"code": "ro",
"name": "Romana",
"pivot": {
"category_id": 3,
"language_id": 3,
"value": "aksessuari-dlya-noutbukov-i-pk-ro",
"id": 9
}
}
]
}
],
"translations": [
{
"id": 1,
"code": "en",
"name": "English",
"pivot": {
"category_id": 1,
"language_id": 1,
"value": "PC",
"id": 1
}
}
]
}
Controller:
return Category::with('children')
->with(array('translations'=>function($query) use ($lang_id){
$query->where('language_id',$lang_id);
}))
->where('parent_id',0)->first();
Model
class Category extends Model
{ ..
public function translations()
{
return $this->belongsToMany('App\Models\Translation','category_language', 'category_id' ,'language_id' )->withPivot('value','id');
}
public function children()
{
return $this->hasMany( 'App\Models\Category' , 'parent_id' , 'id' )->with('translations');
}
}
you can add condition in children method
public function children()
{
return $this->hasMany( 'App\Models\Category' , 'parent_id' , 'id' )->with('translations')->where('language_id', 1);
}
Dry7 answer was close to the one I've implemented later, so I upvoted him.
Finally in model I've added: ...->where('language_id',helper_SetCorrectLangIdForQuery());
and function helper_SetCorrectLangIdForQuery is using global helper of Laravel request()->lang . If lang=enz, than it takes default language from another helper.
I am using laravel 5.5 API resource collection for showing list of products. I am using an array instead of the modal object. I got my list of items but i am not sure how to show item variant array in the response. The actual response array passing to the api resource are:
{
"ID": 3160,
"UserID": 3302,
"ItemName": "2",
"Description": "2",
"Price": 2,
"StockLimited": true,
"StockQuantity": 19,
"CurrencyCode": "USD",
"ImageUrl": "/images/items/Item3302-636434761494584365-qq5HFm.png",
"VariantItems": [
{
"ID": 3181,
"ItemName": "2",
"Price": 0,
"StockLimited": false,
"StockQuantity": 0,
"CurrencyCode": "USD",
"Variants": [
{
"Id": 1099,
"Name": "Red",
"VariantGroupId": 1027,
"VariantGroupName": "Colour"
},
{
"Id": 1111,
"Name": "S",
"VariantGroupId": 1028,
"VariantGroupName": "Size"
}
]
},
{
"ID": 3182,
"ItemName": "2",
"Price": 0,
"StockLimited": false,
"StockQuantity": 0,
"CurrencyCode": "USD",
"Variants": [
{
"Id": 1099,
"Name": "Red",
"VariantGroupId": 1027,
"VariantGroupName": "Colour"
},
{
"Id": 1112,
"Name": "M",
"VariantGroupId": 1028,
"VariantGroupName": "Size"
}
]
}
],
"MerchantName": "seller",
"VariantGroupLists": [
{
"VariantGroupName": "Colour",
"Names": [
"Red",
"Grey",
"Navy"
]
},
{
"VariantGroupName": "Size",
"Names": [
"S",
"M",
"L",
"XL"
]
}
]
}
My ItemResourceCollection
public function toArray($request)
{
return [
'data' => $this->collection->map(function ($item) use ($request) {
return (new ItemResource($item))->toArray($request);
})
];
}
My ItemResource
public function toArray($request)
{
return [
"item_id" => $this->resource->ID,
"item_name" => $this->resource->ItemName,
"description" =>$this->resource->Description,
"item_price"=>$this->resource->Price,
"stock_qty"=>$this->resource->StockQuantity,
"currency_code"=>$this->resource->CurrencyCode,
"item_image_url"=>$this->resource->ImageUrl,
];
}
public function with($request)
{
return ['item_varients' => [new ItemResource($this->resource->VariantItems)]];
}
What I am trying to achieve is this result:
[
{
"item_id": 3160,
"item_name": "BLACK COWL NECK DRESS WITH DIAMANTE DETAIL",
"description": "Test test",
"item_price": 16.99,
"stock_qty": 20,
"currency_code": "SGD",
"item_image_url": "/images/items/Item18-636231488325192562-GoiIBl.png",
"item_varients": [
{
"id": 29,
"name": "Red",
"varientgroupId": 11,
"varientgroupname": "Color"
}
]
}
]
the with() method in ItemResource is not working. How do I add the "item_varients" array in the resource response?
I would first move the line to add the item_varients property inside the method toArray like following:
public function toArray($request)
{
return [
"item_id" => $this->resource->ID,
"item_name" => $this->resource->ItemName,
"description" => $this->resource->Description,
"item_price" => $this->resource->Price,
"stock_qty" => $this->resource->StockQuantity,
"currency_code" => $this->resource->CurrencyCode,
"item_image_url" => $this->resource->ImageUrl,
"item_varients" => [
new ItemResource($this->resource->VariantItems)
]
]
}
Meta information
We do that because the with is meant for to add a meta information block or something similar. See https://laravel.com/docs/5.5/eloquent-resources#adding-meta-data
The advantage when using the with method is, that multiple resources results in only one meta block. This is not what you want, I think.
Resource for VariantItem
I think you have to build a Resource class also for VariantItem. And because the VariantItems are a collection you also have to fill your array called item_variants similar to your ItemResourceCollection. So change your code to look like this:
public function toArray($request)
{
/**
* Prepare your variant items to have a collection
*
* #var Collection $variantItems
*/
$variantItems = collect($this->resource->VariantItems);
return [
"item_id" => $this->resource->ID,
"item_name" => $this->resource->ItemName,
"description" => $this->resource->Description,
"item_price" => $this->resource->Price,
"stock_qty" > $this->resource->StockQuantity,
"currency_code" => $this->resource->CurrencyCode,
"item_image_url" => $this->resource->ImageUrl,
"item_varients" => VariantItem::collection($variantItems)
]
}
Here is the best way to get specific fields using a collection
return [
'id' => $this->id,
'variant_item' => new CustomResource($this->user, ['item_id', 'item_name', 'item_size'])
];