One place for hosting & domains

      realizar

      Cuatro métodos para realizar búsqueda a través de matrices en JavaScript


      En JavaScript, hay muchas maneras útiles de encontrar elementos en matrices. Siempre puede recurrir al bucle básico for, pero con ES6+ hay muchos métodos para recorrer la matriz y encontrar lo que necesita con facilidad.

      Con tantos métodos diferentes, ¿cuál se debería utilizar y en qué caso? Por ejemplo, al realizar una búsqueda en una matriz, ¿quiere saber si un elemento específico está en la matriz? ¿Necesita el índice del elemento o el elemento en sí?

      Con cada método diferente que cubriremos, es importante comprender que todos estos métodos están integrados en Array.prototype. Eso significa que simplemente necesita encadenarlos a cualquier matriz con notación de punto. Esto también significa que estos métodos no están disponibles en objetos o cualquier otra cosa que no sean matrices (aunque hay superposición con cadenas).

      Observemos los siguientes métodos de matriz:

      includes

      const alligator = ["thick scales", 80, "4 foot tail", "rounded snout"];
      
      alligator.includes("thick scales"); // returns true
      

      El método .includes() devuelve un valor booleano y es ideal para indicarle si un elemento existe o no en una matriz. Da una simple respuesta de verdadero true o falso false. Esta es la sintaxis básica:

      arr.includes(valueToFind, [fromIndex]);
      

      Como ve en nuestro ejemplo, solo obtuvimos un parámetro: valueToFind. Este es el valor que debe coincidir en la matriz. El valor opcional fromIndex es un número que indica qué índice debería comenzar a buscar (por defecto es 0, por lo que realiza una búsqueda en toda la matriz). Por lo tanto, dado que en nuestro ejemplo el elemento ‘thick scales’ está en el índice 0, lo siguiente sería falso: alligator.includes('thick scales', 1); ya que comienza a buscar desde el índice 1 en adelante.

      Ahora, hay algunas cosas importantes a tener en cuenta. Este método .includes() utiliza una comparación estricta. Eso significa que, del ejemplo anterior, lo siguiente debería devolver falso: alligator.includes('80'); eso se debe a que aunque 80 == '80' es verdadero, 80 === '80' es falso: diferentes tipos no pasarán la comparación estricta.

      find

      ¿Cuál es la diferencia entre los métodos .find() e includes()? Si en nuestro ejemplo solo cambiamos el texto “includes” por “find”, obtendremos este error:

      Uncaught TypeError: thick scales is not a function
      

      Eso se debe a que el método find requiere una función para ser aprobado. Esto se debe a que el método find no usa solo el operador de comparación simple como en el caso del método “includes()”. En vez de eso, pasará cada elemento a su función y verá si devuelve verdadero o falso. Aunque esto funcione: alligator.find(() => 'thick scales');, probablemente sea recomendable poner su propio operador de comparación en la función para que devuelva cualquier valor relevante.

      const alligator = ["thick scales", 80, "4 foot tail", "rounded snout"];
      
      alligator.find(el => el.length < 12); // returns '4 foot tail'
      

      Esta sencilla función en nuestro método find busca cada elemento de la matriz, con el alias de ‘el’ que se le asigne y se detiene cuando encuentra el primero que sea verdadero. En nuestro caso, verdadero tiene una propiedad de longitud inferior a 12 (los números no tienen una propiedad de longitud). Por supuesto, puede hacer que esta función sea tan compleja como sea necesario, haciendo que su condición de verdadero se ajuste a sus necesidades.

      Observe también que esto no devolvió true. El método find no devuelve un booleano, pero en vez de eso devuelve el primer elemento que coincida. Si no hay un elemento que coincida, ya que no hay nada que cumpla con los criterios definidos en su función, devolverá undefined. También tenga en cuenta que devuelve solo la primera coincidencia, por lo que si hay más de un elemento en la matriz que cumpla con los criterios, solo obtendrá la primera de ellas. En nuestro ejemplo, si hubiera otra cadena de longitud inferior a 12 después de ‘4 foot tall’, no cambiaría nuestro resultado.

      En nuestro ejemplo, solo usamos la devolución de llamada con un parámetro. También puede añadir parámetros para hacer referencia al índice del elemento actual. Otro parámetro puede ser toda la matriz por sí misma, pero se usa de manera muy poco frecuente. Aquí hay un ejemplo usando el índice:

      alligator.find((el, idx) => typeof el === "string" && idx === 2); // returns '4 foot tall'
      

      Sabemos que en nuestra matriz, hay 3 elementos diferentes que cumplen la primera condición (typeof el === ‘string’). Si esa fuera nuestra única condición, devolverá la primera, ‘thick scales’. Pero la diferencia es que solo uno tiene el índice de 2, es decir ‘4 foot tall’.

      Hablando de índices, un método de matriz similar es .findIndex(). Este método también recibe una función, pero como se podrá imaginar, devuelve el índice del elemento que coincida en vez del elemento en sí.

      indexOf

      const alligator = ["thick scales", 80, "4 foot tail", "rounded snout"];
      
      alligator.indexOf("rounded snout"); // returns 3
      

      Al igual que el método .includes(), .indexOf() utiliza una comparación estricta, no una función como en el caso del método .find(). Pero, a diferencia de includes(), devuelve el índice del elemento, en vez de un booleano. También puede indicar a partir de qué índice en la matriz comenzar a buscar.

      indexOf() es un método muy útil. Es rápido y fácil, puede decirle dónde se encuentra el elemento en la matriz y puede indicar si dicho elemento existe. ¿Cómo le indica si el elemento existe? Básicamente, podemos saber que el elemento existe si devuelve un número positivo y si devuelve -1, indicaría que el elemento no existe.

      alligator.indexOf("soft and fluffy"); // returns -1
      alligator.indexOf(80); // returns 1
      alligator.indexOf(80, 2); // returns -1
      

      Como se puede ver, si bien podríamos usar los métodos find() o findIndex() para darnos la misma información, en este método se escribe mucho menos. No tenemos que escribir una función para realizar la comparación, ya que ya está dentro del método indexOf.

      Al igual que los demás métodos, indexOf() también devuelve el índice del primer elemento que encuentra. JavaScript nos proporciona un método de matriz alternativo .lastIndexOf(). Como se podrá imaginar, este método hace lo mismo que indexOf(), pero a partir del último índice de la matriz y funciona al revés. También puede especificar un segundo parámetro, pero recuerde que los índices no cambian solo por el hecho de usar un método diferente.

      const alligator = ["thick scales", 80, "4 foot tail", "rounded snout", 80];
      
      alligator.indexOf(80); // returns 1
      alligator.lastIndexOf(80); // returns 4
      alligator.indexOf(80, 2); // returns 4
      alligator.lastIndexOf(80, 4); // returns 4
      alligator.lastIndexOf(80, 3); // returns 1
      

      Bonus: filter

      const alligator = ["thick scales", 80, "4 foot tail", "rounded snout", 80];
      
      alligator.filter(el => el === 80); //returns [80, 80]
      

      El método filter() es como el método find(), en el sentido de que requiere una función pasada y una condición para lo que se devolverá. La principal diferencia es que filter() siempre devuelve una matriz, incluso si solo hay un elemento que coincida. Pero devolverá todos los elementos que coincidan, mientras que find() solo devuelve la primera coincidencia.

      Lo importante de filter es que devuelve todos los elementos que coinciden con sus criterios. Podría ser mi punto de vista, pero uno se podría confundir pensando “estos son los elementos que quiero filtrar out”, cuando realmente está indicando los elementos que desea filtrar in.

      Conclusión

      El método que me parece más sencillo de utilizar al realizar una búsqueda es el método find(), pero, como podrá ver, en realidad depende de su caso.

      • ¿Solo necesita saber si existe? Utilice .includes().
      • ¿Necesita obtener el elemento en sí? Utilice .find() o .filter() para buscar varios elementos.
      • ¿Necesita encontrar el índice del elemento? Utilice .indexOf() o findIndex() para realizar una búsqueda más compleja.

      Las matrices en los ejemplos presentados aquí fueron muy sencillas. Es posible que se encuentre con una matriz de objetos. A continuación, presentamos algunos ejemplos básicos para navegar por la jungla de objetos anidados:

      const jungle = [
        { name: "frog", threat: 0 },
        { name: "monkey", threat: 5 },
        { name: "gorilla", threat: 8 },
        { name: "lion", threat: 10 }
      ];
      
      // break the object down in order to use .includes() or .indexOf()
      const names = jungle.map(el => el.name); // returns ['frog', 'monkey', 'gorilla', 'lion']
      console.log(names.includes("gorilla")); // returns true
      console.log(names.indexOf("lion")); // returns 3 - which corresponds correctly assuming no sorting was done
      
      // methods we can do on the array of objects
      console.log(jungle.find(el => el.threat == 5)); // returns object - {name: "monkey", threat: 5}
      console.log(jungle.filter(el => el.threat > 5)); // returns array - [{name: "gorilla", threat: 8}, {name: 'lion', threat: 10}]
      



      Source link

      Como usar o .map() para realizar iterações em itens de matrizes em JavaScript


      Introdução

      Desde o método forloop clássico, até o forEach(), diversas técnicas e métodos são usados para realizar iterações em conjuntos de dados em JavaScript. Um dos métodos mais populares é o método .map(). O .map() cria uma matriz depois de chamar uma função específica em cada item na matriz mãe. O .map() é um método de não mutação que, ao contrário dos métodos de mutação, cria uma nova matriz ao invés de alterar a original.

      Esse método pode ser usado de diversas maneiras ao se trabalhar com matrizes. Neste tutorial, vamos analisar quatro usos dignos de atenção do .map() em JavaScript: chamar uma função de elementos de matriz, converter strings em matrizes, renderizar listas em bibliotecas do JavaScript e reformatar objetos de matriz.

      Pré-requisitos

      Este tutorial não exige nenhuma programação, mas se estiver interessado em acompanhar os exemplos, use o Node.js REPL ou ferramentas de desenvolvedor de um navegador.

      Passo 1 — Chamando uma função em cada item em uma matriz

      O .map() aceita uma função de retorno de chamada como um de seus argumentos, e um parâmetro importante dessa função é o valor atual do item que está sendo processado pela função. Esse parâmetro é necessário. Com esse parâmetro, é possível modificar cada item em uma matriz e criar uma nova função.

      Vejamos um exemplo:

      const sweetArray = [2, 3, 4, 5, 35]
      const sweeterArray = sweetArray.map(sweetItem => {
          return sweetItem * 2
      })
      
      console.log(sweeterArray)
      

      Este é o resultado que é registrado no console:

      Output

      [ 4, 6, 8, 10, 70 ]

      Ele pode ser simplificado para torná-lo mais organizado:

      // create a function to use
      const makeSweeter = sweetItem => sweetItem * 2;
      
      // we have an array
      const sweetArray = [2, 3, 4, 5, 35];
      
      // call the function we made. more readable
      const sweeterArray = sweetArray.map(makeSweeter);
      
      console.log(sweeterArray);
      

      O mesmo resultado é registrado no console:

      Output

      [ 4, 6, 8, 10, 70 ]

      Possuir código como sweetArray.map(makeSweeter) torna seu código um pouco mais legível.

      Passo 2 — Convertendo uma string em uma matriz

      O .map() é conhecido por pertencer ao protótipo da matriz. Neste passo, você irá usá-lo para converter uma string em uma matriz. Você não está desenvolvendo o método para trabalhar com strings aqui. Em vez disso, você irá usar o método especial .call().

      Tudo no JavaScript é um objeto, e os métodos são funções ligadas a esses objetos. O .call() permite que você use o contexto de um objeto em outro. Portanto, o contexto do .map() em uma matriz estaria sendo copiado para uma string.

      O .call() pode representar argumentos passados do contexto a ser usado e parâmetros para os argumentos da função original.

      Vejamos um exemplo:

      const name = "Sammy"
      const map = Array.prototype.map
      
      const newName = map.call(name, eachLetter => {
          return `${eachLetter}a`
      })
      
      console.log(newName)
      

      Este é o resultado que é registrado no console:

      Output

      • [ "Sa", "aa", "ma", "ma", "ya" ]

      Aqui, você usou o contexto do .map() em uma string e passou um argumento da função que o .map() espera.

      Isso funciona de maneira semelhante ao método .split() de uma string, com a diferença que cada caractere da string pode ser modificado antes de ser retornado a uma matriz.

      Passo 3 — Renderizando listas em bibliotecas do JavaScript

      Bibliotecas do JavaScript como o React utilizam o .map() para renderizar itens em uma lista. No entanto, isso exige a sintaxe JSX, uma vez que o método .map() consiste de sintaxe JSX.

      Aqui está um exemplo de um componente do React:

      import React from "react";
      import ReactDOM from "react-dom";
      
      const names = ["whale", "squid", "turtle", "coral", "starfish"];
      
      const NamesList = () => (
        <div>
          <ul>{names.map(name => <li key={name}> {name} </li>)}</ul>
        </div>
      );
      
      const rootElement = document.getElementById("root");
      ReactDOM.render(<NamesList />, rootElement);
      

      Esse é um componente sem estado no React, que renderiza um div com uma lista. Os itens individuais da lista são renderizados usando o .map() para iterar na matriz de nomes inicialmente criada. Esse componente é renderizado usando o ReactDOM no elemento DOM com Id de root.

      Passo 4 — Reformatando objetos de matriz

      O .map() pode ser usado para iterar em objetos de uma matriz e, de maneira semelhante às matrizes tradicionais, modificar individualmente o conteúdo de cada objeto e retornar uma nova matriz. Essa modificação é feita com base no que é retornado na função de retorno de chamada.

      Vejamos um exemplo:

      const myUsers = [
          { name: 'shark', likes: 'ocean' },
          { name: 'turtle', likes: 'pond' },
          { name: 'otter', likes: 'fish biscuits' }
      ]
      
      const usersByLikes = myUsers.map(item => {
          const container = {};
      
          container[item.name] = item.likes;
          container.age = item.name.length * 10;
      
          return container;
      })
      
      console.log(usersByLikes);
      

      Este é o resultado que é registrado no console:

      Output

      [ {shark: "ocean", age: 50}, {turtle: "pond", age: 60}, {otter: "fish biscuits", age: 50} ]

      Aqui, você modificou cada objeto na matriz usando a notação de chaves e pontos. Esse caso de uso pode ser empregado para processar ou condensar dados recebidos antes de serem salvos ou analisados por um aplicativo frontend.

      Conclusão

      Nesse tutorial, analisamos quatro usos do método .map() em JavaScript. Em combinação com outros métodos, a funcionalidade do .map() pode ser estendida. Para mais informações, consulte nosso artigo Como usar métodos de matriz em JavaScript: métodos de iteração.



      Source link

      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