Laravel join with sub query - php

I have two models User and Address, one user can have many addresses but I want to fetch only which is primary(where primary=true)
this is what I have tried, and I am getting multiple users in the list
$users = User::join('addresses', 'addresses.user_id', 'users.id')
->select('name','phone_number','address','landmark','city','state','pincode','users.status')
->get();
I tried this too but I am not getting any data
$users = User::join('addresses', 'addresses.user_id', 'users.id')
->where('addresses.primary', true)
->select('name','phone_number','address','landmark','city','state','pincode','users.status')
->get();
thank you
Collection {#375 ▼
#items: array:8 [▼
0 => User {#376 ▶}
1 => User {#377 ▼
#attributes: array:9 [▼
"name" => "Colin Sushanth"
"phone_number" => "9987217545"
"address" => "2nd Cross 3rd street, y this is my address"
"landmark" => "Near the address"
"city" => "Mangalore"
"state" => "Karnataka"
"pincode" => 575002
"status" => "valid"
"primary" => "true"
]
}
2 => User {#378 ▶}
]
}

You should try this:
$users = User::join('addresses', 'addresses.user_id', 'users.id')
->where('addresses.primary','=',1)
->select('name','phone_number','address','landmark','city','state','pincode','users.status')
->get();
Or:
$users = User::join('addresses', 'addresses.user_id', 'users.id')
->where('addresses.primary','=',true)
->select('name','phone_number','address','landmark','city','state','pincode','users.status')
->get();
Updated answer
Blade file:
#if(isset($users))
#foreach($users as $user)
#if($user->primary === 'true')
//Your code
#endif
#endforeach
#endif

I would do it using eloquent models
So you would u do
User::whereHas('primary')->pluck('name','phone_number','address','landmark','city','state','pincode','users.status')
and your model will look like this
public function addresses()
{
return $this->belongsTo('App\Models\Address');
}
public function primary()
{
return $this->addresses->primary == true;
}

Related

Laravel working with nested collection delete nested branch

unable to delete all nested branches where "product" => null
Have a query
$cartWhere['user_id'] = $user_id;
$cartWhere['site_id'] =$currentSite->id;
$item = Cart::select('product_id','quantity')->with(['product' => function($product) use ($search){
$product->join('product_translations', 'products.id', '=', 'product_translations.product_id');
$product->where( 'product_translations.name', 'LIKE','%'.$search.'%');
},'product.manufacturer:id,name'])
->where($cartWhere)->get();
then I receive collection that has all filtered carts but some of these carts have a relation with product => null
1 => App\Models\Cart {#736 ▼
...
#original: array:2 [▼
"product_id" => 1
"quantity" => 2
]
...
#relations: array:1 [▼
"product" => App\Models\Product {#785 ▶}
]
}
2 => App\Models\Cart {#736 ▼
...
#original: array:2 [▼
"product_id" => 2
"quantity" => 2
]
...
#relations: array:1 [▼
"product" => null
]
}
sorry for my English
You can filter them from the results using the collections filter() method
$item = Cart::select('product_id','quantity')
->with(['product' => function($product) use ($search) {
$product->join('product_translations', 'products.id', '=', 'product_translations.product_id');
$product->where( 'product_translations.name', 'LIKE','%'.$search.'%');
}, 'product.manufacturer:id,name'])
->where($cartWhere)
->get()
->filter(function ($cart) {
return $cart->product !== null;
});
Along with with you should use whereHas. So the result will not include any relation with null value. So this way you can also avoid the extra filter method used.

Eloquent request with subitems count

I have 2 tables :
Valuechains : id, created_at, updated_at, deleted_at
Segments : id, valuechain_id (Foreign key), created_at, updated_at, deleted_at
And pivot tables (not really important here).
I have a method with sql requests ...
$valuechains list gives me a list of all the value chains which are not (soft) deleted
$valuechainCount counts the number of valuechains which are published
$segmentCount counts the number of segments for each value chains
I try to use the map function in order to add a column which contains the number of segments for each value chains ...
public function vcListAndSegmentCount() {
$valuechainLists = Valuechain::select('valuechains.id', 'lang_valuechain.vcname', 'lang_valuechain.vcshortname')
->join('lang_valuechain', 'valuechains.id', '=', 'lang_valuechain.valuechain_id')
->join('langs', 'lang_valuechain.lang_id', '=', 'langs.id')
->where('langs.isMainlanguage', '=', '1')
->whereNull('valuechains.deleted_at')
->get();
$valuechainCount = Valuechain::whereNull('valuechains.deleted_at')->count();
for ($i=0; $i < $valuechainCount; $i++) {
$segmentCount[$i] = Segment::whereNull('segments.deleted_at')
->where('valuechain_id', '=', $valuechainLists[$i]->id)->count();
}
$valuechainLists = $valuechainLists->map(function ($record) use ($segmentCount) {
$vclists = array_first($segmentCount, function ($value, $key) use ($record) {
return $value['id'] === $record['valuechain_id'];
});
$record['count'] = $vclists;
return $record;
});
dd($valuechainLists);
}
The map methods adds a column my output collection. Unfortunatelly, the new collection is not giving me the right numbers of segments for each value chain... it only adds one value ...
Here is what I obtain :
Collection {#380 ▼
#items: array:4 [▼
0 => Valuechain {#450 ▼
...
#attributes: array:4 [▼
"id" => 1
"vcname" => "Génétique"
"vcshortname" => "Génétique"
"count" => 6
]
#original: array:3 [▶]
...
}
1 => Valuechain {#451 ▼
...
#attributes: array:4 [▼
"id" => 2
"vcname" => "Biotruc"
"vcshortname" => "Biotruc"
"count" => 6
]
...
}
2 => Valuechain {#452 ▼
...
#attributes: array:4 [▼
"id" => 3
"vcname" => "VC3"
"vcshortname" => "VC3"
"count" => 6
]
...
}
3 => Valuechain {#453 ▼
...
#attributes: array:4 [▼
"id" => 4
"vcname" => "VC4"
"vcshortname" => "VC4"
"count" => 6
]
#original: array:3 [▶]
...
}
]
}
I obtain 6, 6, 6 and 6 whereas the count should be 6, 5, 4, 4...
If you are using Laravel >= 5.2 and if you have defined the relationships on the models, you can use the withCount() method.
It would go something like this:
Valuechain::select('valuechains.id', 'lang_valuechain.vcname', 'lang_valuechain.vcshortname')
->withCount(['segments' => function ($query) {
$query->whereNull('deleted_at);
}])
->join('lang_valuechain', 'valuechains.id', '=', 'lang_valuechain.valuechain_id')
->join('langs', 'lang_valuechain.lang_id', '=', 'langs.id')
->where('langs.isMainlanguage', '=', '1')
->whereNull('valuechains.deleted_at')
->get()
or if your Segment model uses the SoftDeletes trait, then it's a bit simpler:
Valuechain::select('valuechains.id', 'lang_valuechain.vcname', 'lang_valuechain.vcshortname')
->withCount('segments')
->join('lang_valuechain', 'valuechains.id', '=', 'lang_valuechain.valuechain_id')
->join('langs', 'lang_valuechain.lang_id', '=', 'langs.id')
->where('langs.isMainlanguage', '=', '1')
->whereNull('valuechains.deleted_at')
->get()
add count value as a property instead of array element.
$valuechainLists = $valuechainLists->map(function ($record) use ($segmentCount) {
$vclists = array_first($segmentCount, function ($value, $key) use ($record) {
return $value['id'] === $record['valuechain_id'];
});
$record->count = $vclists;
return $record;
});
I changed
$record['count'] = $vclists;
to
$record->count = $vclists;
Add a reference: &$segmentCount
$valuechainLists = $valuechainLists->map(function ($record) use (&$segmentCount) {....
Also I'm not sure what your array_first function is doing.

DB Laravel get and first in same time

I want to show only one result from "links, tags, pages", "->first()", but, I want to show multiple results from "comments", "->get()", separate it in one array, and send to view, how can I do this?
$link = DB::table('links')
->join('tags', 'tags.id', 'links.tag')
->join('pages', 'pages.id', '=', 'links.page_id')
->leftJoin('comments', 'comments.link_id', '=', 'links.id')
->select('links.photo', 'links.id', 'links.description', 'links.country', 'links.url', 'links.suggestions', 'links.shares', 'links.friendly_url', 'links.page_id', 'links.sponsored', 'links.clicks', 'links.title', 'tags.color', 'tags.id as tag_id', 'tags.name', 'pages.name as p_name', 'pages.description as p_description', 'pages.id as p_id', 'pages.followers', 'pages.links', 'pages.friendly_url as p_friendly_url', 'pages.photo as p_photo')
->where('links.friendly_url', $id)
->first();
return view('site.link', compact('link'));
DD($link);
0 => Link {#291 ▼
#relations: array:3 [▼
"page" => Page {#295 ▶}
"tag" => Tag {#289 ▶}
"comments" => Collection {#292 ▼
#items: array:2 [▼
0 => Comment {#299 ▶}
1 => Comment {#301 ▶}
]
}
]
You could use Eloquent. Define relationships:
public function page()
{
return $this->belongsTo(Page::class);
}
public function tag()
{
return $this->belongsTo(Tag::class, 'tag');
}
public function comments()
{
return $this->hasMany(Comment::class);
}
And do this:
Link::with('page', 'tag', 'comments')->where('friendly_url', $id)->first()

Laravel eloquent query with

This query returns all groups with an id however it also returns all the products to every group.
$groups = \App\Group::where('campaign_id', $id)->with('product')->get();
dd($groups->toArray());array:2 [▼
This is the output.
0 => array:6 [▼
"id" => 24
"campaign_id" => "TRE36934"
"group_name" => "group2"
"created_at" => "2017-05-17 16:14:55"
"updated_at" => null
"product" => array:4 [▼
0 => array:8 [▶]
1 => array:8 [▶]
2 => array:8 [▶]
3 => array:8 [▶]
I am trying to return the groups with same id. Can I somehow query? The join in the id in the groups table and the foreign key in call 'group' in the group table.
A simple inner join should suffice here, right?
$groups = \App\Group::join('product', 'group.campaign_id', '=', 'product.group')
->where('group.campaign_id', $id)
->get();
try :
$groups = Group::join('product', 'group.campaign_id', '=', 'product.group')
->where('group.campaign_id', $id)
->get();
If you want to get your product with the same campaing id, you can do the following :
$products = Product::get()->groupBy('campaign_id');
Or you can do it directly from SQL
So, if you want a collection of Product, use your product model :)
I'm not sure but you may try this:
$group = \App\Group::where('campaign_id', $id)->get();
$group->load('products');
Thanks for all your replies they all got me a bit cloer
$products = \App\Product::join('groups', 'groups.id', '=', 'products.group')->get()->groupBy('group');
The basic groupby by Mathieu Ferre got me close. I added a join with a groupby as suggested by Mozammil on the name to give me
$products = \App\Product::join('groups', 'groups.id', '=', 'products.group')->get()->groupBy('group_name');

Laravel MongoDB group by

I'm currently using jenseggers-mongodb eloquent in laravel 5 with mongodb 3.0.3.
I'm trying to join two different tables as follows:
User Model
public function userpayment() {
return $this->hasMany('App\Models\Userpayment', 'user_id', '_id');
}
Userpayment model
public function user() {
return $this->belongsTo('App\Models\User','user_id');
}
I'm using repository pattern
public function __construct() {
$this->model = new User;
}
return $this->model->with(array('userpayment'=>function($query){
$query
->groupBy('dealCodeNumber')
->get();
}))
->where('_id',$sid)
->get();
groupBy dealCodeNumber returns NULL.
array:1 [▼
0 => array:15 [▼
"_id" => "55813f4cbc59a3f1372e9e6f"
"full_name" => "Varathan"
"username" => "shopsyadmin"
"web_url" => ""
"userpayment" => []
]
without groupby returns all.
array:1 [▼
0 => array:15 [▼
"_id" => "55813f4cbc59a3f1372e9e6f"
"full_name" => "Varathan"
"username" => "shopsyadmin"
"userpayment" => array:2 [▼
0 => array:57 [▼
"_id" => "55816ce7cc7d4bac0d000029"
"dealCodeNumber" => "1398410837"
"inserttime" => "1398411401"
"status" => "Pending"
]
1 => array:57 [▶]
]
Querylog with groupby
[query] => shopsy_user_payment.aggregate([{"$match":{"user_id":{"$in":["55813f4cbc59a3f1372e9e6f"]}}},{"$group":{"_id":{"dealCodeNumber":"$dealCodeNumber"}
Why groupby returns null?
To group an column it must be selected before grouping. Changing code to below works:
return $this->model->with(array('userpayment'=>function($query){
$query
->select('product_id','user_id','dealCodeNumber')
->groupBy('dealCodeNumber')
->get();
}))
->where('_id',$sid)
->get();

Categories