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

é seguro usar atributos públicos

Nos curso "PDO" , foi criado um projeto de gestão de estoque e estou tentando replicar o conhecimento obtido lá, mas estou enfrentando uma dúvida, no curso o instrutor definiu os atributos como públicos porém em outros cursos os instrutores dizem que os atributos devem ser privados e os metodos podem ser publicos.

exemplo:

<?php

class Posts
{
    public $id;
    public $titulo;
    public $descricao;
    public $conteudo;

afinal, é seguro?

10 respostas

Como boa prática não é recomendado, porque exige cuidado extra do programador e/ou da equipe de desenvolvimento para que os dados do modelo em questão não sejam manipulados de forma inadequada. O recomendado é sempre ter métodos públicos que façam o acesso aos atributos do objeto, dessa forma fica mais fácil de prever o comportamento da aplicação, afinal, o que for alheio ao meu modelo só vai ter acesso àquilo que eu disponibilizar. Além disso, eu incluiria a questão de manutenção do código como outro fator importante. Imagina se eu precisar, por qualquer motivo que seja, alterar o nome de algum desses atributos. É uma dor de cabeça sair navegando pela code base tentando achar e atualizar as milhões de referências ao atributo que tenha sido alterado (acreidte, já estive lá hahahaha).

então nesses códigos: new-post.php

    $titulo = $_POST['titulo'];
    $descricao = $_POST['descricao'];
    $conteudo = $_POST['conteudo'];
    $imagemDestaque = $_POST['imagemDestaque'];
    $status = $_POST['status'];
    $categoria = $_POST['categoria'];

    $publicar = new Posts();
    $publicar->titulo = $titulo;
    $publicar->descricao = $descricao;
    $publicar->conteudo = $conteudo;
    $publicar->imagemDestaque = $imagemDestaque;
    $publicar->status = $status;
    $publicar->categoria = $categoria;
    $publicar->insertPost();

Posts.php

class Posts
{

    public $id;
    public $titulo;
    public $descricao;
    public $conteudo;
    public $imagemDestaque;
    public $status;
    public $categoria;
    public $data;

    public function insertPost(){
         $query = "INSERT INTO tb_posts (titulo, descricao, conteudo, imagemdestaque, status, categoria) VALUES (:titulo, :descricao, :conteudo, :imagemDestaque, :status, :categoria)";
        $connect = Connection::takeConnection();
        $result = $connect->prepare($query);
        $result->bindValue(':titulo', $this->titulo);
        $result->bindValue(':descricao',  $this->descricao);
        $result->bindValue(':conteudo',  $this->conteudo);
        $result->bindValue(':imagemDestaque',  $this->imagemDestaque);
        $result->bindValue(':status',  $this->status);
        $result->bindValue(':categoria',  $this->categoria);
        $result->execute();


    }
}

o que eu poderia fazer para resolver esse problema? passa pelo uso do __construct()?

Sim, pode ser feito através do construtor. Existe outra opção também, que é chamada de "encapsulamento de campo" (ou algo assim). No caso, vamos criar um método que busca (também conhecido como getter) e outro de define (também chamado de setter) um valor para um atributo do objeto.

Exemplo para o atributo de descrição:


// Método para obtenção da descrição.
public function getDescricao(): string
{
    return $this->descricao;
}

// Método para definir a descrição
public function setDescricao(string $descricao): void
{
    $this->descricao = $descricao;
}

// Edit 1
// Assim, para obtermos a descrição de um post, faríamos algo como:
$post = new Post();
$descricao = $post->getDescricao();

// Se fosse necessário fazermos a alteração da descrição:
$post->setDescricao('Nova descrição para o post...');

Embora não seja uma regra, getters e setters costumam seguir a conveção para nomenclatura de getNomeDoAtributo e setNomeDoAtributo, respectivamente.

mas nesse caso como estou enviando esses dados para o BD eu posso fazer assim:

new-post.php

<?php
require 'db/config.php';
require 'src/Connection.php';
require 'src/Posts.php';

if ($_SERVER['REQUEST_METHOD'] === 'POST'){

    $titulo = $_POST['titulo'];
    $descricao = $_POST['descricao'];
    $conteudo = $_POST['conteudo'];
    $imagemDestaque = $_POST['imagemDestaque'];
    $status = $_POST['status'];
    $categoria = $_POST['categoria'];

    $publicar = new Posts();
    $publicar->insertPost($titulo, $descricao, $conteudo, $imagemDestaque, $status, $categoria);
}

e Posts.php

<?php

class Posts
{

    private $id;
    private $titulo;
    private $descricao;
    private $conteudo;
    private $imagemDestaque;
    private $status;
    private $categoria;
    private $data;

    public function insertPost($titulo, $descricao, $conteudo, $imagemDestaque, $status, $categoria){
        $query = "INSERT INTO tb_posts (titulo, descricao, conteudo, imagemdestaque, status, categoria)
VALUES (:titulo, :descricao, :conteudo, :imagemDestaque, :status, :categoria)";
        $connect = Connection::takeConnection();
        $result = $connect->prepare($query);
        $result->bindValue(':titulo', $titulo);
        $result->bindValue(':descricao',  $descricao);
        $result->bindValue(':conteudo',  $conteudo);
        $result->bindValue(':imagemDestaque',  $imagemDestaque);
        $result->bindValue(':status',  $status);
        $result->bindValue(':categoria',  $categoria);
        $result->execute();


    }
}

Pode ser feito, mas repare que nesse estamos gravando no banco de dados os argumentos passados a insertPost. Os atributos da instância de Post ficaram vazios.

na verdade pensei em apagar os atributos, já que até nesse momento não estou usando eles, mas como estou no começo não sei se usarei no decorrer do projeto.

Qual seria o problema de usar dessa forma?

O problema mais imediato que eu vejo é que, caso seja necessário utilizar os dados da instância de Post, isso não será possível. Além disso, quando necessário, ficará bem mais complicado de obter e manejar dados do banco de dados.

solução!

alterei o código para usar os atributos da classe:

Post.php

class Posts
{

    private $id;
    private $titulo;
    private $descricao;
    private $conteudo;
    private $imagemDestaque;
    private $status;
    private $categoria;
    private $data;

    public function __construct( $titulo, $descricao, $conteudo, $imagemDestaque, $status, $categoria, $data = false, $id = false)
    {
        $this->titulo = $titulo;
        $this->descricao = $descricao;
        $this->conteudo = $conteudo;
        $this->imagemDestaque = $imagemDestaque;
        $this->status = $status;
        $this->categoria = $categoria;
        if($data){
            $this->data = $data;
        }
        if($id){
            $this->id = $id;
        }
    }
    public function insertPost(){
        $query = "INSERT INTO tb_posts (titulo, descricao, conteudo, imagemdestaque, status, categoria)
VALUES (:titulo, :descricao, :conteudo, :imagemDestaque, :status, :categoria)";
        $connect = Connection::takeConnection();
        $result = $connect->prepare($query);
        $result->bindValue(':titulo', $this->titulo);
        $result->bindValue(':descricao',  $this->descricao);
        $result->bindValue(':conteudo',  $this->conteudo);
        $result->bindValue(':imagemDestaque',  $this->imagemDestaque);
        $result->bindValue(':status',  $this->status);
        $result->bindValue(':categoria',  $this->categoria);
        $result->execute();


    }
}

e new-post.php

<?php
require 'db/config.php';
require 'src/Connection.php';
require 'src/Posts.php';

if ($_SERVER['REQUEST_METHOD'] === 'POST'){

    $titulo = $_POST['titulo'];
    $descricao = $_POST['descricao'];
    $conteudo = $_POST['conteudo'];
    $imagemDestaque = $_POST['imagemDestaque'];
    $status = $_POST['status'];
    $categoria = $_POST['categoria'];

    $publicar = new Posts($titulo, $descricao, $conteudo, $imagemDestaque, $status, $categoria);
    $publicar->insertPost();
}

pode ser assim?

Isso aí... Dessa forma, caso seja necessário obter as informações da instância de post mais adiante, as alterações vão ser fáceis de fazer.

obrigado pela ajuda!