I have this function:
public function insert_task_in_table_finished(int $city_id, string $street, string $phone, string $date, int $price, string $comment, int $operator_id, int $task_id, int $status_id, int $team_id, string $started_on, string $finished_on): int
{
$connection = $this->get_db_connection();
$stmt = $connection->prepare(
"INSERT INTO "
. "`tasks_finished`"
. "(`city_id`, `street`, `phone`, `date`, `price`, `comment`, `operator_id`, `task_id`, `status_id`, `team_id`, `started_on`, `finished_on`)"
. " VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
$stmt->execute([$city_id, $street, $phone, $date, $price, $comment, $operator_id, $task_id, $status_id, $team_id, $started_on, $finished_on]);
$result = $stmt->rowCount();
$stmt = null;
return $result;
}
What I am looking to do is - get the ID of the element that I have just inserted with this query.
I have done my research and found that there exists PDO::lastInsertId
function or mysqli_insert_id
both of which return id used in the latest query
.
This would seem like something I would need, however, my main concern is the following situation:
Let's say I have many users on my website and few of them decided to finish a task simultaneously so 3 of them press corresponding buttons.
The idea is that each user should receive an ID
of the task that He
has finished, but considering that those function return that ID
of the last inserted row, I think that it is possible that it could lead to a situation where a user receives ID
of task inserted by someone else in case when there are many simultaneous finishes.
Edit: The questions are:
- For those who have more experience working with PDO/MySQL - is the scenario I described possible?
- If it is, what would be the correct approach to guarantee that each user receives the id of the task that he himself has inserted? (Besides the obvious
SELECT
method)
Edit 2:
Here is how my get_db_connection()
looks:
class DB
{
private function get_db_connection(): PDO
{
$dsn = "mysql:host=127.0.0.1:3306;dbname=crm;charset=utf8mb4";
$username = 'root'; // TODO -> replace with proper one when moving to producction
$password = ''; // TODO -> replace with proper one when moving to producction
$options = [
PDO::ATTR_EMULATE_PREPARES => false, // turn off emulation mode for "real" prepared statements
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, //turn on errors in the form of exceptions
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, //make the default fetch be an associative array
];
try {
$pdo = new PDO($dsn, $username, $password, $options);
} catch (Exception $e) {
error_log($e->getMessage());
exit('Unknown error: PDO Creation');
}
return $pdo;
}
All the actions that are related with DB changes are made only through my repository
which has each function create its own instance of DB
class and then call DB
functions from there.
Like this: (2 functions from my repository
)
function get_user_by_id(int $id)
{
$DB = new DB();
$user = $DB->select_user_by_id($id);
if (empty($user)) {
return false;
}
return $user;
}
function create_new_task(string $table, string $street, string $phone, string $date, int $price, string $comment, string $operator_id): bool
{
$DB = new DB();
$result = $DB->insert_task_in_table($table, $street, $phone, $date, $price, $comment, $operator_id);
if (empty($result)) {
return false;
}
return true;
}
I guess this approach guarantees that each user has his own connection, even more so, each function has its own connection, correct?