PHP Design Patterns: Table Data Gateway [Português - Brasil]

Antonio Silva - Sep 14 '23 - - Dev Community

O que seria o Table Data Gateway?

Table Data Gateway é um padrão de projeto no qual é representado por uma classe que executa o transporte dos dados entre a aplicação e a base de dados. Assim é classe têm como operações apenas métodos de persistência, ou seja de gravação de dados.

Classe Gateway

Teremos também outra classe, sendo ela a de negocio da aplicação usando a classe de gateway sempre que precisar buscar ou salvar dados no banco de dados.

Classe Produto

Na maioria dos casos, um Table Data Gateway lida com um modelo relacional, tendo um relacionamento 1: 1 com as tabelas principais do banco de dados.

Relacionamento

Exemplo

Etapa 1 - Sistema de diretórios:

📦Table_Data_Gateway
 ┣ 📂classes
 ┃ ┣ 📜Produto.php
 ┃ ┗ 📜ProdutoGateway.php
 ┣ 📂config
 ┃ ┗ 📜config.ini
 ┣ 📂database
 ┃ ┗ 📜produto.db
 ┗ 📜index.php
Enter fullscreen mode Exit fullscreen mode

Etapa 2 - Arquivo de configuração do banco de dados:

host = 
name = database/product.db
user = 
pass = 
type = sqlite
Enter fullscreen mode Exit fullscreen mode

Etapa 3 - Banco de dados:

CREATE TABLE produto(
  id INTEGER PRIMARY KEY NOT NULL,
  descricao TEXT,
  estoque FLOAT,
  preco_custo FLOAT,
  preco_venda FLOAT,
  codigo_barras TEXT,
  data_registro DATE,
  origem CHAR(1)
);
Enter fullscreen mode Exit fullscreen mode

Etapa 4 - Classe ProdutoGateway:

<?php

    class ProdutoGateway
    {

        private static $conn;

        public function __construct()
        {

        }

        public static function setConnection(PDO $conn)
        {
            self::$conn = $conn;
        }

        public function find($id, $class = 'stdClass')
        {
            $sql = "SELECT * FROM produto WHERE id = '$id'";
            print "$sql <br>";
            $result = self::$conn->query($sql);
            return $result->fetchObject($class);
        }

        public function all($filter = '', $class = 'stdClass')
        {
            $sql = "SELECT * FROM produto";

            if( $filter )
            {
                $sql .= " WHERE $filter";
            }

            print "$sql <br>";
            $result = self::$conn->query($sql);
            return $result->fetchAll(PDO::FETCH_CLASS, $class);

        }

        public function delete($id)
        {
            $sql = "DELETE FROM produto WHERE id = '$id'";
            print "$sql <br>";
            return self::$conn->query($sql);
        }

        public function save($data)
        {

            if( empty($data->id) )
            {
                $sql = "INSERT INTO produto
                                (descricao, estoque, preco_custo, preco_venda, codigo_barras, data_cadastro, origem)
                                VALUES
                                ('{$data->descricao}',{$data->estoque},{$data->preco_custo},{$data->preco_venda},
                                    {$data->codigo_barras},'{$data->data_cadastro}','{$data->origem}')";
            }
            else
            {
                $sql = "UPDATE produto SET 
                                descricao = '{$data->descricao}', estoque = '{$data->estoque}', preco_custo = '{$data->preco_custo}',
                                preco_venda = '{$data->preco_venda}', codigo_barras = '{$data->codigo_barras}', data_cadastro = '{$data->data_cadastro}',
                                origem = '{$data->origem}'
                                WHERE id = '{$data->id}'";
            }

            print "$sql <br>";
            return self::$conn->exec($sql);

        }

    }
Enter fullscreen mode Exit fullscreen mode

Etapa 5 - Classe de produto:

<?php

    class Produto
    {

        private $data;

        public function __construct()
        {

        }

        public static function setConnection( PDO $conn)
        {
            ProdutoGateway::setConnection($conn);
        }

        public function __get($prop)
        {
            return $this->data[$prop];
        }

        public function __set($prop, $value)
        {
            $this->data[$prop] = $value;
        }

        public static function find($id)
        {
            $gw = new ProdutoGateway;
          return $gw->find($id, 'Produto');
        }

        public static function all($filter = '')
        {
            $gw = new ProdutoGateway;
          return $gw->all($filter, 'Produto');
        }

        public function save()
        {
            $gw = new ProdutoGateway;
            return $gw->save( (object) $this->data);
        }

        public function delete()
        {
            $gw =  new ProdutoGateway;
            return $gw->delete($this->id);
        }

        public function getMargemLucro()
        {
            return (($this->preco_venda - $this->preco_custo)/$this->preco_custo)*100;
        }

        public function registrarCompra($custo, $quantidade)
        {
            $this->preco_custo = $custo;
            $this->estoque += $quantidade;
        }

    }
Enter fullscreen mode Exit fullscreen mode

Teste

<?php

    require_once 'class/Product.php';
    require_once 'class/ProductGateway.php';

    try
    {
        $ini = parse_ini_file('config/config.ini');
        $dbname = $ini['name'];

        $conn = new PDO('sqlite:'.$dbname);
        $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

        Produto::setConnection($conn);
        $produto = new Produto;

    }
    catch(Exception $e)
    {
        print $e->getMessage();
    }
Enter fullscreen mode Exit fullscreen mode

Gravando um produto no banco de dados:

$produto->descricao = 'Suco';
$produto->estoque = 8;
$produto->preco_custo = 12;
$produto->preco_venda = 18;
$produto->codigo_barras = '123123123';
$produto->origem = 'S';
$produto->data_registro = date('Y-m-d');
$produto->save();
Enter fullscreen mode Exit fullscreen mode

Atualizando um produto do banco de dados:

$update = $produto::find(1);
$update->descricao = "Suco de Uva";
$update->save($produto); 
Enter fullscreen mode Exit fullscreen mode

Listando Produtos:

foreach( $produto::all() as $p )
{
  print $p->descricao . ' ';
  print $p->preco_custo . ' ';
  print $p->preco_venda . "<br>";
}
Enter fullscreen mode Exit fullscreen mode

Métodos de negócios:

$p = $produto::find(1);
$p->registrarCompra(24,2); //(custo,quantidade)
$p->save($produto);

print $p->getMargemLucro();
Enter fullscreen mode Exit fullscreen mode
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .