Controller:
$files = File::where('agent_id', $user->id)->with('posts')->get();
Model:
public function posts()
{
return $this->hasManyThrough('App\User', 'App\Post', 'id', 'id', 'post_id', 'user_id');
}
So this return a bunch of data, for example:
{
"success": [
{
"id": 2,
"post_id": 1,
"transaction_id": 4,
"agent_id": 2,
"status": 0,
"posts": [
{
"id": 1,
"name": "john",
"email": "john#gmail.com",
"phone": "489797878",
"type": "1",
"verified": 1,
"otp": null,
"created_at": "2019-11-23 10:17:31",
"updated_at": "2019-11-23 10:17:51",
"api_token": null,
"laravel_through_key": 1
}
]
}
...
}
What I want is, exclude some data, like email or verified and etc. I tried pluck('email') and also makeHidden but no success. any idea how can I do this?
How about doing some thing like below, ( haven't tested the code but should give you a clue )
files = File::where('agent_id', $user->id)
->with(['posts' => function ($q) {
$q->select('name','phone'); // specify whatever you want
}])->get(['column1','column2']);
Just use ->get() include list of those you want to get:
example:
$files = File::where('agent_id', $user->id)->with('posts')->get(['post_id', 'status']);
Related
I have tables with below relationship
And my HousingAdvertisement model has
public function nearPlaces()
{
return $this->hasMany(HousingAdNearPlace::class);
}
and HousingAdNearPlace
public function nearPlace()
{
return $this->hasOne(NearPlace::class, 'id');
}
when I make query like this:
HousingAdvertisement::with('nearPlaces.nearPlace')->where('user_id', '=', auth()->user()->id)->get();
I got HousingAdNearPlace object in HousingAdvertisement model:
[...
{
...,
"near_places": [
{
"id": 27,
"housing_advertisement_id": 48,
"near_place_id": 3,
"created_at": "2021-06-29T12:23:35.000000Z",
"updated_at": "2021-06-29T12:23:35.000000Z",
"near_place": null
},
{
"id": 28,
"housing_advertisement_id": 48,
"near_place_id": 4,
"created_at": "2021-06-29T12:23:35.000000Z",
"updated_at": "2021-06-29T12:23:35.000000Z",
"near_place": null
}
]
...]
How can I got self NearPlace model like this:
[...
{
...,
"near_places": [
{
"id": 3,
"name": "Park",
"slug": "park",
"created_at": "2021-06-29T06:25:57.000000Z",
"updated_at": "2021-06-29T06:25:57.000000Z"
},
{
"id": 4,
"name": "Beach",
"slug": "beach",
"created_at": "2021-06-29T06:25:57.000000Z",
"updated_at": "2021-06-29T06:25:57.000000Z"
}
]
...]
You need "Has Many Through" relationship on HousingAdvertisement
public function nearPlaces()
{
return $this->hasManyThrough(NearPlace::class, HousingAdNearPlace::class);
}
And also define id keys as in ducumentation: https://laravel.com/docs/8.x/eloquent-relationships#has-many-through-key-conventions
You need to use laravel Model Accessor for generating slug from HousingAdvertisement's name row.
For that use -
public function slug()
{
return Str::lower($this->name);
}
This will make a slug from name attribute. Add it on your HousingAdvertisement model. Now you need to cast it with query builder.
For that use -
protected $casts = [
'slug' => 'string',
];
Add this on your HousingAdvertisement model. Finally you can query your database like -
HousingAdvertisement::find(auth()->user()->id)->get(['id', 'name', 'slug', 'created_at', 'updated_at']);
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.
I have this Controller :
public function user_predects()
{
$matches=Match::with('Predect')->get();
return ($matches);
}
and it is get json data like this :
[
{
"id": 1,
"m_date": "2021-02-06 22:00:00",
"home": "Turkey",
"away": "Italy",
"h_goals": 0,
"a_goals": 0,
"predect": [
{
"id": 3,
"user_id": 10,
"match_id": 1,
"h_predect": 1,
"a_predect": 1,
"player_id": 1,
"point": 0,
"created_at": null,
"updated_at": null
},
{
"id": 4,
"user_id": 9,
"match_id": 1,
"h_predect": 2,
"a_predect": 1,
"player_id": 1,
"point": 0,
"created_at": null,
"updated_at": null
Now I want to view same json data but just for one user ,I used this but don't works :
public function user_predects($username)
{
$user = User::where('username',$username)->get()
$matches=Match::with('Predect')->where('Predect.user_id',$user[0]->id)->get();
return ($matches);
}
How can I view matches model with predect model for one user?
Try this one:
public function user_predects($username)
{
$user = User::where('username',$username)->first()
$matches = Match::with(['Predect' => function($query) use ($user) {
return $query->where('Predect.user_id', $user->id);
}])->get();
return ($matches);
}
You can also read about constraining Eager Loading from the official documentation: Constraining Eager Loads
I have this data in method of controller as you see I deleted some keys in method:
$foods = Food::get()->map(function($value){
return collect($value->toArray())->except('pivot', 'deleted_at', 'created_at', 'updated_at');
});
return HttpHelpers::sendJsonData($foods, 200);
and the api response returns this:
{
"success": true,
"data": [
{
"id": 1,
"title": "food1",
"default_price": 2353465456,
"main_meal": 1,
"labels": [
{
"id": 1,
"title": "type1",
"type": "food",
"created_at": "2018-08-23 03:55:33",
"updated_at": "2018-08-23 03:55:33",
"pivot": {
"labelable_id": 1,
"label_id": 1,
"labelable_type": "App\\Models\\Panel\\Food"
}
}
]
},
{
"id": 2,
"title": "food2",
"default_price": 1000,
"main_meal": 0,
"labels": [
{
"id": 1,
"title": "type2",
"type": "food",
"created_at": "2018-08-23 03:55:33",
"updated_at": "2018-08-23 03:55:33",
"pivot": {
"labelable_id": 2,
"label_id": 1,
"labelable_type": "App\\Models\\Panel\\Food"
}
}
]
}
]
}
now my problem is that I do not want to return some keys, like labalable_id and labelable_type in pivot and created_at in labels, please offer me the best way
You can use the makeHidden method for hiding data to JSON. Haven't tried this code but, i think it should work.
https://laravel.com/docs/5.6/eloquent-serialization#hiding-attributes-from-json
$foods = Food::get()->map(function($value){
foreach($value->labels as $label){
$label = $label->makeHidden(['created_at']);
$label->pivot = $label->pivot->makeHidden(['labelable_id', 'labelable_type']);
}
return collect($value->toArray())->except('pivot', 'deleted_at', 'created_at', 'updated_at');
});
If the data response is coming through the stored procedure then in that case you need to store the Pivot table data in a temporary table and select the required keys that you require and display it through API in json.
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');