Hello! I'm trying to achieve something fairly simple, but I'm not sure if it's done in a clean way. I have 3 tables. The users table, the message table and a message_user table (many to many table). The message_user table contains just 2 foreign keys (1 from the users table, and 1 from the message table) as a composite key. The idea is that a user can fill in a message form, select the amount of people the user wants to send the message to and it then sends the message to random users (it does this by attaching the message to let's say; 10 random user id's in the message_user table).
My controller looks like this:
/**
* Store the new message to the database.
*
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
// Create a new Message model, insert the data and save it
$message = new Message($request->except(["amount"]));
$message->user_id = Auth::user()->id;
$message->save();
// Randomize the message
$amount = (int) $request->amount;
$this->messageRandomizer($message, $amount);
// Redirect to the root url (homepage)
return redirect("/");
}
The messageRandomizer method looks like this:
private function messageRandomizer(Message $message, $amount)
{
$iteration = 0;
// While loop because it must have looped the amount of times of the value of $amount (like 10 or so)
while ($iteration < $amount) {
// Pick a random row from the users table. Returns a User Model and save it's id to a variable.
$randomId = User::all()->random(1)->id;
// Attach the message to a random user id if the $randomId is something different than your own user_id (because you can't send/attach the message to yourself). Else loop again.
if ($randomId !== Auth::user()->id) {
// Attach the current message with the randomized id to the message_user table. (userPivot() returns a belongsToMany())
$message->userPivot()->attach($randomId);
// Only increment the current count if the current message got assigned. This way we're 100% sure that we attach the current message the amount of times of the value of $amount. Like 50 times. Or 10 times.
$iteration++;
}
}
}
It looks pretty solid to me, but is there even a cleaner way to do this? I also have another question; The code works fine (also performance wise) when I'm not using composite keys. But the reason I now use composite keys is because I don't want to attach the same message to the same user more than 1 time and instead want the rows to be unique (no duplicates). I know I can fix this problem with a try and catch block that whenever I catch the Integrity constraint violation: 1062 Duplicate entry '12-9' for key 'PRIMARY' error, I just run through the loop again by using a continue; statement, but this doesn't feel like a good practice since the loop just keeps looping over and over until the random number generation is in our favor and finally attaches the message to all intended users.
Thanks in advance!
Edit: Wrapping the code in try and catch blocks makes it a lot worse performance-wise.