JAMES WEB

Aprenda como se faz.


Sumário

Produtos CRUD (Editar)

Na página denominada “Lista de Produtos” no painel administrativo, observa-se a presença do botão “Editar” em cada entrada de produto exibida. Ao acionar tal botão, o sistema redireciona o usuário para o endereço “/admin/products_get/:idproduct”, onde se possibilita a modificação dos dados pertinentes ao produto selecionado.

editar-produtos

Editando um produto

Na página denominada “Lista de Produtos” no painel administrativo, observa-se a presença do botão “Editar” em cada entrada de produto exibida. Ao acionar tal botão, o sistema redireciona o usuário para o endereço “/admin/products_get/:idproduct”, onde se possibilita a modificação dos dados pertinentes ao produto selecionado.

PHP: admin-products.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
// inicio código...
 
//Rota Editar Produtos- Template products-update.html
$app->get('/admin/products_get/:idproduct'function($idproduct) { 
    User::verifyLogin(); 
    $product new Product(); 
    $product->get((int)$idproduct);   
    $page new PageAdmin();     
    $page->setTpl("products-update", [
        'product'=>$product->getValues()
    ]);
  });
 
?>

Explicação linha por linha:

  • L 5 – $app->get(‘/admin/products_get/:idproduct’, function($idproduct) {:
    Define uma rota para lidar com requisições HTTP do tipo GET no caminho /admin/products_get/:idproduct.
    • $app->get(): Indica que esta é uma rota que responde a requisições GET.
    • /admin/products_get/:idproduct: Define o padrão da URL.: idproduct é um parâmetro dinâmico, que captura o valor do ID do produto na URL.
    • function($idproduct) { … }: Define uma função anônima que será executada quando a rota for acessada. O parâmetro $idproduct recebe o valor capturado do parâmetro dinâmico na URL.
  • L 6 – User::verifyLogin();:
    Chama o método estático verifyLogin() da classe User. Este método verifica se o usuário está autenticado e logado. Se o usuário não estiver logado, o método pode redirecioná-lo para a página de login ou exibir uma mensagem de erro.
  • L 7 – $product = new Product();:
    Cria uma nova instância da classe Product e a atribui à variável $product. Esta instância representará o produto a ser editado.
  • L 8 – $product->get((int)$idproduct);:
    Chama o método get() do objeto $product, passando o valor de $idproduct convertido para um inteiro. Este método recupera os dados do produto do banco de dados com base no ID fornecido.
  • L 9 – $page = new PageAdmin();:
    Cria uma nova instância da classe PageAdmin e a atribui à variável $page. Esta instância será usada para renderizar a página de edição do produto.
  • L 10 – $page->setTpl(“products-update”, [:
    Chama o método setTpl() do objeto $page. Este método define o template (arquivo HTML) a ser usado para renderizar a página e passa os dados a serem exibidos no template.
    • “products-update”: Especifica o nome do arquivo de template (provavelmente products-update.html).
    • [: Inicia um array associativo que contém os dados a serem passados para o template.
  • L 11 – ‘product’ => $product->getValues():
    Define um elemento no array associativo.
    • ‘product’: A chave do elemento, que estará disponível no template.
    • $product->getValues(): Chama o método getValues() do objeto $product, que retorna um array associativo contendo os dados do produto. Este array será passado para o template.

Método get()

Na linha 8, “$product->get((int)$idproduct);”, nos referimos ao método get(), que recupera os dados do produto do banco de dados com base no ID fornecido. Ele deve ser inserido na classe “Product” conforme exemplos a seguir:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
// Início do código
 
public function get($idproduct)
    {
        $sql new Sql();
        $results $sql->select("SELECT * FROM tb_products WHERE idproduct = :idproduct", [
            ':idproduct' => $idproduct
        ]);
        $this->setData($results[0]);
    }
 
// resto do código
?>

A função get pega um idproduct, consulta o banco de dados para encontrar o produto correspondente e, em seguida, armazena os dados desse produto no objeto atual. É uma função essencial para recuperar informações de produtos em um sistema que utiliza um banco de dados.

Veja a explicação linha por linha

  • L4 – public function get($idproduct)
    • public: Este modificador de acesso indica que a função get pode ser chamada de qualquer lugar, seja dentro da classe ou fora dela. É como abrir as portas da sua casa para receber visitas.
    • function get($idproduct): Aqui, definimos uma função chamada get. Esta função tem um propósito específico: recuperar informações de um produto. O parâmetro $idproduct é o identificador único do produto que desejamos buscar. É como o número de matrícula de um aluno, que o identifica individualmente.
  • L5 – {
    Abre o bloco de código que contém as instruções da função get. É o início do “corpo” da função.
  • L6 – $sql = new Sql();
    Aqui, criamos uma instância da classe Sql. Imagine a classe Sql como uma caixa de ferramentas especializada em interagir com o banco de dados. Ao criar um novo objeto $sql, estamos pegando essa caixa de ferramentas e preparando-a para uso.
  • L7 – $results = $sql->select(“SELECT * FROM tb_products WHERE idproduct = :idproduct”, [ ‘:idproduct’ => $idproduct ]);
    Esta é a linha crucial, onde a magia acontece.
    • $sql->select(…): Chamamos o método select do objeto $sql. Este método é responsável por executar consultas SQL no banco de dados.
    • “SELECT * FROM tb_products WHERE idproduct = :idproduct”: Esta é a consulta SQL em si. Traduzindo para o português, seria algo como “Selecione todas as colunas (*) da tabela tb_products onde o idproduct é igual a um valor específico”. O :idproduct é um marcador de posição, um “buraco” que será preenchido com o valor real do idproduct.
    • [‘:idproduct’ => $idproduct]: Este é o array que fornece o valor para o marcador de posição. Estamos dizendo: “Substitua :idproduct pelo valor da variável $idproduct”. Isso evita ataques de injeção de SQL, uma prática de segurança fundamental.
    • $results = …: O resultado da consulta SQL é armazenado na variável $results. Este resultado é um array de linhas, onde cada linha representa um registro do banco de dados.
  • L5 – $this->setData($results[0]); Aqui, assumimos que a consulta SQL retornou pelo menos uma linha (o produto com o idproduct especificado).
    • $results[0]: Acessamos o primeiro elemento do array $results, que corresponde à primeira linha retornada pela consulta.
    • $this->setData(…): Chamamos o método setData da própria classe. O $this refere-se ao objeto atual. Este método pega os dados do produto (a linha do banco de dados) e os armazena em propriedades do objeto, tornando-os acessíveis para outras partes do código.
  • L11 – } Fecha o bloco de código da função get.

Função getValues()

Na linha 11 em “admin-produts.php” temos a função getValues() que deve ser reproduzida na Classe Product. Veja o exemplo a seguir:

1
2
3
4
5
6
7
8
9
10
11
12
<?php
// Início do código
 
public function getValues()
    {
        $this->checkPhoto();
        $values = parent::getValues();
        return $values;
    }
 
// resto do código
?>

Veja a seguir a explicação linha por linha do código. Observe que a função verifica a existência de uma imagem para o produto cadastrado:

  • L4 : public function getValues()
    • public: Novamente, o modificador public indica que essa função pode ser chamada de qualquer lugar.
    • function getValues(): Definimos uma função chamada getValues. O nome sugere que ela retorna um conjunto de valores, provavelmente as propriedades de um objeto.
  • L5 : {
    Abre o bloco de código da função.
  • L6 : $this->checkPhoto();
    Esta linha chama o método checkPhoto() dentro do objeto atual (representado por $this). CheckPhoto() realiza uma verificação se um arquivo de foto existe. Se sim ele retorna uma foto relacionada ao produto, se não retorna uma imagem padrão.
  • L7 : $values = parent::getValues();
    Aqui, estamos chamando o método getValues() da classe pai (superclasse) do objeto atual. Isso sugere que a classe atual herda de outra classe que já possui um método getValues(). A classe pai define um conjunto básico de valores que são comuns a todas as classes filhas. O resultado desse método é armazenado na variável $values. Em outras palavras, ele busca os valores da classe pai, e armazena eles na variavel $values.
  • L8 : return $values;
    Finalmente, a função retorna o valor armazenado em $values. Este valor contém os valores obtidos da classe pai.
  • L9 : }
    Fecha o bloco de código da função.

Tratando as imagens dos produtos

A ausência de imagem no cadastro de produtos é permitida. A função checkPhoto() lida com essa eventualidade, exibindo um placeholder (painel cinza) quando necessário. Para permitir o upload de imagens personalizadas, o campo ‘Foto’ inclui o botão ‘Escolher Ficheiro’. Este processa e exibe imagens selecionadas localmente. Para implementar essa funcionalidade, insira os códigos abaixo na classe Products em Products.php.

Função checkPhoto()

Dentro do diretório ‘res/site/img/products/’, a função checkPhoto() busca uma imagem relacionada ao ID do produto. Se a busca falhar, uma imagem padrão é utilizada. O caminho da imagem resultante (armazenado na variável $url) é então definido como a foto do produto, através do método setdesphoto($url).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
// Início do código
 
public function checkPhoto()
    {
        if (file_exists(
            $_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR .
                "ecommerce" . DIRECTORY_SEPARATOR .
                "res" . DIRECTORY_SEPARATOR .
                "site" . DIRECTORY_SEPARATOR .
                "img" . DIRECTORY_SEPARATOR .
                "products" . DIRECTORY_SEPARATOR .
                $this->getidproduct() . ".jpg"
        )) {
            $url "/ecommerce/res/site/img/products/" $this->getidproduct() . ".jpg";
        else {
            $url "/ecommerce/res/site/img/product.jpg";
        }
        return $this->setdesphoto($url);
    }
 
// resto do código
?>

Veja a explicação linha por linha do código:

  • L4 : public function checkPhoto()
    • public: Indica que a função checkPhoto() pode ser chamada de qualquer lugar, dentro ou fora da classe.
    • function checkPhoto(): Define a função checkPhoto(), cujo propósito é verificar e definir a foto de um produto.
  • L5 : {
    Abre o bloco de código que contém as instruções da função.
  • L6 : if (file_exists(
    Inicia uma estrutura condicional if. A função file_exists() verifica se um arquivo ou diretório existe.
  • L7 : $_SERVER[‘DOCUMENT_ROOT’] . DIRECTORY_SEPARATOR .
    • $_SERVER[‘DOCUMENT_ROOT’]: Obtém o caminho absoluto do diretório raiz do servidor web.
    • DIRECTORY_SEPARATOR: Constante que representa o separador de diretórios do sistema operacional (por exemplo, “/” em Linux/macOS e “” em Windows). Isso garante que o código seja compatível com diferentes sistemas.
    • .: O operador de concatenação em PHP, que une as strings.
  • L8 : “ecommerce” . DIRECTORY_SEPARATOR .
    Adiciona o diretório “ecommerce” ao caminho.
  • L9 : “res” . DIRECTORY_SEPARATOR .
    Adiciona o diretório “res” (recursos) ao caminho.
  • L10 : “site” . DIRECTORY_SEPARATOR .
    Adiciona o diretório “site” ao caminho.
  • L10 : “img” . DIRECTORY_SEPARATOR .
    Adiciona o diretório “img” (imagens) ao caminho.
  • L10 : “products” . DIRECTORY_SEPARATOR .
    Adiciona o diretório “products” ao caminho.
  • L10 : $this->getidproduct() . “.jpg”
    Chama o método getidproduct() do objeto atual ($this), que provavelmente retorna o ID do produto. “.jpg”: Concatena a extensão “.jpg” ao ID do produto, formando o nome completo do arquivo da imagem.
  • L15 : $url = “/ecommerce/res/site/img/products/” . $this->getidproduct() . “.jpg”;
    Se o arquivo existir, constrói a URL da imagem com base no ID do produto. Essa URL será usada para exibir a imagem.
  • L16 : Linha 14: } else {
    Inicia o bloco else, que será executado se o arquivo não existir.
  • L17 : $url = “/ecommerce/res/site/img/product.jpg”;
    Se o arquivo não existir, define a URL para a imagem padrão “product.jpg”.
  • L18 : }
    Fecha o bloco else.
  • L19 : return $this->setdesphoto($url);
    Chama o método setdesphoto() do objeto atual, passando a URL da imagem ($url) como argumento. Esse método Retorna o resultado da chamada de setdesphoto().
  • L20 : }
    Fecha o bloco de código da função checkPhoto().

Persistência de Dados do Produto Editado

Após a modificação dos dados do produto, a etapa subsequente é a persistência dessas alterações. Isso é alcançado através do envio de uma requisição HTTP do tipo POST para o endpoint /admin/products/:idproduct. O :idproduct representa um parâmetro dinâmico, substituído pelo identificador único do produto em questão.

A implementação dessa funcionalidade requer a inserção do seguinte trecho de código no arquivo admin_products.php:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
/// início do código
 
//Rota Salvar Edição Produtos- Template products-update.html
$app->post('/admin/products_post/:idproduct'function($idproduct) { 
    User::verifyLogin(); 
    $product new Product(); 
    $product->get((int)$idproduct);   
    $product->setTpl($_POST);
    $product->save();
    $product->setPhoto($_FILES["file"]);
    header("Location: /ecommerce/admin/products");
    exit;
  });
 
// restodo código
?>  

Veja a explicação linha por linha:

  • L5: $app->post(‘/admin/products_post/:idproduct’, function($idproduct) {
    Esta linha inicia a definição de uma rota no aplicativo web.
    • $app->post(): indica que esta rota responde a requisições HTTP do tipo POST. Este tipo de requisição é comumente usado para enviar dados para o servidor, como em formulários de envio.
    • ‘/admin/products_post/:idproduct’: define o caminho da rota. :idproduct é um parâmetro dinâmico, ou seja, pode variar dependendo do ID do produto que está sendo processado.
    • function($idproduct) {: inicia uma função anônima que será executada quando a rota for acessada. $idproduct é o parâmetro que recebe o valor dinâmico do ID do produto.
  • L6: User::verifyLogin();
    Esta linha chama um método estático verifyLogin() da classe User. Este método tem a responsabilidade de verificar se o usuário está autenticado e tem permissão para acessar esta rota. Trata-se de uma medida de segurança essencial para proteger áreas administrativas do sistema.
  • L7: $product = new Product();
    Aqui, um novo objeto da classe Product é instanciado. A classe Product representa um produto no sistema e contém os atributos e métodos necessários para manipular os dados do produto.
  • L8: $product->get((int)$idproduct);
    Este trecho chama o método get() do objeto $product, passando o $idproduct como argumento. O (int) garante que o $idproduct seja convertido para um número inteiro, prevenindo erros. O método get() recupera os dados do produto correspondente ao $idproduct do banco de dados e os armazena no objeto $product.
  • L9: $product->setTpl($_POST);
    O método setTpl() do objeto $product é chamado, passando o array $_POST como argumento. $_POST contém os dados enviados pelo formulário na requisição POST. setTpl() atualiza os atributos do objeto $product com os valores recebidos do formulário.
  • L10: $product->save();
    Este trecho invoca o método save() do objeto $product. save() persiste as alterações feitas no objeto $product no banco de dados.
  • L11: $product->setPhoto($_FILES[“file”]);
    O método setPhoto() do objeto $product é chamado, passando o array $_FILES[“file”] como argumento.$_FILES[“file”] contém os dados do arquivo enviado pelo usuário, neste caso, uma foto. O método setPhoto() processa o arquivo e o associa ao produto.
  • L12:header(“Location: /ecommerce/admin/products”);
    Esta linha redireciona o usuário para a página /ecommerce/admin/products. Após o processamento dos dados do produto, o usuário é redirecionado para a lista de produtos.
  • L13: exit;
    A função exit encerra a execução do script. Esta linha garante que nenhum código adicional seja executado após o redirecionamento.

Função ‘setPhoto()’

PHP: Product.php (função setPhoto)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?php
/// início do código
 
public function setPhoto($file)
    {
        $extension explode('.'$file['name']);
        $extension end($extension);
        switch ($extension) {
            case "jpg":
            case "jpeg":
                $image = imagecreatefromjpeg($file["tmp_name"]);
                break;
            case "gif":
                $image = imagecreatefromgif($file["tmp_name"]);
                break;
            case "png":
                $image = imagecreatefrompng($file["tmp_name"]);
                break;
        }
        $dest $_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR .
            "ecommerce" . DIRECTORY_SEPARATOR .
            "res" . DIRECTORY_SEPARATOR .
            "site" . DIRECTORY_SEPARATOR .
            "img" . DIRECTORY_SEPARATOR .
            "products" . DIRECTORY_SEPARATOR .
            $this->getidproduct() . ".jpg";
        imagejpeg($image$dest);
        imagedestroy($image);
        $this->checkPhoto();
    }
 
// restodo código
?>  

Veja a explicação do código linha por linha:

  • L4: public function setPhoto($file)
    Esta linha define uma função pública chamada setPhoto que recebe um parâmetro $file. O parâmetro $file espera receber um array associativo contendo informações sobre o arquivo enviado pelo usuário, tipicamente o array $_FILES associado a um campo de upload de arquivo.
  • L5: {
    Início do bloco de código da função.
  • L6: $extension = explode(‘.’, $file[‘name’]);
    Esta linha utiliza a função explode() para dividir o nome do arquivo em um array de strings, usando o ponto (.) como delimitador. O resultado é armazenado na variável $extension. Esta operação visa extrair a extensão do arquivo.
  • L7: $extension = end($extension);
    A função end() é usada para obter o último elemento do array $extension, que corresponde à extensão do arquivo. O valor da extensão é então sobrescrito na variável $extension.
  • L8: switch ($extension) {
    Esta linha inicia uma estrutura de controle switch que verifica o valor da variável $extension.
  • L9-L11: case “jpg”: case “jpeg”: $image = imagecreatefromjpeg($file[“tmp_name”]); break;
    Este bloco case lida com arquivos de imagem JPEG. Se a extensão for “jpg” ou “jpeg”, a função imagecreatefromjpeg() é chamada para criar uma imagem a partir do arquivo temporário ($file[“tmp_name”]). O resultado é armazenado na variável $image. break; encerra a execução do switch.
  • L12-L14: case “gif”: $image = imagecreatefromgif($file[“tmp_name”]); break;
    Este bloco case lida com arquivos de imagem GIF. Se a extensão for “gif”, a função imagecreatefromgif() é chamada para criar uma imagem a partir do arquivo temporário. O resultado é armazenado na variável $image.break; encerra a execução do switch.
  • L15-L17: case “png”: $image = imagecreatefrompng($file[“tmp_name”]); break;
    Este bloco case lida com arquivos de imagem PNG. Se a extensão for “png”, a função imagecreatefrompng() é chamada para criar uma imagem a partir do arquivo temporário. O resultado é armazenado na variável $image.break; encerra a execução do switch.
  • L19-L25: $dest = $_SERVER[‘DOCUMENT_ROOT’] . DIRECTORY_SEPARATOR . “ecommerce” . DIRECTORY_SEPARATOR . “res” . DIRECTORY_SEPARATOR . “site” . DIRECTORY_SEPARATOR . “img” . DIRECTORY_SEPARATOR . “products” . DIRECTORY_SEPARATOR . $this->getidproduct() . “.jpg”; 1
    Esta linha constrói o caminho completo para o arquivo de destino onde a imagem será salva.
    • $_SERVER[‘DOCUMENT_ROOT’]: obtém o diretório raiz do servidor web.
    • DIRECTORY_SEPARATOR: garante a compatibilidade entre diferentes sistemas operacionais. A string concatena os diversos diretórios, e também o id do produto, obtido através do método $this->getidproduct(), e finaliza o nome do arquivo com a extensão “.jpg”.
  • L26: imagejpeg($image, $dest);
    Esta linha utiliza a função imagejpeg() para salvar a imagem criada anteriormente ($image) no caminho de destino ($dest). A imagem é salva no formato JPEG.
  • L27: imagedestroy($image);
    A função imagedestroy() é chamada para liberar a memória utilizada pela imagem criada. Isso é importante para evitar o consumo excessivo de recursos do servidor.
  • L28: $this->checkPhoto();
    Esta linha chama o método checkPhoto() do objeto atual ($this). Este método verifica se a foto foi salva com sucesso e pode realizar outras operações relacionadas à foto do produto.
  • L29: }
    Fim do bloco de código da função.

Para Saber Mais…

  • Função ‘verifyLogin’
  • Função ‘setData’
  • Função ‘save’
  • Método ‘setTpl’
  • Array
  • Função file_exists()
  • Função explode()
  • Função end()
  • Função imagejpeg()
  • Função imagecreatefromjpeg()
  • Função imagecreatefromgif()
  • Função imagecreatefrompng()
  • Função imagedestroy()