PHP Design Patterns: Table Data Gateway [Português - Brasil]
Tags: php, braziliandevs
Published: 2023-09-14 17:32:57

## 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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hwf0wn5qfvy22a759gel.png)

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uye966k7dp0vcd0cnb89.png)

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uxk8danqdxvroeoemnry.png)

## Exemplo

**Etapa 1 - Sistema de diretórios:**
```
📦Table_Data_Gateway
 ┣ 📂classes
 ┃ ┣ 📜Produto.php
 ┃ ┗ 📜ProdutoGateway.php
 ┣ 📂config
 ┃ ┗ 📜config.ini
 ┣ 📂database
 ┃ ┗ 📜produto.db
 ┗ 📜index.php
```
**Etapa 2 - Arquivo de configuração do banco de dados:**

```bash
host = 
name = database/product.db
user = 
pass = 
type = sqlite
```
**Etapa 3 - Banco de dados:**

```sql
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)
);
```
**Etapa 4 - Classe ProdutoGateway:**

```php
<?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);

		}

	}
```
**Etapa 5 - Classe de produto:**

```php
<?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;
		}

	}
```

## Teste

```php
<?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();
    }
```
**Gravando um produto no banco de dados:**

```php
$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();
```
**Atualizando um produto do banco de dados:**

```php
$update = $produto::find(1);
$update->descricao = "Suco de Uva";
$update->save($produto); 
```
**Listando Produtos:**

```php
foreach( $produto::all() as $p )
{
  print $p->descricao . ' ';
  print $p->preco_custo . ' ';
  print $p->preco_venda . "<br>";
}
```
**Métodos de negócios:**

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

print $p->getMargemLucro();
```