Beruflich Dokumente
Kultur Dokumente
Novatec
Terceira edio
Segunda edio (ISBN: 978-85-7522-200-3)
Primeira edio (ISBN: 978-85-7522-137-2)
PHP
Programando com Orientao a Objetos
3a edio
captulo 1
Introduo ao PHP
22
No mesmo ano Andi Gutmans e Zeev Suraski, dois estudantes que utilizavam essa
linguagem em um projeto acadmico de comrcio eletrnico, resolveram cooperar
com Rasmus para aprimorar o PHP. Para tanto, reescreveram todo o cdigo-fonte,
com base no PHP/FI2, dando incio assim ao PHP 3, disponibilizado oficialmente em junho de 1998. Entre as principais caractersticas do PHP 3 estavam a
extensibilidade, a possibilidade de conexo com vrios bancos de dados, novos
protocolos, uma sintaxe mais consistente, suporte orientao a objetos e uma
nova API, que possibilitava a criao de novos mdulos e que acabou por atrair
vrios desenvolvedores ao PHP. No final de 1998, o PHP j estava presente em
cerca de 10% dos domnios da internet. Nessa poca o significado da sigla PHP
mudou para PHP: Hypertext Preprocessor, retratando, assim, a nova realidade de
uma linguagem com propsitos mais amplos.
No inverno de 1998, Zeev e Andi comearam a trabalhar em uma reescrita do
ncleo do PHP, tendo em vista melhorar seu desempenho e sua modularidade em
aplicaes complexas. O nome foi rebatizado para Zend Engine (Zeev + Andi).
O PHP 4, j baseado nesse mecanismo, foi lanado em maio de 2000, trazendo
melhorias como sees, suporte a diversos servidores web, alm da abstrao de
sua API, permitindo inclusive ser utilizado como linguagem para shell script.
Apesar de todos os esforos, o PHP ainda necessitava de maior suporte orientao a objetos. Esses recursos foram trazidos pelo PHP 5, aps um longo perodo
de desenvolvimento que culminou com sua disponibilizao oficial em julho de
2004. Ao longo de mais de uma dcada, o PHP vem adicionando mais e mais
recursos e se consolida ano aps ano como uma das linguagens de programao
orientadas a objetos que mais crescem no mundo. Estima-se que o PHP seja utilizado em mais de 80% dos servidores web existentes, tornando-a disparadamente
a linguagem mais utilizada para desenvolvimento web. Ao longo do livro, veremos
esses recursos empregados em exemplos prticos.
Fonte: PHP Group (http://php.net/history.php)
23
1.2.2 Configurao
Ao iniciarmos com o PHP, importante sabermos configurar o ambiente. Nesse
sentido a funo phpinfo() muito importante, pois ela apresenta uma tabela com a
configurao atual do PHP, como nveis de erro, extenses instaladas, entre outros.
<?php
phpinfo();
63
Resultado:
O Leo roeu a roupa do rei de Roma
ou
$cores = array('vermelho', 'azul', 'verde', 'amarelo');
ou
$cores = [ 'vermelho', 'azul', 'verde', 'amarelo' ];
=
=
=
=
'maria';
'joo';
'carlos';
'jos';
De qualquer forma, para acessar o array indexado, basta indicar o seu ndice
entre colchetes:
echo
echo
echo
echo
$cores[0];
$cores[1];
$cores[2];
$cores[3];
//
//
//
//
resultado
resultado
resultado
resultado
=
=
=
=
vermelho
azul
verde
amarelo
75
1.12.2 Exemplos
Para exemplificar o acesso ao banco de dados, criaremos dois programas. O primeiro deles ser responsvel por inserir dados em um banco de dados PostgreSQL; o
segundo ir listar os resultados inseridos pelo primeiro programa. Para criar o banco de dados utilizado nos exemplos, certifique-se de que voc tem o PostgreSQL
instalado em sua mquina e utilize os seguintes comandos:
# createdb livro
# psql livro
livro=# CREATE TABLE famosos (codigo integer, nome varchar(40));
CREATE TABLE
livro=# \q
Observao: possvel criar a base de dados utilizando o software PgAdmin (www.
pgadmin.org), que apresenta uma interface totalmente grfica para gerenciar o banco
de dados.
pgsql_insere.php
<?php
// abre conexo com Postgres
$conn = pg_connect("host=localhost port=5432 dbname=livro user=postgres password=");
// insere vrios registros
pg_query($conn, "INSERT INTO
pg_query($conn, "INSERT INTO
pg_query($conn, "INSERT INTO
pg_query($conn, "INSERT INTO
pg_query($conn, "INSERT INTO
pg_query($conn, "INSERT INTO
pg_query($conn, "INSERT INTO
famosos
famosos
famosos
famosos
famosos
famosos
famosos
(codigo,
(codigo,
(codigo,
(codigo,
(codigo,
(codigo,
(codigo,
nome)
nome)
nome)
nome)
nome)
nome)
nome)
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
(1,
(2,
(3,
(4,
(5,
(6,
(7,
'rico Verssimo')");
'John Lennon')");
'Mahatma Gandhi')");
'Ayrton Senna')");
'Charlie Chaplin')");
'Anita Garibaldi')");
'Mrio Quintana')");
// fecha a conexo
pg_close($conn);
No prximo exemplo, o programa se conectar ao mesmo banco de dados do exemplo anterior, chamado livro, localizado em localhost. Em seguida ele ir selecionar
cdigo e nome de famosos existentes nesse banco de dados, exibindo-os em tela.
captulo 2
A orientao a objetos um paradigma que representa uma filosofia para construo de sistemas. Em vez de construir um sistema formado por um conjunto
de procedimentos e variveis nem sempre agrupadas de acordo com o contexto,
como se fazia em linguagens estruturadas (Cobol, Clipper, Pascal), na orientao
a objetos utilizamos uma tica mais prxima do mundo real. Lidamos com objetos: estruturas que carregam dados e comportamento prprio, alm de trocarem
mensagens entre si com o objetivo de formar algo maior, um sistema.
Orientao a objetos uma abordagem para concepo de sistemas, um paradigma
de programao. Atualmente a abordagem mais utilizada para concepo de
sistemas. Entretanto nem sempre foi assim. Para entender o que a orientao a
objetos e como ela utilizada, primeiro importante compreender como era o
desenvolvimento antes de a orientao a objetos se tornar o paradigma vigente.
105
classes/Fabricante.php
<?php
class Fabricante {
private $nome;
private $endereco;
private $documento;
public function __construct( $nome, $endereco, $documento ) {
$this->nome
= $nome;
$this->endereco = $endereco;
$this->documento = $documento;
}
public function getNome() {
return $this->nome;
}
}
108
Inicialmente ser criada a classe Caracteristica. Uma caracterstica ter apenas dois
atributos: nome e valor. So exemplos de nomes: cor, peso, tamanho e potncia. So exemplos de valores: branco, 20 kg, 200 watts e assim por diante.
classes/Caracteristica.php
<?php
class Caracteristica {
private $nome;
private $valor;
public function __construct( $nome, $valor ) {
$this->nome = $nome;
$this->valor = $valor;
}
public function getNome() {
return $this->nome;
}
public function getValor() {
return $this->valor;
}
}
Em seguida, alteraremos a classe Produto para que ela tenha os mtodos para compor caractersticas. Inicialmente precisaremos declarar um atributo $caracteristicas, que ser um vetor interno que armazenar uma ou mais instncias contendo
objetos da classe Caracteristica. Escreveremos o mtodo addCaracteristica(), que
receber os parmetros $nome e $valor e criar internamente um objeto da classe
Caracteristica para armazenar esses dois dados. O objeto criado ser adicionado
ao vetor ($this->caracteristicas). J o mtodo getCaracteristicas() simplesmente retornar o vetor de caractersticas.
111
ou seja, somente poder receber objetos da classe Produto. A classe Cesta contar
tambm com o mtodo getItens(), que por sua vez retornar os itens da cesta.
classes/Cesta.php
<?php
class Cesta {
private $time;
private $itens;
public function __construct( ) {
$this->time = date('Y-m-d H:i:s');
$this->itens = array();
}
public function addItem( Produto $p ) {
$this->itens[] = $p;
}
public function getItens() {
return $this->itens;
}
public function getTime() {
return $this->time;
}
}
122
Para atingir o encapsulamento, uma das formas definir a visibilidade das propriedades e dos mtodos de um objeto. A visibilidade define a forma como essas
propriedades devem ser acessadas. Existem trs formas de acesso:
Visibilidade Descrio
public
private
protected
2.11.1 Public
Demonstrar a visibilidade public uma tarefa simples, pois um atributo declarado
como public pode ser alterado de qualquer parte, ou seja, tanto de dentro da classe
153
Para resolver esse problema, podemos usar o Design Pattern Adapter para converter os mtodos da PHPMailer para o formato de chamada de mtodos que
voc espera em sua aplicao. Vamos construir a classe PHPMailerAdapter, que se
trata de uma camada fina ao redor da PHPMailer para converter o formato de
chamada de mtodos. Assim IsSMTP() se transformar em setUseSmtp(), MsgHTML() se
transformar em setHtmlBody() e AddAttachment() se transformar em addAttach(), entre
outros. A seguir temos a classe PHPMailerAdapter. Trata-se de uma classe funcional,
que s precisa da PHPMailer para funcionar.
classes/PHPMailerAdapter.php
<?php
class PHPMailerAdapter {
private $pm;
public function __construct() {
$this->pm = new PHPMailer;
$this->pm-> CharSet = 'utf-8';
}
captulo 3
164
168
)
Arquivo no encontrado
magic_intro.php
<?php
class Titulo {
private $dt_vencimento;
190
bases.xml
<bases>
<base id="1">
<name>teste</name>
<host>192.168.0.1</host>
<type>mysql</type>
<user>mary</user>
</base>
<base id="2">
<name>producao</name>
<host>192.168.0.2</host>
<type>pgsql</type>
<user>admin</user>
</base>
</bases>
193
'teste'));
'192.168.0.1'));
'mysql'));
'mary'));
: Resultado:
<bases>
<base id="1">
<name>teste</name>
<host>192.168.0.1</host>
<type>mysql</type>
<user>mary</user>
</base>
</bases>
Observao: caso esteja rodando o PHP no browser, veja o XML pelo cdigo-fonte
da pgina.
3.5 SPL
SPL um conjunto de classes e interfaces que fornece ao desenvolvedor uma API
padronizada para resolver problemas comuns e tambm criar classes com maior
potencial de interoperabilidade.
O PHP sempre ofereceu muitas funes para manipulao de arquivos (file, basename,
fopen, file_get_contents, file_put_contents, copy, unlink, rename, filesize, fwrite, pathinfo),
manipulao de vetores (array_diff, array_merge, array_shift, array_pop, array_unshift,
array_push, array_keys. array_values), entre outros. Antes do PHP 5, quando a SPL ainda
no existia, mesmo tendo esse arsenal de funes disposio, sempre existiram
programadores que preferiam fazer tudo de maneira orientada a objetos. Assim
muitos acabaram criando classes que "agrupavam" funcionalidades em comum
para fornecer um meio orientado a objetos de resolver problemas. O que a SPL
oferece um conjunto de classes com funcionalidades comuns, como manipulao
de arquivos, vetores, pilhas e filas de maneira padronizada.
204
3.6 Reflection
Reflection (Reflexo) uma API formada por um conjunto de classes que permite
que um programa possa obter informaes sobre sua prpria estrutura, suas classes, interfaces, seus mtodos, suas funes, entre outros. Entre essas informaes
podemos descobrir as constantes, os atributos e mtodos de uma classe, descobrir se um mtodo abstrato, privado ou final, descobrir informaes sobre os
parmetros de um mtodo, entre outros.
3.6.1 ReflectionClass
A API Reflection pode ser aplicada sobre cdigo-fonte construdo pelo desenvolvedor, mas tambm sobre classes nativas do PHP, como as classes da SPL. Para
demonstrar algumas funcionalidades, vamos declarar uma pequena classe somente
para propsito didtico. No cdigo a seguir teremos as classes Veiculo e Automovel com
alguns atributos e mtodos definidos. O prximo passo ser investigar essa classe.
veiculo.php
<?php
class Veiculo
protected
protected
protected
protected
{
$ano;
$cor;
$marca;
$parts;
218
3.10 Namespaces
Quando o PHP surgiu no existiam classes. Depois de algumas verses foram
criadas as classes e os programadores comearam a criar cdigos orientados a
objetos em PHP. No PHP3 j era possvel declarar classes e criar objetos a partir
delas. Mas naquela poca o suporte orientao a objetos no PHP no era robusto e os objetos eram tratados internamente como vetores associativos. Apesar
de ter suporte orientao a objetos, a maioria ainda programava de maneira
estruturada, declarando funes e usando os comandos include/require para incluir
arquivos e reaproveitar cdigo.
O PHP4 melhorou algumas coisas, mas foi o PHP5 que causou uma revoluo. No
PHP5 foram introduzidas grandes funcionalidades como passagem de objetos por
referncia, mtodos mgicos, interfaces, classes e mtodos abstratos, visibilidade,
__construct() e __destruct(), autoload, static, excees, SimpleXML, SPL, entre outras.
229
Por fim temos uma variao do exemplo anterior, na qual solicitaremos que
determinada classe registre ela mesma o seu mtodo de carregamento de classes. Neste caso instanciaremos a classe de carga ApplicationLoader e solicitaremos
o mtodo register(). O mtodo register() por sua vez ir executar a funo
spl_autoload_register() para registrar o mtodo $this->loadClass() como autoloader.
Essa abordagem interessante, pois permite que a classe de carregamento altere
no somente o algoritmo de carga, mas tambm o prprio nome do mtodo de
carga (loadClass) sem interferir na chamada externa (register).
spl_autoload3.php
<?php
$al = new ApplicationLoader;
$al->register();
class ApplicationLoader {
public function register() {
spl_autoload_register(array($this, 'loadClass'));
}
public function loadClass($class) {
if (file_exists("App/{$class}.php")) {
require_once "App/{$class}.php";
return TRUE;
}
}
}
Observao: por motivos de simplificao colocamos a declarao da classe
(ApplicationLoader), bem como sua chamada, no mesmo arquivo, porm essa no uma
boa prtica. Na realidade a classe dever estar localizada em um arquivo prprio, que
contenha somente a sua definio, enquanto sua instanciao e consequente chamada
(register) normalmente estar no principal arquivo da aplicao (index.php), j que
as requisies para as demais classes do projeto partem dele.
captulo 4
Persistncia
Ao programarmos de maneira orientada a objetos, nossa aplicao deve ser formada exclusivamente por um conjunto de objetos relacionados. Quando trabalhamos com um conjunto de objetos em memria, em algum momento precisamos
persistir esses objetos na base de dados, ou seja, armazen-los e permitir que
sejam posteriormente carregados a partir do banco de dados para a memria.
Pensando nisso, estudaremos as tcnicas mais utilizadas para persistncia de
objetos em bases de dados relacionais, assim como criaremos uma API orientada
a objetos que ir permitir que faamos tudo isso de forma transparente, sem nos
preocuparmos com os detalhes internos de implementao.
4.1 Introduo
De modo geral, persistncia significa continuar a existir, perseverar, durar longo
tempo ou permanecer. No contexto de uma aplicao de negcios, na qual temos
objetos representando as mais diversas entidades a serem manipuladas (pessoas,
mercadorias, livros, clientes, arquivos etc.), persistncia significa a possibilidade
de esses objetos existirem em um meio externo aplicao que os criou, de modo
que esse meio deve permitir que o objeto perdure, ou seja, no deve ser um meio
voltil. Os bancos de dados relacionais so o meio mais utilizado para isso (embora no seja o nico). Com o auxlio de mecanismos sofisticados especficos de
cada fornecedor, esses bancos de dados oferecem vrios recursos que permitem
armazenar e manipular, por meio da linguagem SQL, os dados neles contidos.
235
238
conhecer essa interface para manipular as informaes. O acesso aos dados via
linguagem SQL, por exemplo, fica contido nessa camada. Dessa forma evitamos
ter a manipulao de dados espalhada pelo cdigo-fonte da aplicao, podendo
inclusive estruturar a equipe de desenvolvimento para que os mais talentosos em
SQL sejam responsveis pelas classes de acesso aos dados.
Existem alguns Gateways que implementam o acesso s estruturas de dados. A
seguir estudaremos alguns dos mais utilizados, que so Table Data Gateway, Row
Data Gateway, Active Record e Data Mapper.
247
Um Row Data Gateway deve prover mtodos que permitam construir um objeto
e posteriormente armazen-lo no banco de dados, alm de mtodos estticos que
permitam carregar um objeto ou um conjunto de objetos do banco de dados.
A classe ProdutoGateway a seguir demonstra a implementao de um Row Data
Gateway. A classe utiliza os mtodos mgicos __set() e __get() para armazenar
atributos no vetor $this->data. O mtodo esttico setConnection() utilizado para
receber a conexo PDO com a base de dados. Os mtodos estticos find() e all() so
utilizados para buscar respectivamente um registro e um conjunto de registros.
Os mtodos find() e all() sempre retornaro objetos da classe ProdutoGateway, o que
alcanado pelo uso da constante __CLASS__ nos mtodos fetch() e fetchAll(). A
constante __CLASS__ representa a prpria classe em que utilizada. Como o Row
Data Gateway armazena seus atributos internamente no vetor $this->data, esses
atributos estaro disponveis no momento de realizar operaes como delete() e
save(). Assim, essas operaes no precisaro receber parmetros para indicar o
registro sobre o qual as operaes sero realizadas, bastando coletar esses dados
do vetor $this->data.
Observao: neste exemplo as propriedades sero armazenadas em um array chamado
$data. Isso porque estamos utilizando os mtodos __get() e __set() para interceptar
os acessos aos atributos do objeto.
248
classes/rdg/ProdutoGateway.php
<?php
class ProdutoGateway {
private static $conn;
private $data;
function __get($prop) {
return $this->data[$prop];
}
function __set($prop, $value) {
$this->data[$prop] = $value;
}
public static function setConnection( PDO $conn ) {
self::$conn = $conn;
}
public static function find($id) {
$sql = "SELECT * FROM produto where id = '$id' ";
print "$sql <br>\n";
$result = self::$conn->query($sql);
return $result->fetchObject(__CLASS__);
}
public static function all($filter = '') {
$sql = "SELECT * FROM produto ";
if ($filter) {
$sql .= "where $filter";
}
print "$sql <br>\n";
$result = self::$conn->query($sql);
return $result->fetchAll(PDO::FETCH_CLASS, __CLASS__);
}
public function delete() {
$sql = "DELETE FROM produto where id = '{$this->id}' ";
print "$sql <br>\n";
return self::$conn->query($sql);
}
public function save() {
if (empty($this->data['id'])) {
$id = $this->getLastId() +1;
$sql = "INSERT INTO produto (id, descricao, estoque, preco_custo, ".
258
Para demonstrar esse Design Pattern, vamos criar algumas classes bastante simples. Inicialmente precisamos de uma classe para representar um produto. Fica
claro aqui que a classe proposta uma classe incompleta, pois carece de mtodos
de negcio.
classes/dm/Produto.php
<?php
class Produto {
private $data;
function __get($prop) {
return $this->data[$prop];
}
function __set($prop, $value) {
$this->data[$prop] = $value;
}
}
Agora vamos criar uma classe para representar uma venda. Essa classe ter
mtodos para atribur e retornar um ID, bem como adicionar (addItem) e retornar
(getItens) itens (produtos).
classes/dm/Venda.php
<?php
class Venda {
private $id;
282
classes/api/Record.php
<?php
abstract class Record {
protected $data; // array contendo os dados do objeto
public function __construct($id = NULL) {
if ($id) { // se o ID for informado
// carrega o objeto correspondente
$object = $this->load($id);
if ($object)
{
$this->fromArray($object->toArray());
}
}
}
O mtodo __clone() ser executado sempre que um objeto for clonado. Nesses
casos em que um Active Record clonado, ele deve manter todas as suas propriedades, com exceo de seu ID, por isso estamos limpando o ID do clone. Caso
mantivssemos o mesmo ID, teramos dois objetos Active Record com o mesmo ID
no sistema, o que causaria erros na persistncia do objeto. Limpar o ID far com
que um novo ID seja gerado para o clone no momento em que ele for persistido
na base de dados.
public function __clone() {
unset($this->data['id']);
}
captulo 5
Apresentao e controle
Aquele que conhece os outros sbio; mas quem conhece a si mesmo iluminado! Aquele
que vence os outros forte; mas aquele que vence a si mesmo poderoso! Seja humilde e
permanecers ntegro.
Lao-Ts
320
322
Ao utilizarmos o padro MVC, alguns cuidados devem ser tomados, por exemplo:
Uma classe de modelo no deve emitir mensagens ao usurio por meio de
comandos como print, muito menos gerar mensagens contendo marcaes
como HTML. Exibir informaes ao usurio por meio de uma linguagem
de marcao uma tarefa de uma classe de visualizao.
Uma classe de controle no deve executar diretamente comandos de acesso a
dados como SQL. Buscar e atualizar dados relativos ao modelo de domnio
so tarefas de uma classe de modelo.
Uma classe de visualizao no deve conter regras de negcio, nem decidir
o que deve ser executado em determinado momento. Regras de negcio
so de responsabilidade de uma classe de modelo, e decidir o que deve ser
executado de responsabilidade de uma classe de controle.
Observao: um sistema MVC clssico ter uma classe Controller para cada View
existente, mas essa abordagem no a nica. Alguns frameworks frequentemente
mesclam View e Controller na mesma camada, deixando-as diretamente vinculadas.
326
App/Config/livro.ini
host
name
user
pass
type
= localhost
= App/Database/livro.db
=
=
= sqlite
330
exemplo_loader.php
<?php
require_once 'Lib/Livro/Core/ClassLoader.php';
$al= new Livro\Core\ClassLoader;
$al->addNamespace('Livro', 'Lib/Livro');
$al->register();
use Livro\Database\Connection;
$obj1 = Connection::open('livro');
var_dump($obj1);
Resultado:
object(PDO)#2 (0) { }
339
345
captulo 6
Formulrios e listagens
Uma sociedade s ser democrtica quando ningum for to rico que possa comprar
algum e ningum for to pobre que tenha de se vender a algum.
Jacques Rousseau
Neste captulo iremos nos concentrar em alguns dos componentes que esto entre
os mais utilizados na maioria das aplicaes: formulrios e listagens. Utilizamos
formulrios para as mais diversas formas de entrada de dados na aplicao, como
para a insero de novos registros, definio de preferncias do sistema ou de
parmetros para filtragem de um relatrio, entre outras. Utilizamos listagens para
exibir os dados da aplicao para simples conferncia, em relatrios, ou ainda
para editar e excluir registros. Neste captulo criaremos componentes que visam
facilitar a implementao de formulrios e listagens de forma orientada a objetos.
6.1 Formulrios
No final do captulo 1 criamos alguns exemplos simples de utilizao de formulrios em PHP. Naqueles exemplos, construmos os formulrios utilizando simplesmente HTML. No captulo anterior abordamos os benefcios que a utilizao
de componentes e templates nos proporciona para a criao de interfaces, sendo
o principal deles o maior isolamento entre a apresentao e a lgica da aplicao.
Nesta seo utilizaremos os conhecimentos adquiridos no captulo anterior para
desenvolver um conjunto de classes que permitiro a criao e manipulao de
formulrios de maneira totalmente orientada a objetos.
Aplicaes de negcio frequentemente utilizam diversas telas para entrada de
dados por meio de formulrios. Ao projetar um sistema, temos de pensar no reaproveitamento de cdigo. A abordagem tradicional, vista no captulo 1, minimiza
385
387
oferecer. Entre essas operaes, podemos citar: definir o nome do campo, definir
um rtulo (label) para o campo, definir um valor para o campo, definir se o campo
ser editvel, entre outros.
Para montar um formulrio, utilizaremos um relacionamento de agregao entre
a classe Form e a classe Field. Dessa forma, ser possvel adicionar ao formulrio
quaisquer objetos filhos de Field. Para tal, ser criado na classe Form, um mtodo
que permitir adicionar campos (objetos Field) em sua estrutura. Veja na figura
6.1 o diagrama de classes resumido.
A partir de ento, podemos comear a construir as classes que faro parte desse
ecossistema de objetos inter-relacionados que o formulrio.
429
Para iniciar, a classe FormWrapper ir receber em seu mtodo construtor uma instncia
j existente da classe Form, sobre a qual ir realizar as transformaes necessrias
para adequar a estrutura do formulrio existente e convert-la na estrutura que a
biblioteca Bootstrap espera. A instncia j existente ser armazenada no atributo
$decorated.
Como a ideia do Design Pattern adicionar comportamento a um objeto j existente, no podemos anular os comportamentos (mtodos) j existentes. Tambm
no vamos reescrev-los aqui. Mtodos da classe Form, como setName(), addField(),
addAction(), entre outros, devem continuar funcionando a partir da classe nova.
Para que eles continuem a funcionar, sempre que o desenvolvedor executar um
mtodo no encontrado na classe FormWrapper, automaticamente a execuo ser
redirecionada para o objeto decorado, representado pelo atributo $decorated. Esse
redirecionamento de chamadas obtido pelo mtodo __call(), automaticamente
executado sempre que um mtodo no encontrado na classe atual for executado.
Nesses casos a execuo redirecionada por meio da funo call_user_func_array()
para o objeto decorado.
432
App/Control/ContatoFormWrapper.php
<?php
use Livro\Control\Page;
use Livro\Control\Action;
use Livro\Widgets\Form\Form;
use Livro\Widgets\Form\Entry;
use Livro\Widgets\Form\Combo;
use Livro\Widgets\Form\Text;
use Livro\Widgets\Container\Panel;
use Livro\Widgets\Wrapper\FormWrapper;
class ContatoFormWrapper extends Page {
private $form;
function __construct() {
parent::__construct();
// instancia um formulrio
$this->form = new FormWrapper(new Form('form_contato'));
$this->form->style = 'display:block; margin:20px;';
// cria os campos do formulrio
$nome
= new Entry('nome');
$email
= new Entry('email');
$assunto = new Combo('assunto');
$mensagem = new Text('mensagem');
$this->form->addField('Nome', $nome, 300);
$this->form->addField('E-mail', $email, 300);
$this->form->addField('Assunto', $assunto, 300);
$this->form->addField('Mensagem', $mensagem, 300);
// define alguns atributos
$assunto->addItems( array('1' => 'Sugesto',
'2' => 'Reclamao',
'3' => 'Suporte tcnico',
433
6.2 Listagens
At o momento, vimos como implementar formulrios de uma maneira orientada
a objetos. Usamos formulrios para cadastrar novos registros, bem como editar
registros existentes. Porm, antes de chegarmos a uma tela contendo um formulrio,
440
Lib/Livro/Widgets/Datagrid/DatagridColumn.php
<?php
namespace Livro\Widgets\Datagrid;
use Livro\Control\Action;
class DatagridColumn {
private $name;
private $label;
private $align;
captulo 7
Quando morremos, nada pode ser levado conosco, com a exceo das
sementes lanadas por nosso trabalho e do nosso conhecimento.
Dalai Lama
Ao longo desta obra, criamos uma srie de classes para automatizar desde a conexo com banco de dados, transaes, persistncia de objetos e manipulao de
colees de objetos, at a criao de componentes para interface como dilogos,
formulrios, listagens, e outros. Ao longo de cada captulo procuramos dar exemplos da utilizao de cada classe criada e agora chegou o momento de utilizar esse
conhecimento para construir algo maior, uma aplicao completa.
7.1 Aplicao
O objetivo deste captulo a construo de uma aplicao para controle de vendas.
Essa aplicao contar com cadastros bsicos como clientes, cidades, produtos,
fabricantes, processo de registro de vendas, e tambm relatrios de vendas e de
contas geradas. Com isso, pretendemos mostrar como construir diferentes tipos
de interface e interao entre o usurio e a aplicao. A aplicao criada ser
de pequeno porte, e no ter como objetivo o uso em um ambiente real, afinal
somente um prottipo voltado para o aprendizado. Ao compreender como o
prottipo foi construdo, voc poder construir aplicaes maiores.
A aplicao proposta contar com as seguintes funcionalidades:
Cadastro de cidades Oferecer um cadastro de cidades, com informaes como:
nome da cidade e estado.
466
467
7.1.1 Index
No captulo 5 abordamos o Design Pattern Front Controller pela primeira vez.
importante lembrar que para Martin Fowler um Front Controller um controlador que manipula todas as requisies do sistema. Para implementar um Front
Controller, utilizamos o prprio index.php. A partir daquele instante, convencionamos que, para executar alguma classe controladora especfica, seria necessrio
acessar index.php?class=ClienteControl. Porm, para executar uma ao especfica,
seria necessrio acessar index.php?class=ClienteControl&method=listar, por exemplo.
Em um sistema grande, existem tarefas comuns a todas as pginas do sistema,
como: verificao de permisso, carregamento das classes (Autoloader), carregamento do template do sistema, entre outras. Essas tarefas comuns podem ser
realizadas justamente no index.php. O index.php a seguir, que ser utilizado para
a nova aplicao, define os Autoloaders, responsveis pelo carregamento dos
componentes construdos no diretrio Lib (ClassLoader) e tambm para as classes
da aplicao construdas no diretrio App (AppLoader). Em seguida, verifica se h
alguma requisio ($_GET). Se h uma requisio e se existe um parmetro chamado
468
Para encaixar o contedo do programa dentro do template relativamente simples. Veja no programa a seguir que realizada a leitura do contedo do arquivo
de template que est localizado em App/Templates/template.html. O contedo desse
arquivo armazenado na varivel $template. Logo em seguida, verificado se h
alguma requisio ($_GET) informando uma classe ($_GET['class']). Caso exista
alguma requisio desse tipo, o contedo da pgina exibido no momento em
que executamos o seu mtodo show(). Todo esse processo est protegido por um
controle de excees try/catch.
Para capturar o contedo gerado por uma pgina, usamos o controle de output
do PHP, com as funes ob_start(), ob_get_contents() e ob_end_clean(), que capturam
o contedo gerado por comandos como echo ou print. Dessa forma, a execuo do
472
7.2 Modelo
Para desenvolver nossa aplicao de vendas proposta neste captulo, precisamos
criar um modelo coerente e compreensvel, que facilite o posterior desenvolvimento do mesmo. Vamos ento criar um modelo de classes, que demonstrar o
relacionamento entre os objetos da aplicao, e em seguida convert-lo em um
modelo relacional, com os relacionamentos entre as tabelas de um banco de dados.
Temos a classe Pessoa, que armazenar os clientes do sistema. Pessoa tem associao
com Cidade e esta com Estado. Uma Pessoa poder ter vrios grupos, por isso a agregao com a classe Grupo. Objetos da classe Conta estaro associados com a Pessoa
para qual aquela Conta deve ser paga. Objetos da classe Venda estaro associados
474
500
Na figura 7.4 apresentado o resultado final do formulrio construdo. O formulrio em questo est no modo de edio.
506
528
A partir do momento em que o usurio clicar no boto Terminar, ser direcionado outra interface, que por sua vez permitir que o mesmo informe detalhes
529
da transao para que a mesma seja armazenada no banco de dados. Nesta etapa,
ele informar: cliente, descontos, acrscimos, parcelamento e observao. A figura
7.10 demonstra essa tela de finalizao, que ir registrar a venda na base de dados,
bem como gerar as parcelas financeiras. Esta classe ser chamada de ConcluiVendaForm.
539
Na parte superior da tela teremos um formulrio perguntando duas datas (inicial e final de vencimento). Com base nas datas informadas (que so opcionais)
o programa ir gerar uma listagem no formato HTML sobre as contas com