Solucionado (ver solução)

Importante

Você está vendo a versão anterior da nova experiência da Alura que estamos preparando para você. Em breve, ela ganha uma identidade visual novinha totalmente pensada em potencializar seus estudos!

Solucionado
(ver solução)
11
respostas

Dificuldade nos getters e setters

Segue o erro apresentado:

Fatal error: Uncaught Error: Call to a member function getNome() on null in C:\xampp\htdocs\loja\Projeto-de-php\loja\produto-lista.php:20 Stack trace: #0 {main} thrown in C:\xampp\htdocs\loja\Projeto-de-php\loja\produto-lista.php on line 20

Segue os códigos: adiciona-produto.php, altera-produto.php, banco-categoria.php, banco-produto.php, produto-altera-formulario.php, produto-formulario-base.php, produto-formulario.php e produto-lista.php.

adiciona-produto.php:

<?php 
require_once("cabecalho.php");
require_once("banco-produto.php");
require_once("logica-usuario.php");
require_once("class/Produto.php");
require_once("class/Categoria.php");

verificaUsuario();

$categoria = new Categoria();
$categoria->getId($_POST['categoria_id']);

$produto = new Produto();
$produto->getNome($_POST['nome']);
$produto->getPreco($_POST['preco']);
$produto->getDescricao($_POST['descricao']);

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

$produto->getCategoria = $categoria;

if(insereProduto($conexao, Produto $produto)) { ?>
    <p class="text-success">O produto <?= $produto->getNome() ?>, <?= $produto->getPreco() ?> foi adicionado.</p>
<?php 
} else {
    $msg = mysqli_error($conexao);
?>
    <p class="text-danger">O produto <?= $produto->getNome() ?> não foi adicionado: <?= $msg?></p>
<?php
}
?>

<?php include("rodape.php"); ?>

altera-produto.php

<?php
require_once("cabecalho.php");
require_once("banco-produto.php");
require_once("class/Produto.php");
require_once("class/Categoria.php");

$categoria = new Categoria();
$categoria->id = $_POST['categoria_id'];

$produto = new Produto();
$produto->getId($_POST['id']);
$produto->getNome($_POST['nome']);
$produto->getPreco($_POST['preco']);
$produto->getDescricao($_POST['descricao']);
$produto->getCategoria($categoria);
$produto->getCategoria()->getid($_POST["categoria_id"]);
$produto->getUsado($_POST["usado"]);

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



if(alteraProduto($conexao, $produto)) { ?>
    <p class="text-success">O produto <?= $produto->nome ?>, <?= $produto->preco ?> foi alterado.</p>
<?php 
} else {
    $msg = mysqli_error($conexao);
?>
    <p class="text-danger">O produto <?= $produto->nome ?> não foi alterado: <?= $msg?></p>
<?php
}
?>

<?php include("rodape.php"); ?>

banco-categoria.php

<?php
require_once("conecta.php");
require_once("class/Categoria.php");

function listaCategorias($conexao) {

    $categorias = array();
    $query = "select * from categorias";
    $resultado = mysqli_query($conexao, $query);

    while($categoria_array = mysqli_fetch_assoc($resultado)) {

        $categoria = new Categoria();
        $categoria->getId($categoria_array['id']);
        $categoria->getNome($categoria_array['nome']);

        array_push($categorias, $categoria);
    }

    return $categorias;
}
11 respostas

banco-produto.php

<?php
require_once("conecta.php");
require_once("class/Produto.php");
require_once("class/Categoria.php");

function listaProdutos($conexao) {

    $produtos = array();
    $resultado = mysqli_query($conexao, "select p.*,c.nome as categoria_nome 
        from produtos as p join categorias as c on c.id=p.categoria_id");

    while($produto_array = mysqli_fetch_assoc($resultado)) {

        $categoria = new Categoria();
        $categoria->getNome($produto_array['categoria_nome']);

        $produto = new Produto();
        $produto->getId($produto_array['id']);
        $produto->getNome($produto_array['nome']);
        $produto->getDescricao($produto_array['descricao']);
        $produto->getCategoria($categoria);
        $produto->getPreco($produto_array['preco']);
        $produto->getUsado($produto_array['usado']);

        array_push($produtos, $produto);
    }

    return $produtos;
}

function insereProduto($conexao, Produto $produto) {

    $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($conexao, $query);
}

function alteraProduto($conexao, 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($conexao, $query);
}

function buscaProduto($conexao, $id) {

    $query = "select * from produtos where id = {$id}";
    $resultado = mysqli_query($conexao, $query);
    $produto_buscado = mysqli_fetch_assoc($resultado);

    $categoria = new Categoria();
    $categoria->getId($produto_buscado['categoria_id']);

    $produto = new Produto();
    $produto->getId($produto_buscado['id']);
    $produto->getNome($produto_buscado['nome']);
    $produto->getDescricao($produto_buscado['descricao']);
    $produto->getCategoria($categoria);
    $produto->getPreco($produto_buscado['preco']);
    $produto->getUsado($produto_buscado['usado']);

    return $produto;
}

function removeProduto($conexao, $id) {

    $query = "delete from produtos where id = {$id}";

    return mysqli_query($conexao, $query);
}

produto-altera-formulário.php

<?php
require_once("cabecalho.php");
require_once("banco-categoria.php");
require_once("banco-produto.php");

$id = $_GET['id'];
$produto = buscaProduto($conexao, $id);
$categorias = listaCategorias($conexao);

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

?>

<h1>Alterando produto</h1>
<form action="altera-produto.php" method="post">
    <input type="hidden" name="id" value="<?=$produto->getId()?>">
    <table class="table">
        <?php include("produto-formulario-base.php"); ?>
        <tr>
            <td>
                <button class="btn btn-primary" type="submit">Alterar</button>
            </td>
        </tr>
    </table>
</form>

<?php include("rodape.php"); ?>

produto-formulario-base.php

<tr>
    <td>Nome</td>
    <td>
        <input class="form-control" type="text" name="nome" 
            value="<?=$produto->getNome()?>">
    </td>
</tr>
<tr>
    <td>Preço</td>
    <td>
        <input class="form-control" type="number" step="0.01" name="preco" 
            value="<?=$produto->getPreco()?>">
    </td>
</tr>
<tr>
    <td>Descrição</td>
    <td>
        <textarea class="form-control" name="descricao"><?=$produto->getDescricao()?></textarea>
    </td>
</tr>
<tr>
    <td></td>
    <td><input type="checkbox" name="usado" <?=$produto->getUsado()?> value="true"> Usado
</tr>
<tr>
    <td>Categoria</td>
    <td>
        <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->id?>" <?=$selecao?>>
                    <?=$categoria->getNome()?>
                </option>
            <?php 
            endforeach
            ?>
        </select>
    </td>
</tr>

produto-formulario.php

<?php
require_once("cabecalho.php");
require_once("banco-categoria.php");
require_once("logica-usuario.php");
require_once("class/Produto.php");
require_once("class/Categoria.php");

verificaUsuario();

$categoria = new Categoria();
$categoria->setId(1);

$produto = new Produto();
$produto->getCategoria($categoria);

$categorias = listaCategorias($conexao);

?>    

<h1>Formulário de produto</h1>
<form action="adiciona-produto.php" method="post">
    <table class="table">

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

        <tr>
            <td>
                <button class="btn btn-primary" type="submit">Cadastrar</button>
            </td>
        </tr>
    </table>
</form>

<?php include("rodape.php"); ?>

produto-lista.php

<?php
require_once("cabecalho.php");
require_once("banco-produto.php");
require_once("logica-usuario.php");

verificaUsuario();
?>


<table class="table table-striped table-bordered">
    <?php
    $produtos = listaProdutos($conexao);
    foreach($produtos as $produto) :
    ?>
        <tr>
            <td><?= $produto->getNome() ?></td>
            <td><?= $produto->getPreco(); ?></td>
            <td><?= $produto->precoComDesconto(); ?></td>
            <td><?= substr($produto->getDescricao(), 0, 40); ?></td>
            <td><?= $produto->getCategoria()->getNome(); ?></td>

            <td>
                <a class="btn btn-primary" 
                    href="produto-altera-formulario.php?id=<?=$produto->getId()?>">
                    alterar
                </a>
            </td>
            <td>
                <form action="remove-produto.php" method="post">
                    <input type="hidden" name="id" value="<?=$produto->getId()?>">
                    <button class="btn btn-danger">remover</button>
                </form>
            </td>
        </tr>
    <?php
    endforeach
    ?>    
</table>

<?php include("rodape.php"); ?>

Ao tentar realizar a inserção de um novo produto, não é possível cadastrar uma categoria porque não me mostra a opção para selecionar.

Oi Hugo, pelo mensagem de erro, acontece quando você lista os produtos, não é isso? Cola o Produto.php aqui pra gente ver?

Produto.php

<?php

class Produto {

    private $id;
    private $nome;
    private $preco;
    private $descricao;
    private $categoria;
    private $usado;

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



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

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



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


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


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


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

    public function precoComDesconto($valor = 0.6){
        if ($valor >= 0 && $valor <= 0.5) {
            return $this->preco - ($this->preco * $valor);
        }else{
            $texto = "Desconto inválido";
            ?>
            <p class="alert-danger form-control"><?=$texto?></p>
    <?php  
        }

    }


}

?>

Fala Hugo, tudo certo?! :D

Vamos lá cara, pelo que eu entendi logo de cara ao olhar seu código foi que você está dando GET em objetos logo acima instanciados e eles vem "vazios" para que você possa SETAR valores neles e manipula-los como quiser.

Como no Exemplo abaixo. (Você "gettando" ao invés de setar os valores.)

$categoria = new Categoria();
$categoria->getId($_POST['categoria_id']);

$produto = new Produto();
$produto->getNome($_POST['nome']);
$produto->getPreco($_POST['preco']);
$produto->getDescricao($_POST['descricao']);

Recebendo os valores e setando no objeto previamente instanciado.

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

$produto = new Produto();
$produto->setNome($_POST['nome']);
$produto->setPreco($_POST['preco']);
$produto->setDescricao($_POST['descricao']);

Como você estava fazendo, ele pegava todos os valores dos atributos do objeto que você acabou de instanciar (NULL) e persistia no banco. Sendo assim, quando você realizava a consulta para ter o retorno dos valores, os mesmos retornavam como foram persistidos (NULOS), consistindo no erro. :)

Boa Gabriel, me parece ser esse mesmo o problema. Hugo, dá uma olhada, corrige e se tudo tiver certinho, marca a resposta do Gabriel como solução, tá bem?

Olá, entendi o que estava fazendo de errado, creio que fiz as alterações certas, publiquei os códigos no git - > https://github.com/HugoNCastro/Projeto-de-php/tree/master/loja

Após fazer as alterações conforme a explicação do Gabriel, vi que no produto-formulario.php eu não consigo mostrar as categorias para adicionar usando $produto->getCategoria($categoria); . Porém usando set no lugar do get o código me mostra um erro na linha 61 da classe produto, onde justamente está o setCategoria(). Até agora foi o primeiro erro que achei :|

Opa mano, tudo bem?! Olha eu novamente por aqui!!

Então cara, baixei o seu projeto e estou fazendo algumas correções em relação a sintaxe apenas, notei que possuiam erros nas Models (Categoria/Produto), alguns erros no arquivo CriaProduto entre outros..

Percebi que você está usando um banco local, você poderia commitar o script .sql do banco que você está usando? Não se preocupe, usarei apenas para os testes..

Estou anotando todas as mudanças que estou realizando, e mantendo tambem o seu codigo original logo abaixo o meu corrigido, para que você possa analisar onde estavam os erros. No aguardo do script, abraço!

Boa Gabriel, não esquece de compartilhar aqui com a gente depois tá bem?

solução!

E aí Hugo, tudo numa boa?!

Então cara, como disse anteriormente baixei o seu projeto (criei um fork na verdade) para dar uma olhada no código e corrigir os eventuais erros. Solicitei uma copia do seu script, porém, como não obtive resposta não pude olhar/testar os seus arquivos de conexão. Enfim, fiz algumas correções nos arquivos. Criei um arquivo com o nome "ALTERAÇÕES" nele está descrito tudo que modifiquei e os respectivos arquivos..

Ah sim, não se preocupe que eu mantive TUDO que você fez previamente, todas as correções que fiz mantive seu código original (comentado) para que você possa ver a diferença entre os mesmos e também comentários sobre o que estava errado e alguns também explicando o porque o que fiz estava certo. No mais é isso, dê uma lida nos arquivos e qualquer coisa estamos aqui!!

Link do Fork: https://github.com/gabriel-sisjr/Projeto-de-php

Basicamente é isso, forte abraço e até a próxima!!!

Vlw mano. Desculpa não ter te enviado os dados de conexão tô meio ocupado esses dias.