Laravel query with joins, same name in multiple tables - php

I have a large query. For all intents and purposes, I'll recreate the issue using a smaller query as an example:
DB::table('cases')
->join('contacts', 'cases.id', '=', 'contacts.id')
->select('cases.name', 'contacts.name')
->get();
And then in laravel's templating (Blade) when I do a foreach loop and print the results, it's printing the results from the cases table for {{ $case->name }}
I understand the problem and why it is happening, but how can I make it work properly?

This is a PDO restriction and has nothing to do with laravel. If you need them both, you'll have to alias it in your query:
DB::table('cases')
->join('contacts', 'cases.id', '=', 'contacts.id')
->selectRaw('cases.name as cases_name, contacts.name as contacts_name')
->get();

Related

Laravel where with 2 tables

I'm trying to check the another table to remove the matches from the results but unable to figure this out.
$value = people::select(array('people.blog_id'))
->join('blocks', 'people.user_id', '=', 'blocks.blocker')
->where('people.user_id', $user->id)
->where('blocks.blocker', '!=', 'people.user_id')
->get()
->toArray();
What I am trying to achieve, is to strip away the results when getting user_id from people where blocker is found as well in the blocks table, but the following returns an empty array.
As per laravel doc
You may use the table method on the DB facade to begin a query. The table method returns a fluent query builder instance for the given table, allowing you to chain more constraints onto the query and then finally get the results using the get method.
Change your query statement like bellow-
$articles = DB::table('people')
->join('blocks', 'people.user_id', '=', 'blocks.blocker')
->where('blocks.blocker', '<>', 'people.user_id')
->select('people.blog_id')
->get();
I think you should use right join here instead of simple join,
You can do it like.
$value = people::select(array('people.blog_id'))
->join('blocks', 'people.user_id', '=', 'blocks.blocker', 'right')
->where('people.user_id', $user->id)
->get()->toArray();
Please notice the fourth parameter in the join statement, this will include only the results where blocks will find.
Hope this will help

Laravel Eloquent join table and count related

I have two tables, categories and product. I'm trying to add a query to count products of each category without foreach of the categories. I reached the query below:
DB::table('categories')->leftJoin('product', 'categories.id', '=','categpry_id')
->selectRaw('categories.*, count(product.id) as Count')
->where('product.status',1)
->groupBy('categories.id')
->get();
But the problem I'm facing is when a category doesn't have products it's not showing. I want to show the categories with no product with 0 product in the array.
You can use Eloquent's withCount method:
$categories = Category::withCount('products')->get();
Each $category will have a products_count attribute.
I'm pretty sure you can use rightJoin for this.
Not 100% sure though.
The first line in your code is bad in a few ways
'categories.id', '=','categpry_id')
You have a typo
Add the table also 'categories.id', '=', 'products.category_id'
If you're using models, which you should be... #DigitalDrifter has an "Eloquent" solution.
Two asides
I would refrain from using mysql reserved words in your aliases. COUNT(product.id) AS product_count instead.
You can minimize your raw statement with an array passed to select instead.
Here is what I would use
Categories::leftJoin(Product::class, 'product.category_id', '=', 'categories.id')
->select([
'categories.*',
DB::raw('COUNT(products.id) AS product_count')
])
->where('product.status', 1)
->groupBy('categories.id')
->get();
TIL.
Model::withCount('relation') that is pretty darn cool too.

Laravel: WhereNull, OrWhere, is ignoring WhereRaw

In my controller I am using Laravels WhereNull, OrWhere and WhereRaw in DB Query. It is pulling in all the results but the problem is it looks like it is pulling in everything and ignoring the last Where clause. I have used this in a different method on other controllers and it works fine. Is there a specific order or something I am missing?
Doesn't Work (Ignores WhereRaw and shows all results)
$lists = DB::table('statuses')
->whereNull('company_id')
->orWhere('company_id', '=', Auth::user()->company_id)
->whereRaw("FIND_IN_SET('Task',assigned_to)")
->get();
This works in other controllers used as a different method without the whereRaw:
return Status::whereNull('company_id')->orWhere('company_id', '=', Auth::user()->company_id)
->orderBy('created_at', 'asc')
->get();
Sample DB
Source link: https://laravel.com/docs/5.3/queries#where-clauses
Use DB::raw instead of whereRaw
->where(DB::raw("FIND_IN_SET('Task',assigned_to)"))

Laravel 4 unable to join on multiple conditions using ->on( ) more than once

In a nutshell I am trying to do a join with more than one condition. We are using legacy Laravel 4, and the actual class I've tracked it to is Illuminate\Database\Query\Builder. Here is what I am adding:
->leftJoin('node_fields AS visible_for_categories', function($join){
$join->on('nv2.id', '=', 'visible_for_categories.node_version_id');
$join->on('visible_for_categories.name', '=', 'visible_for_categories');
})
It works fine with the first $join->on( ) call, but the page fails if the second on is called. why is this and what is the proper way to do this in Laravel 4?
The way that worked for me on the above query is as follows:
->leftJoin('node_fields AS visible_for_categories', function($join){
$join->on('nv2.id', '=', 'visible_for_categories.node_version_id');
$join->on('visible_for_categories.name', '=', DB::raw("'visible_for_categories'"));
})
The query builder will assume all three values in the on() function are fields, not strings, and will parse out the . period as well.
The general assumption is that JOINS will have the relational field joins to create structure, and the WHERE conditionals will provide the desired filter. However anyone who's worked esp. with LEFT or RIGHT joins knows this is not always possible.
Be careful for SQL injection using DB::raw but in this case, an EAV table, we're dealing with a fixed string, not a variable.
Try
->leftJoin('node_fields AS visible_for_categories', function($join){
$join->on('nv2.id', '=', 'visible_for_categories.node_version_id')
->on('visible_for_categories.name', '=', 'visible_for_categories');
})

Only get the first row while doing a leftjoin

Is it possible to limit the result while doing a leftjoin?
(Laravel 4.2) - Querybuilder
I've got the following query with laravel's querybuilder:
DB::table('part')
->leftjoin('model', 'model.model_id', '=', 'part.model_id')
->leftjoin('make', 'model.make_id', '=', 'make.make_id')
->leftJoin('photo', 'photo.part_id', '=', 'part.part_id')
->select( 'part.part_id',
'part.model_id',
'make.desc as make_desc',
'model.desc as model_desc',
'photo.local as local_img',
'photo.cdn as cdn_img')
->take(8)->get();
Every part has more then 4 photos, but i only want the first photo to be included in the join. The problem is that when i use this query, i get 8 part objects (results). But the 8 results are not 8 parts, but 2 parts. This query creates 4 of the same part objects, with the only difference being the photo (the join includes every photo).
I tried things like:
->select( '(photo.local LIMIT 1) as local_img',
'(photo.cdn LIMIT 1) as cdn_img')
But this doesn't work. I also tried to do raw query's. Also i tried to use the '->take(1)' in a leftjoin closure, like this:
->leftjoin('photo', function($q){
$q->on('photo', 'photo.part_id', '=', 'part.part_id')->take(1);
});
But this is not possible.
I`m searching for a solution to only include the first photo row in a leftjoin.
Edit: Following up on mgrueter's answer. I know that a groupby would do the trick, but this makes the query very slow. So i want to do it in a different way so the query doesn't get to slow.
Group the results by 'part.id':
DB::table('part')
->leftjoin('model', 'model.model_id', '=', 'part.model_id')
->leftjoin('make', 'model.make_id', '=', 'make.make_id')
->leftJoin('photo', 'photo.part_id', '=', 'part.part_id')
->select( 'part.part_id',
'part.model_id',
'make.desc as make_desc',
'model.desc as model_desc',
'photo.local as local_img',
'photo.cdn as cdn_img')
->group_by('part.part_id')
->take(8)->get();
And also order the results by 'photo.created' or whatever column you have to determine, which is the first photo.

Categories