I have the following table relationship:
Results ->
Objectives ->
Users ->
User
And my current query is the following:
$results = \App\Models\Results::with('objectives')
->with('objectives.users')
->with('objectives.users.user')
->get();
It works great. But now, I'd like to return only the users that are active.
$results = \App\Models\Results::with(['objectives' => function($query)
{
$query->with(['users' => function ($subQuery)
{
$subQuery->with(['user' => function($thirdQuery)
{
$thirdQuery->where('active', true);
}]);
}]);
}]);
But the result of this query returns an empty user (which is the one that is no longer active).
{
"id": 267068,
"objective_id": 9291,
"user_id": 79598,
"created_at": "2020-11-04 00:52:32",
"updated_at": "2020-11-04 00:52:32",
"user": null
},
{
"id": 267069,
"objective_id": 9291,
"user_id": 79599,
"created_at": "2020-11-04 00:52:32",
"updated_at": "2020-11-04 00:52:32",
"user":
{
"id": 79599,
"name": "John Doe",
"created_at": "2020-10-01 05:53:34",
"updated_at": "2020-10-01 05:53:34",
}
},
Applying ->whereHas('objectives.users.user') also doesn't seem to do anything!
Related
I am fairly new to laravel so I would like to know how do you grab a the data from 'data' with laravel query
the dynamo database is like this
{
"subdomain": "subdomain",
"uuid": "uuid_1234",
"data": {
"credit_limit": 1200,
"id": 1234,
"name": "Allan",
"number": 651234568
}
}
and i want to only get from the database
"credit_limit": 1200,
"id": 1234,
"name": "Allan",
"number": 651234568
the code I used is
$dynamo = DB::connection('dynamo')
->table('module_details')
->whereIndex('subdomain-index')
->where('uuid', '=', strtolower($this->Class).'_'.array_get($result['data'], 'id'))
->wherePartitionKey('subdomain', '=', Config::get('node.subdomain'))
->select('data')
->get();
but this code gave me the result of
"data": {
"credit_limit": 1200,
"id": 1234,
"name": "Allan",
"number": 651234568
}
try this
$dynamo = DB::connection('dynamo')
->table('module_details')
->whereIndex('subdomain-index')
->where('uuid', '=', strtolower($this->Class).'_'.array_get($result['data'], 'id'))
->wherePartitionKey('subdomain', '=', Config::get('node.subdomain'))
->select('data.credit_limit','data.id','data.name','data.number')
->get();
it will give you specific data that you want
I am in a situation where I want to get the form for each team of based on competition
Team model
public function standing()
{
return $this->hasMany(Standing::class);;
}
Competition model
public function standing()
{
return $this->hasMany(Standing::class);;
}
Each Team has many Standing
Each Competition has many Standing
standing table
team_id
competition_id
form
my code
$f = Fixture::where('status', 'NS')
->with('teamA', 'teamB', 'competition')
->get();
since all fixtures of all competitions are coming, but once team can be in two competition,
hence its form is different.
[
{
"name": "Leicester vs Newcastle",
"team_a": {
"id": 10,
"name": "Leicester",
**"form": null**
},
"team_b": {
"id": 2,
"name": "Newcastle",
**"form": null**
},
"competition_id": 1,
"competition": {
"id": 1,
"name": "Premier League",
},
},
{
"name": "Leeds vs Tottenham",
"id": 344,
"team_a": {
"id": 19,
"name": "Leeds",
"form": null
},
"team_b": {
"id": 11,
"form": null
},
"competition_id": 2,
"competition": {
"id": 1,
"name": "Other League",
},
},
]
I have tried to explain the situation,
can someone please tell me how to get this?
for ex.
in champions league(competition), man. united has form WWWLDW, but same team in another league might be different
I'm fetching some models from database using Laravel Eloquent. The code is like this-
$jobs = User::find($request->user_id)
->jobs
->where('status', $request->status);
return $jobs;
For the value of status = 0, the output is an array of objects-
[
{
"id": 6,
"name": "Mwkkdndnnd",
"desc": ".amsmsmskxnndsmsms",
"credits": "100",
"category_id": "1",
"views": "0",
"user_id": "11",
"deadline": "2017-07-19",
"status": "0",
"assigned_to": null,
"assigned_on": null,
"closed_at": null,
"created_at": "2017-07-17 09:57:28",
"updated_at": "2017-07-17 09:57:28"
}
]
But for the value of status = 1, the output is an object containing multiple objects-
{
"1": {
"id": 7,
"name": "Promote my company ",
"desc": "My brand needs to be promoted.",
"credits": "100",
"category_id": "1",
"views": "0",
"user_id": "11",
"deadline": "2017-07-20",
"status": "1",
"assigned_to": "12",
"assigned_on": "2017-07-18 09:32:51",
"closed_at": null,
"created_at": "2017-07-17 18:43:50",
"updated_at": "2017-07-18 09:32:51"
}
}
What is wrong the code?
Any help would be appreciated
Based on my experience with chaining another where with find, there can be unexpected behavior. So you should attempt to simply change everything to where, i.e,
$jobs = User::where('id', $request->user_id)->jobs->where('status', $request->status);
Because generally, the find method will return One model that matches, and calling a where on that model the key is not preserved so it just does a query on all the records instead of one. I may not be entirely correct, but I am pretty sure about find with where in this situation.
I would propose in order to actually see whats wrong, simply call the Job model directly and find where you have that user id (in case the relationship exists in this direction)
Job::where('user_id', $request->user_id)->get();
In fact, my observation is that you might be nursing a potential issue where if user with that id does not exist, then one uncaught error is triggered to the user. Do a check somehow in that place. findOrFail() might be helpful.
I wonder if anyone can help, as I've hit a wall and still learning Laravel ORM. Can anyone explain why, when I run:
public function locationTags(){
return $this->hasMany('App\UserHasLocationTags', 'user_id')
->join('location_tags AS lt', 'lt.id', '=', 'location_tag_id');
}
I get this result set: (snipped...)
{
"id": 1,
"created_at": "2015-05-13 13:04:56",
"updated_at": "2015-05-13 13:04:56",
"email": "REMOVED",
"firstname": "REMOVED",
"lastname": "REMOVED",
"location_id": 0,
"deleted_at": null,
"permissions": [],
"location_tags": [
{
"user_id": 1,
"location_tag_id": 1,
"id": 1,
"created_at": "2015-05-13 13:06:28",
"updated_at": "2015-05-13 13:06:28",
"name": "Test Tag 0",
"location_id": 1,
"deleted_at": null
},
{
"user_id": 1,
"location_tag_id": 2,
"id": 2,
"created_at": "2015-05-13 11:40:21",
"updated_at": "2015-05-13 12:56:13",
"name": "Test Tag 123",
"location_id": 1,
"deleted_at": null
}
]
}
Which is ace! However, when I start to select the columns I want from the location_tags join, with:
public function locationTags(){
return $this->hasMany('App\UserHasLocationTags', 'user_id')
->join('location_tags AS lt', 'lt.id', '=', 'location_tag_id')
->select('lt.id', 'lt.name');
}
I end up with:
{
"id": 1,
"created_at": "2015-05-13 13:04:56",
"updated_at": "2015-05-13 13:04:56",
"email": "REMOVED",
"firstname": "REMOVED",
"lastname": "REMOVED",
"location_id": 0,
"deleted_at": null,
"permissions": [],
"location_tags": []
}
Can someone explain what's going on? And possibly point me in the right direction to limit the selects? Thanks!
Update
I've also tried:
$query = \App\User::with(['permissions', 'locationTags' => function($query){
$query->select('lt.id', 'lt.name');
}]);
Which returns the same result :(
Figured it out. The key here was that you must include a select() value of at least one key that Laravel can use to map the result set. In my case it was user_id, like so:
public function locationTags(){
return $this->hasMany('App\UserHasLocationTags', 'user_id')
->join('location_tags AS lt', 'lt.id', '=', 'location_tag_id')
->select('user_id', 'lt.name', 'location_tag_id');
}
Which then returns a much nicer results set:
{
"id": 1,
"created_at": "2015-05-13 13:04:56",
"updated_at": "2015-05-13 13:04:56",
"email": "REMOVED",
"firstname": "REMOVED",
"lastname": "REMOVED",
"location_id": 0,
"deleted_at": null,
"permissions": [],
"location_tags": [
{
"user_id": 1,
"name": "Test Tag 0",
"location_tag_id": 1
},
{
"user_id": 1,
"name": "Test Tag 123",
"location_tag_id": 2
}
]
}
Hope this helps someone out in the future, because it kept me guessing for a good couple of hours.
I'm sorry but you've gone a little sideways here. The relationship definition should just define the Relationship. It's a powerful feature that supports many other aspects of the ORM. What you've done here is more or less build a custom Query, severely limiting the effectiveness of the relationship.
Up until recently, the proper way would have looked something like this.
// class User
public function userHasLocationTags() {
$this->hasMany('App\UserHasLocationTags', 'user_id');
}
// class UserHasLocationTags
public function locationTags() {
$this->hasMany('App\LocationTags', 'location_tag_id');
}
And you would eager load all the results like this.
$user = User::where('id', 1)->with('userHasLocationTags.locationTags')->first();
The code above produces in 3 queries. One to get the User, one to get all the UserHasLocationTags and a one to get all the LocationTags. This may seem wasteful on first blush but consider the following.
$users = User::take(100)->with('userHasLocationTags.locationTags')->get();
Again, this is only 3 queries but now you have loaded 100 users with all their location tags.
But I can see you are a man with an eye for efficiency, and loading all the intermediate relationships and the whole nested hierarchy probably doesn't sit well with you. Well good news! Laravel 5 has added another relationship type for just this situation. hasManyThrough (scroll down a bit to find it).
Has Many Through
The "has many through" relation provides a convenient short-cut for accessing distant relations via an intermediate relation. For example, a Country model might have many Post through a User model.
So in your case it may look something like this...
// class User
public function locationTags()
{
return $this->hasManyThrough('App\LocationTags', 'App\UserHasLocationTags');
}
$users = User::take(100)->with('locationTags')->get();
So now we are down to two queries. If you feel the need to optimize this further and only select specific columns, you can modify the eager load.
$users = User::take(100)->with(['locationTags' => function ($query)
{
$query->select('user_id', 'name', 'location_tag_id');
})->get();
And if you do that frequently, you should wrap it up in a scope.
I need to update my code to include Media, which is oneToMany unidirectional mapped in Object.php Entity. Ideally I need my code to return all objects even though without media, currently it only returns objects WITH media but it returns multiple results if there are multiple media items.
If you think I refactor the code and use something much simpler, than let me know - I didn't find a way to get the feed using the getRepo() and findBy() functions (no serialization?)
Here's my code:
// Build object QB
$emObject = $this->objectService->getManager();
$qbObject = $emObject->createQueryBuilder();
$qbObject->addSelect(['o.id', 'o.title', 'o.description', 'm as multimedia', 'c.id as category_id', 'c.name as category_name'])
->from('Application\Entity\Cms\Object', 'o')
->leftJoin('Application\Entity\Cms\Media', 'm', 'WITH', '1 = 1')
->leftJoin('o.media', 'om')
->leftJoin('Application\Entity\Cms\Category', 'c', 'WITH', '1 = 1')
->leftJoin('o.category', 'oc')
->andWhere('om.id = m.id')
->andWhere('oc.id = c.id')
->andWhere('o.member = :member')
->setParameter('member', $member);
$objectList = $qbObject->getQuery()->getResult(Query::HYDRATE_ARRAY);
$viewModel->setVariables(['object' => $objectList]);
return $viewModel;
Which returns:
{
"object": [
{
"multimedia": {
"id": 22,
"title": null,
"url": "\/srv\/pois\/cms\/e9049aaac93ce96c81e16340027a804b.png"
},
"id": 34,
"title": "imgTest",
"description": "f",
"category_id": 1,
"category_name": "Chambres"
},
{
"multimedia": {
"id": 23,
"title": null,
"url": "\/srv\/pois\/cms\/ce0c7d669c567369485a01c65197943f.png"
},
"id": 34,
"title": "imgTest",
"description": "f",
"category_id": 1,
"category_name": "Chambres"
}
]
}
However, I need the multimedia objects to be in one array and only return 1 object, like:
{
"object": [
{
"multimedia": {
1: {
"id": 22,
"title": null,
"url": "\/srv\/pois\/cms\/e9049aaac93ce96c81e16340027a804b.png"
},
0: {
"id": 23,
"title": null,
"url": "\/srv\/pois\/cms\/ce0c7d669c567369485a01c65197943f.png"
},
}
"id": 34,
"title": "imgTest",
"description": "f",
"category_id": 1,
"category_name": "Chambres"
}
]
}
I always work with DQL queries without QueryBuilder. I think this is what you want:
$query = $this->entityManager->createQuery(
"SELECT o, m FROM 'Application\Entity\Cms\Object' o JOIN o.multimedia m WHERE o.member = :member"
);
$query->setParameters(array('member' => $member));
$objects = $query->getResult();
I don't think it is more complicated than that.
In QueryBuilder it probably looks like this:
$qb = $this->entityManager->createQueryBuilder();
$qb->select('o', 'm')
->from('Application\Entity\Cms\Object', 'o')
->leftJoin('o.multimedia', 'm')
->where('o.member = :member')
->setParameter('member', $member);
return $qb->getQuery()->getResult();
Please come back with details if this doesn't return what you want. I might be able to help out to get what you want.