Select * from a pivot table in laravel - php

I have a many to many relation with table users,items and the pivot table user_item and i need to call the query : Select * from user_item where user_id=$user->id in laravel and return the results in json format. I try with
$user=User::find(session('user_id'))->items()->get();
return response ()->json($user);
But it doesn't work. How can I do that?
class User extends Authenticatable {
public function items (){
return $this->belongsToMany ("App\Models\Item", "user_item", "user", "item");
}
}
class Item extends Models {
public function users (){
return $this->belongsToMany ("App\Models\User", "user_item", "item", "user");
}
}

You can define columns in your pivote table using withpivot method
public function items (){
return $this->belongsToMany ("App\Models\Item", "user_item",
"user", "item")->withPivot(['column1', 'column2','another_column']);
}
to get relation instead of using get(), you should use like below:
$user=User::find(session('user_id'))->items;
return response ()->json($user);
above will give below json result:
[{
"id": 4,
"name": "PC",
"pivot": {
"column1": 1,
"column2": 4,
"another_column": "2016-03-03"
}
},
{
"id": 5,
"name": "Phone",
"pivot": {
"column1": 1,
"column2": 4,
"another_column": "2016-03-03"
}
}]
you can also include pivot in use user model using with():
$user=User::with('items')->find(session('user_id'));
return response ()->json($user);
give json result something like:
{
"id": 1,
"name": "User Name",
"email": "email#user.com",
"created_at": null,
"updated_at": null,
"items": [{
"id": 4,
"name": "PC",
"pivot": {
"column1": 1,
"column2": 4,
"another_column": "2016-03-03"
}
},
{
"id": 5,
"name": "Phone",
"pivot": {
"column1": 1,
"column2": 4,
"another_column": "2016-03-03"
}
}]
}]

Related

Eloquent Model relationship does not return sub-relationship specific column value

I have attempted to achieve to pull the user's info and the product details (Which specified the nickname and name) when the product name equal to "Oops" but I have no idea why the getProducts does not return any things.
User Model
public function getProducts(){
return $this->hasMany('App\Models\Product','users_id');
}
Product Model
public function users(){
return $this->belongsTo(User::class);
}
The code of pulling data:
$products = User::with(['getProducts' => function($query){
$query->select("users_id","name","nickname");
}])->get();
The current output:
"data": [
{
"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,
"get_products": [
]
},
{
"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,
"get_products": [
{
"nickname":"MCD",
"name":"Oops"
},
{
"nickname":"Mary Brown",
"name":"Oops"
},
{
"nickname":"Kentucy",
"name":"KFC"
},
{
"nickname":"Texas Chicken",
"name":"TXS"
}
]
}
]
The expected output
"data": [
{
"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,
"get_products": [
]
},
{
"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,
"get_products": [
{
"nickname":"MCD",
"name":"Oops"
},
{
"nickname":"Mary Brown",
"name":"Oops"
}
]
}
]
getProducts is not a good name for the relationship, lets simply call it products.
public function products()
{
return $this->hasMany('App\Models\Product','users_id');
}
Your code in the comment doesn't work because you specify the where clause in the main query, not the sub query.
return User::with(['products' => function ($query) {
$query->select("users_id","name","nickname");
}])
// This got to be in the sub query.
->where("products.name","Oops")
->get();
So let's update your code to this:
$productName = 'Oops';
return User::with(['products' => function ($query) use ($productName) {
$query->select("users_id","name","nickname", "price")
->where("name","LIKE", "%{$productName}%");
}])
->get();
I have seen your comment to this answer. Let's define a total custom attribute for the User model:
class User extends Model
{
protected $appends = ['total'];
public function getTotalAttribute()
{
// This is higher order message, if you haven't used it: https://laravel.com/docs/8.x/collections#higher-order-messages
return $this->products->sum->price;
}
}
Then the total attribute will be part of any user.

Laravel return json with eloquent collection relationship values

I have the following function inside the UsersApiController class :-
public function getKhatmas()
{
$user = Auth::user();
$khatmas = $user->khatmas;
return response()->json($khatmas);
}
The above code give the following response :-
[
{
"id": 3,
"hash": "5ec72b4913d1a",
"type": 2,
"type_text": "sample text",
"division": 2,
"division_variant": 1,
"status": "active",
"expiry_date": null,
"is_name": 0,
"user_id": 2,
},
{
"id": 4,
"hash": "5ec72b7005126",
"type": 2,
"type_text": "sample text",
"division": 2,
"division_variant": 1,
"status": "active",
"expiry_date": null,
"is_name": 0,
"user_id": 2,
},
]
Relationship function in User Model file :-
public function khatmas()
{
return $this->hasMany('App\Khatma');
}
App\Khatma file content :-
public function type()
{
return $this->belongsTo('App\KhatmaType');
}
In above json response , ("type": 2) is the foreign key of App\KhatmaType Model .
I want instead of json response with the foreign key of KhatmaType Model, i want it to return the column "title" from App\KhatmaType to be like this :-
{
"id": 3,
"hash": "5ec72b4913d1a",
"type": "this is title from App\KhatmaType Model",
"type_text": "sample text",
"division": 2,
"division_variant": 1,
"status": "active",
"expiry_date": null,
"is_name": 0,
"user_id": 2,
}
`I tried with the following :-
$khatmas = $user->khatmas->with('type');
But it return error : Method Illuminate\Database\Eloquent\Collection::with does not exist
Fixed by using the following query builder:-
public function getKhatmas()
{
$user = Auth::user();
$khatmas = Auth::user()->khatmas()
->select('hash','type_text','status','expiry_date','type_id')
->with('type')->get();
return response()->json($khatmas);
}

Laravel pass parameter to its distant relationship (translate children)

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.

Laravel model belongs to current user and global user

I have the following collections:
User
{
"id": 1,
"name": "Bob"
},
{
"id": 2,
"name": "Mary"
}
Stuff
{
"id": 1,
"user_id": 1,
"name": "Bob's stuff"
},
{
"id": 2,
"user_id": 2,
"name": "Mary's stuff"
},
{
"id": 3,
"user_id": 0,
"name": "Everyone's stuff"
},
{
"id": 4,
"user_id": null,
"name": "Global stuff"
}
... and the following models:
class User extends Eloquent {
public function stuff() {
return $this -> hasMany( 'Stuff' ) ;
}
}
class Stuff extends Eloquent {
public function user() {
return $this -> belongsTo( 'User' ) ;
}
}
How to I automatically add Everyone's stuff ( User.id == 0 ) and Global stuff ( User.id == null ) to everybody's model? In other words, if I was querying for Bob's stuff I wish to get the following:
{
"id": 1,
"user_id": 1,
"name": "Bob's stuff"
},
{
"id": 3,
"user_id": 0,
"name": "Everyone's stuff"
},
{
"id": 4,
"user_id": null,
"name": "Global stuff"
}
You can use this:
public function stuff() {
return $this->hasMany(Stuff::class)->orWhere('user_id', 0)->orWhereNull('user_id');
}
A disadvantage is that you can't just add other WHERE clauses:
$user->stuff()->where('foo', 'bar')->get(); // Doesn't work as expected.
As a consequence, eager loading doesn't work.

How to select specific fields from nested relations in Eloquent

I have the following query in Eloquent:
public function firstSubsectionIdsOnly()
{
return $this->model->with(['sections' => function ($q) {
$q->with(['subsections' => function ($q2) {
$q2->first();
}
])->first();
}])->whereHas('sections.subsections')->first();
}
This returns something like this:
{
"id": 1,
"name": "Training exercise",
"entry": "<p>sss</p>",
"created_at": "2018-04-20 09:38:36",
"updated_at": "2018-04-20 10:08:27",
"sections": [
{
"id": 1,
"name": "Section 1 Training",
"parent": null,
"position": 1,
"created_at": "2018-05-04 09:37:23",
"updated_at": "2018-05-04 09:37:23",
"pivot": {
"training_exercise_id": 1,
"section_id": 1
},
"subsections": [
{
"id": 2,
"name": "Subsection 1 training",
"parent": 1,
"created_at": "2018-05-04 09:54:09",
"updated_at": "2018-05-04 09:54:09"
}
]
}
]
}
I would like for it to only select the id fields for each relation so it should return something like this:
{
"id": 1,
"name": "Training exercise",
"entry": "<p>sss</p>",
"created_at": "2018-04-20 09:38:36",
"updated_at": "2018-04-20 10:08:27",
"sections": [
{
"id": 1,
"subsections": [
{
"id": 2,
}
]
}
]
}
I have tried adding $q->select('id'); to the subsections nested closure but that returns an empty subsections array.
Any idea on how I can achieve this? I am using Laravel 5.6
As others have stated before, you need to include the foreign key in the values you select. Let's say we have two models. Parent and Child. This is the bare minimum you have to select.
App\Parent::select('id')->with(['children' => function ($query) {
$query->select('id', 'parent_id');
}])->get();
It nets you something like
Illuminate\Database\Eloquent\Collection {
all: [
App\Parent {
id: 1,
children: Illuminate\Database\Eloquent\Collection {
all: [
App\Child {
id: 109,
parent_id: 1,
},
App\Child {
id: 153,
parent_id: 1,
},
],
},
},
],
}
If you're trying to go for the inverse, you still need the foreign key, like so
App\Child::select('id', 'parent_id')->with('parent' => function ($query) {
$query->select('id');
}])->get();
This nets you
Illuminate\Database\Eloquent\Collection {
all: [
App\Child {
id: 1,
parent_id: 58,
parent: App\Parent {
id: 58,
},
},
],
}
I'm using select() instead of get() for legibility on the queries but you must use select() for the subqueries.
If you use with('relation') => function ($query) { $query->get(['id']); } you'll get the whole object.
You have to include the foreign key columns. For the subsections relationship:
$q2->select('id', 'parent');

Categories