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=”[email protected]”;
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',
'
[email protected]',
'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 = "[email protected]";
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", "[email protected]");
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' => '
[email protected]',
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>
<!--
Comentário: button tipo reset -
limpar formulário (XHTML)
-->
<button type="reset" name="dez">Limpar</button>
<!--
Comentário: input tipo submit -
envio do formulário (HTML)
-->
<input type="submit" name="dez" value="Enviar" />
<!--
HTML/XHTML - Referência Básica - 216
Comentário: button tipo reset -
limpar formulário (HTML)
-->
<input type="reset" name="dez" value="Limpar" />
</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("[email protected]","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 []:
[email protected] 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
[email protected] 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.