PHP para Iniciantes: Tipos de Dados Primitivos - Objetos

Esse tipo de dado tem um grande peso em qualquer linguagem que o implemente. Ele traz à tona o paradigma de Programação Orientada a Objeto, amplamente conhecida como POO. Se você não conhece isso, recomendo fortemente que pesquise leituras sobre este assunto. Se você pretende trabalhar com PHP em alto nível, isto é, seguindo padrões e tudo mais, você vai precisar saber disso.

No geral, eu vou tentar auxiliar na sua compreensão sem abordar muitos detalhes (afinal, vai ter um tópico só sobre Classes e Objetos bem mais pra frente), usando minhas próprias palavras ou plagiando alguém sem querer por ter aprendido há muito tempo. Caso eu realmente faça isso (plágio), me avise aí nos comentários! Faço questão de dar créditos aos autores reais e não tenho intenção alguma de ganhar qualquer coisa com esses artigos.

Agora vamos parar com o papo furado e ir direto ao ponto!

O que é POO?

Eu já te disse: um paradigma de programação. Um paradigma é um conceito de como devemos organizar nossos projetos e há muitos paradigmas por aí que você pode acabar usando sem perceber. Por exemplo: Programação Imperativa, Programação Funcional, Programação Estruturada, etc. Alguns podem ser usados ao mesmo tempo, inclusive.

E no caso de POO, nós tentamos deixar o nosso código um pouco semelhante ao mundo real. É daí que vem o nome "objeto", que pode ser qualquer coisa (votação da zoeira: devemos mudar o nome para Programação Orientada a Qualquer Coisa? -sqn).

Então quando você faz um projeto que envolve noção do que é um usuário, nesse paradigma, você precisa criar uma estrutura capaz de representar isso. E aí você precisa refletir sobre alguns aspectos, por exemplo:

  • quais dados um usuário pode registrar? (login? senha? nome?)
  • o que um usuário pode fazer? (validarSenha?)

E aos poucos você irá construir uma imagem sólida do que você quer representar nesse usuário. Essa imagem sólida é a sua classe. A classe define tudo sobre os seus respectivos objetos. Continuando o nosso raciocínio, temos:

<?php //Usuario.php
class Usuario {
    private string $login;
    private string $senha;
    private string $nome;

    public function __construct(string $login, string $senha, string $nome): void
    {
        $this->login = $login;
        $this->senha = $senha;
        $this->nome = $nome;
    }

    public function validarSenha(string $senhaParaValidar): void
    {
        if ($this->senha !== $senhaParaValidar) {
            throw new Exception("Login e/ou senha inválido(s).");
        }
    }
}

Não se preocupe se não entender nada, porque só vamos falar de fato sobre isso, como mencionei antes, no artigo sobre Classes e Objetos. O fato é que essa classe define o que é um usuário no sistema. Que ele tem login, senha e nome. Além disso, ele tem uma ação validarSenha, que recebe a senha que desejamos validar e compara com a senha que está registrada no usuário.

Então, quando você quer instanciar um novo objeto, você usa a chamada new NomeDaClasse(...):

<?php //index.php
require_once (__DIR__ . "/Usuario.php"); // incorpora a classe Usuario criada anteriormente

$fabio = new Usuario("fabio", "senharuim123", "Fabio dos Santos");
$joao = new Usuario("joao", "senhapior321", "Joao Alecrim");

Em algumas passagens lá na definição da classe, você pode ter reparado que usei uma "variável" $this. Na real, isso não é uma variável. Por definição, isso é uma forma de dizer que você quer acessar alguma propriedade ou método do objeto que está acionando aquela linha.

Por exemplo, o comando validarSenha usa isso, e continuando o exemplo acima, nós podemos fazer:

// abaixo não vai dar erro, pois ao acionar o "validarSenha", o "$this" será a instância do objeto "$fabio", cuja senha é a que está inserida aí
$fabio->validarSenha("senharuim123");

// agora teremos um erro, pois o "$this" no "validarSenha" estará se referindo ao objeto "$joao", que tem uma senha diferente
$joao->validarSenha("senharuim123"); // Exception

Mesmo que não saiba o que é uma Exception, se você executar o código acima você verá um erro de "Login e/ou senha inválido(s).".

Deu para entender mais ou menos o que é POO? Aliás, essa é só a ponta do iceberg. Tem muitos outros conceitos para explorar nesse tema. Poliformismo é o mais legal, na minha opinião, mas aqui não é o lugar para isso. Se você se interessou, sério, corra atrás e estude.

Como criar um objeto

Bom, você viu há pouco que para criar um objeto você precisa da definição da classe. Tendo isso, você poderá instanciar um objeto chamando o comando new NomeDaClasse(...), considerando sempre os argumentos que precisam ser preenchidos (sim, é possível ter argumentos opcionais).

Mas Kiko, essa é a única forma de criar um objeto? Eu vi em artigos anteriores você fazer um objeto a partir de um... array?!

Convertendo para objetos

É verdade, é possível converter coisas para objeto. Mas nesse caso, a ação é converter e não criar/instanciar. Ao converter um tipo de dados para objeto, algo interessante pode acontecer em cada situação. O que há em comum entre todas as possibilidades é que o objeto gerado acaba por ser uma instância da classe padrão stdClass, que significa Standard Class. Como falei: todo objeto precisa de uma classe, e se você converte algo para alguma coisa que não tem classe, então a classe utilizada será a padrão do PHP.

Se você converte um array para objeto, o que acontece é que todos os índices do primeiro nível do array viram uma propriedade pública do objeto (no exemplo acima não tem propriedade pública, mas uma propriedade seria o $nome do usuário). Por exemplo:

<?php

$array = [
    "login" => "fabio",
    "senha" => "senharuim123",
    "nome" => "Fabio dos Santos",
];
$object = (object) $array;
echo $object->login; //fabio

Já se você converte qualquer outro tipo de dado para objeto, há duas possibilidades:

  • se o dado for null, então o objeto criado será vazio (sem propriedades);
  • já se o dado tiver algum vaor, então o valor será atribuído à propriedade scalar:
      <?php
      $saldoDosSonhos = 9999999;
      $saldo = (object) $saldoDosSonhos;
      echo $saldo->scalar; // 9999999
    

E se converter um objeto para objeto, Kiko?

Aí nada vai acontecer, porque você não tá convertendo... Não é mesmo? Hehehe.

Um pouco sobre propriedades, métodos e visibilidade

Bom, a essa altura você já entendeu que objeto é uma estrutura de dados gerada a partir de uma classe. Essa classe define tudo o que deve compor aquele objeto. Então, durante a instância, você pode ter algumas propriedades e métodos, onde cada um desses carinhas pode ser visível ou não do lado de fora da classe. Naquele exemplo de usuário, todas as propriedades possuem a visibilidade private, o que significa que somente o objeto sabe que aqueles dados existem dentro dele.

Como assim, Kiko?!

Uma propriedade privada existe somente no escopo da classe. Se você tentar imprimir echo $fabio->senha, terá um erro, pois não está visível do lado de fora do objeto. Para tornar visível, você teria de mudar de private para public, como está no método validarSenha.

No caso de uma propriedade com visibilidade pública, significa que todo mundo pode ver, escrever e apagar o dado que estiver ali. Então, se você mudar a visibilidade de $senha para público, pode ter alguma passagem no código que faz $fabio->senha = "senhaalterada" para adulterar a senha no meio do processo.

Ou até mesmo re-criar aquele método validarSenha inserindo $fabio->senha === "minhasenha", gerando o caos de funções iguais espalhadas pelo projeto.

Pois é, nem tudo precisa ser público. E além dessas duas visibilidades, tem uma terceira que é a visibilidade protegida (protected), que envolve hierarquia de classes e é um rolê que foge totalmente do foco desse artigo, mas que é de leitura obrigatória. Sim, eu tô implorando pra você estudar isso, hehe.

Acho que entendi... Mas e métodos?

Método nada mais é que uma função com um contexto mais fechado. Porém, eu ainda não falei de função, então não posso responder dessa forma hahahaha. Então podemos usar outra analogia: método é uma ação. Geralmente quando você pensar em verbos que um objeto pode fazer, cada verbo será, no mínimo, um método.

Esse método pode gerar outros métodos ali dentro. Ou talvez outras classes, para retirar responsabilidades (e aqui eu indico outra leitura legal que é o SOLID), etc.

Vê que o assunto cresce exponencialmente? Quanto mais eu te ensino, mais coisa você descobre que precisa aprender, hehel. Mas não desanima! Você está aprendendo bastante e evoluindo. E eu gostaria muito de te conhecer, então não deixa de comentar, ok?! Por hoje é só, espero que tenha gostado e nos vemos no próximo artigo, falando sobre ITERÁVEIS!!

Na ordem da documentação do PHP, iteráveis vem antes de objetos. Para mim, isso não faz o menor sentido (talvez por ter sido mais recente, apenas). Iteráveis menciona objetos e arrays, então preferi falar primeiro de objetos já que também já falei sobre arrays, beleza?

E é isso.

Inté!