Laravel: Count through two Models - php

I have three tables, settlements table hasMany add_members table and ciphers table hasMany add_members table. In Settlement and Cipher Model I put function:
public function members()
{
return $this->hasMany('App\AddMember');
}
so now, when I need count how many rows in add_members table I have but with reon_id in settlements table I did like this:
$first_count = Settlement::where('town_id', Auth::user()->town_id)
->with('members')
->where('reon_id', '1')
->count();
and that working, but now I need second count which also counting add_members rows with reon_id == 1 in settlements table but woth one more relationships where cipher == 0 in ciphers table. If I do with belongsTo relationship through AddMember Model I'm getting error:
(2/2) QueryException
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'reon_id' in 'where clause'
$second_count = Settlement::where('town_id', Auth::user()->town_id)
->with('members')
->where('reon_id', '1')
->Cipher::with('members')
->where('cipher', '0')
->count();
I know that this second is wrong but I don't know hot to get with reon_id == 1 in Settlement model and cipher == 0 in Cipher model...

Laravel relation table query
$first_count = Settlement::where('town_id', Auth::user()->town_id)
->with(['members', function ($q) {
$q->where('reon_id', 1);
}])->get();
or
$first_count = Settlement::with('members')->where('town_id', Auth::user()->town_id)
->whereHas('members', function ($q) {
$q->where('reon_id', 1);
})->get();

Have you tried it this way, so eloquent know which column is in which table?
$users = App\User::with(['posts' => function ($query) {
$query->where('title', 'like', '%first%');
}])->get();
Or type additional Info about columns like this:
App\Book::with('author:id,name')->get();
More in laravel docs

Related

Laravel WithSum / WithCount Relationships not bringing results

I am trying to make a query using Laravel eloquent but at the moment I have not had good results.
My query is about the scope of relationships in Laravel. We have two tables:
table 1 : orders
table 2 : products in orders (depends on table 1)
We have a relationship in the model.
public function products()
{
return $this->hasMany(OrderProduct::class);
}
OrderProduct (detail of products in orders) has the following fields:
id
order_id
product_id
qty
line_total
What we are trying to achieve is a query that returns the sum of line_total when the product_id is 139.
We tried the following options without success in the controller:
$orderspaid = Order::with('products')
->where('customer_id', '=', Auth::id())
->where('status', '=', 'completed')
->withSum ('products','line_total')
->where('product_id', '=', '139')
->get();
Error: Column not found: 1054 Unknown column 'product_id'
$orderspaid = Order::withCount(['products as orderproducts' => function($query) {
$query->where('orderproducts.product_id', '=', 139)
->select(DB::raw('sum(line_total)'));
}])->get();
But with no success.
My main question is, it is possible to use sum(line_total) or withSum('products','line_total') to directly sum the amount of money that a particular product_id have?.
Additional Info: Tinker information displaying the relationship between orders and orderproducts.
You can try this one. I don't have those tables ready to test so I could be wrong
So basicly, the method being tried is that products with wanted id will be preloaded, in this case, it's 139. When withSum is called on products table, it will use eagerly products that have been specified beforehand.
$product_id = 139;
$orderspaid = Order::with(['products' => function ($query) use ($product_id) {
$query->where(`products.id`, $product_id);
}])
->where('customer_id', '=', Auth::id())
->where('status', '=', 'completed')
->withSum('products', 'line_total')
->get();
dd($orderspaid);
Tell me if that works for you.

How to Join two different tables in Laravel

QueryException in Connection.php line 729:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'site_name' in
'where clause' (SQL: select email_date, url, recipient from
report_list where site_name = mywebsite)
$records = DB::table('report_list')
->select('email_date','url','recipient')
->where('site_name',$site_name)
->get();
return records;
return view('monthlyReport')
->with('records',$records)
->with('site_name',$site_name);
My site_name was on different table and I don't know if I need to put Join or Make a model for this two.
Can someone help me with this query?
First of all You need to add column named "site_name" to your "report_list" table in database.
this query is for you to join 2 tables (here I took example "users" table as second table If your second table is defferent use your) ->
$records = DB::table('report_list')
->join('users', 'report_list.user_id', '=', 'users.id')
->where('report_list.site_name', '=', $site_name);
->select('users.*', 'report_list.email_date','report_list.url','report_list.recipient')
->get();
return view('monthlyReport')
->with(['records' => $records , 'site_name' => $site_name ]);
If you show the tables to see the columns and table names could help you better, while these are some examples:
//Option 1
$results = DB::table('users')
->join('business', 'users.id', '=', 'business.user_id')
->select('users.*', 'business.name', 'business.telephone', 'business.address')
->get();
//Option 2
$results = User::join("business as b","users.id","=","business.user_id")
->select(DB::raw("users.*"), "b.name as business_name", "b.telephone as business_telephone", "b.address as business_address")
->get();
The laravel docs: https://laravel.com/docs/5.6/queries#joins
You should create a model for your other table which I assume it's Site then in the report_list model create a relation method like :
public function sites(){
return $this->hasOne(Site::class);
}
or:
public function sites(){
return $this->hasOne('App\Models\Site);
}
After that in your eloquent query use this :
$records = DB::table('report_list')
->select('email_date','url','recipient')
->whereHas('sites', function($query){
$query->where('site_name',$site_name);
})
->with('sites')
->get();

Eloquent doesn't call table

Im trying to filter results by name of a relationship
$questions = Question::whereHas('category', function ($q) use ($coh) {
$q->where('id', $coh->id);
})->get();
And i'm gettign the following error:
SQLSTATE[42S22]: Column not found: 1054 Unknown column
'questions.question_category_id' in 'where clause' (SQL: select * from
question_categories where questions.question_category_id =
question_categories.id and question_categories.id = 1 limit 1)
Reading the error is obvious why it isn't working, is because eloquent or me are not calling the question table, shouldn't it called it automatically because i'm putting Question::??
Just go to your Question model and the following line in your category()
class Question extends Model{
public function category(){
return $this->hasMany('App\Category', 'category_id');
}
}
Then try to hit the query
$questions = Question::whereHas('category', function ($q) use ($coh) {
$q->where('id', $coh->id);
})->get();
If I understood correctly, the relationship should be that a Question belongsTo category and a Category hasMany questions.
So in order to filter you could do it different ways depending on the attributes of your table.
If you want to do it with Questions, since you have the category_id as a Foreing Key you could do something like this(assuming your foreing key field is named = 'question_category_id'):
$questions = Question::("question_category_id", "=", $coh);
As someone mentioned you could also use the Category Model to access all questions belonging to that Category since you should have defined in your Category Model that each category hasMany Questions.

Laravel Eloquent and Mysql join a table IF another join is null

Three main tables:
products
advertisers
locations
Two pivot tables:
advertisers_locations
products_locations
Relationships:
A product belongs to an advertiser and an advertiser has many locations (Locations it can ship products to)
A product can also have it own set of locations that override the advertiser locations (Some products have delivery restrictions)
What I need to do is:
Select all products
Check if products_locations table for product ID and join it.
If it does not exist then join the advertisers locations table
Is this possible to do in one query and using eloquent? Here's my code - struggling with the conditional:
public function scopeWhereShippableToLocation($query)
{
$location_id = session('location_id');
$query->where(function ($q) use ($location_id) {
$q->join('products_locations', 'products_locations.product_id', '=', 'products.id')
->where('products_locations.location_id', '=', $location_id);
});
$query->orWhere(function ($q) use ($location_id) {
$q->join('advertisers_locations', 'advertisers_locations.advertiser_id', '=', 'products.advertiser_id')
->where('advertisers_locations.location_id', '=', $location_id);
});
//dd($q->toSql());
return $query;
}
This is currently producing a MySQL error:
Column not found: 1054 Unknown column 'products_locations.location_id' in 'where clause' (SQL: select `products`.*,
I think I have a solution for you using eloquent, rather than the query builder. You need to check to see if the relationship exists, if not you need another query. This can be done using the following:
public function scopeWhereShippableToLocation($query)
{
$location_id = session('location_id');
// WhereHas check to see if a relationship exists, IE: The pivot table
// orWhereHas will be checked if the first where does not exist
$query->whereHas('products_locations', function ($q) use ($location_id) {
$q->where('location_id', $location_id);
})->orWhereHas('advertisers_locations', function ($q) use ($location_id) {
$q->where('location_id', $location_id);
});
return $query;
}
This should work providing that your Products, Advertisers and Locations relationship methods are set up.

Laravel Eloquent - Query builder cant find column with having function

I have a pivot table 'game_genre'(with game_id and genre_id). The game and genre model has a belongsToMany relationship similar to example below.
I have been attempting to gather the games which contain both genre_id of 60 and 55 together. I have been getting the correct result using the following SQL query, but when using the following query builder I end up getting a column not found error when using the having() function.
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'genre_id' in 'having clause'
Im not sure how else to structure the query builder?
MODEL:
class Game extends Model
{
public function genres()
{
return $this->belongsToMany('App\Genre');
}
}
SQL:
SELECT *
FROM game_genre
WHERE genre_id = 55 OR genre_id = 60
GROUP BY game_id
HAVING COUNT(DISTINCT genre_id) = 2;
CONTROLLER:
$game = Game::whereHas('genres', function ($query)
{
$query->where('genre_id', '55')
->orWhere('genre_id', '60')
->groupBy('game_id')
->having('genre_id','=', 2);
})->get();
You forgot the aggregate function (in this case COUNT) in your HAVING condition:
$query->where('genre_id', '55')
->orWhere('genre_id', '60')
->groupBy('game_id')
->havingRaw('COUNT(DISTINCT genre_id) = 2');
Instead of adding several where() and orWhere() to your query, you could also use whereIn() which takes an array:
$myArray = [55,60];
$query->whereIn('genre_id', $myArray)
->groupBy('game_id')
->havingRaw('COUNT(DISTINCT genre_id) = 2');
You can use the following query to get the Games which contain both genre_id of 60 and 55:
$games = Game::whereHas('genres', function ($query) {
$query->where('genre_id', '55');
})
->whereHas('genres', function ($query) {
$query->where('genre_id', '60');
})
->get();

Categories