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

Dúvida no Ex. 4 da Aula 8 - DAO - Data Access Object

Boa tarde pessoal. Estou com mais um erro, agora no formulário de alteração. Já consigo inserir e excluir o produto, mas na hora que chamo para alterar aparece o seguinte erro: Fatal error: Call to a member function setNome() on array in C:\wamp64\www\loja\produto-formulario-base.php on line 8 Se no produto-formulario-base.php eu retirar a função setNome, deixar apenas como produto['nome'] por exemplo, o campo vem preenchido para alteração, mas ai o formulário de adição começa a dar o mesmo erro acima. Segue o código do produto-altera-formulario.php

<?php
require_once ("header.php");

$categoria = new Categoria();
$categoria->setId($_GET['categoria_id']);

if(array_key_exists('usado', $_POST)){
    $usado = "true";
} else {
    $usado = "false";
}

$produto = new Produto($_POST['nome'], $_POST['preco'], $_POST['descricao'], $categoria, $usado);
$produto->setId($_GET['id']);


$usado = $produto->getUsado() ? "checked='checked'" : "";

$produtoDAO = new produtoDAO($conexao);
$produto = $produtoDAO->buscaProduto($produto);

#var_dump($produto);

$categoriaDAO = new categoriaDAO($conexao);
$categorias=$categoriaDAO->listaCategorias();

?>
<h1>Formulário de alteração de produtos</h1>
<form action="altera-produto.php" method="post">
    <input type="hidden" name="id" value="<?=$produto['id']?>" />
    <table class="table">

        <?php include ("produto-formulario-base.php");?>

        <tr>
            <td><button class="btn btn-primary" type="submit">Alterar</td>
        </tr>
    </table>
</form>
<?php include("footer.php");?>

E o código do produto-formulario-base.php

<tr>
    <td>Nome: </td>
    <td><input class="form-control" type="text" name="nome" value="<?=$produto->setNome($_POST['nome'])?>"></td>
</tr>
<tr>
    <td>Preco: </td>
    <td><input class="form-control" type="number" name="preco" value="<?=$produto->setPreco($_POST['preco'])?>"></td>
</tr>
<tr>
    <td>Descrição: </td>
    <td><textarea class="form-control" name="descricao"><?=$produto->setDescricao($_POST['descricao'])?></textarea>
</tr>
<tr>
    <td></td>
    <td><input type="checkbox" name="usado" <?=$usado?> value="true"> Usado
</tr>
<tr>
    <td>Categorias: </td>
    <td>
        <select class="form-control" name="categoria_id">
            <?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>
    </td>
</tr>
19 respostas

sem as class Produto não tem como lhe ajudar

Opa. Tá na mão: A class produto:

<?php
class Produto{
    private $id;
    private $nome;
    private $preco;
    private $descricao;
    private $categoria;
    private $usado;

    function __construct($nome, $preco, $descricao, Categoria $categoria, $usado)
    {
        $this->setNome($nome);
        $this->setPreco($preco);
        $this->setDescricao($descricao);
        $this->setCategoria($categoria);
        $this->setUsado($usado);
    }

    function __toString()
    {
        return "Nome: ".$this->getNome().", Preço: ".$this->getPreco().", Descricao: ".$this->getDescricao().", Categoria: ".$this->getCategoria().", Usado: ".$this->getUsado();
}

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

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

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

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

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

    public function setPreco($preco){
        $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 getUsado(){
        return $this->usado;
    }

    public function setUsado($usado){
        $this->usado = $usado;
    }

    public function valorComDesconto($valor=0.05){
        if ($valor > 0 && $valor < 1){
            $this->preco -= $this->preco * $valor;
            return $this->preco;
        }
    }
}

A classe produtoDAO:

<?php
class produtoDAO{

    private $conexao;
    private $nome;
    private $preco;
    private $descricao;
    private $categoria_id;
    private $usado;

    function __construct($conexao)
    {
        $this->conexao = $conexao;
    }

    function listaProdutos(){
        $produtos = [];
        $resultado = mysqli_query($this->conexao, "select p.*, c.nome as categoria_nome from produtos as p join categorias as c on p.categoria_id = c.id");
        while ($produto_atual = mysqli_fetch_assoc($resultado)) {
            $categoria = new Categoria();
            $categoria->setNome($produto_atual['categoria_nome']);

            $produto = new Produto($produto_atual['nome'],$produto_atual['preco'],$produto_atual['descricao'],$categoria,$produto_atual['usado']);
            $produto->setId($produto_atual['id']);

            array_push($produtos, $produto);
        }
        return $produtos;
    }

    function buscaProduto(Produto $produto){
        $query = "select * from produtos where id = '{$produto->getId()}'";
        $resultado = mysqli_query($this->conexao, $query);
        return mysqli_fetch_assoc($resultado);
    }

    function insereProduto(Produto $produto){
        $this->nome = mysqli_real_escape_string($this->conexao, $produto->getNome());
        $this->preco = mysqli_real_escape_string($this->conexao, $produto->getPreco());
        $this->descricao = mysqli_real_escape_string($this->conexao, $produto->getDescricao());
        $this->categoria_id = mysqli_real_escape_string($this->conexao, $produto->getCategoria()->getId());
        $this->usado = mysqli_real_escape_string($this->conexao, $produto->getUsado());
        $query = "insert into produtos (nome, preco, descricao, categoria_id, usado) values ('{$produto->getNome()}' , {$produto->getPreco()}, '{$produto->getDescricao()}', {$produto->getCategoria()->getId()}, {$produto->getUsado()})";
        return mysqli_query($this->conexao, $query);
    }

    function removeProduto(Produto $produto){
        $query = "delete from produtos where id = '{$produto->getId()}'";
        var_dump($query);
        return mysqli_query($this->conexao, $query);
    }

    function alteraProduto(Produto $produto){
        $query = "update produtos set nome='{$produto->getNome()}', preco={$produto->getPreco()} , descricao='{$produto->getDescricao()}', categoria_id={$produto->getCategoria()->getId()} , usado={$produto->getUsado()} where id = '{$produto->getId()}'";
        return mysqli_query($this->conexao, $query);
    }
}

todos os seus values estão errados , você esta tetando editar logo a informação vem do banco e vc esta usando o metodo set que serve para setar um valor que viria de um post porem você não esta fazendo um post de nada, você esta pegando os dados da base de dados e colocando dentro da variavel $produto tanto que vc usa $produto['id'] depois do form , então nos outros campos vc deve fazer a mesma forma porem só que passando os nomes do campo correto $produto['nome_do_campo'], caso vc retorne um objeto produto quando vc faz a consulta voce poderia usar **$produto->getNome()**.

Errado
 <td><input class="form-control" type="text" name="nome" value="<?=$produto->setNome($_POST['nome'])?>"

Correto

 <td><input class="form-control" type="text" name="nome" value="<?=$produto['nome']?>"
ou
 <td><input class="form-control" type="text" name="nome" value="<?=$produto->getNome()?>"

Certo, mas essa alteração eu já havia feito. Dessa forma a alteração funciona, mas eu começo a ter o mesmo erro que dá na alteração quando vou inserir um produto novo.

Voce tem pode fazer um if ternario no value dessa forma (isset($produto['nome'])?$produto['nome']:''

Ou crie um formulario para cada um

Opa. Fiz o if dessa forma: (isset($produto['nome'])) ? $produto['nome'] : $produto->setNome($_POST['nome'])?>. Na alteração funcionou mas na adição não. Ou tá errado do jeito que eu fiz ou não entra no if.

Ola Samuel você ainda esta fazendo do jeito que eu disse que era errado :) , vc n usa o método set dentro de um campo input porque os valores ainda não existem então nao tem como você setar eles, então eles so vão existir quando vc fizer o submite. Voce tem que usar como lhe enviei em cima com um espaço em branco pq se o valor nao tiver setado ele vai colocar um vazio e na adição os values tem que ser vazio já que eles não existem e você esta querendo adicionar algo novo

Opa. Então Alan, não vi que você tinha colocado ' ' no final, erro meu. Fiz as alterações agora e mesmo assim não está funcionando. Agora o erro que dava na tela de alteração está dando na tela de inserção. Igualzinho. Segue o código do meu formulário base:

Nome:

Preco:

Descrição: <?=isset($produto['descricao']) ? $produto['descricao'] : ' '?>

value="true"> Usado

Categorias: <?php foreach($categorias as $categoria) : $essaEhaCategoria = $produto->getCategoria()->getId() == $categoria->getId(); $selecao = $essaEhaCategoria ? "selected='selected'" : ""?> > <?=$categoria->getNome()?> <?php endforeach ?>

Cara, não sei mais o que fazer. Não quero ter que fazer outro formulário, vai ser como andar pra trás.

Cara, marquei como solucionada mas não está, cliquei errado ¬¬

Opa Samuel, pode ficar tranquilo seu problema é muito fácil de ser revolvido estou aqui para ajudá-lo e fazer você entender como funciona :)

Segue um codigo que eu fiz para você entender como usar oque eu havia lhe dito nos post anteriores

<?php
  if ($_POST) {
      $produto['nome'] = $_POST['nome'];
      $produto['quantidade'] = $_POST['quantidade'];
      /**
       * Descomente esse var_dump e você vera que a variavel produto so vai recever valor quando ela tiver o primeiro post
       */
      //var_dump($produto);
  }

 ?>

<form class="" action="" method="post">
  <!-- Caso o valor não exista ele vai insterir o vazio depois dos : -->
  <input type="text" name="nome" value="<?=isset($produto['nome']) ? $produto['nome'] : ''?>">
  <input type="text" name="quantidade" value="<?=isset($produto['quantidade']) ? $produto['quantidade'] : ''?>">

  <input type="submit" name="name" value="Enviar">
</form>

Cara. Esgotei minhas possibilidades. Fiz do jeitinho que vc passou no exemplo. Criei um arquivo de testes com o seu exemplo e fiz, e deu certo, mas no meu projeto não vai. Tem como eu te enviar o projeto pra vc dar uma olhada?

sim, pode me enviar que eu vejo aqui

Aqui. Dentro tem uma pasta chamada BD, tem o script para criação do banco de dados. Usuário e senha estão no script.

solução!

Então tem alguns erros de class no seu codigo com letras minusculas como categoria e produto.

Para resolver o problema de fazer a buscar retorna um objeto de Produtos eu fiz de uma forma simples porem não é a melhor pratica porem para você entender eu fiz dessa forma

ProdutoDao

  function buscaProduto(Produto $produto){
        $query = "select * from produtos where id = '{$produto->getId()}'";
        #var_dump("$query");
        $resultado = mysqli_query($this->conexao, $query);
        $resultadoFetch = mysqli_fetch_assoc($resultado);
        $produto->setNome($resultadoFetch['nome']);
        $produto->setPreco($resultadoFetch['preco']);
        $produto->setDescricao($resultadoFetch['descricao']);
        $produto->setUsado($resultadoFetch['usado']);
        $categoria = new Categoria();
        $categoria->setId($resultadoFetch['categoria_id']);
        $produto->setCategoria($categoria);
        return $produto;
    }

Miolo do Formulario

<tr>
    <td>Nome: </td>
    <td><input class="form-control" type="text" name="nome" value="<?=!is_null($produto->getNome()) ? $produto->getNome() :'';?>"></td>
</tr>
<tr>
    <td>Preco: </td>
    <td><input class="form-control" type="number" name="preco" value="<?=!is_null($produto->getPreco()) ? $produto->getPreco() :'';?>"></td>
</tr>
<tr>
    <td>Descrição: </td>
    <td><textarea class="form-control" name="descricao"><?=!is_null($produto->getDescricao()) ? $produto->getDescricao() :''?></textarea>
</tr>
<tr>
    <td></td>
    <td><input type="checkbox" name="usado" <?=$usado?> value="true"> Usado
</tr>
<tr>
    <td>Categorias: </td>
    <td>
        <select class="form-control" name="categoria_id">
            <?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>
    </td>
</tr>

alterar

<input type="hidden" name="id" value="<?=$produto->getId()?>">

Esta com erro de salvar porem deixei isso para você tentar resolver é bem simples, obs sempre user var_dump para você debugar e sempre fique de olho no error do php ele vai te ajudar bastante descobrir tudo que vc precisa

Cara, deu super certo agora. Pelo que entendi, vc alterou só o método buscaProduto para que a cada chamada ele faz o select vai atribuindo o valor retornado, correto. Não entendi muito bem o pq vc fez isso sendo que a função buscaProduto, do jeito que ela estava antes já trazia os resultados. Pra tentar entender eu comentei o seu buscaProduto e deixei o antigo, ai ele dá o seguinte erro: Fatal error: Call to a member function getId() on array Qual foi a sacada de usar os setters dentro do buscaProduto?

De qualquer maneira, deu certo, muito obrigado. Agora vamos pra segunda briga, utilizar o UsuarioDAO rsrsrs.

Teve os values também que vc alterou, agora ele checa se o valor é diferente de NULL

então oque eu fiz foi colocar o array no objeto produto, você estava uma hora usando o objeto Produto e outra hora usando um array então deixei tudo dentro do objeto já que você passa o objeto como parâmetro no buscarProduto eu só aproveitei ele e passei o resultado e retornei ele mesmo na função. Espero ter ajudado

Não sabe o tanto que ajudou. Vlw.

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software