Você está na página 1de 235

PHP & MySQL

Essentials

www.4linux.com.br
-2

Sumário

Capítulo 1
Introdução
......................................................................................................................................................10
1.1. Objetivos...........................................................................................................................10
1.2. Definição do projeto.........................................................................................................11
1.3. PHP e MySQL - onde vamos chegar ...............................................................................11
1.4. Como funciona um servidor Web ....................................................................................12
1.4.1. URL (Uniform Resource Locator) ou endereço da página
..........................................................................................................................................................14
1.4.2. Protocolo .................................................................................................................................14
1.4.3. Endereço do Servidor : Porta .................................................................................................15
1.4.4. Diretório/Arquivo ...................................................................................................................16
1.4.5. Arquivos índice de diretórios..................................................................................................16
1.5. Instalando o servidor web Apache com suporte ao PHP ...............................................17
1.5.1. Gerenciando pacotes com o Aptitude ....................................................................................17
1.5.2. Instalando o servidor Apache 2 com suporte ao PHP5..........................................................18

Capítulo 2
Breve revisão ao HTML/XHTML ................................................................................................20
2.1. Objetivos...........................................................................................................................20
2.2. Introdução teórica............................................................................................................21
2.3. Conhendo e personalizando o editor Gedit ....................................................................22
2.4. Estrutura básica de uma página HTML/XHTML ...........................................................23
2.5. Um primeiro exercício em HTML/XHTML ....................................................................25
2.5.1. Organizando o exercício ........................................................................................................25
2.5.2. Formulário de Compras .........................................................................................................26
2.6. Páginas estáticas X Páginas dinâmicas ..........................................................................28

Capítulo 3
A solução: PHP ............................................................................................................................29
3.1. Objetivos...........................................................................................................................29
3.2. Introdução teórica............................................................................................................29
3.3. Características do PHP ...................................................................................................30
3.4. Sintaxe básica .................................................................................................................31
3.5. Variáveis ..........................................................................................................................33
3.5.1. Conceito...................................................................................................................................33
3.5.2. Nomes de variáveis ................................................................................................................34
-3

3.5.3. Tipos de variáveis suportados ...............................................................................................34


3.5.4. Atribuíndo valor a uma variável.............................................................................................35
3.5.5. Atribuíndo valor a Strings ......................................................................................................35
3.6. Exercício Teórico..............................................................................................................37
3.7. Variáveis do PHP .............................................................................................................38
3.7.1. Variáveis de ambiente ............................................................................................................38
3.7.2. Variáveis superglobais ...........................................................................................................38
3.7.3. Constantes ..............................................................................................................................39
3.7.4. Constantes pré-definidas .......................................................................................................39
3.8. Operadores .....................................................................................................................39
3.8.1. Aritméticos .............................................................................................................................40
3.8.2. Operador de strings ...............................................................................................................40
3.8.3. Operador de atribuição ..........................................................................................................41
3.8.4. Operadores bit a bit ...............................................................................................................41
3.8.5. Operadores lógicos ................................................................................................................42
3.8.6. Operadores de comparação ...................................................................................................42
3.8.7. Operadores de incremento e decremento .............................................................................43
3.8.8. Ordem de precedência dos operadores .................................................................................43
3.9. Exercícios Teóricos...........................................................................................................44

Capítulo 4
Integrando o PHP ao HTML .......................................................................................................46
4.1. Objetivos...........................................................................................................................46
4.2. Primeira forma:................................................................................................................47
4.3. Segunda Forma:...............................................................................................................48
4.3.1. Terceira forma:........................................................................................................................48
4.4. Laboratório.......................................................................................................................49

Capítulo 5
Estruturas de controle ...............................................................................................................50
5.1. Objetivos...........................................................................................................................50
5.2. Introdução teórica............................................................................................................50
5.3. Condição: if/else ..............................................................................................................51
5.4. Condição elseif e switch/case .........................................................................................52
5.4.1. Adicionando ao script .............................................................................................................54
5.5. Laços de Repetição ou Loops .........................................................................................55
5.5.1. Interrompendo uma estrutura de controle ...........................................................................56
5.6. Laboratório.......................................................................................................................56

Capítulo 6
Funções .......................................................................................................................................57
-4

6.1. Objetivo.............................................................................................................................57
6.2. Introdução teórica............................................................................................................57
6.3. Laboratório.......................................................................................................................59
6.4. Escopo das Variáveis .......................................................................................................59

Capítulo 7
Formulários, GET e POST...........................................................................................................62
7.1. Objetivos...........................................................................................................................62
7.2. Passando variáveis entre scripts.....................................................................................63
7.2.1. Os métodos GET e POST ........................................................................................................63
7.3. Laboratório.......................................................................................................................66
7.4. Criando Links...................................................................................................................66

Capítulo 8
Arrays e Strings...........................................................................................................................68
8.1. Objetivos...........................................................................................................................68
8.2. Arrays...............................................................................................................................68
8.3. Strings..............................................................................................................................69
8.4. Strings vão muito além doque apenas caracteres que representam texto. Com strings
podemos trabalhar com arrays, validação de campos, formatação de texto e até mesmo
criar uma classe de template.
Vamos ver nesse capitulo algumas funções interessantes para se trabalhar com Strings.. 69
8.4.1. str_replace()............................................................................................................................69
8.4.2. strip_tags()...............................................................................................................................70
8.4.3. stristr().....................................................................................................................................70
8.4.4. strcmp()...................................................................................................................................71
8.4.5. Explode e Implode...................................................................................................................71
8.5. Laboratório.......................................................................................................................72

Capítulo 9
Header, Cookies, Sessões ...........................................................................................................73
9.1. Objetivos...........................................................................................................................73
9.2. Introdução teórica............................................................................................................74
9.2.1. Como utilizar sessões .............................................................................................................74
9.3. Laboratório.......................................................................................................................75

Capítulo 10
Introdução ao Banco de dados MySQL.......................................................................................76
10.1. Objetivos.........................................................................................................................76
10.2. Introdução teórica..........................................................................................................77
10.3. Instalando o MySQL ......................................................................................................77
-5

10.3.1. Melhorando a segurança do banco .....................................................................................78


10.4. Instalando o suporte ao MySQL no PHP 5. ..................................................................80
10.4.1. Instalando uma interface web para gerenciamento do MySQL .........................................80
10.5. Conceitos básicos de Banco de Dados .........................................................................80
10.5.1. Tabelas ..................................................................................................................................80
10.5.2. Registros (ou tupla) ..............................................................................................................81
10.5.3. Colunas (Atributos ou Campos) ...........................................................................................81
10.5.4. Domínio (Tipos de Dados) ....................................................................................................81
10.5.5. Chave ....................................................................................................................................81
10.5.6. Índices ..................................................................................................................................82
10.5.7. Relacionamentos ..................................................................................................................83
10.6. A Linguagem SQL .........................................................................................................83
10.6.1. Alguns padrões de sintaxe para o SQL do MySQL .............................................................84
10.6.2. Tipos de dados mais usados no MySQL ..............................................................................85
10.7. Criando Bancos e Tabelas .............................................................................................86
10.7.1. Criando tabelas ....................................................................................................................87
10.7.2. Obtendo informações sobre o banco e tabelas....................................................................88
10.7.3. Inserindo registros (INSERT) ..............................................................................................88
10.7.4. Atualizando registros (UPDATE) ........................................................................................90
10.7.5. Excluindo registros (DELETE) .............................................................................................91
10.7.6. Selecionando registros (SELECT) .......................................................................................92
10.8. Administração de usuários ..........................................................................................95
10.9. phpMyAdmin .................................................................................................................96
10.10. Construindo a base de dados do website ...................................................................96
10.10.1. Garantindo as permissões de acesso .................................................................................99
10.10.2. Populando o banco. ............................................................................................................99
10.11. Conceitos Avançados...................................................................................................99
10.11.1. Transações..........................................................................................................................99
10.11.2. Prepared Statment............................................................................................................100
10.12. Finalizando ................................................................................................................101

Capítulo 11
Integrando o PHP com MySQL ................................................................................................102
11.1. Objetivos.......................................................................................................................102
11.2. Extensão Melhorada MySQL (mysqli).........................................................................103
11.2.1. Conectando-se ao banco ....................................................................................................103
11.2.2. Executando consultas ........................................................................................................104
11.2.3. Recuperando registros........................................................................................................105
11.2.4. Passando por todos registros .............................................................................................106
11.2.5. Exemplo completo com uso do Modo Orientado a Objeto ................................................107
11.2.6. Prepared Statment..............................................................................................................108
-6

11.2.7. Transactions........................................................................................................................110
11.3. PDO (PHP Data Objects)..............................................................................................111
11.3.1. Conectando-se ao banco ....................................................................................................112
11.3.2. Executando consultas ........................................................................................................113
11.3.3. Executando inserções, exclusões e atualizações...............................................................114
11.3.4. Prepared Statment..............................................................................................................114
11.3.5. Transactions........................................................................................................................116

Capítulo 12
Programação Orientada a Objetos ...........................................................................................117
12.1. Objetivos.......................................................................................................................117
12.2. Introdução teórica........................................................................................................118
12.3. Conceitos .....................................................................................................................118
12.3.1. Classe .................................................................................................................................118
12.3.2. Objeto .................................................................................................................................119
12.3.3. Atributos .............................................................................................................................119
12.3.4. Métodos ..............................................................................................................................119
12.4. Uma classe simples: Pessoa ........................................................................................119
12.5. Herança .......................................................................................................................122
12.6. Encapsulamento ..........................................................................................................124
12.7. Métodos mágicos.........................................................................................................125
12.7.1. __construct .........................................................................................................................125
12.7.2. __destruct ...........................................................................................................................127
12.7.3. __get e __set.........................................................................................................................127
12.7.4. __toString............................................................................................................................130
12.7.5. Outros métodos mágicos ...................................................................................................131
12.8. Classes Abstratas ........................................................................................................131
12.9. Interfaces e Métodos Abstratos...................................................................................132
12.9.1. Interfaces............................................................................................................................132
12.9.2. Métodos Abstratos..............................................................................................................133
12.10. Atributos Estáticos ....................................................................................................133
12.11. Métodos Estáticos .....................................................................................................134
12.12. A mensagem de erro mais louca do PHP .................................................................137

Capítulo 13
Streams......................................................................................................................................138
13.1. Objetivo........................................................................................................................138
13.2. Introdução teórica........................................................................................................138
13.3. Método fopen ..............................................................................................................139
13.3.1. Gravando informações em arquivos ..................................................................................139
13.3.2. Lendo arquivos ...................................................................................................................140
-7

13.3.3. Fechando arquivos ............................................................................................................140


13.4. Método file ..................................................................................................................140
13.5. Método file_get_contents ............................................................................................141

Capítulo 14
Tratamento de Erros e Exceções..............................................................................................142
14.1. Objetivos.......................................................................................................................142
14.2. Exibição de erros.........................................................................................................142
14.2.1. Função die...........................................................................................................................144
14.2.2. Capturando e Gerando Erros..............................................................................................144
14.2.3. Registro de Erros (Log)......................................................................................................145
14.2.4. Configurando o php.ini.......................................................................................................146
14.3. Tratamento de Exceções..............................................................................................147
14.3.1. Métodos...............................................................................................................................147

Capítulo 15
Construindo uma classe de acesso a dados .............................................................................148
15.1. Objetivos.......................................................................................................................148
15.2. Porque uma classe Tabela? .........................................................................................149
15.3. Construindo a classe tabela ........................................................................................150
15.3.1. config.inc.php – arquivo de configuração..........................................................................150
15.3.2. Atributos da Classe Tabela.................................................................................................151
15.3.3. Construtor ..........................................................................................................................152
15.3.4. Um getter automático.........................................................................................................154
15.3.5. Método para execução de consultas..................................................................................155
15.3.6. Listando (SELECT) registros..............................................................................................157
15.3.7. Recuperando um registro pela chave primária.................................................................159
15.3.8. Excluindo um registro pela chave primária.......................................................................160
15.3.9. Inserindo um registro.........................................................................................................161
15.3.10. Atualizando um registro....................................................................................................163
15.4. Criando um CRUD........................................................................................................166
15.4.1. O que é um CRUD?.............................................................................................................166
15.4.2. Criando as classes filhas ....................................................................................................166
15.4.3. Adicionando um método específico à classe......................................................................167
15.4.4. Exemplo de uso ..................................................................................................................168

Capítulo 16
Separando HTML do PHP: Classe Template............................................................................175
16.1. Objetivo........................................................................................................................175
16.2. Introdução teórica........................................................................................................176
16.3. Classe Template: pegando e exibindo arquivos de templates....................................177
16.4. Cabecalho do Site Administrativo...............................................................................180
-8

16.5. Cabeçalho do site público............................................................................................182


16.6. Rodapé..........................................................................................................................183
16.7. Abstração de listagem de registros.............................................................................184
16.8. Outros métodos............................................................................................................188
16.8.1. templates/login.html...........................................................................................................197
16.8.2. templates/livroResumo.html...............................................................................................198
16.8.3. templates/livroDetalhe.html ..............................................................................................199

Capítulo 17
Segurança: Sistema de Login...................................................................................................200
17.1. Objetivo........................................................................................................................200
17.2. Classe Seguranca.........................................................................................................201
17.2.1. login.php..............................................................................................................................204
17.2.2. logout.php...........................................................................................................................206
17.2.3. index.php alterado para checar usuário logado................................................................206

REFERÊNCIAS
BIBLIOGRÁFICAS......................................................................................................................207

ANEXOS.....................................................................................................................................209
HTML/XHTML - Referência Básica......................................................................................210
Estrutura Básica de uma página ....................................................................................................210
Tags de Texto ..................................................................................................................................211
Listas ...............................................................................................................................................211
Imagens ..........................................................................................................................................212
Tabelas ............................................................................................................................................212
Formulários .....................................................................................................................................213
Enviando e-mails com o PHP ...............................................................................................217
Verificando o tipo de uma variável ......................................................................................218
Transformação de tipos - Coerções ...............................................................................................219
Transformação explícita de tipos ...................................................................................................221
Conexão segura ....................................................................................................................222
Instalando a ferramenta OpenSSL - (Secure Socket Layer) .........................................................222
Criando uma certificadora local ....................................................................................................222
Criando um site seguro ..................................................................................................................223
Acertando o resolvedor de nomes local .........................................................................................224
Criando uma requisição de certificação ........................................................................................224
Assinando a certificação ................................................................................................................224
Habilitando o site seguro ...............................................................................................................225
Habilitando conexão segura ...........................................................................................................225
Reiniciando o servidor web. ...........................................................................................................225
-9

Capítulo 18
A certificação.............................................................................................................................226
18.1. Questionário ZEND(Inglês).........................................................................................227

Índice de tabelas
Tabela 1: Tipos de Dados no PHP5.........................................................................................34
Tabela 2: Caracteres de Escape..............................................................................................36
Tabela 3: Variáveis Superglobais do PHP...............................................................................38
Tabela 4:Operadores aritméticos ...........................................................................................40
Tabela 5: Operador de string .................................................................................................40
Tabela 6: Operadores de Atribuição.......................................................................................41
Tabela 7: Operadores Bit a Bit................................................................................................41
Tabela 8:Operadores lógicos ..................................................................................................42
Tabela 9: Operadores de comparação ...................................................................................42
Tabela 10:Operadores de incremento/decremento ...............................................................43
Tabela 11:Ordem de precedência dos operadores ................................................................43
Tabela 12: Tabela Clientes......................................................................................................80
Tabela 13:Tabela de Operadores de Comparação .................................................................93
Tabela 14:Tabela Operadores Lógicos ...................................................................................94
Tabela 15: Caracteres de especificação de tipo...................................................................109
Tabela 16: Lista de tipos para método bindParm.................................................................114

Índice de Figuras
Figura 1.1: Como funciona um servidor Web.........................................................................13
Figura 10.1: Tabela Pessoa ....................................................................................................87
Figura 12.1: Classe Pessoa...................................................................................................120
Figura 12.2: Herança de classes..........................................................................................122
Capítulo 1 Introdução - 10

Capítulo 1

Introdução

1.1. Objetivos

• Compreender o mercado atual do PHP;

• Entender o funcionamento de um servidor web;

• Estar apto para instalar o servidor web Apache com suporte ao PHP.

Introdução teórica
Agora iremos definir nosso projeto, ver aonde iremos chegar com o PHP e o
SBGD MySQL.
Capítulo 1 Introdução - 11

1.2. Definição do projeto

Nosso projeto será dividido em 4 partes:

◦ Cadastro de Produtos;

◦ Cadastro de Usuário;

◦ Login;

◦ Pedido.

1.3. PHP e MySQL - onde vamos chegar

No mercado atual de desenvolvimento um dos maiores focos é o


desenvolvimento de aplicações para internet - sejam websites, sejam sistemas.
Muitas aplicações que antigamente rodavam exclusivamente em um computador
isolado ou em redes locais hoje são distribuídas através de intranets (redes internas
com recursos da internet) ou extranets (redes internas que se comunicam com
clientes externos).

Estas aplicações necessitam de profissionais que dominem 3 tecnologias


básicas:

• Web Design;
• Uma linguagem de desenvolvimento Web;
• Um banco de dados.

O Web Design é um ramo de criação artística, mas que também envolve a


programação em HTML/XHTML, CSS, e também em linguagens acessórias como
Javascript e Flash. Apesar de ser possível criar inclusive animações (como no caso do
Flash), o Web Design está limitado à criação de páginas ESTÁTICAS, em que o
conteúdo será sempre o mesmo independente de quantas vezes for solicitado.
Capítulo 1 Introdução - 12

Linguagens de desenvolvimento Web permitem a criação de páginas


DINÂMICAS, ou seja, que serão diferentes a depender da solicitação, das
informações que foram atualizadas, do usuário que realiza a requisição, etc. Para isto
são instaladas no lado do servidor, ou interagem com recursos do servidor.

Banco de dados são aplicações que armazenam informações de modo


organizado, facilitando a inclusão, exclusão, alteração, exclusão e recuperação destes
dados. Existem várias situações em que os dados estão armazenados em sistemas
especialistas, como servidores de email, sistemas de arquivos, etc, mas o uso mais
intensivo e comum é armazenar em banco de dados.

Entretanto, para utilizar estas tecnologias é preciso um hospedeiro que as


forneça para os clientes: o Servidor Web

1.4. Como funciona um servidor Web

Servidor é um aplicativo que aguarda requisições de clientes, realiza algum


processamento baseado nestas requisições e responde a eles conforme as suas
atribuições.

Servidores Web, a princípio, são "entregadores de arquivos". Recebem


requisições de arquivos (geralmente HTML e imagens) dos clientes e entregam.
Entretanto, são mais inteligentes do que isso, podendo repassar requisições para
outros sistemas, linguagens de programação, etc, receber este processamento e
repassar para o cliente.

No lado do cliente é necessário um aplicativo cliente, conhecido como


navegador ou browser. Ele envia as requisições ao servidor Web e tem a função de
interpretar o código recebido (HTML/XHTML, principalmente), montar a página e
requisitar informações adicionais como imagens e outras mídias.

O protocolo de comunicação utilizado pelos servidores Web é o HTTP


(Protocolo de Transferência de Hipertexto). Sites seguros utilizam o protocolo
HTTPS, que é uma extensão segura do HTTP.
Capítulo 1 Introdução - 13

Figura 1.1: Como funciona um servidor Web

Na Figura 1.1: Como funciona um servidor Web ilustra-se o funcionamento


básico de um servidor Web.

É importante perceber que, de modo básico, o servidor Web é um servidor de


páginas HTML/XHTML. Os arquivos HTML/XHTML possuem comandos (tags) que
solicitam outros tipos de arquivos (imagens, animações, etc) ao servidor. Então, uma
única página HTML/XHTML servida pode resultar em várias solicitações adicionais
ao servidor (chamados "hits").
Capítulo 1 Introdução - 14

1.4.1. URL (Uniform Resource Locator) ou endereço da página

O endereço de um página web é representado pela URL (Uniform Resource


Locator). Ele é composto de:

• Protocolo
• Endereço do Servidor (normalmente seu nome de host/domínio): porta (a
porta é opcional)
• Recurso no servidor (no caso de serviços Web, diretório/arquivo)

Exemplo:

http://www.4linux.com.br/cursos/php-mysql-web-developer-412.html

1.4.2. Protocolo

Protocolo pode ser compreendido como uma "língua comum" para que dois
computadores troquem informações dentro de um padrão de requisição e respostas,
independente de suas plataformas, ambientes, linguagens de programação, etc.

Isto permite que um computador rodando Windows se comunique com um


outro computador rodando Linux, MacOS, Unix, etc, e independente de fabricantes
de hardware - e vice-versa também.

O protocolo dos servidores Web, como já vimos, é o HTTP (ou HTTPS para
modo seguro). Entretanto, é comuns os navegadores também se comunicarem com
outros serviços com outros protocolos como o FTP.

No caso de uma URL para um endereço web, o protocolo será normalmente


http:// ou https://.
Capítulo 1 Introdução - 15

1.4.3. Endereço do Servidor : Porta

O endereço do servidor geralmente é representado geralmente por um FQDN


(Fully Qualified Domain Name - Nome de Domínio Plenamente Qualificado) de um
host DNS (Domain Name System - Sistema de Nomes de Domínios), mas também
pode ser representado pelo seu endereço IP.

O DNS é um sistema que trabalha como uma "agenda telefonica", resolvendo


nomes de domínio para endereços IP, que são a forma direta de comunicação a um
servidor. Todo servidor possui seu endereço IP, e também podemos acessá-lo
diretamente por ele.

Entretanto, existem diversos servidores web com um único IP respondendo


por vários domínios, então neste caso é mandatório utilizar-se o nome de host em
DNS para acessar este serviço.

A porta padrão dos servidores Web é 80 e por isto pode ser omitida na
navegação usual. Se o servidor aguarda requisições em outra porta, é necessário
informá-la após o endereço, separado por dois pontos.

Exemplos de Endereços:
www.4linux.com.br
netclass.hackerteen.com
66.118.142.41
netclass.hackerteen.com:8020
66.118.142.41:8050

Observação: O nome de host www é um padrão para nomes de máquinas que


hospedam um site Web, mas não é uma obrigatoridade. Atualmente é muito comum
sites mais curtos, ou que respondam sem a necessidade desta informação
(redirecionam automaticamente para www). Teste: http://4linux.com.br e veja o que
acontece.
Capítulo 1 Introdução - 16

1.4.4. Diretório/Arquivo

Uma vez fechada a conexão com o servidor, então solicitamos um arquivo


específico a ser retornado. Este é solicitado na estrutura diretorio/nome_arquivo.

É importante compreender que existe uma relação direta entre o caminho que
informamos e o sistema de arquivos, pois o servidor Web determina um "caminho
raiz" para os arquivos.

Deste modo, sendo o caminho raiz de um domínio:

/var/www/4linux

Então, se solicitamos o endereço:

http://www.4linux.com.br/cursos/php-mysql-web-developer-412.html

O servidor Web nos retornará o arquivo:

/var/www/4linux/cursos/php-mysql-web-developer-412.html

Este exemplo é um simplificação. Diversos sistemas web modernos utilizam


um recurso chamado de "reescrita de URLs" (URL rewrite), onde um
endereço é redirecionado internamente para arquivos que os processam
dinamicamente, mediante regras determinadas - mas os clientes utilizam
sempre endereços uniformes e fixos.

1.4.5. Arquivos índice de diretórios

Com um pouco de atenção é possível perceber um "furo" neste sistema:


quando não é inforado nenhum arquivo, (exemplo: http://www.4linux.com.br e
Capítulo 1 Introdução - 17

http://www.4linux.com.br/cursos, que arquivo será fornecido pelo servidor web?

Neste caso existe uma configuração nos servidores que é DirectoryIndex (ou
semelhante): ele especifíca qual o arquivo que será acessado caso se requisite
apenas um diretório, ou seja, qual o índice do diretório. Os padrões mais comuns são
index.html (padrão Apache) e default.html (padrão ISS, da Microsoft). Quando o
servidor possui vínculo com alguma outra linguagem, é comum que os arquivos desta
linguagem também sejam configurados, como index.php (PHP), index.pl (Perl), etc.

1.5. Instalando o servidor web Apache com


suporte ao PHP

1.5.1. Gerenciando pacotes com o Aptitude

Nosso curso será realizado numa plataforma GNU/Linux utilizando a


distribuição Debian 5.0-Lenny. O gerenciador de pacotes oficial do Debian é o
aptitude. Para o utilizarmos, precisamos inicialmente configurar os repositórios no
arquivo /etc/apt/sources.list. No nosso caso, usaremos um repositório interno.

Configure as fontes como mostrado abaixo :

deb http://192.168.1.1/lenny main contrib non-free

Agora atualizaremos a base de dados local :

# aptitude update

Podemos procurar por pacotes com o comando abaixo. Por exemplo, para
buscar o pacote apache2 :
Capítulo 1 Introdução - 18

# aptitude search apache2

Existem vários pacotes. São em sua maioria pacotes de bibliotecas opcionais.


Mas aquele que nos interessa é o apache2

1.5.2. Instalando o servidor Apache 2 com suporte ao PHP5

# aptitude install apache2

Testando a instalação

Abra um navegador e digite a URL:

http://localhost/

Se tudo funcionou bem, vamos instalar o PHP 5 :

# aptitude install php5

Testando a instalação do PHP5

Para testar, é necessário criar um arquivo com extensão .php no diretório raiz
do servidor web, que é /var/www:

# gedit /var/www/phpinfo.php
Capítulo 1 Introdução - 19

Coloque neste arquivo o seguinte código:

<?php phpinfo() ?>

E então é possível verificá-lo na endereço:

http://localhost/phpinfo.php

Esta função especial do PHP fornece dados completos sobre a instalação do


servidor Web e do PHP, sendo muito útil no desenvolvimento - mas perigoso em um
ambiente de produção, onde não devemos dar informações excessivas aos clientes.

Agora você está com seu servidor Web com suporte a PHP funcional.
Capítulo 2 Breve revisão ao HTML/XHTML - 20

Capítulo 2

Breve revisão ao HTML/XHTML

2.1. Objetivos

• Rever os conteúdos necessários de HTML;

• Compreender as diferenças de páginas estáticas e páginas dinâmicas.


Capítulo 2 Breve revisão ao HTML/XHTML - 21

2.2. Introdução teórica

O HTML (HyperText Markup Language - Linguagem de Marcação de


Hipertexto) é uma linguagem de marcação, ou seja, utiliza TAGS (marcadores) para
indicar início e fim de comandos.

Atualmente utilizamos o padrão HTML 4.01. Entretanto, existe uma outra


especificação, que é o XHTML 1.0, que é uma reformulação do HTML para seguir os
padrões do XML, muito mais rígido, mas também muito mais portável e consistente
que o HTML. O XHTML exige tags em minúsculas e sempre fechadas (abriu, fechou),
atributos sempre com valores e com valores entre aspas simples, entre outras coisas.

O XHTML também não permite formatação dentro das TAGS como o HTML, a
formatação é sempre através de folhas de estilo em cascata (CSS). Isto facilita muito
a vida do programador, além de tornar as páginas mais leves e de carregamento mais
ágil.

Entretanto, HTML e XHTML são muitíssimo parecidos. Neste curso, o


conjunto de TAGS utilizadas são praticamente coincidentes nas duas. A sintaxe será
preferencialmente em XHTML (tags minúsculas, sem formatação no conteúdo) mas
sem rigidez, ou seja, aceitando algumas facilidade do HTML, pois não é objetivo ser
um curso de XHTML/HTML.

Sugere-se que o desenvolvedor em Web domine o XHTML e CSS, para


implementar com padrões mais consistentes seus projetos. Entretanto, não é escopo
deste curso o Webdesign, portanto, apenas tags básicas serão revistas para o bom
andamento do curso.

A seguir será feita uma pequena revisão dos conceitos das TAGS
HTML/XHMTL e criado um pequeno conjunto de páginas com as TAGS básicas para
este curso.

No Apendice A - HTML/XHTML - Tags Básicas você encontra uma referência


básica às tags utilizadas neste exercício.
Capítulo 2 Breve revisão ao HTML/XHTML - 22

2.3. Conhendo e personalizando o editor Gedit

Utilizaremos o editor Gedit em nosso curso. Ele é simples, mas possui


alguns recursos úteis que nos ajudarão na edição dos arquivos em
HTML/XHTML e PHP.

Sempre acesse o Gedit como root, pois de outro modo não será possível
salvar os arquivos dentro do diretório /var/www.

Para isto, acesse um terminal como root e digite:

#cd /var/www
#gedit &

O "&" informa que o comando será executado em segundo plano, liberando


o terminal para outros comandos.

Configurações interessantes no Gedit (menu Editar -> Preferências):

• Aba Visualização, ativar Mostrar números de linha;


• Aba Visualização, ativar Destacar parênteses correspondentes;
• Aba Editor, Largura das tabulações: informar 2;
• Aba Editor, ativar Inserir espaços em vez de tabulações.

Outra dica interessante é o realce de sintaxe, que facilita a detecção de erros


de digitação. Para usá-la, ao iniciar um novo arquivo já o salve com a extensão
adequada (.html para HTML, .php para PHP, etc). Caso necessite forçar um realce
específico, utilize o menu Ver -> Modo de destaque e selecione o desejado.
Capítulo 2 Breve revisão ao HTML/XHTML - 23

2.4. Estrutura básica de uma página


HTML/XHTML

Os documentos em HTML/XHTML, como já foi mencionado, são estruturas


organizadas em TAGS, que são elementos (palavras chave) entre os sinais < e >. Eles
são comandos de formatação da linguagem. As TAGS possuem abertura e
fechamento, geralmente representadas assim:

1 <b>texto em negrito</b>
2 <p> parágravo </p>
3 <h1> título em primeiro nível </h1>

Algumas TAGS não possuem fechamento (no HTML) ou são "autofechadas",


(no XHTML que exige que toda TAGS tenham fechamento). Isto é comum em
elementos vazios ou que não englobam texto:

4 <br />Quebra de linha


5 <hr />Linha horizontal
6 <input type="text" name="endereco" />

Como toda linguagem de programação, existe um meio de expressar


comentários, trechos que não serão executados, apenas para documentação:

7 <!-- Esta é a TAG de comentário -->

As TAGS podem ter atributos, que no XHTML devem obrigatoriamente ter


valor e este estar entre aspas duplas:

8 <textarea name="observacao" rows="20" cols="50">


9 algum texto
10 </textarea>
Capítulo 2 Breve revisão ao HTML/XHTML - 24

Todo documento HTML deveria ter a seguinte estrutura básica (o XHTML


EXIGE):

11 <html>
12 <head>
13

14 <title>Título da página</title>
15 </head>
16 <body>
17 textos, imagens, links, etc...
18 </body>
19 </html>

O documento HTML/XHTML possui dois grandes blocos: o <head> e o <body>.


No <head> são colocadas informações de cabeçalho do arquivo, inclusive o título da
página, inclusão de arquivos externos como CSS e Javascript, definição de metatags
para agilizar pesquisas em sites de busca. No <body> é onde se coloca o conteúdo
propriamente dito da página.

No HTML não há distinção entre tags com caixa baixa ou alta, ou seja <HTML>,
<Html> e <html>, mas o XHTML é rígido e só aceita tags e atributos em minúsculas.

OBSERVAÇÃO:

Olhando com atenção arquivos na internet veremos que a maioria dos


arquivos começam um código como segue:

20 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


21 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
Capítulo 2 Breve revisão ao HTML/XHTML - 25

Este é o DOCTYPE, ou seja, definição do tipo de arquivo e especificação de


sua especificação DTD(Document Type Definition). Este é um tópico avançado sobre
HTML/XHTML, e foge do escopo deste curso. Você pode saber um pouco mais sobre
isto nas referências abaixo:

Doctype - DTD - Document Type Definition (em português):


http://revolucao.etc.br/archives/doctype-dtd-document-type-definition/

Recommended DTDs to use in your Web document (em inglês):


http://www.w3.org/QA/2002/04/valid-dtd-list.html

2.5. Um primeiro exercício em HTML/XHTML

2.5.1. Organizando o exercício

Para construir um exemplo organizado, vamos criar um diretório base para


nosso exercício. Abra um terminal como root e siga os comandos:

#cd /var/www
#mkdir curso
#cd curso
#mkdir html
#mkdir php

Agora temos o diretório /var/www/curso/html, que pode ser acessado no


navegador pela URL http://localhost/curso/html .
Capítulo 2 Breve revisão ao HTML/XHTML - 26

2.5.2. Formulário de Compras

Esta página conterá um pequeno formulário em HTML.

Salve o arquivo abaixo em /var/www/curso/html/comprar.html.

1 <html>
2 <head>
3 <title>
4 Borracharia do Tux
5 </title>
6 </head>
7 <body>
8 <h1>Borracharia do Tux</h1>
9 <form action="processar.html" method="post">
10 <table border="1">
11

12 Item
13 Quantidade
14

15

16 <td>Rodas</td>
17 <td>
18 <input type="text" name="nrodas" size="3" maxlength="3">
19 </td>
20

21

22 <td>Pneus</td>
23 <td>
24 <input type="text" name="npneu" size="3" maxlength="3">
25 </td>
26

27

28 <td>Parafusos</td>
29 <td>
30 <input type="text" name="nparafusos" size="3" maxlength="3">
31 </td>
Capítulo 2 Breve revisão ao HTML/XHTML - 27

32

33

34 <td>Como você conheceu a Borracharia do Tux?</td>


35 <td>
36 <select name="find">
37 <option value="a">Na 4Linux</option>
38 <option value="b">Anúncio na TV</option>
39 <option value="c">Internet</option>
40 <option value="d">Indicação</option>
41 </select>
42 </td>
43

44

45 <td colspan="2">
46 <input type="submit" value="Enviar" />
47 </td>
48

49 </table>
50 </form>
51 </body>
52 </html>

Para acessar em seu navegador utilize a URL


http://localhost/curso/html/comprar.html .

Página de recebimento do Formulário:

Salve o arquivo abaixo em /var/www/curso/html/processar.html.

1 <html>
2 <head>
3 <title>
4 Borracharia do Tux
5 </title>
Capítulo 2 Breve revisão ao HTML/XHTML - 28

6 </head>
7 <body>
8 <h1>Borracharia do Tux</h1>
9 <h2>Pedido finalizado.</h2>
10 </body>
11 </html>

Testando: abra no navegador a URL


http://localhost/curso/html/comprar.html, preencha o formulário e
envie. Você será levado para a página processar.html.

2.6. Páginas estáticas X Páginas dinâmicas

Neste exemplo, se preenchemos ou não o formulário, ou se acessamos a


página processar.html diretamente, o resultado é o mesmo, pois são páginas
estáticas, que não interagem com o usuário. No máximo poderíamos usar um recurso
antigo de enviar um email com o formulário.

Por meio de páginas dinâmicas é possível processar este envio de


informações, realizando tarefas como manipulação de banco de dados e gerar então
páginas com respostas a requisições específicas, ou a envio de formulários com
dados de um determinado cliente, por exemplo.

Isto nos permite então criarmos aplicações web dos mais variados tipos, desde
agendas a fóruns, sistemas de documentação, jogos, chats, dentre outros.

O HTML/XHTML é "público", ou seja, o navegador o recupera e pode ser


visualizado facilmente. Entretanto, é possível embutir dentro do HTML/XHTML
código de outras linguagens, que são processados no servidor e então o navegador só
recebe o resultado. Isto permite uma maior segurança.

Para escrever páginas dinâmicas existem várias linguagens, como Active


Server Pages (ASP); Java Server Pages (JSP); além do PHP Hipertext Preprocesor
(PHP), que é o tópico de nosso curso.
Capítulo 3 A solução: PHP - 29

Capítulo 3

A solução: PHP

3.1. Objetivos

• Estar apto a executar os conceitos básicos vistos nesse capítulo.

• Obter noções de variáveis, sintaxe básica e operadores.

3.2. Introdução teórica

O PHP é uma linguagem para programar scripts, livre, gratuita,


independente de plataforma, rápida e muito utilizada para gerar conteúdo
dinâmico na Web, com uma grande biblioteca de funções e extensa
documentação.
É uma linguagem INTERPRETADA com tipagem DINÂMICA.
Foi criado originalmente em 1994 por Rasmus Lerdorf e ao longo de sua
história teve muitas contribuições de outros desenvolvedores. Atualmente o
PHP está em sua versão 5.2.8 (08/12/2008). Sua versão de desenvolvimento
é a 6.
Capítulo 3 A solução: PHP - 30

Qualquer pessoa pode baixar através da página principal do PHP -


www.php.net - e de forma gratuita, um módulo que faz com que nosso
servidor Web interprete os scripts escritos nesta linguagem.

3.3. Características do PHP

Esta linguagem de programação está preparada para realizar muitos tipos de


aplicações Web, graças à extensa quantidade de funções com a qual está dotada.
Existem funções que cobrem desde cálculos matemáticos complexos até tratamento
de conexões de rede.

O PHP é uma linguagem poderosa e pode fazer praticamente qualquer coisa


que as linguagens concorrentes. Entretanto, é sempre bom lembrar que cada
linguagem tem suas forças e fraquezas, vantagens e desvantagens.

Uma das principais características do PHP é o suporte a um grande número


de bancos de dados, como dBase, Interbase, mySQL, Oracle, Sybase, PostgreSQL e
vários outros, tornando uma tarefa simples construir uma página, baseada em um
banco de dados, com PHP.

Além disso, o PHP tem suporte a outros serviços através de protocolos, como
IMAP, SNMP, NNTP, POP3 e, logicamente, HTTP. Ainda é possível abrir sockets e
interagir com outros protocolos.

Seu primeiro programa em PHP

Utilizaremos um exemplo simples, em que o PHP trará escrito na página a


frase "Olá Mundo!". Utilize o Gedit para criar este arquivo.

12 <?php
13 echo("Olá Mundo!");
14 ?>

Salve o arquivo em /var/www/curso/php/olamundo.php e abra-o em seu


navegador com a URL http://localhost/curso/php/olamundo.php.
Capítulo 3 A solução: PHP - 31

Este exemplo nos mostra o comando echo, que "ecoa" ou envia uma string
como HTML/XHTML. O ideal é que no decorrer do script seja montada uma página
HTML/XHTML perfeitamente formatada para não gerar erros de visualização.

3.4. Sintaxe básica

Para que um arquivo seja interpretado como código PHP é necessário que
ele tenha a extensão .php (ou outra que seja configurada no servidor Web,
o que não é muito comum).

O arquivo pode misturar código em PHP e HTML. Para isto, é preciso


delimitar o conteúdo em PHP com TAGS especiais, que são:

// STANDARD TAGS
<?php
comandos;
?>
// SHORT TAGS
<?
comandos;
?>
// SCRIPT TAGS
<script language="php">
comandos;
</script>
// ASP TAGS
<%
comandos;
%>
Capítulo 3 A solução: PHP - 32

As formas mais comuns são as duas primeiras, sendo que o DESEJÁVEL é a


primeira, por sua clareza e não ambigüidade.

A forma SHORT TAG estará disponível apenas se a opção short_open_tags


for definida como on no arquivo de configuração /etc/php5/apache2/php.ini
do PHP5 – o que é uma opção padrão comum nos servidores.

A forma ASP TAG é “Deprecated”, ou seja, será eliminada em uma versão


futura do PHP – ou seja, não a utilize!

Se o arquivo só contém comandos PHP, é posssível omitir a tag de


finalização ( ?> ). Isto também evita que espaços após esta tag causem
problemas com headers já enviados (principalmente em sessões).

No PHP os comandos deve terminar em ponto-e-vírgula (;), como no exemplo


abaixo:

15 phpinfo();
16 echo "testando";

Se faltar o ponto-e-vírgula haverá um erro no script, como abaixo:

17 phpinfo()
18 echo "testando";
Capítulo 3 A solução: PHP - 33

Entretanto, estruturas de controle não precisam de ponto e vírgula - como é o


caso do if no exemplo:

19 <?php
20 if ($x == $x) //não precisa de ponto e vírgula
21 {
22 echo 'com ponto e vírgula'; //precisa de ponto e vírgula
23 }
24 ?>

Comentários podem ser nas três formas abaixo:

25 <?php
26 // Comentário de uma única linha,
echo "teste" // ou até o final da linha
27 # Comentário de uma única linha, ou até o final da linha (pouco
usado)
28 /*
29 Comentário em
30 múltiplas linhas
31 */
32 ?>

3.5. Variáveis

3.5.1. Conceito

O PHP é uma linguagem fracamente tipada, ou seja, não exige declaração de


tipos. Além disso, é de tipagem dinâmica: determina o tipo da variável conforme o
valor que lhe é atribuído, podendo ter alterado tipo durante a execução pela simples
atribuição de um valor diferente.
Capítulo 3 A solução: PHP - 34

3.5.2. Nomes de variáveis

As variáveis no PHP sempre iniciam com o cifrão ($) seguido de uma letra ou
do caracter "_".

// Variáveis válidas
$dia
$Mes
$_ano
// Variáveis inválidas
$*dia
$9meses
$(nome)

O PHP é case sensitive, ou seja, as variáveis $Mes e $mes são diferentes.

Todo projeto deve ter uma padronização no nome das variáveis. Elas não
devem ser codificadas demais a ponto de não serem claras, nem longas a
ponto de dificultar seu uso. Além disso, deve-se evitar variáveis
complemente em maiúsculas, pois este é um padrão para CONSTANTES.

3.5.3. Tipos de variáveis suportados

PHP suporta os seguintes tipos de dados:

Tabela 1: Tipos de Dados no PHP5

Tipo Macro Tipo Básico Tipo Detalhado


Escalares (scalar) boolean Lógico:
apenas um valor true ou false
0 ou 1
int Decimal: 10, -8765, 0
Octal: 0755, 0140 (inicia com zero)
Hexadecimal: 0x754; 0XFF; -0x1A0
Capítulo 3 A solução: PHP - 35

float Decimal: 10.98, -7976,000987


Exponential: 1E6 (1000000), 1.2e2 (120)
string Texto
Outras informações (conteúdo serializado,
como imagens, som, etc.)
Array Conteiner de elementos ordenados (veja
Compostos mais na página REFERENCIA)
(compound)
Objects Conteiner de dados e código
NULL Representa variável sem valor (que é
diferente de ter valor zero ou vazio)
Outros
resource Indica armazenamento de recursos externos,
geralmente manipulados por módulos.

3.5.4. Atribuíndo valor a uma variável

O símbolo de atribuição é o igual ( = ).

33 <?php
34 $teste = "Linux";
35 $total = 867;
36 ?>

3.5.5. Atribuíndo valor a Strings

Strings podem ser atribuídas de duas maneiras:

Utilizando aspas simples ( ' ) - desta maneira, o valor da variável será


exatamente o texto contido entre as aspas (com exceção de \\ e \' - ver tabela abaixo)

Utilizando aspas duplas ( " ) - desta maneira, qualquer variável ou caractere


de escape será expandido antes de ser atribuído.

Teste o exemplo abaixo :

37 <?php
38 $teste = "Linux";
39 $php = '---$teste---\n';
Capítulo 3 A solução: PHP - 36

40 echo "$php";
41 ?>

A saída desse script será:

---$teste--\n

Teste este outro exemplo

42 <?php
43 $teste = "Linux";
44 $php = "---$teste---\n";
45 echo "$php";
46 ?>

A saída desse script será:

---Linux---

(com uma quebra de linha no final)

Existe também a sintaxe conhecida como HEREDOC, que utiliza o delimitador


especial <<< seguido de uma palavra chave, que determinará o final da string:

47 <?php
48 $teste = <<<TEXT
49 Uma linha de texto
50 TEXT;
51 ?>

A tabela seguinte lista os caracteres de escape:

Tabela 2: Caracteres de Escape

Sintaxe Significado
\n Nova linha
\r Retorno de carro
\t Tabulação horizontal
\\ A própria barra \
\' Aspas simples '
\” Aspas duplas “
Capítulo 3 A solução: PHP - 37

3.6. Exercício Teórico

1. Qual das tags abaixo representa uma ASP TAG:

a) <? ?>

b) <?php ?>

c) <# #>

d) <% %>

2. Como eu declaro uma HEREDOC?

___________________________________________________________________________________

___________________________________________________________________________________

___________________________________________________________________________________

3. Qual a diferença de “aspas duplas” para 'aspas simples' ?

___________________________________________________________________________________

___________________________________________________________________________________

___________________________________________________________________________________

2. Explique o significado dos seguintes caracteres de escape e de um exemplo de


utilização:

\n ->______________________________________________________________________________

\t ->______________________________________________________________________________

\r ->______________________________________________________________________________
Capítulo 3 A solução: PHP - 38

3.7. Variáveis do PHP

3.7.1. Variáveis de ambiente

O PHP possui diversas variáveis de ambiente, como a $PHP_SELF, que contém


o nome e o path do próprio arquivo. Algumas outras contém informações sobre o
navegador do usuário, o servidor http, a versão do PHP e outras diversas
informações.

Para ter uma listagem de todas as variáveis e constantes de ambiente e seus


respectivos conteúdos, utilizamos a função phpinfo().

3.7.2. Variáveis superglobais

O PHP possui um conjunto de variáveis reservadas e pré-definidas, de tipo


array, que mantêm diversas informações do programa e do ambiente. Essas variáveis,
são chamadas de superglobais e são de escopo global.

As variáveis superglobais do PHP são:

Tabela 3: Variáveis Superglobais do PHP

Variável Descrição
$GLOBALS Contém uma referência a cada variável disponível no escopo das variáveis
do script. As chaves desta matriz são os nomes das variáveis globais.
$_SERVER Estas variáveis são definidas pelo servidor web, caso contrário são
relacionadas ao ambiente de execução do script atual.
$_GET Variáveis disponíveis no script, oriundas de HTTP GET.
$_POST Variáveis disponíveis no script, oriundas de HTTP POST.
$_COOKIE Variáveis disponíveis no script, oriundas de HTTP cookies.
$_FILES Variáveis disponíveis no script, oriundas do envio de arquivos via HTTP.
$_ENV Variáveis disponíveis no script através do ambiente de execução do script.
$_REQUEST Através desta variável, tem-se acesso ao conteúdo das variáveis $_GET,
$_POST e $_COOKIE.
$_SESSION Variáveis registradas na sessão do script atual.
Capítulo 3 A solução: PHP - 39

3.7.3. Constantes

Ao contrário das variáveis, por vezes é interessante definir valores fixos para
todo script, mas também fazendo referência a eles. Estas são as constantes. Por
exemplo, se nosso script faz diversos cálculos usando o número PI, podemos defini-lo
e usá-lo da seguinte forma, utilizando a função define:

52 //Definindo
53 define('PI', 3.1415);
54 //Usando
55 $circunferencia = 2 * PI * $raio;

O padrão é que os nomes de constantes sejam em maiúsculas. Ao contrário


das variáveis, elas não levam o cifrão (%) na frente de seu nome.

3.7.4. Constantes pré-definidas

O PHP possui algumas constantes pré-definidas, indicando a versão do PHP, o


Sistema Operacional do servidor, o arquivo em execução, e diversas outras
informações. Para ter acesso a todas as constantes pré-definidas, podemos utilizar a
função phpinfo(), que exibe uma tabela contendo todas essas constantes pré-
definidas.

3.8. Operadores

Os operadores têm grande utilidade no desenvolvimento. Com eles podemos


comparar e efetuar cálculos entre variáveis, dentre outras atividades.
Capítulo 3 A solução: PHP - 40

3.8.1. Aritméticos

Os operadores aritméticos são símbolos utilizados para efetuarmos cálculos


matemáticos.

Só podem ser utilizados quando os operandos são números (integer ou float).


Se forem de outro tipo, terão seus valores convertidos antes da realização da
operação. Além dos operadores básicos listados a seguir, existem várias funções para
cálculos e operações específicos.

Tabela 4:Operadores aritméticos

Operador Significado
+ Adição
- Subtração
* Multiplicação
/ Divisão
% Módulo

3.8.2. Operador de strings

Só há um operador exclusivo para strings:

Tabela 5: Operador de string

Operador Significado
. Concatenação
Capítulo 3 A solução: PHP - 41

3.8.3. Operador de atribuição

Existe um operador básico de atribuição e diversos derivados. Sempre


retornam o valor atribuído. No caso dos operadores derivados de atribuição, a
operação é feita entre os dois operandos, sendo atribuído o resultado para o
primeiro. A atribuição é sempre por valor, e não por referência.

Tabela 6: Operadores de Atribuição

Operador Significado
= Atribuição simples
+= Atribuição com adição
-= Atribuição com subtração
*= Atribuição com multiplicação
/= Atribuição com divisão
%= Atribuição com módulo
.= Atribuição com
concatenação

Exemplo:

56 <?php
57 $a = 7;
58 $a += 2;// $a passa a conter o valor 9
59 $a -= 1;// $a passa a conter o valor 8
60 $a /= 4;// $a passa a conter o valor 2
61 ?>

3.8.4. Operadores bit a bit

Comparam dois números bit a bit. São utilizados em situações muito


específicas na programação :

Tabela 7: Operadores Bit a Bit

Operador Significado
& E lógico
Capítulo 3 A solução: PHP - 42

| OU lógico
^ OU exclusivo
~ NÃO (inversão)
>> LEFT shift
<< RIGHT shift

3.8.5. Operadores lógicos

Utilizados para inteiros representando valores booleanos . Seu uso mais


comum é em condições de estruturas de controle (Veja Estruturas de controle ).

Tabela 8:Operadores lógicos

Operador Significado
and E lógico
or OU lógico
xor OU exclusivo
! NÃO (inversão)
&& E lógico
|| OU lógico

Existem dois operadores para "e" e para "ou", pois eles têm diferentes
posições na ordem de precedência.

3.8.6. Operadores de comparação

As comparações são feitas entre os valores contidos nas variáveis, e não as


referências.

Sempre retornam um valor booleano ("true" ou "false").

Tabela 9: Operadores de comparação

Operador Significado
== Igual a
!= Diferente de
< Menor que
> Maior que
<= Menor ou igual a
Capítulo 3 A solução: PHP - 43

>= Maior ou igual a


=== Igual em valor e tipo
!== Diferente em valor e/ou
tipo

3.8.7. Operadores de incremento e


decremento

Tabela 10:Operadores de incremento/decremento

Operador Significado
++ Incrementa de 1
-- Decrementa de 1

Podemos utilizá-los de duas formas: antes ou depois da variável. Quando


utilizado antes, retorna o valor da variável já incrementado ou decrementado.
Quando utilizado depois, retorna o valor da variável antes de incrementá-la ou
decrementá-la.

Exemplos:

62 <?php
63 $a = $b = 10; // $a e $b recebem o valor 10
64 $c = $a++; // $c recebe 10 e $a passa a ter 11
65 $d = ++$b; // $d recebe 11, valor de $b já incrementado
66 ?>

3.8.8. Ordem de precedência dos operadores

A tabela a seguir mostra a ordem de precedência dos operadores no momento


de avaliar as expressões. Ela está ordenada dos ítens de menor precedência para o
de maior precedência, isto é os últimos operadores são avaliados primeiros:

Tabela 11:Ordem de precedência dos operadores

Precedência Associatividade Operadores


1 Esquerda ,
2 Esquerda or
Capítulo 3 A solução: PHP - 44

3 Esquerda xor
4 Esquerda and
5 Direita print
6 Esquerda = += -= *= /= .= %= & = != ~ = < <= >
>=
7 Esquerda ?:
8 Esquerda ||
9 Esquerda &&
10 Esquerda|
11 Esquerda ^
12 Esquerda &
13 Não associa == !=
14 Não associa < >
15 Esquerda << >>
16 Esquerda +-.
17 Esquerda */%
18 Direita ! ~ ++ -- (int) (double) (string) (array)
(object) @
19 Direita [
20 Não associa new
21 Não associa ()

3.9. Exercícios Teóricos

1. Cite um tipo de variável inválida?

________________________________________________________________________________
________________________________________________________________________________

2. Qual a saída da operação: 4%2 ?

________________________________________________________________________________
________________________________________________________________________________

3. Qual a saída da operação: ((4*4)-4.2.1) ?

________________________________________________________________________________
________________________________________________________________________________
Capítulo 3 A solução: PHP - 45

4. Se dissermos que DELTA equivale a ((4*4)-4.2.1) e que x' é: (-4+(√∆))/2.4


A saída será:

________________________________________________________________________________
________________________________________________________________________________

5. Qual a solução acima em sintaxe PHP?

________________________________________________________________________________
________________________________________________________________________________
________________________________________________________________________________
________________________________________________________________________________
________________________________________________________________________________
________________________________________________________________________________
Capítulo 4 Integrando o PHP ao HTML - 46

Capítulo 4

Integrando o PHP ao HTML

4.1. Objetivos

• Fazer a integração do HTML no PHP para exibir os dados de forma amigável ao


usuário.
Capítulo 4 Integrando o PHP ao HTML - 47

Existem três técnicas básicas de integrar o PHP ao HTML:

• Incluir código PHP no meio do código HTML;

• Dar saída a código HTML através de comandos do PHP (echo, print, printf,
etc.);

• Armazenar o conteúdo a ser exibido numa variável e então dar saída a código
HTML através de comandos do PHP (echo, print, printf, etc.);

4.2. Primeira forma:

67 <html>
68 <head>
69 <title>
70 Borracharia do Tux
71 </title>
72 </head>
73 <body>
74 <h1>Borracharia do Tux</h1>
75

76 <?php
77 echo '<h2 align="center">Pedido finalizado em ';
78 echo date('H:i, jS F');
79 echo '</h2>';
80 ?>
81

82 </body>
83 </html>

Perceba que utilizando as tags básicas do PHP (no exemplo <?php ?>)
inserimos uma sequência de comandos PHP, que tiveram “saída” através do comendo
echo.
Capítulo 4 Integrando o PHP ao HTML - 48

4.3. Segunda Forma:

84 <?php
85 echo '
86 <html>
87 <head>
88 <title>
89 Borracharia do Tux
90 </title>
91 </head>
92 <body>
93 <h1>Borracharia do Tux</h1>
94 <h2 align="center">Pedido finalizado em ' .
95 date('H:i, jS F') . '</h2>
96 </body>
97 </html>';
98 ?>

Neste outro exemplo, o arquivo é iniciado com a TAG <?php e seguido do


comando echo, que vai concatenar tanto uma string contendo trecho de código
HTML quanto saída de comandos do próprio PHP (date);

4.3.1. Terceira forma:

99 <?php
100 $conteudo = '
101 <html>
102 <head>
103 <title>
104 Borracharia do Tux
105 </title>
106 </head>
107 <body>
Capítulo 4 Integrando o PHP ao HTML - 49

108 <h1>Borracharia do Tux</h1>


109 <h2 align="center">Pedido finalizado em ';
110 $conteudo .= date('H:i, jS F') . '</h2>
111 </body>
112 </html>';
113 echo $conteudo;
114 ?>

Agora o conteúdo é acumulado (concatenado) na variável $conteudo, que é


“echoada” ao final do script.

4.4. Laboratório

1. Criar um formulário de cadastro de Produtos.

2. Criar um formulário de cadastro de Login.

3. Criar um carrinho de compras.


Capítulo 5 Estruturas de controle - 50

Capítulo 5

Estruturas de controle

5.1. Objetivos

• Saber fazer a escolha da estrutura de controle correta para tomada de


decisões.

• Implementar a sintaxe das tomadas de decisões em algorítmo.

5.2. Introdução teórica

As estruturas de controle são elementos básicos nas linguagens de


programação, onde o fluxo do programa pode ser alterado. Basicamente são
divididos em Condicionais e Laços de Repetição ou Loops
Capítulo 5 Estruturas de controle - 51

5.3. Condição: if/else

O principal comando para controle de fluxo é o if/else. Sua sintaxe é mostrada


abaixo:

if (condição)
comando; // Executado se a condição for true, apenas um comando

if (condição){
comandos // Executado se a condição for true
}

// O uso do else é opcional:


if (condição){
comandos // Executado se a condição for true
}
else{
comandos // Executado se a condição for false
}

// Também pode ser usada uma sintaxe reduzida para atribuição


$sexoExtenso = ($sexo == 'M') ? 'Masculino' : 'Feminino';

A condição é uma expressão lógica que retorna true ou false.


Capítulo 5 Estruturas de controle - 52

Vamos exercitar esse comando, incrementando nosso código:

115 if( $total == 0) {


116 echo 'Você não selecionou nenhum item!<br />';
117 }
118 else {
119 echo 'Itens comprados: <br />';
120 if ( $_POST['nrodas'] > 0 )
121 echo $_POST['nrodas'] . ' rodas.<br />';
122 if ( $_POST['npneu'] > 0 )
123 echo $_POST['npneu'] . ' pneus.<br />';
124 if ( $_POST['nparafusos'] > 0 )
125 echo $_POST['nparafusos'] . ' parafusos.<br />';
126 }

5.4. Condição elseif e switch/case

Temos ainda que avaliar a combobox que indica a forma pela qual o usuário
conheceu a Borracharia do Tux.

Mas neste caso, temos várias opções, e não apenas um verdadeiro ou falso.
Nesse caso, podemos utilizar os comandos elseif e switch/case. Um mesmo exemplo é
mostrado abaixo com cada uma das formas:

127 // Exemplo de uso do elseif


128 if ($dia=="Sábado"){
129 echo "Fico em casa";
130 }
131 elseif ($dia=="Domingo"){
132 echo "Vou passear";
133 }
134 else{
135 echo "É dia da semana, vou trabalhar!!!";
136 }
Capítulo 5 Estruturas de controle - 53

137

138 // Exemplo de uso do switch/case


139 switch($dia){
140 case "Sábado":
141 echo "Fico em casa";
142 break;
143 case "Domingo":
144 echo "Vou passear";
145 break;
146 default:
147 echo "É dia da semana, vai trabalhar!!!";
148 }

No switch é importante o uso do break é importante, pois senão o código


será executado até o final do bloco switch. Em algumas circunstâncias isto
pode ser o desejado. O case especial default, apesar de não obrigatório, é
desejável, pois determina um bloco padrão a ser executado caso nenhum
case anterior seja satisfeito.
Capítulo 5 Estruturas de controle - 54

5.4.1. Adicionando ao script

Qualquer umas das formas de teste e validação podem ser usados no script
processar.php.

149 echo '<p>Você conheceu a Borracharia do Tux ';


150 // Para facilitar, criaremos uma variável de nome $find
151 $find = $_POST['find'];
152 // Opção usando o elseif
153 if($find == 'a')
154 echo 'na 4Linux</p>';
155 elseif($find == 'b')
156 echo 'por anúncio na TV</p>';
157 elseif($find == 'c')
158 echo 'através da internet.</p>';
159 elseif($find == 'd')
160 echo 'por indicação.</p>';
161 else
162 echo 'não sabemos como!</p>';
163

164 // Opção usando o switch


165 switch($find){
166 case 'a':
167 echo 'na 4Linux.</p>'; break;
168 case 'b':
169 echo 'por anúncio na TV.</p>'; break;
170 case 'c':
171 echo 'através da internet.</p>'; break;
172 case 'd':
173 echo 'por indicação.</p>'; break;
174 default:
175 echo 'não sabemos como!</p>'; break;
176 }
Capítulo 5 Estruturas de controle - 55

5.5. Laços de Repetição ou Loops

Diversas vezes temos de repetir o mesmo código. Por exemplo, listar uma lista
que tenha 4 ítens, não é difícil escrever utilizando 4 linhas com o comando "echo".
Agora imaginamos a dor de cabeça que seria imprimir uma lista de compras com 100
ítens! Nestes casos, utiliza-se o while ou o for.

Estes dois ciclos são muito similares, visto que se pode sempre converter um
ciclo em outro, e vice-versa. A decisão de utilizar um ou outro, é pessoal e tem a ver
com a simplicidade de interpretação. Existem situações onde um while aplica-se com
mais facilidade e em outras o for. O while é bastante utilizado para passar pelos
registro de uma consulta ao banco de dados.

A sintaxe do while é mostrada abaixo:

177 while(condição){
178 //bloco de código
179 }

O bloco de código é repetido até que a condição se torne falsa. Note que é
importante que dentro do ciclo a condição seja alterada em algum momento para
falsa, pois do contrário o programa travará neste loop.

O comando for é exemplificado abaixo:

180 for ($i=1; $i < 6; $i++){


181 //bloco de código a executar
182 echo '<p>Iteração número: ' . $i . '</p>';
183 }

A saída desde loop será:

Iteração número: 1
Iteração número: 2
Iteração número: 3
Iteração número: 4
Iteração número: 5
Capítulo 5 Estruturas de controle - 56

5.5.1. Interrompendo uma estrutura de


controle

Se for necessário interromper um loop, pode-se utilizar a instrução break.


Esse comando faz com que o script continue a partir da próxima após o loop. O
comando continue faz com que o loop vá direto para a próxima iteração, sem
executar as demais instruções daquele loop. Por fim, o comando exit interrompe a
execução do script PHP.

5.6. Laboratório

Criar uma estrutura de controle que valida quando apresentar o login e o


logout da aplicação, assim como escrever o nome do visitante ou do usuário na tela.
Capítulo 6 Funções - 57

Capítulo 6

Funções

6.1. Objetivo

• Enteder a funcionalidade das funções e usar os escopos de variáveis.

6.2. Introdução teórica

Funções são blocos de código reutilizável. Elas podem ou não solicitar


parâmetros, e podem ou não retornar valores.

Sua sintaxe básica é:

184 <?php
185 function fazerAlgo ($arg_1, $arg_2, /* ..., */ $arg_n)
186 {
187 echo "Exemplo de função.\n";
188 return $valor_retornado;
189 }
190 ?>
Capítulo 6 Funções - 58

A função pode não solicitar argumentos, apenas realizar algum


processamento:

191 <?php
192 function mostrarTitulo ()
193 {
194 echo "<h1>Capítulo 1</h1>";
195 }
196

197 // Utilizando a função


198 mostrarTitulo();
199 ?>

Entretanto, a função pode também solicitar parâmetros e utilizá-los em algum


processamento:

200 <?php
201 function mostrarTitulo ($numero)
202 {
203 echo "<h1>Capítulo $numero";
204 }
205 // Utilizando a função
206 mostrarTitulo("1");
207 ?>

Mesmo tendo parâmetros, eles podem não ser obrigatórios se tiverem um


valor padrão estabelecido na função:

208 <?php
209 function mostrarTitulo ($numero='1')
210 {
211 echo "<h1>Capítulo $numero</h1>";
212 }
213

214 // Agora a função funciona tanto assim:


215 mostrarTitulo("3");
216

217 // quanto assim, mas então a variável $numero tera valor = 1


Capítulo 6 Funções - 59

218 mostrarTitulo();
219

220 ?>

Uma função pode retornar valores utilizando-se a palavra chave return.

221 <?php
222 function mostrarTitulo ($numero='1')
223 {
224 return "<h1>Capítulo $numero</h1>";
225 }
226

227 // Utilizando a função


228 echo mostrarTitulo("1");
229 ?>

Qualquer comando que houver depois de um return será ignorado, pois ele
encerra a função.

6.3. Laboratório

Criar uma função para o cabeçalho do site, uma para o menu e outra para o
rodapé.

6.4. Escopo das Variáveis

A regra básica é a seguinte:

• Variáveis definidas dentro da função só são visíveis dentro da função


• Variáveis definidas fora da função não estão disponíveis para a função
• Variáveis SuperGlobais do PHP estão disponíveis em qualquer lugar

Para acessar uma variável externa dentro da função, utiliza-se uma das duas
sintaxes abaixo:
Capítulo 6 Funções - 60

230 <?php
231 $nome = 'Maria';
232 $sobrenome = 'da Silva';
233 $idade = 25;
234 $dataNascimento = '01/01/1984';
235

236 function exibirPessoa ()


237 {
238 // definindo variáveis globais disponíveis para função
239 global $nome, $sobrenome;
240

241 // Isto funciona


242 echo "<p>Nome da pessoa: $nome $sobrenome</p>";
243

244 // Isto não funciona, variável não disponível


245 echo "<p>Idade: $idade</p>";
246

247 // Isto funciona, utilizando variável $GLOBALS


248 echo "<p>Data de Nascimento: " . $GLOBALS['dataNascimento'] .
"</p>";
249 }
250

251 // Utilizando a função


252 exibirPessoa();
253 ?>

O modificador static força o script a manter o valor da variável entre


execuções do script:

254 function contador(){


255 static $x = 0;
256 return $x++;
257 }
258 echo contador();echo contador();echo contador();
259 // A saída será: 012
// Lembrando que o return acontecerá antes da incrementação da variável
Capítulo 6 Funções - 61

O modificador static é muito utilizado em funções recursivas, já que o


valor de algumas variáveis precisa ser mantido. Ele funciona da seguinte
forma: o valor das variáveis declaradas como estáticas é mantido ao
terminar a execução da função. Na próxima execução da função, ao
encontrar novamente a declaração com static, o valor da variável é
recuperado.

Em outras palavras, uma variável declarada como static tem o mesmo


"tempo de vida" que uma variável global, porém sua visibilidade é restrita ao escopo
local em que foi declarada e só é recuperada após a declaração.

Outro exemplo:

260 <?php
261 function Teste()
262 {
263 echo "$a";
264 static $a = 0;
265 $a++;
266 }
267 ?>

O exemplo acima não produzirá saída alguma. Na primeira execução da


função, a impressão ocorre antes da atribuição de um valor à função, e
portanto o conteúdo de $a é nulo (string vazia). Nas execuções seguintes da
função Teste() a impressão ocorre antes da recuperação do valor de $a, e
portanto nesse momento seu valor ainda é nulo. Para que a função retorne
algum valor o modificador static deve ser utilizado antes da impressão.
Capítulo 6 Funções - 62

Capítulo 7

Formulários, GET e POST

7.1. Objetivos

• Compreender as diferenças entre os métodos GET e POST .

• Aprender a passar váriaveis de um script para outro.


Capítulo 7 Formulários, GET e POST - 63

7.2. Passando variáveis entre scripts

Os scripts PHP são autônomos. Para que recebam interações do usuário


através dos navegadores é preciso utilizar-se dos métodos GET e POST disponíveis
nos servidores Web.

Os dois métodos podem enviar praticamente o mesmo tipo de informação,


entretanto enquanto o GET utiliza-se da URL para enviar as informações, o POST
utiliza o cabeçalho da requisição (ou seja, envia de forma “oculta”). Pela diferença de
meio, o GET possui limitações de tamanho da informação (que variam por navegador,
podendo ser afetados inclusive por proxies) enquanto o POST possui suporte para
largas informações, ainda que este limite varie e possa ser configurado em alguns
servidores Web.

7.2.1. Os métodos GET e POST

O GET é um método do HTTP destinado a enviar dados do cliente para o


servidor. É acionado por meio de um formulário HTML através da diretiva
method="get" incluída na tag <form>.

Quando um formulário HTML utiliza o método GET, o fluxo de dados é


separado do endereço URL através de um ponto de interrogação (?). Esta forma de
endereçamento e separação pode ser observada no campo de endereços do
navegador do usuário. Logo após o formulário ter sido enviado, podemos ver algo
como:

http://www.meusite.com/meuscript.php?campo1=valor1&campo2=valor2

De outro modo, é possível enviar uma informação via método GET sem a
necessidade de formulário, apenas digitando uma URL diretamente na barra de
endereço do navegador.
Capítulo 7 Formulários, GET e POST - 64

O POST é outro método do HTTP similar ao GET, porém é acionado por


meio da diretiva method="post" incluída na tag <form>.
Este método faz com que os dados do formulário sejam transmitidos
“ocultos” no cabeçalho (header) da requisição e não apareçam na URL.

Ao escrevermos nossos scripts, devemos sempre lembrar qual método


estamos usando afim de determinarmos se iremos ler os dados do vetor $_POST ou
$_GET.

Sempre que possível, deve-se utilizar o método POST, pois através do


método GET os dados enviados ficam mais expostos através da URL no
navegador, o que representa uma falha de segurança. Entretando, isto é
apenas uma diretriz - a não ser que haja criptografia, os dados de um POST
podem ser capturados no caminho. A segurança é um conjunto de
procedimentos em que esta prática é incluída.

Para recuperar os dados enviados, utilizamos as variáveis superglobais $_GET,


$_POST e opcionalmente $_REQUEST (que recupera ambos valores, além do contido na
variável superglobal $_COOKIES).

Numa requisição feita como segue:

http://www.meusite.com/meuscript.php?
nome=Joao&idade=29&fone[com]=3333.4444&fone[res]=9999.888

É possível recuperar os valores enviados para o script meuscript.php das


seguintes formas:

268 $nome = $_GET['nome'];


269 $idade = $_GET['idade'];
Capítulo 7 Formulários, GET e POST - 65

270 $foneComercial = $_GET['fone']['com'];


271 $foneComercial = $_GET['fone']['res'];
272 // ou
273 $nome = $_REQUEST['nome'];
274 $idade = $_REQUEST['idade'];
275 $foneComercial = $_REQUEST['fone']['com'];
276 $foneComercial = $_REQUEST['fone']['res'];

Já um envio realizado pelo formulário abaixo:

277 <form method='post' action='meuscript.php'>


278 Nome: <input type='text' name='nome' /><br/>
279 Idade: <input type='text' name='idade' /><br/>
280 Fone Comercial: <input type='text' name='fone[com]' /><br/>
281 Fone Residencial: <input type='text' name='fone[res]' /><br/>
282 <button type='submit'>Enviar</button>
283 </form>

É possível recuperar os valores enviados para o script meuscript.php das


seguintes formas:

284 $nome = $_POST['nome'];


285 $idade = $_POST['idade'];
286 $foneComercial = $_POST['fone']['com'];
287 $foneComercial = $_POST['fone']['res'];
288 // ou
289 $nome = $_REQUEST['nome'];
290 $idade = $_REQUEST['idade'];
291 $foneComercial = $_REQUEST['fone']['com'];
292 $foneComercial = $_REQUEST['fone']['res'];

A variável superglobal $_REQUEST é útil mas deve ser utilizada com


cuidado. Por não preocupar-se com a origem da informação, pode ser
Capítulo 7 Formulários, GET e POST - 66

facilmente alvo de ataque. Portanto, deve ser utilizada como última opção –
o ideal é usar ou $_GET ou $_POST.

7.3. Laboratório

Criar paginas que recebem os parâmetros dos formulários de Cadastro de


Produtos e Usuários.

7.4. Criando Links

O método GET é a escolha automática quando monta-se links. Uma atividade


de programação muito comum para linguagens Web é a montagem de links
dinamicamente, com passagem de parâmetros (variáveis).

Uma forma simples é simplesmente concatenar os valores para montar o


resultado final:

293 $nome = 'joao';


294 $url = '/meuscript.php?nome=' . $nome;
295 echo '<a href="' . $url . '">Editar Nome</a>

Isto gera:

<a href="/meuscript.php?nome=joao">Editar Nome</a>

Entretanto, existem caracteres que não podem ser colocados literalmente na


URL (como espaço), então utiliza-se uma função do PHP para realizar isto, que é o
urlencode.

296 $nome = 'joao da silva';


297 $url = '/meuscript.php?nome=' . $nome;
298 echo '<a href="' . $url . '">Editar Nome</a>';
Capítulo 7 Formulários, GET e POST - 67

Isto gera:

<a href="/meuscript.php?nome=joao%20da%20silva">Editar Nome</a>

Apesar do uso deste comando, não é preciso utilizar a função urldecode ao


receber a variável através da variável superglobal $_GET; isto é feito
automaticamente.
Capítulo 8 Arrays e Strings - 68

Capítulo 8

Arrays e Strings

8.1. Objetivos

• Compreender o uso de arrays e strings

• Verificar as funções para trabalhar com Strings

8.2. Arrays

Um array no PHP é atualmente um mapa ordenado. Um mapa é um tipo que


relaciona chaves para valores. Este tipo é otimizado de várias maneiras,
então você pode usá-lo como um array real, ou uma lista (vetor), hashtable
(que é uma implementação de mapa), dicionário, coleção, pilha, fila e
provavelmente mais. Como você pode ter outro array PHP como um valor,
você pode facilmente simular árvores.
A explicação dessas estruturas estão além do escopo desse manual, mas
você pode encontrar exemplos para cada uma dessas estruturas a seguir.
Para mais informações sobre estruturas, refira-se a literatura externa sobre
esses tópicos.
Capítulo 8 Arrays e Strings - 69

Exemplo de array:

299 $array = array(“iPod”,”iMac”);

Ainda com arrays, posso associá-los a uma lista, fazendo com que variáveis
assumam determinados valores correspondentes aos índices do array.

300 $list(“nome”,”idade”,”sexo”) = array(“joao”,”40”,”M”);

Podemos ainda através de um laço recuperar valores de um array de forma


dinâmica e interativa. Com isso usamos o foreach para facilitar nossas vidas.

301 foreach($array as $valor){


302 echo $valor.”<br />”;
303 }

8.3. Strings

8.4. Strings vão muito além doque apenas caracteres que representam
texto. Com strings podemos trabalhar com arrays, validação de campos,
formatação de texto e até mesmo criar uma classe de template.
Vamos ver nesse capitulo algumas funções interessantes para se trabalhar
com Strings.

8.4.1. str_replace()

A função str_replace() nos permite alterar ocorrências de uma string por


qualquer outra informação que quisermos, com isso, podemos fazer com que o PHP
sempre que encontrar uma ocorrência do tipo %nome% seja substituído por “João”.
Capítulo 8 Arrays e Strings - 70

304 str_replace(“%nome%”,”João”,”<b>Olá %nome%</b>”)

8.4.2. strip_tags()

Com a função strip_tags() permitimos ao PHP que bloqueie tags HTML de uma
determinada string, mantendo assim uma certa “segurança” ao código gerado.
Isso é valido por exemplo em um sistema de comentários, ao qual eu permito que o
usuário faça uso de tags do tipo “<p>”, “<b>” e “<i>”.

305 strip_tags(“<a href='ola.php'><b><i>Ola


mundo</i></b></a>”,”<b>”)

8.4.3. stristr()

Com stristr() conseguimos fazer buscas de determinadas “palavras” e uma


string, tendo como retorno uma informação booleana.

306 $string='hello world';


if(stristr($string,'earth')===FALSE){
echo “Não encontramos a palavra earth”;
}
Capítulo 8 Arrays e Strings - 71

8.4.4. strcmp()

Com strcmp conseguimos comparar duas strings, tendo retorno booleano.


Vale ressaltar que essa função é case sensitive, caso queira ignorar maiúsculas e
minúsculas faça uso da função strcasecmp().

307 if(strcmp(“a”,”A”)==0){
308 echo “As strings são iguais”;
309 }

8.4.5. Explode e Implode

Exatamente como o nome diz, essas funções explodem e implodem strings e


arrays.

A primeira, tem por sua vez, a função de explodir uma string dividindo-a em
array.
Com isso conseguimos por exemplo validar um e-mail.

310 $email=”kinn.coelho@4linux.com.br”;
311 $verificacaoEmail = explode(“@”,$email);
312 $verificacaoDominio = explode(“.”$verificacaoEmail[0]);
313 if(verificacaoEmail[0] != “” AND verificacaoDominio[1] !=””)
314 echo “E-mail válido”;

O Implode por sua vez, nos permite transformar um array em uma string.

315 $pessoa['nome'] = ”Kinn”;


316 $pessoa['sobrenome'] = ”Coelho”;
317 $nomeCompleto = implode(“ ”,$pessoa);
318 echo $nomeCompleto.”<br />”;
319 if(is_string($nomeCompleto)){
320 echo “É uma string”;
321 }
Capítulo 8 Arrays e Strings - 72

8.5. Laboratório

Fazendo uso das funções de Strings, vamos criar nossa engine de template.

Iremos fazer uso do método chamado substituição de parâmetros.

322 $pagina = file_get_contents(“templates/”.$_GET['pag'].”.php”);


323 $corpo = str_replace(array(“%nome%”,”%sobreNome
%”),array(“João”,”Silva”));
324 echo $corpo;
Capítulo 8 Arrays e Strings - 73

Capítulo 9

Header, Cookies, Sessões

9.1. Objetivos

• Apreder porque e como fazer uso de sessão para armazenar valores.

• Trabalhar com sessão e ver suas funções.


Capítulo 9 Header, Cookies, Sessões - 74

9.2. Introdução teórica

Cada execução de um script em PHP é isolada. Portanto, informações


utilizadas por um script que já encerrou não estão disponíveis para outro script.

Para administrar esta situação existem duas maneiras: ou guardar


informações no cliente (COOKIE) ou no servidor (SESSION). Informações no cliente
são vulneráveis e devem ser utilizadas com parcialidade, e para informações não
vitais.

Já a SESSION armazena no servidor, por padrão em arquivo, valores que o


programador definir. Este arquivo tem um tempo de vida: a partir do último acesso é
contado um tempo, e o próprio Apache trata de realizar a "limpeza" (garbage
collection)de arquivos antigos.

Este tempo de vida é determinado no arquivo de configuração do PHP


localizado em:

/etc/php5/apache2/php.ini

session.gc_maxlifetime = 1440
;(1440 seconds = 24 minutes)

9.2.1. Como utilizar sessões

As sessões são iniciadas com a função:

325 session_start();

Esta função inicia uma sessão entre o servidor e o navegador (e não o


computador!!) e armazena em arquivo (padrão do PHP, pode ser alterado para banco
de dados). Se a seção já existe, ele a carrega.

A partir deste momento, é possível armazenar valores na sessão utilizando o


array SuperGlobal $_SESSION:
Capítulo 9 Header, Cookies, Sessões - 75

326 session_start();
327 $_SESSION['login'] = 'jorge';

Enquanto a sessão estiver ativa, qualquer script que a carregar pode fazer uso
desta variável.

Para eliminar uma sessão, primeiro é preciso carregá-la e em seguida


utilizamos uma função de "destruição":

328 session_start();
329 session_destroy();

Por padrão o PHP utiliza um COOKIE para armazenar o ID da sessão. Se os


COOKIES estiverem desativados no navegador do cliente, as sessões não funcionam.
A apesar de ser utilizado em poucas soluções, é possível passar o ID da sessão
através da URL.

9.3. Laboratório

Fazendo uso da session, vamos fazer com que produtos sejam adicionados em
nossa sessão e consequentemente no carrinho de compras.

Para isso, vamos assumir que nosso array produtos recebera alguns produtos
como valores, para fins de testes do nosso carrinho.

Ex:

produtos(“iPod”,”iPad”,”iMac”,”Milestone”,”Android”,”ZendStudio”)
Capítulo 10 Introdução ao Banco de dados MySQL - 76

Capítulo 10

Introdução ao Banco de dados MySQL

10.1. Objetivos

• Levantar um SGDB MySQL em ambiente Linux funcional com o PHP.

• Estar apto a criar um database e efetuar query SQL.

• Administrar o database via terminal e interface web.


Capítulo 10 Introdução ao Banco de dados MySQL - 77

10.2. Introdução teórica

Um banco de dados é uma coleção de dados estruturados. Ele pode ser


qualquer coisa desde uma simples lista de compras a uma galeria de imagens ou a
grande quantidade de informação da sua rede corporativa. Para adicionar, acessar, e
processar dados armazenados em um banco de dados, é necessário um sistema de
gerenciamento de bancos de dados, no caso o Servidor MySQL.

O Servidor MySQL foi desenvolvido originalmente para lidar com bancos de


dados grandes de maneira muito mais rápida que trabalhar diretamente com os
arquivos. A conectividade, velocidade, e segurança fazem com que o MySQL seja
altamente adaptável para acessar bancos de dados na Internet.

10.3. Instalando o MySQL

Para instalar o MySQL, use o aptitude.

# aptitude install mysql-server-5.0

Testando o banco

A sintaxe do cliente do banco é:

# mysql -u USER -p DATABASE

Exemplo:

mysql> show databases;


mysql> quit;

A configuração padrão do MySQL é muito permissiva, permite o acesso sem


senha.
Capítulo 10 Introdução ao Banco de dados MySQL - 78

10.3.1. Melhorando a segurança do banco

Existe um utilitário criado especialmente para resolver esse problema.


Observe a mensagem explícita que ele apresenta logo no início! Leia atentamente as
perguntas, e observe as falhas de segurança existentes antes deste procedimento.

# mysql_secure_installation

NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR


ALL MySQL
SERVERS IN PRODUCTION USE! PLEASE READ EACH STEP CAREFULLY!
In order to log into MySQL to secure it, we'll need the current
password for the root user. If you've just installed MySQL, and
you haven't set the root password yet, the password will be blank,
so you should just press enter here.
(SOLICITA SENHA ATUAL DO root, PRESSIONE ENTER)
Enter current password for root (enter for none):
OK, successfully used password, moving on...
Setting the root password ensures that nobody can log into the MySQL
root user without the proper authorisation.
(DEFINIR SENHA DO root? Y)
Set root password? [Y/n] Y
(NOVA SENHA)
New password:
(REPETIR NOVA SENHA)
Re-enter new password:
Password updated successfully!
Reloading privilege tables..
... Success!
By default, a MySQL installation has an anonymous user, allowing anyone
to log into MySQL without having to have a user account created for
them. This is intended only for testing, and to make the installation
go a bit smoother. You should remove them before moving into a
Capítulo 10 Introdução ao Banco de dados MySQL - 79

production environment.
(REMOVER USUÁRIOS ANÔNIMOS? Y)
Remove anonymous users? [Y/n] Y
... Success!
Normally, root should only be allowed to connect from 'localhost'. This
ensures that someone cannot guess at the root password from the network.
(DESABILITAR ACESSO REMOTO DO root? Y)
Disallow root login remotely? [Y/n] Y
... Success!
By default, MySQL comes with a database named 'test' that anyone can
access. This is also intended only for testing, and should be removed
before moving into a production environment.
(REMOVER BANCO DE DADOS test E ACESSO A ELE? Y)
Remove test database and access to it? [Y/n] Y
- Dropping test database...
ERROR 1008 (HY000) at line 1: Can't drop database 'test'; database doesn't
exist
... Failed! Not critical, keep moving...
- Removing privileges on test database...
... Success!
Reloading the privilege tables will ensure that all changes made so far
will take effect immediately.
(REINICIAR PRIVILÉGIOS? Y)
Reload privilege tables now? [Y/n] Y
... Success!
Cleaning up...
All done! If you've completed all of the above steps, your MySQL
installation should now be secure.
Thanks for using MySQL!
Capítulo 10 Introdução ao Banco de dados MySQL - 80

10.4. Instalando o suporte ao MySQL no PHP 5.

Utilizaremos novamente o aptitude.

aptitude install php5-mysql

Para que o suporte seja ativado, reinicie o Apache:

/etc/init.d/apache2 restart

10.4.1. Instalando uma interface web para


gerenciamento do MySQL

aptitude install phpmyadmin

10.5. Conceitos básicos de Banco de Dados

10.5.1. Tabelas

Todos os dados de um banco de dados relacional (BDR) são armazenados em


tabelas. Uma tabela é uma simples estrutura de linhas e colunas. Cada linha contém
um mesmo conjunto de colunas mas as linhas não seguem qualquer tipo de ordem.
Em um banco/base de dados podem existir uma ou centenas de tabelas. O limitador é
imposto exclusivamente pela ferramenta de software utilizada.

Tabela 12: Tabela Clientes

# CPF Nome1
1 152.487.265-42 João da Silva
2 687.481.682-88 Maria Joaquina
3 001.645.852.12 Agnaldo Souza
Capítulo 10 Introdução ao Banco de dados MySQL - 81

10.5.2. Registros (ou tupla)

Cada linha, formada por uma lista ordenada de colunas, representa um


registro (ou tupla). Os registros não precisam necessariamente conter dados em
todas as colunas, os seus valores podem ser nulos.

Formalmente falando, uma tupla é uma lista ordenada de valores, onde cada
valor é do domínio especificado pelo atributo definido no esquema de relação.

10.5.3. Colunas (Atributos ou Campos)

As colunas de uma tabela, são também chamadas de Atributos ou Campos.


Cada atributo/campo pertence a um domínio (tipo de campo), que define os valores
que podem ser associados aquele atributo.

10.5.4. Domínio (Tipos de Dados)

Os Dominios possuem características que definem os possíveis valores que


serão armazenado em um atributo de uma tupla. Por exemplo. Em um campo do tipo
numérico, serão somente armazenados números. Os sistemas de banco de dados
possuem regras para consistir os dados que são armazenados.

10.5.5. Chave

As tabelas relacionam-se umas as outras através de chaves. Uma chave é um


conjunto de um ou mais campos que determinam a unicidade de cada registro.

Por exemplo, se um banco (base) de dados tem como chave Código do Produto
+ ID Sistema, sempre que acontecer uma inserção de dados, o sistema de
gerenciamento de banco (base) de dados irá fazer uma consulta para identificar se o
Capítulo 10 Introdução ao Banco de dados MySQL - 82

registro não se encontra gravado na tabela. Caso exista um novo registro não será
criado, sendo que apenas a alteração do registro existente será possível. A unicidade
dos registros, determinada por sua chave, também é fundamental para a criação dos
índices.

Temos dois tipos de chaves:

• Chave Primária: (PK - Primary Key) é a chave que identifica cada registro
dando-lhe unicidade. A chave primária nunca se repetirá. A maioria dos
bancos também exige que ela seja NÃO NULA (NOT NULL) além de única.
• Chave Estrangeira: (FK - Foreign Key) é uma chave formada pela chave
primária de outra tabela e a chave de um campo da tabela que recebe o
relacionamento. Define um relacionamento entre as tabelas e pode ocorrer
repetidas vezes.

Observação 1: Geralmente Chaves Primárias são de apenas um campo, mas


podem ser compostas, ou seja, vários campos fazem parte dela. Isto determina que a
combinação entre os campos é que precisa ser única, e não os campos que
isoladamente a compõe.

Observação 2: Por questão de escopo, chaves estrangeiras não serão tratadas


neste curso.

10.5.6. Índices

O limite de registro em uma tabela é imposto exclusivamente pela ferramenta


de software utilizada. Sendo assim, para a recuperação dos dados é necessário a
existência de mecanismos que facilitem a consulta, proporcionando uma perfomance
aceitável para a mesma. Para isso, os sistemas de bancos de dados relacionais criam
índices das tabelas, sendo que esses índices são atualizados constantemente.

Caso o índice se corrompa por algum motivo, é possível que pesquisas possam
retornar resultados não desejados ou que inserções de chaves duplicadas aconteçam.
Nesse caso o banco de dados será corrompido também. Os sistemas de bancos
(bases) de dados possuem mecanismos de evitar que esses eventos ocorram como
também possibilitam a recuperação dos índices e consistência da tabela caso eles
ocorram.
Capítulo 10 Introdução ao Banco de dados MySQL - 83

10.5.7. Relacionamentos

Como o próprio nome sugere, um(a) BDR possui diversos relacionamentos


entre as tabelas existentes.

Um relacionamento é feito ligando-se um campo de uma tabela X com um


campo de uma tabela Y ou tabela estrangeira. Por exemplo, se pedidos (em uma
tabela) estão relacionados a um cliente (em outra tabela), o SGBD poderá bloquear a
remoção deste cliente enquanto ele possuir pedidos registrados. (Observação: no
caso de chaves primárias compostas, a relação se dará entre todos os campos desta
chave)

Existem alguns tipos de relacionamentos possíveis:

• Um para um (1 para 1)
• Um para muitos (1 para N)
• Muitos para muitos (N para N), que não pode ser implementado diretamente
no modelo relacional e tem que ser construído com uma tabela auxiliar.

10.6. A Linguagem SQL

A Linguagem SQL possui, basicamente, três grupos de comandos: DDL, DML


e DCL.

• DDL (Data Definition Language) - Linguagem de Definição de Dados


Permite a criação e alteração de objetos do banco de dados. Apesar de
baseado na SQL padrão, geralmente existem extensões para cada SGDB
utilizado. Os comandos clássicos são:
• CREATE - cria um objeto (uma tabela, por exemplo) dentro do banco de
dados (ou o próprio)
• DROP - apaga um objeto do banco de dados
• ALTER - altera um objeto do banco de dados
• DML (Data Manipulation Language) - Linguagem de Manipulação de
Dados
Permite a alteração dos dados dentro das tabelas. Os mais comuns são:
• SELECT (SELECIONAR) - para seleção de dados em um ou mais
registros
Capítulo 10 Introdução ao Banco de dados MySQL - 84

• INSERT (INSERIR) - para inclusão um registro


• UPDATE (ATUALIZAR) - para modificação valores de um registro
• DELETE (EXCLUIR) - para exclusão de um registro
• TRUNCATE (TRUNCAR) - exclui todos registros da tabela
• DCL (Data Control Language) - Linguagem de Controle de Dados
DCL controla os aspectos de autorização de dados e licenças de usuários
para controlar quem tem acesso para ver ou manipular dados dentro do
banco de dados.
Duas palavras-chaves da DCL:
• GRANT - autoriza ao usuário executar ou setar operações
• REVOKE - remove ou restringe a capacidade de um usuário de executar
operações

10.6.1. Alguns padrões de sintaxe para o SQL


do MySQL

Os comando SQL precisam terminar em ponto-e-vírgula ( ; ). Em algumas


situações como quando executados isoladamente ou na tela de comandos SQL é
possível ignorar o ponto-e-vírgula. Porém, em scripts isto é imprescindível. Para a
criação do hábito, todos os comandos aqui apresentados terão a terminação padrão.

Strings (textos) devem estar envolvidos em aspas simples/apóstrofo (') ou


aspas duplas(").

'Isto é um texto válido'


"Caixa d'água"
'Ops... Caixa d'água com erro de sintaxe'

Comentários (texto que não será executado) no SQL é criado colocando


entre /* e */. O MySQL também permite o uso de dois hífens

/*
Isto é um comentário
*/
Capítulo 10 Introdução ao Banco de dados MySQL - 85

-- Isto também é um comentário

10.6.2. Tipos de dados mais usados no MySQL

TEXTO

• CHAR(n) - String (texto) de tamanho fixo “n”. Limite 255 caracteres. Usado
quando o texto armazenado é sempre do mesmo tamanho, como em UF, CPF,
CEP
• VARCHAR(n) - String (texto) de tamanho variável até o máximo de “n”.
Limite 65.532k. Usado quando não se sabe o tamanho exato do texto a ser
armazenado, mas apenas seu tamanho máximo, como em Nome, Endereço,
etc.
• ENUM – Objeto de texto que permite definir uma lista dos valores válidos,
armazendo um deles.
• TINYTEXT, TEXT, MEDIUMTEXT, LONGTEXT – Campos texto variáveis,
podendo conter:
- TINYTEXT: of 255 (28 – 1) caracteres
- TEXT: 65,535 (216 – 1) caracteres
- MEDIUMTEXT: 16,777,215 (224 – 1) caracteres
- LONGTEXT: 4,294,967,295 or 4GB (232 – 1) caracteres

DATA

• DATE - Data (o formato armazenado é aaaa-mm-dd, ou 2000-12-31 para 31


de dezembro de 2000)
• TIME – Hora (00:00)
• YEAR – Ano (YYYY) 2K -> 70=1970 to 69=2069
• TIMESTAMP - Data e Hora automática (YYYY-MM-DD HH:MM:SS)
• DATETIME - Data e Hora Simultaneamente (YYYY-MM-DD HH:MM:SS )

NÚMEROS

• FLOAT(n,d) ou DOUBLE(n,d) - números com precisão decimal (n – total de


dígitos, d - casas decimais)
• DECIMAL(n,d) ou NUMERIC(n,d) – números com casas decimais
especificadas (n – total de dígitos, d - casas decimais)
• INTEGER - Dados numéricos inteiros. Possui subtipos conforme tamanho de
Capítulo 10 Introdução ao Banco de dados MySQL - 86

valores que aceita: TINYINT, SMALLINT, MEDIUMINT, INT, BIGINT

BINÁRIOS

BLOB - Este tipo de campo é o tipo indicado para armazenar Textos Grandes
“Memos”, Fotos, Gráficos, Ícones, isto é, aparentemente não tem um tipo de dado
que não possa ser armazenado no Campo Blob. Campos Blob´s não podem ser
indexados. Um tipo especial de BLOB é o TEXT, otimizado para texto.

Os campos tipo BLOB possuem subtipos conforme tamanho de valores que


aceita:

• TINYBLOB: of 255 (28 – 1) bytes


• BLOB: 65,535 (216 – 1) bytes
• MEDIUMBLOB: 16,777,215 (224 – 1) bytes
• LONGBLOB: 4,294,967,295 or 4GB (232 – 1) bytes

10.7. Criando Bancos e Tabelas

Criando e utilizando bancos:

CREATE DATABASE cadastro;

Para utilizar o banco tem-se o comando USE:

USE cadastro;
Capítulo 10 Introdução ao Banco de dados MySQL - 87

Para facilitar, vamos criar um tabela Pessoa, a seguinte estrutura:

Figura 10.1: Tabela Pessoa

10.7.1. Criando tabelas

A sintaxe básica para criação de tabelas é:

CREATE TABLE nometabela(


nomecampo1 TIPO OPCOES,
nomecampo2 TIPO OPCOES,
nomecampo3 TIPO OPCOES,
nomecampo4 TIPO OPCOES
);

Exemplo:

CREATE TABLE pessoa (


codigo INT NOT NULL AUTO_INCREMENT ,
nome VARCHAR(50) NOT NULL ,
email VARCHAR(50) NULL ,
sexo ENUM('M', 'F') NOT NULL DEFAULT 'M',
data_nascimento DATE NULL ,
escolaridade VARCHAR(30) NULL ,
data_cadastro DATE NULL ,
PRIMARY KEY (codigo)
)

Vamos conhecer as palavras chave utilizadas:

• NOT NULL: o campo não aceita valores nulos


Capítulo 10 Introdução ao Banco de dados MySQL - 88

• NULL: o campo aceita valores nulos


• DEFAULT: determina o valor padrão, caso não seja informado
• AUTO_INCREMENT: o campo será autonumerado (tem que ser NOT NULL e
chave primária)
• PRIMARY KEY (codigo): determina que o campo codigo será chaver primária
da tabela

Observação: o nome da tabela é case sensitive, ou seja, cadastro é diferente


de Cadastro que é diferente de CADASTRO.

10.7.2. Obtendo informações sobre o banco e


tabelas

Liste os bancos do servidor:

SHOW DATABASES;

Liste as tabelas do banco :

SHOW TABLES;

Obtenha detalhes da tabela :

DESCRIBE pessoa;

10.7.3. Inserindo registros (INSERT)

Para inserir dados em uma tabela utilizamos o comando INSERT. A sintaxe do


comando INSERT utiliza três blocos:

/* Definindo tabela */
Capítulo 10 Introdução ao Banco de dados MySQL - 89

INSERT INTO TABELA


/* Lista de campos separados por vírgula -
se não for informada, serão todos os campos */
( CAMPO1, CAMPO2, CAMPO3, CAMPO4 )
/* Lista de valores a serem inseridos, separados por vírgula */
VALUES ('valor1', 2, '2006-12-31', NULL);

Textos devem estar entre aspas simples ou duplas. As datas no formato aaaa-
mm-dd, também entre aspas simples ou duplas.

Valores NULL Os campos não informados receberão o valor nulo (NULL). Se o


campo foi criado com a opção NOT NULL, isto acarretará um erro. Se possuir a
opção valor padrão (DEFAULT), ao invés de NULL armazenará o valor DEFAULT
especificado. O campo autonumerado sem valor informado será incrementado
automaticamente.

Exemplo na tabela Pessoa:

INSERT INTO pessoa (


codigo ,
nome ,
email ,
sexo ,
data_nascimento ,
escolaridade ,
data_cadastro
)
VALUES (
NULL ,
'João da Silva',
'joao@silva.com.br',
'M',
'1970-10-14',
'Graduado em Administração',
'2009-01-13'
);
Capítulo 10 Introdução ao Banco de dados MySQL - 90

10.7.4. Atualizando registros (UPDATE)

Para atualizar dados em uma tabela utilizamos o comando UPDATE. A palavra


chave SET (definir) define os campos a serem alterados. A sintaxe do comando
UPDATE é quase sempre utilizada em conjunto com a cláusula WHERE, restringindo
os registros a serem atualizados. Isto nos gera 3 sintaxes básicas:

Alterando TODOS OS REGISTROS - sem cláusula WHERE:

/* Definindo tabela */
UPDATE TABELA
/* Lista de campos a serem atualizados separados por vírgula */
SET
CAMPO1 = 'Novo Valor',
CAMPO2 = 45,
CAMPO3 = '2006-12-31';

Alterando APENAS UM REGISTRO ESPECÍFICO - cláusula WHERE filtrando a


chave primária da tabela:

/* Definindo tabela */
UPDATE TABELA
/* Lista de campos a serem atualizados separados por vírgula */
SET
CAMPO1 = 'Novo Valor',
CAMPO2 = 45,
CAMPO3 = '2006-12-31'
/* Filtrando a chave primária */
WHERE
CAMPO_QUE_É_CHAVE_PRIMÁRIA = 4587

Alterando VÁRIOS REGISTROS - cláusula WHERE filtrando um ou mais


registros da tabela:

/* Definindo tabela */
UPDATE TABELA
/* Lista de campos a serem atualizados separados por vírgula */
Capítulo 10 Introdução ao Banco de dados MySQL - 91

SET
CAMPO1 = 'Novo Valor',
CAMPO2 = 45,
CAMPO3 = '2006-12-31'
/* Filtrando vários registros */
WHERE
CAMPO1 = 'Valor qualquer'
AND CAMPO2 > 2;

Exemplo na tabela Pessoa:

UPDATE pessoa SET


nome = 'João da Silva e Souza',
data_nascimento = '1970-10-18'
WHERE
codigo = 1;

10.7.5. Excluindo registros (DELETE)

Para excluir registros em uma tabela utilizamos o comando DELETE. A sintaxe


do comando DELETE é quase sempre utilizada em conjunto com a cláusula WHERE,
restringindo os registros a serem atualizados. Funciona como um SELECT que apaga
os registros selecionados. Isto nos gera 3 sintaxes básicas, como no UPDATE:

Excluindo TODOS OS REGISTROS - sem cláusula WHERE:

/* Definindo tabela */
DELETE FROM TABELA;

Excluindo APENAS UM REGISTRO ESPECÍFICO - cláusula WHERE filtrando a


chave primária da tabela:

/* Definindo tabela */
DELETE FROM TABELA
Capítulo 10 Introdução ao Banco de dados MySQL - 92

/* Filtrando a chave primária */


WHERE
CAMPO_QUE_É_CHAVE_PRIMÁRIA = 4587

Filtrando VÁRIOS REGISTROS - cláusula WHERE filtrando um ou mais


registros da tabela:

/* Definindo tabela */
DELETE FROM TABELA
/* Filtrando vários registros */
WHERE
CAMPO1 = 'Valor qualquer'
AND CAMPO2 > 2;

Observação: para limpar (excluir todos os registros de uma tabela),


reiniciando a autonumeração, usamos o comando TRUNCATE:

TRUNCATE TABELA;

Exemplo na tabela Pessoa:

DELETE FROM pessoa


WHERE codigo = 1;

10.7.6. Selecionando registros (SELECT)

Seleção é a operação mais utilizada em SQL. Veremos a seguir suas sintaxes


mais básicas, criando gradativamente seleções mais complexas. O comando chave é o
SELECT.

Sintaxe básica :

/* Selecionar */
SELECT
/* Lista de campos separados por vírgula */
CAMPO1, CAMPO2, CAMPO3
Capítulo 10 Introdução ao Banco de dados MySQL - 93

/* Da tabela */
FROM TABELA;

Para selecionar todos os campos, utilize o asterisco “*”.

A consulta abaixo seleciona todos registros:

SELECT * FROM TABELA;

Condições

A cláusula WHERE expressa a condição ONDE. É utilizada para:

• Filtrar os registros dada uma ou mais restrições


• Relacionar tabelas

Os campos que serão utilizados na filtragem não precisam ser exibidos no


resultado da consulta.

A clásula WHERE é usada SEMPRE após a lista de tabelas.

Filtrando dados

Para filtrar dados, é necessário usar operadores ou comparadores. Os


operadores básicos são:

Tabela 13:Tabela de Operadores de Comparação

Operador Descrição Exemplo


= igual a CAMPO1 = 'JORGE'
<> diferente de CAMPO1 <> 'JORGE'
> maior que CAMPO1 > CAMPO5
CAMPO1 > 10
< menor que CAMPO1 < CAMPO5
CAMPO1 < 10
>= maior ou igual que CAMPO1 >= CAMPO5
CAMPO1 >= 10
<= menor ou igual que CAMPO1 <= CAMPO5
CAMPO1 <= 10
LIKE como CAMPO1 LIKE '%JORGE%'
BETWEEN entre CAMPO1 BETWEEN
35 AND 50
IN em CAMPO1 IN (1,2,3,4,5)
NOT IN não está em CAMPO1 NOT IN (1,2,3,4,5)

Observação: o símbolo percentual (%) é um coringa para pesquisas em texto,


Capítulo 10 Introdução ao Banco de dados MySQL - 94

significa qualquer trecho de texto, inclusive nenhum.

Exemplo:

/* Selecionar todos os campos */


SELECT *
/* da tabela pessoa*/
FROM pessoa
/* onde */
WHERE
/*
o valor do campo NOME comece com 'josé'
e continue com qualquer coisa
(inclusive nada)
*/
NOME LIKE 'josé%';

O MySQL não faz distinção entre maiúsculas e minúsculas e caracteres


acentuados, então José e JOSE são iguais na comparação.

Para filtrar por mais de um campo, utilize as operadores lógicas:

Tabela 14:Tabela Operadores Lógicos

Operador Descrição
OR OU - Um filtro ou outro
AND E - Um filtro e outro filtro

Exemplo :

/* Selecionar todos os campos */


SELECT *
/* da tabela pessoa*/
FROM pessoa
/* onde */
WHERE
/* o valor do campo sexo seja igual a 'M' */
sexo = 'M'
/* OU o valor do campo data_nascimento seja maior que 01/01/1970 */
Capítulo 10 Introdução ao Banco de dados MySQL - 95

OR data_nascimento > '1970-01-01';

10.8. Administração de usuários

O controle de acesso ao banco é feito pelo comando GRANT. Com ele é


possível especificar quais ações, determinados usuários em certas localidades podem
executar sobre quais tabelas.

É muito importante salientar que o usuário para o no MySQL é um conjunto e


usuário X host de onde acessa, no formato usuario@host. Ou seja, podem existir dois
usuários com mesmo nome, desde que acessando de hosts diferentes.

No exemplo a seguir sobre é dado permissão sobre todo o banco de dados


livraria para o usuário dono acessando do host localhost o banco de dados livraria,
cuja senha é password.

GRANT SELECT, INSERT, UPDATE, DELETE


ON livraria.*
TO dono@localhost IDENTIFIED BY 'password';

Para ativar a criação do usuário é necessário recarregar a tabela de


privilégios:

FLUSH PRIVILEGES

Como é bastante comum a instalação de aplicativos e sistemas em PHP no


mesmo servidor em que está o MySQL, é corriqueiro criar usuários @localhost,
geralmente um para cada sistema instalado, evitando acessos indevidos.

De mesmo modo, o MySQL por padrão no Debian não permite acessos de


outros hosts. É preciso comentar uma configuração no arquivo /etc/mysql/my.cnf :

bind-address = 127.0.0.1

colocando um símbolo de sustenido (cerquilha) na frente, ficando assim:

#bind-address = 127.0.0.1
Capítulo 10 Introdução ao Banco de dados MySQL - 96

Para ativar, reinicia-se o serviço MySQL:

/etc/init.d/mysql restart

10.9. phpMyAdmin

O phpMyAdmin é uma ferramenta de administração do banco de dados


MySQL implementada em PHP, com interface web. É bastante amigável e muito útil
para aquele que não se sentem muito confortáveis com a SQL.

A quase totalidade dos provedores de hospedagem o utilizam como


ferramenta de administração.

Para acessar o phpMyAdmin informe a seguinte URL em seu navegador:

http://localhost/phpmyadmin

10.10. Construindo a base de dados do


website

Seguindo as orientações anteriores, vamos criar as tabelas no banco de dados


que servirão de base para o nosso website.

O exemplo será documentado na linha de comando, mas pode ser executado


no phpMyAdmin.

Criando a base e selecionando-a. No prompt do MySQL digite os comando a


seguir.

create database livraria;


use livraria;

Tabela usuario :

CREATE TABLE usuario (


Capítulo 10 Introdução ao Banco de dados MySQL - 97

login char(16) NOT NULL,


nome char(16) NOT NULL,
senha char(40) NOT NULL,
perfil enum('admin','gerente','despacho') NOT NULL,
PRIMARY KEY (login)
);

Tabela categoria :

CREATE TABLE categoria (


cat_id int(10) unsigned NOT NULL auto_increment,
descricao char(60) NOT NULL,
PRIMARY KEY (cat_id)
);

Tabela cliente :

CREATE TABLE cliente (


cliente_id int(10) unsigned NOT NULL auto_increment,
nome char(60) NOT NULL,
endereco char(80) NOT NULL,
cidade char(30) NOT NULL,
uf char(20) default NULL,
cep char(9) default NULL,
PRIMARY KEY (cliente_id)
);

Tabela livro :

CREATE TABLE livro (


isbn char(13) NOT NULL,
Capítulo 10 Introdução ao Banco de dados MySQL - 98

autor char(80) default NULL,


titulo char(100) default NULL,
cat_id int(10) unsigned default NULL,
preco float(10,2) NOT NULL,
sumario varchar(1000) default NULL,
PRIMARY KEY (isbn)
);

Tabela pedido:

CREATE TABLE pedido (


pedido_id int(10) unsigned NOT NULL auto_increment,
cliente_id int(10) unsigned NOT NULL,
total float(6,2) default NULL,
data date NOT NULL,
status char(10) default NULL,
entrega_nome char(60) NOT NULL,
entrega_endereco char(80) NOT NULL,
entrega_cidade char(30) NOT NULL,
entrega_uf char(20) default NULL,
entrega_cep char(9) default NULL,
forma_pagto enum('BOLETO','DEPÓSITO','CARTÃO') NOT NULL,
PRIMARY KEY (pedido_id)
);

Tabela pedidoitem :

CREATE TABLE pedidoitem (


peditem_id int(10) unsigned NOT NULL auto_increment,
pedido_id int(10) unsigned NOT NULL,
isbn char(13) NOT NULL,
preco float(10,2) NOT NULL,
quantidade tinyint(3) unsigned NOT NULL,
PRIMARY KEY (peditem_id)
);
Capítulo 10 Introdução ao Banco de dados MySQL - 99

10.10.1. Garantindo as permissões de acesso

grant select, insert, update, delete


on livraria.*
to livaria@localhost identified by 'password';

10.10.2. Populando o banco.

Para inserir os dados no nosso banco, vamos utilizar um script já pronto:


populate.sql :

mysql> exit;
mysql -u root -p < populate.sql

10.11. Conceitos Avançados

10.11.1. Transações

Transação é uma sequência de instruções que deverá ser lida como uma
instrução indivisível.

Uma transação deve ser atômica (tudo ou nada), ou seja, ou são todas
operações executadas ou todas são ignoradas.

Sua vantagem é a garantia de integridade. Em especial em operações em que


várias tabelas são afetadas simultaneamente. Um exemplo clássico é a inclusão de
uma Nota Fiscal (uma tabela) e seus itens (outra tabela): a nota fiscal é incluída
primeiro, os itens são vinculados a ela pela sua chave... mas se a gravação falhar
antes do último item, existe um inconsistência.

Se estiver toda operação embutida numa transação, isto não acontece.


Capítulo 10 Introdução ao Banco de dados MySQL - 100

Outro efeito da transação é isolar seu processamento do efeito de outras


transações.

O MySQL possui uma sintaxe própria em seus scripts para tratar transações.
Utiliza-se o comando START TRANSACTION antes de um conjunto de operações para
indicar que fazem parte de uma transação; e ao final, mediante uma condição, define-
se se será efetivada toda transação (COMMIT) ou abortada completamente
(ROLLBACK).

Observação: nem todos tipos de motor de banco de dados do MySQL


suportam transações (o padrão MySQL não suporta; normalmente é utilizado o
INNOBD para estas situações).

10.11.2. Prepared Statment

Prepared statment (declaração preparada) é um recurso de banco de


dados (presente também no MySQL) que permite definir uma consulta e executá-las
várias vezes com parâmetros diferentes.

Exemplo

SELECT * FROM pessoa WHERE id = ?

O ? (ponto de interrogação) é chamado de placeholder, que será substituído


por um valor enviado para complementação da consulta.

Vantagens:

• Podem ser utilizadas para aumentar a segurança, pois a lógica da consulta é


verificada em separado dos dados (parâmetros) – separação que ajuda
prevenir ataques de Ataques de SQL Injection;
• Em processamentos em lote (repetitivos, vários inserts ou selects) aumenta
do desempenho global, pois a consulta é "parseada" (testada em sua sintaxe)
apenas uma vez.

Desvantagens:

• Para uma única operação, gera mais requisições (uma para a preparação,
outra para a execução final).
Capítulo 10 Introdução ao Banco de dados MySQL - 101

10.12. Finalizando

Este capítulo foi uma breve introdução à linguagem SQL no MySQL. Há


muitos recursos úteis que não caberiam no escopo desta pequena introdução;
maiores informações podem ser obtidas no manual do MySQL:

• Português, referência da versão 4.1:


http://dev.mysql.com/doc/refman/4.1/pt/index.html
• Inglês, referência da versão 5.1:
http://dev.mysql.com/doc/refman/5.1/en/index.html
Capítulo 11 Integrando o PHP com MySQL - 102

Capítulo 11

Integrando o PHP com MySQL

11.1. Objetivos

• Usar métodos de acesso a banco que dão suporte a PHP O.O .

• Usar biblioteca de abstração de dados com suporte a diversos bancos de


dados(MySQL, PostgreSQL, etc).

Neste capítulo abordaremos duas formas básicas de conexão do PHP ao


MySQL : com a Extensão Melhorada MySQL (mysqli) e PHP Data Objects
(PDO).
Capítulo 11 Integrando o PHP com MySQL - 103

11.2. Extensão Melhorada MySQL (mysqli)

O PHP 5 possui uma nova biblioteca para conectar-se ao MySQL, chamada


mysqli. A partir da versão 4, foi acrescentado um novo protocolo de conexão ao
MySQL que é muito mais rápido, e essa biblioteca permite tirar vantagem dele.

Ela permite uso na forma procedural (funções) ou orientada a objeto


(classes).

11.2.1. Conectando-se ao banco

Para conectar-se a um banco, utilizamos o comando a seguir.

Modo Orientado a Objeto:

330 // Conexão
331 $conexao = new mysqli('host', 'user', 'password', 'database');
332 if (mysqli_connect_errno()) {
333 echo 'Erro na conexão: ' . mysqli_connect_error();
334 exit;
335 }
336 // Comandos relacionadas à conexão...
337 $conexao->close();

Modo Procedural:

338 $conexao = mysqli_connect('localhost', 'user',


339 'password', 'database');
340 if (!$conexao) {
341 echo 'Erro na conexão: ' . mysqli_connect_error();
342 exit;
343 }
344 // Comandos relacionadas à conexão...
345 mysqli_close($conexao);
Capítulo 11 Integrando o PHP com MySQL - 104

Vale a pena verificar o resultado da tentativa de conexão, porque o código


restante não funcionará sem uma conexão válida de banco de dados. Por isto foi
colocada uma condição testando a conexão, exibindo a mensagem e abortando o
script.

Apesar de podermos especificar em qual banco de dados pretendemos


trabalhar, é possível alterá-lo:

Modo Orientado a Objeto:

346 $conexao = new mysqli('host', 'user', 'password', 'database');


347 $conexao->select_db(newDatabase);

Modo Procedural:

348 $conexao = mysqli_connect('localhost', 'user', 'password',


'database');
349 mysqli_select_db('$conexao', 'newDatabase');

11.2.2. Executando consultas

As consultas são realizadas através de strings que contém declarações SQL.


Por exemplo:

Modo Orientado a Objeto:

350 $sql = "SELECT * FROM pessoa";


351 $resultado = $conexao->query($query);
352 // para liberar o resultado da memória após uso
353 $resultado->free();

Modo Procedural:

354 $sql = "SELECT * FROM pessoa";


355 $resultado = $conexao($conexao, $sql);
Capítulo 11 Integrando o PHP com MySQL - 105

356 // para liberar o resultado da memória após uso


357 mysql_free_result($resultado);

Observe o fato de que na string de consulta não é necessário colocar o ponto-


e-vírgula no final.

Podemos também consultar o número de linhas retornadas na última consulta:

Modo Orientado a Objeto:

358 $sql = "SELECT * FROM pessoa";


359 $resultado = $conexao->query($query);
360 $totalRegistros = $resultado->num_rows;

Modo Procedural:

361 $sql = "SELECT * FROM pessoa";


362 $resultado = $conexao($conexao, $sql);
363 $totalRegistros = mysqli_num_rows($resultado);

Observação: num_rows serve para SELECT. INSERT, DELETE e UPDATE geram


affected_rows.

11.2.3. Recuperando registros

Para extrair o resultado da pesquisa, usamos o comando:

Modo Orientado a Objeto:

364 $sql = "SELECT * FROM pessoa";


365 $resultado = $conexao->query($query);
366 // retornando em forma de objeto
367 $registro = $resultado->fetch_object();
368 // retornando em forma de array
369 $registro = $resultado->fetch_assoc();
370

371 Modo Procedural:


Capítulo 11 Integrando o PHP com MySQL - 106

372 $sql = "SELECT * FROM pessoa";


373 $resultado = $conexao($conexao, $sql);
374 // retornando em forma de objeto
375 $registro = mysqli_fetch_object($resultado);
376 // retornando em forma de array
377 $registro = mysqli_fetch_assoc($resultado);

11.2.4. Passando por todos registros

A cada execução do comando anterior, obteremos mais uma linha retornada


pela busca, até que seja retornado nulo. Então é muito simples utilizarmos um laço
de repetição para passar por todos os campos de uma tabela.

Modo Orientado a Objeto:

378 // retornando em forma de objeto


379 while($registro = $resultado->fetch_object()) {
380 echo $registro->nome . ' - ' .$registro->email . '<br/>';
381 }
382 // retornando em forma de objeto
383 while($registro = $resultado->fetch_assoc()) {
384 echo $registro['nome'] . ' - ' .$registro['email'] . '<br/>';
385 }

Modo Procedural:

386 // retornando em forma de objeto


387 while($registro = mysqli_fetch_object($resultado)) {
388 echo $registro->nome . ' - ' .$registro->email . '<br/>';
389 }
390 // retornando em forma de objeto
391 while($registro = mysqli_fetch_assoc($resultado)) {
392 echo $registro['nome'] . ' - ' .$registro['email'] . '<br/>';
393 }
Capítulo 11 Integrando o PHP com MySQL - 107

11.2.5. Exemplo completo com uso do Modo


Orientado a Objeto

394 <?php
395 // Arquivo conexao.php
396 // Dados para conexão
397 $servidor = 'localhost';
398 $banco = 'cadastro';
399 $usuario = 'cadastro';
400 $senha = 'password';
401

402 // Conexão
403 $conexao = new mysqli($servidor, $usuario, $senha,$banco);
404

405 // Testando se conexão é válida


406 if (mysqli_connect_errno()) {
407 echo 'Erro na conexão: ' . mysqli_connect_error();
408 exit;
409 }
410

411 // Selecionando todos registros


412 $sql = "SELECT * FROM pessoa";
413 $result = $conexao->query($sql);
414

415 // Cabeçalho da tabela com total de registros


416 echo '
417 <table>
418 <caption>Total de registros: ' . $result->num_rows .
'</caption>
419 <tr>
420 <td>Código</td>
421 <td>Nome</td>
422 <td>Email</td>
423 </tr>
424 ';
Capítulo 11 Integrando o PHP com MySQL - 108

425

426 // Passando por todos os registros e exibindo


427 while($registro = $result->fetch_object()) {
428 echo '
429 <tr>
430 <td>' . $registro->codigo . '</td>
431 <td>' . $registro->nome . '</td>
432 <td>' . $registro->email . '</td>
433 </tr>
434 ';
435 }
436

437 // Finalizando tabela


438 echo '
439 </table>
440 ';
441

442 // Liberando resultado da memória


443 $resultado->free();
444

445 // Encerrando conexao


446 $conexao->close();
447 ?>

11.2.6. Prepared Statment

Prepared Statment exigem dois passos: a preparação e a execução com


passagem dos parâmetros.

A forma de trabalho é um pouco diferente de uma consulta comum. É preciso:

• Preparar a declaração com o método prepare (orientado a objeto) ou a


função mysqli_prepare (procedural).
• Passar parâmetros com o método bind_param (orientado a objeto) ou a
função mysqli_stmt_bind_param (procedural).
Capítulo 11 Integrando o PHP com MySQL - 109

• Executar a declaração com o método execute (orientado a objeto) ou a


função mysqli_stmt_execute (procedural).
• Definir os campos a serem recuperados em variávies com o método
bind_result (orientado a objeto) ou a função mysqli_stmt_bind_result
(procedural).
• Recuperar os registros (com o sem loop através do while) com o método
fetch (orientado a objeto) ou a função mysqli_stmt_fetch

É preciso passar os parâmetros informando seu tipo, conforme a tabela a


seguir:

Tabela 15: Caracteres de especificação de tipo

Caractere Descrição
i corresponde a uma variável de tipo inteiro
d corresponde a uma variável de tipo double
s corresponde a uma variável de tipo string
b corresponde a uma variável que contém
dados para um blob e enviará em pacotes

Modo Orientado a Objeto:

448 $sql = "SELECT nome, idade, cidade FROM pessoa


449 WHERE sexo = ? AND uf = ?";
450 $sexo = 'M';
451 $uf= 'DF';
452 if ($stmt = $conexao->prepare($sql)) {
453 // A ordem é importante!
454 // Passar a lista de tipos, seguida valores
455 // em forma ou não de variáveis
456 $stmt->bind_param('ss', $sexo, $uf);
457 $stmt->execute();
458 $stmt->bind_result($nome, $idade, $cidade);
459 while ($stmt->fetch()) {
460 echo "{$nome}, {$idade} anos, residente em {$cidade}\n";
461 }
462 $stmt->close();
463 }
Capítulo 11 Integrando o PHP com MySQL - 110

Modo Procedural:

464 $sql = "SELECT nome, idade, cidade FROM pessoa


465 WHERE sexo = ? AND uf = ?";
466 $sexo = 'M';
467 $uf= 'DF';
468 if ($stmt = mysqli_prepare($conexao, $sql)) {
469 // A ordem é importante!
470 // Passar a lista de tipos, seguida valores
471 // em forma ou não de variáveis
472 mysqli_stmt_bind_param($stmt, 'ss', $sexo, $uf);
473 mysqli_stmt_execute($stmt);
474 mysqli_stmt_bind_result($stmt, $nome, $idade, $cidade);
475 while (mysqli_stmt_fetch($stmt)) {
476 echo "{$nome}, {$idade} anos, residente em {$cidade}\n";
477 }
478 $stmt->close();
479 }

11.2.7. Transactions

A biblioteca mysqli trabalha em modo de AUTOCOMMIT, ou seja, cada


consulta é imediatamente executada.

Portanto, desabilitar o AUTOCOMMIT inicia uma transação, e todas as


consultas executadas após este comando só serão efetivadas com um COMMIT, ou
canceladas com um ROLLBACK.

Os exemplos explicados a seguir detalham o procedimento:

Modo Orientado a Objeto:

480 $conexao = new mysqli('host', 'user', 'password', 'database');


481 // Desabilita autocommit e inicia transação
482 $conexao->autocommit(FALSE);
Capítulo 11 Integrando o PHP com MySQL - 111

483 $conexao->query("INSERT INTO pessoa (nome, idade, sexo)


484 VALUES ('João Silva', 25, 'M')");
485 $conexao->query("INSERT INTO pessoa (nome, idade, sexo)
486 VALUES ('Maria Silva', 21, 'F')");
487 /*
488 $conexao->commit retorna TRUE se todas as consultas forem
489 executadas com sucesso, ou FALSE se qualquer uma falhar
490 - neste caso, acontecerá o $conexao->rollback
491 if (!$conexao->commit()) {
492 $conexao->rollback();
493 }

Modo Procedural:

494 $conexao = mysqli_connect('localhost', 'user', 'password',


'database');
495 // Desabilita autocommit e inicia transação
496 mysqli_autocommit($conexao);
497 mysqli_query($conexao, "INSERT INTO pessoa (nome, idade, sexo)
498 VALUES ('João Silva', 25, 'M')");
499 mysqli_query($conexao, "INSERT INTO pessoa (nome, idade, sexo)
500 VALUES ('Maria Silva', 21, 'F')");
501 /*
502 mysqli_commit($conexao) retorna TRUE se todas as consultas
forem
503 executadas com sucesso, ou FALSE se qualquer uma falhar
504 - neste caso, acontecerá o mysqli_rollback($conexao)
505 if (!mysqli_commit($conexao)) {
506 mysqli_rollback($conexao);
507 }

11.3. PDO (PHP Data Objects)

O PHP 5.1 Possui nativamente a biblioteca de abstração de banco de dados


PDO (PHP Data Objects). Sua grande vantagem é permitir acesso a vários bancos de
Capítulo 11 Integrando o PHP com MySQL - 112

dados suportados pelo PHP numa única classe.

11.3.1. Conectando-se ao banco

Para conectar-se a um banco, utilizamos o comando a seguir.

508 // Conexão utilizando DSN = Data Source Name


509 // Exemplo com MySQL
510 $dsn = 'mysql:host=localhost;dbname=banco';
511 // Exemplo com Postgres
512 $dsn = 'pgsql:host=localhost;dbname=banco';
513 $conexao = new PDO($dsn, 'user', 'password');

O PDO retorna excessões em forma de objeto (visto mais adiante neste curso).
Portanto, é possível utilizar a sintaxe try/catch para capturar e tratar erros.

514 try
515 {
516 $dsn = 'mysql:host=localhost;dbname=banco';
517 $conexao = new PDO($dsn, 'user', 'password');
518 $conexao->setAttribute(PDO::ATTR_EMULATE_PREPARES, TRUE);
519 $conexao->setAttribute(PDO::ATTR_ERRMODE,
PDO::ERRMODE_EXCEPTION);
520 }
521 catch (PDOException $e)
522 {
523 echo 'Erro: ' . $e->getMessage();
524 }
Capítulo 11 Integrando o PHP com MySQL - 113

11.3.2. Executando consultas

Este é o método para SELECT. Apesar de retornar um OBJETO, utiliza-se de


recursos do PHP 5.1 (chamado SPL) para poder ser iterado com o foreach:

525 $sql = "SELECT * FROM pessoa";


526 $resultados = $conexao->query($sql);
527

528 // Retornando em forma de array associativo


529 foreach ($resultados as $registro)
530 {
531 echo "{$registro['nome']}, {$registro['idade']}\n";
532 }
533 // ou
534 while ($registro = $resultados->fetch())
535 {
536 echo "{$registro['nome']}, {$registro['idade']}\n";
537 }
538

539 // Retornando em forma de objetos


540 $resultado->setFetchMode(PDO::FETCH_OBJ);
541 foreach ($resultado as $registro)
542 {
543 echo "{$registro->nome}, {$registro->idade}\n";
544 }
545 // ou
546 while ($registro = $resultado->fetchObject())
547 {
548 echo "{$registro->nome}, {$registro->idade}\n";
549 }

Podemos também consultar o número de linhas retornadas na última consulta:

550 $sql = "SELECT * FROM pessoa";


551 $resultados = $conexao->query($sql);
552 $totalRegistros = $resultado->rowCount();
Capítulo 11 Integrando o PHP com MySQL - 114

Observação: rowCount serve para SELECT. INSERT, DELETE e UPDATE geram


affected_rows.

11.3.3. Executando inserções, exclusões e


atualizações

Método para INSERT, DELETE e UPDATE.

553 $sql = "INSERT INTO pessoa (nome, idade, sexo)


554 VALUES ('João Silva', 25, 'M')";
555 $regAfetados = $conexao->exec($sql);
556 echo "Registros afetados: {$regAfetados}";

11.3.4. Prepared Statment

O PDO permite o uso tanto do placeholder (ponto de interrogação) quanto de


parâmetros nomeados (padrão :variavel).

O método bindParam pode opcionalmente o tipo e o tamanho da informação


para validá-lo. Os tipos podem ser:

Tabela 16: Lista de tipos para método bindParm

Constante Descrição
PDO::PARAM_BOOL Boolean
PDO::PARAM_NULL Null
PDO::PARAM_INT Integer
PDO::PARAM_STR Char, Varchar
(padrão)
PDO::PARAM_LOB Blob

Para recuperar os dados utiliza-se o método fetch, que recebe como


parâmetro uma constante que determina como ele vai retornar os dados, sendo os
mais comuns PDO::FETCH_ASSOC e PDO::FETCH_OBJ.
Capítulo 11 Integrando o PHP com MySQL - 115

Sintaxe com placeholder:

557 $sql = "SELECT nome, idade, cidade FROM pessoa


558 WHERE sexo = ? AND uf = ?";
559 $sexo = 'M';
560 $uf= 'DF';
561 $stmt = $conexao->prepare($sql);
562 $stmt->bindParam(1, $sexo, PDO::PARAM_INT);
563 $stmt->bindParam(2, $uf, PDO::PARAM_STR, 12);
564 $resultado = $stmt->execute();
565

566 // Passando pelos registros em modo ASSOC (Array)


567 while ($registro = $stmt->fetch(PDO::FETCH_ASSOC)) {
568 echo "{$registro['nome']}, {$registro->['idade']}\n";
569 }
570 // OU...
571 // Passando pelos registros em modo OBJECT
572 while ($registro = $stmt->fetch(PDO::FETCH_OBJ)) {
573 echo "{$registro->nome}, {$registro->'idade'}\n";
574 }

Sintaxe com parâmetros nomeados:

575 $sql = "SELECT nome, idade, cidade FROM pessoa


576 WHERE sexo = :sexo AND uf = :uf";
577 $sexo = 'M';
578 $uf= 'DF';
579 $stmt = $conexao->prepare($sql);
580 $stmt->bindParam(':sexo', $sexo, PDO::PARAM_INT);
581 $stmt->bindParam(':uf', $uf, PDO::PARAM_STR, 12);
582 $stmt->execute();
583

584 // Passando pelos registros em modo ASSOC (Array)


585 while ($registro = $stmt->fetch(PDO::FETCH_ASSOC)) {
586 echo "{$registro['nome']}, {$registro->['idade']}\n";
587 }
588 // OU...
Capítulo 11 Integrando o PHP com MySQL - 116

589 // Passando pelos registros em modo OBJECT


590 while ($registro = $stmt->fetch(PDO::FETCH_OBJ)) {
591 echo "{$registro->nome}, {$registro->'idade'}\n";
592 }

11.3.5. Transactions

Uma transação no PDO funciona de modo semelhante à biblioteca MySQL.


Entretanto, como retorna exceção, pode-se utilizar a sintaxe try/catch para capturar
o erro. Possui também um método para iniciar a transação, como vê-se no exemplo
que segue.

593 $dsn = 'mysql:host=localhost;dbname=banco';


594 $conexao = new PDO($dsn, 'user', 'password');
595 $conexao->setAttribute(PDO::ATTR_EMULATE_PREPARES, TRUE);
596 $conexao->setAttribute(PDO::ATTR_ERRMODE,
PDO::ERRMODE_EXCEPTION);
597 $conexao->beginTransaction();
598 try
599 {
600 $conexao->exec("INSERT INTO pessoa (nome, idade, sexo)
601 VALUES ('João Silva', 25, 'M')");
602 $conexao->exec("INSERT INTO pessoa (nome, idade, sexo)
603 VALUES ('Maria Silva', 21, 'F')");
604 $conexao->commit();
605 }
606 catch (PDOException $e)
607 {
608 $conexao->rollBack();
609 echo 'Erro: ' . $e->getMessage();
610 }
Capítulo 12 Programação Orientada a Objetos - 117

Capítulo 12

Programação Orientada a Objetos

12.1. Objetivos

• Entender os diversos tipos de classes e suas aplicações.

• Implementar Herança e Interface, afim de ter um código que segue os padrões.

• Reunir as informações adquiridas para fechar o conceito de Design Patterns.


Capítulo 12 Programação Orientada a Objetos - 118

12.2. Introdução teórica

Neste capítulo será abordada uma breve revisão do Programação Orientada a


Objetos. Este paradigma propõe-se a resolver os problemas da programação criando
um abstração das coisas reais através de CLASSES. É o paradigma de programação
mais utilizado na atualidade, fazendo parte da maioria das linguagens modernas.

O PHP possui suporte à Orientação a Objeto, porém não completo.


Inicialmente o PHP era uma linguagem procedural e funcional, mas hoje a maioria
dos projetos de ponta software livre utilizando o PHP utilizam a Orientação a Objeto
como paradigma principal.

12.3. Conceitos

Na Orientação a objetos os problemas de programação são enxergados


através da abstração de indíviduos semelhantes em estruturas estáticas chamadas
CLASSES. Quando criamos um INSTÂNCIA desta CLASSE, representando um objeto
único, temos um OBJETO.

12.3.1. Classe

É uma abstração de um conjunto de indíviduos com características e ações


semelhantes, dentro de um contexto que interesse à resolução de um problema de
programação.

As classes são estruturas ESTÁTICAS que representam características e ações


semelhantes de um grupo de entidades. Em programação, podem representar
diversos tipos de entidades como componentes de negócio da aplicação, entidades da
interface, conexão, arquivo, tabelas de um banco de dados, um chat, um fórum, uma
página web, um formulário, etc.
Capítulo 12 Programação Orientada a Objetos - 119

12.3.2. Objeto

É a representação de indivíduo único que é construído com base nas


características e ações de uma classe. Uma INSTÂNCIA de uma classe.

Objetos são estruturas DINÂMICAS baseadas nas estruturas ESTÁTICAS das


CLASSES.

12.3.3. Atributos

Atributos são características fundamentais de uma classe ou de um conjunto


de objetos. Se temos a classe VEÍCULOS, podem ser atributos a COR, NÚMERO DE
RODAS, VELOCIDADE MÁXIMA, QUANTIDADE DE MARCHAS, entre outros.

12.3.4. Métodos

Métodos são açãos, atividades, procedimentos que uma classe pode executar
ou podemos executar com a classe. Se temos a classe VEÍCULOS, podem ser métodos
a ACELERAR, FREAR, VIRAR À DIREITA, VIRAR À ESQUERDA, ANDAR À FRENTE,
ANDAR DE RÉ, entre outros.

12.4. Uma classe simples: Pessoa

Para facilitar o entendimento, vamos começar definindo uma classe simples,


com alguns atributos e apenas um método.
Capítulo 12 Programação Orientada a Objetos - 120

Figura 12.1: Classe


Pessoa

Para utilizar a classe, é preciso criar uma organização em nosso diretório.


Abra um terminal como root e digite os comandos:

cd /var/www/curso
mkdir classes
cd classes
gedit Pessoa.class.php &

Interessante observar o padrão de nomeclatura de extensão do arquivo


utilizado: .class.php. Ele é bastante comum e inclusive sugerido por alguns editores
mais avançados.

Pode-se então criar a classe em PHP neste arquivo:

611 <?php
612 // Definição da classe
613 class Pessoa {
614

615 // Definição de variáveis


616 protected $codigo;
617 public $nome;
Capítulo 12 Programação Orientada a Objetos - 121

618 public $email;


619 public $data_nascimento;
620 public $escolaridade;
621 public $data_cadastro;
622

623 // Definição de método


624 public function enviarEmail ($assunto, $mensagem) {
625 // Enviando email com a função mail
626 mail($this->email, $assunto, $mensagem);
627 echo "<p>Email enviado com sucesso</p>";
628 }
629 }
630 ?>

Algumas sintaxes novas surgiram na definição da classe. Vamos conhecê-las:

• class: Para definição do nome da classe, que ficará englobada entre chaves
• private, public: Definem o encapsulamento, visto mais adiante
• function: Já conhecido, define aqui um método da classe
• $this->email: o $this é uma auto-referência, ou seja, a classe faz uma
referência a um atributo ou método dela mesma, no caso, o atributo email

Para utilizar a classe, vamos utilizar outro arquivo que vai importar o arquivo
da classe mediante o uso do comando include. este arquivo será salvo com o nome
/var/www/curso/testeClasse.php.

631 <?php
632 include('classes/Pessoa.class.php');
633 $joao = new Pessoa;
634 $joao->nome = "João";
635 $joao->email = "joao@teste.com.br";
636 $assunto = 'Teste de envio';
637 $mensagem = 'Olá, pessoa.';
638 echo "Enviando mensagem para " . $joao->nome;
639 $joao->enviarEmail($assunto, $mensagem);
640 ?>
Capítulo 12 Programação Orientada a Objetos - 122

Quando precisamos criar uma instância de uma classe numa variável,


utilizamos a palavra chave new. Então, os métodos e atributos da classe podem ser
referenciados pela variável utilizando-se o símbolo "->".

Neste exemplo, foi atribuído um valor ao atributo nome do objeto $joao, e


depois enviado um email através de seu método enviarEmail.

12.5. Herança

A capacidade de uma classe de absorver, herdar as características e ações de


outra classe. Assim, a classe que DA QUAL se herda é chamaada CLASSE PAI ou
SUPERCLASSE, e a classe que herda de uma outra classe são chamadas CLASSE
FILHA ou SUBCLASSE.

Qual a importância do uso da Herança? O reuso de código. A possibilidade de


não repetir determinado código em vários lugares, além da possibilidade de
correções e ajustes EM CASCATA. Além disso, evita-se o retrabalho, ou a correção de
um código em mais de um lugar. O trabalho de manutenção do cógido se torna muito
mais fácil.

A classe FILHA herda todas os atributos e métodos da classe PAI, e pode criar
outros ou, dentro de certas limitações, alterar os métodos da classe PAI.

Figura 12.2: Herança de classes


Capítulo 12 Programação Orientada a Objetos - 123

No exemplo, foram criadas duas classes derivadas: Professor e Aluno. Para


criá-las no PHP, vamos utilizar dois arquivos.

Primeiro, /var/www/curso/classes/Professor.class.php :

641 <?php
642 // Definição da classe EXTENDIDA = Herança
643 class Professor extends Pessoa {
644

645 // Definição de variáveis


646 public $turmas;
647 public $graduacao;
648 public $especializacao;
649 public $mestrado;
650 public $doutorado;
651

652 // Novo método


653 public function adicionarTurma ($turma) {
654 $this->turmas[] = $turma;
655 }
656 }
657 ?>

Segundo, /var/www/curso/classes/Aluno.class.php :

658 <?php
659 // Definição da classe EXTENDIDA = Herança
660 class Aluno extends Pessoa {
661

662 // Definição de variáveis


663 public $serie;
664 public $nomePai;
665 public $nomeMae;
666

667 // Novo método


668 public function alterarSerie ($serie) {
669 $this->serie = $serie;
Capítulo 12 Programação Orientada a Objetos - 124

670 }
671 }
672 ?>

É importante salientar que estas classes derivadas só podem ser utilizadas se


o arquivo da classe PAI, no caso Pessoa, for incluído antes no arquivo for utilizá-las.

Vamos testar criando o arquivo /var/www/curso/testeClasse2.php:

673 <?php
674 include('classes/Pessoa.class.php');
675 include('classes/Aluno.class.php');
676 $joao = new Aluno;
677 $joao->nome = "João";
678 $serie = 8;
679 $joao->alterarSerie($serie);
680

681 echo "O aluno " . $joao->nome . " está na "


682 . $joao->serie . "ª série";
683 ?>

12.6. Encapsulamento

Encapsulamento é a característica da classe de apresentar ao mundo seus


métodos de forma a proteger os atributos e métodos internos de uso incorreto da
classe, não sendo necessário saber como cada ação é implementada - o que interessa
é que se pode utilizar a classe com determinada finalidade. Através do
encapsulamento podemos utilizar a classe sem saber como é construída
internamente.

Existem três tipos de visibilidade utilizadas pelo encapsulamento para prover


a proteção dos métodos e atributos:

• Pública (public): O atributo ou método pode ser acessado pela classe que o
definiu, pelas classes derivadas desta classe (filhas) e pelas instâncias dessas
classes (objetos).
• Protegida (protected): O atributo ou método pode ser acessado pela classe
Capítulo 12 Programação Orientada a Objetos - 125

que o definiu, pelas classes derivadas desta classe (filhas) mas NÃO pelas
instâncias dessas classes (objetos).
• Privada (private): O atributo ou método pode ser acessado APENAS classe
que o definiu, e JAMAIS pelas classes derivadas desta classe (filhas) ou pelas
instâncias dessas classes (objetos).

Através das palavras chave public, protected e private na frente de um


atributo ou método determinamos sua visibilidade. Esta possibilidade só existe a
partir da versão 5 do PHP.

12.7. Métodos mágicos

Métodos mágicos são métodos especiais do PHP que realizam determinadas


tarefas específicas numa classe. Veremos a seguir alguns deles.

12.7.1. __construct

Executado no momento em que a classe é instanciada, é utilizado para:

• Executar um código que inicialize variáveis ou algo no ambiente para a


criação do objeto
• Receber valores obrigatórios na inicialização do objeto

Podemos alterar a classe Pessoa para que solicite alguns valores em sua
inicialização:

684 <?php
685 class Pessoa {
686

687 protected $codigo;


688 public $nome;
689 public $email;
690 public $data_nascimento;
691 public $escolaridade;
692 public $data_cadastro;
693
Capítulo 12 Programação Orientada a Objetos - 126

694 // Método Construtor


695 public function __construct ($codigo, $nome, $email=null) {
696 $this->codigo = $codigo;
697 $this->nome= $nome;
698 $this->email = $email;
699 }
700

701 // Definição de método


702 public function enviarEmail ($assunto, $mensagem) {
703 // Enviando email com a função mail
704 mail($this->email, $assunto, $mensagem);
705 echo "<p>Email enviado com sucesso</p>";
706 }
707 }
708 ?>

Agora a classe Pessoa só pode ser instanciada se ao menos dois parâmetros


forem indicados, mas também pode ser instanciada se forem passados os três
parâmetros. Teste criando o arquivo /var/www/curso/testeClasse3.php:

709 <?php
710 include('classes/Pessoa.class.php');
711 $joao= new Pessoa(1, "João");
712 $miguel = new Pessoa(2, "Miguel", "miguel@teste.com.br");
713 echo "Primeira pessoa: " . $joao->nome . "<br/>";
714 echo "A pessoa " . $miguel->nome . " tem o email " . $miguel-
>email;
715 ?>

Não é possível acessar diretamente o atributo $joao->codigo ou


$miguel->codigo porque o atributo é PROTEGIDO (protected).

O construtor também é herdado pelas classes filhas como outro metódo


comum.
Capítulo 12 Programação Orientada a Objetos - 127

12.7.2. __destruct

O método mágico __destruct é executado quando o objeto é retirado da


memória. Isto acontece em duas situações.

• Quando a variável é explicitamente retirada da memória, o que é feito com a


função unset()
• Quando o script termina sua execução

Este método é utilizado para forçar o salvamento de um registro antes de


retirá-lo da memória (forçadamente), eliminar arquivos temporários criados pelo
objeto, atualizar contadores de objetos abertos, entre outras utilidades.

12.7.3. __get e __set

Getters e Setters são termos comuns para métodos que recuperam (get) e
definem (set) valores para um atributo da classe. É extremamente comum que
atributos sejam protegidos ou privados, e sejam alterados unicamente através de
métodos para garantir sua integridade.

Mas nem todos os métodos necessitam desta proteção. Entretanto, é muito


comum mesmo assim implementar os métodos getAtributo e setAtributo para
manter a padronização.

Porém... e se forem muitos atributos com comportamento padrão? Então


podem ser "magicamente" acessados com os métodos __get e __set.

Sem o uso dos getters automáticos no arquivo de exemplo


/var/www/curso/getset.php:

716 <?php
717 class Pessoa {
718 protected $id;
719 protected $nome;
720 protected $idade;
721 protected $sexo;
Capítulo 12 Programação Orientada a Objetos - 128

722 }
723

724 $joao = new Pessoa();


725 $joao->id = 1;
726 echo $joao->id;
727 ?>

Isto gera o erro:

Fatal error: Cannot access protected property Pessoa::$id in


/var/www/curso/getset.php on line 10

Pode-se criar um getter e um setter no padrão comum para solucionar esta


situação:

728 <?php
729 class Pessoa {
730 protected $id;
731 protected $nome;
732 protected $idade;
733 protected $sexo;
734

735 public function setId($valor) {


736 // convertendo forçadamente a ser um inteiro
737 $this->id = (int) $valor;
738 }
739

740 public function getId() {


741 return $this->id;
742 }
743

744 }
745

746 $joao = new Pessoa();


747 $joao->setId(1);
748 echo $joao->getId();
749 ?>
Capítulo 12 Programação Orientada a Objetos - 129

Mas, de forma precisa e automática pode-se utilizar os métodos mágicos:

750 <?php
751 class Pessoa {
752 protected $id;
753 protected $nome;
754 protected $idade;
755 protected $sexo;
756

757 public function setId($valor) {


758 // convertendo forçadamente a ser um inteiro
759 $this->id = (int) $valor;
760 }
761

762 public function getId() {


763 return $this->id;
764 }
765

766 public function __set($name, $value) {


767 $this->$name = $value;
768 }
769 public function __get($name) {
770 return $this->$name;
771 }
772 }
773

774 $joao = new Pessoa();


775 $joao->setId(1);
776 $joao->nome = 'João';
777 $joao->idade = 35;
778 $joao->sexo = 'Masculino';
779 echo $joao->getId() . " - " . $joao->nome;
780 ?>

E então todos os atributos estão disponíveis através dos métodos mágicos. Isto
não impede que se tenha métodos personalizados.
Capítulo 12 Programação Orientada a Objetos - 130

12.7.4. __toString

Quando um objeto é tratado como uma string (como num comando echo) ele
gera um erro. Entretanto, é possível determinar como será a saída de um objeto
nesta situação implementando o método mágico __toString.

Veja o exemplo sem uso do __toString com o arquivo


/var/www/curso/toString.php:

781 <?php
782 class meuErro {
783 public $saida = 'Meu erro';
784 }
785 $erro = new meuErro;
786 echo $erro;
787 ?>

Ao rodar este script recebe-se o erro:

Catchable fatal error: Method meuErro::__toString() must return a string


value in /var/www/curso/toString.php on line 6

Agora "corrigindo" com a implementação do método mágico __toString;

788 <?php
789 class meuErro {
790 public $saida = 'Meu erro';
791

792 public function __toString() {


793 return $this->meuErro;
794 }
795 }
796 $erro = new meuErro;
797 echo $erro;
798 ?>
Capítulo 12 Programação Orientada a Objetos - 131

12.7.5. Outros métodos mágicos

O PHP possui outros métodos mágicos, com diversas funcionalidades. São


eles: __construct, __destruct, __call, __callStatic, __get, __set, __isset, __unset, __sleep,
__wakeup, __toString, __set_state e __clone.

Uma lista completa dos métodos mágicos e suas funcionalidades é encontrada


no manual do PHP:

http://www.php.net/manual/pt_BR/language.oop5.magic.php

12.8. Classes Abstratas

Classes abstratas não podem ser instanciadas diretamente. Servem apenas de


base para classes filhas.

No exemplo da classe PAI Pessoa, esta poderia ser definida como ABSTRATA,
apenas servindo de base para as classes Professor e Aluno.

No PHP isto é feito com uso da palavra chave abstract:

799 <?php
800 abstract class Pessoa {
801 // (...)
802 ?>
Capítulo 12 Programação Orientada a Objetos - 132

12.9. Interfaces e Métodos Abstratos

12.9.1. Interfaces

Interfaces são estruturas que defininem que métodos e atributos precisa


implementar, sem definir como esses métodos serão tratados.

As classes então implementam a interface, e uma classe pode implementar


mais de uma interface.

Se executado a seguinte declaração num arquivo de teste


/var/www/curso/interface.php:

803 <?php
804 interface iPessoa {
805 public function enviarEmail() ;
806 }
807 class Aluno implements iPessoa {
808

809 }
810 ?>

Acontecerá o seguinte erro:

Fatal error: Class Aluno contains 1 abstract method and must therefore be
declared abstract or implement the remaining methods
(iPessoa::enviarEmail) in /var/www/curso/interface.php on line 7

Ou seja, é obrigatório implementar o método enviarEmail:

811 <?php
812 interface iPessoa {
813 public function enviarEmail() ;
814 }
Capítulo 12 Programação Orientada a Objetos - 133

815 class Aluno implements iPessoa {


816 public function enviarEmail() {
817 echo 'Envia Email';
818 }
819 }

12.9.2. Métodos Abstratos

Métodos abstratos são definidos em classes abstratas. Eles obrigam que as


classes filhas implementem este método, então geralmente só possuem uma chamada
sem nenhum código implementado.

Comportam-se de modo análogo às interfaces, mas apenas para um método.


São comumentes criados em classes abstratas para forçar suas filhas a
implementarem determinado método com os parâmetros definidos na classe pai.

Exemplo:

820 <?php
821 class Aluno implements iPessoa {
822 abstract public function enviarEmail($email);
823 }

12.10. Atributos Estáticos

Atributos estáticos tem uma função semelhante à uso em funções. O atributo


definido como estático terá seu valor compartilhado pelas diversas instâncias de uma
classe. Isto tem várias utilidades, como compartilhar conexões ou manter um
contador de instâncias.

Exercite criando e executando o arquivo /var/www/curso/static1.php:

824 class Contador {


825
Capítulo 12 Programação Orientada a Objetos - 134

826 private static $cont = 0;


827

828 public function __construct() {


829 self::$cont++;
830 }
831

832 public function __destruct() {


833 self::$cont--;
834 }
835

836 public function getCont() {


837 return self::$cont;
838 }
839 }
840

841 $obj1 = new Contador;


842 echo $obj1->getCont() . " - ";
843

844 $obj2 = new Contador;


845 echo $obj2->getCont() . " - ";
846

847 $obj3 = new Contador;


848 echo $obj1->getCont() . " - ";
849

850 unset($obj2);
851 echo $obj1->getCont() . " - ";

Com o uso de um construtor e um destrutor foi implementado um contador de


objetos. Na primeira instância o contador é definido em 1, e a cada nova
incrementado em 1. Ao ser destruído um objeto, o contador é diminuído em 1.

12.11. Métodos Estáticos

Os métodos estáticos podem ser acessados sem a necessidade de instância da


classe. Isto é especialmente útil para classes acessórias, que servem como biblioteca
de funções de uma área afim.
Capítulo 12 Programação Orientada a Objetos - 135

Vamos testar criando o arquivo /var/www/curso/classes/Data.class.php:

852 <?php
853 class Data {
854

855 // Recebe a data em formato dd/mm/aaaa e formata em aaaa-mm-dd


856 static function formatarBanco ($data){
857 $dataTemp = explode('/',$data);
858 return $dataTemp[2] . '-' . $dataTemp[1] . '-' . $dataTemp[0];
859 }
860

861 // Recebe a data em formato aaaa-mm-dd e formata em dd/mm/aaaa


862 static function formatarTela ($data){
863 $dataTemp = explode('-',$data);
864 return $dataTemp[2] . '/' . $dataTemp[1] . '/' . $dataTemp[0];
865 }
866 }
867 ?>

Para acessar métodos estáticos utilizamos o operador de resolução de escopo


(::).

Crie o arquivo /var/www/curso/testeClasse3.php para testar o seu uso:

868 <?php
869 include('classes/Data.class.php');
870

871 $dataBanco = '2009-01-13';


872 echo 'Convertendo data do banco ' . $dataBanco .
873 ' para data de exibição ' . Data::formatarTela ($dataBanco) ;
874

875 echo '<br/>';


876

877 $dataTela = '31/12/2008';


878 echo 'Convertendo data de exibição ' . $dataTela .
879 ' para data do banco ' . Data::formatarBanco ($dataTela) ;
880

881 ?>
Capítulo 12 Programação Orientada a Objetos - 136

Alguns cuidados devem ser tomados para evitar erros no uso de métodos
estáticos. Primeiro: métodos estáticos são utilizados sem instância da classe, então
não podem utilizar a chamada $this. Em seu lugar, utilizam o self:: .

Se os valores não terão alteração, então utiliza-se CONSTANTES, que são


especificadas com a palavra chave const e possuem obrigatoriamente valor definido.

Vamos alterar a classe Data.class.php para possuir um padrão de separadores


de data (que poderiam ser substituídos em caso de mudança de língua):

882 <?php
883 Class Data {
884 const SEPARADOR_BANCO = '-';
885 const SEPARADOR_TELA = '/';
886

887 // Recebe a data em formato dd/mm/aaaa e formata em aaaa-mm-dd


888 static function formatarBanco ($data){
889 $dataTemp = explode(self::SEPARADOR_TELA,$data);
890 return $dataTemp[2] . '-' . $dataTemp[1] . '-' . $dataTemp[0];
891 }
892

893 // Recebe a data em formato aaaa-mm-dd e formata em dd/mm/aaaa


894 static function formatarTela ($data){
895 $dataTemp = explode(self::SEPARADOR_BANCO,$data);
896 return $dataTemp[2] . '/' . $dataTemp[1] . '/' . $dataTemp[0];
897 }
898 }
899 ?>

A classe Data foi alterada definindo em constantes os separadores "padrão" a


serem utilizados. O exemplo testeClasse3.php será executado sem nenhuma
alteração.
Capítulo 12 Programação Orientada a Objetos - 137

12.12. A mensagem de erro mais louca do PHP

Um erro na utilização do operador de resolução de escopo (::), colocando-o em


local não esperado gera a seguinte mensagem de erro pelo PHP:

Parse error: syntax error, unexpected T_PAAMAYIM_NEKUDOTAYIM,


expecting ',' or ';' in /var/www/curso/eOMeuErroFoiCrer.php on line 12

Esta louca mensagem tem explicação no manual do PHP:

Paamayim Nekudotayim pode parecer, de inicio, uma escolha estranha


para um dois pontos duplo. No entanto, na hora de escrever o Engine da
Zend 0.5 (que provia o PHP3), foi o que a equipe da Zend decidiu.
Realmente significa dois pontos duplo - em Hebreu!
Capítulo 13 Streams - 138

Capítulo 13

Streams

13.1. Objetivo

• Manipular arquivos e suas informações.

13.2. Introdução teórica

A camada Streams do PHP é uma abstração para acesso a arquivos. Stream é


um termo genérico que refere-se a um vasto número de recursos, inclusive conexões
de rede. O PHP possui a possibilidade de ler streams de rede, assim como tornar-se
um serviço que recebe e devolve streams.

Neste capítulo veremos a manipulação de arquivos locais. Para manipular


arquivos no PHP temos três métodos básicos: com a função fopen(), com a função
file() e com a função file_get_contents();
Capítulo 13 Streams - 139

13.3. Método fopen

Para abrir um arquivo em PHP utilizamos a função fopen(), cuja sintaxe é:

900 fopen(filename, mode);

Exemplos :

901 $texto = fopen ("/home/turing/file.txt", "r");


902 $gif = fopen ("/home/linux/file.gif", "wb");

Em Mode é especificado o modo de abertura do arquivo, ou seja, se o arquivo


deve ser aberto para leitura, escrita, etc. Os principais modos de abertura são:

• r Abre o arquivo no modo somente leitura e posiciona o ponteiro no


início do arquivo. O arquivo já precisa estar criado;
• r+ Abre o arquivo para leitura/escrita e posiciona o ponteiro no início do
arquivo;
• w Abre o arquivo no modo somente escrita. Se o arquivo já existir será
sobrescrito. Caso contrário um novo arquivo é criado;
• w+ Abre o arquivo para leitura/escrita. Se o arquivo já existir, será
sobrescrito. Caso contrário um novo arquivo é criado;
• a Abre o arquivo para anexar dados, posicionando o ponteiro no final do
arquivo. Se o arquivo não existir, será criado um novo;
• a+ Abre o arquivo para leitura/anexo, posicionando o ponteiro no final do
arquivo. Se o arquivo não existir será criado um novo.

13.3.1. Gravando informações em arquivos

Para adicionar dados em arquivos utiliza-se a função fwrite().

Exemplo :

903 $fp = fopen('dados.txt', 'a');


904 fwrite($fp, "Acrescentando ao arquivo!\n");
Capítulo 13 Streams - 140

905 fclose($fp);

13.3.2. Lendo arquivos

Para leitura de um arquivo, utiliza-se a função fgets(), que lê um determinado


número de bytes do arquivo informado.

906 $fp = fopen('dados.txt', 'r');


907 // Lê os 20 primeiros caracteres do arquivo
908 $text = fgets($fp, 20);
909 fclose($fp);

Existe também a função fgetc() que permite ler, caractere a caractere, um


arquivo.

13.3.3. Fechando arquivos

Depois de utilizar o arquivo, é necessário que ele seja fechado.

Para tanto utilizamos a função fclose().

910 $fp = fopen('dados.txt', 'r');


911 fclose($fp);

13.4. Método file

Para finalidades mais práticas existe a função file(). Esta função lê um


arquivo completo e armazena cada linha do arquivo como um elemento de um array.
Depois de ler todo o conteúdo do arquivo, file() o fecha automaticamente, não
sendo necessária uma chamada a fclose().

912 <?php
Capítulo 13 Streams - 141

913 $file_lines = file('dados.txt');


914 echo 'Primeira linha:' . $file_lines[0];
915 // Passando por todas linhas do arquivo.
916 foreach ($file_lines as $line) {
917 echo $line . '<br />';
918 }
919

920 // Para evitar problemas com caracteres de quebra de linha


(\n\r)
921 // é interessante utilizar a função rtrim para "limpar"
922 // à direita a string
923 foreach ($file_lines as $line) {
924 echo rtrim($line) . '<br />';
925 }

13.5. Método file_get_contents

Esta função lê um arquivo inteiro para uma variável. Muito útil para arquivos
HTML, por exemplo.

926 $file_html = file_get_contents('dados.html');


927 echo $file_html;
Capítulo 14 Tratamento de Erros e Exceções - 142

Capítulo 14

Tratamento de Erros e Exceções

14.1. Objetivos

• Lidar com os erros deixando o ambiente agradavel ao usuário.

• Tratar excessões para analise e correção dos erros do sistema.

14.2. Exibição de erros

Todas as linguagens de alto nível possuem algum modo de permitir ao


programador receber mensagens de erro e tratar como exibí-las ao usuário final.

Este processo é importante por três motivos:


Capítulo 14 Tratamento de Erros e Exceções - 143

• Exibir mensagens amigáveis ao usuário final

• Registrar erros para análise posterior

• Debugar em modo de desenvolvimento, com ou sem registro

O PHP, a partir de sua versão 5, possui duas formas de realizar o tratamento,


uma procedural e outra orientada a objeto.

O PHP 5 permite a configuração de quais tipos de erros serão exibidos.

Os erros são referenciados por constantes. Estas constantes estão


disponíveis em:
http://www.php.net/manual/pt_BR/errorfunc.constants.php

(Passe o link para os alunos, também está disponível nos links Depois da Aula)

Alguns erros são fatais, não podem ser capturados e impedem o uso do script.
Por exemplo, erros de sintaxe – entretanto, estes dificilmente chegam na aplicação
final.

Para o desenvolvimento, é sugerido o uso do E_ALL && E_STRICT.

• E_ALL: Todos erros e avisos, como suportado, exceto de nível E_STRICT no


PHP < 6.
• E_STRICT: Notícias em tempo de execução. Permite ao PHP sugerir
mudanças ao seu código as quais irão assegurar melhor interoperabilidade e
compatibilidade futura do seu código.
• Isto é feito com a diretiva error_reporting. Esta diretiva pode ser alterada
de duas formas:
• no arquivo php.ini
• em tempo de execução com a função error_reporting.
Capítulo 14 Tratamento de Erros e Exceções - 144

14.2.1. Função die

O PHP possui um comando que encerra o script, que é o exit. Ele permite
recebimento de um parâmetro, que é uma mensagem que será exibida ao encerrar o
script.

Historicamente, é mais comum o uso de seu “apelido”, o die. Diversos


comandos que exigem tratamento do tipo “fatal” são realizados com a expressão or
die('mensagem').

No exemplo do slide, a tentativa de conexão, quando não funcionar, vai gerar


o encerramento do script com a exibição do SQL que gerou o erro. Isto,
evidentemente é muito pouco elegante e dá informações excessivas ao usuário final
(aqui serve apenas como exemplo!).

Apesar de não ser uma forma muito elegante, é bastante utilizada,


especialmente em scripts antigos. Em scripts PHP para uso em linha de comando
podem ser um pouco mais adequados, mas em sistemas web seu uso deve ser evitado
em detrimento a um tratamento mais elaborado de erros, como visto a seguir.

Reforçando: como é um recurso que é encontrado em vários scripts, é


estudado aqui para o conhecimento dos alunos, mas seu uso não é incentivado.

14.2.2. Capturando e Gerando Erros

É possível “gerar” ou “disparar” um erro manualmente com a função


trigger_error. Ela gera um erro do tipo E_USER (ou, como segundo parâmetro,
qualquer de suas variantes E_USER_*).

Seu uso é normalmente em conjunto com uma função de tratamento


personalizado definida com a função set_error_handler. Esta função define uma
função personalizada que recebe automaticamente os erros gerados pelo sistema ou
então erros manuais gerados pela função trigger_error.

A função personalizada recebe automaticamente quatro parâmetros:


Capítulo 14 Tratamento de Erros e Exceções - 145

• errno = o número do erro, que corresponde ao código da constante E_*;


• errstr = o texto (string) com a mensagem de erro;
• errfile = o nome do arquivo onde ocorreu o erro;
• errline = a linha do arquivo onde ocorreu o erro.

Com estas informações é possível montar uma mensagem personalizada, ou


até registrar em arquivo, como veremos em seguida.

14.2.3. Registro de Erros (Log)

A função error_log permite realizar o “log” ou “registro” de um erro. Esta


função permite três métodos:

• 0 – syslog: registro no log padrão do sistema (syslog no Linux, por exemplo);


• 1 – email: envio de um email com a função mail do PHP;
• 3 – adicionar a arquivo: utilizando um arquivo personalizado para gravar o
registro.
• Da mesma forma que a função personalizada de tratamento de erro definida
pela função set_error_handler, também recebe quatro parâmetros:
• errno = o número do erro, que corresponde ao código da constante E_*;
• errstr = o texto (string) com a mensagem de erro;
• errfile = o nome do arquivo onde ocorreu o erro;
• errline = a linha do arquivo onde ocorreu o erro.
Capítulo 14 Tratamento de Erros e Exceções - 146

14.2.4. Configurando o php.ini

Algumas sugestões para ambiente de desenvolvimento (para produção, o


contrário).
As informações que seguem são da documentação do PHP em:
http://br.php.net/manual/pt_BR/errorfunc.configuration.php

display_errors = On
Isto determina quando os erros devem ser mostrados como parte da saída
ou se devem ser escondidos do usuário.
display_startup_errors = On
Mesmo quando display_errors esta em on, erros que aconteçam durante a
inicialização do PHP não são mostrados. É fortemente recomendado manter
display_startup_errors em off, exceto para procurar erros.
error_reporting = E_ALL | E_STRICT
Define o nível de erros para reportar. (já visto anteriormente).
log_errors = On
Indica se as mensagens de erro do script devem ficar no log de erros do
servidor ou em error_log. Esta opção depende do servidor.
track_errors = On
Se ativado, a última mensagem de erro sempre estará disponível na variável
$php_errormsg. (ou seja, é possível recuperar o último erro apenas com a
manipulação desta variável).
Capítulo 14 Tratamento de Erros e Exceções - 147

14.3. Tratamento de Exceções

Esta forma de tratamento de erros está disponível para as extensões


(bibliotecas) modernas do PHP 5 que são orientadas a objeto.

Ou seja:

• funções usam o ERROR REPORTING


• extensões modernas usam Exceptions

Exception é um modo de retornar um erro sob a forma de um objeto. É


possível inclusive extender a classe padrão do PHP e criar erros personalizados.

O uso mais simples e comum de Exceptions é a sua captura para tratamento


personalizado. Isto é feito através de uma sintaxe try...catch, onde um código é
executado num bloco try e se ele gerar uma Exception, esta é capturada e tratada no
bloco catch.

14.3.1. Métodos

Com dos métodos da classe Exception é possível personalizar o tratamento


de erros. A classe Exception possui mais informações que a mensagem de erro
padrão do PHP, por isto é mais útil para debug.

Além da mensagem, código do erro, arquivo e linha onde ocorreu o erro, o


classe também possui o TRACE, que mostra todos os arquivos que foram chamados
até o acontecimento do erro. Isto permite “rastrear” (realizar o “trace”) o erro, saber
de onde veio, todo caminho até ele – e isto é muito útil no debug.

getMessage – Obtém a mensagem da exceção


getCode – Obtém o código da exceção
getFile - Obtém o arquivo na qual a exceção ocorreu
getLine – Obtém a linha na qual a exceção ocorreu
getTrace – Obtém a stack trace como um array
getTraceAsString – Obtém a stack trace como uma string
Capítulo 14 Tratamento de Erros e Exceções - 148

Capítulo 15

Construindo uma classe de acesso a

dados

15.1. Objetivos

• Construir classes de abstração de dados.

• Manipular os dados abstraídos.

• Executar ações no banco de dados.


Capítulo 15 Construindo uma classe de acesso a dados - 149

Neste capítulo construiremos uma classe para facilitar nosso trabalho de


acesso às tabelas de nosso banco de dados.

Mas antes vamos criar uma nova estrutura de diretórios, já pensando em


nosso projeto. Como root execute:

# cd /var/www
# mkdir livraria
# cd livraria
# mkdir admin imagens intro site classes imagensLivros templates

Os diretórios criados terão a seguinte utilidade

• admin: área administrativa do website


• imagens: imagens gerais, ícones utilizados no website
• intro: área de testes iniciais
• site: o website em si
• classes: arquivos de classes
• imagensLivros: imagens dos livros armazenados
• templates: templates HTML de nosso site

Todas as classes serão criadas no diretório correspondente.

15.2. Porque uma classe Tabela?

No capítulo sobre o MySQL vimos que existem quatro operações muito


comuns em uma tabela: selecionar, atualizar, inserir e excluir. O problema é que
precisamos escrever um código personalizado para cada tabela do banco. Se forem 3
ou 4, tudo bem, mas e se forem 150? Para isso, criaremos uma classe abstrata
chamada Tabela, que servirá de base para classes de nosso banco de dados.

Esta não poderá ser utilizada diretamente, pois só será possível definindo
valores para seus atributos básicos.
Capítulo 15 Construindo uma classe de acesso a dados - 150

15.3. Construindo a classe tabela

15.3.1. config.inc.php – arquivo de


configuração

Primeiro, vamos criar o arquivo de configuração de acesso ao banco de dados


e debug: /var/www/livraria/config.inc.php

928 <?php
929 /*
930 * Configurações de acesso ao banco de dados
931 */
932

933 $bdconfig['driver'] = 'mysql'; // Servidor de Banco


de Dados
934 $bdconfig['servidor'] = 'localhost'; // Servidor de Banco
de Dados
935 $bdconfig['usuario'] = 'livrariaUser'; // Usuário de acesso
936 $bdconfig['senha'] = '123456'; // Senha de acesso
937 $bdconfig['banco'] = 'livraria'; // Banco
938 $bdconfig['opcoes'] = array(PDO::MYSQL_ATTR_INIT_COMMAND =>
"SET NAMES utf8"); // Opções do Driver
939

940 // Ativa visualização de consultas SQL


941 $debugBanco = false;
942

943 // Variável de DEBUG


944 $DEBUG = array();
945

946 // Arquivo de log


947 $CONFIG['arquivo_log'] = '/var/www/livraria/livraria.log';
948

949 // Função autoload para carga automática de Classes


950 function __autoload($classe) {
Capítulo 15 Construindo uma classe de acesso a dados - 151

951 include_once("classes/{$classe}.class.php");
952 }

As configurações de banco ficam na variável $bdconfig.

Opções de debug serão ativadas com as variáveis $debugBanco e $DEBUG,


sendo que esta última é inicializada com um array vazio.

Também é configurado um arquivo de log numa variável em array $CONFIG,


que pode ser utilizada futuramente para armazenar outras configurações do sistema.

Ao final, para não precisar de outro arquivo, foi definida a função __autoload,
para carga automática de classes. Desta forma, este é o único arquivo a ser incluído
para funcionamento básico do sistema.

É preciso, evidentemente, criar o banco de dados. Utilizaremos o conteúdo do


anexo Banco de Dados do Projeto.

15.3.2. Atributos da Classe Tabela

Agora faremos a construção por partes, para facilitar. Vamos criar o arquivo
/var/www/livraria/classes/Tabela.class.php e definir os atributos :

953 <?php
954 /*
955 Classe Abstrata Tabela
956 */
957 abstract class Tabela {
958

959 // conexao sera compartilhada entre todas as instâncias


960 private static $conexao;
961

962 // nome da tabela


963 protected $tabela;
964

965 // chave primária da tabela


Capítulo 15 Construindo uma classe de acesso a dados - 152

966 protected $chavePrimaria;


967

968 // Array com lista de campos da tabela


969 protected $campos = array();
970

971 // Array com lista de campo=>legenda


972 protected $legendas = array();
973 }

Todo os atributos são protegidos, pois não queremos que o usuário final tenha
acesso aos valores, a não ser de modo controlado (getters e setters).

Entretanto, temos um atributo static, pois queremos que ele se mantenha


entre as instâncias da classe. Isto é importante, como veremos a seguir no
construtor, para que só tenhamos uma instância da conexão para todas os objetos
Tabela instanciados (através de suas classes filhas).

Alguns métodos só farão sentido quando formos utilizar a tabela, então, mais
adiante os compreenderemos.

15.3.3. Construtor

Agora criamos o construtor que tem a função conectar ao banco de dados.


Note que o atributo conexão é estático, para ser compartilhado entre todas as tabelas
abertas. Ele vai checar se não existe conexão aberta, e utilizando a palavra chave
global acessa a variável $bdconfig, que definimos no arquivo config.inc.php.

Observação: tenha cuidado de incluir os conteúdos adicionais que seguem


sempre ANTES da chave de fechamento final da classe, senão ele torna-se
uma função comum, não pertencente à classe!!!

974 /*
975 * Método construtor
976 * Se conexão não existir, cria, senão, nada a fazer
Capítulo 15 Construindo uma classe de acesso a dados - 153

977 * (reutiliza a criada por outra instância da classe Tabela )


978 */
979 public function __construct() {
980

981 // Recuperando array com configuração de acesso


982 global $bdconfig;
983

984 // Testando se já está definido atributo estático


985 // $conexao. Se não estiver, então realiza a conexão
986 // (se já estiver... não precisa fazer de novo)
987 if (!isset(self::$conexao)) {
988

989 // Montando Data Source Name no formato:


990 // "mysql:host=localhost;dbname=banco";
991 $dsn =
"{$bdconfig['driver']}:host={$bdconfig['servidor']};dbname={$bdco
nfig['banco']}";
992

993 // Usando tratamento de exceção para capturar possível


erro
994 try
995 {
996 // Realizando conexão e armazenando em constante
997 self::$conexao = new PDO($dsn,
998 $bdconfig['usuario'],
999 $bdconfig['senha'],
1000 $bdconfig['opcoes']);
1001 } catch (PDOException $e) {
1002

1003 // Montando mensagem de erro


1004 $erro = '<h1>Erro:</h1><pre>' . $e->getMessage() .
"\n" .
1005 $e->getTraceAsString() . '</pre>' . "\n";
1006

1007 // Gravando erro no log


1008 error_log(date('Y-m-d H:i:s') . " - " . $erro, 3,
Capítulo 15 Construindo uma classe de acesso a dados - 154

$GLOBALS['CONFIG']['arquivo_log']);
1009

1010 // Exibindo erro para o usuário e encerrando script


1011 die($erro);
1012 }
1013 }
1014

1015 } // function __construct

Aqui são utilizados vários conceitos já estudados. Vejamos:

• Linha 9: uso da palavra chave global para ter acesso a uma variável fora do
escopo da função/método, e recuperar as informações do arquivo de
configuração.
• Linha 14: uso do isset com negação (!) no teste lógico, para verificar se a
variável NÃO está definida, e uso do escopo self:: para acessar uma
variável estática da classe;
• Linha 18: montagem do Data Source Name para conexão com a biblioteca
PDO utilizando a variável de configuração importada para o escopo do
método com a palavra chave global;
• Linha 21: utilizando o tratamento de exceção com o try...catch;
• Linha 24: a conexão em si. Notar que é armazenada estaticamente, para
estar disponível para outras instâncias da classe – na segunda instância, este
bloco condicional não é executado, pois a variável já está definida – ver linha
14;
• Linhas 30 a 41: gerando uma mensagem de erro para o usuário final e
gravando no arquivo de log definido na configuração. O uso do método
getTraceString facilita o rastreio do erro.

15.3.4. Um getter automático

Vamos precisar recuperar alguns atributos da classe, mas eles são protegidos.
Então utiliza-se o método mágico __get. Note que não nos interessa setters, pois não
permitiremos alterações, apenas leitura dos atributos.

1016 /*
1017 * Método mágico __get
Capítulo 15 Construindo uma classe de acesso a dados - 155

1018 * Para recuperar atributos


1019 * Note que não interessa implementar o __set!!
1020 */
1021 public function __get($var) {
1022

1023 return $this->$var;


1024

1025 } // function __get

15.3.5. Método para execução de consultas

O próximo método é o query, que centraliza a execução de consultas do


banco. Se o debug estiver ativo, exibe a consulta; isto é útil para termos certeza do
que está acontecendo. Se houver erro de sinxate, haverá log do erro e poderemos
definir se o erro será fatal ou não.

1026 /*
1027 * Método query
1028 * Executa uma consulta através da conexão estabelecida
1029 * Verifica se o debug está ativo
1030 * (variável $debugBanco=true em config.inc.php)
1031 * Retorna um objeto com o resultado da consulta
1032 */
1033 public function query($sql)
1034 {
1035 global $debugBanco;
1036

1037 // Se debug ativado, exibe SQL na tela


1038 if ($debugBanco) $GLOBALS['debugBanco'] .=
"<pre>$sql</pre><hr>";
1039

1040 // Usando tratamento de exceção para capturar possível


erro
1041 try
Capítulo 15 Construindo uma classe de acesso a dados - 156

1042 {
1043 // Define o método pelo pelos primeiros caracteres =
SELECT ou select
1044 $type = substr($sql, 0, 6);
1045

1046 // Se for SELECT utiliza o método query do PDO


1047 if ($type == 'SELECT' || $type == 'select') {
1048

1049 $resultado = self::$conexao->query($sql);


1050

1051 // Senão utiliza o método exec do PDO


1052 } else {
1053

1054 $resultado = self::$conexao->exec($sql);


1055

1056 }
1057

1058 return $resultado;


1059

1060 } catch (PDOException $e) {


1061

1062 // Montando mensagem de erro


1063 $erro = '<h1>Erro:</h1><pre>' . $e->getMessage() .
"\n" .
1064 $e->getTraceAsString() . '</pre>' . "\n";
1065

1066 // Gravando erro no log


1067 error_log(date('Y-m-d H:i:s') . " - " . $erro, 3,
$GLOBALS['CONFIG']['arquivo_log']);
1068

1069 // Opção de erro fatal


1070 die($erro);
1071

1072 // Opção de erro silencioso


1073 // return false;
1074

1075 }
Capítulo 15 Construindo uma classe de acesso a dados - 157

1076

1077 } // function query

• Linha 13: se o debug está ativo, então inclui no elemento ['debugBanco']


do array $DEBUG a string de SQL para posterior exibição; isto é feito com a
variável superglobal $GLOBALS;
• Linha 19: retirando os primeiro 6 caracteres da consulta para posterior
comparação com a função substr;
• Linha 22: comparando para saber se a consulta é SELECT. Isto é necessário
por que o PDO possui métodos diferentes para SELECT e para outros tipos
de consulta (como INSERT, DELETE e UPDATE);
• Linhas 24 e 29: executando a consulta com os métodos query ou exec,
conforme o tipo definido na condição da linha 22;
• Linha 33: retornando o resultado, que pode ser um objeto com um conjunto
de registros (no caso de select) ou a quantidade de linhas afetadas (no caso
de INSERT, DELETE e INSERT);
• No caso de erro na consulta, será gravado no log, mas o código permite que
o programador opte por dois comportamentos: erro fatal ou apenas log. Isto
não está parametrizado, ou seja, comenta-se um código e libera-se o outro. O
return false permite que seja usado este método como condição.

15.3.6. Listando (SELECT) registros

O método listar realiza selecão de registros. Ele pode opcionalmente solicitar


um filtro (cláusula WHERE), uma ordem (clásula ORDER BY) e um limitador de
registros retornados (cláusula LIMIT).

1078 /*
1079 * Método listar
1080 * Executa uma consulta na tabela, podendo:
1081 * - Recebe (opcionalmente) filtro em formato SQL
1082 * - Recebe (opcionalmente) ordem em formato SQL
1083 * - Recebe (opcionalmente) limite em formato MySQL
1084 * Retorna um objeto com o resultado da consulta
1085 */
1086 public function listar ($filtro=null, $ordem=null,
Capítulo 15 Construindo uma classe de acesso a dados - 158

$limite=null){
1087

1088 // Monta consulta concatenando tabela


1089 $sql = "SELECT * FROM " . $this->tabela;
1090

1091 // Se foi enviado filtro, concatena filtro


1092 if (!is_null($filtro)) { $sql .= " WHERE $filtro";}
1093

1094 // Se foi enviado ordem, concatena ordem


1095 if (!is_null($ordem)){ $sql .= " ORDER BY $ordem";}
1096

1097 // Se foi enviado limite, concatena limite


1098 if (!is_null($limite)){ $sql .= " LIMIT $limite";}
1099

1100 // Retorna objeto com o resultado encontrado


1101 return $this->query($sql);
1102

1103 } // function listar

Este método utiliza três parâmetros opcionais. Realiza um SELECT na tabela


(através do atributo $this->tabela) .

Os parâmetros opcionais recebem as sintaxes do WHERE, ORDER BY e LIMIT.


Se forem informados (ou seja, diferentes de null).

Este método faz uso do método query, que já foi visto.

A sintaxe do LIMIT utilizada é o padrão do MySQL. Isto limita seu uso a


este banco. Para não tornar o exemplo extenso, não se fez um tratamento
desta situação.
O ideal seria testar com switch o driver de banco de dados utilizado (por
exemplo checando a variável $bdconfig['driver'] ou então com o método
self::$conexao->getAttribute(PDO::ATTR_DRIVER_NAME)) e realizar a
sintaxe adequada.
Capítulo 15 Construindo uma classe de acesso a dados - 159

15.3.7. Recuperando um registro pela chave


primária

O método listarPorChave é extremamente útil: retorna um registro pela sua


chave primária.

1104 /*
1105 * Método listarPorChave
1106 * Executa uma consulta filtrando pela chave primária da
tabela
1107 * Recebe um valor que é um id de um registro
1108 * Retorna um objeto com o registro
1109 */
1110 public function listarPorChave ($chave){
1111

1112 // Executa consulta


1113 $resultado = $this->listar($this->chavePrimaria . " =
'$chave'");
1114

1115 // Retorna objeto com o registro encontrado


1116 return $resultado->fetchObject();
1117

1118 } // function listarPorChave

Ele é facilmente implementado, pois a classe possui o atributo chavePrimaria,


e então solicita o valor de uma chave e reutiliza o método listar para recuperar um
único registro. Para facilitar a utilização, já faz o "fecth" para retornar um único
registro em forma de objeto.
Capítulo 15 Construindo uma classe de acesso a dados - 160

15.3.8. Excluindo um registro pela chave


primária

O método excluir também atua através de uma chave primária, o que


implementa uma segurança, evitando riscos de exclusão de muitos registros
simultaneamente.

1119 /*
1120 * Método excluir
1121 * Exclui um registro filtrando pela chave primária da
tabela
1122 * Recebe um id de um registro
1123 * Retorna um objeto com o resultado
1124 */
1125 public function excluir ($chave){
1126 // Monta consulta concatenando tabela, campo que é chave
primária e o valor enviado
1127 $sql = "DELETE FROM " . $this->tabela . "
1128 WHERE " . $this->chavePrimaria . " = '$chave'";
1129

1130 // Retorna objeto com o resultado encontrado


1131 return $this->query($sql);
1132

1133 } // function excluir

O método excluir é quase autoexplicativo, também utiliza o mesmo conceito


do método listarPorChave, mas monta o SQL e executa através do método query.
Capítulo 15 Construindo uma classe de acesso a dados - 161

15.3.9. Inserindo um registro

O método inserir é extremamente prático: recebe como entrada um array


contendo um par nome_do_campo => valor., como no exemplo:

1134 $dadosInserir = array(


1135 'nome' => 'Miguel Barbosa',
1136 'email' => 'miguel@teste.com.br',
1137 'data_nascimento' => '1983-10-07',
1138 );

É o que normalmente recebe-se num POSTs de formulários - por isto sua


praticidade.

1139 /*
1140 * Método inserir
1141 * Insere um registro
1142 * Recebe um array que contém itens no formato $campo =>
$valor
1143 * (um $_POST de formulário é uma boa opção)
1144 * Retorna um objeto com o resultado
1145 */
1146 public function inserir ($dados){
1147

1148 // Usando tratamento de exceção para capturar possível


erro
1149 try
1150 {
1151 // Testando se é um array, ou abortando;
1152 if(!is_array($dados)) {
1153 throw new Exception('Esperado um Array para Inserir
Registro');
1154 };
1155
Capítulo 15 Construindo uma classe de acesso a dados - 162

1156 } catch (Exception $e) {


1157

1158 // Montando mensagem de erro


1159 $erro = '<h1>Erro:</h1><pre>' . $e->getMessage() .
"\n" .
1160 $e->getTraceAsString() . '</pre>' . "\n";
1161

1162 // Gravando erro no log


1163 error_log(date('Y-m-d H:i:s') . " - " . $erro, 3,
$GLOBALS['CONFIG']['arquivo_log']);
1164

1165 // Exibindo erro para o usuário e encerrando script


1166 die($erro);
1167

1168 }
1169

1170 // Monta consulta concatenando tabela


1171 $sql = "INSERT INTO " . $this->tabela . " (";
1172

1173 // Varre array $dados e atribui $key => $value


1174 // com campo e valor
1175 foreach ($dados as $campo => $valor)
1176 {
1177

1178 // concatena o campo para montar a primeira parte do


INSERT
1179 $campos .= "$campo,";
1180

1181 // concatena o valor para montar a segunda parte do


INSERT
1182 $valores .= "'$valor',";
1183

1184 }
1185

1186 // Elimindo última vírgula e finalizando


1187 $sql .= substr($campos,0,-1) . ") VALUES (";
Capítulo 15 Construindo uma classe de acesso a dados - 163

1188 $sql .= substr($valores,0,-1) . ")";


1189

1190 // Total de registros inseridos (0 ou 1)


1191 return $this->query($sql);
1192

1193 } // function inserir

• Para evitar falha por tentativa de utilizar o foreach em uma string (pois tem
que receber um array) então capturou-se uma exceção com o try...catch
entre as linhas 10 e 30;
• Linha 10: teste lógico com o is_array negado (!) para verificar se a variável
enviada $dados é realmente um array, se não for dispara uma exceção;
• Linha 37: o "pulo do gato" do método, varre o array com dados e concatena
separadamente o nome do campo e o valor, para montar as duas partes do
INSERT;
• Linhas 49 e 50: com o substr retira-se a vírgula excedente na lista de
campos e valores;

Colocar todos valores entre aspas simples funciona no MySQL mas pode
causar erro em outros bancos de dados. Isto limita seu uso a este banco.
Para não tornar o exemplo extenso, não se fez um tratamento desta
situação.
O ideal seria testar com switch o driver de banco de dados utilizado (por
exemplo checando a variável $bdconfig['driver'] ou então com o método
self::$conexao->getAttribute(PDO::ATTR_DRIVER_NAME)) e realizar a
sintaxe adequada.

15.3.10. Atualizando um registro

De mesmo modo, o método atualizar também recebe um array com pares


nome_do_campo => valor, mas também a chave primária do registro a ser
atualizado. Outro método extremamente útil.

1194 /*
1195 * Método atualizar
1196 * Atualiza um registro filtrando pela chave primária
Capítulo 15 Construindo uma classe de acesso a dados - 164

1197 * Recebe um array que contém itens no formato $campo =>


$valor
1198 * (um $_POST de formulário é uma boa opção)
1199 * Recebe um id de um registro
1200 * Retorna um objeto com o resultado
1201 */
1202 public function atualizar ($chave, $dados){
1203

1204 // Usando tratamento de exceção para capturar possível


erro
1205 try
1206 {
1207 // Testando se é um array, ou abortando;
1208 if(!is_array($dados)) {
1209 throw new Exception('Esperado um Array para Inserir
Registro');
1210 };
1211

1212 } catch (Exception $e) {


1213

1214 // Montando mensagem de erro


1215 $erro = '<h1>Erro:</h1><pre>' . $e->getMessage() .
"\n" .
1216 $e->getTraceAsString() . '</pre>' . "\n";
1217

1218 // Gravando erro no log


1219 error_log(date('Y-m-d H:i:s') . " - " . $erro, 3,
$GLOBALS['CONFIG']['arquivo_log']);
1220

1221 // Exibindo erro para o usuário e encerrando script


1222 die($erro);
1223

1224 }
1225

1226 // Monta consulta concatenando tabela


1227 $sql = "UPDATE " . $this->tabela. " SET ";
Capítulo 15 Construindo uma classe de acesso a dados - 165

1228

1229 // Varre array $dados e atribui $key => $value


1230 // com campo e valor
1231 foreach ($dados as $campo => $valor)
1232 {
1233

1234 // concatena o campo e valor para montar atualização do


campo
1235 $sql .= "$campo = '$valor',";
1236

1237 }
1238

1239 // Eliminando última vírgula


1240 $sql = substr($sql,0,-1);
1241

1242 // Monta restante da condição concatenando campo que é


chave primária e o valor enviado
1243 $sql .= " WHERE " . $this->chavePrimaria . " = '$chave'";
1244

1245 // Total de registros atualizados (0 ou 1)


1246 return $this->query($sql);
1247

1248 } // function atualizar

A lógica do método atualizar é semelhante ao do método inserir, apenas


trocando a sintaxe do SQL, e a recebendo também a chave primária, com a qual se
filtrará o registro como consta na linha 50.
Capítulo 15 Construindo uma classe de acesso a dados - 166

15.4. Criando um CRUD

15.4.1. O que é um CRUD?

CRUD é o acrônimo da expressão em língua Inglesa Create, Retrieve,


Update e Delete, usada para definir quatro operações básicas usadas em
bancos de dados relacionais (RDBMS) ou em interface para usuários para
criação, consulta, atualização e destruição de dados.
Fonte: http://pt.wikipedia.org/wiki/CRUD

Boa parte do trabalho "braçal" numa aplicação é CRUD. Por isto, nossa classe
tabela foi criada para facilitar a geração de um CRUD

15.4.2. Criando as classes filhas

Esta parte é bastante mecânica, pois o trabalho "bruto" foi feito pela classe
Tabela. Se não formos utilizar legendas, a criação de classes filhas é muito simples,
bastando extender a classe Tabela e informar os atributos $tabela e
$chavePrimaria:

1249 <?php
1250 class Categoria extends Tabela {
1251 protected $tabela = 'categoria';
1252 protected $chavePrimaria = 'id';
1253 }
1254 ?>

Mas para um uso completo, incluindo a possibilidade de montar


automaticamente formulários e tabelas, é preciso ter a listagem dos campos e
legendas. Na sequência um exemplo com a tabela Categoria, criado no arquivo
/var/www/livraria/classes/Categoria.class.php (para ser automaticamente
carregada pela função __autoload):
Capítulo 15 Construindo uma classe de acesso a dados - 167

1255 <?php
1256

1257 class Categoria extends Tabela {


1258

1259 protected $tabela = 'categoria';


1260 protected $chavePrimaria = 'id';
1261 protected $campos = array('id', 'descricao');
1262 protected $legendas = array(
1263 'id'=>'ID',
1264 'descricao'=>'Categoria'
1265 );
1266 }

15.4.3. Adicionando um método específico à


classe

Uma das características da Herança é que permite que uma classe filha tenha
novos métodos, utilizando-se das facilidade da classe pai.

Por exemplo, vamos criar um método que já traz as categorias em ordem


alfabética.

Inclua o método na classe Categoria:

1267 public function listarAlfabetico() {


1268

1269 return $this->listar(null,'descricao');


1270

1271 }

Que nada mais faz que executar o método listar com um parâmetro para para
ordenação.
Capítulo 15 Construindo uma classe de acesso a dados - 168

15.4.4. Exemplo de uso

O conjunto de arquivos a seguir demonstra como utilizar as classes. Serão


gravados no diretório intro.

Eles criam uma interface chamada de CRUD: Create, Retrieve, Update e


Delete, ou seja, Criar, Recuperar, Atualizar e Excluir.

Já possuímos um arquivo de configuração com o __autoload, então, basta


incluí-lo para termos acesso a todas as classes.

A página inicial é a listagem das categorias em Arquivo


/var/www/livraria/intro/index.php, acessível através da URL :

http://localhost/livraria/intro

A partir dela é possível editar ou excluir um registro da tabela.

1272 <?php
1273 /*
1274 index.php
1275 Lista Categorias
1276 */
1277

1278 // Incluindo arquivo de configuração


1279 include_once('../config.inc.php');
1280

1281 // Criando nova instância da classe Categoria


1282 $tabCategoria = new Categoria;
1283

1284 // Listando categorias com o método listar


1285 $categorias = $tabCategoria->listar();
1286

1287 // Link para inserção de registro


1288 echo '<a href="inserirCategoria.php?id='.$categoria-
>id.'">Nova Categoria</a>';
1289

1290 // Iniciando tabela utilizando legendas da classe Categoria


Capítulo 15 Construindo uma classe de acesso a dados - 169

1291 echo '<table>


1292 <tr>
1293 <th>Ação</th>
1294 <th>'. $tabCategoria->legendas['id'] .'</th>
1295 <th>'. $tabCategoria->legendas['descricao'] .'</th>
1296 </tr>
1297 ';
1298

1299 // Realizando laço com resultado


1300 // Enquanto a atribuição for verdadeira, executa código
1301 // método fetchObject recupera cada registro
1302 // em forma de objeto
1303 while ($categoria = $categorias->fetchObject()) {
1304

1305 // Montando a linha da tabela com link para edição e


exclusão
1306 echo '
1307 <tr>
1308 <td>
1309 <a href="editarCategoria.php?id='.$categoria-
>id.'">editar</a> -
1310 <a href="excluirCategoria.php?id='.$categoria-
>id.'">excluir</a>
1311 </td>
1312 <td>
1313 '.$categoria->id.'
1314 </td>
1315 <td>'.$categoria->descricao.'</td>
1316 </tr>
1317 ';
1318

1319 }
1320

1321 echo '</table>';


Capítulo 15 Construindo uma classe de acesso a dados - 170

O arquivo de edição cria um formulário e carrega um registro baseado em sua


chave primária. O mesmo arquivo é destino do formulário, e então uma condição
testa se um campo do formulário foi enviado, quando então realiza o salvamento.

Este é o arquivo /var/www/livraria/intro/editarCategoria.php

1322 <?php
1323 /*
1324 editarCategoria.php
1325 Exibe registro para edição
1326 Realiza atualização em Banco
1327 */
1328

1329 // Incluindo arquivo de configuração


1330 include_once('../config.inc.php');
1331

1332 // Criando nova instância da classe Categoria


1333 $tabCategoria = new Categoria;
1334

1335 // Verificando o método de envio (POST) e se existe uma


variável
1336 // Então considera o formulário enviado
1337 if ($_SERVER['REQUEST_METHOD'] == 'POST' &&
isset($_POST['id'])) {
1338

1339 // Se é envio do formulário,


1340 // então recupera via POST o id
1341 $id = $_POST['id'];
1342

1343 // Executando consulta de atualização


1344 if ($tabCategoria->atualizar($id, $_POST)) {
1345

1346 // Tudo bem, retornou um registro atualizado


1347 echo '<h2>Registro Salvo</h2>';
1348

1349 } else {
Capítulo 15 Construindo uma classe de acesso a dados - 171

1350

1351 // Erro, ou houve falha no SQL


1352 // ou nada foi atualizado.
1353 echo "<h2>ERRO ao salvar Registro ou sem alteração</h2>";
1354

1355 }
1356

1357 } else {
1358

1359 // Se não é envio do formulário,


1360 // então recupera via GET o id
1361 $id = $_GET['id'];
1362

1363 }
1364

1365 // Link para retornar à listagem


1366 echo '<a href="index.php">Voltar</a>';
1367

1368 // Recuperando o registro com método listarPorChave


1369 $registro = $tabCategoria->listarPorChave($id);
1370

1371 // Iniciando formulário e enviado para o mesmo arquivo


1372 echo '
1373 <form action="editarCategoria.php" method="post" >
1374 ';
1375

1376 // Recuperando cada campo em loop


1377 // atribuindo às variáveis $campo e $valor
1378 // para montar dinamicamente formulário
1379 foreach ($registro as $campo => $valor)
1380 {
1381 // Recuperando legenda do campo
1382 echo $tabCategoria->legendas[$campo].': '.
1383 '<input type="text" name="'.$campo.'"'.
1384 ' value="'.$valor.'" /><br/>' . "\n";
1385 }
Capítulo 15 Construindo uma classe de acesso a dados - 172

1386

1387 // Encerrando o formulário com um botão Salvar


1388 echo '
1389 <button type="submit">Salvar</button>
1390 </form>
1391 ';

O arquivo de inclusão é bastante parecido com o de edição, mas mostra um


formulário vazio. Com o seu envio, ele insere o registro no banco utilizando o recurso
da classe Tabela.

Este é o arquivo /var/www/livraria/intro/inserirCategoria.php

1392 <?php
1393 /*
1394 inserirCategoria.php
1395 Insere um novo registro em Banco
1396 */
1397

1398 // Incluindo arquivo de configuração


1399 include_once('../config.inc.php');
1400

1401 // Criando nova instância da classe Categoria


1402 $tabCategoria = new Categoria;
1403

1404 // Verificando o método de envio (POST) e se existe uma


variável
1405 // Então considera o formulário enviado
1406 if ($_SERVER['REQUEST_METHOD'] == 'POST' &&
isset($_POST['descricao'])) {
1407

1408 // Executando consulta de inserção


1409 if ($tabCategoria->inserir($_POST)) {
1410

1411 // Tudo bem, retornou um registro incluído


1412 echo '<h2>Registro Salvo</h2><a
href="index.php">Voltar</a>';
Capítulo 15 Construindo uma classe de acesso a dados - 173

1413

1414 } else {
1415

1416 // Erro, ou houve falha no SQL


1417 // ou nada foi atualizado.
1418 echo "<h2>ERRO ao salvar Registro ou sem alteração</h2>";
1419

1420 }
1421

1422 } else {
1423

1424 ?>
1425 <form action="inserirCategoria.php" method="post" >
1426 Descrição: <input type="text" name="descricao" value=""
/><br/>
1427 <button type="submit">Salvar</button>
1428 </form>
1429

1430 <?php
1431 }

O arquivo de exclusão, para evitar acidentes, pede confirmação para excluir.


Então envia a solicitação para ele mesmo, com uma variável a mais de confirmação,
para só então realizar a exclusão.

Arquivo /var/www/livraria/intro/excluirCategoria.php ;

1432 <?php
1433 /*
1434 excluirCategoria.php
1435 Exclui um registro
1436 */
1437

1438 // Incluindo arquivo de configuração


1439 include_once('../config.inc.php');
1440 // Criando nova instância da classe Categoria
1441 $tabCategoria = new Categoria;
Capítulo 15 Construindo uma classe de acesso a dados - 174

1442

1443 // Verificando se foi enviado o id e confirmação (ok)


1444 if($_GET['id'] && $_GET['ok']) {
1445

1446 // Executando consulta de exclusão


1447 if ($tabCategoria->excluir($_GET['id'])) {
1448

1449 // Tudo bem, retornou um registro incluído


1450 echo '<h2>Categoria excluída com sucesso</h2><a
href="index.php">Voltar</a>';
1451

1452 } else {
1453

1454 // Erro, ou houve falha no SQL


1455 // ou nada foi excluído.
1456 echo '<h2>ERRO!! Exclusão não efetuada</h2><a
href="index.php">Voltar </a>';
1457

1458 }
1459

1460 } else {
1461

1462 // Solicitação de exclusão, então vamos recuperar o registro


1463 $categoria = $tabCategoria->listarPorChave($_GET['id']);
1464

1465 // Montando links SIM / NÃO


1466 echo '
1467 <h2>Confirma exclusão da categoria?</h2>
1468 <h3>' . $categoria->id . ' - ' . $categoria->descricao .
'</h3>
1469 <a href="index.php">NÃO</a>
1470 <a href="excluirCategoria.php?id=' . $categoria-
>id .'&ok=1">SIM</a>
1471 ';
1472

1473 }
Capítulo 15 Construindo uma classe de acesso a dados - 175

Capítulo 16

Separando HTML do PHP: Classe

Template

16.1. Objetivo

• Organizar o código a tal modo que o HTML não interfira no desenvolvimento


puro do PHP.

• Facilitar a interação do WebDesigner com o Programador.


Capítulo 16 Separando HTML do PHP: Classe Template - 176

16.2. Introdução teórica

Um costume aplicações PHP antigas é a de misturar o código HTML com o


PHP em praticamente todos os arquivos. Este método "funciona", mas gera uma
dificuldade muito grande, por dois motivos:

• Interação complicada entre webdesigner e programador;

• Manutenção complicada pelo tamanho dos arquivos.

Aplicações modernas procuram separar o conteúdo do HTML do código PHP,


ou o que é chamado de lógica de apresentação da lógica de controle. O Design
Pattern MVC é um dos padrões que utiliza esta lógica. Mas antes do advento do MVC
já utilizavam conjuntos de classes ou bibliotecas de funções para separar estas
partes, num método chamado de templating.

Algumas destas ferramentas criam até uma linguagem própria para gerenciar
a lógica de apresentação.

Neste curso vamos sugerir um sistema de templating simples, para exercitar o


conhecimento adquirido.

Sua lógica é ter um diretório (templates) com arquivos HTML que contém
códigos de partes "lógicas" da página (cabecalho, rodape, menu, etc). O conteúdo
dinâmico é incluído com uso de um padrão de substituição: "variáveis" em formato
%VARIAVEL%.

Para dar acesso e garantir segurança na inclusão destes arquivos, será


utilizada uma classe Template, que será composta de métodos estáticos e fará a
substituição das variáveis.

Existe uma limitação: algumas ações como loops e condições não podem ser
incluídas no template. Mas o objetivo não é criar um sistema perfeito e sim exercitar
nosso conhecimento adquirido.
Capítulo 16 Separando HTML do PHP: Classe Template - 177

16.3. Classe Template: pegando e exibindo


arquivos de templates

Para garantir que os arquivos só serão incluídos a partir do diretório da


aplicação, vamos definir no arquivo config.inc.php uma variável para evitar acesso
indevido:

1474 $CONFIG['raiz_site'] = '/var/www/460livraria/';

E então segue o arquivo classes/Template.class.php:

1475 <?php
1476 /*
1477 Classe Template
1478 Responsável pela parte visual do sistema
1479 */
1480

1481 class Template {


1482

1483 const TEMPLATE_DIR = 'templates/';


1484

1485 /*
1486 * pegarArquivo
1487 * Pega um arquivo e faz a substituição de seu parâmetros
1488 * Método estático e privado, só pode ser utilizado
1489 * por outros métodos
1490 */
1491 static private function pegarArquivo($arquivo,
$parametros=array()) {
1492

1493 // Recuperando array de configuração


1494 // contido no arquivo config.inc.php
1495 global $CONFIG;
1496

1497 // Usando exceção para tratar erro de inclusão de arquivo


Capítulo 16 Separando HTML do PHP: Classe Template - 178

1498 try {
1499

1500 // Montando o diretório até o arquivo


1501 $dir = $CONFIG['raiz_site'] . self::TEMPLATE_DIR;
1502

1503 // Proteção contra XSS


1504 // retirando \, /, ..
1505 $arquivo = str_replace(
1506 array('\\','/','..'),
1507 array('','',''),
1508 $arquivo
1509 );
1510

1511 // Se o arquivo não existe, então dispara exceção


1512 if (!file_exists($dir.$arquivo )) {
1513

1514 throw new Exception("Template $arquivo não


existe.");
1515

1516 } else {
1517

1518 // Recuperando o arquivo para uma variável


1519 $conteudo = file_get_contents($dir.$arquivo);
1520

1521 // Testando se é um array, ou abortando;


1522 if(!is_array($parametros)) {
1523 throw new Exception('Esperado um Array para Inserir
Registro');
1524 }
1525

1526 // Passando por parâmetros para criar


1527 // arrays para substituição
1528 foreach ($parametros as $chave => $valor) {
1529

1530 $de[] = $chave;


1531 $para[] = $valor;
Capítulo 16 Separando HTML do PHP: Classe Template - 179

1532

1533 }
1534

1535 // Substituindo parâmetros


1536 $conteudo = str_replace($de, $para, $conteudo);
1537

1538 // Retornando conteúdo


1539 return $conteudo;
1540

1541 }
1542

1543 } catch (Exception $e) {


1544

1545 // Montando mensagem de erro


1546 $erro = '<h1>Erro:</h1><pre>' . $e->getMessage() .
"\n" .
1547 $e->getTraceAsString() . '</pre>' . "\n";
1548

1549 // Gravando erro no log


1550 error_log(date('Y-m-d H:i:s') . " - " . $erro, 3,
$GLOBALS['CONFIG']['arquivo_log']);
1551

1552 // Exibindo erro para o usuário e encerrando script


1553 die($erro);
1554

1555 }
1556

1557 }
1558

1559

1560 /*
1561 * exibirArquivo
1562 * Pega e dá saída um arquivo
1563 */
1564 static public function exibirArquivo($arquivo,
$parametros=array()) {
1565
Capítulo 16 Separando HTML do PHP: Classe Template - 180

1566 echo self::pegarArquivo($arquivo, $parametros);


1567

1568 }
1569 }

O código está comentado, mas vale ressaltar cuidados para evitar invasões,
em especial a retirada de carateres que possam montar um caminho forçado a um
arquivo que não esteja no diretório templates. Outra questão é a substituição das
variáveis do template, que é o "pulo do gato" da classe.

O método pegarArquivo é privado para evitar acesso direto; numa abordagem


em que esta classe pudesse ser extendida, ele deveria ser protegido.

O método exibirArquivo é utilizado para dar saída imediata a um arquivo.


Será muito utilizado por outros métodos.

Para compreender o uso da classe, é preciso criar alguns templates e métodos


para acessá-los. Veremos na sequência alguns exemplos.

Observação: os métodos da classe Template serão passados um a um, mas


tenha cuidado de incluir este conteúdos adicionais que seguem sempre
ANTES da chave de fechamento final da classe, senão ele torna-se uma
função comum, não pertencente à classe!!!

16.4. Cabecalho do Site Administrativo

Arquivo de template (templates/cabecalhoAdmin.html). O cabeçalho terá


todas informações até o início do bloco de conteúdo, inclusive os elementos div que
organizam a página.

1570 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
1571 <html xmlns="http://www.w3.org/1999/xhtml">
1572

1573 <head>
1574 <title>Livraria do Tux</title>
Capítulo 16 Separando HTML do PHP: Classe Template - 181

1575 <link rel="stylesheet" type="text/css"


href="../style.css" />
1576 </head>
1577 <body>
1578

1579 <div id="pagina">


1580

1581 <div id="cabecalho">


1582

1583 <h1>Livraria do Tux - Administração</h1>


1584

1585 <div style="clear:both"></div>


1586

1587 </div><!-- cabecalho -->

O método correspondente na classe Template é muito simples:

1588 /*
1589 * cabecalhoAdmin
1590 */
1591 static public function gerarCabecalhoAdmin() {
1592

1593 $arquivo = 'cabecalhoAdmin.html';


1594 $parametros = array();
1595 self::exibirArquivo($arquivo, $parametros);
1596

1597 }

Como todos os métodos são estáticos, é utilizada a palavra chave self seguida
do separador de escopo (::).
Capítulo 16 Separando HTML do PHP: Classe Template - 182

16.5. Cabeçalho do site público

Template (templates/cabecalhoSite.html):

1598 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
1599 <html xmlns="http://www.w3.org/1999/xhtml">
1600

1601 <head>
1602 <title>Livraria do Tux</title>
1603 <link rel="stylesheet" type="text/css"
href="../style.css" />
1604 </head>
1605 <body>
1606

1607 <div id="pagina">


1608

1609 <div id="cabecalho">


1610

1611 <div id="vercarrinho">


1612 Total de ítens = %CARRINHO_TOTAL_ITENS%<br />
1613 Valor total = R$ %CARRINHO_VALOR_TOTAL%<br />
1614 <a href="verCarrinho.php">ver carrinho</a>
1615 </div>
1616

1617 <h1>Livraria do Tux</h1>


1618

1619 <div style="clear:both"></div>


1620

1621 </div><!-- cabecalho -->

Neste template já temos duas variáveis a serem substituídas. Seu uso ficara
mais claro na construção do site público, mas seu método mostra como passar os
parâmetros para a exibição do template.

1622 /*
1623 * cabecalhoSite
Capítulo 16 Separando HTML do PHP: Classe Template - 183

1624 */
1625 static public function gerarCabecalhoSite() {
1626

1627 $arquivo = 'cabecalhoSite.html';


1628 $parametros = array(
1629 '%CARRINHO_TOTAL_ITENS
%'=>$_SESSION['itens'],
1630 '%CARRINHO_VALOR_TOTAL%'=>
1631 number_format($_SESSION['tota
l'],
1632 2 , ',', '.')
1633 );
1634 self::exibirArquivo($arquivo, $parametros);
1635

1636 }

16.6. Rodapé

Template (templates/rodape.html):

1637 <div style="clear:both"></div>


1638

1639 <div id="rodape">


1640 <h1>Todos os direitos reservados à Livraria do Tux</h1>
1641 </div><!-- rodape -->
1642

1643 </div><!-- pagina -->


1644 %DEBUG%
1645 </body>
1646 </html>

No rodapé será exibido DEBUG do sistema, que terá tudo que for enviado
para a variável $DEBUG definida inicialmente no arquivo config.inc.php e as
variáveis superglobais do PHP que são importantes para debugar o sistema.

Para que isto seja possível, veremos as alterações no arquivo config.inc.php:


Capítulo 16 Separando HTML do PHP: Classe Template - 184

1647 (...)
1648

1649 // Ativa debug


1650 $debug = true;
1651

1652 // Ativa visualização de consultas SQL


1653 $debugBanco = true;
1654

1655 // Variável de DEBUG


1656 $DEBUG = array();
1657

1658 (...)

Na classe Template então é criado o método correspondente ao arquivo


HTML:

1659 /*
1660 * rodape
1661 */
1662 static public function gerarRodape() {
1663

1664 $arquivo = 'rodape.html';


1665 $parametros = array(
1666 '%DEBUG%'=>self::debug()
1667 );
1668 self::exibirArquivo($arquivo, $parametros);
1669

1670 }

16.7. Abstração de listagem de registros.

Este método não faz utilização de templates, mas faz uma pequena abstração
de uma listagem dos registros de uma tabela. Isto só é possível porque as
informações sobre os campos e legendas estão disponíveis através das classes
extendidas de cada tabela.
Capítulo 16 Separando HTML do PHP: Classe Template - 185

1671 /*
1672 * método gerarTabela
1673 * Recebe o objeto Tabela, um resultado
1674 * e opcionalmente uma lista de campos para listar
1675 */
1676 static function gerarTabela($tabObj, $tabResult,
$campos=false) {
1677

1678 // Iniciando a tabela


1679 $conteudo = '
1680 <table border="1">
1681 <tr>
1682 <th>Ações</th>
1683 ';
1684

1685 // Se foi enviado a variável $campo


1686 // então monta cabeçalho somente com estes
1687 if ($campos) {
1688

1689 // Varrendo a lista de campos enviada


1690 foreach ($campos as $campo) {
1691

1692 // Montando legendas com


1693 // as informações do objeto Tabela
1694 $conteudo .= '
1695 <th>' . $tabObj->legendas[$campo] . '</th>
1696 ';
1697 }
1698

1699 } else {
1700 // Não foi enviada lista de campos
1701 // Varrendo as legendas do objeto Tabela
1702 foreach ($tabObj->legendas as $campo) {
1703

1704 $conteudo .= '


1705 <th>' . $campo . '</th>
Capítulo 16 Separando HTML do PHP: Classe Template - 186

1706 ';
1707 }
1708

1709 }
1710

1711 // Finalizando linha de cabeçalho


1712 $conteudo .= '
1713 </tr>
1714 ';
1715

1716 // Passando por registros


1717 // Usando o fetch em padrão ASSOCIATIVO
1718 while ($tabLinha = $tabResult->fetch(PDO::FETCH_ASSOC)) {
1719 // Montando ações (editar e excluir)
1720 // baseado no objeto Tabela
1721 $conteudo .= '
1722 <tr>
1723 <td>
1724 <a href="' . $tabObj->tabela . 'Editar.php?' .
$tabObj->chavePrimaria . "=" . $tabLinha[$tabObj-
>chavePrimaria] . '">
1725 <img src="../imagens/editar.png" alt="editar"
title="Editar"></a>
1726 <a href="' . $tabObj->tabela . 'Excluir.php?' .
$tabObj->chavePrimaria . "=" . $tabLinha[$tabObj-
>chavePrimaria] . '">
1727 <img src="../imagens/excluir.png" alt="excluir"
title="Excluir"></a>
1728 </td>
1729 ';
1730

1731 // Se foi enviado a variável $campo


1732 // então monta cabeçalho somente com estes
1733 if ($campos) {
1734

1735 // Varrendo a lista de campos enviada


Capítulo 16 Separando HTML do PHP: Classe Template - 187

1736 foreach ($campos as $campo) {


1737

1738 // Montando valores com


1739 // as informações do array com campos
1740 $conteudo .= '
1741 <td>' . $tabLinha[$campo] . '</td>
1742 ';
1743 }
1744

1745 } else {
1746 // Não foi enviada lista de campos
1747 // Varrendo as campos do registro
1748 foreach ($tabLinha as $campo => $valor) {
1749

1750 // Montando valores


1751 $conteudo .= '
1752 <td>' . $valor. '</td>
1753 ';
1754 }
1755

1756 }
1757

1758 // Finalizando linha


1759 $conteudo .= '
1760 </tr>
1761 ';
1762 }
1763

1764 // Finalizando tabela


1765 $conteudo .= '
1766 </table>
1767 ';
1768 return $conteudo;
1769 }
Capítulo 16 Separando HTML do PHP: Classe Template - 188

Para usar este método, segue o exemplo (que pode ser adaptado para
qualquer tabela):

1770 <?php
1771 include_once('../config.inc.php');
1772

1773 echo '<h2>Listar Categorias</h2>';


1774

1775 // Instância da classe


1776 $tabLivro = new Livro;
1777

1778 // Recuperando um grupo de registros


1779 $livros = $tabLivro->listar();
1780

1781 // Para escolher os campos a serem exibidos,


1782 // define-se um array com os campos
1783 $campos = array('id', 'isbn', 'autor', 'titulo');
1784

1785 // Gerando tabela de listagem automaticamente


1786 echo Template::gerarTabela($tabLivro, $livros);
1787

1788 // Gerando apenas com os campos escolhidos


1789 echo Template::gerarTabela($tabLivro, $livros, $campos);

16.8. Outros métodos

Os demais métodos não serão explicados detalhadamente, mas seus


comentários são bastante claros sobre sua utilidade.

Seu uso ficará mais evidente na montagem dos sites administrativo e público,
na continuidade do curso.

1790 /*
1791 * gerarMenuAdmin
1792 */
1793 static function gerarMenuAdmin () {
Capítulo 16 Separando HTML do PHP: Classe Template - 189

1794

1795 $conteudo = '


1796 <div id="menucategorias">
1797 <h3>' . $_SESSION['login'] . ' (' . $_SESSION['perfil'] .
')</h3>
1798 <h4>' . $_SESSION['nome'] . '</h4>
1799 <h4>' . $_SESSION['horalogin'] . '</h4>
1800 <h4><a href="logout.php">sair</a></h4>
1801

1802 <h1>Administração</h1>
1803 <ul>
1804 <li><a href="livroListar.php">Listar Livros</a></li>
1805 <li><a href="livroInserir.php">Inserir Livro</a></li>
1806 <li><a href="categoriaListar.php">Listar Categorias</a></li>
1807 <li><a href="categoriaInserir.php">Inserir
Categoria</a></li>
1808 <li><a href="pedidoListar.php">Listar Pedidos</a></li>
1809 </ul>
1810 ';
1811 if(Seguranca::temPerfil('admin')) {
1812

1813 $conteudo .= '


1814 <h1>Sistema</h1>
1815 <ul>
1816 <li><a href="usuarioListar.php">Listar Usuários</a></li>
1817 <li><a href="usuarioInserir.php">Inserir Usuário</a></li>
1818 </ul>
1819 ';
1820

1821 }
1822

1823 $conteudo .= '</div>';


1824 return $conteudo;
1825

1826 }
1827
Capítulo 16 Separando HTML do PHP: Classe Template - 190

1828 /*
1829 * gerarListaCategorias
1830 */
1831 static function gerarListaCategorias () {
1832

1833 $tabCategoria = new Categoria();


1834 $categorias = $tabCategoria->listarAlfabetico();
1835

1836 $conteudo = '


1837 <div id="menucategorias">
1838 <h1>Categorias</h1>
1839 <ul>'."\n";
1840

1841 while ($cat = $categorias->fetchObject()) {


1842 $conteudo .= '
1843 <li>
1844 <a href="livrosCategoria.php?catid=' . $cat->id . '">
1845 ' . $cat->descricao . '
1846 </a>
1847 </li>'."\n";
1848 }
1849

1850 $conteudo .= '</ul>


1851 </div>';
1852

1853 return $conteudo;


1854

1855 }
1856

1857 /*
1858 * adminGerar
1859 */
1860 static public function gerarAdmin($conteudo='') {
1861

1862 self::gerarCabecalhoAdmin();
1863 echo self::gerarMenuAdmin();
Capítulo 16 Separando HTML do PHP: Classe Template - 191

1864 echo $conteudo;


1865 self::gerarRodape();
1866

1867 }
1868

1869 /*
1870 * siteGerar
1871 */
1872 static public function gerarSite($conteudo='') {
1873

1874 self::gerarCabecalhoSite();
1875 echo self::gerarListaCategorias();
1876 echo $conteudo;
1877 self::gerarRodape();
1878

1879 }
1880

1881 static function gerarLivroResumo ($objLivro) {


1882 global $CONFIG;
1883

1884 $arquivo = 'livroResumo.html';


1885 $parametros = array(
1886 '%IMAGEM%' => $CONFIG['livrosDir'].
$objLivro->isbn.'.jpeg',
1887 '%LIVROID%' => $objLivro->id,
1888 '%TITULO%' => $objLivro->titulo,
1889 '%AUTOR%' => $objLivro->autor,
1890 '%PRECO%' =>
number_format($objLivro->preco, 2 , ',', '.'),
1891 );
1892 return self::pegarArquivo($arquivo, $parametros);
1893

1894 }
1895

1896 static function gerarLivroDetalhe ($objLivro) {


1897 global $CONFIG;
Capítulo 16 Separando HTML do PHP: Classe Template - 192

1898

1899 $arquivo = 'livroDetalhe.html';


1900

1901 $parametros = array(


1902 '%IMAGEM%' => $CONFIG['livrosDir'].
$objLivro->isbn.'.jpeg',
1903 '%LIVROID%' => $objLivro->id,
1904 '%TITULO%' => $objLivro->titulo,
1905 '%AUTOR%' => $objLivro->autor,
1906 '%PRECO%' =>
number_format($objLivro->preco, 2 , ',', '.'),
1907 '%SUMARIO%' => nl2br($objLivro-
>sumario),
1908 );
1909 return self::pegarArquivo($arquivo, $parametros);
1910

1911 }
1912

1913

1914 /*
1915 * gerarLogin
1916 */
1917 static public function gerarLogin($parametros) {
1918

1919 $arquivo = 'login.html';


1920 return self::pegarArquivo($arquivo, $parametros);
1921

1922 }
1923

1924

1925

1926 /*
1927 * método debug
1928

1929 */
1930 private static function debug () {
1931
Capítulo 16 Separando HTML do PHP: Classe Template - 193

1932 // Recuperando variável que ativa ou não o debug no


config.inc.php
1933 global $debug, $DEBUG;
1934

1935 // verifica se o debug está ativo


1936 if ($debug) {
1937

1938 $conteudo = '<div id="debug">';


1939

1940 /*
1941 * gerarMenuAdmin
1942 */
1943 static function gerarMenuAdmin () {
1944

1945 $conteudo = '


1946 <div id="menucategorias">
1947 <h3>' . $_SESSION['login'] . ' (' . $_SESSION['perfil'] .
')</h3>
1948 <h4>' . $_SESSION['nome'] . '</h4>
1949 <h4>' . $_SESSION['horalogin'] . '</h4>
1950 <h4><a href="logout.php">sair</a></h4>
1951

1952 <h1>Administração</h1>
1953 <ul>
1954 <li><a href="livroListar.php">Listar Livros</a></li>
1955 <li><a href="livroInserir.php">Inserir Livro</a></li>
1956 <li><a href="categoriaListar.php">Listar Categorias</a></li>
1957 <li><a href="categoriaInserir.php">Inserir
Categoria</a></li>
1958 <li><a href="pedidoListar.php">Listar Pedidos</a></li>
1959 </ul>
1960 ';
1961 if(Seguranca::temPerfil('admin')) {
1962

1963 $conteudo .= '


1964 <h1>Sistema</h1>
Capítulo 16 Separando HTML do PHP: Classe Template - 194

1965 <ul>
1966 <li><a href="usuarioListar.php">Listar Usuários</a></li>
1967 <li><a href="usuarioInserir.php">Inserir Usuário</a></li>
1968 </ul>
1969 ';
1970

1971 }
1972

1973 $conteudo .= '</div>';


1974 return $conteudo;
1975

1976 }
1977

1978 /*
1979 * gerarListaCategorias
1980 */
1981 static function gerarListaCategorias () {
1982

1983 $tabCategoria = new Categoria();


1984 $categorias = $tabCategoria->listarAlfabetico();
1985

1986 $conteudo = '


1987 <div id="menucategorias">
1988 <h1>Categorias</h1>
1989 <ul>'."\n";
1990

1991 while ($cat = $categorias->fetchObject()) {


1992 $conteudo .= '
1993 <li>
1994 <a href="livrosCategoria.php?catid=' . $cat->id . '">
1995 ' . $cat->descricao . '
1996 </a>
1997 </li>'."\n";
1998 }
1999

2000 $conteudo .= '</ul>


Capítulo 16 Separando HTML do PHP: Classe Template - 195

2001 </div>';
2002

2003 return $conteudo;


2004

2005 }
2006

2007 /*
2008 * adminGerar
2009 */
2010 static public function gerarAdmin($conteudo='') {
2011

2012 self::gerarCabecalhoAdmin();
2013 echo self::gerarMenuAdmin();
2014 echo $conteudo;
2015 self::gerarRodape();
2016

2017 }
2018

2019 /*
2020 * siteGerar
2021 */
2022 static public function gerarSite($conteudo='') {
2023

2024 self::gerarCabecalhoSite();
2025 echo self::gerarListaCategorias();
2026 echo $conteudo;
2027 self::gerarRodape();
2028

2029 }
2030

2031 static function gerarLivroResumo ($objLivro) {


2032 global $CONFIG;
2033

2034 $arquivo = 'livroResumo.html';


2035 $parametros = array(
2036 '%IMAGEM%' => $CONFIG['livrosDir'].
$objLivro->isbn.'.jpeg',
Capítulo 16 Separando HTML do PHP: Classe Template - 196

2037 '%LIVROID%' => $objLivro->id,


2038 '%TITULO%' => $objLivro->titulo,
2039 '%AUTOR%' => $objLivro->autor,
2040 '%PRECO%' =>
number_format($objLivro->preco, 2 , ',', '.'),
2041 );
2042 return self::pegarArquivo($arquivo, $parametros);
2043

2044 }
2045

2046 static function gerarLivroDetalhe ($objLivro) {


2047 global $CONFIG;
2048

2049 $arquivo = 'livroDetalhe.html';


2050

2051 $parametros = array(


2052 '%IMAGEM%' => $CONFIG['livrosDir'].
$objLivro->isbn.'.jpeg',
2053 '%LIVROID%' => $objLivro->id,
2054 '%TITULO%' => $objLivro->titulo,
2055 '%AUTOR%' => $objLivro->autor,
2056 '%PRECO%' =>
number_format($objLivro->preco, 2 , ',', '.'),
2057 '%SUMARIO%' => nl2br($objLivro-
>sumario),
2058 );
2059 return self::pegarArquivo($arquivo, $parametros);
2060

2061 }
2062

2063

2064 /*
2065 * gerarLogin
2066 */
2067 // Varrendo variável global com informações de debug
2068 foreach ($DEBUG as $chave => $valor) {
Capítulo 16 Separando HTML do PHP: Classe Template - 197

2069

2070 $conteudo .= "<h1>$chave</h1>\n<pre>$valor</pre>";


2071

2072 }
2073

2074 // Exibindo variáveis superglobais


2075

2076 $conteudo .=
"<h1>SESSÃO</h1>\n<pre>".print_r($_SESSION,true)."</pre>";
2077

2078 $conteudo .=
"<h1>COOKIE</h1>\n<pre>".print_r($_COOKIE,true)."</pre>";
2079

2080 $conteudo .=
"<h1>POST</h1>\n<pre>".print_r($_POST,true)."</pre>";
2081

2082 $conteudo .=
"<h1>GET</h1>\n<pre>".print_r($_GET,true)."</pre>";
2083

2084 $conteudo .=
"<h1>FILES</h1>\n<pre>".print_r($_FILES,true)."</pre>";
2085

2086 $conteudo .= '</div>';


2087 }
2088

2089 return $conteudo;


2090

2091 }

Templates utilizados são colocados na sequência.

16.8.1. templates/login.html

1 <div id="login">
Capítulo 16 Separando HTML do PHP: Classe Template - 198

2 <form method="post" action="login.php">


3 <table>
4 %ERRO%
5 <tr>
6 <th>Login:</th>
7 <td><input type="text" name="login" value="%LOGIN%"></td>
8 </tr>
9 <tr>
10 <th>Senha:</th>
11 <td><input type="password" name="senha"></td>
12 </tr>
13 <tr>
14 <td colspan=2 align="center">
15 <input type="submit" name="entrar" value="Entrar">
16 </td>
17 </tr>
18 <tr>
19 </table>
20 </form>
21 </div>

16.8.2. templates/livroResumo.html

1 <div class="resumolivro">
2 <img src="%IMAGEM%">
3 <h3>
4 <a href="verLivro.php?livroid=%LIVROID%">
5 %TITULO%
6 </a>
7 </h3>
8 <h4>%AUTOR%</h4>
9 <h5>%PRECO%</h5>
10 <a href="verLivro.php?livroid=%LIVROID%">ver
Capítulo 16 Separando HTML do PHP: Classe Template - 199

detalhes</a><br>
11 <a href="verCarrinho.php?livroid=%LIVROID%">adicionar ao
carrinho</a>
12 </div>

16.8.3. templates/livroDetalhe.html

1 <div class="resumolivro">
2 <img src="%IMAGEM%">
3 <h3>
4 <a href="verLivro.php?livroid=%LIVROID%">
5 %TITULO%
6 </a>
7 </h3>
8 <h4>%AUTOR%</h4>
9 <h5>%PRECO%</h5>
10 <p>%SUMARIO%</p>
11 <a href="verLivro.php?livroid=%LIVROID%">ver
detalhes</a><br>
12 <a href="verCarrinho.php?livroid=%LIVROID%">adicionar ao
carrinho</a>
13 </div>
Capítulo 17 Segurança: Sistema de Login - 200

Capítulo 17

Segurança: Sistema de Login

17.1. Objetivo

• Manter o sistema seguro, com permissionamento de login.

• Filtrar injections.
Capítulo 17 Segurança: Sistema de Login - 201

17.2. Classe Seguranca

14 <?php
15

16 class Seguranca {
17

18 /*
19 * método autenticar
20 * Recebe usuário e senha e realiza autenticação
21 * Retorna true ou false
22 * Se for true, inicia sessão com dados do usuário
23 */
24 static public function autenticar($usuario, $senha) {
25

26 // Iniciando instânca da tabela usuário


27 $tabUsuario = new Usuario;
28

29 // O filtro testa login e senha com MD5


30 $filtro = "login = '" . $_POST['login'] ."' AND senha =
md5('" . $_POST['senha'] . "')";
31 $usuario = $tabUsuario->listar($filtro);
32

33 // Verifica se retornou conteúdo e quantas linhas (0 ou


1)
34 if($usuario && $usuario->rowCount()) {
35

36 // Inicia sessão
37 session_start();
38

39 // Recupera o registro
40 $usuarioLogin = $usuario->fetchObject();
41

42 // Alimenta variável de sessão


43 $_SESSION['login'] = $_POST['login'];
44 $_SESSION['horalogin'] = date('d/m/Y H:i');
45 $_SESSION['nome'] = $usuarioLogin->nome;
Capítulo 17 Segurança: Sistema de Login - 202

46 $_SESSION['perfil'] = $usuarioLogin->perfil;
47

48 // Retorna verdadeiro
49 return true;
50

51 } else {
52

53 // Não confere usuário e senha,


54 // inicia e destrói sessão para limpá-la
55 session_start();
56 session_destroy();
57

58 // Retorna falso
59 return false;
60

61 }
62

63 }

64 /*
65 * método estaConectado
66 * Testa se o usuário está conectado
67 * Se não estiver, destrói sessão e
68 * envia para tela de login
69 */
70 static public function estaConectado() {
71

72 // inicia ou conecta-se a uma sessão


73 session_start();
74

75 // Verifica se a sessão possui


76 // uma variável que foi definida no login
77 if(!isset($_SESSION['login'])) {
78

79 // se não houver, destrói a sessão e redireciona


80 session_destroy();
Capítulo 17 Segurança: Sistema de Login - 203

81 header('Location:login.php');
82

83 }
84

85 }
86

87

88

89

90

91 /*
92 * método temPerfil
93 * Checa se usuário está no perfil solicitado
94 * ou numa lista de perfis(em array)
95 */
96

97 static public function temPerfil($perfil) {


98

99 // Se perfil não é array, "transforma" em array


100 if(!is_array($perfil)) $perfil = array($perfil);
101

102 // Testa se o perfil do usuário na sessão está


103 // na lista de perfis enviados
104 if (in_array($_SESSION['perfil'], $perfil)) {
105

106 // Retorna verdadeiro, está no perfil


107 return true;
108

109 } else {
110

111 // Retorna falso, não está no perfil


112 return false;
113

114 }
115

116 }
117 /*
Capítulo 17 Segurança: Sistema de Login - 204

118 * método checaAcesso


119 * Verifica se usuário tem acesso
120 * Se não tem, redireciona para página de
121 * Acesso Negado
122 */
123 static public function checaAcesso($perfil) {
124

125 // Se perfil não é array, "transforma" em array


126 if(!is_array($perfil)) $perfil = array($perfil);
127

128 // Testa se o perfil do usuário na sessão está


129 // na lista de perfis enviados
130 if (!in_array($_SESSION['perfil'], $perfil)) {
131

132 // Se não está na lista de perfis, redireciona


133 header('Location:acessoNegado.php');
134

135 }
136

137 }
138

139 }

17.2.1. login.php

140 <?php
141

142 // Incluindo arquivo de configuração


143 include_once("../config.inc.php");
144

145 // Iniciando parâmetros para template de login


146 $parametros = array('%ERRO%'=>'', '%LOGIN%'=>'');
147

148 // Verificando o método de envio (POST) e se existe uma


variável
Capítulo 17 Segurança: Sistema de Login - 205

149 // Então considera o formulário enviado


150 if($_SERVER['REQUEST_METHOD'] == 'POST' &&
isset($_POST['login'])){
151

152 // Usando classe Seguranca para realizar autenticação


153 if(Seguranca::autenticar($_POST['login'], $_POST['senha'])) {
154

155 // Se foi autenticado, redireciona para index


156 header('Location:index.php');
157

158 } else {
159

160 // Não autenticou, então altera os parâmetros


161 // do template de login para emitir
162 // mensagem de erro e mostrar o login digitado
163 $parametros = array(
164 '%ERRO%'=>
165 '<caption>Usuário ou Senha não
conferem</caption>',
166 '%LOGIN%'=>$_POST['login'],
167 );
168

169 }
170

171 }
172

173 // Não é gerado o template de admin padrão,


174 // pois já contém menu
175 // Cabecalho, formulário de login e rodapé
176 // são gerados individualmente e tem saída com echo
177 echo Template::gerarCabecalhoAdmin();
178 echo Template::gerarLogin($parametros);
179 echo Template::gerarRodape();
Capítulo 17 Segurança: Sistema de Login - 206

17.2.2. logout.php

180 <?php
181

182 // Reconecatando e destruindo a cessão


183 session_start();
184 session_destroy();
185

186 // Redirecionando para tela de login


187 header('Location:login.php');

17.2.3. index.php alterado para checar usuário


logado

188 <?php
189

190 // Incluindo arquivo de configuração


191 include_once('../config.inc.php');
192

193 // Checando se está conectado


194 Seguranca::estaConectado();
195

196 // Gerando template do site administrativo


197 Template::gerarAdmin('');
Capítulo 17 Segurança: Sistema de Login - 207

REFERÊNCIAS
BIBLIOGRÁFICAS
Capítulo 17 Segurança: Sistema de Login - 208

ECO, UMBERTO. Como se faz uma tese em Ciências Humanas. 6.ª


edição. Lisboa: Editorial Presença. 1995.

Homepage oficial de Umberto Eco, website: http://www.umbertoeco.it/.


Acesso em 26 de abril de 2010.
ANEXOS
HTML/XHTML - Referência Básica - 210

HTML/XHTML - Referência Básica

Este documento é uma referência rápida às tags básicas do HTML/XHTML.


Não é um curso completo tampouco uma referência completa.

Estrutura Básica de uma página

<html>
<!-- Comentário: cabeçalho da página -->
<head>
<!-- Comentário: título da página no navegador -->
<title>
Título da Página
</title>
<!-- Comentário: inclusão da folha de estilos CSS -->
<style type="text/css">estilo.css</style>
</head>
<!-- Comentário: corpo da página -->
<body>
Corpo da página
</body>
</html>
HTML/XHTML - Referência Básica - 211

Tags de Texto

<h1>Título Nível 1</h1>


<h2>Título Nível 2</h2>
<h3>Título Nível 3</h3>
<h4>Título Nível 4</h4>
<h5>Título Nível 5</h5>
<h6>Título Nível 6</h6>
<p>Parágrafo</p>
Quebra de linha<br />
Linha Horizontal<hr />

Listas

Uma lista não ordenada


<ul>
<li>Primeiro</li>
<li>Segundo</li>
<li>Terceiro</li>
</ul>
Uma lista ordenada
<ol>
<li>Primeiro</li>
<li>Segundo</li>
<li>Terceiro</li>
</ol>

Listas de definição

<dl>
<dt>Homossexual</dt>
<dd>Sabão em pó para lavar os órgão genitais</dd>
<dt>Promoção</dt>
<dd>Algo para um cara grande (feminino diminutivo: pra
HTML/XHTML - Referência Básica - 212

mocinha)</dd>
</dl>

Imagens

<img src="caminho/confirmar.jpg" alt="confirmar" />

Tabelas

<table>
<caption>Título da tabela (XHTML)</caption>
<!-- Comentário: thead é cabeçalho da tabela -->
<thead>

<tr>
<th>Nome</th>
<th>Idade</th>
<th>Local</th>

</thead>
<!--
Comentário: tfoot é cabeçalho da tabela,
será exibido no final da tabela -->
<tfoot>

<!--
Comentário: colspan é um atributo que diz que esta coluna
tera tamanho de "x" colunas
-->
<td colspan="3">Total de Pessoas: 03</td>

</tfoot>
<tbody>
HTML/XHTML - Referência Básica - 213

<tr>
<td>João Guedes</td>
<td>31</td>
<td>Santa Maria – RS</td>
</tr>
<tr>
<td>Mário Carvalho</td>
<td>28 anos</td>
<td>Salvador – BA</td>
</tr>
<tr>
<td>Cristiane Ramalho</td>
<td>23 anos</td>
<td>Barreiras – BA</td>
</tr>
</tbody>
</table>

Formulários

<form action="destino.php" method="post">


<!-- Comentário: fieldset é um agrupador de campos -->
<fieldset>
<legend>Legenda do fieldset</legend>

<!-- Comentário: label é legendar para um campo (XHTML) -->


<label for="um">Texto: input type text</label>
<input id="um" type="text" name="um" size="20"value="123456" />
<br/>

<label for="dois">Senha: input password</label>


<input id="dois" type="password" name="dois" size="20"
value="123456" />
<br />
HTML/XHTML - Referência Básica - 214

<label for="tres">Área de texto: textarea </label>


<textarea class="semTabela" name="tres" cols="50" rows="3">
Aqui temos texto em profusão
</textarea>

<br />
</fieldset>

<fieldset>
<legend>Um grupo para seleção</legend>

<label for="quatro">Select: select</label>


<select id="quatro" name="quatro">
<optgroup label="Premiados">
<option value="1">primeiro</option>
<option value="1">segundo</option>
<option value="1">terceiro</option>
</optgroup>
<optgroup label="Sofredores">
<option value="1">quarto</option>
<option value="1">quinto</option>
<option value="1">sexto</option>
</optgroup>
</select>
</fieldset>

<fieldset>
<legend>Input Checkbox</legend>
<!--
Comentário: o atributo "name"
deve ser diferente para cada checkbox
-->
<input type="checkbox" name="seis" value="1" />
Marque este<br />
HTML/XHTML - Referência Básica - 215

<input type="checkbox" name="sete" value="1" />


Marque este também<br />
<input type="checkbox" name="oito" value="1" />
E este também
</fieldset>

<fieldset >
<legend>Input Radio</legend>
<!--
Comentário: o atributo "name" deve em cada input radio
do mesmo grupo
-->
<input type="radio" name="nove" value="1" />Marque este<br />
<input type="radio" name="nove" value="1" />Ou este<br />
<input type="radio" name="nove" value="1" />Ou este
</fieldset>

<fieldset >
<legend>Botões</legend>
<!--
Comentário: button tipo submit -
envio do formulário (XHTML)
-->
<button type="submit" name="dez">Enviar</button>&nbsp;
<!--
Comentário: button tipo reset -
limpar formulário (XHTML)
-->
<button type="reset" name="dez">Limpar</button>&nbsp;
<!--
Comentário: input tipo submit -
envio do formulário (HTML)
-->
<input type="submit" name="dez" value="Enviar" />&nbsp;
<!--
HTML/XHTML - Referência Básica - 216

Comentário: button tipo reset -


limpar formulário (HTML)
-->
<input type="reset" name="dez" value="Limpar" />&nbsp;

</fieldset>

</form>
Enviando e-mails com o PHP - 217

Enviando e-mails com o PHP

O comando mail() é usado para enviar mensagens de texto simples. Este


comando conta com o sistema de correio local para distribuir e-mails. Assim, se seu
sistema não contar com um programa de correio local, como o sendmail ou postfix,
este comando não funcionará. Veja sintaxe e exemplo abaixo:

bool mail(string to, string subject, string message[, string


additional_headers]);

Exemplo :

198 mail("contato@4linux.com.br","Assunto","Corpo da mensagem");

O programa que envia o e-mail é configurado na diretiva sendmail_path do


arquivo php.ini.
Verificando o tipo de uma variável - 218

Verificando o tipo de uma variável

O PHP utiliza checagem de tipos dinâmica, ou seja, uma variável pode conter
valores de diferentes tipos em diferentes momentos da execução do script. Por este
motivo não é necessário declarar o tipo de uma variável para usá-la. O interpretador
PHP decidirá qual o tipo daquela variável, verificando o conteúdo em tempo de
execução.

Ainda assim, é permitido converter os valores de um tipo para outro desejado,


utilizando casting ou a função settype(), descrita logo adiante.

Nem sempre é possível saber qual o tipo de uma variável em determinado


instante se não contar com a ajuda de algumas funções que verificam isso. A
verificação pode ser feita de duas maneiras:

1 - Utilizando a função gettype(), em que a sintaxe é a seguinte:

string gettype(mixed var);

2 - Utilizando as funções is_*(). São elas:

• is_array()
• is_bool()
• is_float()
• is_integer()
Verificando o tipo de uma variável - 219

• is_null()
• is_numeric()
• is_object()
• is_resource()
• is_scalar()
• is_string()

onde a sintaxe é a seguinte:

bool is_<tipo> (mixed var);

A função retorna TRUE se var é do tipo indicado, e FALSE se não.

A palavra mixed indica que a variável var pode ser de diversos tipos. E a
função pode retornar as seguintes strings: integer, double, string, array, object e
unknown type.

Dica: Nunca use gettype() para testar um certo tipo, a string devolvida
poderá sofrer alterações em uma versão futura. Ao invés, use as funções is_*.

Transformação de tipos - Coerções

Quando ocorrem determinadas operações (soma "+", por exemplo) entre dois
valores de tipos diferentes, o PHP converte o valor de um deles automaticamente
(coerção). Se o operando for uma variável, seu valor não será alterado.

O tipo para o qual os valores dos operandos serão convertidos é determinado


da seguinte forma: se um dos operandos for float, o outro será convertido para float,
senão, se um deles for integer, o outro será convertido para integer.

Veja este exemplo:

199 <?php
200 $php = "1";// $php é a string "1"
201 $php = $php + 1; // $php é o integer 2
202 $php = $php + 3.7; // $php é o double 5
Verificando o tipo de uma variável - 220

Como podemos notar, o PHP converte string para integer ou float mantendo o
valor.

O sistema utilizado pelo PHP para converter strings em números é analisado o


início da string:

• Se contiver um número, ele será avaliado. Senão, o valor será 0 (zero);


• O número pode conter um sinal no início ("+" ou "-");
• Se a string contiver um ponto em sua parte numérica a ser analisada, ele
será considerado, e o valor obtido será float/double;
• Se a string contiver um "e" ou "E" em sua parte numérica a ser analisada, o
valor seguinte será considerado como expoente da base 10, e o valor obtido
será double.

Teste o exemplo abaixo

203 <?php
204 $php = 1 + "10.5";// $php == 11.5
205 echo '<p>' . $php . '</p>';
206 $php = 1 + "-1.3e3"; // $php == -1299
207 echo '<p>' . $php . '</p>';
208 $php = 1 + "teste10.5"; // $php == 1
209 echo '<p>' . $php . '</p>';
210 $php = 1 + "10testes"; // $php == 11
211 echo '<p>' . $php . '</p>';
212 $php = 1 + " 10testes";// $php == 11
213 echo '<p>' . $php . '</p>';
214 $php = 1 + "+ 10testes"; // $php == 1
215 echo '<p>' . $php . '</p>';
216 $php = 1 + "- 10testes"; // $php == 1
217 ?>
Verificando o tipo de uma variável - 221

Transformação explícita de tipos

A sintaxe do typecast de PHP é semelhante ao de C: basta escrever o tipo


entre parênteses antes do valor .

Exemplo:

218 <?php
219 $php = 15; // $php é integer (15)
220 $php = (double) $php;// $php é double (15.0)
221 $php = 3.9; // $php é double (3.9)
222 $php = (int) $php;// $php é integer (3)
223 // o valor decimal é truncado
224 ?>

Os tipos de cast permitidos são:

• (int), (integer) muda para integer;


• (real), (double), (float) muda para float;
• (string) muda para string;
• (array) muda para array;
• (object) muda para objeto.

Com a função settype

A função settype() converte uma variável para o tipo especificado, que pode
ser "integer", "double", "string", "array" ou "object".

Exemplo:

225 <?php
226 $php = 15; // $php é integer
227 settype($php,double);// $php é double
Conexão segura - 222

Conexão segura

O site que implementamos, fora as funcionalidades que ainda faltam, não pode
ser utilizado para

uma finalidade séria em hipótese alguma. Isso porque, no formulário de


pagamento, o usuário envia vários dados incluindo o número do cartão de crédito.
Entretanto, os dados não são criptografados e podem ser facilmente interceptados e
visualizados por intrusos.

Para resolver esse problema, precisamos embaralhar os dados antes de serem


enviados, de modo que se porventura sejam interceptados, não possam ser
compreendidos. Somente o servidor sabe como desenbaralhar a informação. Essa
funcionalidade é provida pelo servidor web e é transparente aos scripts PHP. Vejamos
como prosseguir para habilitar a conexão segura com o servidor.

Instalando a ferramenta OpenSSL - (Secure


Socket Layer)

# aptitude install openssl

Criando uma certificadora local

A autenticidade de um site é assinada por uma organização certificadora


oficial. Como estamos

apenas fazendo alguns testes, criaremos nossa própria organização


localmente. Vejamos como fazer isso:

# mkdir /root/ssl
Conexão segura - 223

# cd /root/ssl
# /usr/lib/ssl/misc/CA.sh -newca

Uma série de perguntas são feitas. Preencha-as conforme o quadro abaixo. A


demais perguntas podem ser simplesmente respondidas com <ENTER>.

Enter PEM pass phrase: 123456


Verifying - Enter PEM pass phrase: 123456
Country Name (2 letter code) [AU]:BR
State or Province Name (full name) [Some-State]:SP
Locality Name (eg, city) []:Sao Paulo
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Certificadora
Organizational Unit Name (eg, section) []:TI
Common Name (eg, YOUR name) []:www.certificadora.com.br
Email Address []:suporte@certificadora.com.br

Se tudo ocorreu bem, aparecerá uma mensagem informando que a


certificadora foi criada.

Criando um site seguro

Precisamos criar um domínio virtual que aceite conexão segura. Crie um


arquivo chamado livraria dentro do diretório /etc/apache2/sites-available:

NameVirtualHost <Seu IP>


<VirtualHost www.livraria.com.br>
DocumentRoot /var/www/livraria
SSLEngine On
SSLCertificateFile /root/ssl/newcert.pem
SSLCertificateKeyFile /root/ssl/newkey.pem
ServerName www.livraria.com.br
ServerAdmin suporte@livraria.com.br
ErrorLog /var/log/apache2/livaria.com.br-error.log
CustomLog /var/log/apache2/livaria .com.br-access.log common
</VirtualHost>
Conexão segura - 224

Acertando o resolvedor de nomes local

Entretanto, o DNS irá resolver o nome acima para outro IP. Precisamos incluir
uma entrada no arquivo /etc/hosts:

<Seu IP> www.livraria.com.br

Criando uma requisição de certificação

Agora que temos uma certificadora, precisamos solicitar a ela a assinatura do


nosso site. Digitem o comando abaixo:

# cd /root/ssl
# /usr/lib/ssl/misc/CA.sh -newreq

E preencham conforme o quadro abaixo. Atentem para a URL fornecida, que


deve ser a mesma configurada no VirtualHost do Apache.

Enter PEM pass phrase: 1234


Verifying - Enter PEM pass phrase: 1234
Country Name (2 letter code) [AU]:BR
State or Province Name (full name) [Some-State]:SP
Locality Name (eg, city) []:Sao Paulo
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Livraria do
Tux
Organizational Unit Name (eg, section) []:TI
Common Name (eg, YOUR name) []:www.livraria.com.br
Email Address []:suporte@livaria .com.br

Assinando a certificação

Uma vez que a certificadora tem uma requisição, devemos então assiná-la.
Digitem o comando abaixo.

A senha solicitada é da certificadora, isto é, 123456. Respondam com y e o


Conexão segura - 225

site estará então certificado.

# /usr/lib/ssl/misc/CA.sh -sign

Habilitando o site seguro

O comando abaixo disponibiliza o VirtualHost que criamos. Responda


conforme indicado:

# a2ensite
Site name? livraria

Habilitando conexão segura

# a2enmod ssl

For fim, habilite a porta de conexão segura 443. Adicione a seguinte linha ao
arquivo /etc/apache2/ports.conf :

Listen 443

Reiniciando o servidor web.

Para que as ações tenham resultado, devemos reinicializar o servidor. Ao ser


solicitada, utilize a senha do servidor, isto é, 1234.

/etc/init.d/apache2 restart

Tente acessar o site com a URL:

https://www.livraria.com.br

Visualize o certificado apresentado no browser.


Conexão segura - 226

Capítulo 18

A certificação

• A prova:

◦ A prova é composta de 70 questões em inglês com 90 minutos de duração.

◦ Temos em média 1min e 2seg por questão na prova.

◦ A prova é mista de questões dos seguintes tipos:

▪ Múltipla-escolha

▪ Discursiva

▪ Somatória
Questionário ZEND(Inglês) - 227

18.1. Questionário ZEND(Inglês)

1. Which of the following functions will sort an array in


ascending order by value, while preserving key associations?
-asort()
-usort()
-krsort()
-ksort()
-sort()

2. A fingerprint of a string can be determined using which of the


following?
-md5()
-hash()
-fingerprint()
-None of the above

3. Consider the following XML document


<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
lang="en">
<head>
<title>XML Example</title>
</head>
<body>
<p>
Moved to <<a
href="http://example.org/">http://www.example.org/</a>.>
<br>
</p>
</body>
</html>
Questionário ZEND(Inglês) - 228

What is wrong with this document, and how can it be corrected?

-The document is completely valid


-All special XML characters must be represented as entities
within the -content of a node
-All tags must be closed
-You cannot specify a namespace for the attribute
-The DOCTYPE declaration is malformed

4.
<?php
$a = array(
1 => 'red',
'green',
'blue',
'purple' => array(
'house' => 'dog',
'food' => 'meal',
'here' => 'gone',
'hello' => array(
5 => 'goodbye',
8 => 'something',
'correct')));
?>
Which of the following print statements will output the string
“correct”?

-print $a['purple][4][3];
-print $a['purple']['hello'][9];
-print $a[2][4][3];
-print $a[2][4][9];
-print $a[4]['hello'][9];

5. If you would like to store your session in the database, you


Questionário ZEND(Inglês) - 229

would do which of the following?

-It requires a custom PHP extension to change the session handler


-Implement the session_set_save_handler() function
-Create functions for each session handling step and use
session_set_save_handler() to override PHP’s internal settings
-Configure the session.save_handler INI directive to your session
class

6. Consider the following PHP script:

get_socket($host1, $port1),
‘data’ => str_pad(“”, 500000, “A”));
$write_map[] = array(‘fr’ => get_socket($host2, $port2),
‘data’ => str_pad(“”, 500000, “B”));
$write_map[] = array(‘fr’ => get_socket($host3, $port3),
‘data’ => str_pad(“”, 500000, “C”));
do {
$write_sockets = array();
foreach($write_map as $data) {
$write_sockets[] = $data['fr'];
}
$num_returned = stream_select($r = null, $write_sockets, $e =
null, 30);
if($num_returned) {
foreach($write_sockets as $fr) {
foreach($write_map as $index => $data) {
if($data['fr'] === $fr) {
$len = fwrite($fr, $data['buf']);
if($len) {
$data['buf'] = substr($data['buf'], $len);
if(empty($data['buf'])) {
fclose($data['fr']);
unset($write_map[$index]);
}
Questionário ZEND(Inglês) - 230

}
}
}
}
}
} while(??????????);
?>

What should go in the ??????? above for this script to function


properly?

-$num_returned > 0
-$len > 0
-!empty($data['buf'])
-count($write_sockets)
-count($write_map)

7. Using flock() to lock a stream is only assured to work under


what circumstances?

-When running in a Linux environment local filesystem


-When accessing the stream of the local filesystem
-When running in a Windows environment and accessing a share
-When accessing a bi-directional stream
-When accessing a read-only stream

8. Which PCRE regular expression will match the string PhP5-


rocks?

-/^[hp1-5]*\-.*/i
-/[hp1-5]*\-.?/
-/[hp][1-5]*\-.*/
-/[PhP]{3}[1-5]{2,3}\-.*$/
-/[a-z1-5\-]*/
Questionário ZEND(Inglês) - 231

9. The ______ keyword is used to indicate an incomplete class or


method, which must be further extended and/or implemented in
order to be used.

final

protected

incomplete

abstract

implements

10. What is the output of?


function apple($apples = 4)
{
$apples = $apples / 2;
return $apples;
}
$apples = 10;
apple($apples);
echo $apples;

10

11 . Which of the following is the best way to split a string on


the “-=-” pattern?

They all are equally proper methods


Questionário ZEND(Inglês) - 232

str_split($string, strpos($string, “-=-”))

preg_split(“-=-”, $string);

explode(“-=-” $string);

12. Consider the following PHP script fragment:


createElement(‘title’);
$node = ????????
$title->appendChild($node);
$head->appendChild($title);
?>
What should ??????? be replaced with to add a node with the value
of Hello, World!

-$dom->createTextNode(“Hello, World”);
-$dom->appendElement($title, “text”, “Hello, world!”);
-$dom->appendTextNode($title, “Hello, World!”);
-$dom->createElement(‘text’, “Hello, World”);
-None of the above

13. Implementing your own PDO class requires which steps from the
list below?(choose 3)

-Extending the PDOStatement Class


-Set the PDO::ATTR_STATEMENT_CLASS parameter
-Call the PDO::setStatementClass() method
-Extend the PDO class
-Set the PDO::ATTR_USE_CLASS paramater
14. Which from the following list is not an approrpiate use of an
array?

-As a list
-All of these uses are valid
-As a Lookup Table
-A Stack
-As a hash table
Questionário ZEND(Inglês) - 233

15. What variable reference would go in the spots indcated


by ????? in the code segment below?

-$msg{$i}
-ord($msg);
-chr($msg);
-substr($msg, $i, 2);

16. When is it acceptable to store sensitive information in an


HTTP cookie?

-Only under extremely controlled situations


-When the cookie is sent over a secure HTTP request
-When it is encrypted
-It is always acceptable

17. Consider the following PHP string representing an SQL


statement:
$query = “UPDATE users SET password=’$password’ WHERE
username=’$username’”;

Which of the following values for $username or $password would


change the behavior of this query when executed?

-None of the above


-$username = “foobar\’ WHERE username=’admin’”;
-$password = “foobar’ WHERE username=’admin’ –:”;
-$username = “foobar\’ WHERE username=’admin’”;
-$password = “\”foobar\” WHERE username=\”admin\”";

18. When attempting to prevent a cross-site scripting attack,


which of the following is most important?
Questionário ZEND(Inglês) - 234

-Not writing Javascript on the fly using PHP


-Filtering Output used in form data
-Filtering Output used in database transactions
-Writing careful Javascript
-Filtering all input

19. In a situation where you want one and only one instance of a
particular object, the ________ design pattern should be used.

20. Which of the following list of potential data sources should


be considered trusted?

-None of the above


-$_ENV
-$_GET
-$_COOKIE
-$_SERVER

21. Which of the following php.ini directives should be disabled


to improve the outward security of your application?

-safe_mode
-magic_quotes_gpc
-register_globals
-display_errors
-allow_url_fopen

22. The _______ method will be called automatically when an


object is represented as a string.

-getString()
-__get()
Questionário ZEND(Inglês) - 235

-__value()
-__toString()
-__getString()

23. Which functions would be needed to translate the following


string:
I love PHP 5
to the following?
5 PHP EVOL I
(choose 2)

-mirror()
-strtoupper()
-toupper()
-str_reverse()
-strrev()

24. When embedding PHP into XML documents, what must you ensure
is true in order for things to function properly?

-Disabling of the short_tags PHP.ini directive


-Enabling the asp_tags PHP.ini directive
-That you have XPath support enabled in PHP 5
-That your XML documents are well-formed
-None of the above, PHP can be embedded in XML in all cases.

Você também pode gostar