I am trying to use eloquent's with query within a join query to attach the relationships of the table I am joining with however I am faced with the error "Call to undefined method Illuminate\Database\Query\JoinClause::with()"
Hence, how can I use the different with query to attach the relationship data that I need to my target table that I am joining with? (Manual tickets table)
$manual_tickets = ManualTicketLog::select('*')
->where('manual_ticket_logs.user_id','=',$user->id)
->where(function ($checkStatus) {
$checkStatus->where('manual_ticket_logs.status','=','Created')
->orWhere('manual_ticket_logs.status','=','Started');
})
->whereIn('manual_ticket_logs.id', function($q){
$q->select(DB::raw('MAX(id) FROM manual_ticket_logs WHERE (manual_ticket_logs.status != "ClockedOutUser" and manual_ticket_logs.status != "ClockedOutSupervisor" and manual_ticket_logs.status != "AssignByLocation" and manual_ticket_logs.status != "Queued") GROUP BY manual_ticket_logs.manual_ticket_id'));
})
->join('manual_tickets', function ($join) {
$join->on('manual_ticket_logs.manual_ticket_id', '=', 'manual_tickets.id')
->where('manual_tickets.hidden','=',null)
->with('prior_rerouted_ticket');
})
->select('manual_tickets.*', 'manual_ticket_logs.id as manual_ticket_logs_id')
->get();
Portion of code that results in error
->with('prior_rerouted_ticket');
$manual_tickets = ManualTicketLog::select('*')
->where('manual_ticket_logs.user_id', '=', $user->id)
->where(function ($checkStatus) {
$checkStatus->where('manual_ticket_logs.status', '=', 'Created')
->orWhere('manual_ticket_logs.status', '=', 'Started');
})
->whereIn('manual_ticket_logs.id', function ($q) {
$q->select(DB::raw('MAX(id) FROM manual_ticket_logs WHERE (manual_ticket_logs.status != "ClockedOutUser" and manual_ticket_logs.status != "ClockedOutSupervisor" and manual_ticket_logs.status != "AssignByLocation" and manual_ticket_logs.status != "Queued") GROUP BY manual_ticket_logs.manual_ticket_id'));
})
->join('manual_tickets', function ($join) {
$join->on('manual_ticket_logs.manual_ticket_id', '=', 'manual_tickets.id')
->where('manual_tickets.hidden', '=', null);
})
->with('manual_tickets.prior_rerouted_ticket')
->select('manual_tickets.*', 'manual_ticket_logs.id as manual_ticket_logs_id')
->get();
Move relations from join.
Issue has been resolved by restructuring the query. Instead of querying from the manual ticket logs table and then joining it to the manual tickets table whilst trying to find a way to attach the relationship to the manual tickets table, I queried from the manual tickets table first and attached it's relationship before joining it to the manual ticket logs table
$manual_tickets = ManualTicket::select('*')
->where('manual_tickets.hidden','=',null)
->where('manual_tickets.user_id','=',$user->id)
->join('manual_ticket_logs', function ($join) use($user) {
$join->on('manual_ticket_logs.manual_ticket_id', '=', 'manual_tickets.id')
->where('manual_ticket_logs.user_id','=',$user->id)
->where(function ($checkStatus) {
$checkStatus->where('manual_ticket_logs.status','=','Created')
->orWhere('manual_ticket_logs.status','=','Started');
})
->whereIn('manual_ticket_logs.id', function($q){
$q->select(DB::raw('MAX(id) FROM manual_ticket_logs WHERE (manual_ticket_logs.status != "ClockedOutUser" and manual_ticket_logs.status != "ClockedOutSupervisor" and manual_ticket_logs.status != "AssignByLocation" and manual_ticket_logs.status != "Queued") GROUP BY manual_ticket_logs.manual_ticket_id'));
});
})
->with('manual_tickets.prior_rerouted_ticket')
->select('manual_tickets.*', 'manual_ticket_logs.id as manual_ticket_logs_id')
->get();
Related
There is a chat table and intermediate table.
I need to get from the chat table only those chats for which all user identifiers are found.
Now I am getting records if at least one match is found
My query
$chat = $this->select('chats.*')->distinct()
->rightJoin("chat_user", function ($query) {
$query->on("chats.id", "=", "chat_user.chat_id")
->whereIn("chat_user.user_id", [2, 17]);
})
->where('chats.type', '=', 'single')
->get();
Result
But I need a chat width id 4, because only it matches my request
I also tried to do it like this
$chat = $this->select('chats.*')->distinct()
->rightJoin("chat_user", function ($query) use ($members_ids) {
$query->on("chats.id", "=", "chat_user.chat_id")
->where("chat_user.user_id", 2)
->where("chat_user.user_id", 17);
})
->where('chats.type', '=', 'single')->get();
But result is empty
In plain SQL, this could be achieved with the following query:
SELECT chats.*
FROM chats
WHERE chats.type = 'single'
AND EXISTS (SELECT 1 FROM chat_user WHERE user_id = 2 AND chat_id = chats.id)
AND EXISTS (SELECT 1 FROM chat_user WHERE user_id = 7 AND chat_id = chats.id)
Translated into a Laravel query, we get the following:
$userIds = [2, 7];
$chats = DB::table('chats')
->where('chats.type', 'single')
->where(function (Builder $query) use ($userIds) {
foreach ($userIds as $userId) {
$query->whereExists(fn (Builder $query) => $query
->select(DB::raw(1))
->from('chat_user')
->where('chat_user.user_id', $userId)
->whereColumn('chat_user.chat_id', 'chats.id'));
}
})
->select('chats.*')
->get();
You should do something like this instead:
$chat = $this->select('chats.*')->distinct()
->rightJoin('chat_user', function ($query) {
$query->on('chats.id', '=', 'chat_user.chat_id')
->where('chat_user.user_id', 2)
->where('chat_user.user_id', 17);
})
->where('chats.type', '=', 'single')
->get();
Specifying multiple where works as an AND condition. If you use whereIn() will work as an OR conditions for the supplied values.
I have 2 tables, groups and questions. I need the result in such a way that it contains group name and corresponding non-deleted question count.
The structure and data for the two tables are as afollows.
My expected Result is as follows
I tried the following code, but it gives the entire row including the deleted questions.
$groupname = DB::table('groups as d')
->select([
'd.id','d.group_name',DB::raw("count(dtls.survey_group_id) as count")
])
->leftJoin('questions as dtls','d.id', '=', 'dtls.survey_group_id')
->whereNotExists( function ($query) {
$query->select(DB::raw(1))
->from('questions')
->where('id', 'd.id')
->where('dtls.is_deleted', 1);
})
->groupBy('d.id','d.group_name')
->get()
->toArray();
A problem here is that ->where('id', 'd.id') mathches id with the literal string d.id which obviously is not what you want. In addition, inner query tables should be aliased to prevent ambiguity. You can try changing it to:
$groupname = DB::table('groups as d')
->select([
'd.id','d.group_name',DB::raw("count(dtls.survey_group_id) as count")
])
->leftJoin('questions as dtls','d.id', '=', 'dtls.survey_group_id')
->whereNotExists( function ($query) {
$query->select(DB::raw(1))
->from('questions as innerDtls')
->whereRaw('innerDtls.id = d.id')
->where('dtls.is_deleted', 1);
})
->groupBy('d.id','d.group_name')
->get()
->toArray();
Alternatively your current query can be simplified to:
$groupname = DB::table('groups as d')
->select([
'd.id','d.group_name',DB::raw("count(dtls.survey_group_id) as count")
])
->leftJoin('questions as dtls','d.id', '=', 'dtls.survey_group_id')
->where('dtls.is_deleted', 0)
->groupBy('d.id','d.group_name')
->get()
->toArray();
Good day all, I am trying to count all records in a table but only if the table does not contain data in a specific column (deleted_at). It is a join table the table names are companies and employees. I am currently counting the records with a DB::raw but it should only count it if the deleted_at column is null. Please understand that i am a beginner.
public function index()
{
$user = Auth::user()->id;
$companies = DB::table('companies AS c')
->select([
'c.id',
'c.logo',
'c.company_name',
'c.created_at',
'c.sector',
'c.deleted_at',
DB::raw('COUNT(e.id) AS employee_count')
])
->leftJoin('employees AS e', 'e.company_id', '=', 'c.id' )
->leftJoin('company_user AS cu', 'cu.company_id', '=', 'c.id')
->where('cu.user_id', '=', $user)
->where('c.deleted_at', '=', null)
->groupBy('c.id')
->get();
return view('account.companies.index')
->with('companies', $companies);
}
If you are using Mysql then you could use conditional aggregation
$companies = DB::table('companies AS c')
->select([
'c.id',
'c.logo',
'c.company_name',
'c.created_at',
'c.sector',
'c.deleted_at',
DB::raw('SUM(c.deleted_at IS NULL) AS employee_count')
])
->leftJoin('employees AS e', 'e.company_id', '=', 'c.id' )
->leftJoin('company_user AS cu', 'cu.company_id', '=', 'c.id')
->where('cu.user_id', '=', $user)
->groupBy('c.id')
->get();
In mysql when an expression is used inside sum(a= b) it will result as a boolean 0/1 so you can get your conditional count using above
Or you could use whereNull() method in your query
->whereNull('c.deleted_at')
Use this code:
$employeeCount = DB::table('employees')
->select('companies.name', DB::raw('count(employees.id) as employee_count'))
->join('companies', 'employees.company','=','companies.id')
->groupBy('companies.id')
->get();
I've been able to get the query result I need using the following raw sql:
select `person`.`id`, `full_name`, count(actions.user_id) as total
from `persons`
left join `actions`
on `actions`.`person_id` = `persons`.`id`
and `actions`.`user_id` = $user
where `type` = 'mp'
group by `persons`.`id`
But I haven't been able to get it working in eloquent yet.
Based on some similar answers, I'd tried functions within ->where() or leftJoin(), but the count of each person's actions isn't yet being filtered by $user. As it stands:
$query = Person::leftJoin('actions', function($q) use ($user)
{
$q->on('actions.person_id', 'persons.id')
->where('actions.user_id', $user);
})
->groupBy('persons.id')
->where('type', 'foo')
//->where('actions.user_id', '=', $user)
->get(['persons.id', 'full_name', DB::raw('count(actions.id) as total')]);
I'm at least heading in roughly the right direction, right...?
If it's relevant, the Persons.php model has two actions relationships:
public function actions()
{
return $this->hasMany('Action');
}
public function actionsUser($id)
{
return $this->hasMany('Action')->where('user_id', $id);
}
So, for reference, I solved it like so:
$query = Person::leftJoin('actions', function($q) use ($user)
{
$q->on('actions.person_id', '=', 'persons.id')
->where('actions.user_id', '=', "$user");
})
->groupBy('persons.id')
->where('type', 'foo')
->get(['persons.id', 'full_name', DB::raw('count(actions.id) as total')]);
The ->where() clause within leftJoin, oddly, needs the speech marks for the variable to be passed through the sql query correctly (likewise, '2' doesn't seem to work while "2" does).
I found that the where doesn't always work on the leftJoin clause
If in the future you get any trouble with it, I'd suggest you using this:
$query = Person::leftJoin('actions', function($q) use ($user)
{
$q->on('actions.person_id', '=', 'persons.id')
->on('actions.user_id', '=', "$user");
})
->groupBy('persons.id')
->where('type', 'foo')
->get(['persons.id', 'full_name', DB::raw('count(actions.id) as total')]);
Hope it helps someone.
When laravel eloquent just start getting complex like this
For more flexibility and readability I'll just use plain sql statement then hydrate the results.
$sql = "
SELECT `person`.`id`,
`full_name`,
count(actions.user_id) AS total
FROM `persons`
LEFT JOIN `actions`
ON `actions`.`person_id` = `persons`.`id`
AND `actions`.`user_id` = $user
WHERE `type` = 'mp'
GROUP by `persons`.`id`
";
$query = Person::hydrate(
DB::select( $sql )
);
I have the following Models and related database tables.
Resource
Standard
Resource_Standard
I've given both the tables a belongsToMany correctly and all the naming conventions are correct. I'm trying to do a join on a query, but I keep getting an error that the field I'm checking against doesn't exist. Since I have several values to check against I'm passing them as an array to the query builder. Here is how I'm building my query:
$resource = Resource::where(function($query) use($values)
{
if($values["grade"] != 0)
$query->where('grade_id', '=', $values["grade"]);
if($values['subject'] != 0)
$query->where('subject_id', '=', $values['subject']);
if($values['types'] != '')
{
if(is_array($values['types']) && count($values['types'])> 0)
$query->whereIn('resourcetype_id', $values['types']);
else
$query->where('resourcetype_id', '=', $values['types']);
}
if($values['standards'] != '')
{
if(is_array($values['standards']) && count($values['standards'])> 0)
{
$query->join('resource_standard', 'resource_standard.resource_id', '=', 'resource.id')
->with('standards')->whereIn('resource_standard.standard_id', $values['standards']);
}
else
{
$query->join('resource_standard', 'resource_standard.resource_id', '=', 'resource.id')
->with('standards')->where('resource_standard.standard_id', '=', $values['standards']);
}
}
})->distinct()->take(30)->get();
When there is a standard_id to check against it gives the following error:
{
"error":{
"type":"Illuminate\\Database\\QueryException",
"message":"SQLSTATE[42S22]: Column not found: 1054 Unknown column 'resource_standard.standard_id' in 'where clause' (SQL: select distinct * from `resources` where (`grade_id` = 2 and `subject_id` = 1 and `resource_standard`.`standard_id` in (4832, 4833)) limit 30)",
"file":"\/Users\/luke\/Dropbox\/DEV\/PHP\/4aplus\/4aplus\/vendor\/laravel\/framework\/src\/Illuminate\/Database\/Connection.php","line":555
}
}
You can join using Eloquent model as well. Just use following code:
$resource = Resource::join('resource_standard', 'resource_standard.resource_id', '=', 'resources.id')
Instead of this:
$resource = DB::table('resources')->join('resource_standard', 'resource_standard.resource_id', '=', 'resources.id')
Don't forget to call ->get() at last.
I resolved this by using DB::table rather than the Model. I guess you can't do a join with a model perhaps.
$resource = DB::table('resources')->join('resource_standard', 'resource_standard.resource_id', '=', 'resources.id')