Select and count using Laravel Eloquent - php

I'm working on a small project using Laravel, right now i display my products that i have in my database in HTML table.
So right now i have created another database table called variants, to store products variants,
i would like to count the number of variants that i have for each product
this is my code :
as you can see i select also the categories, brands, suppliers
i want to count the number of the variants ( since i have already a table called variants, contain the product_id field )
public function index()
{
$products = Product::with(['category', 'brand', 'supplier'])->orderBy('id', 'desc')->paginate(15);
return response()->json($products);
}
My current Result :
{
"current_page": 1,
"data": [
{
"id": 3,
"product_name": "Ipad",
"product_description": null,
"product_category": 4,
"product_supplier": 1,
"product_buying_price": "5500.00",
"product_selling_price": "66.00",
"product_min_stock": "10.00",
"product_max_stock": "10.00",
"product_alert_stock": 10,
"product_alert_phone": "+1 (1084) 565-43109",
"product_alert_email": "daqaxipig#mailinator.net",
"product_cost_price": "65.00",
"product_supplier_discount": "10.00",
"product_brand": 5,
"product_warehouse": 2,
"product_availability": 2,
"deleted_at": null,
"created_at": null,
"updated_at": null,
"category": {
"id": 4,
"category_name": "TABLET",
"category_parent": null,
"category_description": null,
"deleted_at": null,
"created_at": null,
"updated_at": null
},
"brand": {
"id": 5,
"brand_name": "Apple",
"deleted_at": null,
"created_at": null,
"updated_at": null
},
"supplier": {
"id": 1,
"supplier_company": "Dataxpress",
"supplier_code": "55598548455",
"supplier_tax_number": "68958955",
"supplier_phone": "4382251059",
"supplier_fax": "4382251059",
"supplier_website": "oppo.com",
"supplier_email": "ab#dothostia.com",
"supplier_note": "Aliquip porro est n",
"supplier_type": 1,
"supplier_address": "Consequuntur maxime",
"supplier_city": "Qui consectetur non",
"supplier_state": "Ex nemo sit quia ame",
"supplier_zip": "46033",
"supplier_country": "HU",
"supplier_representative": 2,
"supplier_price_list": 4,
"supplier_tax_type": 2,
"supplier_currency": "GBP",
"deleted_at": null,
"created_at": "2020-01-17 18:16:55",
"updated_at": "2020-01-17 18:16:55"
}
},
{
"id": 2,
"product_name": "Samsung A35",
"product_description": "test",
"product_category": 1,
"product_supplier": 1,
"product_buying_price": "500.00",
"product_selling_price": "500.00",
"product_min_stock": "10.00",
"product_max_stock": "20.00",
"product_alert_stock": 15,
"product_alert_phone": "+1 (1023) 803-2526",
"product_alert_email": "duvupihujo#mailinator.net",
"product_cost_price": "600.00",
"product_supplier_discount": "30.00",
"product_brand": 4,
"product_warehouse": 2,
"product_availability": 2,
"deleted_at": null,
"created_at": null,
"updated_at": null,
"category": {
"id": 1,
"category_name": "Super Phone",
"category_parent": null,
"category_description": null,
"deleted_at": null,
"created_at": null,
"updated_at": null
},
"brand": {
"id": 4,
"brand_name": "Samsung",
"deleted_at": null,
"created_at": null,
"updated_at": null
},
"supplier": {
"id": 1,
"supplier_company": "Dataxpress",
"supplier_code": "55598548455",
"supplier_tax_number": "68958955",
"supplier_phone": "4382251059",
"supplier_fax": "4382251059",
"supplier_website": "oppo.com",
"supplier_email": "ab#dothostia.com",
"supplier_note": "Aliquip porro est n",
"supplier_type": 1,
"supplier_address": "Consequuntur maxime",
"supplier_city": "Qui consectetur non",
"supplier_state": "Ex nemo sit quia ame",
"supplier_zip": "46033",
"supplier_country": "HU",
"supplier_representative": 2,
"supplier_price_list": 4,
"supplier_tax_type": 2,
"supplier_currency": "GBP",
"deleted_at": null,
"created_at": "2020-01-17 18:16:55",
"updated_at": "2020-01-17 18:16:55"
}
},
{
"id": 1,
"product_name": "Elton Mullins",
"product_description": "Possimus rerum comm",
"product_category": 2,
"product_supplier": 1,
"product_buying_price": "97.00",
"product_selling_price": "354.00",
"product_min_stock": "10.00",
"product_max_stock": "20.00",
"product_alert_stock": 5,
"product_alert_phone": "+1 (884) 587-2414",
"product_alert_email": "pywu#mailinator.com",
"product_cost_price": "989.00",
"product_supplier_discount": "10.00",
"product_brand": 3,
"product_warehouse": 2,
"product_availability": 2,
"deleted_at": null,
"created_at": null,
"updated_at": null,
"category": {
"id": 2,
"category_name": "Phones",
"category_parent": null,
"category_description": null,
"deleted_at": null,
"created_at": null,
"updated_at": null
},
"brand": {
"id": 3,
"brand_name": "Oppo",
"deleted_at": null,
"created_at": null,
"updated_at": null
},
"supplier": {
"id": 1,
"supplier_company": "Dataxpress",
"supplier_code": "55598548455",
"supplier_tax_number": "68958955",
"supplier_phone": "4382251059",
"supplier_fax": "4382251059",
"supplier_website": "oppo.com",
"supplier_email": "ab#dothostia.com",
"supplier_note": "Aliquip porro est n",
"supplier_type": 1,
"supplier_address": "Consequuntur maxime",
"supplier_city": "Qui consectetur non",
"supplier_state": "Ex nemo sit quia ame",
"supplier_zip": "46033",
"supplier_country": "HU",
"supplier_representative": 2,
"supplier_price_list": 4,
"supplier_tax_type": 2,
"supplier_currency": "GBP",
"deleted_at": null,
"created_at": "2020-01-17 18:16:55",
"updated_at": "2020-01-17 18:16:55"
}
}
],
"first_page_url": "http://app.quicknsales.com/backend/product?page=1",
"from": 1,
"last_page": 1,
"last_page_url": "http://app.quicknsales.com/backend/product?page=1",
"next_page_url": null,
"path": "http://app.quicknsales.com/backend/product",
"per_page": 15,
"prev_page_url": null,
"to": 3,
"total": 3
}
i need to add a key for ex : nbr_variants : x, foreach data item

I assumed your product table hasMany relation with variants. As you said in comment products.id & variants.product_id
Make function variants in product model using hasMany relationship.
Class Product extends Model{
public function variants(){
return $this->hasMany('App\Variant','product_id','id');
}
}
And now you can call it by using withCount
public function index()
{
$products = Product::with(['category', 'brand', 'supplier','variants'])->withCount('variants')->orderBy('id', 'desc')->paginate(15);
return response()->json($products);
}
As a result, You'll get product with variants and count as well.

Related

Larvel querying relationship existence still returns empty records

I'm working in a Laravel 9 project and need to show only records where the deeply nested relationship has records, in my case, tiers.
My relationship right now is still returning me pingtree_entries even though tiers are empty, what am I missing?
Here's my top level query:
$pingtree = Pingtree::where('company_id', $company_id)
->where('id', $id)
->has('pingtree_entries.tiers')
->with('pingtree_entries.tiers')
->first();
This should be saying something like:
Get me my Pingtree by company ID and ID with my tiers associated to the pingtree_entries for the Pingtrees where there is more than 0 tiers.
My Pingtree model defines:
/**
* Get the pingtrees that the model has.
*/
public function pingtree_entries()
{
return $this->hasMany(PingtreeEntry::class);
}
My PingtreeEntry model defines:
/**
* Get the buyer tier that the model has.
*/
public function tiers()
{
return $this->hasMany(BuyerTier::class, 'id', 'buyer_tier_id');
}
This is outputting the following via Postman:
{
"model": {
"id": 1,
"user_id": 1,
"company_id": 1,
"pick_chance": 4,
"name": "omnis iusto consequatur",
"description": "Hic nihil suscipit error.",
"is_enabled": false,
"created_at": "2023-01-27T14:15:26.000000Z",
"updated_at": "2023-01-27T14:15:26.000000Z",
"deleted_at": null,
"is_deleting": false,
"pingtree_entries": [
{
"id": 1,
"user_id": 1,
"company_id": 1,
"buyer_id": 2,
"buyer_tier_id": 4,
"pingtree_id": 1,
"pingtree_group_id": null,
"processing_order": 1,
"is_enabled": true,
"created_at": "2023-01-27T14:15:26.000000Z",
"updated_at": "2023-01-27T14:15:26.000000Z",
"deleted_at": null,
"tiers": [
{
"id": 4,
"user_id": 1,
"company_id": 1,
"buyer_id": 2,
"country_id": 2,
"product_id": 3,
"name": "dignissimos voluptas et",
"description": "Dolore tempora et maxime nam.",
"processing_class": "et",
"is_default": false,
"is_enabled": false,
"created_at": "2023-01-27T14:15:25.000000Z",
"updated_at": "2023-01-27T14:15:25.000000Z",
"deleted_at": null,
"is_deleting": false
}
]
},
{
"id": 3,
"user_id": 1,
"company_id": 1,
"buyer_id": null,
"buyer_tier_id": null,
"pingtree_id": 1,
"pingtree_group_id": 1,
"processing_order": 1,
"is_enabled": false,
"created_at": "2023-01-27T14:15:26.000000Z",
"updated_at": "2023-01-27T14:15:26.000000Z",
"deleted_at": null,
"tiers": []
}
]
}
}
Note that the last PingtreeEntry has no tiers. So I don't want to show the whole PingtreeEntry model at all.
Attempted with whereHas
$pingtree = Pingtree::where('company_id', $company_id)
->where('id', $id)
->whereHas('pingtree_entries.tiers')
->with('pingtree_entries.tiers.buyer')
->first();
use :
$pingtree = Pingtree::where('company_id', $company_id)
->where('id', $id)
->with([
'pingtree_entries' => fn($q) => $q->has('tiers'),
'pingtree_entries.tiers',
])
->first();

laravel relationship tickets, ticket messages and message attachments

I am writing a support ticket system in laravel. I need to establish relationships between tables. I'm new to Laravel. I need to get the messages of a ticket and the files of those messages. By reading the documentation, I have established a relationship between the messages belonging to the ticket and it works correctly. However, I need to get the files under those messages, can you help me with this?
The json of the messages is as follows:
{
"ticket": [
{
"id": 1,
"subject": "test 1",
"department_id": 1,
"priority": "low",
"status": "open",
"users_id": 1,
"created_at": "2022-10-03T11:47:42.000000Z",
"updated_at": "2022-10-04T17:31:10.000000Z",
"deleted_at": null,
"author": "Admin Admin",
"author_id": 1,
"department": "Genel",
"messages": [
{
"id": 1,
"admin_tickets_id": 1,
"users_id": 1,
"admin_users_id": null,
"reply": "test mesajıdır.",
"deleted_at": null,
"created_at": "2022-10-03T11:47:42.000000Z",
"updated_at": "2022-10-03T11:47:42.000000Z"
},
{
"id": 5,
"admin_tickets_id": 1,
"users_id": null,
"admin_users_id": 1,
"reply": "test mesajıdır.",
"deleted_at": null,
"created_at": "2022-10-03T11:47:42.000000Z",
"updated_at": "2022-10-03T11:47:42.000000Z"
},
{
"id": 9,
"admin_tickets_id": 1,
"users_id": null,
"admin_users_id": 1,
"reply": "test için yaziyom",
"deleted_at": null,
"created_at": "2022-10-04T22:19:32.000000Z",
"updated_at": "2022-10-04T22:19:32.000000Z"
},
{
"id": 10,
"admin_tickets_id": 1,
"users_id": null,
"admin_users_id": 1,
"reply": "test",
"deleted_at": null,
"created_at": "2022-10-04T22:26:39.000000Z",
"updated_at": "2022-10-04T22:26:39.000000Z"
},
{
"id": 11,
"admin_tickets_id": 1,
"users_id": null,
"admin_users_id": 1,
"reply": "test",
"deleted_at": null,
"created_at": "2022-10-04T22:27:00.000000Z",
"updated_at": "2022-10-04T22:27:00.000000Z"
},
{
"id": 12,
"admin_tickets_id": 1,
"users_id": null,
"admin_users_id": 1,
"reply": "deneme",
"deleted_at": null,
"created_at": "2022-10-04T22:28:45.000000Z",
"updated_at": "2022-10-04T22:28:45.000000Z"
},
{
"id": 13,
"admin_tickets_id": 1,
"users_id": null,
"admin_users_id": 1,
"reply": "yine deneme",
"deleted_at": null,
"created_at": "2022-10-04T22:32:34.000000Z",
"updated_at": "2022-10-04T22:32:34.000000Z"
}
]
}
]
}
but I want it to be like this:
Pay attention to the file below the message.
{
"ticket": [
{
"id": 1,
"subject": "test 1",
"department_id": 1,
"priority": "low",
"status": "open",
"users_id": 1,
"created_at": "2022-10-03T11:47:42.000000Z",
"updated_at": "2022-10-04T17:31:10.000000Z",
"deleted_at": null,
"author": "Admin Admin",
"author_id": 1,
"department": "Genel",
"messages": [
{
"id": 1,
"admin_tickets_id": 1,
"users_id": 1,
"admin_users_id": null,
"reply": "test mesajıdır.",
"deleted_at": null,
"created_at": "2022-10-03T11:47:42.000000Z",
"updated_at": "2022-10-03T11:47:42.000000Z"
"attachments": [
{
"id": 1
"name": "deneme",
"extension": "pdf",
},
]
},
{
"id": 5,
"admin_tickets_id": 1,
"users_id": null,
"admin_users_id": 1,
"reply": "test mesajıdır.",
"deleted_at": null,
"created_at": "2022-10-03T11:47:42.000000Z",
"updated_at": "2022-10-03T11:47:42.000000Z"
},
{
"id": 9,
"admin_tickets_id": 1,
"users_id": null,
"admin_users_id": 1,
"reply": "test için yaziyom",
"deleted_at": null,
"created_at": "2022-10-04T22:19:32.000000Z",
"updated_at": "2022-10-04T22:19:32.000000Z"
},
{
"id": 10,
"admin_tickets_id": 1,
"users_id": null,
"admin_users_id": 1,
"reply": "test",
"deleted_at": null,
"created_at": "2022-10-04T22:26:39.000000Z",
"updated_at": "2022-10-04T22:26:39.000000Z"
},
{
"id": 11,
"admin_tickets_id": 1,
"users_id": null,
"admin_users_id": 1,
"reply": "test",
"deleted_at": null,
"created_at": "2022-10-04T22:27:00.000000Z",
"updated_at": "2022-10-04T22:27:00.000000Z"
},
{
"id": 12,
"admin_tickets_id": 1,
"users_id": null,
"admin_users_id": 1,
"reply": "deneme",
"deleted_at": null,
"created_at": "2022-10-04T22:28:45.000000Z",
"updated_at": "2022-10-04T22:28:45.000000Z"
},
{
"id": 13,
"admin_tickets_id": 1,
"users_id": null,
"admin_users_id": 1,
"reply": "yine deneme",
"deleted_at": null,
"created_at": "2022-10-04T22:32:34.000000Z",
"updated_at": "2022-10-04T22:32:34.000000Z"
}
]
}
]
}
I share my controllers and models:
TicketsController.php
public function show($id) {;
$data = array();
$data['ticket'] = AdminTickets::addSelect([
'author' => Users::select(DB::raw("name || ' ' || surname as fullname"))
->whereColumn('id', 'admin_tickets.users_id')
->limit(1),
'author_id' => Users::select('id')
->whereColumn('id', 'admin_tickets.users_id')
->limit(1),
'department' => AdminTicketDepartments::select('name')
->whereColumn('id', 'admin_tickets.department_id')
->limit(1),
])->where('id', $id)->with('messages', fn ($query) =>
$query->whereHas('attachments')
)->get();
return $data;
die();
return view('admin.tickets.show', $data);
}
AdminTickets Model:
public function messages()
{
return $this->hasMany(AdminTicketReplies::class);
}
AdminTicketReplies Model:
public function attachments() {
return $this->hasManyThrough(AdminTicketAttachments::class, AdminTicketReplies::class);
}
I think I'm making a mistake in the AdminTicketReplies model. How can I do that?
You are now getting all messages that have at least one attachment. you can add the attachments by using another with():
->where('id', $id)->with('messages', fn ($query) =>
$query->whereHas('attachments')
$query->with('attachments')
)->get();
If you want all messages and include the attachments, you can use the dot notation:
->where('id', $id)->with('messages.attachments')

How to modify array structure returned by eloquent in laravel

I currently have the below array structure that I get when running Bonus::with('users')->get()
I have tried adding the array and merging similar keys but it is not working. I tried using the helper methods provided in laravel but I don't seem to be able to get it working.
[
{
"id": 1,
"users_id": 1,
"bonus_type_id": 1,
"is_paid": 0,
"amount": "100.00",
"description": "desc",
"note": null,
"created_by": 2,
"last_modified_by": null,
"created_at": null,
"updated_at": null,
"deleted_at": null,
"user": {
"id": 1,
"name": "test",
"email": "test#testing.com",
"email_verified_at": null,
"status": 1,
"created_at": "2019-07-18 11:41:35",
"updated_at": "2019-07-18 11:41:35",
"deleted_at": null
}
},
{
"id": 2,
"users_id": 1,
"bonus_type_id": 2,
"is_paid": 0,
"amount": "100.00",
"description": "desc",
"note": null,
"created_by": 2,
"last_modified_by": null,
"created_at": null,
"updated_at": null,
"deleted_at": null,
"user": {
"id": 1,
"name": "test",
"email": "test#testing.com",
"email_verified_at": null,
"status": 1,
"created_at": "2019-07-18 11:41:35",
"updated_at": "2019-07-18 11:41:35",
"deleted_at": null
}
},
{
"id": 3,
"users_id": 2,
"bonus_type_id": 2,
"is_paid": 1,
"amount": "100.00",
"description": "desc",
"note": null,
"created_by": 2,
"last_modified_by": null,
"created_at": null,
"updated_at": null,
"deleted_at": null,
"user": {
"id": 1,
"name": "another test",
"email": "another#testing.com",
"email_verified_at": null,
"status": 1,
"created_at": "2019-07-18 11:41:35",
"updated_at": "2019-07-18 11:41:35",
"deleted_at": null
}
}
]
I want the result to be something like that
[
{
user_id: 1,
name: "test",
bonuses: [
{
bonus_type_id: 1,
amount: 100,
is_paid: 0,
},
{
bonus_type_id: 2,
amount: 100,
is_paid: 0,
}
],
},
{
user_id: 2,
name: "another",
bonuses: [
{
bonus_type_id: 2,
amount: 100,
is_paid: 1,
},
]
}
]
You need to change your eloquent relationship. Define hasMany relationship function bonuses inside User model for bonuses table and use that to get the desired result like so:
User::with('bonuses')->get();
That way it will return results from users table and populate bonuses for each user.
makes sense?
You can get specific information with select subquery, if your relations are correctly set, this should work.
User::select('user_id','name','bonus_id')
->with(array('bonuses'=> function($query){
$query->select('bonus_type_id','amount','is_paid');
}))->get();

How can I hidden data in JSON if variable is empty

I got a some trouble in my Laravel application, in Search function, when I do search the result is
{
"data": [
{
"id": 2,
"user_id": 8,
"identity_number": "213918273",
"name": "Pekerja_2",
"gender_id": 1,
"date_of_birth": "1999-05-25",
"address": "Jalan Bandung Raya no 50",
"province_id": 32,
"city_id": 3273,
"district_id": 3273160,
"phone": "4232343432",
"image": null,
"created_at": "2018-01-11 10:59:54",
"updated_at": "2018-01-11 10:59:54",
"partner_id": null,
"skill": [
{
"id": 3,
"worker_id": 2,
"skill_id": 6,
"sub_skill_id": 18,
"created_at": "2018-01-15 13:06:48",
"updated_at": "2018-01-15 13:06:48",
"price": null,
"unit": null
}
]
},
{
"id": 3,
"user_id": 16,
"identity_number": "213918273",
"name": "Pekerja_3",
"gender_id": 1,
"date_of_birth": "1999-05-25",
"address": "Jalan Bandung Raya no 50",
"province_id": 32,
"city_id": 3273,
"district_id": 3273160,
"phone": "2345234234",
"image": null,
"created_at": "2018-01-15 13:06:48",
"updated_at": "2018-01-15 13:06:48",
"partner_id": null,
"skill": []
}
]
}
as you can see that "Skill" with id number 3 is empty, I want all in id number 3 is empty also.
My controller is :
$worker = Worker::with(['skill' => function($q) use ($request) {
$q->where('worker_skills.sub_skill_id', $request['sub_skill_id']);
}])->whereHas('skill');
And I want something like this :
{
"data": [
{
"id": 2,
"user_id": 8,
"identity_number": "213918273",
"name": "Pekerja_2",
"gender_id": 1,
"date_of_birth": "1999-05-25",
"address": "Jalan Bandung Raya no 50",
"province_id": 32,
"city_id": 3273,
"district_id": 3273160,
"phone": "2534234234",
"image": null,
"created_at": "2018-01-11 10:59:54",
"updated_at": "2018-01-11 10:59:54",
"partner_id": null,
"skill": [
{
"id": 3,
"worker_id": 2,
"skill_id": 6,
"sub_skill_id": 18,
"created_at": "2018-01-15 13:06:48",
"updated_at": "2018-01-15 13:06:48",
"price": null,
"unit": null
}
]
},
]
}
The point is, if "skill" variable is empty then data not show and vice versa.
Thankyou any help will appreciate, sorry for bad english
You can add a callback to your whereHas function with the same filter as the with function
$worker = Worker::with(['skill' => function($q) use ($request) {
$q->where('worker_skills.sub_skill_id', $request['sub_skill_id']);
}])
->whereHas('skill', function($q) use ($request) {
$q->where('worker_skills.sub_skill_id', $request['sub_skill_id']);
})
->get();
You can try this $worker = Worker:has('skill')->get();
Only worker that have at least one skill are contained in the collection

Using Eloquent ORM in Laravel to perform search of database using 'not regexp'

I'm dealing with searching in categories by slug and I want to exclude results which contain dash & number at the end (like: powerbank-1).
My query :
$categories = Category::where('active_products', ">", 0)
->where('slug', 'LIKE', "%$search_term%")
->where('slug', 'not regexp', "/$search_term-[0-9]/")
->get();
My result still contain unwanted results with -1 & -2 endings in slug:
{
"query": "powerbank",
"categories": [
{
"id": 18,
"parent_id": 17,
"lft": 108,
"rgt": 109,
"depth": 1,
"name": "Powerbank",
"description": null,
"description2": null,
"products": 43,
"active_products": 38,
"created_at": "2016-08-25 20:51:42",
"updated_at": "2016-09-20 06:06:06",
"slug": "powerbank"
},
{
"id": 20,
"parent_id": 19,
"lft": 124,
"rgt": 125,
"depth": 1,
"name": "Powerbank",
"description": null,
"description2": null,
"products": 43,
"active_products": 38,
"created_at": "2016-08-25 20:51:43",
"updated_at": "2016-09-20 06:06:06",
"slug": "powerbank-1"
},
{
"id": 22,
"parent_id": 21,
"lft": 136,
"rgt": 137,
"depth": 1,
"name": "Powerbank",
"description": null,
"description2": null,
"products": 43,
"active_products": 38,
"created_at": "2016-08-25 20:51:43",
"updated_at": "2016-09-20 06:06:06",
"slug": "powerbank-2"
}]
}
Found the problem why was not working: delete slashes from regex, so itt will be:
->where('slug', 'not regexp', "$search_term-[0-9]")

Categories