Laravel nested eloquent relationships using model - laravel

I am trying to getting the more sorted object as output using laravel eloquent relationships
Section::with(['fieldTypes','fields'=>
function ($query) use ($id) {
$query->where('user_id', '=', $id);
},
'fields.fieldType'=> function ($query) {
$query->select('id','type','url','icon');
}])->get();
Output
"fields": [
{
"id": 1,
"user_id": 1,
"field_type_id": 1,
"section_id": 3,
"title": "Facebook",
"value": "inderjit",
"order": 1,
"field_type": {
"id": 1,
"type": "facebook",
"url": "https://www.facebook.com/"
}
}
]
I want output like this . I want to merge 2 objects as one
"fields": [
{
"id": 1,
"user_id": 1,
"field_type_id": 1,
"section_id": 3,
"title": "Facebook",
"value": "inderjit",
"order": 1,
"type": "facebook",
"url": "https://www.facebook.com/"
}
]

Something like this. You can add a method in your model where you trigger a leftJoin. Then you have the fields of the relation in the model.
public function scopeJoinWithFieldTypes($query)
{
return $query->leftJoin("field_types", "field_type.id", "=", "fields.id");
}

Related

jenssegers/laravel-mongodb One to Many (with reference) relationship doesn't work at all

I have 2 models created with jenssegers/laravel-mongodb package.
<?php
class CronJob extends Model {
protected $connection = 'mongodb';
protected $collection = 'cronjobs';
protected $primaryKey = '_id';
protected $dates = [
'created_at',
'updated_at'
];
public function details()
{
return $this->hasMany(CronJobDetail::class, 'parent_id', '_id');
}
}
class CronJobDetail extends Model {
protected $connection = 'mongodb';
protected $collection = 'cronjobsdetails';
protected $primaryKey = '_id';
protected $dates = [
'created_at',
'updated_at'
];
public function job()
{
return $this->belongsTo(CronJob::class, 'parent_id', '_id');
}
When I call CronJobDetail::first()->job I get the parent CronJob object successfully. But when I do the same as inverse like CronJob::first()->details, I get empty collection for some reason. Why isn't it working as expected?
Here's some example data for better insight:
CronJob document
{
"_id": {
"$oid": "6308cd0b2b290000c100086b"
},
"name": "Deneme-2022-08-26 16:39:23 (2)",
"job": "assignproduct",
"job_count": 2,
"product_id": "630869372b290000c1000865",
"product_name": "Deneme",
"tax_rate": 18,
"organisation": 111,
"created_by": 4,
"created_by_name": "Çağlar TUFAN",
"price": 150,
"currency": "TL",
"created_at": "2022-08-26 16:39:23",
"updated_at": "2022-08-26 16:39:23"
}
CronJobDetails documents
{
"_id": {
"$oid": "6308cd0b2b290000c100086b"
},
"name": "Deneme-2022-08-26 16:39:23 (2)",
"job": "assignproduct",
"job_count": 2,
"product_id": "630869372b290000c1000865",
"product_name": "Deneme",
"tax_rate": 18,
"organisation": 111,
"created_by": 4,
"created_by_name": "Çağlar TUFAN",
"price": 150,
"currency": "TL",
"created_at": "2022-08-26 16:39:23",
"updated_at": "2022-08-26 16:39:23"
},
{
"_id": {
"$oid": "6308cd0b2b290000c100086d"
},
"job": "assignproduct",
"email": "erhan#w3.com.tr",
"product_id": "630869372b290000c1000865",
"product_name": "Deneme",
"organisation": 111,
"status": 0,
"created_by": 4,
"created_by_name": "Çağlar TUFAN",
"price": 150,
"currency": "TL",
"created_at": "2022-08-26 16:39:23",
"updated_at": "2022-08-26 16:39:23",
"name": "Deneme-2022-08-26 16:39:23 (2)",
"parent_id": {
"$oid": "6308cd0b2b290000c100086b"
}
}

How to retrieve Json data type data in SQL using a where condition in LARAVEL

Question : How to retrieve Json data type data in SQL using a where condition in LARAVEL?
I want to display all the order that contains order->Product->user->id === 1
{
"currentUserID": 1,
"currentUserName": "Mohamed Naalir",
"order": [
{
"id": 26,
"Product": [
{
"id": 4,
"name": "Araliya Rice",
"desription": "Araliya Rice",
"salePrice": 500,
"category": "Rice",
"user": {
"id": 1,
"name": "Mohamed Naalir",
}
}
],
},
{
"id": 27,
"Product": [
{
"id": 2,
"name": "white sugar",
"desription": "aaa",
"salePrice": 100,
"category": "Sugar",
"user": {
"id": 5,
"name": "Mohamed Sharaf",
}
}
],
}
]
}
json where clauses
$orders = DB::table('orders')
->whereJsonContains('Product', [['user' => ['id' => 1]]])
->get();

Limit number of results in nested query

I have a table called comments with the following columns:
| id | user_id | post_id | parent_id | text |
I have this setup for a nested comment system, like Disqus:
If the comment has no parent comment, parent_id will be 0. But if a comment has a parent, the parent_id will be the id of the parent comment.
In my Comments.php model, I have this relationship:
public function children()
{
return $this->hasMany('App\Comment', 'parent_id', 'id')->with('children');
}
Now, if I query the comments:
$comments = Comment::where('post_id', 1)
->where('parent_id', 0)
->with('children')
->get();
The output will look something like this:
[
{
"id": 5,
"user_id": "2",
"post_id": "1",
"parent_id": "0",
"text": "Text",
"children": [
{
"id": 7,
"user_id": "1",
"post_id": "1",
"parent_id": "5",
"text": "Text",
"children": [
{
"id": 8,
"user_id": "3",
"post_id": "1",
"parent_id": "7",
"text": "Text",
"children": [
]
},
{
"id": 11,
"user_id": "3",
"post_id": "1",
"parent_id": "7",
"text": "Text",
"children": [
]
},
]
},
{
"id": 9,
"user_id": "1",
"post_id": "1",
"parent_id": "5",
"text": "Text",
"children": [
]
}
,
{
"id": 10,
"user_id": "1",
"post_id": "1",
"parent_id": "5",
"text": "Text",
"children": [
]
}
]
},
{
"id": 6,
"user_id": "3",
"post_id": "1",
"parent_id": "0",
"text": "Text",
"children": [
]
}
]
Or, in simpler terms:
- 5
-- 7
--- 8
--- 11
-- 9
-- 10
- 6
What I want to do is limit the number of results returned per depth.
So, for example, how can I change my query/code such that it returns:
Ten top-level results (parent_id of 0)
Two level-1 results
One level-2 result
So in the end, the query should output the comments like this:
- 5
-- 7
--- 8
-- 9
- 6
As you can see, there are two top-level results (up to 10 allowed), two level-1 results, and one level-2 result.
How can I do this?
Instead of using with in the model that may gets you uncontrolled retrieval of data, why not do it when you need it?
Which means, in your Comment.php, remove the with:
public function children()
{
return $this->hasMany('App\Comment', 'parent_id', 'id');
}
And in your controller/helper/service classes, only retrieve what you need? For example:
$comments = Comment::where('post_id', 1)
->where('parent_id', 0)
->with('children' => function($query) {
$query->with('children' => function($query) {
$query->with('children')
->orderBy('created_at', 'desc')
->take(1); //last 1
})
->orderBy('created_at', 'desc')
->take(2); // intermediate 2
})
->orderBy('created_at', 'desc')
->take(10) //the outermost 10
->get();
Not tested yet, but theoretically should work :)
Note: Added order by created_at because we usually want the latest few comments to comes out at the top :)

How to get parent objects and nested children objects by parent and children ids

I have a parent object (blogpost) and nested items (comments)
The parent and nested objects are both keyed by an id
So if I fetch the parent object, i will get all the children too
GET /my_index/blogpost/1
{
"id": 1,
"title": "Nest eggs",
"body": "Making your money work...",
"tags": [ "cash", "shares" ],
"comments": [
{
"id": 2,
"comment": "Great article",
"age": 28,
"stars": 4,
"date": "2014-09-01"
},
{
"id": 4,
"comment": "More like this please",
"age": 31,
"stars": 5,
"date": "2014-10-22"
}
]
}
Question
However, I only want to fetch the parent and a subset of children based on children ids
e.g. My desired behaviour is this:
GET /my_index/blogpost/1?onlyGetCommentIds=4
{
"id": 1,
"title": "Nest eggs",
"body": "Making your money work...",
"tags": [ "cash", "shares" ],
"comments": [
{
"id": 4,
"comment": "More like this please",
"age": 31,
"stars": 5,
"date": "2014-10-22"
}
]
}
See in the above example that only comment id == 4 is returned along with the parent object.
How do I construct this query?
You need to use nested inner_hits in order to achieve what you want
POST /my_index/blogpost/_search
{
"_source": {
"exclude": "comments"
},
"query": {
"bool": {
"filter": [
{
"term": {
"id": 1
}
},
{
"nested": {
"path": "comments",
"query": {
"term": {
"comments.id": 4
}
},
"inner_hits": {}
}
}
]
}
}
}
The response will include the parent object (without the comments nested objects) and another inner_hits section containing only the desired nested comment with id = 4.

Laravel Eloquent - Get Eloquent Relationship Model Data From nested Relationship

I have 3 models like this-
User
<?php
namespace App;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
protected $fillable = [
'profile_picture',
'first_name',
'last_name',
'email',
'cell_no',
'website',
'date_of_birth',
'social_security_number_p1',
'social_security_number_p2',
'social_security_number_p3',
'address',
'location_latitude',
'location_longitude',
'password',
'user_type',
'is_enabled'
];
protected $hidden = [
'password',
'remember_token',
'id',
'user_type',
'is_enabled',
'created_at',
'updated_at'
];
public function advertisement()
{
return $this->hasMany('App\Advertisement', 'user_id');
}
}
Advertisement
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Auth;
class Advertisement extends Model
{
protected $fillable = [
'user_id',
'category_id',
'sub_category_id',
'title',
'price',
'description',
'address',
'location_lat',
'location_lon',
'is_active',
'deleted_at'
];
public function User()
{
return $this->belongsTo('App\User','user_id', 'id');
}
public function Offer()
{
return $this->hasMany('App\Offer', 'add_id', 'id');
}
}
Offer
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Offer extends Model
{
protected $fillable = [
'add_id',
'user_id',
'price',
'message'
];
public function User()
{
return $this->hasOne('App\User','user_id','id');
}
public function Advertisement()
{
return $this->hasOne('App\advertisement','add_id','id');
}
}
I want to get advertisements with offer and offers with offer sender (user).
So, I am doing something like this-
return Advertisement::with('AdvertisementImages')
->with('Offer')
->with('User')
->where('user_id', Auth::user()->id)
->get();
And getting this-
[
{
"id": 1,
"user_id": 16,
"title": "123asd",
"price": 123,
"description": "asd asd asd ",
"address": "Dhaka University Campus, Dhaka, Dhaka Division, Bangladesh",
"location_lat": 23.73,
"location_lon": 90.39,
"total_views": "110",
"avg_rating": "4.0000",
"is_reviewed": 0,
"is_offer_sent": 1,
"advertisement_images": [
{
"image_name": "16-68261.jpg"
},
{
"image_name": "16-34746.JPG"
},
{
"image_name": "16-79570.jpg"
}
],
"offer": [
{
"id": 1,
"add_id": 1,
"user_id": 9,
"price": 123,
"message": "asd ad asdasd ",
"created_at": "2016-08-11 02:22:43",
"updated_at": "2016-08-11 02:22:43"
},
{
"id": 2,
"add_id": 1,
"user_id": 15,
"price": 43,
"message": "as dfasd ",
"created_at": "2016-08-11 02:24:04",
"updated_at": "2016-08-11 02:24:04"
},
{
"id": 3,
"add_id": 1,
"user_id": 16,
"price": 23,
"message": "hgf",
"created_at": "2016-08-11 02:25:31",
"updated_at": "2016-08-12 01:37:42"
}
],
"user": {
"profile_picture": "",
"first_name": "Ne",
"last_name": "Ajgor",
"cell_no": null,
"email": "ajgor#me.com",
"website": "",
"date_of_birth": "0000-00-00",
"social_security_number_p1": "",
"social_security_number_p2": "",
"social_security_number_p3": "",
"address": "",
"location_latitude": 0,
"location_longitude": 0
}
}
]
So, it is wrong. I am getting user from Advertisement.
But I like to have user from Offer.
So, I need to have something like this-
[
{
"id": 1,
"user_id": 16,
"title": "123asd",
"price": 123,
"description": "asd asd asd ",
"address": "Dhaka University Campus, Dhaka, Dhaka Division, Bangladesh",
"location_lat": 23.73,
"location_lon": 90.39,
"total_views": "110",
"avg_rating": "4.0000",
"is_reviewed": 0,
"is_offer_sent": 1,
"advertisement_images": [
{
"image_name": "16-68261.jpg"
},
{
"image_name": "16-34746.JPG"
},
{
"image_name": "16-79570.jpg"
}
],
"offer": [
{
"id": 1,
"add_id": 1,
"user_id": 9,
"price": 123,
"message": "asd ad asdasd ",
"created_at": "2016-08-11 02:22:43",
"updated_at": "2016-08-11 02:22:43",
"user": {
"profile_picture": "",
"first_name": "Me",
"last_name": "Ajgor",
"cell_no": null,
"email": "ajgor#me.com",
"website": "",
"date_of_birth": "0000-00-00",
"social_security_number_p1": "",
"social_security_number_p2": "",
"social_security_number_p3": "",
"address": "",
"location_latitude": 0,
"location_longitude": 0
}
},
{
"id": 2,
"add_id": 1,
"user_id": 15,
"price": 43,
"message": "as dfasd ",
"created_at": "2016-08-11 02:24:04",
"updated_at": "2016-08-11 02:24:04",
"user": {
"profile_picture": "",
"first_name": "Ne",
"last_name": "Ajgor",
"cell_no": null,
"email": "ajgor#me.com",
"website": "",
"date_of_birth": "0000-00-00",
"social_security_number_p1": "",
"social_security_number_p2": "",
"social_security_number_p3": "",
"address": "",
"location_latitude": 0,
"location_longitude": 0
}
},
{
"id": 3,
"add_id": 1,
"user_id": 16,
"price": 23,
"message": "hgf",
"created_at": "2016-08-11 02:25:31",
"updated_at": "2016-08-12 01:37:42",
"user": {
"profile_picture": "",
"first_name": "Je",
"last_name": "Ajgor",
"cell_no": null,
"email": "ajgor#me.com",
"website": "",
"date_of_birth": "0000-00-00",
"social_security_number_p1": "",
"social_security_number_p2": "",
"social_security_number_p3": "",
"address": "",
"location_latitude": 0,
"location_longitude": 0
}
}
]
}
]
Can anyone please help me, what I need to call?
Thanks in advance for helping.
I have solved it like this-
Advertisement::with('AdvertisementImages')
->with('Offer','Offer.User')
->where('user_id', Auth::user()->id)
->has('Offer')
->get();

Resources