One place for hosting & domains

      PDO

      Como usar a extensão PHP PDO para realizar transações do MySQL em PHP no Ubuntu 18.04


      O autor selecionou a Open Sourcing Mental Illness para receber uma doação como parte do programa Write for DOnations.

      Introdução

      Uma transação de MySQL consiste em um grupo de comandos em SQL relacionados de maneira lógica e que são executados no banco de dados como uma única unidade. As transações são usadas para aplicar a conformidade com as propriedades ACID (Atomicidade, Consistência, Isolamento e Durabilidade) em um aplicativo. Este é um conjunto de padrões que regem a confiabilidade das operações de processamento em um banco de dados.

      A atomicidade assegura o êxito de transações relacionadas ou um fracasso completo se ocorrer um erro. A consistência garante a validade dos dados enviados ao banco de dados, de acordo com a lógica de negócios definida. O isolamento consiste na execução correta de transações concomitantes, garantindo que os efeitos de diferentes clientes conectados a um banco de dados não afetem uns aos outros. A durabilidade garante que transações logicamente relacionadas permaneçam no banco de dados permanentemente.

      As instruções de SQL emitidas através de uma transação devem ser bem-sucedidas ou falhar completamente. Se alguma das consultas falhar, o MySQL reverte as alterações e elas nunca são confirmadas no banco de dados.

      Um bom exemplo para entender como as transações do MySQL funcionam é um site de e-commerce. Quando um cliente realiza um pedido, o aplicativo insere registros em várias tabelas, como: orders (pedidos) e orders_products (produtos do pedido), dependendo da lógica de negócios. Os registros de múltiplas tabelas relacionadas a um único pedido precisam ser enviados atomicamente ao banco de dados como uma única unidade lógica.

      Outro caso de uso está em um aplicativo bancário. Quando um cliente estiver transferindo dinheiro, algumas transações são enviadas ao banco de dados. A conta do remetente é debitada e a conta do destinatário é creditada. As duas transações devem ser confirmadas simultaneamente. Se uma delas falhar, o banco de dados retornará ao seu estado original e nenhuma alteração deve ser salva no disco.

      Neste tutorial, você usará a extensão PDO do PHP. Ela oferece uma interface para trabalhar com bancos de dados em PHP, possibilitando a realização de transações do MySQL em um servidor Ubuntu 18.04.

      Pré-requisitos

      Antes de começar, você precisará do seguinte:

      Passo 1 — Criando um banco de dados amostrais e tabelas

      Antes de começar a trabalhar com transações do MySQL, primeiro você criará um banco de dados amostrais e adicionará algumas tabelas. Primeiro, faça login no seu servidor do MySQL como root:

      Quando solicitado, digite sua senha de user root do MySQL e clique em ENTER para continuar. Em seguida, crie um banco de dados. Para os fins deste tutorial, chamaremos o banco de dados de sample_store:

      • CREATE DATABASE sample_store;

      Você verá o seguinte resultado:

      Output

      Query OK, 1 row affected (0.00 sec)

      Crie um usuário chamado sample_user para o seu banco de dados. Lembre-se de substituir a PASSWORD por um valor forte:

      • CREATE USER 'sample_user'@'localhost' IDENTIFIED BY 'PASSWORD';

      Emita privilégios completos para o seu usuário no banco de dados sample_store:

      • GRANT ALL PRIVILEGES ON sample_store.* TO 'sample_user'@'localhost';

      Por fim, recarregue os privilégios do MySQL:

      Você verá o seguinte resultado assim que criar seu usuário:

      Output

      Query OK, 0 rows affected (0.01 sec) . . .

      Com o banco de dados e o usuário configurados, agora você pode criar várias tabelas para demonstrar como as transações do MySQL funcionam.

      Faça log-off do servidor MySQL:

      Assim que o sistema desconectar você, verá o seguinte resultado:

      Output

      Bye.

      Em seguida, faça login com as credenciais do sample_user que você acabou de criar:

      • sudo mysql -u sample_user -p

      Digite a senha para o sample_user e clique em ENTER para continuar.

      Vá para o sample_store, fazendo dele banco de dados selecionado no momento:

      Você verá o seguinte resultado assim que ele for selecionado:

      Output

      Database Changed.

      Em seguida, crie uma tabela de products (produtos):

      • CREATE TABLE products (product_id BIGINT PRIMARY KEY AUTO_INCREMENT, product_name VARCHAR(50), price DOUBLE) ENGINE = InnoDB;

      Esse comando cria uma tabela products com um campo chamado product_id. Voce usará um tipo de dados chamado BIGINT que consegue acomodar um valor elevado de até 2^63-1. Esse mesmo campo é usado como uma PRIMARY KEY, de modo a identificar exclusivamente produtos. A palavra-chave AUTO_INCREMENT instrui o MySQL a gerar o próximo valor numérico conforme novos produtos vão sendo adicionados.

      O campo product_name é do tipo VARCHAR, que consegue reter um máximo de 50 letras ou números. Para o price (preço) do produto, usa-se um tipo de dados chamado DOUBLE para suprir os formatos com ponto flutuante, em preços com casas decimais.

      Por fim, usa-se o InnoDB como ENGINE, pois ele suporta com facilidade as transações do MySQL, ao contrário de outros mecanismos de armazenamento, como o MyISAM.

      Assim que criar sua tabela de products, você receberá o seguinte resultado:

      Output

      Query OK, 0 rows affected (0.02 sec)

      Em seguida, adicione alguns itens à tabela de products, executando os comandos a seguir:

      • INSERT INTO products(product_name, price) VALUES ('WINTER COAT','25.50');
      • INSERT INTO products(product_name, price) VALUES ('EMBROIDERED SHIRT','13.90');
      • INSERT INTO products(product_name, price) VALUES ('FASHION SHOES','45.30');
      • INSERT INTO products(product_name, price) VALUES ('PROXIMA TROUSER','39.95');

      Após cada operação de INSERT, você verá um resultado parecido com este:

      Output

      Query OK, 1 row affected (0.02 sec) . . .

      Em seguida, verifique se os dados foram adicionados à tabela de produtos:

      Você verá uma lista dos quatro produtos que você inseriu:

      Output

      +------------+-------------------+-------+ | product_id | product_name | price | +------------+-------------------+-------+ | 1 | WINTER COAT | 25.5 | | 2 | EMBROIDERED SHIRT | 13.9 | | 3 | FASHION SHOES | 45.3 | | 4 | PROXIMA TROUSER | 39.95 | +------------+-------------------+-------+ 4 rows in set (0.01 sec)

      Em seguida, você criará uma tabela de customers (clientes) para reter informações básicas sobre os clientes:

      • CREATE TABLE customers (customer_id BIGINT PRIMARY KEY AUTO_INCREMENT, customer_name VARCHAR(50) ) ENGINE = InnoDB;

      Assim como na tabela de products, você usa o tipo de dados BIGINT para o customer_id. Isso garantirá que a tabela possa suportar muitos clientes, indo até 2^63-1 registros. A palavra-chave AUTO_INCREMENT aumenta o valor das colunas assim que você insere um novo cliente.

      Como a coluna customer_name aceita valores alfanuméricos, usa-se o tipo de dados VARCHAR com um limite de 50 caracteres. Novamente, o ENGINE de armazenamento InnoDB é usado para dar suporte às transações.

      Após executar o comando anterior para criar a tabela customers, você verá o seguinte resultado:

      Output

      Query OK, 0 rows affected (0.02 sec)

      Você adicionará três clientes da amostra à tabela. Execute os seguintes comandos:

      • INSERT INTO customers(customer_name) VALUES ('JOHN DOE');
      • INSERT INTO customers(customer_name) VALUES ('ROE MARY');
      • INSERT INTO customers(customer_name) VALUES ('DOE JANE');

      Assim que os clientes tiverem sido adicionados, você verá um resultado parecido com este:

      Output

      Query OK, 1 row affected (0.02 sec) . . .

      Em seguida, verifique os dados na tabela customers:

      Você verá uma lista dos três clientes:

      Output

      +-------------+---------------+ | customer_id | customer_name | +-------------+---------------+ | 1 | JOHN DOE | | 2 | ROE MARY | | 3 | DOE JANE | +-------------+---------------+ 3 rows in set (0.00 sec)

      Em seguida, você criará uma tabela de orders para registrar os pedidos realizados por diferentes clientes. Para criar a tabela de orders, execute o seguinte comando:

      • CREATE TABLE orders (order_id BIGINT AUTO_INCREMENT PRIMARY KEY, order_date DATETIME, customer_id BIGINT, order_total DOUBLE) ENGINE = InnoDB;

      Você usará a coluna order_id como a PRIMARY KEY. O tipo de dados BIGINT permite que você acomode até 2^63-1 pedidos e aumentará automaticamente o valor após cada inserção de pedido. O campo order_date terá a data e hora de quando o pedido foi realizado. Consequentemente, o tipo de dados DATETIME é usado. O customer_id se relaciona à tabela de customers que você criou anteriormente.

      Você verá o seguinte resultado:

      Output

      Query OK, 0 rows affected (0.02 sec)

      Como um único pedido de um cliente pode conter vários itens, você precisa criar uma tabela de orders_products para reter essas informações.

      Para criar a tabela de orders_products, execute o seguinte comando:

      • CREATE TABLE orders_products (ref_id BIGINT PRIMARY KEY AUTO_INCREMENT, order_id BIGINT, product_id BIGINT, price DOUBLE, quantity BIGINT) ENGINE = InnoDB;

      Você deve usar o ref_id como a PRIMARY KEY e isso aumentará o valor automaticamente após cada inserção de registro. A order_id e a product_id se relacionam às tabelas de orders e products, respectivamente. A coluna de price é do tipo de dados DOUBLE, para que possa acomodar valores com pontos flutuantes.

      O mecanismo de armazenamento InnoDB deve corresponder às outras tabelas criadas anteriormente, uma vez que o pedido de um único cliente afetará várias tabelas que usam simultaneamente as transações.

      Seu resultado confirmará a criação da tabela:

      Output

      Query OK, 0 rows affected (0.02 sec)

      Você não adicionará dados às tabelas de orders e orders_products por enquanto. No entanto, você fará isso mais tarde, usando um script PHP que implementa as transações do MySQL.

      Faça log-off do servidor MySQL:

      Agora, seu esquema de banco de dados está completo e você o preencheu com alguns registros. Em seguida, você criará uma classe PHP para lidar com conexões de banco de dados e transações do MySQL.

      Neste passo, você criará uma classe PHP que usará PDO (Objetos de dados do PHP) para lidar com as transações do MySQL. A classe irá se conectar ao seu banco de dados MySQL e inserirá dados atomicamente ao banco de dados.

      Salve o arquivo de classe no diretório raiz do seu servidor Web Apache. Para fazer isso, crie um arquivo DBTransaction.php, usando seu editor de texto:

      • sudo nano /var/www/html/DBTransaction.php

      Depois, adicione o código a seguir ao arquivo: Substitua a PASSWORD pelo valor que você criou no Passo 1:

      /var/www/html/DBTransaction.php

      <?php
      
      class DBTransaction
      {
          protected $pdo;
          public $last_insert_id;
      
          public function __construct()
          {
              define('DB_NAME', 'sample_store');
              define('DB_USER', 'sample_user');
              define('DB_PASSWORD', 'PASSWORD');
              define('DB_HOST', 'localhost');
      
              $this->pdo = new PDO("mysql:host=" . DB_HOST . ";dbname=" . DB_NAME, DB_USER, DB_PASSWORD);
              $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
              $this->pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
          }
      

      No início da classe DBTransaction, o PDO usará as constantes (DB_HOST, DB_NAME, DB_USER e DB_PASSWORD) para inicializar e se conectar ao banco de dados que você criou no passo 1.

      Nota: como estamos demonstrando aqui transações do MySQL em uma escala pequena, declaramos as variáveis do banco de dados na classe DBTransaction. Em um projeto de produção grande, normalmente, você criaria um arquivo de configuração separado e carregaria as constantes do banco de dados desse arquivo usando uma instrução PHP require_once.

      Em seguida, você deve definir dois atributos para a classe PDO:

      • ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION: este atributo instruirá o PDO a gerar uma exceção se um erro for encontrado. Tais erros podem ser registrados para depuração.
      • ATTR_EMULATE_PREPARES, false: esta opção desabilita a emulação das instruções preparadas e permite que o próprio mecanismo de banco de dados MySQL prepare as instruções.

      Agora, adicione o seguinte código ao seu arquivo para criar os métodos para a sua classe:

      /var/www/html/DBTransaction.php

      . . .
          public function startTransaction()
          {
              $this->pdo->beginTransaction();
          }
      
          public function insertTransaction($sql, $data)
          {
              $stmt = $this->pdo->prepare($sql);
              $stmt->execute($data);
              $this->last_insert_id = $this->pdo->lastInsertId();
          }
      
          public function submitTransaction()
          {
              try {
                  $this->pdo->commit();
              } catch(PDOException $e) {
                  $this->pdo->rollBack();
                  return false;
              }
      
                return true;
          }
      }
      

      Salve e feche o arquivo, pressionando CTRL + X, Y e, depois, ENTER.

      Para trabalhar com as transações do MySQL, criam-se três métodos principais na classe DBTransaction: startTransaction, insertTransaction e submitTransaction.

      • startTransaction: este método instrui o PDO a iniciar uma transação e desliga a confirmação automática até que um comando de confirmação seja emitido.

      • insertTransaction: este método recebe dois argumentos. A variável $sql mantém a instrução SQL a ser executada, enquanto a variável $data é uma matriz dos dados a serem ligados à instrução SQL, uma vez que você está usando instruções preparadas. Os dados são informados como uma matriz ao método insertTransaction.

      • submitTransaction: este método confirma as alterações no banco de dados permanentemente, emitindo um comando de commit(). No entanto, se houver um erro e as transações tiverem um problema, o método chama o método rollBack() para reverter o banco de dados ao seu estado original, caso uma exceção do PDO seja levantada.

      Sua classe DBTransaction inicializa uma transação, prepara os diferentes comandos SQL a serem executados. Por fim, confirma atomicamente as alterações no banco de dados se não houver problemas. Caso contrário, a transação é revertida. Além disso, a classe permite que você recupere o registro order_id que você acabou de criar, acessando a propriedade pública last_insert_id.

      Agora, a classe DBTransaction está pronta para ser chamada e usada por qualquer código PHP, que você criará a seguir.

      Passo 3 — Criando um script PHP para usar a classe DBTransaction

      Você criará um script PHP que implementará a classe DBTransaction e enviará um grupo de comandos SQL ao banco de dados MySQL. Você imitará o fluxo de trabalho de um pedido de cliente em um carrinho de compras on-line.

      Essas consultas SQL afetarão as orders e as tabelas de orders_products. Sua classe DBTransaction deve permitir alterações no banco de dados apenas se todas as consultas forem executadas sem erros. Caso contrário, você receberá um erro e qualquer tentativa de alteração será revertida.

      Você está criando um único pedido para o cliente JOHN DOE, identificado com o customer_id 1. O pedido do cliente possui três itens diferentes com quantidades diferentes na tabela de products. Seu script PHP recebe os dados do pedido do cliente e os envia à classe DBTransaction.

      Crie o arquivo orders.php:

      • sudo nano /var/www/html/orders.php

      Depois, adicione o código a seguir ao arquivo:

      /var/www/html/orders.php

      <?php
      
      require("DBTransaction.php");
      
      $db_host = "database_host";
      $db_name = "database_name";
      $db_user = "database_user";
      $db_password = "PASSWORD";
      
      $customer_id = 2;
      
      $products[] = [
        'product_id' => 1,
        'price' => 25.50,
        'quantity' => 1
      ];
      
      $products[] = [
        'product_id' => 2,
        'price' => 13.90,
        'quantity' => 3
      ];
      
      $products[] = [
        'product_id' => 3,
        'price' => 45.30,
        'quantity' => 2
      ];
      
      $transaction = new DBTransaction($db_host, $db_user, $db_password, $db_name);
      

      Você criou um script PHP que inicializa uma instância da classe DBTransaction que você criou no Passo 2.

      Nesse script, você inclui o arquivo DBTransaction.php e inicializa a classe DBTransaction. Em seguida, prepare uma matriz multidimensional de todos os produtos que o cliente está pedindo da loja. Você também invocará o método startTransaction() para iniciar uma transação.

      Em seguida, adicione o código a seguir para finalizar seu script orders.php:

      /var/www/html/orders.php

      . . .
      $order_query = "insert into orders (order_id, customer_id, order_date, order_total) values(:order_id, :customer_id, :order_date, :order_total)";
      $product_query = "insert into orders_products (order_id, product_id, price, quantity) values(:order_id, :product_id, :price, :quantity)";
      
      $transaction->insertQuery($order_query, [
        'customer_id' => $customer_id,
        'order_date' => "2020-01-11",
        'order_total' => 157.8
      ]);
      
      $order_id = $transaction->last_insert_id;
      
      foreach ($products as $product) {
        $transaction->insertQuery($product_query, [
          'order_id' => $order_id,
          'product_id' => $product['product_id'],
          'price' => $product['price'],
          'quantity' => $product['quantity']
        ]);
      }
      
      $result = $transaction->submit();
      
      if ($result) {
          echo "Records successfully submitted";
      } else {
          echo "There was an error.";
      }
      
      

      Salve e feche o arquivo, pressionando CTRL + X, Y e, depois, ENTER.

      Prepare o comando a ser inserido na tabela de pedidos através do método insertTransaction. Depois, recupere o valor da propriedade pública last_insert_id da classe DBTransaction e o utilize como $order_id.

      Assim que você tiver um $order_id, utilize o ID único para inserir os itens do pedido do cliente na tabela de orders_products.

      Por fim, você chama o método submitTransaction para confirmar todos os detalhes do pedido do cliente no banco de dados se não houver problemas. Caso contrário, o método submitTransaction reverterá as tentativas de alterações.

      Agora, você executará o script orders.php em seu navegador. Substitua o your-server-IP pelo endereço IP público do seu servidor e execute o seguinte:

      http://your-server-IP/orders.php

      Você verá uma confirmação de que os registros foram enviados com sucesso:

      Resultado em PHP da classe MySQL de transações

      Seu script PHP está funcionando conforme o esperado e o pedido – com os produtos do pedido associados – foram enviados atomicamente ao banco de dados.

      Você executou o arquivo orders.php em uma janela do navegador. O script invocou a classe DBTransaction que, por sua vez, enviou os detalhes de orders ao banco de dados. No próximo passo, você verificará se os registros foram salvos nas tabelas do banco de dados relacionadas.

      Passo 4 — Confirmando as entradas em seu banco de dados

      Neste passo, você verificará se a transação iniciada a partir da janela do navegador para o pedido do cliente foi postada nas tabelas do banco de dados, conforme esperado.

      Para fazer isso, faça login no seu banco de dados MySQL novamente:

      • sudo mysql -u sample_user -p

      Digite a senha para o sample_user e tecle ENTER para continuar.

      Vá para o banco de dados sample_store:

      Antes de prosseguir, certifique-se de que o banco de dados foi alterado, confirmando o resultado a seguir:

      Output

      Database Changed.

      Em seguida, emita o seguinte comando para recuperar os registros da tabela orders:

      Isso exibirá o seguinte resultado, detalhando o pedido do cliente:

      Output

      +----------+---------------------+-------------+-------------+ | order_id | order_date | customer_id | order_total | +----------+---------------------+-------------+-------------+ | 1 | 2020-01-11 00:00:00 | 2 | 157.8 | +----------+---------------------+-------------+-------------+ 1 row in set (0.00 sec)

      Em seguida, recupere os registros da tabela orders_products:

      • SELECT * FROM orders_products;

      Você verá um resultado com uma lista de produtos do pedido do cliente, parecido com o seguinte:

      Output

      +--------+----------+------------+-------+----------+ | ref_id | order_id | product_id | price | quantity | +--------+----------+------------+-------+----------+ | 1 | 1 | 1 | 25.5 | 1 | | 2 | 1 | 2 | 13.9 | 3 | | 3 | 1 | 3 | 45.3 | 2 | +--------+----------+------------+-------+----------+ 3 rows in set (0.00 sec)

      O resultado confirma que a transação foi salva no banco de dados e que sua classe DBTransaction auxiliar está funcionando conforme o esperado.

      Conclusão

      Neste guia, você usou o PDO do PHP para trabalhar com as transações do MySQL. Embora este não seja um artigo conclusivo sobre a criação de um software de e-commerce, trata-se de um exemplo de como usar transações do MySQL em seus aplicativos.

      Para aprender mais sobre o modelo ACID do MySQL, consulte o guia InnoDB e o modelo ACID, no site oficial do MySQL. Acesse nossa página de conteúdo do MySQL para obter mais tutoriais, artigos e Q&A relacionados.



      Source link

      Cómo usar la extensión PHP PDO para realizar transacciones de MySQL en PHP en Ubuntu 18.04


      El autor seleccionó Open Sourcing Mental Illness para recibir una donación como parte del programa Write for DOnations.

      Introducción

      Una transacción de MySQL es un conjunto de comandos SQL que guardan una relación lógica y se ejecutan en la base de datos como una sola unidad. Las transacciones se utilizan para garantizar el cumplimiento de ACID (atomicidad, consistencia, aislamiento y durabilidad, por su sigla en inglés) en las aplicaciones. Se trata de un conjunto de normas que determinan la confiabilidad de las operaciones de procesamiento de las bases de datos.

      La atomicidad garantiza que las transacciones relacionadas sean correctas o no surtan ningún efecto si se produce un error. La consistencia garantiza la validez de los datos enviados a la base de datos según la lógica de negocios definida. El aislamiento es la correcta ejecución de transacciones simultáneas que garantiza que los efectos de los distintos clientes que se conectan a una base de datos no se afecten entre sí. La durabilidad garantiza que las transacciones con relación lógica se conserven en la base de datos de forma permanente.

      Las instrucciones SQL que se emiten a través de una transacción deben ser correctas fracasar por completo. Si alguna consulta falla, MySQL revierte los cambios y no se confirman en la base de datos.

      Un buen ejemplo para comprender cómo funcionan las transacciones de MySQL es un sitio web de comercio electrónico. Cuando un cliente realiza un pedido, la aplicación inserta registros en varias tablas, por ejemplo, orders y orders_products, dependiendo de la lógica de negocio. Los registros de varias tablas relacionados con un único pedido se deben enviar de forma atómica a la base de datos como una sola unidad lógica.

      Otro caso de uso es una aplicación bancaria. Cuando un cliente transfiere dinero, se envían algunas transacciones a la base de datos. Se debita dinero de la cuenta del remitente y se acredita en la del receptor. Las dos transacciones se deben confirmar de forma simultánea. Si una de ellas falla, la base de datos volverá a su estado original y no se guardarán cambios en el disco.

      En el caso de este tutorial, usará la extensión PHP PDO, que ofrece una interfaz para trabajar con bases de datos en PHP, para realizar transacciones de MySQL en un servidor de Ubuntu 18.04.

      Requisitos previos

      Para comenzar, necesitará lo siguiente:

      Paso 1: Crear una base de datos y tablas de ejemplo

      Primero, creará una base de datos de ejemplo y agregará algunas tablas para comenzar a trabajar con transacciones de MySQL. Primero, inicie sesión en su servidor MySQL como root:

      Cuando se le solicite, introduzca su contraseña root de MySQL y presione INTRO para continuar. Luego, cree una base de datos. En este tutorial, la denominaremos sample_store:

      • CREATE DATABASE sample_store;

      Verá lo siguiente:

      Output

      Query OK, 1 row affected (0.00 sec)

      Cree un usuario llamado sample_user para su base de datos. Recuerde sustituir PASSWORD por un valor seguro:

      • CREATE USER 'sample_user'@'localhost' IDENTIFIED BY 'PASSWORD';

      Conceda privilegios completos a su usuario para la base de datos sample_store:

      • GRANT ALL PRIVILEGES ON sample_store.* TO 'sample_user'@'localhost';

      Por último, vuelva a cargar los privilegios de MySQL:

      Una vez que cree su usuario, verá el siguiente resultado:

      Output

      Query OK, 0 rows affected (0.01 sec) . . .

      Ahora, con la base de datos y el usuario establecidos, puede crear varias tablas para ver cómo funcionan las transacciones de MySQL.

      Cierre sesión en el servidor de MySQL:

      Una vez que el sistema cierre su sesión, verá el siguiente resultado:

      Output

      Bye.

      Luego, inicie sesión con las credenciales de sample_user que acaba de crear:

      • sudo mysql -u sample_user -p

      Ingrese la contraseña de sample_user y presione INTRO para continuar.

      Pase a sample_store para que sea la base de datos seleccionada:

      Una vez que la seleccione, verá el siguiente resultado:

      Output

      Database Changed.

      A continuación, cree una tabla products:

      • CREATE TABLE products (product_id BIGINT PRIMARY KEY AUTO_INCREMENT, product_name VARCHAR(50), price DOUBLE) ENGINE = InnoDB;

      Este comando crea una tabla products con un campo denominado product_id. Se utiliza el tipo de datos BIGINT, que puede admitir un valor elevado de hasta 2^63-1. Se utiliza este mismo campo como PRIMARY KEY para identificar productos de forma única. La palabra clave AUTO_INCREMENT indica a MySQL que genere el siguiente valor numérico cuando se insertan nuevos productos.

      El campo product_name es de tipo VARCHAR y puede contener hasta 50 letras o números. En price del producto, se utiliza el tipo de datos DOUBLE para admitir formatos de punto flotante en los precios con números decimales.

      Por último, se utiliza InnoDB como ENGINE porque admite fácilmente las transacciones de MySQL a diferencia de otros motores de almacenamiento, como MyISAM.

      Cuando haya creado su tabla products, verá el siguiente resultado:

      Output

      Query OK, 0 rows affected (0.02 sec)

      A continuación, añada algunos elementos a la tabla products al ejecutar los siguientes comandos:

      • INSERT INTO products(product_name, price) VALUES ('WINTER COAT','25.50');
      • INSERT INTO products(product_name, price) VALUES ('EMBROIDERED SHIRT','13.90');
      • INSERT INTO products(product_name, price) VALUES ('FASHION SHOES','45.30');
      • INSERT INTO products(product_name, price) VALUES ('PROXIMA TROUSER','39.95');

      Verá un resultado similar al siguiente después de cada operación INSERT:

      Output

      Query OK, 1 row affected (0.02 sec) . . .

      Luego, compruebe que se hayan agregado los datos a la tabla products:

      Verá una lista con los cuatro productos que insertó:

      Output

      +------------+-------------------+-------+ | product_id | product_name | price | +------------+-------------------+-------+ | 1 | WINTER COAT | 25.5 | | 2 | EMBROIDERED SHIRT | 13.9 | | 3 | FASHION SHOES | 45.3 | | 4 | PROXIMA TROUSER | 39.95 | +------------+-------------------+-------+ 4 rows in set (0.01 sec)

      A continuación, creará una tabla customers para almacenar información básica sobre los clientes:

      • CREATE TABLE customers (customer_id BIGINT PRIMARY KEY AUTO_INCREMENT, customer_name VARCHAR(50) ) ENGINE = InnoDB;

      Al igual que en la tabla products, se utiliza el tipo de datos BIGINT para customer_id para garantizar que la tabla pueda admitir muchos clientes, hasta 2^63-1 registros. La palabra clave AUTO_INCREMENT aumenta el valor de las columnas cuando se inserta un nuevo cliente.

      Como la columna customer_name acepta valores alfanuméricos, se utiliza el tipo de datos VARCHAR, que tiene un límite de 50 caracteres. Nuevamente, se utiliza InnoDB como ENGINE de almacenamiento para admitir las transacciones.

      Después de ejecutar el comando anterior para crear la tabla customers, verá el siguiente resultado:

      Output

      Query OK, 0 rows affected (0.02 sec)

      Agregará tres clientes de ejemplo a la tabla. Ejecute el siguiente comando:

      • INSERT INTO customers(customer_name) VALUES ('JOHN DOE');
      • INSERT INTO customers(customer_name) VALUES ('ROE MARY');
      • INSERT INTO customers(customer_name) VALUES ('DOE JANE');

      Una vez que haya agregado los clientes, verá un resultado similar al siguiente:

      Output

      Query OK, 1 row affected (0.02 sec) . . .

      Luego, verifique los datos de la tabla customers:

      Verá una lista con los tres clientes:

      Output

      +-------------+---------------+ | customer_id | customer_name | +-------------+---------------+ | 1 | JOHN DOE | | 2 | ROE MARY | | 3 | DOE JANE | +-------------+---------------+ 3 rows in set (0.00 sec)

      A continuación, creará una tabla orders para registrar los pedidos de los distintos clientes. Para crear la tabla orders, ejecute el siguiente comando:

      • CREATE TABLE orders (order_id BIGINT AUTO_INCREMENT PRIMARY KEY, order_date DATETIME, customer_id BIGINT, order_total DOUBLE) ENGINE = InnoDB;

      Se utiliza la columna order_id como PRIMARY KEY. El tipo de datos BIGINT le permite ingresar hasta 2^63-1 pedidos que se incrementan de forma automática cada vez que se introduce uno nuevo. El campo order_date contiene la fecha y la hora reales en que se realiza un pedido y, por lo tanto, se utiliza el tipo de datos DATETIME. El campo customer_id se relaciona con la tabla customers que creó anteriormente.

      Verá lo siguiente:

      Output

      Query OK, 0 rows affected (0.02 sec)

      Como el pedido de un cliente puede contener varios elementos, debe crear una tabla orders_products para almacenar esta información.

      Para crear la tabla orders_products, ejecute el siguiente comando:

      • CREATE TABLE orders_products (ref_id BIGINT PRIMARY KEY AUTO_INCREMENT, order_id BIGINT, product_id BIGINT, price DOUBLE, quantity BIGINT) ENGINE = InnoDB;

      Se utiliza ref_id como PRIMARY KEY, que se incrementará automáticamente con cada registro que se ingrese. Los campos order_id y product_id se relacionan con las tablas orders y products respectivamente. La columna price es de tipo DOUBLE para poder admitir valores flotantes.

      El motor de almacenamiento InnoDB debe coincidir con las otras tablas creadas anteriormente, dado que el pedido de un cliente afectará varias tablas que utilizan transacciones en simultáneo.

      Su resultado confirmará la creación de la tabla:

      Output

      Query OK, 0 rows affected (0.02 sec)

      Por el momento, no agregará datos a las tablas orders y orders_products, pero lo hará más adelante utilizando una secuencia de comandos PHP que implementa transacciones de MySQL.

      Cierre sesión en el servidor de MySQL:

      Ahora, su esquema de base de datos está completo y lo completó con algunos registros. Ahora, creará una clase PHP para gestionar las conexiones de la base de datos y las transacciones de MySQL.

      Paso 2: Diseñar una clase PHP para administrar transacciones de MySQL

      En este paso, creará una clase PHP que usará PDO (objetos de datos de PHP) para gestionar transacciones de MySQL. La clase se conectará con su base de datos de MySQL e insertará datos de forma atómica en la base de datos.

      Guarde el archivo de clase en el directorio root de su servidor web de Apache. Para hacerlo, cree un archivo DBTransaction.php con su editor de texto:

      • sudo nano /var/www/html/DBTransaction.php

      Luego, añada el siguiente código al archivo. Reemplace PASSWORD por el valor que creó en el paso 1:

      /var/www/html/DBTransaction.php

      <?php
      
      class DBTransaction
      {
          protected $pdo;
          public $last_insert_id;
      
          public function __construct()
          {
              define('DB_NAME', 'sample_store');
              define('DB_USER', 'sample_user');
              define('DB_PASSWORD', 'PASSWORD');
              define('DB_HOST', 'localhost');
      
              $this->pdo = new PDO("mysql:host=" . DB_HOST . ";dbname=" . DB_NAME, DB_USER, DB_PASSWORD);
              $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
              $this->pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
          }
      

      Al comienzo de la clase DBTransaction, el PDO utilizará las constantes (DB_HOST, DB_NAME, DB_USER, y DB_PASSWORD) para inicializar la base de datos que creó en el paso 1 y conectarse a ella.

      Nota: Debido a que estamos demostrando transacciones de MySQL en pequeña escala en este tutorial, declaramos las variables de la base de datos en la clase DBTransaction. En un proyecto de producción de gran envergadura, normalmente, crearía un archivo de configuración separado y cargaría las constantes de la base de datos de ese archivo usando la instrucción de PHP require_once.

      A continuación, establezca dos atributos para la clase PDO:

      • ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION: este atributo le indica a PDO que inicie una excepción si se encuentra un error. Los errores se pueden registrar para su depuración.
      • ATTR_EMULATE_PREPARES, false: esta opción desactiva la emulación de las instrucciones preparadas y permite que el motor de la base de datos de MySQL las prepare por su cuenta.

      Ahora, añada el siguiente código a su archivo para crear los métodos de su clase:

      /var/www/html/DBTransaction.php

      . . .
          public function startTransaction()
          {
              $this->pdo->beginTransaction();
          }
      
          public function insertTransaction($sql, $data)
          {
              $stmt = $this->pdo->prepare($sql);
              $stmt->execute($data);
              $this->last_insert_id = $this->pdo->lastInsertId();
          }
      
          public function submitTransaction()
          {
              try {
                  $this->pdo->commit();
              } catch(PDOException $e) {
                  $this->pdo->rollBack();
                  return false;
              }
      
                return true;
          }
      }
      

      Guarde y cierre el archivo pulsando CTRL + X, Y e INTRO.

      Para trabajar con las transacciones de MySQL, se crean tres métodos principales en la clase DBTransaction: startTransaction, insertTransaction y submitTransaction.

      • startTransaction: este método le indica a PDO que inicie una transacción y desactive la confirmación automática hasta que se emita un comando de confirmación.

      • insertTransaction: este método toma dos argumentos. La variable $sql contiene la instrucción SQL que se ejecutará y la variable $data es una matriz de los datos que se vincularán con la instrucción SQL, dado que se utilizarán instrucciones preparadas. Los datos se pasan como una matriz al método insertTransaction.

      • submitTransaction: este método confirma los cambios de forma permanente en la base de datos al emitir un comando commit(). Sin embargo, si hay un error y las transacciones tienen un problema, el método invoca el método rollBack() para hacer que la base de datos regrese a su estado original en caso de que se produzca una excepción de PDO.

      Su clase DBTransaction inicia una transacción, prepara los diferentes comandos SQL que se ejecutarán y, por último, confirma los cambios en la base de datos de forma atómica si no hay problemas. De lo contrario, la transacción se revierte. Además, la clase le permite obtener el registro order_id que acaba de crear al acceder a la propiedad pública last_insert_id.

      Ahora, la clase DBTransaction está lista para invocarse y utilizarse mediante cualquier código PHP, que se creará a continuación.

      Paso 3: Crear una secuencia de comandos PHP para usar la clase DBTransaction

      Creará una secuencia de comandos PHP que implementará la clase DBTransaction y enviará un conjunto de comandos SQL a la base de datos de MySQL. Simulará el flujo de trabajo de un pedido de un cliente en un carrito de compras en línea.

      Estas consultas SQL afectarán las tablas orders y orders_products. Su clase DBTransaction solo debería permitir cambios en la base de datos si todas las consultas se ejecutan sin errores. De lo contrario, verá un error y se revertirán los cambios que haya intentado implementar.

      Creará un pedido único para el cliente JOHN DOE identificado con la customer_id 1. En el pedido del cliente hay tres artículos diferentes con cantidades distintas de la tabla products. Su secuencia de comandos PHP toma los datos del pedido del cliente y los envía a la clase DBTransaction.

      Cree el archivo orders.php:

      • sudo nano /var/www/html/orders.php

      Luego, añada el siguiente código al archivo:

      /var/www/html/orders.php

      <?php
      
      require("DBTransaction.php");
      
      $db_host = "database_host";
      $db_name = "database_name";
      $db_user = "database_user";
      $db_password = "PASSWORD";
      
      $customer_id = 2;
      
      $products[] = [
        'product_id' => 1,
        'price' => 25.50,
        'quantity' => 1
      ];
      
      $products[] = [
        'product_id' => 2,
        'price' => 13.90,
        'quantity' => 3
      ];
      
      $products[] = [
        'product_id' => 3,
        'price' => 45.30,
        'quantity' => 2
      ];
      
      $transaction = new DBTransaction($db_host, $db_user, $db_password, $db_name);
      

      Creó una secuencia de comandos PHP que inicia una instancia de la clase DBTransaction que creó en el paso 2.

      En esta secuencia de comandos, incluye el archivo DBTransaction.php e inicia la clase DBTransaction. Luego, prepara una matriz multidimensional con todos los productos que el cliente pide a la tienda. También invoca el método startTransaction() para iniciar una transacción.

      A continuación, añada el siguiente código para finalizar su secuencia de comandos orders.php

      /var/www/html/orders.php

      . . .
      $order_query = "insert into orders (order_id, customer_id, order_date, order_total) values(:order_id, :customer_id, :order_date, :order_total)";
      $product_query = "insert into orders_products (order_id, product_id, price, quantity) values(:order_id, :product_id, :price, :quantity)";
      
      $transaction->insertQuery($order_query, [
        'customer_id' => $customer_id,
        'order_date' => "2020-01-11",
        'order_total' => 157.8
      ]);
      
      $order_id = $transaction->last_insert_id;
      
      foreach ($products as $product) {
        $transaction->insertQuery($product_query, [
          'order_id' => $order_id,
          'product_id' => $product['product_id'],
          'price' => $product['price'],
          'quantity' => $product['quantity']
        ]);
      }
      
      $result = $transaction->submit();
      
      if ($result) {
          echo "Records successfully submitted";
      } else {
          echo "There was an error.";
      }
      
      

      Guarde y cierre el archivo pulsando CTRL + X, Y e INTRO.

      El comando que se insertará en la tabla de pedidos se prepara con el método insertTransaction. A continuación, obtenga el valor de la propiedad pública last_insert_id de la clase DBTransaction y úselo como $order_id.

      Una vez que se dispone de una $order_id, se utiliza la identificación única para insertar los artículos del pedido del cliente en la tabla orders_products.

      Por último, invoque el método submitTransaction para confirmar los datos del pedido del cliente en la base de datos si no hay problemas. De lo contrario, el método submitTransaction revertirá los cambios que haya intentado realizar.

      Ahora, ejecute la secuencia de comandos orders.php en su navegador. Ejecute lo siguiente y sustituya your-server-IP por la dirección IP pública de su servidor:

      http://your-server-IP/orders.php

      Verá la confirmación de que los registros se enviaron correctamente:

      Resultado de PHP de la clase de transacciones de MySQL

      Su secuencia de comandos PHP funciona según lo previsto y el pedido y los productos del pedido se enviaron a la base de datos de forma atómica.

      Ejecutó el archivo orders.php en la ventana de un navegador. La secuencia de comandos invocó la clase DBTransaction, que, a su vez, envió los datos de orders a la base de datos. En el siguiente paso, verificará si los registros se almacenaron en las tablas relacionadas de la base de datos.

      Paso 4: Confirmar los entradas en su base de datos

      En este paso, verificará si la transacción del pedido del cliente iniciada desde la ventana del navegador se envió a las tablas de la base de datos según lo previsto.

      Para hacerlo, vuelva a iniciar sesión en su base de datos de MySQL:

      • sudo mysql -u sample_user -p

      Ingrese la contraseña de sample_user y presione INTRO para continuar.

      Pase a la base de datos sample_store:

      Antes de continuar, asegúrese de que la base de datos se haya modificado al confirmar el siguiente resultado:

      Output

      Database Changed.

      Luego, emita el siguiente comando para obtener los registros de la tabla orders:

      Esto mostrará el siguiente resultado en el que se detalla el pedido del cliente:

      Output

      +----------+---------------------+-------------+-------------+ | order_id | order_date | customer_id | order_total | +----------+---------------------+-------------+-------------+ | 1 | 2020-01-11 00:00:00 | 2 | 157.8 | +----------+---------------------+-------------+-------------+ 1 row in set (0.00 sec)

      A continuación, obtenga los registros de la tabla orders_products:

      • SELECT * FROM orders_products;

      Verá un resultado similar al siguiente con una lista de los productos del pedido del cliente:

      Output

      +--------+----------+------------+-------+----------+ | ref_id | order_id | product_id | price | quantity | +--------+----------+------------+-------+----------+ | 1 | 1 | 1 | 25.5 | 1 | | 2 | 1 | 2 | 13.9 | 3 | | 3 | 1 | 3 | 45.3 | 2 | +--------+----------+------------+-------+----------+ 3 rows in set (0.00 sec)

      El resultado confirma que la transacción se guardó en la base de datos y que su clase auxiliar DBTransaction está funcionando según lo previsto.

      Conclusión

      En esta guía, utilizó PDO de PHP para trabajar con transacciones de MySQL. Si bien en este artículo no se abarcan todos los aspectos del diseño de un software de comercio electrónico, se ofreció un ejemplo para usar transacciones de MySQL en sus aplicaciones.

      Para obtener más información sobre el modelo ACID de MySQL, considere consultar la guía InnoDB y el modelo ACID en el sitio web oficial de MySQL. Visite nuestra página de contenido de MySQL para acceder a más tutoriales, artículos y preguntas y respuestas relacionados.



      Source link

      Comment utiliser l’extension PHP PDO pour exécuter MySQL en PHP sur Ubuntu 18.04


      L’auteur a choisi Open Sourcing Mental Illness pour recevoir un don dans le cadre du programme Write for DOnations.

      Introduction

      Une transaction MySQL est un groupe de commandes SQL logiquement liées qui sont exécutées dans la base de données comme une seule unité. Les transactions sont utilisées pour faire respecter la conformité ACID ( Atomicité, Cohérence, Isolation et Durabilité) dans une application. Il s’agit d’un ensemble de normes qui régissent la fiabilité des opérations de traitement dans une base de données.

      L’atomicité garantit le succès des opérations connexes ou un échec complet si une erreur se produit. La cohérence garantit la validité des données soumises à la base de données selon une logique commerciale définie. L’isolation est l’exécution correcte de transactions simultanées garantissant que les effets des différents clients se connectant à une base de données n’affectent pas les autres. La durabilité garantit que les transactions logiquement liées restent en permanence dans la base de données.

      Les instructions SQL émises via une transaction doivent soit réussir, soit échouer complètement. Si l’une des requêtes échoue, MySQL annule les modifications et celles-ci ne sont jamais enregistrées dans la base de données.

      Un bon exemple pour comprendre comment fonctionnent les transactions MySQL est un site web de commerce électronique. Lorsqu’un client passe une commande, l’application insère des enregistrements dans plusieurs tableaux, tels que : orders et orders_products, en fonction de la logique commerciale.  Les enregistrements multi-tableaux liés à une seule commande doivent être envoyés de manière atomique à la base de données en tant qu’unité logique unique.

      Un autre cas d’utilisation est celui d’une application bancaire. Lorsqu’un client transfère de l’argent, deux transactions sont envoyées à la base de données. Le compte de l’expéditeur est débité et le compte du destinataire est crédité. Les deux transactions doivent être effectuées simultanément. Si l’une d’elles échoue, la base de données revient à son état initial et aucune modification ne doit être enregistrée sur le disque.

      Dans ce tutoriel, vous utiliserez l’extension PHP PDO, qui fournit une interface permettant de travailler avec des bases de données en PHP, pour effectuer des transactions MySQL sur un serveur Ubuntu 18.04.

      Conditions préalables

      Avant de commencer, vous aurez besoin des éléments suivants :

      Étape 1 — Création d’un exemple de base de données et de tableaux

      Vous allez d’abord créer une base de données type et ajouter quelques tableaux avant de commencer à travailler avec les transactions MySQL. Tout d’abord, connectez-vous à votre serveur MySQL en tant que root :

      Lorsque vous y êtes invité, entrez votre mot de passe MySQL en tant que root et appuyez sur ENTER (ENTRÉE) pour continuer. Ensuite, créez une base de données. Aux fins de ce tutoriel, nous appellerons la base de données sample_store:

      • CREATE DATABASE sample_store;

      Vous verrez le résultat suivant :

      Output

      Query OK, 1 row affected (0.00 sec)

      Créez un utilisateur appelé sample_user pour votre base de données. N’oubliez pas de remplacer PASSWORD par une valeur forte :

      • CREATE USER 'sample_user'@'localhost' IDENTIFIED BY 'PASSWORD';

      Donnez à votre utilisateur tous les privilèges pour la base de données sample_store :

      • GRANT ALL PRIVILEGES ON sample_store.* TO 'sample_user'@'localhost';

      Enfin, rechargez les privilèges MySQL :

      Vous verrez la sortie suivante une fois que vous aurez créé votre utilisateur :

      Output

      Query OK, 0 rows affected (0.01 sec) . . .

      Avec la base de données et l’utilisateur en place, vous pouvez maintenant créer plusieurs tableaux pour montrer comment fonctionnent les transactions MySQL.

      Déconnectez-vous du serveur MySQL :

      Une fois que le système vous a déconnecté, vous verrez le résultat suivant :

      Output

      Bye.

      Ensuite, connectez-vous avec les informations d’identification de l'utilisateur que vous venez de créer :

      • sudo mysql -u sample_user -p

      Entrez le mot de passe de sample_user et appuyez sur ENTER (ENTRÉE) pour continuer.

      Passez à la base de données sample_store pour qu’elle devienne la base de données actuellement sélectionnée :

      Vous verrez la sortie suivante une fois qu’elle sera sélectionnée :

      Output

      Database Changed.

      Ensuite, créez un tableau products :

      • CREATE TABLE products (product_id BIGINT PRIMARY KEY AUTO_INCREMENT, product_name VARCHAR(50), price DOUBLE) ENGINE = InnoDB;

      Cette commande crée un tableau products avec un champ nommé product_id. Vous utilisez un type de données BIGINT qui peut accueillir une valeur importante allant jusqu’à 2^63-1. Vous utilisez ce même champ comme CLÉ PRIMAIRE pour identifier les produits de manière unique. Le mot-clé AUTO_INCREMENT indique à MySQL de générer la valeur numérique suivante lorsque de nouveaux produits sont insérés.

      Le champ product_name est du type VARCHAR qui peut contenir jusqu’à 50 lettres ou chiffres maximum. Pour le prix du produit, vous utilisez un type de données DOUBLE pour tenir compte des formats à virgule flottante dans les prix avec des nombres décimaux.

      Enfin, vous utilisez l’InnoDB comme MOTEUR car il prend confortablement en charge les transactions MySQL contrairement à d’autres moteurs de stockage tels que MyISAM.

      Une fois que vous aurez créé votre tableau products, vous obtiendrez le résultat suivant :

      Output

      Query OK, 0 rows affected (0.02 sec)

      Ensuite, ajoutez des éléments au tableau products en exécutant les commandes suivantes :

      • INSERT INTO products(product_name, price) VALUES ('WINTER COAT','25.50');
      • INSERT INTO products(product_name, price) VALUES ('EMBROIDERED SHIRT','13.90');
      • INSERT INTO products(product_name, price) VALUES ('FASHION SHOES','45.30');
      • INSERT INTO products(product_name, price) VALUES ('PROXIMA TROUSER','39.95');

      Vous verrez une sortie semblable à celle qui suit après chaque opération INSERT :

      Output

      Query OK, 1 row affected (0.02 sec) . . .

      Ensuite, vérifiez que les données ont été ajoutées au tableau products :

      Vous verrez une liste des quatre produits que vous avez insérés :

      Output

      +------------+-------------------+-------+ | product_id | product_name | price | +------------+-------------------+-------+ | 1 | WINTER COAT | 25.5 | | 2 | EMBROIDERED SHIRT | 13.9 | | 3 | FASHION SHOES | 45.3 | | 4 | PROXIMA TROUSER | 39.95 | +------------+-------------------+-------+ 4 rows in set (0.01 sec)

      Ensuite, vous allez créer un tableau customersqui contiendra des informations de base sur les clients :

      • CREATE TABLE customers (customer_id BIGINT PRIMARY KEY AUTO_INCREMENT, customer_name VARCHAR(50) ) ENGINE = InnoDB;

      Comme dans le tableau products, vous utilisez le type de données BIGINT pour le customer_id et cela garantira que le tableau peut supporter un grand nombre de clients, jusqu’à 2^63-1 enregistrements. Le mot-clé AUTO_INCREMENT incrémente la valeur des colonnes une fois que vous avez inséré un nouveau client.

      Comme la colonne customer_name accepte les valeurs alphanumériques, vous utilisez du type de données VARCHAR avec une limite de 50 caractères. Là encore, vous utilisez le MOTEUR de stockage InnoDB pour prendre en charge les transactions.

      Après avoir exécuté la commande précédente pour créer le tableau customers, vous verrez le résultat suivant :

      Output

      Query OK, 0 rows affected (0.02 sec)

      Vous ajouterez trois exemples de clients à la table. Exécutez les commandes suivantes :

      • INSERT INTO customers(customer_name) VALUES ('JOHN DOE');
      • INSERT INTO customers(customer_name) VALUES ('ROE MARY');
      • INSERT INTO customers(customer_name) VALUES ('DOE JANE');

      Une fois que les clients ont été ajoutés, vous verrez un résultat semblable à ce qui suit :

      Output

      Query OK, 1 row affected (0.02 sec) . . .

      Ensuite, vérifiez les données dans le tableau customers :

      Vous verrez une liste des trois clients :

      Output

      +-------------+---------------+ | customer_id | customer_name | +-------------+---------------+ | 1 | JOHN DOE | | 2 | ROE MARY | | 3 | DOE JANE | +-------------+---------------+ 3 rows in set (0.00 sec)

      Ensuite, vous allez créer un tableau orders pour enregistrer les commandes placées par différents clients. Pour créer le tableau orders, exécutez la commande suivante :

      • CREATE TABLE orders (order_id BIGINT AUTO_INCREMENT PRIMARY KEY, order_date DATETIME, customer_id BIGINT, order_total DOUBLE) ENGINE = InnoDB;

      Vous utilisez la colonne order_id comme CLE PRIMAIRE. Le type de données BIGINT vous permet d’enregistrer jusqu’à 2^63-1 commandes et s’incrémentera automatiquement après chaque insertion de commande. Le champ order_date contiendra la date et l’heure réelles de la commande et, par conséquent, vous utilisez le type de données DATETIME.  Le customer_id concerne le tableau customers que vous avez précédemment créé.

      Vous verrez le résultat suivant :

      Output

      Query OK, 0 rows affected (0.02 sec)

      Comme la commande d’un seul client peut contenir plusieurs articles, vous devez créer un tableau orders_products qui contiendra ces informations.

      Pour créer le tableau orders_products, exécutez la commande suivante :

      • CREATE TABLE orders_products (ref_id BIGINT PRIMARY KEY AUTO_INCREMENT, order_id BIGINT, product_id BIGINT, price DOUBLE, quantity BIGINT) ENGINE = InnoDB;

      Vous utilisez le ref_id comme CLÉ PRIMAIRE et celui-ci s’incrémentera automatiquement après chaque insertion d’enregistrement. order_id et product_id correspondent respectivement aux tableaux orders et products. La colonne price est du type de données DOUBLE afin de tenir compte des valeurs flottantes.

      Le moteur de stockage InnoDB doit correspondre aux autres tableaux créés précédemment, car la commande d’un seul client affectera plusieurs tableaux simultanément en utilisant des transactions.

      Votre sortie confirmera la création du tableau :

      Output

      Query OK, 0 rows affected (0.02 sec)

      Vous n’ajouterez aucune donnée aux tableaux orders et orders_products pour l’instant, mais vous le ferez plus tard en utilisant un script PHP qui implémente des transactions MySQL.

      Déconnectez-vous du serveur MySQL :

      Votre schéma de base de données est maintenant complet et vous l’avez rempli avec quelques enregistrements. Vous allez maintenant créer une classe PHP pour gérer les connexions à la base de données et les transactions MySQL.

      Étape 2 — Conception d’une classe PHP pour traiter les transactions MySQL

      Dans cette étape, vous allez créer une classe PHP qui utilisera PDO (PHP Data Objects) pour gérer les transactions MySQL. La classe se connectera à votre base de données MySQL et insèrera des données atomiquement à la base de données.

      Enregistrez le fichier de la classe dans le répertoire racine de votre serveur web Apache. Pour ce faire, créez un fichier DBTransaction.php à l’aide de votre éditeur de texte :

      • sudo nano /var/www/html/DBTransaction.php

      Ensuite, ajoutez le code suivant au fichier. Remplacez PASSWORD par la valeur que vous avez créée à l’étape 1 :

      /var/www/html/DBTransaction.php

      <?php
      
      class DBTransaction
      {
          protected $pdo;
          public $last_insert_id;
      
          public function __construct()
          {
              define('DB_NAME', 'sample_store');
              define('DB_USER', 'sample_user');
              define('DB_PASSWORD', 'PASSWORD');
              define('DB_HOST', 'localhost');
      
              $this->pdo = new PDO("mysql:host=" . DB_HOST . ";dbname=" . DB_NAME, DB_USER, DB_PASSWORD);
              $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
              $this->pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
          }
      

      Vers le début de la classe DBTransaction, le PDO utilisera les constantes (DB_HOST, DB_NAME, DB_USER, et DB_PASSWORD) pour initialiser et se connecter à la base de données que vous avez créée à l’étape 1.

      Remarque : Comme nous démontrons ici des transactions MySQL à petite échelle, nous avons déclaré les variables de la base de données dans la classe DBTransaction. Dans un grand projet de production, vous devriez normalement créer un fichier de configuration séparé et charger les constantes de la base de données à partir de ce fichier en utilisant une déclaration PHP require_once.

      Ensuite, vous définissez deux attributs pour la classe PDO :

      • ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION : cet attribut indique à PDO de lancer une exception si une erreur est rencontrée. De telles erreurs peuvent être enregistrées pour le débogage.
      • ATTR_EMULATE_PREPARES, false : cette option désactive l’émulation des déclarations préparées et permet au moteur de la base de données MySQL de préparer les déclarations lui-même.

      Ajoutez maintenant le code suivant à votre fichier pour créer les méthodes pour votre classe :

      /var/www/html/DBTransaction.php

      . . .
          public function startTransaction()
          {
              $this->pdo->beginTransaction();
          }
      
          public function insertTransaction($sql, $data)
          {
              $stmt = $this->pdo->prepare($sql);
              $stmt->execute($data);
              $this->last_insert_id = $this->pdo->lastInsertId();
          }
      
          public function submitTransaction()
          {
              try {
                  $this->pdo->commit();
              } catch(PDOException $e) {
                  $this->pdo->rollBack();
                  return false;
              }
      
                return true;
          }
      }
      

      Enregistrez et fermez le fichier en appuyant sur CTRL + X, Y, puis sur ENTER.

      Pour travailler avec les transactions MySQL, vous créez trois méthodes principales dans la classe DBTransaction : startTransaction, insertTransaction et submitTransaction.

      • startTransaction : cette méthode demande à PDO de démarrer une transaction et désactive l’auto-validation jusqu’à ce qu’une commande de validation soit émise.

      • insertTransaction : cette méthode prend deux arguments. La variable $sql contient l’instruction SQL à exécuter tandis que la variable $data est un tableau des données à lier à l’instruction SQL puisque vous utilisez des déclarations préparées. Les données sont transmises sous forme de tableau à la méthode insertTransaction.

      • submitTransaction : Cette méthode valide les modifications apportées à la base de données de manière permanente en lançant une commande commit(). Cependant, s’il y a une erreur et que les transactions rencontrent un problème, la méthode appelle la méthode rollBack() pour remettre la base de données dans son état initial au cas où une exception PDO serait soulevée.

      Votre classe DBTransaction initialise une transaction, prépare les différentes commandes SQL à exécuter, et enfin valide les modifications de la base de données de manière atomique s’il n’y a pas de problème, sinon, la transaction est annulée. De plus, la classe vous permet de récupérer l’enregistrement order_id que vous venez de créer en accédant à la propriété publique last_insert_id.

      La classe DBTransaction est maintenant prête à être appelée et utilisée par n’importe quel code PHP, que vous allez créer ensuite.

      Étape 3 — Création d’un script PHP pour utiliser la classe DBTransaction

      Vous allez créer un script PHP qui implémentera la classe DBTransaction et enverra un groupe de commandes SQL à la base de données MySQL. Vous imiterez le déroulement de la commande d’un client dans un panier d’achat en ligne.

      Ces requêtes SQL affecteront les tableaux orders et orders_products. Votre classe DBTransaction ne devrait permettre de modifier la base de données que si toutes les requêtes sont exécutées sans aucune erreur.  Dans le cas contraire, vous obtiendrez un retour d’erreur et toute tentative de modification sera annulée.

      Vous créez une commande unique pour le client JOHN DOE identifié avec le customer_id 1.La commande du client comporte trois articles différents avec des quantités différentes du tableau products. Votre script PHP prend les données de la commande du client et les soumet dans la classe DBTransaction.

      Créez le fichier orders.php :

      • sudo nano /var/www/html/orders.php

      Ensuite, ajoutez le code suivant au fichier :

      /var/www/html/orders.php

      <?php
      
      require("DBTransaction.php");
      
      $db_host = "database_host";
      $db_name = "database_name";
      $db_user = "database_user";
      $db_password = "PASSWORD";
      
      $customer_id = 2;
      
      $products[] = [
        'product_id' => 1,
        'price' => 25.50,
        'quantity' => 1
      ];
      
      $products[] = [
        'product_id' => 2,
        'price' => 13.90,
        'quantity' => 3
      ];
      
      $products[] = [
        'product_id' => 3,
        'price' => 45.30,
        'quantity' => 2
      ];
      
      $transaction = new DBTransaction($db_host, $db_user, $db_password, $db_name);
      

      Vous avez créé un script PHP qui initialise une instance de la classe DBTransaction que vous avez créée à l’étape 2.

      Dans ce script, vous incluez le fichier DBTransaction.php et vous initialisez la classe DBTransaction. Ensuite, vous préparez un tableau multidimensionnel de tous les produits que le client commande dans le magasin. Vous invoquez également la méthode startTransaction() pour lancer une transaction.

      Ensuite, ajoutez le code suivant pour terminer votre script orders.php :

      /var/www/html/orders.php

      . . .
      $order_query = "insert into orders (order_id, customer_id, order_date, order_total) values(:order_id, :customer_id, :order_date, :order_total)";
      $product_query = "insert into orders_products (order_id, product_id, price, quantity) values(:order_id, :product_id, :price, :quantity)";
      
      $transaction->insertQuery($order_query, [
        'customer_id' => $customer_id,
        'order_date' => "2020-01-11",
        'order_total' => 157.8
      ]);
      
      $order_id = $transaction->last_insert_id;
      
      foreach ($products as $product) {
        $transaction->insertQuery($product_query, [
          'order_id' => $order_id,
          'product_id' => $product['product_id'],
          'price' => $product['price'],
          'quantity' => $product['quantity']
        ]);
      }
      
      $result = $transaction->submit();
      
      if ($result) {
          echo "Records successfully submitted";
      } else {
          echo "There was an error.";
      }
      
      

      Enregistrez et fermez le fichier en appuyant sur CTRL + X, Y, puis ENTER.

      Vous préparez la commande à insérer dans le tableau orders via la méthode insertTransaction. Après cela, vous récupérez la valeur de la propriété publique last_insert_id de la classe DBTransaction et l’utilisez-comme $order_id.

      Une fois que vous avez un $order_id, vous utilisez l’ID unique pour insérer les éléments de la commande du client dans le tableau orders_products.

      Enfin, vous appelez la méthode submitTransaction pour valider l’ensemble des détails de la commande du client dans la base de données s’il n’y a pas de problème. Dans le cas contraire, la méthode de la submitTransaction annulera les tentatives de modification.

      Vous allez maintenant exécuter le script orders.php dans votre navigateur. Exécutez ce qui suit et remplacez your-server-IP par l’adresse IP publique de votre serveur :

      http://your-server-IP/orders.php

      Vous verrez la confirmation que les enregistrements ont été soumis avec succès :

      Sortie PHP de la classe de transactions MySQL

      Votre script PHP fonctionne comme prévu et la commande ainsi que les produits associés ont été soumis à la base de données de manière atomique.

      Vous avez exécuté le fichier orders.php dans une fenêtre du navigateur. Le script a invoqué la classe DBTransaction qui a à son tour soumis les détails des orders (commandes) à la base de données. Dans l’étape suivante, vous allez vérifier si les enregistrements ont été sauvegardés dans les tableaux correspondants de la base de données.

      Étape 4 — Confirmation des entrées dans votre base de données

      Au cours de cette étape, vous vérifierez si la transaction initiée depuis la fenêtre du navigateur pour la commande du client a été enregistrée dans les tableaux de la base de données comme prévu.

      Pour ce faire, connectez-vous à nouveau à votre base de données MySQL :

      • sudo mysql -u sample_user -p

      Entrez le mot de passe du sample_user et appuyez sur ENTER (ENTRÉE) pour continuer.

      Passez à la base de données sample_store :

      Assurez-vous que la base de données est modifiée avant de poursuivre en confirmant la sortie suivante :

      Output

      Database Changed.

      Ensuite, lancez la commande suivante pour récupérer les enregistrements du tableau orders :

      Cela affichera la sortie suivante détaillant la commande du client :

      Output

      +----------+---------------------+-------------+-------------+ | order_id | order_date | customer_id | order_total | +----------+---------------------+-------------+-------------+ | 1 | 2020-01-11 00:00:00 | 2 | 157.8 | +----------+---------------------+-------------+-------------+ 1 row in set (0.00 sec)

      Ensuite, récupérez les enregistrements du tableau orders_products :

      • SELECT * FROM orders_products;

      Vous verrez une sortie semblable à celle qui suit avec une liste de produits de la commande du client :

      Output

      +--------+----------+------------+-------+----------+ | ref_id | order_id | product_id | price | quantity | +--------+----------+------------+-------+----------+ | 1 | 1 | 1 | 25.5 | 1 | | 2 | 1 | 2 | 13.9 | 3 | | 3 | 1 | 3 | 45.3 | 2 | +--------+----------+------------+-------+----------+ 3 rows in set (0.00 sec)

      Le résultat confirme que la transaction a été enregistrée dans la base de données et que la classe DBTransaction de votre assistant fonctionne comme prévu.

      Conclusion

      Dans ce guide, vous avez utilisé le PDO PHP pour travailler avec des transactions MySQL. Bien que cet article ne soit pas exhaustif sur la conception d’un logiciel de commerce électronique, il a fourni un exemple d’utilisation des transactions MySQL dans vos applications.

      Pour en apprendre davantage sur le modèle ACID de MySQL, pensez à consulter le guide InnoDB et le modèle ACID sur le site officiel de MySQL. Consultez notre page de contenu MySQL pour d’autres tutoriels, articles et Questions & Réponses.



      Source link