IBM
Canais iMasters

PHP + CodeIgniter

Magic Methods PHP 5 - Orientação a Objetos com PHP + CodeIgniter

Algum tempo atrás lí a seguinte frase:

“Programação OO em PHP está se resumindo a programação orientada a métodos”

Não lembro mais onde vi isso (se alguém souber, me avise), mas essa frase me impactou para uma reflexão sobre os códigos que vinha e venho escrevendo em PHP.

Salvo pelo uso de frameworks que acabam inevitavelmente herdando características e métodos de suas classes principais, muitos scripts PHP acabam se tornando um agrupamento de métodos e funções agregados em uma classe.

Criar uma classe simplesmente para dar include em arquivos externos ou chamar funções não é orientação a objetos.

Este artigo objetiva apresentar de uma forma bastante simplificada a representação de uma classe pessoa através da criação de dois objetos pessoa distintos aplicando esta metodologia ao framework CodeIgniter.

Desta forma teremos um controlador chamado pessoa que é também a nossa classe e uma view para apresentar os dados. Tudo muito simples.
O foco do artigo está nos “Magic Methods” do PHP5. Vamos utilizar apenas 3 dos 14 Magic Methods num primeiro momento, o __get(),o __set() e o __construct. Em uma continuação trabalharemos com os demais médotos.

Neste primeiro artigo não apresentarei a abstração da classe, para que fique o mais simples possível. No segundo faremos a abstração e uso de Interface.

O PHP não permite herança multipla, por isto não poderemos herdar propriedades de mais de uma classe, e como nossa classe pessoa já herda as propriedades de controller precisaremos criar nossa classe pessoa seguindo o modelo real de uso, ou seja, a representação da nossa classe concreta.

Vamos ao código do controlador pessoa.php

<?php
class Pessoa extends Controller {

private $nome;
private $cpf;
private $sexo;

function __construct()
{
parent::Controller();
}

public function __set($campo,$valor){
$this->$campo = $valor;
}

public function get($campo){
return $this->$campo;
}

function index()
{
$data = array();

$joao = new pessoa();
$joao->nome = "JOAO";
$joao->sexo = "M";
$joao->cpf = "123.456.789-00";

$leticia = new pessoa();
$leticia->nome = "LETICIA";
$leticia->sexo = "F";
$leticia->cpf = "987.654.321-99";

$data['joao']['nome'] = $joao->nome;
$data['joao']['sexo'] = $joao->sexo;
$data['joao']['cpf'] = $joao->cpf;

$data['leticia']['nome'] = $leticia->nome;
$data['leticia']['sexo'] = $leticia->sexo;
$data['leticia']['cpf'] = $leticia->cpf;

$this->load->view('pessoa',$data);
}
}

O importante a observar neste código é que estamos utilizando o __construct() e não repetindo o nome da classe para o construtor, igualmente também poderemos ter um método __destruct() que, por exemplo, poderia limpar uma sessão de login após o envio de uma determinada mensagem ou limpar um carrinho de compras ao final do seu processamento.

E o não menos importante, os métodos __get() e __set() que permitem ajustarmos e recuperarmos qualquer atributo público da classe sem a necessidade de construir os “getters” e “setters” um a um.

Isto faz com que possamos acessar atributos privados de nossas classes de maneira mais segura e semântica e com muito menos trabalho. Da para perceber que o PHP fica a cada dia mais parecido com o Java e o C# neste sentido, reservadas as proporções.

Vamos às explicações:

O método mágico __set().

public function __set($campo,$valor){
        $this->$campo = $valor;
 }

É muito simples de compreender de que forma estamos acessando cada atributo, ao receber dois parâmetros sendo o primeiro o atributo e o segundo o valor atribuído, o método ajusta automaticamente estes valores.

E isto é acessado no seguinte código.

$joao->nome = "JOAO";

O método __get é ainda mais simples pois apenas retorna o valor de um atributo, onde this é o próprio objeto concreto, a instância da classe, apontando para o valor atribuído aquela variável.

public function get($campo){
return $this->$campo;
}

Ou seja para recuperar um valor basta apontar para ele da seguinte maneira.

$joao->nome;

Levando em consideração que $joao é a instância do objeto e não a classe em si.

Acompanhem os próximos artigos para ver como fica a abstração da classe pessoa e o estudo dos demais métodos mágicos do PHP 5.


Comente também

8 Comentários

Adler Parnas
Adler Parnas

Parabéns pela artigo! Gostaria de fazer uma colocação em relação ao método __set():

- criar um método __set para atribuir um valor a uma variável privada sem realizar nenhum processamento, pra mim parece meio sem sentido, a não ser que você queira uma variável somente leitura.

Matheus
Matheus

Nao vi utilidade neste codigo em ter os atributos como private e usar os metodos magicos para acessar os atributos diretamente. O metodo de chegar o cpf e/ou cnpj deveria estar nos metodos, certo?

Taffarel de Lima Oliveira
Taffarel de Lima Oliveira

Legal o artigo, curti sobre como vc aborda o tema. O que mais me complica é que outros autores tratam do assunto de diferentes formas de implementação e sempre apresentam uma justificativa, e como estou no começo não saberia qual forma é a mais 'correta' por assim dizer.

Ademir Cristiano Gabardo
Ademir Cristiano Gabardo

Olá Taffarel, Matheus e Adler. Este é um artigo "polêmico". Conversando com vários desenvolvedores você irá encontrar várias respostas diferentes. A idéia de escrever partiu justamente da necessidade de encontrar um caminho e compreender as questões de abstração, encapsulamento e herança.

Existem muitas maneiras distintas de fazer a mesma coisa, e não necessariamente uma estará errada e outra certa. Do ponto de vista da semântica alguma delas estará sempre mais adequada.

Este exemplo é didático, e não se encaixa num ambiente de produção. Mas tem por finalidade apresentar os métodos mágicos no PHP.
Linguagens como o JAVA e o C# já vem implementando este tipo construção de código "a muitas luas" atrás. E por esta razão em alguns aspectos estão mais bem estruturadas.

O que particularmente considero mais importante sobre isso é a comunidade PHP adotar a Orientação a objetos de maneira plena, e não se resumir a criar classes apenas para agrupar métodos.

Espero que seja útil de algum modo.
Abraços

Eduardo Matos
Eduardo Matos

Eu entendi o intuito do tutorial, mas não gostei muito dessa integração com Codeigniter. Estou em um projeto (usando o Codeigniter) onde faço coisas desse tipo, mas coloca todas as minhas classes (customizadas) na pasta libraries, o que faz muito mais sentido na minha opinião. Sempre tento manter o controller o mais reduzido possível, principalmente por se tratar do Codeigniter, que nem sempre te dá uma estrutura legal pra isso.

Erick Pintor
Erick Pintor

Como já dito nos comentários acima, existem muitas formas de ser fazer esta mesma implementação em PHP mas, particularmente, não acredito que utilizar métodos mágicos para acessar variáveis privadas tornará seu código ?mais OO?.
Primeiramente há neste artigo uma quebra no conceito de MVC pois não faz o menor sentido a classe de ?Pessoa? ser um controlador.
Eu acredito que se utilizarmos melhor o padrão MVC neste exemplo poderemos separar melhor as classes e não precisaremos de métodos mágicos para acessar nossas propriedades, pois podemos (e devemos pois é o mais correto!) implementar os getter's e setter's para cada propriedade sem poluir a classe.
Trabalhei muito tempo com PHP e nunca gostei de utilizar métodos mágicos. Imagine se você precisar fazer uma validação no setter de uma propriedade... se você possui um setter implementado você apenas vai no setter e implementa a sua validação! Agora imagine se você possui setter's mágicos... você colocaria um ?if($campo == 'x')?, não acho que seja legal.
Devemos tomar cuidado com este tipo de facilidade que as linguagens nos proporcionam pois muitas vezes elas não se comportam bem a medida em que seu sistema cresce e precisa de novas funcionalidades, validações, controles de segurança, etc...
Para quem realmente necessita deste recurso sugiro que utilize o método ?__call? simulando as chamadas dos metodos get e set pois, caso você implemente o método ele será chamado mais prioridade que o método ?__call?.

Segue um exemplo deste método:
<?php
class Teste {

public function __call($metodo, $parametros){
echo "Chamou o método: " . $metodo . " com os argumentos: " . implode(', ', $parametros) . '<br/>';
}

public function setIdade(){
echo 'Chamou a implementação do setter de idade <br/>';
}
}

$t = new Teste();
$t->setNome('Erick');
$t->setIdade(1);
?>

Henrique José Pires Barcelos
Henrique José Pires Barcelos

Métodos mágicos são o que há de mais horripilante e anti-OO no PHP.
Seu uso é totalmente desnecessário e existem muitas outras maneiras de obter a mesma funcionalidade sem utilizá-los. Além de tudo, são EXTREMAMENTE LENTOS.

Foram criados sob o pretexto de 'facilidade de uso', mas tornam o código confuso. Por culpa dessa e de outras coisas, o PHP é tachado de "linguagem-brinquedo".

Na minha opinião, esse recurso deve ser tratado como "decorativo". Passem loooonge dele.

Steve Zuckerberg
Steve Zuckerberg

Achei muito ruim esse tutorial.
Nada a ver a classe pessoa ser um Controller. Cade o MVC?
E ainda diz que escreveu um livro sobre o CodeIgniter..
Deve ser um livro de como NÃO programar com CodeIgniter.
Que gambiarra esse get e set genérico

Qual a sua opinião?

Comentários considerados ofensivos serão moderados.

Parceiros

IBM
PagSeguro
Internet Innovation
Dialhost
HostNet
Tecla
KingHost
DotStore
Dinamize