Solucionado (ver solução)
Solucionado
(ver solução)
43
respostas

Fotos

Bom dia, agradeceria ajuda de onde estou errando:

Estou tentando fazer upload de imagens através da pagina altera-produto (caso o usuário não tenha a imagem no momento do cadastramento do produto ele poderá fazer o upload depois, para isso, bastando alterar o produto) .

erro:

Notice: Undefined variable: nome_imagem in C:\Bitnami\wampstack-5.6.19-0\apache2\htdocs\beladuquesa\sys\banco-produto.php on line 81
O produto Saia Rita foi alterado.

Segue o arquivo produto-altera-adiciona

<?php
require_once 'conecta.php';
require_once 'banco-cor.php';
require_once 'banco-tamanho.php';
require_once 'banco-categoria.php';
require_once 'banco-produto.php';
require_once 'produto.php';
require_once 'cor.php';
require_once 'tamanho.php';
require_once 'categoria.php';
require_once 'logica-usuario.php';
?>
<?php
verificaUsuario();
?>
<!--require_once 'logica-usuario.php';
verificaUsuario(); -->


<main class="container">
    <article class="principal">

<?php

$categorias = listaCategorias($conexao);
$cores = listaCores($conexao);
$tamanhos = listaTamanhos($conexao);

$produto = new Produto();
$produto->setCategoria(new Categoria());
$produto->setcor(new Cor());
$produto->settamanho(new Tamanho());
$ehAlteracao = false;
$action = "adiciona-produto.php";
$id = "";

//Campos do formulario
//Inserir os demais campos do formulario

if (array_key_exists('id', $_GET)) {
    $id = $_GET['id'];
    if ($id <> ""){
        $produto = buscaProduto($conexao, $id);
        $ehAlteracao = true;
        $nome = $produto->getNome() ;
        //Carregar os demais campos do formulário

        $action = "altera-produto.php";
    }
}

?>
<h1><?=$ehAlteracao ? "Alterar" : "Cadastrar" ?> produto</h1>
<form action="<?=$action ?>" method="post">

   <!-- Adicionar os demais campos do formulário -->

    <input type="hidden" name="id" value="<?=$id; ?>" />

    <div class="form-group">
        <label>Codigo Barras:</label>
            <input type="text" name="codigo" class="form-control"
                value="<?=$produto->getCodigo() ?>" >
    </div>

    <div class="form-group">
    <label>Nome:</label>
    <input class="form-control" type="text" name="nome"
        value="<?=$produto->getNome() ?>">
    </div>

    <div class="form-group">
        <label>Preco:</label>
            <input type="text" name="preco" class="form-control"  
                value="<?=$produto->getPreco() ?>">

    </div>

<div class="form-group">
        <label>Descricao:</label>
            <textarea class="form-control" name="descricao"><?=$produto->getDescricao() ?></textarea>
    </div>

    <div class="form-group">
        <label>Cor:</label>
            <select name="cor_id" class="form-control">
            <?php
            foreach($cores as $cor) :
            $essaEhACor = $produto->getCor()->getId()
            == $cor->getId();
            $selecao = $essaEhACor ? "selected='selected'" : "";
            ?>
                <option value="<?=$cor->getId() ?>" <?=$selecao ?> >
                        <?=$cor->getNome() ?>
                </option>
                <?php endforeach ?>

            </select>
    </div>
    <div class="form-group">
        <label>Tamanho:</label>
            <select name="tamanho_id" class="form-control">
            <?php
            foreach($tamanhos as $tamanho) :
            $essaEhATamanho = $produto->getTamanho()->getId()
            == $tamanho->getId();
            $selecao = $essaEhATamanho ? "selected='selected'" : "";
            ?>
                <option value="<?=$tamanho->getId() ?>" <?=$selecao ?> >
                        <?=$tamanho->getNome() ?>
                </option>
                <?php endforeach ?>

            </select>
    </div>
<div class="form-group">
        <label>Categoria:</label>
            <select name="categoria_id" class="form-control">
            <?php
            foreach($categorias as $categoria) :
            $essaEhACategoria = $produto->getCategoria()->getId()
            == $categoria->getId();
            $selecao = $essaEhACategoria ? "selected='selected'" : "";
            ?>
            <option value="<?=$categoria->getId() ?>" <?=$selecao ?> >
                    <?=$categoria->getNome() ?>
            </option>
        <?php endforeach ?>

    </select>
    </div>

<div class="form-group">
        <label>Imagem:</label>
            <input type="file" name="foto" class="form-control"  
                value="foto">
<br>

        <button class="btn btn-danger" type="submit">Salvar</button>
</form>

</article>
</main>

</div> <!-- /container -->

arquivo altera-produto

<?php
require_once 'conecta.php';
require_once 'banco-produto.php';
require_once 'banco-cor.php';
require_once 'banco-tamanho.php';
require_once 'banco-categoria.php';
require_once 'produto.php';
require_once 'cor.php';
require_once 'tamanho.php';
require_once 'categoria.php';


$produto = new Produto();
$produto->setId( $_POST['id'] );
$produto->setCodigo( $_POST["codigo"]) ;
$produto->setNome( $_POST["nome"]);
$produto->setPreco( $_POST["preco"]);
$produto->setDescricao( $_POST["descricao"]);
    $cor = new Cor(); 
    $cor->setId( $_POST["cor_id"]);
$produto->setCor($cor);
    $tamanho = new Tamanho();
    $tamanho->setId( $_POST["tamanho_id"]);
$produto->setTamanho($tamanho);
    $categoria = new Categoria();
    $categoria->setId( $_POST["categoria_id"]);
$produto->setCategoria($categoria);
$produto->setFoto( $_POST["foto"]);


if(alteraProduto($conexao, $produto)) { ?>
<!--<script type="text/javascript">
    setTimeout(function(){window.location="produto-lista.php"} , 20000);
    </script>-->
<p class="text-success">
O produto <?=$produto->getNome() ?> foi alterado.
</p>
<noscript> 
Se não for direcionado automaticamente, clique <a href="produto-lista.php">aqui</a>. 
</noscript>
<?php
} else {
$msg = mysqli_error($conexao);
?>
<p class="text-danger">O produto <?=$produto->getNome() ?>
 não foi alterado: <?= $msg?></p>
<?php
}
?>

<!--<script language="JavaScript"> 
window.location="produto-lista.php"; 
</script>

classe Produto

<?php
class Produto
{
private $id;
private $codigo;
private $nome;
private $preco;
private $descricao;
private $categoria;
private $cor;
private $tamanho;
private $foto;


function __construct()
{

}

public function getId()
{
return $this->id;
}
public function setId($id)
{
$this->id = $id;
}

public function getCodigo()
{
return $this->codigo;
}
public function setCodigo($codigo)
{
$this->codigo = $codigo;
}


public function getNome()
{
return $this->nome;
}
public function setNome($nome)
{
$this->nome = $nome;
}

public function getPreco()
{
return $this->preco;
}
public function setPreco($preco){
  if(!is_numeric($preco)){
    $preco_convertido = str_replace("R$ ", "", $preco);
    $preco_convertido = str_replace(".", "", $preco_convertido);
    $preco_convertido = (float) str_replace(",", ".", $preco_convertido);
    $this->preco = $preco_convertido;
  }else {
    $this->preco = $preco;
  }
}

public function getDescricao()
{
return $this->descricao;
}
public function setDescricao($descricao)
{
$this->descricao = $descricao;
}

public function getCategoria()
{
return $this->categoria;
}
public function setCategoria($categoria)
{
$this->categoria = $categoria;
}

public function getCor()
{
return $this->cor;
}
public function setCor($cor)
{
$this->cor = $cor;
}


public function getTamanho()
{
return $this->tamanho;
}
public function setTamanho($tamanho)
{
$this->tamanho = $tamanho;
}

public function getFoto()
{
return $this->foto;
}
public function setFoto($foto)
{
    // Se a foto estiver sido selecionada
if (!empty($foto["name"])) {
// Largura máxima em pixels
$largura = 150;
// Altura máxima em pixels
$altura = 180;
// Tamanho máximo do arquivo em bytes
$tamanho = 1000;
// Verifica se o arquivo é uma imagem
if(!preg_match("/^image\/(pjpeg|jpeg|png|gif|bmp)$/", $foto["type"])){
$error[1] = "Isso não é uma imagem.";
}
// Pega as dimensões da imagem
$dimensoes = getimagesize($foto["tmp_name"]);
// Verifica se a largura da imagem é maior que a largura permitida
if($dimensoes[0] > $largura) {
$error[2] = "A largura da imagem não deve ultrapassar ".$largura." pixels";
}
// Verifica se a altura da imagem é maior que a altura permitida
if($dimensoes[1] > $altura) {
$error[3] = "Altura da imagem não deve ultrapassar ".$altura." pixels";
}
// Verifica se o tamanho da imagem é maior que o tamanho permitido
if($foto["size"] > $tamanho) {
$error[4] = "A imagem deve ter no máximo ".$tamanho." bytes";
}
// Se não houver nenhum erro
if (count($error) == 0) {
// Pega extensão da imagem
preg_match("/\.(gif|bmp|png|jpg|jpeg){1}$/i", $foto["name"], $ext);
// Gera um nome único para a imagem
$nome_imagem = md5(uniqid(time())) . "." . $ext[1];
// Caminho de onde ficará a imagem
$caminho_imagem = "fotos/" . $nome_imagem;
// Faz o upload da imagem para seu respectivo caminho
move_uploaded_file($foto["tmp_name"], $caminho_imagem);
$this->foto = $foto;
}
}
}

}

arquivo banco-produto na função alteraProduto

function alteraProduto($conexao, $produto) {
 $query ="update produtos set  nome = '{$produto->getNome()}', codigo = '{$produto->getCodigo()}',preco = {$produto->getPreco()}, descricao = '{$produto->getDescricao()}',
cor_id= {$produto->getCor()->getId()}, tamanho_id = {$produto->getTamanho()->getId()},
categoria_id= {$produto->getCategoria()->getId()}, foto = '".$nome_imagem."' where id = {$produto->getId()}";
return mysqli_query($conexao, $query);

}
43 respostas

Sergio, boa note!

Cara, não procurei mais erros no código.

O problema é bem simples, sua função:

function alteraProduto($conexao, $produto) {
 $query ="update produtos set  nome = '{$produto->getNome()}', codigo = '{$produto->getCodigo()}',preco = {$produto->getPreco()}, descricao = '{$produto->getDescricao()}',
cor_id= {$produto->getCor()->getId()}, tamanho_id = {$produto->getTamanho()->getId()},
categoria_id= {$produto->getCategoria()->getId()}, foto = '".$nome_imagem."' where id = {$produto->getId()}";
return mysqli_query($conexao, $query);

}

Você está concatenando na query a variável $nome_imagem, que não existe neste escopo.

Mesmo que você tenha criado ela antes de chamar a função do banco, internamente esta função não tem acesso à nenhuma variável fora do escopo dela, você precisa passar como argumento, sugiro as seguintes mudanças:

Nesta mesma função:

function alteraProduto($conexao, $produto,$nome_imagem) {
 $query ="update produtos set  nome = '{$produto->getNome()}', codigo = '{$produto->getCodigo()}',preco = {$produto->getPreco()}, descricao = '{$produto->getDescricao()}',
cor_id= {$produto->getCor()->getId()}, tamanho_id = {$produto->getTamanho()->getId()},
categoria_id= {$produto->getCategoria()->getId()}, foto = '".$nome_imagem."' where id = {$produto->getId()}";
return mysqli_query($conexao, $query);

}

E em todos os lugares onde você chama esta função, por exemplo no seu if:

if(alteraProduto($conexao, $produto,$nome_imagem)) { ?>

Oi Adriano obrigado pela ajuda, Fiz como vc me orientou:

function alteraProduto($conexao, $produto, $nome_imagem) {
 $query ="update produtos set  nome = '{$produto->getNome()}', codigo = '{$produto->getCodigo()}',preco = {$produto->getPreco()}, descricao = '{$produto->getDescricao()}',
cor_id= {$produto->getCor()->getId()}, tamanho_id = {$produto->getTamanho()->getId()},
categoria_id= {$produto->getCategoria()->getId()}, foto = '".$nome_imagem."' where id = {$produto->getId()}";
return mysqli_query($conexao, $query);

}

e no altera-produto:


if(alteraProduto($conexao, $produto, $nome_imagem)) { ?>
<!--<script type="text/javascript">
    setTimeout(function(){window.location="produto-lista.php"} , 20000);
    </script>-->
<p class="text-success">
O produto <?=$produto->getNome() ?> foi alterado.
</p>

Agora mostra outro erro> Diz que foi alterado, mas a imagem não vai para a pasta tampouco nome da foto não é inserido no BD

Notice: Undefined variable: nome_imagem in C:\Bitnami\wampstack-5.6.19-0\apache2\htdocs\beladuquesa\sys\altera-produto.php on line 31
O produto Vestido Paula foi alterado.

esta é a linha 31

if(alteraProduto($conexao, $produto, $nome_imagem)) { ?>

Sergio, boa noite!

O erro ainda aparece, por que a variável $nome_imagem não está definida antes de você chamar o if da linha 31.

Eo não havia percebido este detalhe, o trecho que pedi para você alterar ainda é válido, ou seja, para você inserir no banco chamando a função alteraProduto, é realmente necessário passar o nome da imagem como argumento.

O que você precisa fazer agora, é de alguma forma pegar esse nome para inserir no banco.

Vi que na linha acima do if, você chama um método para definir o nome da imagem e colocar em uma pasta.

$produto->setFoto( $_POST["foto"]);

Vamos resolver o problema inicial, que é o nome da imagem.

Obviamente, para inserir no banco você precisa ter exatamente o mesmo nome que foi utilizado para mover o arquivo.

Vamos então especializar esta funcionalidade, ao invés de você fazer isso dentro da função setFotos, crie um método para gerar o nome.

Sugiro a seguinte mudança na classe de foto:

<?php
class Produto
{
    private $id;
    private $codigo;
    private $nome;
    private $preco;
    private $descricao;
    private $categoria;
    private $cor;
    private $tamanho;
    private $foto;


    function __construct()
    {

    }

    public function getId()
    {
        return $this->id;
    }
    public function setId($id)
    {
        $this->id = $id;
    }

    public function getCodigo()
    {
        return $this->codigo;
    }
    public function setCodigo($codigo)
    {
        $this->codigo = $codigo;
    }


    public function getNome()
    {
        return $this->nome;
    }
    public function setNome($nome)
    {
        $this->nome = $nome;
    }

    public function getPreco()
    {
        return $this->preco;
    }

    public function setPreco($preco)
    {
          if(!is_numeric($preco))
          {
            $preco_convertido = str_replace("R$ ", "", $preco);
            $preco_convertido = str_replace(".", "", $preco_convertido);
            $preco_convertido = (float) str_replace(",", ".", $preco_convertido);
            $this->preco = $preco_convertido;
          }
          else
          {
            $this->preco = $preco;
          }
    }

    public function getDescricao()
    {
        return $this->descricao;
    }

    public function setDescricao($descricao)
    {
        $this->descricao = $descricao;
    }

    public function getCategoria()
    {
        return $this->categoria;
    }

    public function setCategoria($categoria)
    {
        $this->categoria = $categoria;
    }

    public function getCor()
    {
        return $this->cor;
    }

    public function setCor($cor)
    {
        $this->cor = $cor;
    }


    public function getTamanho()
    {
        return $this->tamanho;
    }

    public function setTamanho($tamanho)
    {
        $this->tamanho = $tamanho;
    }

    public function getFoto()
    {
        return $this->foto;
    }

    public function gerarNovoNome( string $nomeAntigo )
    {
        // Pega extensão da imagem
        preg_match("/\.(gif|bmp|png|jpg|jpeg){1}$/i", $nomeAntigo, $ext);
        // Gera um nome único para a imagem
        $nome_imagem = md5(uniqid(time())) . "." . $ext[1];

        return $nome_imagem;
    }

    public function setFoto($foto)
    {
        // esta variavel precisa existir, mesmo que vazia
        $nome_imagem = null;

        // Se a foto estiver sido selecionada
        if (!empty($foto["name"]))
        {
            // Largura máxima em pixels
            $largura = 150;
            // Altura máxima em pixels
            $altura = 180;
            // Tamanho máximo do arquivo em bytes
            $tamanho = 1000;
            // Verifica se o arquivo é uma imagem
            if(!preg_match("/^image\/(pjpeg|jpeg|png|gif|bmp)$/", $foto["type"]))
            {
                $error[1] = "Isso não é uma imagem.";
            }

            // Pega as dimensões da imagem
            $dimensoes = getimagesize($foto["tmp_name"]);

            // Verifica se a largura da imagem é maior que a largura permitida
            if($dimensoes[0] > $largura)
            {
                $error[2] = "A largura da imagem não deve ultrapassar ".$largura." pixels";
            }

            // Verifica se a altura da imagem é maior que a altura permitida
            if($dimensoes[1] > $altura)
            {
                $error[3] = "Altura da imagem não deve ultrapassar ".$altura." pixels";
            }

            // Verifica se o tamanho da imagem é maior que o tamanho permitido
            if($foto["size"] > $tamanho)
            {
                $error[4] = "A imagem deve ter no máximo ".$tamanho." bytes";
            }

            // Se não houver nenhum erro
            if (count($error) == 0)
            {
                $nome_imagem = $this->gerarNovoNome($foto["name"]);

                // Caminho de onde ficará a imagem
                $caminho_imagem = "fotos/" . $nome_imagem;
                // Faz o upload da imagem para seu respectivo caminho
                move_uploaded_file($foto["tmp_name"], $caminho_imagem);
                $this->foto = $foto;
            }
        }

        return $nome_imagem;
    }

}

Observe que criei a função gerarNovoNome, que recebe o nome antigo do documento e retorna o nome novo.

Executando exatamente o mesmo processo que você fazia ao final da função setFoto.

Com isso, poremos resolver o problema de inserir no banco, adicione a seguinte linha antes do seu if:

$nome_imagem = $produto->setFoto( $_POST["foto"]);

Este pedaço ficaria assim:

// algum código antes disso

$produto->setCategoria($categoria);

$nome_imagem = $produto->setFoto( $_POST["foto"]);

if(alteraProduto($conexao, $produto,$nome_imagem)) { ?>
<!--<script type="text/javascript">
    setTimeout(function(){window.location="produto-lista.php"} , 20000);
    </script>-->

// algum código depois disso

Neste ponto o problema de inserir no banco deve ser resolvido, se der algum problema, é outro problema, talvez com a criação da query, mas não este mesmo erro de variável não definida.

Acredito que as alteração que fiz, dispensam explicações.

Mas em resumo, agora a classe produto gera o nome da imagem, apenas se passar por suas validações.

O próprio método setFoto retorna o novo nome da imagem.

E é este nome que irá para o banco.

O problema que você comentou da imagem não ir para a pasta, podem ser várias coisas.

Você tem que verificar se o arquivo que você está anexando realmente passa pelas validações.

Uma coisa que fiquei curioso, você tem certeza de que o arquivo está sendo enviado pela variável $POST?

Pois o processo normal de upload no php, os arquivos são armazenados na variável $_FILES

A menos que você esteja fazendo algo via javascript, seu formulário está errado.

Falta uma propriedade para o envio de arquivos, da forma como está são enviados apenas os dados dos campos, exceto arquivos.

Hoje está assim:

<form action="<?=$action ?>" method="post">

Precisa estar assim:

<form action="<?=$action ?>" method="post" enctype="multipart/form-data">

Sem o enctype, nenhum arquivo é enviado ao servidor.

E ao enviar, os dados não ficam na variável $_POST e sim na variável $_FILES.

Para testar isso, verifique o resultado do comando abaixo:

echo '<pre>';
print_r( $_POST );
print_r($_FILES);

Coloque isso onde você recebe os dados do formulário, e verá o que estou falando.

Bem, isso deve resolver grande parte dos seus problemas. Espero que consiga resolver mais algum outro que surja.

Boa sorte!

Muito obrigado Adriano, fiz exatamente como me sugeriu e também o enctype:

<h1><?=$ehAlteracao ? "Alterar" : "Cadastrar" ?> produto</h1>
<form action="<?=$action ?>" method="post" enctype="multipart/form-data">>

e ainda não estou conseguindo salvar no BD tampouco na pasta. Esta é a resposta daquele echo :

Array
(
    [id] => 12
    [codigo] => 96
    [nome] => Saia Rita
    [preco] => 99.00
    [descricao] => Saia em popeline e jackard
    [cor_id] => 5
    [tamanho_id] => 4
    [categoria_id] => 1
)
Array
(
    [foto] => Array
        (
            [name] => google-beta-150x180.jpg
            [type] => image/jpeg
            [tmp_name] => C:\Bitnami\wampstack-5.6.19-0\php\tmp\php42E0.tmp
            [error] => 0
            [size] => 13469
        )

)


Notice:  Undefined index: foto in C:\Bitnami\wampstack-5.6.19-0\apache2\htdocs\beladuquesa\sys\altera-produto.php on line 31



O produto Saia Rita foi alterado.

esta é a linha 31 do altera-produto:

$nome_imagem = $produto->setFoto( $_POST["foto"]);

Sergio, o erro de Undefined index: foto, é por que o formulário agora entende que o campo foto é um arquivo, e ao enviar para o php ele vai para a variável $_FILES e não mais $_POST.

Ou seja, sua foto está em $_FILES["foto"], o campo $_POST["foto"] não existe mais.

Oi Adriano fiz a alteração e mudou mas não sei onde errei agora. Você poderia me ajudar?

Array
(
    [id] => 12
    [codigo] => 96
    [nome] => Saia Rita
    [preco] => 99.00
    [descricao] => Saia em popeline e jackard
    [cor_id] => 5
    [tamanho_id] => 4
    [categoria_id] => 1
)
Array
(
    [foto] => Array
        (
            [name] => google-beta-150x180.jpg
            [type] => image/jpeg
            [tmp_name] => C:\Bitnami\wampstack-5.6.19-0\php\tmp\phpAC9E.tmp
            [error] => 0
            [size] => 13469
        )

)


Notice:  Undefined variable: error in C:\Bitnami\wampstack-5.6.19-0\apache2\htdocs\beladuquesa\sys\produto.php on line 166



Catchable fatal error:  Argument 1 passed to Produto::gerarNovoNome() must be an instance of string, string given, called in C:\Bitnami\wampstack-5.6.19-0\apache2\htdocs\beladuquesa\sys\produto.php on line 168 and defined in C:\Bitnami\wampstack-5.6.19-0\apache2\htdocs\beladuquesa\sys\produto.php on line 114

LInha 165 a 168 da classe produto:

  // Se não houver nenhum erro
            if (count($error) == 0)
            {
                $nome_imagem = $this->gerarNovoNome($foto["name"]);

Sergio, boa tarde!

Vamos lá, está quase pronto, é assim mesmo. Normalmente acontecem vários problemas em sequência.

Primeiro vamos resolver o erro:

Notice:  Undefined variable: error in C:\Bitnami\wampstack-5.6.19-0\apache2\htdocs\beladuquesa\sys\produto.php on line 166

O que acontece, é que na sua função setFoto, em vários lugares você está criando um array com a variável erro.

Até ai sem problemas, mas nesta linha você está executando uma contagem de quantos elementos a variável $error possui, mas como não deu nenhum erro, ela não existe.

Você pode resolver de duas formas, use uma ou outra.

Segue a primeira:

// Se não houver nenhum erro
            if ( $error )

Bastra trocar o seu count por uma verificação se a variável existe, se existir significa que ocorreu mesmo um erro.

Outra forma de resolver, é criar esse array no início da sua função, seria assim:

    public function setFoto($foto)
    {
        // esta variavel precisa existir, mesmo que vazia
        $nome_imagem = null;

        // armazena erros se houver
        $error = array();

Veja que apenas criei a variável, então ela vai sempre existir, e o seu count irá funcionar.

Agora vamos ao Fatal Error, esse erro ocorreu, pois eu declarei a assinatura da função de gerar nome desta forma:

public function gerarNovoNome( string $nomeAntigo )

Mas não perguntei se você está usando o PHP 7, se estiver basta alterar para:

public function gerarNovoNome( \string $nomeAntigo )

Adicionando esta barra invertida.

Isto é para garantir que você deve passar uma string como nome, ele não aceita outra coisa, e se for passar um número, deve converter em string antes.

Agora para resolver isso, independente da sua versão do PHP, basta deixar assim:

public function gerarNovoNome( $nomeAntigo )

Desta forma não forçamos nada, mas a desvantagem é que qualquer coisa pode ser informada, e isso nem sempre é bom.

Muito obrigado Adriano, fiz as correções. Entendi. Mas meu arquivo deve ter outra coisa errado veja o erro que apareceu e continuo não conseguindo gravar nem no BD tampouco no arquivo fotos. Onde será que continuo errando?

Array
(
    [id] => 11
    [codigo] => 16
    [nome] => Vestido Anny
    [preco] => 169.00
    [descricao] => vestido em jackard
    [cor_id] => 6
    [tamanho_id] => 8
    [categoria_id] => 2
)
Array
(
    [foto] => Array
        (
            [name] => google-beta-150x180.jpg
            [type] => image/jpeg
            [tmp_name] => C:\Bitnami\wampstack-5.6.19-0\php\tmp\phpC410.tmp
            [error] => 0
            [size] => 13469
        )

)


Catchable fatal error:  Argument 1 passed to Produto::gerarNovoNome() must be an instance of string, string given, called in C:\Bitnami\wampstack-5.6.19-0\apache2\htdocs\beladuquesa\sys\produto.php on line 172 and defined in C:\Bitnami\wampstack-5.6.19-0\apache2\htdocs\beladuquesa\sys\produto.php on line 114

Linha 169 a 172:

eu alterei no começo do arquivo pela segunda opção e mantive essa no final:

 // Se não houver nenhum erro
            if (count($error) == 0)
            {
                $nome_imagem = $this->gerarNovoNome($foto["name"]);

Linha 114

 public function gerarNovoNome( \string $nomeAntigo )
    {

Fiz 2 testes: O primeiro deixando apenas assim:

  public function gerarNovoNome( $nomeAntigo )

e o segundo teste fiz aqui coloquei somente o error:


            // Se não houver nenhum erro
           if ( $error )
            {
                $nome_imagem = $this->gerarNovoNome($foto["name"]);

Fazendo isso, não aparecem erros, mas também a foto não é enviada a pasta e seu nome ao BD.

o echo ficou assim:

Array
(
    [id] => 11
    [codigo] => 16
    [nome] => Vestido Anny
    [preco] => 169.00
    [descricao] => vestido em jackard
    [cor_id] => 6
    [tamanho_id] => 8
    [categoria_id] => 2
)
Array
(
    [foto] => Array
        (
            [name] => google-beta-150x180.jpg
            [type] => image/jpeg
            [tmp_name] => C:\Bitnami\wampstack-5.6.19-0\php\tmp\phpE00.tmp
            [error] => 0
            [size] => 13469
        )

)


O produto Vestido Anny foi alterado.

Sergio, boa tarde!

Esse detalhe do \string depende muito da versão do php. Normalmente adicionando esta barra resolve, mas não foi o caso.

Então pode remover, era uma tentativa apenas de garantir um formato correto para o parâmetro.

Se você quiser fazer uma última tentativa de manter, pode adicionar um conversor de tipo, em todos os locais onde você usa esta função, por exemplo:

$nome_imagem = $this->gerarNovoNome(  (string)$foto["name"]);

Neja que antes da variável $foto["name"], adicionei uma conversão de tipo (string)

É importante que fiquem unidas, ou seja, sem espaços.

Isso converte a variável para um outro tipo.

Por exemplo, vamos supor que você tenha um número que precisa ser tradado como string.

$numero = 1; // arqui é inteiro
$numero = (string)$numero; // arqui é convertido para string

Ou outros formatos, como:

(bool) // conversor para booleano
(int) // conversor para inteiro
(float) // conversor para ponto flutuante

E vários outros, veja mais na parte de conversão de tipos e manipulação de tipos do manual:

http://php.net/manual/pt_BR/language.types.type-juggling.php

http://php.net/manual/pt_BR/language.types.type-juggling.php#language.types.typecasting

E o print_r que você colocou, pode remover, era apenas tara saber de o POST e o FILE estavam vindo corretamente.

Perfeito Adriano, funcionou nenhum erro. Mas não consigo enviar ao arquivo fotos nem ao BD o nome do arquivo. Onde posso verificar este erro? Você teria alguma idéia onde eu possa estar errando agora? Também acredito que falta pouco. Pelo menos erros já não existem. Mas mesmo assim não consigo salvar a foto. Obrigado novamente.

P.s. quanto ao print r (esse eu vou guardar na minha caixa de ferramentas) muito obrigado por me ensinar isso....rssrsr

Adriano fiz outro teste agora mesmo e fiz o seguinte:

alterei novamente essa parte do arquivo if(count..... para esse formato e olha o erro que mostrou:

// Se não houver nenhum erro
           if (count($error) == 0) {
            {
               $nome_imagem = $this->gerarNovoNome(  (string)$foto["name"]);

                // Caminho de onde ficará a imagem
                $caminho_imagem = "fotos/" . $nome_imagem;
                // Faz o upload da imagem para seu respectivo caminho
                move_uploaded_file($foto["tmp_name"], $caminho_imagem);
                $this->foto = $foto;
            }
        }

        return $nome_imagem;
    }

}
}
Warning:  move_uploaded_file(fotos/d1873f17c6c3051ada5f457afa205029.jpg): failed to open stream: No such file or directory in C:\Bitnami\wampstack-5.6.19-0\apache2\htdocs\beladuquesa\sys\produto.php on line 178



Warning:  move_uploaded_file(): Unable to move 'C:\Bitnami\wampstack-5.6.19-0\php\tmp\phpC4B4.tmp' to 'fotos/d1873f17c6c3051ada5f457afa205029.jpg' in C:\Bitnami\wampstack-5.6.19-0\apache2\htdocs\beladuquesa\sys\produto.php on line 178

Linha 178:

 move_uploaded_file($foto["tmp_name"], $caminho_imagem);
solução!

Sergio.

Vamos lá, tem um detalhe.

Você não está verificando se a foto deu erro, o processo de gravar o arquivo, só dá certo se a validação for ok, certo?

Primeiro, adicione essa verificação, alterando o final da função setFoto, assim:

// Se não houver nenhum erro
            if (count($error) == 0)
            {
                $nome_imagem = $this->gerarNovoNome($foto["name"]);

                // Caminho de onde ficará a imagem
                $caminho_imagem = "fotos/" . $nome_imagem;
                // Faz o upload da imagem para seu respectivo caminho
                move_uploaded_file($foto["tmp_name"], $caminho_imagem);
                $this->foto = $foto;
            }
            else
            {
                echo "<pre>";
                echo "Opa!, foto com os seguintes problemas: <br>";
                echo implode("<br>", $error);
                exit;
            }

Depois você altera para como achar melhor, por agora é apenas uma verificação, pois você adicionou um if, mas não tem um else de a foto for inválida.

Segundo ponto, esta pasta "fotos" , onde você quer salvar, realmente existe?

Se não existir, você pode criar isso em tempo de execução, então ficaria assim:

// Se não houver nenhum erro
            if (count($error) == 0)
            {
                $nome_imagem = $this->gerarNovoNome($foto["name"]);

                // caso o diretório não exista
                if( !is_dir("fotos") )
                    mkdir("fotos", "0777", true);

                // Caminho de onde ficará a imagem
                $caminho_imagem = "fotos" . DIRECTORY_SEPARATOR . $nome_imagem;
                // Faz o upload da imagem para seu respectivo caminho
                move_uploaded_file($foto["tmp_name"], $caminho_imagem);
                $this->foto = $foto;
            }
            else
            {
                echo "<pre>";
                echo "Opa!, foto com os seguintes problemas: <br>";
                echo implode("<br>", $error);
                exit;
            }

Adicionei uma verificação se a pasta existe, se não existir cria com a permissão 777, você pode mudar se quiser.

E no caminho da pasta, troquei a barra por DIRECTORY_SEPARATOR, assim não há conflito se o sistema é windows ou linux, mac, etc...

Isso é uma constante do PHP que define o separador de diretórios do sistema operacional.

Com isso deve funcionar :)

Show, Na Mosca!!!!!!! Muito obrigado Adriano.

Primeiro que Deus te ilumine ainda mais, e obrigado pela sua paciência de professor... Eu aprendi muito com você hoje. Espero que muitos alunos possam tirar proveito desta aula de PHP.

abraços.

Sergio

Sergio.

Eu que agradeço sua paciência de passar erro por erro, muitas pessoas querem uma solução mágica que pode ser feito em uma linha.

Realmente este tópico ficou bem extenso, kkk Provavelmente muitas pessoas irão aproveitar esse tópico, pois mencionamos muita coisa do PHP, que irão aparecer nas buscas.

Abraços.

Adriano ajudaaaa. Não sei onde mexi, o upload para pasta está ok mas o caminho no BD não está sendo preenchido. Por favor, onde pode estar este erro? desculpe eu mexi em algum lugar e isso parou de funcionar.

Obrigado novamente.

Sergio, boa noite!

Gerou algum erro? Ou apenas parou de gravar?

Por favor, se possível, poste os códigos novamente para estudarmos o problema.

Quando atualizei para o que você me ensinou o primeiro upload funcionou fez upload e registrou o caminho no BD agora o Upload está ok mas não registra o caminho no ID do produto. Nenhum erro exibido.

altera-produto

$produto = new Produto();
$produto->setId( $_POST['id'] );
$produto->setCodigo( $_POST["codigo"]) ;
$produto->setNome( $_POST["nome"]);
$produto->setPreco( $_POST["preco"]);
$produto->setDescricao( $_POST["descricao"]);
    $cor = new Cor(); 
    $cor->setId( $_POST["cor_id"]);
$produto->setCor($cor);
    $tamanho = new Tamanho();
    $tamanho->setId( $_POST["tamanho_id"]);
$produto->setTamanho($tamanho);
    $categoria = new Categoria();
    $categoria->setId( $_POST["categoria_id"]);
$produto->setCategoria($categoria);
$nome_imagem = $produto->setFoto( $_FILES["foto"]);


if(alteraProduto($conexao, $produto, $nome_imagem)) { ?>
<!--<script type="text/javascript">
    setTimeout(function(){window.location="produto-lista.php"} , 20000);
    </script>-->
<p class="text-success">
O produto <?=$produto->getNome() ?> foi alterado.

classe produto no set e get foto:

public function getFoto()
    {
        return $this->foto;
    }

    public function gerarNovoNome( $nomeAntigo )
    {
        // Pega extensão da imagem
        preg_match("/\.(gif|bmp|png|jpg|jpeg){1}$/i", $nomeAntigo, $ext);
        // Gera um nome único para a imagem
        $nome_imagem = md5(uniqid(time())) . "." . $ext[1];

        return $nome_imagem;
    }

    public function setFoto($foto)
    {

        // esta variavel precisa existir, mesmo que vazia
        $nome_imagem = null;

        // armazena erros se houver
        $error = array();

        // Se a foto estiver sido selecionada
        if (!empty($foto["name"]))
        {
            // Largura máxima em pixels
            $largura = 300;
            // Altura máxima em pixels
            $altura = 500;
            // Tamanho máximo do arquivo em bytes
            $tamanho = 100000;
            // Verifica se o arquivo é uma imagem
            if(!preg_match("/^image\/(pjpeg|jpeg|png|gif|bmp)$/", $foto["type"]))
            {
                $error[1] = "Isso não é uma imagem.";
            }

            // Pega as dimensões da imagem
            $dimensoes = getimagesize($foto["tmp_name"]);

            // Verifica se a largura da imagem é maior que a largura permitida
            if($dimensoes[0] > $largura)
            {
                $error[2] = "A largura da imagem não deve ultrapassar ".$largura." pixels";
            }

            // Verifica se a altura da imagem é maior que a altura permitida
            if($dimensoes[1] > $altura)
            {
                $error[3] = "Altura da imagem não deve ultrapassar ".$altura." pixels";
            }

            // Verifica se o tamanho da imagem é maior que o tamanho permitido
            if($foto["size"] > $tamanho)
            {
                $error[4] = "A imagem deve ter no máximo ".$tamanho." bytes";
            }
// Se não houver nenhum erro
            if (count($error) == 0)
            {
                $nome_imagem = $this->gerarNovoNome($foto["name"]);

                // caso o diretório não exista
                if( !is_dir("fotos") )
                    mkdir("fotos", "0777", true);

                // Caminho de onde ficará a imagem
                $caminho_imagem = "fotos" . DIRECTORY_SEPARATOR . $nome_imagem;
                // Faz o upload da imagem para seu respectivo caminho
                move_uploaded_file($foto["tmp_name"], $caminho_imagem);
                $this->foto = $foto;
            }
            else
            {
                echo "<pre>";
                echo "Opa!, foto com os seguintes problemas: <br>";
                echo implode("<br>", $error);
                exit;
            }
}

banco-produto na função alteraProduto:

function alteraProduto($conexao, $produto, $nome_imagem) {
 $query ="update produtos set  nome = '{$produto->getNome()}', codigo = '{$produto->getCodigo()}',preco = {$produto->getPreco()}, descricao = '{$produto->getDescricao()}',
cor_id= {$produto->getCor()->getId()}, tamanho_id = {$produto->getTamanho()->getId()},
categoria_id= {$produto->getCategoria()->getId()}, foto = '" .$nome_imagem. "' where id = {$produto->getId()}";
return mysqli_query($conexao, $query);

}

Sergio,

Não vejo erros neste código.

Mas senti falta do return $nome_imagem ao final da função setFoto.

Foi removido? Ou apenas não foi copiado?

Outra coisa, no banco apareceu algum registro sem o nome da foto, ou nenhum registro foi adicionado?

Oi Adriano, acho que sem querer eu apaguei o return.

No banco aparece em branco sem o nome da foto.

Coloquei o return no final assim mas está me avisando de um erro:

// Se não houver nenhum erro
            if (count($error) == 0)
            {
                $nome_imagem = $this->gerarNovoNome($foto["name"]);

                // caso o diretório não exista
                if( !is_dir("fotos") )
                    mkdir("fotos", "0777", true);

                // Caminho de onde ficará a imagem
                $caminho_imagem = "fotos" . DIRECTORY_SEPARATOR . $nome_imagem;
                // Faz o upload da imagem para seu respectivo caminho
                move_uploaded_file($foto["tmp_name"], $caminho_imagem);
                $this->foto = $foto;
            }
            else
            {
                echo "<pre>";
                echo "Opa!, foto com os seguintes problemas: <br>";
                echo implode("<br>", $error);
                exit;
            }
        }
}

            return $nome_imagem

}

erro:

Parse error: syntax error, unexpected 'return' (T_RETURN), expecting function (T_FUNCTION) in C:\Bitnami\wampstack-5.6.19-0\apache2\htdocs\beladuquesa\sys\produto.php on line 194

Esse foi o problema.

O return desta função fazia isso.

Para solucionar você pode simplesmente voltar esse return.

Ou aprimorar o código e pegar este nome de outra forma.

Seria assim:

Na sua classe Produto:

public function setFoto($foto)
    {
        // esta variavel precisa existir, mesmo que vazia
        $nome_imagem = null;

        $error = [];

        // Se a foto estiver sido selecionada
        if (!empty($foto["name"]))
        {
            // Largura máxima em pixels
            $largura = 150;
            // Altura máxima em pixels
            $altura = 180;
            // Tamanho máximo do arquivo em bytes
            $tamanho = 1000;
            // Verifica se o arquivo é uma imagem
            if(!preg_match("/^image\/(pjpeg|jpeg|png|gif|bmp)$/", $foto["type"]))
            {
                $error[1] = "Isso não é uma imagem.";
            }

            // Pega as dimensões da imagem
            $dimensoes = getimagesize($foto["tmp_name"]);

            // Verifica se a largura da imagem é maior que a largura permitida
            if($dimensoes[0] > $largura)
            {
                $error[2] = "A largura da imagem não deve ultrapassar ".$largura." pixels";
            }

            // Verifica se a altura da imagem é maior que a altura permitida
            if($dimensoes[1] > $altura)
            {
                $error[3] = "Altura da imagem não deve ultrapassar ".$altura." pixels";
            }

            // Verifica se o tamanho da imagem é maior que o tamanho permitido
            if($foto["size"] > $tamanho)
            {
                $error[4] = "A imagem deve ter no máximo ".$tamanho." bytes";
            }

            $error = [];

            // Se não houver nenhum erro
            if (count($error) == 0)
            {
                $nome_imagem = $this->gerarNovoNome($foto["name"]);

                // caso o diretório não exista
                if( !is_dir("fotos") )
                    mkdir("fotos", "0777", true);

                // Caminho de onde ficará a imagem
                $caminho_imagem = "fotos" . DIRECTORY_SEPARATOR . $nome_imagem;
                // Faz o upload da imagem para seu respectivo caminho
                move_uploaded_file($foto["tmp_name"], $caminho_imagem);

                $this->foto = $foto;
                $this->nome = $nome_imagem; // adicionando o novo nome que geramos agora, é obrigatório fazer isso abaixo da linha de cima. Para atualizar o atributo
            }
            else
            {
                echo "<pre>";
                echo "Opa!, foto com os seguintes problemas: <br>";
                echo implode("<br>", $error);
                exit;
            }
        }
    }

Veja como ficou o método setFoto atualizado.

Mas para isso funcionar, precisamos alterar outros locais, o primeiro é aquele if, deste trecho:

$produto->setCategoria($categoria);
$nome_imagem = $produto->setFoto( $_FILES["foto"]);


if(alteraProduto($conexao, $produto, $nome_imagem)) { ?>
<!--<script type="text/javascript">

Altere para ficar assim:

$produto->setCategoria($categoria);
$produto->setFoto( $_FILES["foto"]);


if(alteraProduto($conexao, $produto)) { ?>
<!--<script type="text/javascript">

Sim, isso mesmo, não vamos mais usar a variável imagem.

Mas falta uma última alteração:

A função do banco era assim:

function alteraProduto($conexao, $produto, $nome_imagem) {
 $query ="update produtos set  nome = '{$produto->getNome()}', codigo = '{$produto->getCodigo()}',preco = {$produto->getPreco()}, descricao = '{$produto->getDescricao()}',
cor_id= {$produto->getCor()->getId()}, tamanho_id = {$produto->getTamanho()->getId()},
categoria_id= {$produto->getCategoria()->getId()}, foto = '" .$nome_imagem. "' where id = {$produto->getId()}";
return mysqli_query($conexao, $query);

}

Deixe assim:

function alteraProduto($conexao, $produto, $nome_imagem) {
 $query ="update produtos set  nome = '{$produto->getNome()}', codigo = '{$produto->getCodigo()}',preco = {$produto->getPreco()}, descricao = '{$produto->getDescricao()}',
cor_id= {$produto->getCor()->getId()}, tamanho_id = {$produto->getTamanho()->getId()},
categoria_id= {$produto->getCategoria()->getId()}, foto = '{$produto->getNome()}' where id = {$produto->getId()}";
return mysqli_query($conexao, $query);

}

Veja que o código ficou mais inteligente, pegando o atributo do objeto produto.

Uma coisa importante, as linhas 183 e 184 da classe produto, precisam seguir esta ordem.

Primeiro definimos os atributos da foto com $this->foto = $foto;

E depois atualizamos apenas o nome com $this->nome = $nome_imagem;

Não executei para saber se inverter daria problema, mas assim é certo que funciona.

Sergio, o return que você colocou está fora do escopo da função e está no escopo da classe.

Desta forma não funciona.

se quiser o return, é logo após o else, assim:

else
            {
                echo "<pre>";
                echo "Opa!, foto com os seguintes problemas: <br>";
                echo implode("<br>", $error);
                exit;
            }

            return $nome_imagem;

Qualquer uma das duas soluções funciona.

Gerou este erro Adriano:

error:  Call to undefined method Produto::gerarNovoNome() in C:\Bitnami\wampstack-5.6.19-0\apache2\htdocs\beladuquesa\sys\produto.php on line 158

Linha 155 a 158:

Se não houver nenhum erro
            if (count($error) == 0)
            {
                $nome_imagem = $this->gerarNovoNome($foto["name"]);

Adriano, bom dia. Consegui resolver utilizando somente o return fiz o teste e funcionou. Faltava isso. Show. agora sim. Se puderes me ajudar uma ultima coisa neste topico como seria o codigo para mostrar a foto do produto na página utilizando todos esses metodos que implementamos?

Tentei isso e não consegui:

<div class="form-group">
        <label>Imagem do Produto:</label>
            <img src="sys/fotos-<?=$produto->getId()?>.jpg">
    </div>

Sergio, boa tarde!

Que bom que deu certo.

Agora para mostrar a imagem, o ideal é que você utilize o mesmo nome que usou para inserir no banco.

<div class="form-group">
        <label>Imagem do Produto:</label>
            <img src="fotos/<?= $nome_imagem ?>.jpg">
    </div>

Mas claro que você precisa ter esta variável neste momento.

Ok, Adriano então seria algo assim:

tenho uma função buscaProduto que faz a busca no BD. Fiz assim acrescentando o $nome_imagem e assim retorno o caminho da foto para pagina produto-altera-adiciona

function buscaProduto($conexao, $id, $nome_imagem) {
$query = "select p.*, c.nome as categoria_nome, co.nome as cor_nome, t.nome as tamanho_nome
from produtos p 
inner join categorias c on(p.categoria_id = c.id)
inner join cor co on(p.cor_id = co.id) 
inner join tamanho t on(p.tamanho_id = t.id)
where p.id = {$id}"; 

$resultado = mysqli_query($conexao, $query);
$array = mysqli_fetch_assoc($resultado);

$produto = new Produto();
$produto->setId( $array['id']);
$produto->setNome( $array['nome']);
$produto->setPreco( $array['preco']);
$produto->setCodigo( $array['codigo']);
$produto->setDescricao( $array['descricao']);
$produto->setCor(new Cor());
$produto->getCor()->setId( $array['cor_id']);
$produto->getCor()->setNome( $array['cor_nome']);
$produto->setTamanho(new Tamanho());
$produto->getTamanho()->setId( $array['tamanho_id']);
$produto->getTamanho()->setNome( $array['tamanho_nome']);
$produto->setCategoria(new Categoria());
$produto->getCategoria()->setId( $array['categoria_id']);
$produto->getCategoria()->setNome( $array['categoria_nome']);
$nome_imagem = $produto->setFoto( $_array["foto"]);

return $produto;

}

Mas houve este erro que não entendo como corrigir:

Warning: Missing argument 3 for buscaProduto(), called in C:\Bitnami\wampstack-5.6.19-0\apache2\htdocs\beladuquesa\sys\produto-altera-adiciona.php on line 103 and defined in C:\Bitnami\wampstack-5.6.19-0\apache2\htdocs\beladuquesa\sys\banco-produto.php on line 48

o Erro se deu neste trecho de codigo no banco-produto

function buscaProduto($conexao, $id,$nome_imagem) {

esta é o arquivo produto-altera-adiciona no trecho de adicionar/alterar

<?php

$categorias = listaCategorias($conexao);
$cores = listaCores($conexao);
$tamanhos = listaTamanhos($conexao);

$produto = new Produto();
$produto->setCategoria(new Categoria());
$produto->setcor(new Cor());
$produto->settamanho(new Tamanho());
$ehAlteracao = false;
$action = "adiciona-produto.php";
$id = "";

//Campos do formulario
//Inserir os demais campos do formulario

if (array_key_exists('id', $_GET)) {
    $id = $_GET['id'];
    if ($id <> ""){
        $produto = buscaProduto($conexao, $id);
        $ehAlteracao = true;
        $nome = $produto->getNome() ;
        //Carregar os demais campos do formulário

        $action = "altera-produto.php";
    }
}

?>
<h1><?=$ehAlteracao ? "Alterar" : "Cadastrar" ?> produto</h1>
<form action="<?=$action ?>" method="post" enctype="multipart/form-data">

Oi Sérgio.

O problema está no arquivo produto-altera-adiciona.php. Você está chamando a função buscaProduto($conexao, $id); passando dois parâmetros, sendo a conexão e o id, porém na declaração da função você pede a variável $nome_imagem:

function buscaProduto($conexao, $id, $nome_imagem) { ... }

A questão é que você não usar essa variável pra nada na função buscaProduto(), ou seja, não precisa dela. Remova da declaração da função esse parâmetro e vai funcionar. Deixe assim:

function buscaProduto($conexao, $id) { ... }

Oi Bruno obrigado. Fiz isso, não está mais exibindo o erro, jóia!!! mas ainda não consigo exibir a foto do produto no arquivo produto-altera-adiciona.

Onde será que eu estou cometendo mais esse erro?

Onde no arquivo produto-altera-adiciona.php você está tentando exibir a foto? Lembre-se, a função buscaProduto() retorna um produto e você o recebe em uma variável aqui:

$produto = buscaProduto($conexao, $id);

Essa variável $produto contém todo o objeto Produto baseado no $id que você passou para a função. Caso queira utilizar a foto desse produto retornado, basta utilizar a função get que você criou na classe de Produto:

x = $produto->getFoto();

Claro que, no lugar de x, você precisa passar o elemento ou a variável que receberá a foto.

Sergio, acho que sei onde está o problema.

$nome_imagem = $produto->setFoto( $_array["foto"]);

return $produto;

Você está retornando o objeto $produto. Mesmo que criou a variável $nome_produto, ela não é acessível fora do escopo.

Voltando ao exemplo do formulário, para exibir o arquivo, precisa ser algo mais ou menos assim:

<div class="form-group">
        <label>Imagem do Produto:</label>
            <img src="fotos/<?= $produto->getNome() ?>.jpg">
    </div>

Mas novamente, tudo depende do escopo onde você está.

Se não resolver, poste o código completo do arquivo onde você está tentando exibir a imagem.

Oi Adriano segue o arquivo formulario "produto-altera-adiciona"

<main class="container">
    <article class="principal">

<?php

$categorias = listaCategorias($conexao);
$cores = listaCores($conexao);
$tamanhos = listaTamanhos($conexao);

$produto = new Produto();
$produto->setCategoria(new Categoria());
$produto->setcor(new Cor());
$produto->settamanho(new Tamanho());
$ehAlteracao = false;
$action = "adiciona-produto.php";
$id = "";

//Campos do formulario
//Inserir os demais campos do formulario

if (array_key_exists('id', $_GET)) {
    $id = $_GET['id'];
    if ($id <> ""){
        $produto = buscaProduto($conexao, $id);
        $ehAlteracao = true;
        $nome = $produto->getNome() ;
        //Carregar os demais campos do formulário

        $action = "altera-produto.php";
    }
}

?>
<h1><?=$ehAlteracao ? "Alterar" : "Cadastrar" ?> produto</h1>
<form action="<?=$action ?>" method="post" enctype="multipart/form-data">

   <!-- Adicionar os demais campos do formulário -->

    <input type="hidden" name="id" value="<?=$id; ?>" />

    <div class="form-group">
        <label>Codigo Barras:</label>
            <input type="text" name="codigo" class="form-control"
                value="<?=$produto->getCodigo() ?>" >
    </div>

    <div class="form-group">
    <label>Nome:</label>
    <input class="form-control" type="text" name="nome"
        value="<?=$produto->getNome() ?>">
    </div>

    <div class="form-group">
        <label>Preco:</label>
            <input type="text" name="preco" class="form-control"  
                value="<?=$produto->getPreco() ?>">

    </div>

<div class="form-group">
        <label>Descricao:</label>
            <textarea class="form-control" name="descricao"><?=$produto->getDescricao() ?></textarea>
    </div>

    <div class="form-group">
        <label>Cor:</label>
            <select name="cor_id" class="form-control">
            <?php
            foreach($cores as $cor) :
            $essaEhACor = $produto->getCor()->getId()
            == $cor->getId();
            $selecao = $essaEhACor ? "selected='selected'" : "";
            ?>
                <option value="<?=$cor->getId() ?>" <?=$selecao ?> >
                        <?=$cor->getNome() ?>
                </option>
                <?php endforeach ?>

            </select>
    </div>
    <div class="form-group">
        <label>Tamanho:</label>
            <select name="tamanho_id" class="form-control">
            <?php
            foreach($tamanhos as $tamanho) :
            $essaEhATamanho = $produto->getTamanho()->getId()
            == $tamanho->getId();
            $selecao = $essaEhATamanho ? "selected='selected'" : "";
            ?>
                <option value="<?=$tamanho->getId() ?>" <?=$selecao ?> >
                        <?=$tamanho->getNome() ?>
                </option>
                <?php endforeach ?>

            </select>
    </div>
<div class="form-group">
        <label>Categoria:</label>
            <select name="categoria_id" class="form-control">
            <?php
            foreach($categorias as $categoria) :
            $essaEhACategoria = $produto->getCategoria()->getId()
            == $categoria->getId();
            $selecao = $essaEhACategoria ? "selected='selected'" : "";
            ?>
            <option value="<?=$categoria->getId() ?>" <?=$selecao ?> >
                    <?=$categoria->getNome() ?>
            </option>
        <?php endforeach ?>

    </select>
    </div>

<div class="form-group">
        <label>Imagem do Produto:</label>
            <img src="fotos/<?= $produto->getFoto() ?>.jpg">
    </div>

<div class="form-group">
        <label>Upload da Imagem:</label>
            <input type="file" name="foto" class="form-control"  
                value="foto">
<br>

        <button class="btn btn-danger" type="submit">Salvar</button>
</form>

</article>
</main>

</div> <!-- /container -->

Sergio,

Existem alguns problemas com a forma como você está usando.

Primeiro, na função buscaProduto, você tem a segunte chamada:

$produto->setFoto( $_array["foto"]);

Esse $_array, não existe no escopo desta função, você está usando o $array e não $_array.

O conteúdo desta variável é resultante da chamada:

$array = mysqli_fetch_assoc($resultado);

Isso significa que na variável $array só irá existir os campos que você definiu na query.

Outro problema, nesta mesma função você está chamando a setFoto, e passando um valor do array como parâmetro.

Ai existe um problema, pois a função setFoto está programada para tratar um arquivo que é enviado ao servidor, ou seja, apenas um $_FILES['foto'].

Em resumo, este é o problema de você não conseguir exibir a imagem, pois a função setFoto serve para processar e adicionar nos atributos do objeto $produto os valores de um arquivo enviado, e não algo recuperado do banco.

O que você precisa fazer, é recuperar o campo com o nome da foto que você tem no banco, e colocar o valor resultante no src da tag img.

E o mesmo serve para os demais locais onde você quer exibir os dados do produto.

Tudo o que for relacionado com a foto, não pode ser recuperado usando o setFoto, ele serve apenas para o upload.

Você deve então popular os atributos do objeto $produto de outra forma, quando os dados são recuperados do banco.

O que você tem até o momento funciona apenas para executar o upload e registrar no banco, mas não estão ok para recuperar esses dados, pelo menos não como estão no momento.

Oi Adriano obrigado, acho que não entendi corretamente. ainda não obtive sucesso. Veja se a forma como eu penso faz sentido:

Preciso buscar no BD o caminho da foto que está dentro da pasta. Depois, no meu formulário encontrar uma forma de ligar o caminho da foto com o id da foto que está guardada na pasta fotos e exibi-la.

Fiz assim:

1) Alterei buscaProduto passando o array da seguinte forma, entendendo que o objetivo do buscaProduto é buscar o produto no BD e disponibilizar o resultado para o formulário.

$produto->setFoto( $array['foto']);

porque estou buscando apenas uma informação no BD como se fosse nome, descrição do produto.

2) No formulário eu alterei o campo onde mostra a foto para;

<div class="form-group">
        <label>Imagem do Produto:</label>
            <img src="fotos/<?= $produto->getFoto() ?>.jpg">
    </div>

Assim eu utilizo o getFoto da classe produto para me mostrar a foto.

Este getFoto deveria ir buscar esse nome de foto na pasta fotos e exibir a imagem?

mas não está acontecendo assim.

Sergio,

É assim, você tem a query dentro da função buscaProduto:

$query = "select p.*, c.nome as categoria_nome, co.nome as cor_nome, t.nome as tamanho_nome
from produtos p 
inner join categorias c on(p.categoria_id = c.id)
inner join cor co on(p.cor_id = co.id) 
inner join tamanho t on(p.tamanho_id = t.id)
where p.id = {$id}";

Você consegue retornar os dados do banco. Isso significa que no seu $array, resultante da linha:

$array = mysqli_fetch_assoc($resultado);

Terá os mesmos itens buscados, ou seja. $array['categoria'], $array['cor_nome'], $array['tamanho_nome']

Não tem um item chamado $array['foto'], pois você não buscou este item.

Ou seja, a linha:

$produto->setFoto( $array['foto']);

Não funciona, pois o parâmetro não existe, e mesmo que existisse não é um arquivo que foi feito upload agora no sistema.

E também os demais campos não funcionam, veja:

$produto->setId( $array['id']);
$produto->setNome( $array['nome']);
$produto->setPreco( $array['preco']);
$produto->setCodigo( $array['codigo']);
$produto->setDescricao( $array['descricao']);

Tudo o que você quer recuperar desse $array, precisa estar na sua query.

Uma sugestão, é você passar o id do seu produto para a função getFoto que você criou.

Dentro dela, minha sugestão é que seja:

function getFoto( $conexao  ){
       $id = $this->getId();

    $query = "SELECT
                    foto

              FROM produtos

              WHERE id = {$id}";

    $resultado = mysqli_query($conexao, $query);
    $array = mysqli_fetch_assoc($resultado);

    return $array['foto'];
}

Mas para que ela funcione, você precisa corrigir sua query da busca de produto, adicionando os campos, e passar a conexão como parâmetro.

Uma ultima alteração, seria esta na função buscaProduto:

$produto->setId( $id );

Assim você garante que o ID estará no objeto, e com estas mudanças que sugeri, acredito que a imagem apareça.

Mas não sei quanto aos demais campos, pois como falei, esses valores não estão na sua query de consulta.

Adriano, não deixe de notar que no SELECT dele ele também pega p.*, logo retorna todos os campos da tabela Produtos. Ou seja, deveria sim retornar o campo Foto.

Bruno,

Verdade, bem observado.

Não notei este detalhe.

De qualquer forma.

A função setFoto trata apenas upload, sendo assim, a getFoto não irá trazer o valor esperado.

Será necessário retornar o nome do arquivo de outra forma, mesmo que seja necessário criar outra função para isso.

Obrigado Bruno e Adriano, fiquei um pouco confuso, poderiam, se possivel, me dar uma olhada no codigo e corrigi-lo?

Estou tentando até agora tudo que me vem a mente e não está funcionando.

Adriano, podes me ajudar mais uma vez para encerrarmos esse post e eu conseguir mostrar a foto?

Veja meu raciocínio:

no formulário de alteração, eu preciso exibir a foto, exatamente como os outros dados do produto. Para isso:

  • preciso buscar os dados do produto no BD. Para isso utilizo a função listaProdutos.
  • No BD a coluna foto mostra o caminho (nome) da foto. E seria isso que a função lista Produtos traz.
  • Para acessar esse caminho (nome da foto) eu utilizo a classe produto no getFoto da mesma maneira dos outros dados dos produtos:
public function getFoto()
{
return $this->foto;
}

para exibir no formulário eu utilizo:

 <img src="fotos/<?= $produto->getFoto() ?>.jpg">

Porque ainda não está funcionando? Qual a diferença entre o dado da foto e os outros dados do produto que vem do BD?

Encontrei mais um problema que não sei como resolver existem fotos que terminam em .jpg e .jpeg e .png e no codigo é o codigo do produto + a extensão do arquivo, como resolvo isso?

Olá Sérgio.

Cara, como está essa sua tabela de produtos? Consegue me mandar uma imagem? Preciso saber como fica um dado na coluna Foto. É só o nome da imagem? A extensão é salva junto na tabela?

Muito obrigado pelo seu retorno Bruno, meu problema como você viu era que estava tentando utilizar o getFoto para devolver o caminho da foto no BD mas na função listaProduto eu estou utilizando o setFoto. Tenho também a função buscaProduto. Como a ajuda do Joel Spinelli aqui no forum fizemos o seguinte: Criamos uma função para passar os dados na classe produto:

public function carregaCaminhoFoto($foto)  {
        $this->foto = $foto;
}

alterei as duas funções lista e buscaProduto da seguinte para passar as fotos:

$produto->carregaCaminhoFoto($array['foto']);

e no caso da Extensão eu pensava que precisava utilizar, mas tentei sem e funcionou e alterei no formulário da seguinte forma (sem extensão)

<div class="form-group">
        <label>Imagem do Produto:</label>
            <img src="fotos/<?=$produto->getFoto() ?>">
    </div>

Desse jeito tudo funcionou.

De qualquer forma, eu te agradeço a consideração e preocupação em ajudar. Muito obrigado mesmo.

abraços

Que bom que conseguiram se juntar e resolver :)

Só um detalhe: a função carregaCaminhoFoto() ficou no lugar da antiga setFoto(), então? Porque a antiga setFoto() estava assim como está essa nova, só mudou o nome.

Oi Bruno, isso mesmo só muda o nome para ligar a função. E fica tudo resolvido. abração!