PHP и Postgresql: последовательная вставка

У меня есть две таблицы, связанные внешним ключом.

Чтобы зарегистрировать пользователя, я хочу последовательно вставить его информацию в информационную таблицу и учетные данные в таблицу доступа.

Но когда вторая вставка не удалась (по какой-либо причине), я хотел бы отменить (удалить) первую.

Вот часть кода:

    // Data going to table "info"
    $info = array(
        "fname" => $_POST["fname"],
        "lname"=> $_POST["lname"]
    );

    // if insert into table "info" is successfull
    if ($lastInsertID = $this->model->addUser("info", $info)) {
        
    // Data going to table "access"
        $access = array(
            "id" => $lastInsertID,
            "password" => $_POST["password"],
            "group" => "users",
            "privilege" => 0,
        );

        // insert into table "access"
        if ($this->model->addUser("access", $access)) {
                echo json_encode(array("success"));
        }
        
        else {
            // if insert into table "access" fails
            // remove the last insert  into table "info"
            $this->model->deleteUser("info", $lastInsertID);
            echo json_encode(array("error", "access"));
        }
    }
    else echo json_encode(array("error", "info"));



Проблема в том, что если вторая вставка (в таблицу «доступ») завершается неудачей, код удаления последней вставки в таблицу «информация» не выполняется. Взамен я получаю только исключение SQLSTATE и единственная строка в таблице «информация» остается

Как я могу улучшить свой код? Или есть ли лучший способ обработки «последовательной вставки» с помощью php и postgresql?

Читайте о транзакциях.

Alex Howansky 01.07.2024 23:27

Спасибо, Алекс. Я признаю, что я новичок в postgresql (я знаю только действия CRUD, но не слишком много). Но я углублюсь в это, чтобы увидеть.

Jalagui 01.07.2024 23:33

Это не специально для PostgreSQL, транзакции поддерживает практически любая база данных.

Frank Heikens 01.07.2024 23:49

Понял @FrankHeikens! Я нашел то, что мне нужно, на странице postgresqltutorial.com/postgresql-php/transaction.

Jalagui 01.07.2024 23:58

Можете ли вы также показать нам свой метод addUser()?

thegaffney 02.07.2024 00:47
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
5
51
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Используйте транзакцию:

Вы можете начать ТРАНЗАКТОИН. Затем выполните addUser().

если ваши действия успешны, зафиксируйте их, в противном случае откатите.

Добавьте несколько простых методов-оболочек в класс модели:

// I don't know your names (class name, variable names, ...), So I use sample names

class DataModel {
  /* your current code */

  public function beginTransaction()
  { $this->db_connection->beginTransaction(); }

  public function commit()
  { $this->db_connection->commit(); }

  public function rollBack()
  { $this->db_connection->rollBack(); }
}

Теперь вызовите методы транзакции в своем коде:

    // Begin a transaction
    $this->model->beginTransaction(); // <=====

    // Data going to table "info"
    $info = array(
        "fname" => $_POST["fname"],
        "lname"=> $_POST["lname"]
    );

    // if insert into table "info" is successfull
    if ($lastInsertID = $this->model->addUser("info", $info)) {
        
        // Data going to table "access"
        $access = array(
            "id" => $lastInsertID,
            "password" => $_POST["password"],
            "group" => "users",
            "privilege" => 0,
        );

        // insert into table "access"
        if ($this->model->addUser("access", $access)) {
            // Commit changes; Write changes to database actually.
            $this->model->commit(); // <=====

            echo json_encode(array("success"));
        }

        else {
            // if insert into table "access" fails
            // RollBack; Cancel all changes you make in your transaction.
            $this->model->rollBack(); // <=====enter code here
            echo json_encode(array("error", "access"));
        }
    }
    else echo json_encode(array("error", "info"));

Примерно это я и сделал. Я обернул транзакцию в try-catch вместо if-else, как вы. Но это сработало. Очень полезно @safineh. Спасибо !

Jalagui 03.07.2024 21:12

Если приведенный выше ответ решил вашу проблему или привел вас к решению, пожалуйста, примите его. Это поможет будущим пользователям столкнуться с такой же или похожей проблемой и удалит ее из очереди без ответа. Пожалуйста, не оставляйте успешно ответивший вопрос без ответа.

Belayer 04.07.2024 00:17

Привет @Belayer. Не знал об этом правиле сообщества (потому что новичок). Но уверяю вас, мне не лень быть благодарным или полезным. Спасибо за ваше предложение.

Jalagui 06.07.2024 17:27

Поймите, это тоже процесс обучения.

Belayer 06.07.2024 18:58

Другие вопросы по теме