I have 2 channels set up: Channel A and Channel B. I also have public registration so users can log in and fill out two forms (Form A and Form B), each form creating an entry in their respective channel with the user as the author. The user can only create an entry in Channel B if they already have an entry in Channel A.
To get all the users who have an entry in Channel A but not in Channel B, I tried writing something like this in my class:
public function getUsersWithoutChannelBEntry()
{
$channel_A_entries = Entry::find()
->sectionId(1)
->all();
$userIds = [];
foreach ($channel_A_entries as $entry) {
$channel_B_entry_exists = Entry::find()
->sectionId(2)
->authorId($entry->authorId)
->exists();
if (! $channel_B_entry_exists) {
$userIds[] = $entry->authorId;
}
}
return User::find()
->id($userIds)
->all();
}
However, this creates an N+1 problem. I have roughly 200 users, so potentially 200 entries in either channel, and thus a lot of db queries and a substantially larger load time.
As an alternative approach, I've also tried looping through Channel A, adding each author ID into an array (Array A), then doing the same with Channel B making Array B. Then I use array_diff()
to extract the author IDs that are in Array A but not in Array B. However, this still causes a bit of long load time.
I've looked into eager loading, but that seems to only apply to related fields.
Is there a more efficient way to get all users who authored a Channel A entry but not Channel B entry?