ignore null objects of eager loaded data- laravel - php

I have folowing JSON returned by ORM
[
{
"id": 3,
"name": "Card Department",
"name_burmese": "Card Department",
"is_active": "1",
"created_at": "2014-11-23 07:02:07",
"updated_at": "2014-11-23 07:02:07",
"orm_bank_contact": []
},
{
"id": 1,
"name": "Loan Department",
"name_burmese": "Loan Department",
"is_active": "1",
"created_at": "2014-11-23 07:01:16",
"updated_at": "2015-02-24 09:05:35",
"orm_bank_contact": []
},
{
"id": 4,
"name": "Remittance Department",
"name_burmese": "Remittance Department",
"is_active": "0",
"created_at": "2015-02-24 09:43:25",
"updated_at": "2015-04-17 12:26:07",
"orm_bank_contact": []
},
{
"id": 2,
"name": "Deposit Department",
"name_burmese": "Deposit Department",
"is_active": "1",
"created_at": "2014-11-23 07:01:34",
"updated_at": "2015-04-20 14:04:27",
"orm_bank_contact": [
{
"id": 27,
"bank_department": 2,
"mobile": "9843139168",
"phone": "9843139168",
"email": "shresthabeenu#gmail.com",
"contact_person": "Binu Shrestha",
"address": "No. 416, Mahabandoola Road, Kyauktada Township, Yangon, Myanmar",
"is_active": "1",
"created_at": "2015-04-15 08:50:16",
"updated_at": "2015-04-15 08:50:16",
"bank_id": 13
}
]
}
]
but i just need
[
{
"id": 2,
"name": "Deposit Department",
"name_burmese": "Deposit Department",
"is_active": "1",
"created_at": "2014-11-23 07:01:34",
"updated_at": "2015-04-20 14:04:27",
"orm_bank_contact": [
{
"id": 27,
"bank_department": 2,
"mobile": "9843139168",
"phone": "9843139168",
"email": "shresthabeenu#gmail.com",
"contact_person": "Binu Shrestha",
"address": "No. 416, Mahabandoola Road, Kyauktada Township, Yangon, Myanmar",
"is_active": "1",
"created_at": "2015-04-15 08:50:16",
"updated_at": "2015-04-15 08:50:16",
"bank_id": 13
}
]
}
]
I need to fetch record with child on eager loaded objects
I tried below
$bank_contact = BankDepartment::with(array('OrmBankContact' => function($query) use($bank_id){
$query->where('bank_id', "=", $bank_id)->where('bank_department','>',0);}))
->get();
But no luck.. what is the proper way?

This query should do the job returning only departments with OrmBankContact
BankDepartment::has('OrmBankContact')->get();
See Eloquent docs on querying relations

Model BankDepartment
class BankDepartment extends Eloquent implements UserInterface, RemindableInterface {
public function OrmBankContact(){
return $this->hasMany('OrmBankContact','bank_department','id');
}
}
Model OrmBankContact
class OrmBankContact extends Eloquent implements UserInterface, RemindableInterface {
public function BankDepartment(){
return $this->belongsTo('BankDepartment','bank_department','id');
}
}
In Any controller you can get like this
$OrmBankContact = BankDepartment::with('OrmBankContact')->get();
$OrmBankContact = $OrmBankContact->toArray();
echo '<pre>'; print_r($OrmBankContact); exit;

Related

Laravel Eloquent perform Aggregation function in the pivot relationship

I would like to perform the average rating of respective product which stored in the pivot table called "reviews".Below are my existing code.
Product Model:
public function reviews(){
return $this->belongsToMany(User::class,'reviews')->withPivot('comment','rating')->withTimestamps();
}
public function getProductRatingAttribute(){
return $this->reviews()->average('rating');
}
User Model:
public function reviews(){
return $this->belongsToMany(Product::class,'reviews')->withPivot('comment','rating')->withTimestamps();
}
Migration for the reviews
Schema::create('reviews', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->unsignedBigInteger('user_id');
$table->unsignedBigInteger('product_id');
$table->string('comment')->nullable();
$table->integer('rating');
$table->foreign('user_id')->references('id')->on('users');
$table->foreign('product_id')->references('id')->on('products');
});
I have attempted to use the below to code construct the expected output but it leads N+1 issue because it does not take advantage of the eager loading of the Laravel Eloquent.
$s = Product::with('reviews')->append('product_rating');
As I check telescope, it produces 6 query which can lead performance issue when the data is large.
Expected output:
{
"msg": [
{
"id": 4,
"created_at": "2021-04-09T07:32:35.000000Z",
"updated_at": "2021-04-09T07:32:35.000000Z",
"name": "MacDonald",
"nickname": "MCD",
"users_id": 1,
"price": "0.00",
"product_rating": "3.3333",
"reviews": [
{
"id": 1,
"name": "John Smith",
"email": "john.smith#hotmail.com",
"email_verified_at": null,
"created_at": "2021-04-08T13:29:13.000000Z",
"updated_at": "2021-04-08T13:29:13.000000Z",
"role": 0,
"pivot": {
"product_id": 4,
"user_id": 1,
"comment": "Ouch",
"rating": 3,
"created_at": "2021-05-01T11:51:26.000000Z",
"updated_at": "2021-05-01T11:52:07.000000Z"
}
},
{
"id": 2,
"name": "Kelvin Ooi",
"email": "kelvin.ooi#hotmail.com",
"email_verified_at": null,
"created_at": "2021-04-08T13:29:13.000000Z",
"updated_at": "2021-04-13T12:07:11.000000Z",
"role": 1,
"pivot": {
"product_id": 4,
"user_id": 2,
"comment": "Ouch",
"rating": 5,
"created_at": "2021-05-01T11:51:26.000000Z",
"updated_at": "2021-05-01T11:52:07.000000Z"
}
},
{
"id": 1,
"name": "John Smith",
"email": "john.smith#hotmail.com",
"email_verified_at": null,
"created_at": "2021-04-08T13:29:13.000000Z",
"updated_at": "2021-04-08T13:29:13.000000Z",
"role": 0,
"pivot": {
"product_id": 4,
"user_id": 1,
"comment": "Ouch",
"rating": 2,
"created_at": "2021-05-01T11:51:26.000000Z",
"updated_at": "2021-05-01T11:52:07.000000Z"
}
}
]
},
{
"id": 10,
"created_at": null,
"updated_at": null,
"name": "Mary Bown",
"nickname": "MB",
"users_id": 1,
"price": "2.88",
"product_rating": "2.0000",
"reviews": [
{
"id": 1,
"name": "John Smith",
"email": "john.smith#hotmail.com",
"email_verified_at": null,
"created_at": "2021-04-08T13:29:13.000000Z",
"updated_at": "2021-04-08T13:29:13.000000Z",
"role": 0,
"pivot": {
"product_id": 10,
"user_id": 1,
"comment": "Ouch",
"rating": 2,
"created_at": "2021-05-01T11:51:26.000000Z",
"updated_at": "2021-05-01T11:52:07.000000Z"
}
}
]
},
{
"id": 11,
"created_at": null,
"updated_at": null,
"name": "Pizza Hut",
"nickname": "pizzahut",
"users_id": 1,
"price": "4.10",
"product_rating": null,
"reviews": [
]
},
{
"id": 12,
"created_at": "2021-04-09T08:00:42.000000Z",
"updated_at": "2021-04-09T08:00:42.000000Z",
"name": "Domino Pizza",
"nickname": "domino",
"users_id": 3,
"price": "0.00",
"product_rating": null,
"reviews": [
]
},
{
"id": 13,
"created_at": "2021-04-26T16:12:53.000000Z",
"updated_at": "2021-04-26T16:12:53.000000Z",
"name": "Chicken Chop",
"nickname": "chickchop",
"users_id": 3,
"price": "0.00",
"product_rating": null,
"reviews": [
]
}
]
}
Appending is performing the query on each record.
Why not perform average on the collection itself?
$s = Product::with('reviews')->get();
$avg = $s->avg('pivot.rating');
Alternatively you can modify the relationship method to include a raw select of the average rating.

Get query instead of replace foreign key by name in laravel

Get query instead of replace foreign key by name in laravel.Get record replacement of menu_id to menu_name.Menu table contains id and menu_name.
"cart_items": [
{
"id": 1,
"cart_id": 1,
"menu_id": 5,
"quantity": "3",
"amount": "150",
"created_at": "2019-09-04 09:45:28",
"updated_at": "2019-09-04 09:45:28"
},
{
"id": 2,
"cart_id": 1,
"menu_id": 4,
"quantity": "3",
"amount": "150",
"created_at": "2019-09-04 09:54:32",
"updated_at": "2019-09-04 09:54:32"
}
]
use Laravel mutators to add menu_name for object, and add menu_id to $hidden =['manu_id']; in the model class
I use with method while fetching query.Its works
$data['cart_items'] = CartItem::with('menu')->where('cart_id',$cart->id)->get();
In my CartItem model i use eloquent orm function:
public function menu()
{
return $this->hasOne('App\Menu','id','menu_id')->select(['id','menu_name']);
}
It returns output:
"cart_items": [
{
"id": 1,
"cart_id": 1,
"menu_id": 5,
"quantity": "3",
"amount": "150",
"created_at": "2019-09-04 09:45:28",
"updated_at": "2019-09-04 09:45:28",
"menu": {
"id": 5,
"menu_name": "PODI IDLI"
}
},
{
"id": 2,
"cart_id": 1,
"menu_id": 4,
"quantity": "3",
"amount": "150",
"created_at": "2019-09-04 09:54:32",
"updated_at": "2019-09-04 09:54:32",
"menu": {
"id": 4,
"menu_name": "CORN PANEER MIX VEG SALAD WITH SAUSAGE"
}
}]

merge the data of two eloquent models into an independent array

I am working with laravel and I have basically these 3 related models in the following way: person model (Person.php), task model (Task.php) and post model (Post.php).
Person.php
public function tasks()
{
return $this->hasMany(Task::class);
}
public function posts()
{
return $this->hasMany(Post::class);
}
Task.php
public function person()
{
return $this->belongsTo(Person::class);
}
Post.php
public function person()
{
return $this->belongsTo(Person::class);
}
this is the way in which the models are related, now I have a method to recover a person and their tasks and posts that looks like this:
Person::with(['tasks','posts'])->findOrFail($id);
this returns the formatted data similar to these (it's an example):
{
"id": 1,
"name": "jhon",
"email": "jhon#gmail.com",
"created_at": "2018-09-14 12:07:35",
"updated_at": "2018-09-14 12:07:38",
"tasks": [
{
"id": 1,
"description": "task description",
"person_id": 1,
"created_at": "2018-09-18 21:07:48",
"updated_at": "2018-09-19 20:47:37",
},
{
"id": 2,
"description": "task description",
"person_id": 1,
"created_at": "2018-09-19 00:15:45",
"updated_at": "2018-09-20 15:28:58",
}
],
"posts": [
{
"id": 1,
"title": "post title",
"person_id": 1,
"created_at": "2018-09-14 12:08:52",
"updated_at": "2018-09-14 16:21:03"
},
{
"id": 3,
"title": "post title",
"person_id": 1,
"created_at": "2018-09-17 18:33:51",
"updated_at": "2018-09-17 18:33:51"
}
]
}
my question is this: is it possible to separate the result of the tasks and posts models in a different array, if this is possible as I should do ?, I want to have a result like this:
[
{
"id": 1,
"description": "task description",
"person_id": 1,
"created_at": "2018-09-18 21:07:48",
"updated_at": "2018-09-19 20:47:37",
},
{
"id": 2,
"description": "task description",
"person_id": 1,
"created_at": "2018-09-19 00:15:45",
"updated_at": "2018-09-20 15:28:58",
},
{
"id": 1,
"title": "post title",
"person_id": 1,
"created_at": "2018-09-14 12:08:52",
"updated_at": "2018-09-14 16:21:03"
},
{
"id": 3,
"title": "post title",
"person_id": 1,
"created_at": "2018-09-17 18:33:51",
"updated_at": "2018-09-17 18:33:51"
}
]
$a = DB:table('posts')->get();
$b = DB:table('tasks')->get();
$c = array_merge($a,$b);
see doc:
https://laravel.com/docs/5.7/queries

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

Subscribed topics

In my forum I'm showing all topics. It looks like this:
So a user can subscribe by clicking on the red hearth.
I'm loading the topics with this json:
{
"forum": {
"id": 1,
"slug": "test",
"name": "test",
"description": "test",
"created_at": null,
"updated_at": null
},
"topics": {
"total": 6,
"per_page": 5,
"current_page": 1,
"last_page": 2,
"next_page_url": "http://forum.dev/api/forum/test?page=2",
"prev_page_url": null,
"from": 1,
"to": 5,
"data": [
{
"id": 1,
"slug": "1",
"name": "1",
"description": "1",
"forum_id": 1,
"created_at": null,
"updated_at": null
},
{
"id": 2,
"slug": "2",
"name": "1",
"description": "1\t",
"forum_id": 1,
"created_at": null,
"updated_at": null
},
{
"id": 3,
"slug": "1",
"name": "1",
"description": "1\t",
"forum_id": 1,
"created_at": null,
"updated_at": null
},
{
"id": 4,
"slug": "1",
"name": "1",
"description": "1",
"forum_id": 1,
"created_at": null,
"updated_at": null
},
{
"id": 5,
"slug": "1",
"name": "1",
"description": "1",
"forum_id": 1,
"created_at": null,
"updated_at": null
}
]
}
}
I'm returning that ^ like this:
$forum->topics()->orderBy('created_at', 'DESC')->paginate(5);
So how do I get a subscribe value on every topic object?
So like this:
"data": [
{
"id": 1,
"slug": "1",
"name": "1",
"description": "1",
"forum_id": 1,
"created_at": null,
"updated_at": null,
"subscribed": true
},
I already made this on my topic model:
/**
* #return mixed
*/
public function subscriptions()
{
return Topic::subscribedBy(Auth::user())->get();
}
And it's working. But how do I send that ^ with every topic.
You can add an attribute (which is not present in the database) by creating an accessor.
public function getSubscriptionsAttribute()
{
return Topic::subscribedBy(Auth::user())->get();
}
and then adding it to the $append property.
protected $appends = ['subscriptions'];
If you're using the $visible whitelist you might have to add it to that property too.
Source (Its all the way in the bottom.)

Categories