Primeiros Elogios ao Use a Cabeça! PHP & MySQL
“PHP e MySQL são duas das tecnologias de desenvolvimento web mais populares
de hoje em dia, e este livro mostra aos leitores o porquê. Criar um site sem elas,
atualmente, é tão inimaginável quanto fazer web design sem CSS. Este livro é uma
ótima introdução e é também uma boa fonte de risadas. E o livro que eu queria ter
tido quando estava aprendendo.”
— HarveyQuamen, ProfessorÁssociado de Inglês e Humanities Computing,
Universidade deAlberta
“Tudo o que nos acostumamos a aceitar como trabalho pesado no processo de aprendizado
técnico foi abandonado, e em seu lugar foi criado um incomum método de aprendizado
divertido. Eu tenho plena confiança de que a série Use a Cabeça! irá revolucionar a
indústria de livros técnicos, e que estes métodos acabarão se tornando o padrão. Aposto
que até a minha avó tecnofóbica poderia aprender técnicas de PHP e MySQL após uma
única leitura. Ela provavelmente ainda se divertiria ao fazê-lo!”
—Will Harris,Administrador de Bancos de Dados, Powered ByGeek
“Ler Use a Cabeça! PHP 8c MySQL é como assistir a uma aula do professor ‘legal’.Faz você
ficar com vontade de aprender.”
----Stephanie Liese, DesenvolvedoraWeb
“Usando imagens e humor, o livro é fácil de digerir, e ainda por cima apresenta um sólido
conhecimento técnico.”
—JeremeAlien, DesenvolvedorWeb
“Após uma desafiadora e ultrarrápida primeira leitura, e vários projetos práticos divertidos,
como por exemplo “Meu cachorro foi abduzido por alienígenas”e a “Agência de
Encontros Mismatch”,não vejo a hora de adicionar um pouco de PHP aos meus sites.”
— David Briggs.Engenheiro de Software e Escritor de Livros Técnicos
Elogios ao Use a Cabeça! HTML com CSS & XHTML
“Eric e Elisabeth Freeman claramente entendem do assunto. À medida que a Internet vai
se tornando mais complexa, fica cadavez mais importante criar páginas web atraentes. O
design elegante é o cerne de todos os capítulos aqui, e cada conceito é apresentado com
doses iguais de pragmatismo e inteligência.”
— Ken Gold-Stein,Vice-Presidente Executivo &Diretor-Gerente, Disney Online
“Aweb seria um lugar muito melhor se todo designer HTML começasse lendo este livro.”
— L. David Baron, Diretor Técnico de Layout &CSS, Mozilla Corporation,
http://dbaron.org/
“Eu escrevo HTML e CSS hã dez anos, e o que antes era um longo processo de aprendizado
por tentativa e erro agora acaba de ser reduzido a um único e atraente livro. HTML
costumava ser algo que você simplesmente ficava fuçando até que as coisas ficassem
bem na tela, mas com o advento de padrões web e a exigência de melhor acessibilidade,
práticas de programação preguiçosasjá não são mais aceitáveis... nem do ponto de vista
empresarial, nem do ponto de vista da responsabilidade social. Use a Cabeça! HTML
com CSS &XHTML lhe ensina como fazer as coisas corretamente desde o princípio, sem
fazer com que o processo pareça impossível de aprender. A linguagem HTML, quando
corretamente ensinada, não é mais complicada do que aprender inglês, e os Freemans
íizerám um excelente trabalho em manter todos os conceitos compreensíveis.”
— Mike Davidson, Presidente &CEO, Newsvine Inc.
“Ah, ótimo. Vocês fizeram um livro de XHTML simples o suficiente para que um CEO
consiga entendê-lo. O que farão a seguir? Um livro de contabilidade simples o suficiente
para que o meu desenvolvedor consiga entender? Se continuar assim acabaremos tendo de
fazer coisas como colaborar e trabalhar em equipe.”
—Janice Fraser, CEO, Adaptive Path
“Este livro tem humor, charme, mas o mais importante: tem coração. Eu sei que parece
algo ridículo de se dizer sobre um livro técnico, mas eu realmente percebo que, no seu
cerne, este livro (ou pelo menos os seus autores) realmente está preocupado em fazer os
leitores aprenderem o material. Isso se faz notar no estilo, na linguagem e nas técnicas. O
aprendizado - realmente entender e compreender - pelo leitor é claramente o objetivo
número um na mente dos Freemans. E obrigado, obrigado, obrigado pela forte e
sensível insistência que o livro prega pelo respeito aos padrões. É ótimo ver um livro para
iniciantes, o qual acredito, que vai ser amplamente lido e estudado, fazer uma campanha
tão eloquente e persuasiva pelo valor do respeito aos padrões na programação de páginas
web. Encontrei aqui até mesmo alguns argumentos que ainda não tinham-me ocorrido
- argumentos que eu posso me lembrar e usar quando as pessoas me perguntam, e elas
perguntam, ‘qual a vantagem de respeitar os padrões, e por que eu devo fazê-lo?’Agora
eu tenho mais munição! Também gostei do fato de o livro apresentar alguns fundamentos
sobre a mecânica de como realmente colocar a página no ar - FTP, fundamentos do
servidor web, estruturas de arquivos, etc.”
—Robert Neer, Diretor de Desenvolvimento de Produto, Movies.com
Elogios ao Use a Cabeça! JavaScript
“Tão prático e útil, e tão bem-explicado. Este livro faz um excelente trabalho dt^apresentar
um iniciante total aoJavaScript, e é mais uma prova da eficiência do método dè ensino
Use a Cabeça! De todos os outros livros deJavaScript, Use a Cabeça!JavaScript é
ótimo para aprender, comparado com outros livros de referência do tamanho de listas
telefônicas.”
—Alex Lee, Estudante, Universidade de Houston
“Uma excelente opção para o desenvolvedorJavaScript iniciante.”
— Fletcher Moore, Desenvolvedor e DesignerWeb, GeorgiaInstitue of
Technology
“Mais um ótimo livro no clássico estilo ‘Use a Cabeça!’”
— TWScannell
“OJavaScript vem sendo há bastante tempo o sistema por trás das páginas web, no lado
do cliente, mas vem sendo também mal entendido e mal utilizado. Com Use a Cabeça!
JavaScript, Michael Morrison apresenta uma introdução direta e fácil de entender sobre
a linguagem, removendo quaisquer mal entendidos que possam ter existido e mostrando
como usá-la da forma mais eficiente para melhorar suas páginas web.”
— AnthonyT. Holdener UI, Desenvolvedor de aplicaçõesweb e autordeAjax: O
GuiaDefinitivo
“Uma página web tem três partes - conteúdo (HTML), aparência (CSS) e comportamento
(JavaScript).Use a Cabeça! HTML apresentou os dois primeiros, e este livro usa a mesma
abordagem divertida e prática para introduzir oJavaScript. A forma divertida com que o
livro apresenta oJavaScript, e as muitas formas como ele reforça as informações para que
você não as esqueça, fazem deste um livro perfeito para iniciantes usarem para começar a
aprender a tomar suas páginas web interativas.”
— Stephen Chapman,Dono daFelgallPtyLtd., editor deJavaScriptde about.com
“Este é o livro que eu estive procurando para recomendar aos meus leitores. E simples o
suficiente para totais iniciantes, mas inclui aprofundamentos suficientes para ser útil aos
usuários mais avançados. E toma divertido o processo de aprendizado. Este pode acabar
sendo o único livro deJavaScript de que você precisará.”
—Julie L. Baumler, EditoradeJavaScriptde BellaOnline.com
Outros livros da série Use a Cabeça!
Use a Cabeça! Java
Use a Cabeça! Análise & Projeto Orientado a Objetos (A&POO)
Use a Cabeça! Ajax Iniciação Rápida
Use a Cabeça! H TM L com C SS e X H TM L
Use a Cabeça! Padrões de Projeto
Use a Cabeça! Servlets e JSP
Use a Cabeça! PM P
Use a Cabeça! SQL
Use a Cabeça! Desenvolvimento de Software
Use a Cabeça! JavaScript
Use a Cabeça! C #
Use a Cabeça! PH P & M ySQL
Use a Cabeça! Física
Use a Cabeça! Álgebra
Use a Cabeça! Ajax Profissional
Use a Cabeça! Estatística
Use a Cabeça! Ruby on Rails
Use a Cabeça! PHP & MÿSQL
v í -
ALTABOOKS
E D I T O R A
Rio de Janeiro 2010
Use aCabeçal PHP &MySQL
Copyright © 2010 da Starlin Alta Con. Com. Ltda.
ISBN: 978-85-7608-502-7
ProduçãoEditorial:
Starlin Alta Con. Com. Ltda.
Gerênciade Produçáo:
Maristela Almeida
CoordenaçãoAdministrativa:
Anderson Câmara
Supervisão deProdução:
Angel Cabeza
Tradução:
Marcelo Santos
Revisão Gramatical:
Fátima Regina Félix
RevisãoTécnica;
Giuliana Cirelli
Formada em Engenharia Elétrica
com ênfase em eletrônica.
Especializada em Programação
em linguagem C++ enos
ambientes de desenvolvimento
Eclipsee VisualStudio.
Diagramação:
Haroldo Sodré
Fechamento:
Luis Rodrigues
TranslatedFrom Original: Head First PHP & MySQL ISBN: 978-0-
596-00630-3
Use a Cabeça.!PHP & MySQL © 2010 Starlin Alta Con. Com. Ltda.
AuthorizedtranslationoftheEnglishedition ofHeadFirstPHP &MySQL
© 2009 Lynn Beighley andMichaelMorrison. This translation ispublished
and sold bypermission ofO’Reilly Media, Inc., the owner ofall rights to
publish and sellthe same. PORTUGUESE language editionpublished by
EditoraStarlinAlta Con. Com. Ltda. Copyright©2010 byEditoraStarlin
Alta Con. Com. Ltda.
Todos osdireitos reservadoseprotegidos pelaLei ne9.610/98. Nenhuma
parte deste livro, sem autorização prévia por escrito da editora, poderá
ser reproduzida ou transmitida sejam quais forem os meios empregados:
eletrônico, mecânico, fotográfico, gravaçáo ou quaisquer outros. Todo o
esforço foi feito para fornecer a mais completa e adequada informação,
contudo a editora e o(s) autor(es) náo assumem responsabilidade
pelos resultados e usos da informação fornecida. Recomendamos aos
leitorestestarainformação,bemcomotomartodososcuidados necessários
(como o backup), antes da efetiva utilização. Este livro não contém
CD-ROM, disquete ou qualquer outra mídia.
Erratas e atualizações: Sempre nos esforçamos para entregar
a você, leitor, um livro livre de erros técnicos ou de conteúdo;
porém, nem sempre isso é conseguido, seja por motivo de
mudança de software, interpretação ou mesmo quando alguns
deslizes constam na versão original de alguns livros que
traduzimos. Sendo assim, criamos em nosso site, www.altabooks.com.
br, aseção Erratas, onde relataremos, com a devida correção, qualquer
erro encontrado em nossos livros.
Avisos e Renúncia de Direitos: Este livro é vendido como está, sem
garantiade qualquer tipo, sejaexpressaou implícita.
Marcas Registradas: Todos os termos mencionados e reconhecidos
como Marca Registrada e/ou comercial são de responsabilidade de seus
proprietários. A Editora informa não estar associada a nenhum produto
e/oufornecedorapresentadonolivro.Nodecorrerdaobra,imagens,nomes
de produtos efabricantes podem ter sido utilizados e, desde já, aEditora
informa que o uso é apenas ilustrativo e/ou educativo, não visando ao
lucro, favorecimento ou desmerecimento do produto/fabricante.
Impressono Brasil
O código de propriedade intelectual de Io de julho de 1992 proíbe
expressamente o uso coletivo sem autorização dos detentores do direito
autoraldaobra,bemcomoacópiailegaldooriginal.Estapráticageneralizada,
nos estabelecimentos de ensino, provoca uma brutal baixa nas vendas dos
livrosaponto de impossibilitarosautoresde criaremnovas obras.
ALTABOOKS
EDITORA
Rua Viúva Cláudio, 291 - Bairro Industrial do Jacaré
TFP- 9n07<vn31 -R in Ar Tan^irn-Tfl • 71 377R-SWÍ0/S41 0 Riy- 71 3777-17^3
Para os meus pais, que frequentemente usam aplicações web e
estão sempre me apoiando
-Lynn Beighley
Para Rasmus Lerdorf, que iniciou sozinho a linguagem que
acabaria se tornando o PHP como nós o conhecemos. Prova
duradoura de que realmente basta uma pessoa para liderar a
todos nós em direção a um caminho novo e mais esclarecido.
-Michael Morrison
o(s) autor{es)
Os Autores de Use a Cabepa! PttPS- MySQL
Lynn Beighley é uma escritora de
ficção presa no corpo de uma escritora
de livros técnicos. Após descobrir que
escrever livros técnicos realmente dava
dinheiro, ela aprendeu a aceitar e
desfrutar a profissão. Depois de voltar
à escola para obter um Mestrado em
Ciência da Computação, trabalhou
para os acrônimos NRL e LANL.
Depois, descobriu o Flash e escreveu
seu primeiro best-seller. Vítima de um
timing infeliz, mudou-se para Silicon
Valley pouco antes da grande crise.
Passou alguns anos trabalhando para
o Yahoo! e escrevendo outros livros
e cursos de treinamento. Finalmente
rendendo-se ã sua vocação de escritora,
mudou-se para a área de Nova Iorque
para obter um MFA em Escrita Criativa.
Sua tese, escrita no estilo Use a Cabeça!,
foi defendida diante de uma sala lotada
de professores e colegas estudantes.
Foi extremamente bem-recebida, e ela
terminou seu curso, terminou Use a
Cabeça! SQL, e acabou de terminar Use
a Cabeça!PHP àf MySQL. Ufa!
Lynn adora viajar, escrever e inventar
histórias detalhadas sobre totais
estranhos. Ela tem um pouco de medo
de OVNIs.
£,VtâC^
Mo'r'f'SOir'
Michael Morrison tem sido um
contribuinte entusiasmado ao mundo
online desde quando mantinha um BBS
no seu Commodore 64, na época em
que ser nerd era bem menos maneiro
do que hoje em dia. Alguns milhares de
bauds depois, ele ainda fica fascinado
com o progresso que fizemos, e com que
rapidez. Michael não tem mais um BBS,
mas ainda se mantém bastante envolvido
com os equivalentes modernos e com
as ferramentas que usamos para criá-los.
Ele passa a maior parte do seu tempo
“oficial” escrevendo sobre tecnologias
relacionadas com a web, tendo escrito
ou co-escrito mais de cinquenta livros,
a respeito desde programação de
jogos para celulares até XML. Entrou
no universo Use a Cabeça! com Use a
Cabeça! JavaScript e não parou mais.
Michael é também o fundador da Stalefish
Labs (www.stalefishlabs.com,uma empresa
de entretenimento especializada emjogos,
brinquedos e mídia interativa. Ejá foi
visto passando tempo fora da Internet (o
quê?!) andando de skate,jogando hóquei
no gelo e cuidando do seu lago de carpas
com sua esposa Masheed. Ele até mesmo
dorme, de vez em quando.
conteúdo
Conteúdo (Sumário)
Introdução xxvii
1 Está Vivo: Adicionando Vida às Suas Páginas Estáticas 1
2 Como Tudo se Combina: Conectando-se ao MySQL 59
3 Criando os Seus Próprios Dados: Crie e Preencha um Banco de Dados 103
4 Sua Aplicação na Web: Aplicações Realistas e Práticas 159
5 Quando um Banco de Dados Não é o Suficiente: Trabalhando com
Dados Armazenados em Arquivos 223
6 Presuma que Estão Todos Querendo Te Pegar: Tom ando a Sua Aplicação Segura 295
7 Lembra de Mim?: Criando Aç|icações Web Personalizadas 345
7V4 Compartilhar é Cuidar: Elimine Código Duplicado 417
8 Colhendo Dados: Controle Seus Dados, Controle Seu Mundo 427
9 Vivendo Melhor Através das Funções: Funções String e Personalizadas 501
10 Regras Para Substituição: Expressões Regulares 561
11 Desenhando Gráficos Dinâmicos: Visualizando seus Dados...e Mais! 605
12 Interfaces com o Mundo: Republicação e Serviços Web 657
i Os Dez Principais Tópicos (Que Não Abordamos): Sobras 713
ii Um Lugar para Brincar: Configure um Ambiente de Desenvolvimento 731
iii O btenha Ainda Mais Proveito: Amplie Seu PHP 749
índice Remissivo 755
Conteúdo (a coisa real)
Introdução
Seu cérebro ligado no PHP e MySQL. você está tentando
aprender alguma coisa, enquanto o seu cérebro está lhe fazendo um favor ao
certificar-se de que você não aprenda. Seu cérebro está pensando “é melhor guardar
espaço para coisas mais importantes, como por exemplo, quais animais selvagens
evitar e se fazer yoga em baixo d'água é uma boa ideia". Então, como enganar o seu
cérebro, fazendo-o pensar que a sua vida depende de aprender PHP e MySQL?
A quem se destina este livro? xxviü
Sabemos o que você está pensando xxix
Metacognição xxxi
Faça seu cérebro lhe obedecer xxxiii
Leia-me xxxiv
Revisão técnica xxxvi
Agradecimentos xxxvii
ix
conteúdo (sumário)
Adicionando Vida às Suas Paginas Estáticas
Está Vivo
Você tem criado ótimas páginas web com HTML, com
toques de CSS. Mas tem percebido que os visitantes do seu site não podem
fazer muita coisa além de olhar passivamente o conteúdo das páginas. A comunicação
está unidirecional, e você gostaria de mudar isso. Na verdade, o que você realmente
gostaria é de saber o que o seu público está pensando. Mas para isso é preciso
permitir que os usuários digitem informações em um formulário web, para que possa
saber o que eles têm em mente. E também precisa ser capaz de processar essas
informações, para que elas lhe sejam entregues. Está começando a parecer que vai
precisar de mais do que HTML para levar seu site para o próximo nível.
HTML é estático e chato 2
PHP dã vida às páginas web 3
Um formulário ajuda Owen a descobrir toda a história 5
Formulários são feitos de HTML 6
O formulário HTML apresenta problemas 8
HTML roda no cliente 10
PHP roda no servidor 11
Os scripts PHP rodam no servidor 12
Use PHP para acessar os dados do formulário 16
Os scripts PHP precisam ficar em um servidor! 18
O servidor transforma PHP em HTML 22
Algumas regras PHP para o seu código 25
Encontrando o nom e perfeito para a sua variável 26
Variáveis servem para armazenar dados de scripts 31
POST é um a variável especial que armazena
dados do formulário 33
$_POST transporta os dados do formulário para o seu script 34
Criando o corpo da mensagem de email com PHP 44
Até mesmo texto simples pode ser formatado... um pouco 46
Newlines precisam de aspas duplas 47
Crie um a mensagem de email para Owen 48
As variáveis armazenam as partes do email 49
Enviando um a mensagem de email com PHP 50
Owen começa a receber emails 53
Owen começa a perder emails 54
conteúdo (sumário)
C o n e c ta n d o -s e M / S o L
Como Tudo se Combina
Saber como as coisas se encaixam, antes de começar a
construir, é uma boa ideia. Você criou seu primeiro script PHP, e ele está
funcionando bem. Mas obter os seus resultados em um email já não é bom o suficiente.
Agora precisa de uma forma de guardar os resultados do seu formulário, para que possa
mantê-los pelo tempo que precisar, e ter acesso a eles quando quiser. Um banco de dados
MySQL pode armazenar seus dados para você. Mas é preciso conectar seu script PHP ao
banco de dados MySQL para fazer isso acontecer.
O formulário de Owen funciona bem. Bem até demais...
MySQL é excelente para armazenar dados
Owen precisa de um banco de dados MySQL
Crie um banco de dados e um a tabela MySQL
A instrução INSERT em ação
Use SELECT para obter dados da tabela
Deixe o PHP lidar com as coisas tediosas do SQL
O PHP permite usar os dados do formulário web de Owen
Conecte-se ao seu banco de dados a partir do PHP
Insira dados com um script PHP
Use funções PHP para falar com o banco de dados
Conecte-se com mysqli_connect()
Construa a query INSERT no PHP
Consulte o banco de dados MySQL com PHP
Encerre sua conexão com mysqli-close{)
$_POST fornece os dados do formulário
Owen precisa de ajuda para peneirar seus dados
91
60
61
62
64
67
70
73
74
76
77
78
80
85
96
86
87
1 Owen sai em busca de Fang 98
Crie e rteencjici um Betnco de Dcufos
Criando os Seus Próprios Dados
Nem sempre você tem os dados de que precisa.
Às vezes você mesmo tem que criar os dados que pretende usar, às vezes
precisa criar as tabelas que irão armazenar esses dados E às vezes precisa criar
o banco que armazenará os dados que precisa criar. Confuso? Você não ficará.
Prepare-se para aprender como criar seus próprios bancos de dados e tabelas. E
se isso não for o suficiente, ainda criará, no processo, a sua primeira aplicação
combinando PHP e MySQL.
A loja Elvis está aberta 104
Elmer precisa de um a aplicação 105
Visualize o projeto da aplicação de Elmer 106
Tudo começa com um a tabela 109
Faça contato com o servidor MySQL 110
Crie um banco de dados para os emails de Elmer 111
Crie um a tabela dentro do banco de dados 112
JPrecisamos definir os nossos dados 113
I Conheça alguns tipos de dados MySQL 114
Crie sua tabela com um a consulta 117
SELECIONE o banco de dados antes de usá-lo 120
DESCRIBE revela a estrutura das tabelas 123
I Elmer está pronto para armazenar dados 125
Crie o script “Adicionar Email” 126
O outro lado da aplicação de Elmer 133
O funcionamento interno do script “Enviar Email” 134
Em primeiro lugar, obtenha os dados 135
mysqli_fetch_array() obtém os resultados da consulta 136
Loop para um WHILE 139
Loop através dos dados com while 140
Você tem email... de Elmer! 145
As vezes, as pessoas querem sair 146
Removendo dados com DELETE 147
Use WHERE e DELETE para apagar
dados específicos 148
Minimize o risco de apagamentos acidentais 149
QueroSerElvis.com é um a aplicação web 154
conteúdo (sumário)
custom
erm
afling(ítf;
A p l i c a r e s R e a lis ta s e p r á tic a s
Sua Aplicação na Web
Às vezes você precisa ser realista e repensar seus planos.
Ou então planejar com mais cuidado logo no começo. Uma vez lançada a sua
aplicação na Web, você poderá descobrir que não planejou suficientemente bem.
Coisas que pensou que funcionariam podem não ser boas o suficiente no mundo
real. Este capítulo dá uma olhada em alguns problemas do mundo real que podem
ocorrer quando você transfere sua aplicação do ambiente de testes para um site real. E
enquanto isso, lhe mostraremos exemplos de códigos PHP e SQL importantes.
conteúdo (sumário)
MateMe&vfccoM
itocyçw
rlIrW
raíT
*.Ja*rw
>
w
ò
M
a
f
c
*
M
aB
v
f
e
«
w
i
f
l
n
f
l
'
l
&
l
E
r*3
u
-,
C
us»ni*r<*!retncw
efl.
nD
&
n
n
y d
e
r
v
i
y
Q
J
W
f
l
h
^
g
u
n
M
d
l
s
k

Qh
r
o
*
W
v
f
l
f
l
l
J
w
s
f
i
g
e
l
i
e
r
r
a
a
b
d
u
e
i
M
n
«
-
«
W
0
S
&
»
/
t
K
r
«
â
J
e
«
OD
c
nD
í
a
o
w
a
r
a
p
e
f
ô
s
^
i
n
g
-
í
f
i
o
p
ô
T
.
í
ô
m
Elmer tem alguns clientes irritados 160
Protegendo Elmer de... Elmer 163
Exija bons dados do formulário 164
A lógica por trás da validação de Enviar Email 165
Seu código pode tomar decisões com IF 166
Testando em busca da verdade 167
IF verifica mais do que apenas igualdade 168
A lógica por trás da validação de Enviar Email 171
Funções PHP para verificar variáveis 172
Teste múlüplas condições com AND e OR 179
Os usuários do formulário precisam de feedback 183
Facilite a entrada e a saída do PHP 193
Use um flag para evitar código duplicado 194
Codifique o formulário HTML apenas um a vez 195
Um formulário que referencia a si raesmo 199
Aponte a ação do formulário para o script 200
Verifique se o formulário foi submetido 202
Alguns usuários ainda estão insatisfeitos 206
As linhas da tabela precisam ser identificáveis individualmente 208
As chaves primárias possibilitam a identificação individual 210
Das caixas de verificação até as IDs dos clientes 215
Faça loop através de um array com foreach 216
xiii
conteúdo (sumário)
T ra b a lh a n d o c o m D a d o s A rm a z e n a d o s ©m A í^ u lV o s
Quando um Banco de Dados Não é o Suficiente
Não acredite no hype... peio menos não naquele sobre
OSbanCOS de dados. Certamente os bancos são maravilhosos para se
armazenar todo tipo de dados que envolvam texto, mas e quanto aos dados binários?
Coisas como imagens JPEG e documentos PDF? Faz sentido armazenar todas essas
figuras da sua coleção de palhetas raras de guitarra em uma tabela de banco de
dados? Geralmente não. Esses tipos de dados normalmente são armazenados em
arquivos, e nós os deixaremos nos arquivos. Mas é inteiramente possível ter o melhor
de dois mundos - este capítulo revela que você pode usar arquivos e bancos de dados
juntos para criar aplicações PHP cheias de dados binários.
Guitarristas virtuais gostam de competir 224
A imagem é a prova 225
aplicação precisa armazenar imagens 226
Planejando os uploads de arquivos gráficos no Guitar Wars 231
O banco de dados das pontuações máximas precisa ser ALTERado 232
Como fazer para o usuário enviar a imagem? 236
Insira o (nome do) arquivo gráfico no banco de dados 238
Descubra o nome do arquivo enviado 239
Para onde foi o arquivo enviado? 244
Crie um lar para os arquivos gráficos enviados 248
Dados compartilhados precisam ser compartilhados 254
Serão necessários dados do script compartilhado 255
Pense em require_once como um “inserir” 256
O mais im portante para as pontuações máximas é a ordem 258
Homenageando o Guitar Warrior núm ero um 261
Formate a maior pontuação com HTML e CSS 262
São permitidas apenas imagens pequenas 267
A validação de arquivos torna a aplicação mais robusta 268
} -
Planeje um a página Admin 272
Gere links para remoção de pontuações na página Admin 275
Os scripts são capazes de comunicarem-se uns com os outros 276
Sobre GETs e POSTs 278
GET, POST e a remoção d e pontuações 280
Isole a maior pontuação para ser removida 283
Controle o quanto você pode remover com LIMIT 284
T o rn a n d o ct -S ua A p lic a ç ã ? S e g u r a
Presuma que Estão Todos Querendo Te Pegar
Seus pais estavam certos: não fale com estranhos, ou peio
menos não confie neles. Na pior das situações, não dê a eies as chaves para
acessar os dados da sua aplicação, presumindo que não vão fazer nada de
errado. Vivemos num mundo cruel, e você não pode partir do princípio que
todos são confiáveis. Na verdade, como desenvolvedor de aplicações web você
precisa ser metade incrédulo e metade adepto de teorias de conspiração. Sim,
as pessoas em geral são más e elas definitivamente querem te pegar! OK, talvez
isso seja um pouco de exagero, mas é muito importante levar a segurança a
sério e elaborar as suas aplicações de forma que elas fiquem protegidas contra
qualquer um que pretenda causar danos.
conteúdo (sumário)
O dia em que a música m orreu 296
Para onde foram as pontuações? 297
Segurança contra os bárbaros 299
Protegendo a página Guitar Wars Admin 300
i A autenticação HTTP exige cabeçalhos 302
ij Tudo Sobre o Cabeçalho 304
Controle os cabeçalhos com PHP 305
Autenticando com cabeçalhos 306
Crie um script Autorizar 314
Guitar Wars Episódio II: Ataque dos Clones de Pontuação 318
Subtração por adição 319
A segurança requer intervenção hum ana 320
Planeje moderação no Guitar Wars 321
Abra espaço para aprovações com ALTER 322
Pontuações não-aprovadas não são dignas 327
O hack de um milhão de pontos 330
Tudo em moderação...? 331
Como exatamente ela fez isso? 333
Enganando o MySQL com comentários 334
O formulário Add Score recebeu um a injeção de SQL 335
Proteja seus dados contra injeções de SQL 336
Um INSERT mais seguro (com parâmetros) 337
A validação de formulários nunca é inteligente demais 339
Cessar fogo! 341
XV
C d ^ n d p A p l i ^ ç ê ^ s W e b p e rS 9 n cú i^ld ctó
7
Lembra de Mim?
Ninguém gosta de ser esquecido, especialmente
usuários de aplicações Web. Se a aplicação tiver que trabalhar a
noção de “comunidade”, ou seja, se for planejado que os usuários interajam com
a aplicação de uma forma pessoal, então ela terá de se lembrar dos usuários.
Você detestaria ter que se apresentar novamente à sua família a cada vez que
entrasse em casa. Não precisa fazê-lo porque seus parentes possuem uma
coisa maravilhosa chamada memória. Mas aplicações web não se lembram das
pessoas automaticamente - é preciso que um desenvolvedor web esperto use
as ferramentas disponíveis (PHP e MySQL, talvez?) para criar aplicações web
personalizadas que realmente sejam capazes de se lembrar dos usuários.
conteúdo (sumário)
Tov*w pis», m nsedtolog Into ar«
Místfiatch*o* w»w nrte-match^er
:
Y
o
t
r
p
u
i
w
e
r
d
V
t
ftb
t
s
e
n
t
J
f
t
.
t
h
s
d
e
a
r
' •
•■
<
. :ijntftlÈ*
,Passtw
rdiJ*«*««•M
„AemftfTíbjythís passwwd in mykeythain
~êwesO
Lastiume:
Gendfr: frwfciMismatch*ViewProfíte
Bm
U
iue:;
City: >0^» Ushtímws jnesâes
State: Ígü FÈPStnwne:Joijao
Ffctnxe N
ísiks
Gfflda1
; Mate
BSrtbâate 1981-H-Q3
L
o
c
a
t
í
n
u A
t
h
e
c
s
,
G
À
Wouklyouliketo
Dizem que os opostos se atraem
O negócio do Mismatch são os dados pessoais
O Mismatch precisa dos logins dos usuários
Preparando o banco de dados para os logins
| Construindo uma interface de usuário para o login
Criptografe as senhas com SHA()
Comparando senhas
Autorizando usuários com HTTP
Fazendo login dos usuários com autenticação HTTP
Um formulário para novos usuários se cadastrarem
Do que é feito o cookie?
Use cookies com PHP
Repensando o fluxo dos logins
Um login baseado em cookies
Fazer logout significa apagar cookies
As sessões não dependem do cliente
Mantendo-se atualizado com os dados das sessões
Renove o Mismatch com as sessões
Faça Logout com sessões
Complete a sessão de transformações
Os usuários não estão se sentindo bem-vindos
As sessões tem vida curta...
...mas os cookies podem durar para sempre!
Sessões + Cookies = Persistência de login superior
346
347
348
351
353
354
355
358
361
365
375
376
379
380
385
389
391
392
393
398
404
406
407
409
conteúdo (sumário)
Elimine Côdigp Duplicado
Compartilhar é Cuidar
Guarda-chuvas não são a única coisa que pode ser
Compartilhada. Em qualquer aplicação web, você poderá encontrar
situações em que um mesmo código encontra-se duplicado em mais de um
lugar. Isso não só é um desperdício de recursos, como também pode levar
a problemas de manutenção, uma vez que você inevitavelmente acabará
fazendo modificações e estas terão de ser efetuadas em mais de um lugar.
A solução é eliminar o código duplicado, compartilhando-o. Em outras
palavras, você mantém o código duplicado em apenas um lugar, e depois,
apenas referencia esse código sempre que precisar dele. A eliminação de
código duplicado resulta em aplicativos mais eficientes, de manutenção
mais fácil, e finalmente, mais robustos..
O Mismatch está em pedaços 421
Reconstruindo o Mismatch a partir de um template 422
Reconstrua o Mismatch com templates 424
O Mismatch está novamente em pé... e muito m elhor organizado 426
0 dâbefiâlho aparece «o ali» de
cada pagina do Mismatch, e exibe ©
titulo da aplidaçSojuntamente tom
un> trtulo específico pagina..
w» título espet$to
Cada pagina do Mismatch
<^ue■
forpevsowàtaadapavào
usuário exigira um todig© de
login, o <ual mantém registro
do usuário-
0 vodape -fomeCe Conteúdo
«a parte de baixo de todas
as paginas do AWatch,
« ^wâí inclui um aviso de
í.opyv-:*Ll
XVII
conteúdo (sumário)
C^nttole Seus üa<fcs, Seu Mundç>
Colhendo Dados
Nada como uma boa colheita de dados no outono, um sem-fim de
informações prontas para serem examinadas, classificadas, comparadas, combinadas,
enfim, qualquer coisa que a sua excelente aplicação web precisar que seja feito.
Compensador? Sim. Mas assim como as colheitas na vida real, é preciso muito trabalho
duro e uma boa dose de conhecimento para se obter controle sobre os dados em um
banco MySQL. Os usuários da web exigem mais do que dados estáticos e enfadonhos.
Eles querem dados enriquecedores... dados compensadores... dados relevantes. Então,
o que você está esperando? Dê a partida no seu trator MySQL e mãos à obra!
Fazendo o desencontro perfeito 428
Os desencontros se referem aos dados 429
Modele o banco de dados com um schema 431
Junte várias tabelas 436
Chaves estrangeiras em ação 437
As tabelas podem combinar linha por linha 438
eT Uma linha leva a muitas outras 439
Checando linhas de muitas-para-muitas 440
Crie um questionário Mismatch 445
Coloque as respostas no banco de dados 446
E possível com andar um formulário com dados 450
Gere o formulário do questionário Mismatch 456
Procure por um pouco de normalidade 462
Ao normalizar, pense em termos de átomos 463
Três passos para se criar um banco de dados normalizado 465
Alterando o banco de dados do Mismatch 469
Então, o Mismatch realmente é normal? 470
Uma consulta dentro de um a consulta
dentro de um a consulta... 472
Vamos todos juntar as tabelas 473
Ligue os pontos 474
Certamente podemos fazer mais com os innerjoins 475
Apelidos para tabelas e colunas 477
Joins, ao trabalho! 478
Cinco passos para um desencontro com sucesso 485
Compare usuários pela “desencontrabilidade” 487
Tudo o que precisamos é um loop FOR 488
conteúdo (sumário)
Funçpes String e persç>ncillzíulas
Vivendo Melhor Através das Funções
As funções levam as suas aplicações para um nível superior.
Você já vem usando as funções internas do PHP para realizar as coisas. Agora é hora
de dar uma olhada em mais algumas funções internas realmente úteis. E depois você
aprenderá a criar suas próprias funções personalizadas para levá-lo mais além do que
sequer imaginava que fosse possível. Bem, talvez não tão longe que você comece a usar
espadas laser, mas as funções personalizadas certamente simplificam o seu código e o
tornam reutilizável.
Strings e funções personalizadas 501
Um bom trabalho arriscado é difícil de encontrar 502
A busca não deixa margem para erros 504
; As consultas SQL podem ser flexíveis com LIKE 505
; Transforme um a string em palavras individuais 510
Implode() cria um a string a partir de substrings 513
Pré-processe a string de busca 519
Substitua caracteres de busca indesejados 520
í A consulta precisa de termos de busca legítimos 524
Copie elementos não-vazios para um novo array 525
As vezes você só precisa de parte de um a string 528
Extraia substrings do início ou do fim 529
Podemos classificar nossos resultados com múltiplas consultas 532
As funções lhe permitem reutilizar código 536
Construa um a consulta com um a função personalizada 537
Funções personalizadas: o quão personalizadas elas realmente são? 538
SWITCH toma muito mais decisões do que IF 542
Dê a build_query() a capacidade de classificar 545
Podemos paginar os nossos resultados 548
O btenha apenas as linhas de que você precisa com LIMIT 549
Controle os links das páginas com LIMIT 550
M antenha registro dos dados da paginação 551
Defina as variáveis da paginação 552
Revise a consulta para ter resultados paginados 553
Gere os links de navegação da página 554
M ontando o script Search completo 557
O script Search completo, continua... 558
xix
conteúdo (sumário)
E x p te s s P e s íle g u lc tfe s
Regras Para Substituição
As funções string são adoráveis. Mas, ao mesmo tempo,
são limitadas. Certamente elas podem realizar tarefas como lhe dizer a
extensão da sua string, truncar a string, trocar certos caracteres por outros. Mas
às vezes você precisa de liberdade para lidar com manipulações de texto mais
complexas. É aqui que as expressões regulares podem ajudar. Elas podem
modificar strings de forma precisa, com base em um conjunto de regras, em vez
de um só critério.
A Riskyjobs permite que os usuários submetam currículos
Decida como deverá ser a aparência dos seus dados
Formule um padrão para números telefônicos
Confira padrões com relação a expressões regulares
Crie padrões usando metacaracteres
Ajuste os padrões com classes de caracteres
Verifique os padrões com preg_match()
Padronize os dados dos números de telefone
Livre-se dos caracteres indesejados
Conferir endereços de email pode ser complicado
Sufixos de domínios estão por toda a parte
Use PHP para verificar o domínio
Validação de email: m ontando o quadro
562
566
569
570
572
579
584
591
592
596
598
599
600
ViSUcdizctndo seus Dados--. eMaís!
Desenhando Gráficos Dinâmicos
É claro que todos nós conhecemos o poder de uma boa
consulta e os consequentes resultados satisfatórios.
Mas os resultados de consultas nem sempre falam por si mesmos. Às vezes é
útil apresentar os dados de uma forma diferente, uma forma mais visual. O PHP
possibilita o fornecimento de uma representação gráfica dos dados: gráficos pizza,
gráficos em barra, diagramas de Venn, desenhos Rorschach, qualquer coisa. Vale
de tudo para ajudar os usuários a compreender os dados que fluem através da sua
aplicação. Mas nem todos os gráficos úteis, em aplicações PHP, se originam do seu
banco de dados. Por exemplo, você sabia que é possível evitar ataques de bots de
spam com imagens geradas dinamicamente?
conteúdo (sumário)
Guitar Wars Reloaded: A Vingança das Máquinas 606
Nenhum formulário de input está a salvo 607
Precisamos separar os humanos das máquinas 608
Podemos vencer a automação usando a automação 611
Gere o texto da senha de CAPTCHA 613
Visualizando a imagem CAPTCHA 614
Por dentro das funções gráficas GD 616
Desenhando texto com um a fonte 620
Gere um a imagem CAPTCHA aleatória 623
A sanidade retorna ao Guitar Wars 625
Adicione CAPTCHA ao script Adicionar Pontuação 627
Cinco graus de oposição 630
Pondo a desencontrabilidade em tabela 631
Armazenando dados do gráfico com barras 632
Lendo entre as linhas com o senhor dos gráficos 635
De um array para outro 636
Crie um array de tópicos desencontrados 638
Formulando um plano para execução de
gráficos de barras 639
Amassando as categorias 640
A matemática das categorias 641
Fundamentos dos gráficos de barras 644
Desenhe e mostre a imagem do gráfico de barras 647
Imagens individuais do gráfico de barras para todos 650
Os usuários do Mismatch estão gostando dos
gráficos de barras 653
xxi
ÍfepukliCcLçÍÍ9 e SetViçPSWeb
U
Interfaces com o Mundo
Existe um grande mundo lá fora, mundo esse que a sua
aplicação web não pode se dar ao luxo de ignorar ou o que
talvez seja mais, você é que não gostaria que o mundo ignorasse a sua aplicação.
Uma excelente maneira de fazer o mundo notá-la é tornar os seus dados
disponíveis para republicação, o que significa que os usuários poderão assinar o
conteúdo do seu site, em vez de ter de visitá-lo diretamente para encontrar novas
informações. Não apenas isso, a sua aplicação pode fazer interfaces com outras
aplicações, através dos serviços web, e pode tirar proveito dos dados de outras
pessoas para fornecer uma experiência mais rica.
conteúdo (sumário)
Algutts clientes de email tèm suporte a
conteúdo “pu sh”»permitindo que você
receba atualizações do site da m esm a
com o recebe m ensagens de email.
Muitos navegadores
web também lhe
permitem exam inar
conteúdo “push" que
revela rapidamente a s
noticias m ais recentes
publicadas em um
determinado site.
Até m esm o dispositivos
m óveis provém a c e sso a
conteúdo ‘'push*, o qual é
enviado autom aticam ente
quando elgo se m odifica no
Owen precisa avisarao mundo sobreFang 658
Envie dados sobre abduções alienígenas para aspessoas 659
O RSSenvia conteúdo web para aspessoas 660
ORSSé naverdade XML 651
Dobanco de dados para o news reader 666
Visualizando RSS 669
O que interessaaum comunicador 671
Gere um envio RSSdinamicamente 672
Crieum linkpara o envio RSS 676
Umvídeorale mais que milpalavras 678
Obtendo conteúdo webde terceiros 680
Republicando vídeos doYouTube 681
;Fazendo uma requisição devídeo noYouTube 682
Owen estapronto para criaruma requisiçãoREST 686
OYouTubefalaXML 690
Deconstruindo uma respostaXMLdoYouTube 694
Visualize os dados de vídeoXML 695
Acesse os dadosXML com objetos 696
De elementos XMLpara objetosPHP 697
Penetre nos dadosXML com objetos 698
Não semum namespace! 699
Cadavez mais avistamentos de Fang 701
Disponibilizevídeos para visualização 702
Formate os dadosde vídeo para exibição 703
$oL>ras
Os Dez Principais Tópicos (Que Não Abordamos)
Mesmo depois de tudo isso, ainda tem mais um pouco A
in
d
a
temos mais algumas coisas que você precisa conhecer. Não seria certo nós as
ignorarmos, mesmo que só precisem de uma breve menção. Portanto, antes de guardar
o livro, dê uma lida nestes pequenos, mas importantes parágrafos sobre PHP e MySQL.
Além disso, uma vez concluído este aqui, só faltarão mais dois pequenos apêndices... e
o índice... e talvez algumas propagandas... e aí o livro realmente acaba. Promessa!
conteúdo (sumário)
#1. Adapte este livro para funções PHP4 e mysql 714
#2. Permissões do usuário no MySQL 716
#3. Relato de erros para o MySQL 718
#4. Erros PHP com tratamento de exceções 719
#5. PHP orientado a objetos 721
#6. Tom ando segura a sua aplicação PHP 723
#7. Proteja sua aplicação de scripts cross-site 725
#8. Precedência de operadores 727
#9. Qual é a diferença entre PHP 5 e PHP 6 728
#10. Reutilizando o PHP de terceiros 730
xxiii
C^nífgute um Ambiente deDesenVplVimentP
1 1 Um Lugar para Brincar
I I Você precisa de um lugar para praticar suas recém-
• • adquiridas habilidades em PHP e MySQL, porém sem tornar
OSSeUS dados vulneráveis na web. É sempre uma boa ideia ter um
local seguro para desenvolver sua aplicação PHP antes de lançá-la no mundo (ou seja,
na web). Este apêndice contém instruções para a instalação de um servidor web, do
MySQL e do PHP, para lhe fornecer um lugar seguro onde possa trabalhar e praticar.
conteúdo (sumário)
Servidor
Crie um ambiente de desenvolvimento PHP 732
Descubra o que você tem 732
Você tem um servidor web? 733
Você tem o PHP? Qual versão? 733
Você tem o MySQL? Qual versão? 734
Comece pelo Servidor Web 735
Passos para a instalação do PHP 737
Instalando o MySQL 738
Passos para a instalação do MySQL no Windows 739
Habilitando o PHP no Mac OS X 742
Passos para a instalação do MySQL no Mac OS X 742
Passando do ambiente de produção para um site no ar 744
Dump seus dados (e as suas tabelas) 745
Prepare-se para usar seus dados 745
Mova os dados consolidados para o servidor ativo 746
Conecte-se ao servidor ativo 747
conteúdo (sumário)
9Ê9
III
Araplí
lie Seu
Obtenha Ainda Mais Proveito
Sim, você pode programar com PHP e MySQL e criar
Ótimas aplicações Web. Mas você sabe que ainda deve haver mais a
se explorar. E há. Este pequeno apêndice irá lhe mostrar como instalar a extensão
mysqli e a extensão biblioteca gráfica GD. Em seguida, mencionaremos mais
algumas extensões do PHP que você poderá querer baixar. Porque às vezes não
tem problema em querer sempre mais.
Estendendo o seu PHP 750
E no Mac.. 753
XXV
Como UsorEsteLíVrc>
Introdução
Nesta seção, respondemos à ‘
»»iporfcâ^ie per^wvfca--
u&
ivfcdo> por <
^
w
eíoi <^ue eles doSoÊdV
’âm isso e» um
livro de PtfP e My£$U”
xxvii
como usar este fivro
A quem se destina este livro?
Se você puder responder “sim” a todas estas perguntas:
Você é um web designer com experiência em HTML ou
XHTML, e deseja melhorar as suas páginas?
Você deseja ir além do simples HTML e aprender,
entender e se lembrar como usar PHP e MySQL para
criar aplicações web?
Você prefere conversas informais e estimulantes, em vez
de aulas enfadonhas e acadêmicas?
então este livro é para você.
Quem provavelmente deve fugir deste livro?
Se você puder responder “sim” a qualquer uma destas perguntas:
Você não tem conhecimento nenhum sobre conceitos básicos de
programação, tais como variáveis e loops?
(Mas mesmo que jamais tenha programado antes, você provavelmente
será capaz de absorver os conceitos-chaves de que precisa, neste livro.)
Você é um super desenvolvedor web PHP procurando
por um livro de referência?
Você tem medo de tentar algo diferente? Você prefere
arrancar um dente do que misturar listras com xadrez?
Você acha que um livro técnico não pode ser sério se
um dos exemplos é um banco de dados sobre abduções
alienígenas?
então este livro não é para você.
Nota Ao d.fjHa.e.fc d o d t f l d í „ â r k e t i
de frredi-fxj.
introdução
Sabemos o quevocê está pensando
“Como isso aqui pode ser um livro de PHP e MySQL sério?”
“Por que tantas figuras?”
“E realmente possível aprender desta forma?”
Sabemos o que o seu cérebro está pensando
Seu cérebro pede novidade. Ele está sempre buscando, vasculhando,
esperando por algo fora do comum. Ele foi construído dessa forma, e
isso lhe ajuda a se m anter vivo..
Assim, o que o seu cérebro faz com todas as coisas rotineiras, comuns,
normais, que você encontra? Faz todo o possível para evitar que elas
interfiram no trabalho real do cérebro - registrar coisas que sejam
importantes. Ele não se dá ao trabalho de armazenar as coisas chatas;
elas nunca conseguem passar pelo filtro “isto aqui obviamente não é
importante”.
Como o seu cérebro sabe o que é ou não é importante? Suponha que
você esteja fazendo um a caminhada na selva e um tigre pule na sua
frente; o que acontece com a sua mente e o seu corpo?
Os neurônios se acendem. As emoções fluem. A química dispara.
E é assim que o seu cérebro sabe que...
Isto deve ser importante! Não se esqueça!
Mas imagine que você esteja em casa ou em um a biblioteca. É uma
área segura, aconchegante, livre de tigres. Você está estudando. Se
preparando para uma prova. Ou tentando aprender algum difícil
assunto técnico que o seu chefe acha que só vai levar um a semana, dez
dias no máximo.
Só um problema. Seu cérebro está tentando lhe fazer um grande favor. Ele
está tentando se certificar de que este conteúdo obviamente desimportante
não ocupe recursos que são escassos. Recursos esses que são mais bem
empregados armazenando-se as coisas realmente importantes. Como
tigres. Como o perigo do fogo. Como esconder rapidamente ajanela do
navegador com o vídeo de discos voadores no You Tube, antes que o seu
^ ÚrcU-c
Isto ;
,mF'»rtâKit'
chefe apareça.
E não há um a forma simples de dizer ao seu cérebro “ei, cérebro,
muito obrigado, mas não im porta o quanto este livro seja chato,
e quão poucas emoções eu esteja sentindo neste exato momento,
eu realmente quero que você se lembre destes assuntos.”
Videos de ÍH/Ms no You
Tube sa©obvia»wewte »«ais
mievessa>vfces para o seu
ievebv-o do ^ue um liw-o
de TJ.
xxix
como usar este livro
tíntendeni9s c
jue o JeítPr c[e um JiVtP cfa sène ^Jse a C^eça!
Então, o que é preciso para se aprender algo? Primeiramente, você precisa
entender o assunto, e depois se certificar de que não vai esquecê-lo. Não
adianta tentar entulhar fatos dentro da sua cabeça. Com base nas pesquisas
mais recentes em ciência cognitiva, neurobiologia e psicologia da educação,
é necessário muito mais do que texto em uma página para um verdadeiro
aprendizado. Nós sabemos como chamar a atenção do seu cérebro
Alguns dos princípios de aprendizado Use a Cabeçal:
Use o recurso visual. Imagens são muito mais memoráveis do que palavras
sozinhas, e tomam o aprendizado muito mais eficiente (até 89% de melhoria em
estudos sobre lembrança e transferência). Eias também tornam as coisas mais
compreensíveis. Coloque as palavras dentro ou perto das imagens às quais
elas se referem, em vez de na parte de baixo da página ou na página seguinte, e
os estudantes terão duas vezes mais probabilidade de conseguir resolver problemas
relacionados ao conteúdo.
U se um estilo coiw ersacional e personalizado.
Em estudos recentes, os estudantes tiveram um desempenho
até 40% melhor, em testes pós-aprendizado, quando o
conteúdo falava diretamente ao leitor, usando um estilo
conversacional, em primeira pessoa, do que quando se usava
um tom mais formal, Conte histórias, em vez de lecionar. Use 1
casual. Não se leve muito a sério. Hm que você prestaria mais c
estimulante conversa informal ou uma aula?
Faça o estudante pensar um pouco m ais profun
Em outras palavras, a não ser que você ativamente exercite os
neurônios, não vai acontecer muita coisa dentro da sua cabeç
precisa estar motivado, engajado, curioso e inspirado para res
problemas, chegar aconclusões e gerar conhecimento novo. f
isso, você precisa de desafios, exercícios e perguntas que prov
o raciocínio, bem como de atividades que envolvam ambos os
hemisférios do cérebro e vários sentidos.
Obtenha - e mantenha - a atenção do leitor. Tod<
passamos por uma situação de "eu realmente quero aprender
não consigo passar da página um acordado". O seu cérebro pr
em coisas que sejam fora do comum, interessantes, estranhas,
assunto técnico novo e difícil não precisa ser enfadonho. O se
mais rapidamente se não for.
Provoque as emoções. Nós sabemos que a sua capacid
algo depende largamente do conteúdo emocional. Você se lei
que se importa. Você se lembra de algo quando sente algo. N
<
de histórias de partir o coração sobre um garoto e seu cachori
emoções como surpresa, curiosidade, diversão, "que ... é essa?
fera!” que vem quando você resolve um quebra-cabeças, apre
acha que é difícil ou percebe que você sabe algo que o Bob "e
do departamento de engenharia, não sabe.
U**a pequena domdào- Na verdade, nés
íe**os Kistória de pariir o doraça© sobre
um $ârci# e seu ÁSâherro - o dadhorro -Ç
oi
abduzido por alienígenas, e vode ajudará ©
* 3»kí/flB-f-Srá—
ioJ.
introdução
Metacognipão: pensando sobre pensar
Sevocê realmente quer aprender com mais rapidez e mais profu
preste atenção ao modo como prestamos atenção. Pense sobre c
pensa. Aprenda sobre como você aprende.
raramente nos ensinaram a aprender.
Masnós partimos do princípio de que, sevocê está com este livro
é porque realmente quer aprender a criar sitesbaseados em bane
dados, usando PHP e MySQL. Eprovavelmente não quer despenc
tempo. Pará poder usar o que você irá ler neste livro, terá de se lei
do que leu. E para isso,você precisa entender o assunto. Para tirai
proveito possível deste livro ou de qualquerlivro ou experiência d
assuma a responsabilidade sobre o seu cérebro. Focalize o seu
cérebro neste conteúdo.
O segredo é fazer o seu cérebro ver o novo material que você
está aprendendo como sendo Realmente Importante. Crucial
para o seu bem-estar. Tão importante quanto um tigre. Caso
contrario, você se verá numa batalha constante, com o seu
cérebro fazendo o possível para que o novo conteúdo não
seja gravado..
Então, como é que você faz com que o seu
cérebro trate o “PHP e MySQL” como se ele fosse um
tigre faminto?
Existe a forma lenta e tediosa, e existe a forma mais rápida e mais
eficiente. Aforma lenta é pura repetição. Você obviamente sabe
é possível aprender e se lembrar até dos assuntos mais chatos, se
continuar empurrando repetidamente a mesma coisa para o seu
cérebro. Com suficiente repetição, seu cérebro diz “ele não sent
isto é realmente importante, mas continua olhando as mesmas c
repetidas e repetidas vezes, então suponho que deve ser importa
Aforma maisrápida éfazerqualquercoisaque aumente aatividade
cerebral, ede preferência, diferentes tipos de atividade cerebral.As
listadasna páginaanterior sãoumagrande parte dasolução, e sãoo
que comprovadamente ajudam o seucérebro a trabalharem seufav
exemplo, alguns estudosmostram que colocarpalavras dentro dasfí
que elasdescrevem (emvezde colocá-lasem algum outro lugarna f
como, porexemplo, em umalegenda ou no corpo do texto) obriga
cérebro atentarentender arelação entre aspalavrase afigura, e ist<
maisneurônios seativarem. Quando mais neurônios se ativam,há n
chancesde oseucérebro entender que istoé algo aque'rale apena
atenção, epossivelmenteregistrar.
Um estilo conversacional ajuda porque as pessoas tendem a pres
mais atenção quando percebem que estão envolvidas em uma cc
uma vez que, nessa situação, espera-se que elas acompanhem o <
está sendo dito para saber quando e como responder. O mais fai
é que o seu cérebro não necessariamente liga se a “conversa”é e
você e um livro! Por outro lado, se a escrita tiver um estilo form;
seu cérebro o perceberá da mesma forma como a experiência d
uma lição sentado em uma sala de aula cheia de estudantes pass
Não é preciso ficar acordado.
Mas as figuras e o estilo conversacional são apenas o início...
Amaioria das pessoas não faz aulas de metacognição ou de teori
aprendizado na escola. Sempre se esperou que nós aprendêsseir
XXXI
como usar este f/vro
Um Desencontro!
Ítilnoí
ã • r
n t i V ' A Ta PiUç de -tenror
Aqui esta o que NOS fizemos:
Nós usamos figuras, porque o seu cérebro está ajustado para prestar atenção
em sinaisvisuais, e não em texto. Pelo menos no que concerne ao seu
cérebro, uma imagem realmente vale por mil palavras. E quando texto e
imagens precisam trabalharjuntos, nós colocamos o texto dentro das figuras,
porque o seu cérebro funciona de forma mais eficiente quando o texto se
encontra dentro da coisa a que ele se refere, em vez de em uma legenda ou
escondido em algum lugar dentro do texto.
Nós usamos redundância, dizendo a mesma coisa de formas diferentes e com
diferentes tipos de mídia, e visando a múltiplos sentidos, para aumentar a
chance de o conteúdo ser registrado em mais de uma área do seu cérebro.
Nós usamos conceitos e figuras de formas inesperadas, porque o seu cérebro
está ajustado para prestar atenção em novidades, e usamos figuras e ideias com
pelo menos algum conteúdo emocional, porque o cérebro está ajustado
para prestar atenção à bioquímica das emoções. Aquilo que nos faz sentir
algo é mais provável de serlembrado, mesmo que esse sentimento não seja
nada mais que um pouco de humor, surpresa ou interesse.
Nós usamos um estilo personalizado, conversacional, porque o seu
cérebro está ajustado para prestar mais atenção quando ele acredita que
você está envolvido em uma conversação do que quando pensa que está
passivamente ouvindo uma apresentação- Seu cérebro faz isso mesmo
quando você está lendo.
Nós incluímos mais de 80 atividades, porque o seu cérebro está ajustado
para aprender e se lembrar mais quando você faz algo do que quando lê
sobre algo. Efizemos os exercícios desafiadores, porém resolvíveis, porque
isso é o que a maioria das pessoas prefere.
Nósusamosváriosestilos de aprendizado, porque você poderá preferir
procedimentos passo-a-passo, enquanto que outras pessoaspoderão querer
entender o quadro geral primeiro, e outras ainda sóquerem verum exemplo.
Masindepen dentemente do seu método preferido de aprendizado, todo
mundo sebeneficia emver omesmo conteúdo representado de diversasfornias.
Nós incluímos conteúdo para ambos os hemisférios do seu cérebro,
porque quanto mais partes do seu cérebro você utiliza, maior a
probabilidade de você aprender e se lembrar, e maior o tempo
durante o qual conseguirá se manter focado. Uma vez que trabalhar
um lado do cérebro frequentemente significa que o outro lado terá um M w
L J U Ê L Ê / x Z
tempo para descansar, você poderá ser mais produtivo nos estudos, por um
período de tempo maior.
Nós incluímos estórias e exercícios que apresentam mais de um ponto
de vista, porque o seu cérebro está ajustado para aprender com mais
profundidade quando é forçado a fazer avaliações ejulgamentos.
Nós incluímos desafios, com exercícios e fazendo perguntas que nem sempre
tem uma resposta direta, porque o seu cérebro está ajustado para aprender
e se lembrar quando precisa trabalhar em algo. Pense no seguinte: não é
possívelfazer seu corpo ficar em forma apenas olhando as pessoas malhando
na academia. Mas nós fizemos nosso melhor para garantir que, quando
estiver trabalhando duro, será sempre nas coisas certas, para que não tenha
que gastar um neurônio sequer a mais do que o necessário processando um
exemplo difícil de entender ou tentando decifrar um texto difícil, cheio de
termos técnicos obscuros ou sisudo demais.
Nós usamos pessoas. Nas estórias, exemplos, figuras, etc., porque, bem,
porque você é uma pessoa. E o seu cérebro presta mais atenção nas pessoas
do que nas coisas.
lente isto'
NAO
CCNFÏE
;$B3p3
scaaSséi?
introdução
Veja o que fazer para que o seu
cérebro se curve em sinal de submissão
Ok, fizemos a nossa parte. O resto é com você. Estas dicas funcionam
como um ponto de partida; ouça o seu cérebro e descubra o que
funciona e o que não funciona para você. Experimente coisas diferentes.
fcíeH* jsta pájina c cole na
porta da sua geladeira.
Vá devagar. Quanto mais você entende,
menos você tem que memorizar.
Não leia, simplesmente. Pare e pense. Quando
o livro lhe apresentar uma pergunta, não pule
direto para a resposta. Imagine que uma pessoa
real está lhe fazendo a pergunta. Quanto mais
aprofundadamente você forçar o seu cérebro a
pensar, maior a sua chance de realmente aprender
e se lembrar do que aprendeu.
Faça os exercícios. Faça suas próprias |
anotações.
Nós elaboramos os exercícios, mas se os
fizéssemos para você, isso seria como ir à
academia e ter alguém para m alhar por você.
E não basta só olhar os exercícios. Use um
lápis. Há muita evidência de que a atividade
física durante o processo de aprendizado pode
m elhorar este último.
Leia as seções “Não Existem i
Perguntas Idiotas”.
Todas elas. Elas não são com entários opcionais
fazem parte do conteúdo central! Não as deixe
de lado.
Que isso seja a última coisa que você
lê antes de dormir. Ou pelo menos a
última coisa desafiante
Parte do aprendizado (especialm ente a
transferência para a m em ória de longo
prazo) ocorre depois que você fecha o livro.
Seu cérebro precisa de algum tem po para
realizar todo o processam ento. Se você tentar
absorver novas inform ações durante esse
tem po, um a parte do que você acabou de
apren d er será perdida.
i Beba água. Em grande quantidade.
Seu cérebro funciona m elhor quando envolvido
em um bom banho. A desidratação (que pode
acontecer antes mesmo de você sentir sede)
prejudica as funções cognitivas.
0 PHP o MySQL. ÍKe £er«*>'rte»* éríar ^
vjebreais —naosc es^ueta y
de envia-las e C*perimer>tí-!as em um
servidor y»eb vevdadeiro..
Converse sobre o que está lendo.
Em voz alta
Falar ativa uma parte diferente do cérebro. Se você
quer entender algo ou aumentar as suas chances
de se lembrar do assunto depois, pronuncie-o em
voz alta. Melhor ainda, tente explicá-lo, em voz alta,
a outra pessoa. Você aprenderá mais rapidamente
e poderá descobrir ideias que não tinha percebido
ainda durante a leitura,
lOuça o seu cérebro.
Preste atenção para saber se o seu cérebro
está ficando sobrecarregado. Se você perceber
que está começando a ler superficialmente ou
esquecer o que acabou de ler, é hora de fazer
um a pausa. Uma vez que você passa de certo
ponto, não é possível aprender mais rápido
tentando absorver mais e mais conteúdo e
poderá até prejudicar o processo.
^Sinta algo.
Seu cérebro precisa saber que isto é
importante. Envolva-se com as estórias. Crie
as suas próprias legendas para as fotos.
Resmungar sobre um a piada ruim ainda é
m elhor do que não sentir nada.
Escreva bastante código.
Só existe um a forma de aprender a programar:
escrevendo um monte de código. E é isso que
você irá fazer ao longo deste livro. Programar
é uma habilidade, e a única forma de se ficar
bom nela é praticando. Nós iremos lhe oferecer
muitas oportunidades de praticar: cada capítulo
terá exercícios que apresentam problemas para
você resolver. Não deixe de fazê-los - uma boa
parte do aprendizado acontece quando você
resolve os exercícios. Nós incluímos soluções -
não tenha medo de dar uma olhada na solução
caso não consiga resolver algum exercício! (é
comum um pequeno detalhe atrapalhar toda a
resolução) Mas tente resolver o problema antes
de olhar as soluções. E, definitivamente, faça o
exercício funcionar antes de passar para a parte
seguinte do livro.
XXXIII
como usar este livro
Leia-me
Isto é uma experiência de aprendizado, e não um livro de referência. Nós
deliberadamente retiramos tudo que pudesse atrapalhar o aprendizado de
qualquer que seja o assunto tratado em um determinado ponto do livro. E
na primeira leitura, você precisa começar pelo começo, porque cada capítulo
assume que você aprendeu o que viu no anterior.
Nós começamos ensinando alguns conceitos simples de
programação e fundamentos de conexão a banco de dados,
em seguida apresentamos funções PHP e instruções MySQL
mais complexas, e finalmente mostramos alguns conceitos
mais complexos sobre aplicações.
Embora seja importante permitir aos usuários adicionar dados e a retirar
dados de uma aplicação web, antes disso, é preciso primeiramente, entender a
sintaxe tanto do PHP quanto do MySQL. Assim, nós começamos apresentando
instruções PHP e MySQL que você pode experimentar na prática. Assim,
você poderá imediatamente fazer algo com PHP e MySQL, e começará a se
sentir estimulado em usar essas tecnologias. Depois, mais adiante no livro, lhe
mostraremos as boas práticas de projeto de aplicações e de bancos de dados.
Nesse ponto,já terã um sólido domínio da sintaxe de que vai precisar e poderá
se concentrar em aprender os conceitos.
Nós não abordaremos todas as instruções, funções ou
palavras-chaves do PHP ou MySQL
Teria sido possível colocar cada instrução, função e palavra-chave do PHP e do
MySQL neste livro, mas nós achamos que iria preferir um livro que não fosse
do tamanho de um catálogo telefônico, e lhe ensinasse as instruções, funções
e palavras-chaves mais importantes. Apresentaremos aquelas que você precisa
conhecer, e que usará em 95% do tempo. E após terminar este livro, terá a
confiança para procurar sozinho informações sobre aquela função de que
precisa para terminar a aplicação que acabou de escrever. ^ ^ ^ ^ A
Nós estamos abordando o PHP 5 e o MySQL 5.0.
Devido ao fato de muita gente ainda usar o PHP 4 ou 5, nós evitamos usar
códigos específicos para o PHP 4, 5ou 6 sempre que possível. Sugerimos que
você use o PHP 5ou 6 e o MySQL 5 ou 6 ao estudar os conceitos deste livro.
No desenvolvimento deste livro, nos concentramos no PHP 5 e no MySQL
5, ao mesmo tempo nos certificando de que o código fosse compatível com
versões posteriores.
Você precisa de um servidor web com suporte a PHP.
O PHP precisa ser executado através de um servidorweb para funcionar
corretamente. Você precisa do Apache ou de algum outro servidorweb
instalado na sua máquina local, ou em alguma máquina à qual você tenha
algum acesso, para que possa executar comandos MySQL sobre os dados.
Consulte osApêndices ii e iii para instruções sobre como instalar e estender o
PHP e o MySQL.
Na verdade, voòe
pode wsâv o
tovn este SW
voj
-Çâz/ndo al$u»as
modiíitadoes ao
todifto. Consulte o
introdução
Nós usamos o MySQL.
Embora exista uma linguagem SQL Padrão, neste livro nós usaremos a
sintaxe particular do MySQL. Com apenas algumas poucas modificações na
sintaxe, o código deste livro deverá funcionar no Oracle, MS SQL Server,
PostgreSQL, DB2 e em mais alguns outros Sistemas de Gerenciamento de
Bancos de Dados Relacionais (Relational Database Management Systems ou
RDBMSs) existentes. Você terá de pesquisar asfunções e a sintaxe particulares
do PHP, para se conectar a esses outros RDBMSs. Se fôssemos abordar todas
asvariações de sintaxe para cada comando, este livro teria muito mais páginas
do que tem. Nós gostamos das árvores, por isso nos limitamos ao MySQL.
As atividades NÃO são opcionais.
Os exercícios e atividades não são opcionais; fazem parte do conteúdo central
do livro. Alguns deles servem para ajudar a memorização, outros para o
entendimento e alguns irão lhe ajudar a pôr em prática o que acabou de
aprender. Não deixe de fazê-los. As palavras cruzadas são a única coisa que
não precisa fazer, mas são boas para dar ao seu cérebro uma chance de pensar
de uma forma diferente nas palavras e termos que você está aprendendo.
A redundância é intencional e importante.
Uma diferença importante de ura livro Use a Cabeça! é que nós queremos
que você realmente entenda o assunto, E queremos que termine este livro
lembrando-se do que aprendeu. Amaioria dos livros de referência não tem
a retenção e a recuperação como alvo, mas este é um livro de aprendizado, e
portanto, verá alguns conceitos aparecendo mais de uma vez.
Os exemplos são os mais simplificados possíveis.
Nossos leitores nos dizem que é frustrante ter que navegar por 200 linhas
de um exemplo, procurando pelas únicas duas linhas que eles precisam
entender. Amaioria dos exemplos deste livro é mostrada dentro do menor
contexto possível, para que a parte que você está tentando aprender fique
clara e simples. Não espere que todos os exemplos sejam super robustos ou
sempre completos - eles foram escritos especificamente para o propósito
didático, e não são necessariamente 100%funcionais.
Nós colocamos todos os códigos de exemplo e aplicações na Web, para que
você possa copiar e colar partes deles no seu editor de texto ou Terminal
MySQL ou então enviá-los como estão para o seu próprio servidorweb, para
realizar testes. Você os encontrará em
h t t p : / / w w w .altab o o k s. co m .b r
Os endereços de websites de terceiros podem ser alterados ou desatualizados
a qualquer momento pelos seus mantedores, sendo assim, aAlta Books não
controla ou se responsabiliza por qualquer conteúdo de websites.
Vários cios
exemplos, pov-e*»,
são aplidadoes w«b
£o*p|eiasf dapa«s
de +azer Coisas bew
»
poderosas..
Os exercícios Poder do Cérebro não tem respostas.
Para alguns deles, não existe uma única resposta; para outros, parte da
experiência didática das atividades Poder do Cérebro é você decidir se e em
que contexto as suas respostas estão corretas. Em alguns dos exercícios Poder
do Cérebro, você encontrará dicas para lhe guiar na direção correta.
XXXV
equipe de revisão
Revisão técnica
v W e AH» 1>âvid Bri99s Will Hav*-is Stephanie Liese Steve /VJilano
Revisores Técnicos:
JeremeAllené um desenvolvedor web sênior com
experiência no uso das tecnologias mais avançadas
para a criação de aplicações web. Ele tem mais de
nove anos de experiência no uso de PHP, MySQL,
bem como vários outros frameworks, sistemas
operacionais, linguagens de programação e software
de desenvolvimento.
DavidBriggs é um autor de livros técnicos e
engenheiro de localização de software que vive
em Birmingham, Inglaterra. Q uando não está
sendo detalhista sobre como guiar os usuários
através de algum software particularm ente difícil,
não tem nada que ele goste mais do que ir ao
parque local com sua esposa, Paulette e Cleo, o
cachorro da família.
WillHarris é o responsável por um departam ento
de TI que fornece serviços para 11 empresas
em 4 continentes, e é o Vice-Presidente da filial
em Las Vegas do PASS (Professional Association
for SQL Server). A noite, ele entra num a cabine
telefônica, coloca o seu uniform e web 2.0, e sai
por aí ajudando os designers e desenvolvedores
do Powered By Geek a garantir que as suas
plataformas de dados permaneçam flexíveis,
portáteis, de fácil manutenção e RÁPIDAS,
usando MySQL e Rails. Ele também gosta de
passar seu tempo com sua esposa, Heather, suas
lindas filhas Mara e EUie, e seu cachorro Swiper
Stephanieliese é um a instrutora técnica e
desenvolvedora web em Sacramento, Califórnia.
Quando ela não está pregando as virtudes do
código que obedece aos padrões ou removendo
bugs de algum layout CSS, você a encontrará
suando em um a pesada aula de yoga.
Hâv-vey ChHs Shi-Ple-tt
Quando SteveMilano não está escrevendo código
para o The DayJob™ ou tocando punk rock com sua
banda, a Onion Flavored Rings, em algum porão mal
ventilado, ele provavelmente está em casa com seu
laptop, negligenciando a companhia felina de Ralph
ou a companhia humana de Bianca.
Harvey Quameii desistiu de um a carreira em
programação de computadores para se juntar
ao chique e glamouroso mundo universitário.
Atualmente, é Professor Associado de Inglês
e Humanities Computing na Universidade
de Alberta, onde dá aulas sobre cybercultura,
literatura do século XX e desenvolvimento web -
incluindo PHP e MySQL.
ChrisShifletté o Chefe de Tecnologia da OmniTI,
onde lidera a prática de segurança de aplicações
web e guia a iniciativa de desenvolvimento web.
Chris é um reconhecido líder nas comunidades
de segurança do PHP e de aplicações web - um
blogueiro bastante lido em shiflett.org, um
popular palestrante em conferências no mundo
todo, e o fundador do PHP Security Consortium.
Seus livros incluem Essential PHP Security
(O’Reilly) e HTTP Developer’s Handbook (Sams).
introdução
Agradecimentos
Nossos editores:
Muito obrigado a Brett McLaughlin pela incrível
sessão de storyboarding que nos colocou
no caminho certo, e pelo seu compromisso
inquebrantável com o aprendizado cognitivo.
Este livro não existiria se não fosse pelo esforço,
paciência e persistência heróicos de Sanders
Kleinfeld. Ele sempre conseguia apanhar os pinos
com os quais estávamos fazendo malabarismo, toda
vez que inevitavelmente deixávamos cair um (ou
três!), e somos gratos por isso. Esperamos que ele
tenha a chance de descansar por alguns dias antes
de encarar um outro projeto tão difícil quanto este.
A equipe O’Reilly:
Obrigado a Lou Barr pelas suas
fenomenais habilidades em
design, que fizeram este livro ter
uma aparência tão boa.
Obrigado também a Brittany Smith por
todo o seu trabalho em cima da hora e
a Caitrin McCollough por colocar no ar
os sites de exemplo. E a Laurie Petrycki
por acreditar que nós poderíamos
escrever mais um ótimo livro da série
Use a Cabeça!
Sanders tíeiníeid
E também:
Finalmente, muitíssimo obrigado a ElvisWilson
por elaborar os vídeos de alienígenas no You Tube
p ara o C apítulo 12. Ó tim o trabalho! E specialm ente
considerando que ele é um simples diretor de arte do
tempo das cavernas.
xxxvii
1 Adicionando Vida às Suas PáginasEstáticas
* + Está Vivo
Você tem criado ótimas páginas web com HTML, com recursos de
CSS mas tem percebido que os visitantes do seu site não podem fazer muita coisa além de olhar
passivamente o conteúdo das páginas. A comunicação apresenta-se de forma unidirecional e
você gostaria de mudar isso. Na verdade, o que você realmente gostaria é de saber o que o se u
p ú b lico está pen san d o . Mas para isso precisa permitir que os usuários digitem informações em
um formulário web, para que possa saber o que eles têm em mente. E seu site precisa ser capaz
de processar essas informações, para que elas lhe sejam entregues. Está começando a parecer
que você irá precisar de mais do que HTML para levar seu site para o próximo nível.
este é um novo capítulo ► 1
as vezes somente HTML não é suficiente
HTML é estático echato
O HTML é ótimo para se criar páginas web, até aí vocêjá sabe. Mas, e
quando você precisa que as páginas realizem alguma ação? Suponha que
seja necessário fazer uma busca em um banco de dados ou enviar um
email... como fazer? O HTML deixa a desejar, porque é uma linguagem sem
vida, elaborada para exibir informações que nunca se modificam.
0 HTML- c óWo ^«and©
a ‘m-temçao e apenâ*
mas
towparblHar w»a do
seu VidH
o de estimâ^o--
»ao tawfco guando desejô
ir>'tera^iv' to» cs visitantes
do seu site-
©
Estas pessoas
esta© em busda
interação.
O servidorweb representa uma grande parte
do problema com o HTML estático, umavez
que ele funciona como nada mais que um
mecanismo de entrega sem graça. O navegador
requisitauma página, o servidor responde
com HTML, fim da história. Para transformar
sitesem aplicaçõesweb interativas, o servidor
precisa assumir um papel novo, mais dinâmico...
um papel possibilitado pelo PHP.
C»m páginas HTML
pureis, 9 seiVidor
sim p le sm e n te setV e
HTML estático, <jue
SP e de eXibít
coijtôúdp.
Co» uma pequena
ajuda do servido»-/
adicionando vida às suas páginas estáticas
o — '»ctvioor'
PttPdá vida às páginas web
O PHP lhe permite manipular o conteúdo das páginas
web no servidor, imediatamente antes de a página ser
enviada ao navegador cliente. Funciona da seguinte
maneira: um script PHP é executado no servidor, e pode
alterar ou gerar código HTML à vontade. Uma página
HTML então é entregue ao navegador, que não sabe e
nem liga se há PHP envolvido na produção ou zyuste do
HTML, no lado do servidor.
- j 0 dodifto HTML destas
*T 'rtoTM i P0'" PHP, e pode se
^ ’lr'âs — nriodiíiÊar dinawitameníe,
no^ma»S|»as f defendendo do que a
«ri*. fo, jarado v -
dinamita^ente 1
aivavés de PHP, no
servidcv
Com ?H? na parada,
9 seíVxdot Web
e cap eis d e £ e ra r
páginas HTML de
fotma dinâmica,em
tempp real.
PttP Sdo
ain»ia2íhados «o
^ — wvidor web, o^de
r 530 P^essados e
depois os resultados
entreves ao
^vegader £o»,o
Painas HTML.
Servidor web
Navegador
web cliente
Páginas HTML dinâwõtas^^
SCrwodi-fÍÊ3w> e»» 'res^ostâ
à iógita frogvamáiida
presente nos sdripis
PHP, -tornando—
os
intnveiwente íle*íveis.
Banco de
dados MySQL
N A
Os sòrip-b PHP ÒonW
tádíp HTML e ftádiy>
de sdnpt PHP, oi V *s
deterwinaw o modo towo o
tód',50 HTML t «.angulado-
0 PHP armazina e retira
dados de um banto de
dâdos e os incorpora ao
úodigo HTML gerado.
você esté ago/ ► 3
Cães no espapo
Este é o O w en. Ele p erd e u seu cachorro, Fang. Mas
en c o n trar seu cão não sc restringe a um a sim ples larefa
dc p ro c u r a r p e lo bairro. A co n te ce q ue Fang foi abduzido
p o r alienígenas, o que ex p an d e a busca de O w en p o r todo
o universo. O w en sabe um pouco de HTML. e CSS e acha
que um site personalizado p o d eria ajudá-lo a resolver seu
p roblem a, ao p erm itir q u e outras pessoas com partilhem
suas p róprias experiências de abdução alienígena.
Mas, para o b ter inform ações das pessoas, O w en precisará
de um fo rm u lário web capaz de receb er in p u t (en trad a
de dados) dos usuários e notificá-lo sobre esse input. Sem
pro b lem a - o H TM L possui várias tags para a criação de
form ulários web.
Os de-balv»es sao »as o
sâWos t »yt
avrebatado ««* < M a° 50 tcu
_ Y&r umV3'© lwz»
adicionando vida às suas páginas estáticas
Um formulário ajuda Owen a descobrir toda a história
O novo site de Owen, AliensMeAbducteme.com, tem por objetivo conectá-lo com
abduzidos que possam ajudar a esclarecer um pouco sobre o desaparecimento de Fang.
Owen sabe que precisa de um formulário HTML para requisitar histórias de abdução dos
visitantes e que precisa descobrir se por acaso, eles viram Fang durante as suasjornadas
interestelares. Mas Owen precisa de ajuda para conseguir montar o site e colocã-lo no ar.
Eis o que ele tem em mente para o formulário.
Este é o tampo para 0
ewieveço de emaii do visitante-
, 0V
JÉK<^uer uma
dcsâriçâo -Písifii
aliehs.
ísiââ dos
Owtr, espera <ue al^wcm
responda sim, «^
*e eles viram
*a espaçwave alienígena-
^uais^uçv fiomentirios
adiciowais Sâo àolotàda a^ctí.
Òvjen deseja redeber uma
mensagem de em
a»! guando o
usuirio submeter o -formulário-
£ste -formulário c
lOO%t pur© HTML./
O que você achou do formulário HTML de Owen?
Você consegue pensar em quaisquer problemas com os quais Owen
poderá se deparar quando tentar obter dados sobre abduções
usando este formulário? Vá em frente, ponha suas ideias no papel.
. .vrsí..
.r?:..!Aí.:...òX}......................*................................................
você está aqui ► 5
Formulários são feitos de HTML
O formulário “Relate uma Abdução de Owen” (baixe este código através
do site da altabooks.com.br) se compõe, inteiramente, de tags e atributos
HTML. Há campos de texto para a maioria das perguntas, botões de
rádio para descobrir se o visitante viu Fang e uma área de texto para
comentários adicionais. E o formulário está configurado para enviar os
dados recebidos para o endereço de email de Owen.
VailV' c um ^robotoío «ue permi-te
t^uc dados à t -formulários seja»
enviados por email-
formulário html do Owen
Se predisar de um
re-Çresdo de memória
sobre domo driar
•formulários HTML, de
uma olhada «o Capí-Wo
l^vde Use a Cabeça!
HTML tom CSS 
*rtTML
<p>Share your story of alien abduction:</p>
<form method="post" action="m ailto:owen@aliensabductedme.com">
fc-—.
<label for="firstname >t'irst f
i
'
S
I
H
S
"
!<.
/
label>
------- ---- ------
Own ira redeber o donieúdo
deste -formulário enviado
para ele «este endereço de
r «^ail - fohha a<
^
u
i o seu
/ endereço para testar
^ o +ormulár»o.
£ste valor diz. ao servidor
domo e*viar 05 dados.
Será “post” ou w
«çt - N
®
5
explidaremos a di-ferenÇa
mais à írente-
As tajs input dizem ao
-formulário para esperar
irvformadoes, a«ui.
0 atributo type diz. a ação do
-formulário para esperar texto.
cinput type=1
1
text" id="firstname" name="firstname" /><br />
<label for="lastname">Last name:</label>'
Cinput type="text" id="lastname" name="lastname" /><br />
clabel for='’
email">What is your email address?</label>
Cinpuf*~type="text" id="email" name="email" 7><br />
<label for="whenithappened">When did it happen?c/label>
<input type="text" id=T
T
whenithappened" name="whenithappened" /xbr />
clabel for="howlong">How long were you gone?</label>
<input type="textM id="howlong" name="howlong" /xbr />
<label for="howmany">How many did you see?</label>
cinput ty^C="text" id="howmany" name="howmany'
’ /xbr />
<label £or=”aliendescription">Describe them:</label>
<input type="text" id="aliendescription" name^'aliendescription" size="32" /xbr />
<label for="whattheydid">What did they do to you?</label>
<input type="text" id="whattheydid" name="whattheydid" size="32" /xbr />
<label for="fangspotted">Have you seen my dog Fang?</label>
Yes cinput id=”fangspotted" name="fangspotted" type="radio" value="yes" />
No cinput id="fangspotted" name="fangspotted" type="radio" value="no" />cbr />
cimg src="fang. jpg" width=,'100" height="175"
alt="My abducted dog Fang." />cbr />
clabel for="other">Anything else you want to add?c/label>
ctextarea id="other" name="other"x/textareaxbr />
cinput type="submit" value="Report Abduction" name="submit" />
c/form>
0 -formulário -fidS dont»do
dentro de ta$s <£orm> de
abertura e de -fedbamento-
Nenhuma surpresa a^ui - o
-formulário e 0Ô% puro
totligo HTML/
0 botao submeter"
diz. a©-formulário
para exedutar a ação
exposta ali.
adicionando vida às suas páginas estáticas
T f e s r O r í v c
Teste o formulário “Relatar uma Abdução”.
Baixe o código da página “Relatar uma Abdução”no site
da Alta Bóoks, em www.altabooks.com.
br. O código
estará no cadastro deste Livro. O folder chi contém o
formulário de Owen em report.
html, bem como uma folha
de estilo (style.
css) e uma imagem de Fang (fang.jpg).
Abra a página report.html em um editor de texto e
troque o endereço de email de Owen pelo seu. Em seguida,
abra a página em um navegador web, digite algumas
informações no formulário e clique no botão “Relatar
Abdução” (Report Abduction).
t
O â
style.cssJ^(M8f
report.WnM fan9-jpg
AliensAbductedMe -ReportanAbduction
Shareyourstoryofalienabduction;
$u3háo v<*£ submete o Wulário,
isso resulta nos dados a serem
enviados... ou í$so.
First name:
Lost names
What is jour emaflad/lress?
When did tthappen?
How hmg were you gpne?
How many did you see?
Descrfte them;
What did they do to you?
Have you seen my dog Fang?
Aif
N
a
d
j
a
J
f
n
f
g
i
r
i
i
e
’
^a^reen.ccm
111hours
Idozens
!ilttifigreec* me?K
;asksdnttfaboutItfO
Yes Q N 08
0 -formuiario HTML- nao
sab«) reataentci iomo enviar
uma mensagem dt email,
entao ele delega a târeía
para o progva^a de email
do próprio usuário
0s dados do -formulário irvao sao enviados p ara ^y
Owen, a nâo ser <
^
u
e o usuário manualmente
envie esta estranha mensagem de email-
Então, o que você achou? Você recebeu os
dados do formulário como uma mensagem de
email na sua caixa de entrada?
você está aqui ► 7
mailto - má idéia
0 formulário HTML apresenta problemas
O formulário “Relatar uma Abdução”está no ar, operante, mas ele
não consegue obter muitas inforaiações dos usuários. Será que a
abdução de Fang corresponde a um incidente isolado... ou tem algo
de errado com o formulário. Vejamos o que os usuários têm a dizer.
Eu observei algo parecido com
o seguinte no campo Assunto:
?When=<&Where=. Estou confuso.
O
Não aconteceu nada, porque
o meu navegador não tem um
cliente de email padrao... seja
la o que isso signifique.
Quando clico no botão, ele
abre o meu programa de email,
o Outlook, e nada do que digitei,
durante 15 minutos, ficou
registrado no formulário!
Apareceu um email em
branco. Todas as respostas que
eu tive o trabalho de digitar foram
ignoradas. Deveriam abduzir este
formulário idiota!
T ' T mo’tivo> 0 de
esta extraindo mais -kusW ão do «ue
'»Wmaçao dos visitantes do seu site.
O que está acontecendo
aqui? Você tem ideias
sobre como consertar o
formulário?
adicionando vida às suas páginas estáticas
Parece estar tudo OK com
o formulário. Será que o
problema tem algo a ver com
aquela parte do "mailto"?
O
o
Sim. O código HTML do formulário está correto, mas
“mailto” não é uma boa maneira de enviar dados
O formulário de Owen funciona bem até o usuário clicar no botão “Relatar
Abdução”.Nesse ponto, você passaa depender do recurso de m ailto para
empacotar os dados do formulário em uma mensagem de email. Mas este
emaíl não é enviado automaticamente - ele é criado no programa de mail
padrão do computador do usuário. E o pior: o usuário precisa enviarele
mesmo o email, para que os dados sejam realmente enviados para você!
Você não tem nenhum controle sobre a entrega do email, significando que
ele poderá —ou não - fazer aviagem do seu formulário web, passando pelo
navegador do usuário e pelo seu cliente de email, até chegar a você como
uma mensagem de email. Nada bom.
Você precisa de uma forma para ter o controle sobre a entrega do
formulário web. Mais especificamente, você precisa que o PHP empacote
os dados em uma mensagem de email, e depois se certifique de que essa
mensagem será enviada. Isto envolve desviar a sua atenção do cliente
(HTML, m ailto, etc.) para o servidor (PHP).
0 íormulârio esta
ótimo, ate voee
ttã no boWRelatav
Abdução” - enta«? tudo
dcsntoronâ!
você esté aqui ► 9
lado-cliente versus lado-servidor
HTML roda no cliente
O formulário de Owen foi escrito em HTML puro, com uma ação
m ailto que tenta enviar os ciadosvia email. Embora a página report
html venha de um servidorweb, ela é preenchida e processada
inteiramente no navegadorweb do usuário.
O navegador requisita a
páginaweb de Owen, a
qualinclui o formulário
0 software
navegador do seu
domputador roda
a«ui, tambem
torMctido íorno
C L lW T t .
O servidorretorna o
código HTMLpara a
páginaweb.
O usuário preenche o
formulário e o submete.
0 saÊ-bwave servidor web
de O^tTí voda a°ui> tambem
donHedido domo SERVlPöR
A tagde ação do formulário
diz ao navegadorpara
pedir ao programa de email
do usuário que crie uma
mensagem de email.
O programa de email do usuário
cria uma mensagem com os
dados do formulário - mas é o
usuário que precisa enviá-los,
manualmente, a Owen.
O papel do servidor, aqui, limita-se a apenas entregar a página web ao
navegador. Quando o usuário submete o formulário, o navegador (cliente!)
precisa resolver sozinho a questão de como fazer os dados serem enviados
via email. O cliente não está.equipado para entregar dados do formulário -
esse é um trabalho para o servidor.
ô servidor jamais
entra em dontato
tom os dados
digitados em
-formulários <
^
u
e
usem mailto-
adicionando vida às suas páginas estáticas
PHP roda m o servidor
O PHP lhe permite controlar os dados que o usuário digita no
formulário, enviando-os para você de forma transparente. O usuário
digita o seu caso de abdução no formulário, clica no botão “Relatar
Abdução”e pronto! O código PHP cria a mensagem de email, a envia
para você e então gera uma página de confirmação para o usuário.
^ ---- ---
Eu gostaria de
^ receber a página "Relatar
7 uma Abdução1
', por favor.
0 O navegador requisita a
páginaweb de Owen.
O servidor responde com o código
HTMLpara apágina web.
O usuário preenche o formulário e o submete,
enviando os dados a um scriptPHPpresente
no servidor.
O servidor envia umaconfirmação
em HTML ao navegador.
O**:* vetebe, to» u*
ayadaveWen-te atado.
Marque os lugares onde você acha que os scripts PHP devem residir:
| | no cliente X no servidor j^j em ambos j^j em nenhum dos dois
você está aqui ► 11
php é uma linguagem do lado-servidor
Os scrípts PHP rodam mo servidor
O código PHP roda no servidor e é armazenado em sciipts PHP que
geralmente tem a extensão .php. Os scripts PHP frequentemente se
parecem bastante com páginas HTML normais, porque contêm tanto
código HTML quanto CSS. De fato, quando o servidor executa um script
PHP, o resultado final é sempre HTML e CSS puros. Assim, todo script
PHP acaba se transformando em HTML e CSS, uma vez terminada a sua
execução no servidor.
Vamos dar uma olhada mais detalhada no modo como o script PHP
modifica o fluxo do formulário web de Owen.
O navegador do cliente requisitaumapáginaHTML-
re p o rt htm l
O O servidor retorna apágina HTML
hc ttêr M botão "Relatar Abdução", 0
usuatrio submete os dados do •íww.ulirio
para o sfivift PHP do servidor.
O usuário preenche o formulário e o submete,
fazendo o navegador repassar os dadospara um
scriptPHP no servidor.
adicionando vida às suas páginas estáticas
0 PBP é uma linguagem de programação
do lado do serVidPT(serVe-side) -pofs ele
rpda em um serVidor Web.
O servidorretoma umapágina de HTMLpuro,
geradapelo scriptPHP.
0 sdript PttP v-oda no
servidor!
Embora Onome da pagina apareça tom
uma extensão fhp no navegador, ela t
furo HTML, neste ponto.
O navegador exibe a página
de confirmação.
AliensAbductedMe-ReportanAbduction
Youw
ereabductedlastNororiberaodw
eregoneforíI bows
d
e
s
c
r
i
b
e
d
i
c
t
a
WasFau£<h*rc?Do
Y
"
o
u
r
e
m
a
i
l
6
*
h
c
a
O servidor executa o scriptPHP, o qual
envia um email e geraumapágina de
confirmação em HTML.
0 usuário ve A
uma págma de ^
toníirma^ao.
O emailé enviado
para a Caixa de
Entradade Owen.
o atributo action do formulário
£ stc t o YiOTnt ào
seu sflrip-l PHP-
O atributo action dos elementos do formulário é o que
conecta este último ao script PHP, fazendo o script ser
executado quando o formulário é submetido.
Os formulários são criados usando-se a tag HTML <form> e cada tag
<form> possui um atributo action. O arquivo cujo nome você inclui
com o atributo action é usado pelo servidor web para processar o
formulário quando este é submetido. Assim, se o script PHP de Owen
se chamar report.php, então a tag <form> para conectá-lo ao
formulário se parecerá com o seguinte:
<form a c tio n =s m ethod = "p o stM
>
r e p o r t h t m l
Quando o usuário clica no botão “RelatarAbdução’
formulário faz o script report.php ser executado
para processamento dos dados.
<html>
<head>
</hLid
t>e>Alie:1S Me - an Abduction</title>
<body>
^ 2>^lie?
!
.
,
AhdUCt6d Me " ReP°rt an Abduction</h2 >
<link rel- stylesheet" type="text/css" = 1
</head> -ext/css href="style.
css" />
<body>
<h2>Aliens Abducted Me - Report an Abdoction</h2>
<E>ghare your story of alien abduction:</n>
/IfC'
rm method- post1
1 action-repSTt.php-r^ ^ ---
a ação do
no servidor,
0 atvibwto âdtion
da iao| <£<*■
*»>
t o c faz. o
strict PHP sec
ey-edu-tado «o
o -ÇovwuUrio c
submetido-
COI>xun=--report.J ^
mr-msttug'.hi'i.L Igbai»
input type- t
e
X
i
_ id="£irstnameM na,-ns="firstname" /xbi
reportphp
adicionando vida às suas páginas estáticas
nty? existeni
T e r g u n t a s i d í P t c t s
T * * 0 que significa PHP?
PHP é um acrônimo que originalmente significava Personal Home
Pages (Páginas Pessoais). De alguma forma, o acrônimo teve o seu
significado modificado para PHP: Hypertext Processor (Processador
de Hipertexto PHP). Este último é considerado um acrônimo recursivo,
porque ele referencia a si mesmo - um acrônimo (PHP) dentro do
acrônimo. Inteligente? Confuso? Você decide!
* Mesmo que o meu navegador esteja mostrando que o nome da
página termina com .php, ela ainda é puro HTML? Como é possível?
Isso é possível porque a página começa a sua vida como código
PHP no servidor, mas é transformada em código HTML antes de ser
enviada para o navegador. Assim, o servidor executa o código PHP e o
converte em HTML antes de enviá-lo para ser visualizado no navegador.
Isso significa que, mesmo que o arquivo .php contenha código PHP,
o navegador nunca vê esse código - ele vê apenas o código HTML,
resultado da execução do código PHP no servidor.
* Mas não é verdade que toda página web se origina no servidor,
inclusive as páginas HTML puras, em arquivos .html?
Sim. Todos os arquivos que compõem um site ficam armazenados
no servidor - . html, .c s s , . php, etc. Mas nem todos
eles são processados peio servidor. Os arquivos HTML e CSS, bem
como arquivos gráficos, sâo enviados diretamente para o navegador do
cliente, sem preocupações sobre o conteúdo deles. Os arquivos PHP são
diferentes porque contêm códigos que são processados e executados no
servidor web. Não é o código PHP que é enviado ao navegador, e sim os
resultados obtidos ao se executar o código PHP, - esses resultados são
HTML e CSS puros.
você está aqui ► 15
Use PHP para acessar os dados do formulário
seu 1ascript php
Então, Owen precisa de um script PHP capaz de fazer com que as informações do formulário
cheguem a ele de forma mais confiável do que através do e-mail. Vamos criar esse script.
Não se preocupe em entender tudo agora - nós chegaremos lá:
O.*riftsPHP M ,éaVi nw
as doisas -fica»»
•frequentemente
to *ttp *r*tc o & > - ■
mi o w a ^ es.
j X * bastante £«. w»í ^ é a
jájma HTML normal- do pWf5
propriamente dito.
ort an Abduction</title>
<html>
<head>
<title>Aliens Abducted Me
</head>
<body>
<h2>Aliens Abdus? d Me - Report an Abduction</h2>
É per-feitamente
normal um script PHP
íniluir ia^s c atributos
HTML normais.
J
0 blodo de dódijo
inteiro é PHP—o
restante do stript c
HTML normal-
j | fcsU pedaço dc
I PHP obtem
os dados do
•formulário, para
<*e eles possa»
ser exibidos
tomo parte de
uma página de
dottíirmadao.
|||| usamos
PHP para $erar
dódi^o HTML a
partir dos dados
do -formulário-
</body> jftssim domo uma pâ^ina v/cb normal,
s^ipt PHP termina íeôhando
^uâis^uer tajs HTML abertas.
</html>
adicionando vida às suas páginas estáticas
T f e f iT O R f V E
Modifique o formulário de Owen de forma que ele use
um script PHP para processar os dados do formulário.
Crie um novo arquivo de texto chamado re p o rt.php e digite nele
todo o código da página anterior. Esse é o script que irá processar o
formulário web de Owen.
O script PHP ainda não está conectado ao formulário; abra a página
report.html em um editor de textos e modifique a ação do
formulário para report .php em vez de mailto.
:form action = method = "post":
report.html p^ty
reportphp ‘ar>g.jpg
Abra a página re p o rt.html em um navegador web, digite algumas
informações do seu caso de abdução no formulário e clique no
botão “RelatarAbdução”.
AliensAbductedMe -ReportanAbduction
Share yo o r sto iy o f aüfiB abduction;
Dípersdeftd© do seu havendo*-,
vo£e podara ve*- uma pá^ihâ
'web Com wwie*to esquisito ou
Possivelmente apenas o toâi$o-
•fotvfce PttP do séript reportphp.
First name:
Lastname:
W hat is your email address?
W ien did it happen?
How Long-were you gone?
How many did vou see?
Dtsc-rEb« them:
W hat did they do to you?
Have you seen my **6 Fang?
■
5
N
adir
>
alfin®
*e¥r*al|s“
ilasrH
ov^'D
er
:ilh
ß
ü
re
AliensAbductedMe-Reportan Abduction
■
3= ----------Y ouv,™ »M uc«d',SwbeaJLhappewd". echo and w ere gone fo r .
5 iio w _lon g ; echo ’ ^ ,
:
<w.ywn*.. D
e
s
c
r
i
o
e
t
e
m
:
1
.
Sa^des^iior^M
W as Fang *e re ? ‘ ■
YesON
c»®Your«nailaadnsssK.
-mm
Ä “ '*
<raeta _
1want tûadd?
ÎP
teasivoisterm
e. î AiiÂa*Abduc i
<
/
h
e
a
d
v c-
ô
d “£
e
p
c
r
-
f
ca
r
, I
<body> aC f
<
h
2
>
J
U
i
e
c
e â
b
d
u
c
f
c
e
d Report A ixiue tioQ< /h2>
^ M eS aq u e é assim mesmo que o scriptPHP deveria funcionar?
Escreva aqui asua opinião, e o que acha que está acontecendo.
.Ê f á / . .d .. ÇMM yU / ^ % .
sà á^ r^ ê. ..0 .. ......................................
você está aqui ► 17
colocando scripts php no servidor
Os scripts PHP precisam ficar em um servidor!
A não ser que você, por acaso, tenha um servidorweb rodando no seu £ se v©tê tiver
computador local, o script report .php não poderá ser executado ur*servidor web
quando você submeter o form ulário “Relatar uma Abdução”.Lembre-se, o instalado lodalme«tc,
PHP é uma linguagem de programação e precisa de um ambiente onde e ele tiver suporte a
possa rodar. Esse ambiente é um servidorweb com suporte a PHP. Scripts P^P>enta© poderá
PHP e páginas web que dependem deles precisam ser colocadas em um testar os stripts PHP
servidorweb real, não basta apenas abrir um script diretamente a partir de diretamente no seu
um sistema de arquivos local. tomputador.
Os navegadoresweb
não sabem nada sobre
PHP e, portanto,não
são capazes de rodar
scripts PHP.
$0 tontrário de paginas HTML-»
podem ser abertas Totalmente em w*
navegador web, os stripts PttP
sempre ser w
aberW’ através de umâ
IXRLi a partir de um servidor web
£$íe stript PHP representa
apenas um monte de
tódigo sem sentido para o
navegador web.
0 servidor web
entende este
tódigo PHP e
e*etuta o stript!
Wma -forma ra>ida de saber se uma
pagina web esta sendo entregue por
um servidor web c olhar se a U R L
tometa tom w
Kttp:M
. Páginas web
abertas tomo arquivos letais sempre
iomeÇam tom W
-file'W
Os servidoresweb com suporte
aPHP são equipados para
rodar scripts PHP e transformá-
los em páginasHTML que os
navegadorespossam entender.
Os scripts PHP deVem ser
eXecutadPS em um serVídPT
W eb , o u e n tã o n a q íu n c fõ n ã tã o .
adicionando vida às suas páginas estáticas
Coloque os seus scripts PHP no servidor
E perfeitamente válido criar e editar scripts PHP no seu computador local. Porém, você
precisa colocar os arquivos em um servidorweb antes de executá-los. Os arquivos PHP,
frequentemente, são colocadosjunto com arquivos HTML em um servidor. Não hã nada fora
do comum em colocar scripts PHP no servidorweb - basta colocá-los em um lugar onde as
suas páginas web possam acessá-los. Para fazer o upload (envio) dos arquivos para o servidor,
você precisará da ajuda de um utilitário, como por exemplo, um programa de FTP (File
Transfer Protocol ou Protocolo de Transferência de Arquivos).
A maioria dos sdripts
PHP apareie junto dom
outros arquivos, «a
■«esm
a pasta, de*tro do
servidor. são, 3*
vez£s, armazet^adâs
Cmurtvâ pâstá
própria, parâ melhor
or^ãnizaddo no
servidor... mas fido
_ «este daso.
style.css fang.jpg
éjeralmente, ha
pasta «o servidor
web onde a maioria,
se não todos, os
arquivos sao
armazenados.
Fazer o upload dos seus scripts PHP para um servidorweb
não é o suficiente - esse servidor também precisa ter o
PHP instalado nele. Alguns servidores incluem o PHP por
padrão, alguns não.
nãe existem
perguntas idíptas
T * • Como eu posso saberse o meu servidorweb tem o PHP instalado?
Você pode perguntar ao seu administrador, ou à sua empresa de
hospedagem de sites, ou então pode realizar um pequeno teste, você
mesmo. Crie um arquivo de texto chamado t e s t e .p h p e coloque o
seguinte código nele:
<?php
phpinfo(
)
?>
£ste dódi$o pede para
o^t in-formaÇoes sobre o
PHP sejam mostradas no
Agora, envie (upload) o teste.php para oS&tf&Widor, e então digite
a sua URL em um navegador web. Se o PHP estiver instalado no
seu servidor, aparecerão várias informações detalhadas sobre o
PHP, incluindo a sua versão. Bingo!
Se você não
tiver o P H P
instalado no
seu servid or
web, consulte
o Apêndice ii.
Nele, encontrará instruções
para ter o PHP instalado e
operante no seu servidor.
Lembre-se de deietar o sdript
phpmío guando estiver terminado,
desta -forma, nin^uem mais
tonse^ue ver isto
você está aqui > 19
_ — T J e s t O r i v e
test drive no seu script php
Faça o upload dos arquivos da página
"Relatar uma Abdução” e teste o formulário...
novamente.
Envie os arquivos report.html, report.
php, style .
css efang.j pg para um servidorweb que tenha o PHP
instalado. Digite a URL da página report,html no
seu navegador, preencha o formulário com informações
do seu caso de abdução, e clique no botão “Relatar
Abdução”.
rep ort
reportphp fan9-ipg
First name:
Last name:
W hat fs your email address?
When dfd it happen?
How tang w ire you gone?
How many did you see?
Describe them:
What did they do to you?
Have you seen my dog Fang?
Anythmg else vou wfint tn add?
adicionando vida às suas páginas estáticas
Legal. Agora só é preciso adicionar um
pouco de código PHP para enviar os
dados do formulário por email.
Isso mesmo. O script report.php ainda precisa
de algum código para enviar os dados para
Owen por em ail.
Mas isso não é problema, porque o PHP oferece uma função,
que é um pedaço de código pronto reutilizável, que você
pode usar para enviar mensagens por email. Você só precisa
determinar o que a mensagem deve informar, e então pode
usar o PHP para criã-la e enviá-la.
Um momentinho! Nós nem sabemos
como o script report.php original
funciona, e agora ainda temos de
torná-lo capaz de enviar emails. Isso, é
tipo, muito difícil... o que vocês estão
pensando!?
É verdade. Para fazer mais coisas com o
PHP, é preciso saber mais sobre o PHP
Assim, para adicionar a funcionalidade de email
ao script report-php de Owen, você terá de se
aprofundar um pouco mais no PHP e precisará ter um
entendimento sólido de como o script funciona - pelo
menos até aqui.
você está aqui > 21
como o código php muda para html
0 servidor transforma PHPew HTML
Para que se entenda como um script PHP funciona, o principal é entender o que acontece
com o script quando ele é executado no servidor. Amaioria dos scripts PHP contém tanto
código PHP quanto HTML, e o PHP é executado e transformado em HTML antes de o
servidor enviar tudo - na forma de HTML - para o navegador web do cliente. No script
report.php de Owen, o código PHP gera a maior parte do conteúdo HTML no corpo da
página de confirmação. O código HTML em torno do PHP é enviado sem modificações.
Esie dódijo HTML é caiado sem
modiíidaçÕes para c navegador.
Este tódigo PHP e
e*e£utado pelo servidor
e gera o dódigo HTML
òontendo os dados <^*e
forâm digitados no
formulário-
Mais código HTML estate©,
*lu€ e transmitido pelo servidor
ao navegador sem modi£áaçoes.
reportphp
adicionando vida às suas páginas estáticas
Este tod130 HTML
e chad© emicmp©
veal pe!o sdripi PHP,
o «
^w
e perm'rte ao
dodi^o issuer doisas
iniereisar>-tes; demo
for exemple, indluir
dados <
^u
e adabaram
de ser digrfcados em
um•formylario.
Estítido - isto rto sc modi-Pida. £>mãmido - modi-pida—
«dada vez.nue auu^
Orneie o iUr^WaVio/
Thanks for submitting the form.<br / >
You were abducted last November and were gone for 11 hours<br />
Describe them: <br />
Was Fang there? no<br />
Your email
0 resul-fcado -filial do sdript
PHP e uma patina web e
w
*
HTML puro, <
^w
e-foi gerada
dihdMnidamewte «o servidor.
você está aqui ► 23
anatomia do script php do owen
Pescon$truindo oscript PHPde Owen
O script report .php é acionado pelo formulário “Relatar uma Abdução”e o
seu trabalho (no momento) é acessar os dados digitados e gerar uma página
de confirmação. Vejamos como.
O primeiro pedaço de código corresponde a HTML puro. Ele simplesmente
configura a página que estamos criando, incluindo algumas tags HTML
requeridas em toda a página web.
report.php
<html>
<head>
<title>Aliens Abducted Me - Report an Abduction</title>
</head>
<body>
<h2>Aliens Abducted Me - Report an Abduction</h2>
Aqui as coisas começam a ficar interessantes. Estamos prontos para sair
do código HTML e entrar no PHP. A tag <?php abre uma seção de
código PHP - tudo o que vier depois desta tag é puro PHP.
<?php < r
£im, este código
HTML e mínimo —
normalmente voÊe teria
u
mPOCTYPZ, tags
<meta>j etc., mas
estamos mantendo as
Coisas simples, a^ui-
Pa<ui em diante, estaremos
lidando tom código PHP—
pelo menos até chegarmos à
tag de fechamento ?>•
Este código reúne os dados do formulário e os armazena em variáveis individuais,
para que possamos acessá-los posteriormente. Asvariáveis do PHP permitem que
você armazene valores, sejam eles números, textos ou outros tipos de dados.
$when_it_happened - $_POST['whenithappened*
$how_long = $_POST['howlong'];
$alien_description = $_POST['description'];
$fang_spotted = $_POST[Tfangspotted']
$email = $ POST['email'];
Cada linha do código PHP
reune os dados do field
do formulário para umã
nova variável
Agora sim! Aqui, asvariáveis que acabamos de criar são colocadas em ação, sendo
inseridas no código HTML, gerado dinamicamente. O comando echo ocasiona o
output (saída) de código HTML, que é retomado diretamente para o navegador web.
echo
echo
echo
echo
echo
echo
'Thanks for submitting the form.cbr />';
'You were abducted '
1 and were gone for
'Describe them: 1 .
'Was Fang there? ' ,
'Your email address
. $when_it_happened;
' . $how_long . '<br />';
$alien_description . '<br />’
$fang_spotted . '<br
is ' . $email;
FVoduz. a saída de
código ht»l para o
navegador
A tag ?> correspondente a <? encerra a seção de código PHP. Daqui em
diante, estamos de volta ao código HTML normal. M» fecha o
?> ^ _____________________________ ' PhP
Isto finaliza o código PHP - depois desta tag, estamos de volta ao HTML normal.
</body>
</html> ^gora, termine a pagina fechando as tags
HTML <ue havíamos aberto-
o seu código
Algumas regras PHPpara o ounvida
O script re p o rt.php de Owen revela algumas regras fundamentais da linguagem PHP, que
se aplicam a todo script PHP. Vamos dar uma olhada nelas.
O código PHP sempre fica entre tags <?php e ?>.
£eu tódiy>, <?PhP h maioria do* s ô rifb PHP são apenas paginas HTM L
íita a*ui ^ tc*? toá<sp PHP inserido cm al^wmiu^ar - estas -fca^s
^ ^ __míorirwa»« ao Sírvidor ^uai paríe do código e PHP.
l y f Toda instrução PHP precisa terminar com ponto e vírgula (;)
echo 'Thanks for submitting the form.
<br />';^
Sf^adasostu cód,y> íalKav, ’
vo-ií^« se ,0£Í „30 estiueCeu de i"ítr " S a° P f ^
íolotar o "foní» f vr«Ja*. 1«. •*> tarresy<m<k 3o ^
*o*teíe í» „iis d, ^ <** msb™**’
*ue se pode imaginar.
Caso haja qualquer código PHP em uma página web, é uma boa
ideia nomear o arquivo com .php, e não com .html, no servidor.
adicionando vida às suas páginas estáticas
Kã©t essential, »as e uw»aboa
ideia «ornear s trifb PHP tom a
extensão php-
reportphp
Os nomes de variáveis PHP precisam começar com um cifrão ($).
^ ----S»-$email = $ _ P O ST [ »email '] ;
0 ii-frao iden-èi-Pida
dlàràmeftíe a variável PHP,
responsável por armazenar Observando asvariáveisusadas no script report.php, você
mo^a^oes dentro de u» consegue ver quaisquer outras regras do PHP referentes a
sdript PHP. variáveis? Esçreva-asaqui! j
....
você está aqui ► 25
nomeando as variáveis
A VcirîaVel
Ewo^itrsncloonoii^pcfrértopstra^su^vskríávd correspondea
Além de começarcom $, os nomes de variáveisPHP são também “case- ym C91ltíilllôt
sensitive”.Masissonão é tudo - existem outras regras importantespara T A T
osnomes que você pode dar àssuasvariáveis.Algumas delas se referem Pllclc- Y9 Ce pÇciO
à sintaxe, significando que o seu códigofalharásevocê asignorar,
enquanto outras outras obras correspondem a apenas boasideias
transmitidasde uma geração de programadores PHP paraoutra.
Vamos começarcom asregras oficiaisque irão definitivamente causar
problemas sevocê ignorá-lasao nomear suasvariáveis. Sigaestas regras
para criarnomes de variáveisválidas.
J £ n W ido!
l y f Oprimeiro caracter tem de ser um cifrão ($).<
:—^
armazenar dados, e
ca d a v ariáv el te m
um npnie linico.
0 h':'
t f * nome da variável precisa ter no mínimo um caracter.
yÇO primeiro caracter depois do cifrão pode ser uma letra
ou um "underscore" (_), e os caracteres seguintes podem
ser uma letra, um underscore ou um número.
fyÇEspaços e caracteres especiais, fora _ e $ , não são
permitidos em nenhuma parte do nome de uma variável
Sem dontar
>e t requerido
no nome de ioda
variável.
Inválido^ Nomes de
variáveis PHP nao pode»
donter Kí-fens nem
espados.
$emai l Val'do
/
$fang^spotted
Y
1$when-
r õ w h a t ^ 16^—d id _-
- it happened
------------------- :_
1
/álid«
Invalido/ Hííens não sa©
$how long I em nomes de
= ---------- variáveis PHP.
a lx e n jdescription
Válido!-
Sevocê não seguir estasregras, o seu código não funcionará. Existem
ainda, outras regras que podem serseguidas- por uma questão de
“convenções”de programação. Estassãoregras que ajudam a tomaro
código PHP um pouco maisconsistente efacilde serlido.
Use minúsculas nos nomes das variáveis.
Inválido/ Nomes
de variáveis PHP
predisam domedar
dom um di-frao (f).
Os nomes das
VoriaVeís FHT
Em nomes de variáveis com mais de uma palavra, com eçar
separe-as com "underscores". — t
com um c if r a i) ,
e YtfjQ fcpdem
Sevocê ignorarestas duasúltimas regras, não serão geradas falhas
no seu código. Certamente, você encontrará códigosPHP que não
seguem estas regras e, mesmo assim, funcionam perfeitamente. Isso
ocorre porque estasregras- sobre asquaisestamos nos referindo- CÇU^eí eSpaç^S
tratam-se de uma convenção estilística. Elas tomam-se úteis quando
começam a criare nomearsuasprópriasvariáveis.
adicionando vida às suas páginas estáticas
não existem
p e r g u n ta s id io ta s
paraos navegadores. 0 PHPnãom
uda
essefato. 0 queoPHPlheperm
ite
fazerémodificaroconteúdoHTMLem
temporeal, inserindodadoscomoa
datade hoje, informaçõesretiradasde
umbancodedados, ouatém
esm
o
valorescalculados, comoovalortotal do
pedido, emumsitedecom
pras. Assim,
oPHPpermitequevocê manipuleo
HTMLquecompõeaspáginasweb, em
vezdetê-las criadasestaticamente,
apenas um
avez. Ébastantecomumter
um
apáginaHTMLcomcódigoPHPaqui
eali parainserirdadosimportantes, ou
alterar programaticam
enteoHTM
Lde
algumaforma.
Lembre-sedequetodapágina
webcorrespondeao resultadode um
a
comunicaçãodeduas vias, envolvendo
um
a requisiçãofeita pelonavegador
clienteeumarespostadoservidor
web. AURLéabaseda requisição,
enquantoconteúdoretornado pelo
servidor éaresposta. Osscripts PHP
são requisitados damesmaforma
que páginas HTMLnormais, através
de URLsdigitadas no navegadorou
linkadasapartirdeoutras páginas,
ou comoações deformulários. Isso
explica porquea URLde uma“página”
PHPmostrao nom
edoscript.
- Faz diferença escrever os
comandos PHP em maiúsculas
ou minúsculas?
K : Simenão. Emgeral,oPHPnão
é"case-sensitive",portanto,vocêpode
m
isturarm
aiúsculasem
inúsculasna
m
aioriadoscom
andos. Issosignificaque
vocêpodeusarecho, ECHOouE
chO
.
E
ntretanto, porum
aquestãodeconvenção,
éum
aótim
aideiaserconsistentenosseus
scripts.Am
aioriadosprogram
adoresPH
P
prefereusarm
inúsculasnam
aiorparte
dosseuscódigos,eéporissoqueveráa
grafiaechosendousadanosexem
plosde
códigosdestelivro.
T * - Então, mesmo sendo uma má
prática de programação, posso
misturar maiúsculas e minúsculas
no meu código PHP?
M
ãocompletamente. Aexceção
correspondeaos nomesdas variáveis,
oquetambémseaplicaàs localidades
dearmazenamentodedados que
vocêcria. Vejamosavariável $email
usada noscript "Relatar umaAbdução",
comoexemplo. Onomedestavariável
é"case-sensitive", portanto, você não
podesereferiraela como$EMAILou
SeM
ail. Todososnomesdevariáveis,
emPH
P, são"case-sensitive", por
isso, éimportantenomearas variáveis
comcuidadoereferenciá-las de
forma consistente, emtodoocódigo.
Falaremos maissobrenomes de
variáveis emoutromomento.
• Realmente não tem problema
colocar código PHP e HTML no
mesmo arquivo?
Nenhumproblema. Naverdade,
emmuitoscasos, éabsolutamente
necessáriofazer isso.
- E por que colocar PHP e HTML
no mesmo arquivo?
Porqueoverdadeiropropósitoum
servidorwebéservirpáginaswebHTM
L
• O código PHP inserido em
um arquivo HTML precisa estar
na sua própria linha ou posso
colocá-lo em uma linha HTML,
como parte do atributo de uma
tag HTML, por exemplo?
Foraanecessidadedecolocaroseu
códigoPHPdentrodastags<?phpe?>,
nãohárestriçõessobrecom
oinseriresse
códigonoHTM
L. N
averdade,énecessário
colocar,frequentem
ente,umblocode
códigoPHPnom
eiodocódigoH
TM
L, por
exem
plo,quandoestásendoconfiguradoo
atributodeum
atagHTM
L. Esseéumuso
perfeitam
entelegítim
odoP
H
P
.
TÍ^" Já vi códigos PHP iniciados
por <? como tag de abertura, em
vez de <?php. isso está certo?
Naverdade, não. Tecnicamente
issoépermitido, mas não
recomendado. Éprecisoqueuma
configuraçãodoservidor esteja
habilitadaparaqueatag abreviada
(<?) funcione. Atag <?php usual
semprefunciona, entãoémelhor
simplesmente usá-la, sabendoqueo
seu códigovai funcionar.
? : Seo servidorweb sempre
retoma HTML puro para o navegador
do cliente, por que as URLs mostram
o nome do script PHP, como, por
exemplo, paginaweb.php?
Aoutrametadedaequaçãoéaresposta
doservidor, queéocódigoresultante
geradopeloscript P
H
P
. Umavezque
am
aioriadosscriptsPHPgeraHTM
L,
fazsentidoqueessecódigoseja HTM
L
enãoP
H
P
.Assim, nãoéporacidente
queaURLreferencie umarquivo .php
noservidor, oquefazocódigoPHPser
executadonoservidor, resultandoem
umconteúdopuramenteHTM
L, queé
retomadoaonavegador.
^ • As variáveis PHP podem
armazenar outros tipos de dados?
Certamente. Vocêpodeusá-las
paraarmazenardados Booleanos
(verdadeiro/falso). Edados numéricos
podemsertantonúmerosinteiros
quantodepontoflutuante(decim
ais).
Hátambémos"arrays", osquais
armazenamumconjuntodedados, bem
com
oobjetos, osquaisassociamum
conjuntodedadosaocódigousado
para manipulá-los. O
s"arrays"serão
abordadosumpoucomaisadianteainda
nestecapítulo, enquantoos"objetos"
sãoassuntodoCapítulo 12. Existe
tambémumtipodedadoespecial
chamadoNULL, querepresenta
"nenhumvaior". Porexemplo, um
a
variável que nãotenha nenhumvalor
atribuídoaelaéconsiderada NULL.
você está aqui > 27
adicionando dados perdidos no owen
C
lâv-âm
entaíci
unnâ desdVÍÇao
(desóribe) dos aliens no
■í-ovrnulíirio...
••■»as a descrição «a©
aparece na pagina de
LorJtWmàtâo
adicionando vida às suas páginas estáticas
Aponte seu lápis
Há um problema com os dados referentes à descrição
dos aliens, no script report.php de Owen. Circule as
linhas do código que você acha que tem a ver com
o problema e escreva o que elas estão causando.
Alguma ideia do que há de errado?
<html>
<head>
<title>Aliens Abducted Me - Report an Abduction</title>
</head>
<body>
<h2>Aliens Abducted Me - Report an Abduction</h2>
<?php
$when__it_happened = $_POST ['whenithappened1];
$how_long = $_POST [
■’howlong '];
$alien__description. = $_POST ['description1];
$fang_spotted = $_POST[1fangspotted']
$email * $_POST['e m a i l ;

echo 'Thanks for submitting the form.cbr />N:j
echo ’You were abducted ' . $when_it_happene^'; 
■
* 
echo ' and were gone for ' . $how long . />>' '<
echo 'Describe them: 1 . $alien description . '
<br />’
i . m
i, c ik. /
echo ’
Was Fang there? ’ . $fang_spotted . '<br />’;
i
i
s
i
i
o 'Your email address is ' . $email;
?>
</body>
</html>
report,php
você está aqui > 29
apontando solução
F 3|^pottte seulápis
S O UCãO um Pr°klema com 05 dados referentes àdescrição
dos aliens, no script report.php de Owen. Circule as
linhas do código que você acha que tem a ver com o
problema e escreva o que elas estão causando. Alguma
ideiadoquehá deerrado?
£sta ImKa do código
ob-tem a destvitao dos
aliens do respectivo
ta^po no -formulário
ttTMU e os dados
ãVmdz-ena em um3
variável PHP Camada
falien_jdesCription
Report an Abduction</title>
Este código Combina a
descrição dos aliens Com
alguns ot»-fcros -textos
e códigos HTML e
envia tudo isso para o
navegador.
<html>
<head>
<title>Aliens Abducted Me
</head>
<body>
<h2>Aliens Abducted Me - Report an Abduction</h2>
<?php
$when_it_happened = $_POST['wnenithappened']
;
$how_long = $_POST['howlong']
;
$alien_de script-ion = $JPQST[-description']?)
$fang_spotted = $_POST['fangspotted']
$email = $_POST[’email1];
echo ’Thanks for submitting the form.cbr />';
echo 1You were abducted ’ . $when_it happened;
echo 1 and were gone for ' . $how_long . ’<br />';
echo 'Was Fang there?
echo 'Your email address is
?>
</body>
</html>
$alien_description
$fang_spotted^ '
'<br />
$email;
<br />'
Por al^vtm motivo, a variave) falien_
description parece estar vazia- *ada bom.
reportphp
adicionando vida às suas páginas estáticas
Variáveis servem para armazenar dados descripts
AsvariáveisPHPsão como containers que armazenam informações,
damesmaforma que um copo armazena uma bebida. Umavezque
avariável $alien_description estávazia, nós sabemos que os
dados correspondentes do formulário não estão chegando até ela.
Assim, avariável $a1ien_de scription permanece vazia, apesar
da nossatentativa de atribuiralguns dados a ela.
Este e e ftorvie da
variável.
«íelizmewte,
dopo endoniva-se
vâzio-
$a1ien_description
Nós pve£isa**os
de um dopo
•ètrâwsbordando
desd<ri£©es dos
aîienii
igenas'
Saliendescription
Uma forma de consertaro scriptseriaatribuira stringexata que estamos
esperando para avariável $a1ien_description, destaforma:
$alien_description = 'Homenzinhos verdes1
. pnp J PWP, « 'pedaços” de 4
*xto,
0 13* .wt™IO dha-ad« dí striay, deve„
a atribuir <
, val«r da d « .ta a s<mpre w u ]o ts ic i d ttilro d(
variave! da « Verda. ^ rociclB S£(. si |ej ou ^
Este código armazena, definitivamente, o texto 'homenzinhos
verdes ' navariável $alien_description. Masnós resolvemos
um problema criando outro - este código faza descrição ser
sempre a mesma, independentemente do que o usuário digitarno
formulário.
( x f c É R É S R Q
Por algum motivo, a atribuição dos dados do formulário
referentes à descrição dos alienígenas à variável
$aiien_description não está funcionando.
$alien description - $_POST['description 1];
O que você acha que está errado com este código?
você está aqui ► 31
tudo sobre $_PO$T
O
O problema obviamente tem algo a
ver com aquele negócio de $_POST.
Mas nâo tenho ideia do que possa ser.
O problema, de fato, tem algo a ver com $ _ p o s t,
que é um mecanismo usado para que os dados do
formulário sejam transferidos para um script.
O cifrão no início de $ POST é uma dica... $ POST é um
Container! Maisespecificamente, $_POST é um conjunto de locais
de armazenamento usados para que osdados de um formulário web
fiquem armazenados. No caso de Owen, todos os dados enviados
para scriptreportphp sãoarmazenados quando alguém preenche o
formulário e clica no botão de “RelatarAbdução”.Assim, para acessar
osdados do foraiulário e fazerqualquer coisacom eles, nós temos que
usar $_POST. Lembra-se deste código?
$when_it_happened = $_POST['whenithappened1]
;
$how_long = $_POST [
'howlong']; ---•
------ -
$alien_description = $_POST['description'];
$fang_spotted = $_POST[1fangspotted']
;
$email = $_POST [’email1]; # »«esmo adonieCe a
^
u
i
,
exee-fco feio £abo de <uc os
, r is • ààáos. reíere*tes âo email
« W t e a ***<*> « * va*i„ e|é
cn il
abdu^âo sao aonbuidcs a
variável ?Kov#_jong.
Assim, osdados de cadacampo do formulário “RelatarumaAbdução”são
acessados usando-se $_P0ST . Mas o que exatamente é $_P0ST... uma,ariável?
adicionando vida às suas páginas estáticas
t-POST é umavariável especial quearmazena dados
doformulário
$_POST é uma variável especial, conhecida também como superglobal,
porque ela é interna ao PHP e fica disponível para o script inteiro. $_POST
já existe quando o seu script é executado - você não a cria, como as outras
variáveis no PHP.
AliensAbductedMe-ReportanAbduction
Shareyour story of alien atdoctíon:
Asuperglobal POST
armazena todos os dados
d't3'iiados no iormularso-
Firstname:
Lastnamei
Whatisyour esnafladdress?
When did ithappen?
How toug w«reyou gone?
How man} did you sec?
Describethem;
Whatdid they do to yon?
Haveyoa seen my dogFang?
;
A
?
f /
1
M
a
d
i
r f <html>
a
^
r
»
^
1
i
í
«
Y
r
e
a
l
t
í
f
e
e
p
.
e
í
>
m ;J <head>
&
s
th
í
o
v
e
m
f
c
e
r <tifcle>Aliens
^
1
1hoursTy </head>
^
d
a
r
a
u
s <body>
i
l
i
t
t
l
e
s
r
c
e
i
tihm <h2>Alíens A
f
c
d
'
:
a
s
k
e
d a
J
s
o
i
s
t
Ü
F
Or
í
g
u
t
e
t
i
O
f
>
5
Ÿ» © No & <?php
$_POST[’howlong>
]
_ - y POSTr '
when ith a p p e n e d '1;
$how_long =(*$_P05T[1
howlong']; *
)
$alien__de$crIptlon~^'"$'_Ff§Tt~*TSescription' ];
$fang_spotted =
» $_POST[’f^gspotted11
$email = $_POST['email1J;
:
P
l
e
a
s
e
v
o
t
*
?
o
r
n
t
«
.
V
R
eportA
bnhictiw
T
}
echo ’
Thanks for submitting te form.cbr />',
echo 'You were abducted ' . $wen_it_happened;
echo ' and were gone for ’ . $h<Sw long . ‘
<br />';
echo ’
Describe them: ’ . $alien_«oscription . '<br />’
echo ’
Was Fang there? 1 . $fang_spVtted . 1
<br />’;
’
Your email address is 1 .
echo
?>
</body>
</htmI>
Asuperglobal $_POST évinculada diretamente
ao método de submissãousado peloformulário
HTML. Se o método tiversido definido como post,
então todos os dados são empacotados dentro da
superglobal $_POST, onde cadainformação pode
serretiradae usadaconforme necessário.
0 r»eh>do de submissão do
iorwwlav-io determina o
modo Corno©
Sdâdos são
•fornecidos ao script PHP.
reporthtml
l "w
r'
0 nome (“por Quanto
tempo ) vem do atributo «a^e usado
«a ta j <i»pu-è> Correspondente a este
Ca»»po do Tormulario-
0 » E R > 0 __________________
JE /L'"/VV‘-
Como você achaque
a superglobal $_p o s t
funciona? Como ela é capaz
de armazenar múltiplos
valores originários de todas
aquelas caixas de texto do
formulário de Owen?
você está aqui ► 33
$_POST é como um array
$-POSTtransporta osdadosdoformulário para oseuscript
$_POST é um tipo especial de ContainerPHP, conhecido como array, que armazenaum
conjunto de variáveissobum único nome. Quando o usuário submete oformulário de Owen,
os dados que ele digitou nos campos são armazenados no array $_POST, cujo trabalho é
repassaresses dados para o script.
Cada elemento do array $_POST corresponde a uma
determinada informação, digitada em um determinado campo
do formulário. Paraacessarosdados referentes a um campo
específico,vocêusa o nome desse campo com $_POST.
Por exemplo, a duração da abdução é armazenada em $_
POST [' howlong' ]. O código HTMLdo formulário de Owen
revela o modo como os nomes do formulário se relacionam
com os dados armazenados em $ POST.
<p>Share your story of alien abduction:</p>
<form method="post" action="report.php">
Clabel for="firstname">First name:</label>
<input type="text" id="firstr>ame" naree="firstname
Clabel for="lastname”>Last name:</labei>
<input type="text" id="lastname" name="lastname" / x b r £
<label for="email">What is your email address?</lab'
<input type="tex.t" id="email" name="email" /xbr
<label for='’
whenithappened">When did it h /label>
<input type="text" id=nwhenithappened" na nithappened"
<label for="howlong">Hciw long were you go bel>
-------..........SWIfIffill
r= bowmany">How many aid you
<input type="text" id="howinany" name="howman.y" / x b r />
Clabel for=”aliendescription">Describe them:</label>
clabel for="whattheydid">what
<input type="text" id="whattheyd:
<label for="fangspotted">Have youl
Yes <input id="fangspotted" name=
No <input id="fangspotted" nairie="f
Cimg src="fang.jpg" width="100" he
alt="My abducted dog Fang." /Xbr
<label for="other">Anything else you w
<textarea name="othern></textareaxbr
cinput type="submit" value="Report Abducti
</form>
ey do to""you?</label">"'
name="wh.attheydid"|S»ize="32" /X b r />
my dog Fang?</lljel>
angspotted" type="raaS,o" value="yes" />
type="radiovalue="no" /xbr />
="175"
add?</label>
name="submit" />
0 a rra y
$ _ p o sr&
p re e n c tld p co m
PS Vcjpres <jue O
usuarfp dlgitpu
n9 Çprmulárip*
0 nowC do tàrr^Q) H
O
Wmulávio, deicvmina
o modo domo ele e
adessado de«-bro do
array fJ>0£T
‘firstname’
‘iastname’ ‘whenithappened’
$ POST
‘aliendescription’
‘howmany’
Todos os dados do
■
-formulário -fidam disponíveis
através do arrav i PACT
adicionando vida ès suas páginas estáticas
r - ^Aponte seu lápis
X " Examine o código de report.php que está fazendo
a descrição dos aliens ficar em branco e depois
escreva a solução para o problema. Dica: use o
código HTML do formulário exposto na página
anterior para ajudar a isolar o problema.
Lembre-se1
anteriormente, «os
isolamos o problemâ
para essas duas ImKas
de tódigo.
<htrnl>'
<head>
<title>Aliens Abducted Me - Report an Abduction</title>
</head>
<body>
<h2>Aliens Abducted Me - Report an Abduction</h2>
<?php
$when_it_happened = $_POST['whenithappened'];
$how_long = $_POST['howlong'];
(^$alien_description = $_POST[1description
$fang_spotted = $_POST['fangspotted']
$email = $__POST [1email'];
echo 'Thanks for submitting the form.<br />';
echo 1You were abducted ' . $when_it_happened;
echo 1 and were gone for ' . $how_long . '<br />’;
echo 'Describe them: ' , $alien_description . '<br / > ' ; y
»■
*«________________________________— ------ —^
echo 'Was Fang there? 1 . $fang_spotted . '<br />';
echo 'Your email address is ' . $email;
?>
c/body>
</html>
reportphp
você está aqui ► 35
apontando solução
ponteseulápis
Solupão Examine o código de report.php que está fazendo
a descrição dos aliens ficar em branco e depois
escreva a solução para o problema. Dica: use o
código HTML do formulário exposto na página
anterior para ajudar a isolar o problema.
<input type-"text id-
= " a l i e n d e scription" name=(aU6ndescriptiõn^ si
0 fiotwC do £3»*po
C
mrÜportM>l
e "aliendcstvip-tioh”,
diievwte do wwe
"dcsCr'iyt»©« usado Com
fJ>0£T.
Kós pveCisamos
modiiicar ij> o s r
pâra tonrigiv o
nome do Câmpo-'
w
a!icndestvip'tiohW
.
</head>
<body>
report.html
Abducted Me - Report an Abduction</h2>
<?php
$when_it_happened = SN^pST[’
whenithappened1];
$how_long = $_FOST ['howlon^J,
$alien_description = $ POST[
'aliendescvip-bo«’
$fang_spotted = $_POST['fangspotted
$email = $_POST[1email1];
echo ’Thanks for submitting the form.<br
echo 1You were abducted ’ . $when_it_happened;
echo ’ and were gone for ' . $how_long . '<br />';
echo 'Describe them: ' . $alien_description . '<br />';
echo 'Was Fang there? 1 . $fang_spotted . '<br />';
echo 'Your email address is 1 . $email;
?>
</body>
</html>
reportphp
.
- ___ T f e S T O R f V G -------------------------------------
adicionando vida às suas páginas estáticas
Conserte e teste o script.
Modifique a linha de código problemática em report .php e
depois a envie para o seu servidor web. Abra a página report.
html no seu navegador, preencha o formulário com as
informações do seu caso de abdução e clique no botão “Relatar
Abdução” para submeter o formulário agora corrigido script.
você está aqui ► 37
revisando o script php do owen’s
Aponte seu lápis
Há alguns dados digitados no formulário “ Relatar
uma Abdução” que ainda não estamos usando.
Lembre-se, esses dados incluem informações
vitais sobre um caso de abdução, as quais
poderiam ajudar Owen a encontrar seu cão Fang.
Portanto, precisamos acessar ou filtrar todos os
dados do caso e armazená-los em variáveis PHP.
fabièlmznht o sdrift
vcfortfhf’esta
i^snorSndo Cinto
dam^os âo -Çormulârie
v>3dreditávcí!
<form method“"p o st” a ctio n ^ "re p o rt.php">
<Iab e l fo x= "firE tn a m e "> F irst name:</label>
cinput typ e= "text” id = ”firstnam e” name="firstname" /:
clab e l for="lastnam e">Last name:</Iabel>
<input typ e="text" id^'lastnaitie” r-ame="lastname,
T /><
<label fo r= ”e:nail">What is your em ail address?</lsbe
<input typ e="text" id ="em ail" name="email" / X b r /> :
-clabel for="whenithappened">When did it happen?</lai:
cinput ty p e ^ 'te x t” id = ”v
.’henithappened" name=IT
whenitl‘
■clabel fo r= ’^ow idng3»
5How long were you gone?</label;
<input typ e ^ IS iit^ ’ id="how long" naine="howlong" AfljUiMigrise you wanttnaH/i-1
<label f or^"howr.aiV£?>How many d id you see?</label> US?*?®?fltxiiiaSoin
<input typeiHtfeex'C1
' id="hbwmany" name="howmany" / x b
<label fo r= "a lie n d e scrip tio n "> D e sc rib e them :</label>
<input type5^-texfi'^id="aiiendescriptio_n" n ane = "alie n d e scrip tion " s iz e = "32"'
■clabel for=Xjhatjtheydid">,i3hat d id they do to you?</label>
■cinput type=" te xt" id="w hattheydid" nam e="w hattheyd id "size="32" / x b r />
«Clabel for="fangspotted">Have you seen my'dog Fang?</J©Hit^l'
Yes Cinput id = ”fangspotted" name="f£.ngspotted" typ e="rad i
No <input id ="fan gsp otte d" name="fangspotted" typ e="rad io"
<irr,g src = "fa n g .]p g " w idth="100” height="175"
3lt= "M y abdu.c.t^d dog Fang." / x b r />
< label for=r^othei?'>Anything e lse you want to add?</label>
-ctextarea i^js no$Jfer’' name=”othet,’></taxtarea><fcr />
<input type="subm it" v a lu e -" Rspo^t Abduction" name=T
>
submit
</form>
-c/body>
</html>
fl -ta^ <myut>
de dada dawyo
do -Çoviwulario t
ja dkave para
fadesso aos dados,
a partir do PttP•
reporihtml
Escreva o código PHP afim de criar quatro novas variáveis que
armazenem os dados do formulário que estão faltando: $naine,
$how_many, $ w h a t_ th e y_ d id e $ o th e r. Dica: Crie a variável
$name de forma que ela armazene o nomexompleto do usuáriçu--'"
% ...rir..^_iPQ.r^.A..L.,W. !. ......................
%. .á* .í*.fa2.U/.. ....................
1o£.h£r..,rr..i—.í^ríXL .3^................
adicionando vida às suas páginas estáticas
Seu trabalho ainda não terminou. A página de confirmação
gerada peio script PHP precisa usar essas novas variáveis para
exibir mais informações sobre a abdução.
FVedisamos partir disto -
AliensAbductedMe-ReportanAbduction
Yon were abduciedfastNovemberand-weregone for 11Iruis
Describethem*littlegreen
Was Fangthere?do
Youremailaddressisalfh@ihe}Tvsa%ree}Lcom
•para isto/ Repare *ê quantidade
de «ovas iníormaÇoes exibidas.
f r f : ■
0 nome do usuário nSo c esseindiai
para a pagina de dwi-Çirmâçaoj ^
vode precisará dele p o sté rio rité ,
quando enviarmos o email dom os
dados para Owen-
Tfrai&sforsubmittingfee form.
Yoa were abductedlastNovemberandwere gone for 11hours
Humberofaliens:dozens
Desoibet
h
e
s
s
:M e g
r
e
e
a
in^n
The aliensdid this: asked meaboutUFO regulations
Was Fang Sisre? £0
Otbefcomments’.Pleasevoteforna.
YonrftrrmfladdressisaifnStheyrealigiwn.com
Usando todas as variáveis que acabou de criar, exceto Sname,
complete o código abaixo, o qual irá gerar uma página de
confirmação mais infòrmativa.
echo 'Thanks for submitting the form.cbr />';
echo 'You were abducted ' . $when_it_happened;
echo ' and were gone for 1 . $how_long . '<br />';
echo 'Describe them: ' . $.alien_description . '<br />';
Í J ! /'>.'• f * ^  í . í y , J jj Ç
.Ochxk.
.
.
.
W
r
7
:
1
át :
.
.
t kw.V
.
.
. zf...z..àt.--X.á
a
y
í«
-
r
J.íd .
.
.
.
.
.
.
.
.
.
.
S
C
.ít. /.
echo 'Was Fang there? ' . $fang_spotted . '<br />';
1 - A ^ * J * * 3 ^ ,
v Jv V "
.......£&t. hM ?.......... A t ../.■<..............
echo 'Your email address is ' . $email;
£
você está aqui ►
o script php do owert revisado
%^ponte seulápis
Solução
Há alguns dados digitados no formulário “Relatar
uma Abdução” que ainda não estamos usando.
Lembre-se: esses dados incluem informações
vitais sobre um caso de abdução, as quais
poderiam ajudar Owen a encontrar seu cão Fang.
Portanto, precisamos acessar ou filtrar todos os
dados do caso e armazená-los em variáveis PHP.
^•UaUen-be o sóript
reportphp esta
i<yorândo ivnto
£a»pos do ío rm u ld rio .
|inacreditável!
<form method=,’p o st" action »1
1report ,php">
clab ei fo r= "firstn a m e "> F irst name:</label>
cinput typ e="text" id = "firstn am e " name="firstname" /
< label for="lastnam e">Last name:</labei>
<input type=”te xt" id="lastnam e" name-',lastna^!e', /><
< lab e l for="em ail">W hat is your em ail address?</lahe
<input typ e="text" id = "e m ail" name="email" / x b r />
<label for="whenithaopened">When did i t happen?</iafc
<input typ e="text" id^'whenithappened" ■name="wh.enii:i
clab el for="howlDng">How long were yon gone?</label; .
<input typ e="text" id “"howleng” name="howlong" /><b: .— Epfeyog want to add?
< lab e i for="howmany">How many d id you see;</label>
<input typ e="text" id="howmany" naree="howmany" /><b;
<label fo r= "alie n d e sorip tion "> D e £ crib e them:</label
<input typ e="text" id = "a lie n d e so rip tio n " name=T
,a lie n d e sc rip tio n " s iz e =”32
< lab e i for="whattheydid">W hat d id they do to ycu?</label>
<input typ e="text" id="w hattheydid" name=T
,w h attheydid"_size="32" / x b r />
<label for="fangspotted">Have you seen my dog F a n g?< / JS e l>
Yes <input id="fangspoti;ed" r.ame="fangspot ted" typ e = "ra d i
No <input id ="fan gsp otte d" .iame="fangspotted" typ e="rad io"
<img src = "fa n g .jp g " w idth="100" h e igh t= "175"
alt="M y abducted dog Fang." / x b r />
<label fo r= "other">Anything e lse you want to aad?</label>
<textarea id -"o t h e r ".name=”oth e r"> </ te xtare aX b r />
cinput type="subm it" va ltie= "Report Abduotion" narr.e^1'subm it1
1
</fcrm>
</body>
</j
A ta$ <»put>
de cada ca»po
do ioriwulario e
a th iv t para
atesso aos dados,
a partis do PttP
Escreva o código PHPa fim de criar quatro novas variáveis que
armazenem os dados do formulário que estão faltando: Sname,
$how_many, $what_they_did e $other. Dica: Crie a variável
$name de forma que ela armazene o nome completo do usuário.
0 poK-i»íihâl f
ò
f
e
x
j
.
. j
fW
rW
rfcejuhbr Í%amC ■
••/•?JW$T.Ç
varias strings de
■
textoem ur»a
so - umpvodísso
Conkedide tomo
LoKtàteràÇac.
este «paço
separa o
priineiro
r>or»e áo
sobrenome.
fbow^»âlr»y —fJ?OSTC‘Kowrr.ahyjj
f>wh^_tbçy_did 77 /_P.PSTtViaHttiKçyclid/pi
fother =
■
/_Pp$X
adicionando vida às suas páginas estáticas
Seu trabalho ainda não terminou. A página de confirmação
gerada pelo script PHP precisa usar essas novas variáveis para
exibir mais informações sobre a abdução.
Predisamos partir disto
0 nome do usuaHo não c essential
para a pagina de d©n-firmaça©> mas
vote prensará dele posteriormente
quando enviarmos o email tom os
dados para Owe«-
0 Comando
edho é usado
para enviar as
in-Pormacoes
ao navejador,
na íorma
de donteúdo
HT/VJL."
Usando todas as variáveis que acabou de criar,
exceto $name, complete o código abaixo, o qual irá
gerar uma página de confirmação mais informativa.
echo 'Thanks for submitting the form.cbr />';
echo 'You were abducted ' . $when_it_happened;
1
<br />';
As tajs <br />
ajudam a -formatar as
iníormadoes - não se
esqueça de que estamos
usando PttP para driar
ttTM L.
echo 1 and were gone for ' . $how_long
edbo 'Kumber of aliens; 1. fbow_mâny . '<br /> ]
Movamente, pontos'
f
i
n
a
i
s são usados echo 'Describe them: ' . $alien_description . 1
<br />';
para dondatenar edho lTbe aliens did tbis: 1 f>«bat_tbey__did • '<br /> ',
strings c varáveis.......................................'■/»..........................................................................
echo 'Was— Eang -
f
e
j
l
^
re? ' . $fang_spotted . 1
<br />';
edbo 'Other domments: 1. fotber . (<br />',
echo 'Your email address is ' . $email;
você está aqui ► 41
test drive no script php do owen
T f e S T D r i v e
Ajuste o script de Owen e teste as modificações.
Adicione o código das novasvariáveisa re p o rt.php, bem como o código que
enviaasvariáveispara o navegador, com o HTMLformatado. Em seguida, envie o
scriptpara o seu servidorweb, abra a página re p o rt.html no seu navegador e
preenchao formulário com asinformações do seu caso de abdução. Finalmente,
clique no botão “RelatarAbdução”para submetero formulário everos resultados.
n£ÍP existem
Perguntas idiotas
0 que realmente acontece quando eu faço a
concatenação de várias stríngs, usando pontos finais?
R:
0 que acontece com o código PHP no navegadòr?
OK, então como, exatamente, o servidor
transforma o código PHP em códigos HTML e CSS?
Concatenar, neste caso, significa juntar
diversas strings para formar outra, totalmente
diferente. 0 resultado final é sempre uma única string,
não importa quantas tenham existido originalmente.
Assim, quando você concatena strings como parte
de um comando echo, o PHP, primeiramente, as
combina em uma só string e depois envia esta última
para o navegador.
T * * Quando eu concateno uma variável com uma
string, a variável precisa conter texto?
Não. Embora aconcatenação sempre resulteem /
uma string, as variáveis não precisamconter strings j
paraquevocê possausá-las emumprocesso de /
concatenação. Por exemplo, digamos que umavariável
contenha umnúmero; o PHPprimeiramente converte 0
número emuma string edepoisa inclui naconcatenação.
?:
P . 
*■V- Nada. Eisso porque 0código PHP nunca é viste
pelo navegador. Ocódigo PHPé executado no servidor
ese transforma emcódigo HTML, este simsendo
enviado para 0navegador. Assim, 0 navegador nem
sequer fica sabendo da existência do PHP- as páginas
web chegam como puros HTML e CSS.
H Em primeiro lugar, lembre-se de que, por padrão,
assume-se que 0código em umscript PHPé código
HTML. Você pode identificar 0código PHPdentro de um
script colocando-o entre tags <?php e ?>. 0 servidor
vê essas tags e entende que deve rodar 0código dentro
deias como PHPetodo 0código fora dessas tags é
informado ao navegador como sendo umHMTL.
- Certo. Mas isso ainda não explica como o
códig^f^^jh^nsTõrmaíoíiivWTML/CSS. E então?
Ah, é aí que 0comando echo entra erfccena. '
Você pode pensar no echo como umcomando
para enviar as informações que estejamfora do 
domínio das tags <?php e ?>. Assim, 0comando 
echo representa a chave para a capacidade do
PHPde gerar código HTML/CSS, dinamicamente.
Concatenando strings de texto comvariáveis PHP, você
pode construir código HTMLemtempo real e depois
usar echo para enviá-lo ao navegador como parte da
páginaweb resultante. Umbomexemplo disso, no scrip
report .php, é quando atag <br /> éanexad
ao final de umpedaço de texto para gerar uma quebç
de linha no HTMLresultante.
adicionando vida ás suas páginas estáticas
A página de confirmação é útil
para o usuário, mas não para mim.
Ainda preciso que os dados do
formulário sejam enviados para mim
através de um email.
O script PHP ainda precisa enviar os dados do formulário
para Owen.
Daforma como está, o script report.php estáusando osdados do
formulário “RelatarumaAbdução”para geraruma páginade confirmação
HTMLpara ousuário. Masisso ainda não está resolvendo o problema
original, que baseia-se no envio de uma mensagem por email para Owen,
umavezsubmetido o formulário. Ele quer apenas receber uma simples
mensagem de email em modo texto, mais ou menos como a seguinte:
r -
De Wma scm
elKan-fee à
paji»>a web d t Con-fVmaçao,
esta »ensaiem de email
Consiste em texto estático,
Combinado Com dâdos do
-(•oV-mulário
Estamensagem de email pode sergerada a partir de código PHP,
criando-se umastring que combine textos estáticos como "Outros
com entários: " com dados doformulário que estejam armazenados
emvariáveis.
Escrevaaquicomovocê criariaumamensagemde email apartirde texto
estático evariáveisPHP.
-Ê tf -s
•'*...................................................................................................................
AlfNaderfoi abduzido em novembro passado e esteve
ausente por 11 horas.
Número de aliens: dúzias
Descrição dos aliens: homenzinhosverdes
O que elesfizeram: me perguntaram sobre leispara asOVNIs
Fangfoivisto: não
Outros comentários: Porfavorvote em mim.
você está aqui ► 43
construindo o corpo da msg no php
Criando ocorpo da mensagem de email com PHP
Vocêjá viucomo um ponto final pode serusado em códigos PHP
para concatenarváriasstrings de texto em uma só.Agoraprecisa usar
novamente a concatenação para criaruma string que seráa mensagem
de email, com variáveissendo usadasjuntamente com texto estático.
V iáveis c tex to estático
Sao ConCatenados em uma
unica string (a mehsagem
de email) usando—
se pontos
-Pinais.
maioria dos editores de
texto, automaticamente,
quebra o tex to para a linha
seguinte, mesmo <ue vote ndo
inclua no código a sua própria
quebra de Wha (return)-
5msg = ■ ' was abducted
'Number of aliens:
’Fang spotted:
and was gone for ’ .
'Alien description: ’ .
'
Other comment
'■What they did:
Um problema ao se criaruma stringdesse tamanho é que ela demanda
uma grande linha de código PHP, difícilde ler e entender.Você pode
dividiro código PHP em váriaslinhas, para deixá-lo maisfácilde ser
estudado. Certifique-se, apenas, de separaro código em pontos onde
o espaçamento não faça diferença, como por exemplo, entre duas
strings concatenadas e não no meio de uma string. Em seguida, coloque
um ponto evírgulano final da última linha de código, para finalizar a
instrução PHP.
[st© na verdade i apenas uma grande linha
. de código dividida em varias linhas.
Lembre-se^ cada
variável armazena
uma string de texto
« tira d a do -formulário
Relatar uma /'tbducao 5.
v T '
$msg = . 1 was abducted
'Number of aliens:
'Alien description:
'What they did:
'Fang spotted: '
'
Other comments:
Ó^uando uma linha de Codigo
PHP e: deliberadamente,
dividida em varias linhas,
costuma-se indentar as linhas
após a primeira, para ^ue se
perceba, Com mais -facilidade,
*uais linhas Compoem u».a
mesma instrução no seu código-
was gone for
^ de código e Cuidadosamente
dividida, evitando-se separar uma
string no meio.
Mode ainda precisa f inalizar a
instrução» Com um ponto e virgula.
Um a longa linha de c6dígp p jjp pode
set diVidlda era Vatlas llnfcas, desde <jue
Você tenha cm dad° na fcpra de separar
o eódígo.
adicionando vida às suas páginas estáticas
Esse código PHP certamente ficou bonito. Mas
sem formatação, a mensagem de emai! não vai
ficar toda bagunçada?
Sim. Só porque o código PHP está bem organizado, não
quer dizer que o seu output (saída), autom aticam ente,
também ficará bonito.
Organizai’o código PHP para que vocêpossaentendê-lo melhor é
completamente diferente de formatar o output que osusuários irãover.
Você normalmente usará tags HTML para formatar o output do código
PHP, umavezque, na maioriados casos, o PHP é usado para segerar,
dinamicamente, uma páginaweb. Porém não neste caso.
Aqui, estamos gerando uma mensagem de email, que é puro texto, e não
HTML. Precisamos lidarcom o feto de que a mensagem, atualmente, se
parece com o resultado seguinte:
AlfNaderfoi abduzido em novembro passado e esteve
ausente por 11horas.Número de aliens: dúzias Descrição
dos aliens: homenzinhosverdes O que elesfizeram: me
perguntaram sobre leispara as OVNIsFangfoivisto.
nãoOutros comentários: Por favorvote em mim.
I
Hm... isto WftQ 't 0 <^e
Owen metvte
pava 3 sua
de e-m ail
existem
Perguntas Idíçtas
- Existe alguma maneira de se usar
formatação HTML em emails que você envia a
partir de um script PHP?
Existe. Mas isso requer umpasso adicional,
que envolve definir o cabeçalho do tipo de conteúdo
para a mensagem. Cabeçalhos etipos de conteúdo
vão um pouco alémdoescopo desta discussão, por
isso, estamos nos limitando a mensagens de email
emformato de texto simples. Você aprenderá mais
sobre os cabeçalhos no Capítulo 6, portanto, não se
preocupe - você verá como enviar emails em HTML
mais adiante.
W E R » 9
Como você reformataria a
mensagem de email para
torná-la mais fácil de ler?
você está aqui ► 45
formatando texto com php
Até mesmotexto simples podeser
formatado... um pouco
Umavezque Owen estáenviando mensagens de email como texto
simples, sem nenhuma formatação especial HTML, ele não pode
colocar tags<br /> para adicionarquebras de linha para separar
o conteúdo. Masele pode usar caracteres newline (novalinha) ,
que são escapados naforma  n.Assim, em qualquer lugardo
email onde apareça n, seráinseridaumaquebra de linha, fazendo
o conteúdo que viera seguirseiniciar na linhaseguinte. Eiso novo
código para a mensagem de email, com os newlines adicionados:
^ t usado para
^uc seja»* inseridos
darattergs newline na"
■
m
ensagemde em
ail-
Coracteíes cie
escape em P B P
começam com uma
t>arramVertlJa 00-
$msg = $name was abducted $when_it_happened
'Number of aliens: $how ma
and was gone for $how_long ' M '
'  n 1
'Alien description: ’ . $alien_defecription . '
|
'What they did: ’ . $what_they_did . '
|
|
|
;
r .
'Fang spotted: ’ . $fang_spotted . ’
J
j
j
|
j
, .
'Other comments: ' . SothGr;
Alf Nader foi abduzido em novembro passado e esteve
ausente por 11 h o ra ^ ^ ú m e ro de aliens: dúzias^n}
Descrição dos aliens: homenzinhos verdes^rTp que eles
fizeram: me perguntaram sobre leis para as 0  7
N I.<g^ang
foi visto: n ãq g p u tro s comentários: Por favor v o te tS mim.
O que é, exatamente, um caracter de escape?
Umcaracter de escape é umcaracter que: ou é difícil de digitar
ou que, por algum motivo, poderia causar confusão nocódigo PHP.
Você pode estar familiarizado comos caracteres de escape do HTML,
programados de uma forma umpouco diferente, como por exemplo,
& # 1 69 ou &copy para o símbolo de Copyright. OPHPtemum
conjunto bastante pequeno de caracteres de escape que são úteis para
se escrever coisas que poderiamse confundir coma própria linguagem,
como por exemplo, aspas simples (V), aspas duplas (V) e, é claro,
newlines (n).
0 n esta aparedewdo
-tomo te*t© Psormâl)
zm vez. de um
ta ra tte r newline
nada bom-
B j Ú
adicionando vida às suas páginas estáticas
y
cisam de aspas duplas
O problema com o código de Owen é que o PHP trata as strings de forma
diferente, conforme elas se apresentem: dentro de aspas simples ou duplas. Mais
especificamente, os caracteres newline (ji) só podem ser escapados dentro de
aspas duplas. Assim, a mensagem de email com os dados do formulário precisa ser
construída usando-se strings dentro de aspas duplas, para as newlines funcionarem,
Masa históriadas aspas simplesx duplas não termina aí.Asstrings dentro de aspas
simples são consideradas como texto puro, enquanto que o PHP processa asstrings
dentro de aspasduplas em buscade variáveis. Quando umavariávelé encontrada
dentro de uma stringem aspasduplas, o PHP insere o seuvalor dentro da string,
como se tivesseocorrido uma “concatenação”.Assim, a stringdentro de aspas duplas
não só é necessáriapara ofuncionamento dos newlines na mensagem de email, como
também nos permite simplificaro código, colocando asvariáveis diretamente na string.
tontaier>a^ao
ttâo Cw
»ôis
netessavia,
urnâ vex. *ue
as variáveis
pode» ser
veíerendiadâs
diretamente
dentro da
string entre
aspas jdvfIas-
$msg = "$name was abducted $when_it_happened and was gone for $how_long.n"
"Number of aliens: $how manyn" .
"Alien description: $alien_descriptionn"
"What they did: $what_they_didn"t
]
"Fang spotted: $fang spottedn"
"Other comments: $other";
Kao e pretiso dc u*»a no va )
linha guando -for a VmKa
■
Pinal-
Os daracieres newline agora sao
interpretados dorretamente,
graças à siring apresentada entre
aspas duplas.
Mas ainda predisamos dividir a mensagem em
varias strings dondatenâdas para tornar o
dodigo mais legível
não existem
? Se as aspas duplas são tão legais, por que é que por
que fizemos uso, praticamente, aspas simples, até agora?
rJ^I^m lejlJ^em jTiente que agaspas simBJj^não|
 são processadas pelo PHPdëïienhuma manéír^ o que
as tcrrna ideias~paraswitjsrqütí yaü"puiu luxlir/s&m
nenhuma variável inserida. Assim, continuaremos a usar
aspas simples ao longo do livro, a não ser que haja um
bommotivo para usar as duplas. Acoisa mais importante
nesta questão de usar aspas simples ou duplas para as
strings, étentar manter-se o mais consistente possível.
perguntas idiotas
usar umapóstrofo em uma string dentro de aspas
simples, basta fazer escape dele como V,desta forma: ’
H e V s lost! '.0 mesmo se aplica se você quiser
usar uma só aspa dupla dentro de umastring delimitada
por aspas duplas- use V. Nãoé preciso fazer escape
das aspas quando não houver conflito, como por exemplo,
ao usar umapóstrofo emuma string contida entre aspas
duplas: "He's lost!"
.
0 que acontece se eu tiver de usar um
apóstrofo dentro de uma string que esteja dentro
de aspas simples, como por exemplo, em 1He1s
l o s t ! ’ (“ele está perdido!”)?
Então, com as aspas simples, pode-se usar V
mas não n. Como saber quais caracteres de escape
eu posso usar dentro de aspas simples?
As strings denlco^easpas simples só permitemos
caracteres de escapéV eOodos osoutros caracteres
de escape só podemsfèníSados emstrings dentro de
aspas duplas.
R * Éaí que os caracteres de escape são úteis. Para
você está aqui ► 47
envie email com PHP
Enviando uma mensagem de emaii com PHP A Çunçã°
Então, você estápronto para escrevero código PHP que enviaráa mensagem m a ílO , d » ? B T 
a Owen por email. Isto requer afunção interna mail () do PHP, a qual
envia uma mensagem com base em informações que vocêfornece. envia uma
mensagem de
email a partir
de um sctipt.
0 e*dcr£to~àc
o^aíl w
to •
't)"ãSSimto dâ
mail ($to, $subject, $msg) ;j
^ iS
0 torpo da
mensagem.
Essastrês informações são requeridas pelafunção m ail (), portanto,
você sempre tem de fomecê-las. O endereço de email “from”não
é exigido, mas ainda é uma boa ideia incluí-lo. Para especificaro
campo “from”ao chamarafunção m ail (), é preciso üsãrimioutro
argumento dafunção,junto a algumaconcatenação de strings.
mail($to, $subject, $msg,
o ie *to 'FVom:' pretisa ser
fi.oloi.ado antes do endereço,
ao sc espetiíitar o enderedo
de «»ail do remetewte-
Cada parte do emajl
t íometida à -função
mailO por «ma variavel-
$email|;
0 ponto -final t útil mais
uma vez* para tontaíenar
From; dom o endereço de
email de Owen-
nãp existem
?efguntas idiotas
X * Há mais alguma coisa que possa ser
especificada como parte de uma mensagem
de email, além do endereço “from”?
Sim. Vocêpodeespecificartambém
recipientes“copy”(“cópia”) e“blindcopy” (“cópia
oculta”)da mesmaformaqueo“from”- basta
usar' Cc: ' ou ' Bcc: ' emvezde
1From: '.Sequiserespecificartantoum“from”
quantoum“copy”,vocêterádesepará-loscom
umacombinaçãodecaracteres returnenewline
(rn), destaforma:
£ isso mesmo, dois taratteres de
esdape tolados um no outro^
$from . nrnCc:" . $cc
i 'a n t f iif f l ■f
Pretisamos usar aspas duplas a^ui, uma
vez. <
^u
e estamos usando os taratteres
de estape V e n.
adicionando vida às suas páginas estáticas
Mas então, como é que
nós usamos, realmente,
a função mail()?
£nvic a
umâ
p%"mâ HT/WU
em tempo real,
pâva dôh-Çirmâr
^ue O-formulário
toí submetido
Com sudesso.
Basta adicionar ao seu script o código para cham ar mail().
Alinha de código que chamaa função mai1 () é tudo o que vocêprecisa para
enviara mensagem de email. Certifique-se de que este código apareça no script
apóso códigoque criaasvariáveispara o email, e pronto. Eisaqui o código
completo para o script report.
php de Owen, incluindo a chamada para a
função m ail ().
<html>
<head>
<title>Aliens Abducted Me - Report an Abduction</title:
</head>
<body>
<h2>Aliens Abducted Me - Report an Abduction</h2>
<?php
Çname = $_POST[1firstname1] . ' ' . S^POST['lastnaree'
]
$when_it_happened = $_POST[1whenithappened'];
$how_long = $_POST[1
howlong’];
$how_many = S_POST['howmany1];
$alien_deseription = $_POST['aliendescription'];
$what_they_did = $_POST[1
whattheydid’];
$fang_spotted = $_POST[’fangspotted'];
Çemail = $_POST[1
e m a i l ;
Sother = $_POST[’other1];
Pegue todos os dados
do -formulário no array
fJP0ST e doio^ue-os
em variaveis individuais-
Certiíi^ue-se de
tirodar este enderedo
de email pelo seu
próprio, para testar o
sdript-
$to = ’ovien5aliensabductedme.com
^subject = 'Aliens Abducted Me-- Abduction Report1,
$msg = "Snarne was abducted $wh.en_it_happened and was gone for $how_long.n
"Number of aliens: $how_manyn” .
"Alien description: $alien_descriptionn" .
"What they did: $what_they_didn" .
"Fang spotted: $fang_spottedn" .
- '
-
'
X
I
U
mu-
—r
n
m
i
r
i
^
n
t
g
: Sn-t-hgr"-
■ .
.
.
^nail($to, $subject, $
r
c
.
s
g
, ’From:' . Semail)7^>
echo 'Thanks for submitting the form.<br />';
echo 'You were abducted 1 . $when_it_happened;
echo 1 and were gone for 1 . $how_long . ’<br />';
echo 'Number of aliens: 1 . $how_jnany . '<br />’;
echo 'Describe them: ' . $alien_description . '<br />’;
echo ’The aliens did this: ' . $what_they_did . '<br />
echo 'Was Fang there? 1 . $fang_spotted . '<br />';
echo 'Other comments: ' . $other . '<br />';
echo 'Your email address is ' . $email;
Junte os diierentes
pedacos da
mensagem a ser
enviada para Owen.
</body>
</html>
reportphp
você está aqui ► 51
email overload
Owen comepa a perder emails
A boa notícia é que Owen está recebendo emails. A má notícia é que ele está recebendo
muitos, muitos emails. Tantos que está tendo dificuldade em acompanhá-los. A sua Caixa
de Entrada está lotada, e elejá apagou alguns acidentalmente... Owen precisa de uma
forma melhor de armazenar os dados sobre as abduções.
adicionando vida às suas páginas estáticas
*
m u F
Os aliens mexeram com o seu cérebro? Coloque ascoisasno lugar
ligando cadacomponente HTMLou PHP à descrição do que eles fazem.
SilpeígfcW
mailO 
Um software que serve para visualizar e interagir
com páginas web. Age como o lado do cliente em
■ comunicações na web.
Um comando PHP usado para fazero output de algum
i f conteúdo, como, por exemplo, texto simples ou código HTML.
f instastagssão usadas para delimitar o código PHP a fimde
! j que o servidorwebsaibaque deve processá-lo e executá-lo.
^ Um arrayintemo do PHP que armazena osdados
submetidos usando o método “post”.
Uma linguagem de programação usadapara a criação
de scripts, que são executados em um servidorweb.
Todastring precisaestar dentro de umavariável.
Um softwarepara enviarpáginasweb, o qual age
y ' como um servidorem comunicações na web.
/ l _ Uma linguagem marcação usada para descrever a estrutura
/ do conteúdo das páginas web, que são visualizadas em um
navegador web.
Um nome usado para descreverasvariáveisinternas do
^ PHP que ficam acessíveis a todos os scripts.
Uma série de campos de input, em uma páginaweb,
usados para seobter informações dos usuários.
Umafunção intema do PHP que enviamensagens de email.
Um local de armazenamento, em um scriptPHP, que
tem o seu próprio nome e tipo único de dados.
Um tipo de armazenamento de dados em PHP que
permite que várias informações sejam armazenadas em
um mesmo local.
você está aqui > 55
2 C o n e c t a n d o - s e a « M y S o L
* Como Tudo se Encaixa
Saber como as coisas se encaixam, antes de começar a
construir, é uma boa ideia. Você criou seu primeiro script PHP e ele está
funcionando bem. Mas obter os resultados obtidos em um email já não é bom o suficiente.
Agora você precisa de uma forma de guardar os resultados do seu formulário, para que
possa mantê-los pelo tempo que precisar e ter acesso a eles quando quiser. Um banco de
dados MySQL pode armazenar estes dados para você. Mas você precisa conectar seu script
PHP ao banco de dados MySQL para fazer isso acontecer.
este é um novo capítulo ► 59
0 formulário de Owen funciona bem. Pem até demais.
Sera prediso mais
do *^u€ uma xídara
dc da-P
e para
O'uzrt donseguir se
»anter a par de
todos os relatos de
àbdudoes o
^u
e estâo
dHega*do r>asua
Caixa de Enteada.
O novo formulário
para os relatos é ótimo, mas agora
estou recebendo emails demais. Não consigo
beber cafeína suficiente para ler todos eles
assim que os recebo.
O script de Owen estava funcionando bem
enquanto ele estava recebendo apenas
algumas respostas, mas agora ele está
recebendo centenas de emails, muito mais do
que consegue organizar.
Elejá apagou alguns acidentalmente, sem osler. Ealguns estão
indo parar na pasta de spam, a qual ele nunca olha. Na verdade,
um email que lhe interessariamuito pode está escondido na
pastade spam, neste exato momento...Owen precisade uma
forma para armazenar todas asmensagens, de forma que
ele possaconsultá-lasquando tivertempo e encontrar
facilmente aquelas relativasao seu cão Fang.
Este relatório
perdido mendiona
um dao (doo^)...
trata-se de
iníorrnaçoes de
^ue 0we» pvedisa,
[desesperadamente.
From: safiy@gmgs-4Jstnei:
Subject: AliensAüductedMe-AbductionReport
*<V4obef1,200612:1129PMCDT
>
andwasgene
To; „
SatiyJoneswasabducted3daysago
m<imfeefofaliens:four
descfipfion:greenwithsixmala***«----
•w did:Wejusttaikedanqpiayedwith
tor1day-
Humbei
Wienda
Whatleyd
i
d
- C
o
n
t
a
c
tm
s
.
A
Owen predisa «jue mensagens
domo estâ sejâm armazenadas
de -forma segura em algum lugar
o*de ele possa donsuiti-las, em
busda de possíveis avistamewtos
de Fang.
É aqui que um banco de dados MySQLviria a calhar..
Caso vode na©saiba, a <*aior'sa das pessoas J
prohundia /Vjy£$L soletv-âhdo as ultimas —
três letv-as, ou seja, ”my ésse <
^u
êele*.
conectando-se ao My SQL
MySQL é excelente para armazenar dados
Owen realmente precisa de uma forma de armazenar osdados dos relatos
de abduções em um lugar seguro, que não a sua Caixade Entrada de email.
O que ele precisa é de um bancode dados, que é uma espécie de gaveta de
arquivos hi-tech, arrumada e super organizada. Umavezque asinformações
localizadasem um banco de dadosficam totalmente organizadas,você pode
consultar a informação exata que precisar, quando precisar.
Os bancos de dados são gerenciados por um programa especial, chamado
servidor do banco de dados - no nosso caso, um servidor de banco
de dados MySQL. Você se comunica com esse servidor usando uma
linguagem que ele é capaz de entender, que no nosso caso é o SQL. O
servidor do banco de dados geralmente rodajunto a um servidorweb na
mesma máquina, com os dois trabalhando em conjunto na leitura e escrita
de dados e na entrega de páginas web.
0 servidor web prodessâ as requisições
for fS^ihas y/eb, e*edufca s£rip-fcs PHP Computador Servidor
e reiema tonieúdo HTML.
Navegador do Cliente
0 "SOL-1»
siÿni-Piia
Sèrué-tuved
$uery Language
de Consulta
Êsb-wtwrada").
0 M/SoL
qrnicfc&ena
ciados deiïtrç
de tabeleis
do banco de
d ad o s.
Banco de dados MySQL
0 servidor de bastos de dados le e ----
esdreve dados de/para o banòo de dados
Osbancosde dadosMySQLsãoorganizadosem tabelas, asquaisarmazenam
informações emformade linhas e colunas de dadosrelacionados.Amaioria das
aplicaçõeswebusauma ou maistabelasdentro de um mesmobanco de dados,
deformamaisou menosparecidacomo usardiferentespastasdentro de uma
mesma gavetado armário de arquivos.
0 servidor do batóo de
esdreve dados no
Um bâftdo de dados
pode don-ter múl-bpias
-tabelas
0 bário de dados
propriawewfce d,-to
dom £re<uê*ò"tâ, e
ârmô^^ado na
lermâ de ar^tvos
em u» fosto ^
viÿdoj »âs t*3o
^etessariawe^te
predisa ser assW-
Com osdados sobreasabduções armazenadas deformaseguraem
um bancode dados MySQL,Owenpoderá analisar, daformaque
quiser, todos osrelatos de pessoasque responderam “sim”à questão de
seavistaramou não Fang. Elesóprecisade um pouco de código SQL
para secomunicarcom oservidordo banco de dados.
S Q L e u m a
linguagem de
consulta usada
pava <jue o co rra
a comunicação
com um banco de
dadosAiySoL.
v o c ê está aqui ► 61
mysql pode ajudar Owen
Owen precisa de um banco de dados MySQl
Então, estádecidido: osbancos de dadosMySQLsãoúteise Owen precisade
um para armazenardados sobre asabduções alienígenas. Elepoderá, então,
modificaroscriptreportphp paraarmazenardados na tabelei, emvezde enviá-
losparasimesmo, poremail.Atabelamanterá osdados recebidossãose salvos,
dando tempo a Owenpara analisá-losefiltrarpotenciaisavistamentosdeFang.
Masvamos “começarpelo começo”...um banco de dados!
Parase criarum banco de dados My5QL, faz-senecessário um servidor
MySOLcom um softwareespecial.Arazão disso é que, ao contrário de
servidoresweb,um servidorde banco de dados precisareceber instruções
usando comandos SQL.
Acriação<
J
e
bcUlCPg cie
dadps e tabelas
M /SQ L exige
com un icação
com . um serV lJor
M ySq L .
Eu sempre ouvi dizer que a
ferramenta utilizada faz toda a diferença
para se fazer um trabalho direito. Como eu vou
saber qual ferramenta MySQL usar para criar
meu banco de dados e minhas tabelas?
0 -brmihái é urna
janela <^e íomede ôusso via
lihHa de domândo, onde v©
de
pode digitar demandes £QL~
M ySftl terminal
0we* predisa de
uma -ferramenta
para
dHdr seus »ovos
bando de dados
e tabelas.
0 pbpMyAdmm e uma
0 pbpM
yA
dm
mpbpMyAdmiH ferramenta gráfica
f 6 .... ... k, bandos de dados e
€m ------------------------------rtpvMún E' tabelas atvaves de «m3
V j? mtev-íade v*fe.
Duas ferramentas MySQLpopulares são o terminal MySQLe o phpMyAdmin. Ambas lhe
permitem executar comandos SQL para criar bancos de dados e tabelas, inserir dados,
selecionar dados, etc., mas o phpMyAdmin dá um passo além, por fornecer também uma
interface gráfica acessívelviaweb. Algumas empresas de web hosting incluem o phpMyAdmin
como parte do seu serviço MySQLpadrão,já o terminal MySQLpode ser usado para se acessar
a maioria das instalações do MySQL.
conectando~se ao My SQL
Você precisa ter um servidor de banco de dados MySQL instalado antes
de virar esta página.
E impossível ajudar Owen sem um deste! Caso vocêjá tenha um servidor de banco de
dados MySQL instalado e funcionando, continue lendo. Se não, consulte o Apêndice ii e
siga as instruções de instalação. Caso esteja usando um serviço de web hosting que ofereça
MySQL, peça ao administrador que instale o software. Várias informações são necessárias
para se acessar um servidor MySQL. Você voltará a precisar delas posteriormente, portanto,
agora é uma boa hora para entendermos quais são estas informações. Marque-as após ter
escrito ^informação correspondente.
Localização do meuservidorMySQL (endereço IP ounome do host): /,$■
_ / CâSo tenha medo
Nome de usuárioparao meubanco de dados: X2&&& este livro eaia
/ maos erradas,
[Tl Senhaparao meubanco de dados: — ^ ^ s i n t a - s e â
vontade para hão
Vote predisa veriíita r esdrever a senha,
•todas estas daixas.
Com essas informações em mãos, só o que você precisa fazer é confirmar se o servidor
está funcionando. Marque uma das caixas de verificação abaixo para confirmar que você
acessou com sucesso o seu servidor MySQL.
/
R7Í Consigo acessaro meuservidorMySQLcom sucesso, usando o terminal MySQL.
| i/| Consigo acessaromeu servidorMySQLcom sucesso, usando o phpMyAdmin.
| | Consigo acessaro meuservidorMySQLcom sucesso, usando........................................
prediso veriíidar Caso tenha endontrado alguma —
uma destas tres. .utra ferramenta «ue
ÍW ione, esdreva o nome dela a«ui
você está aqui ► 63
Crie um banco de dados e uma tabela MySQL
criando banco de dados e tabelas no mysql
Algumas instalações do MySQLjá incluem um banco de dados. Senão for o caso
da sua, você terá de criarseu próprio banco, usando o comando SQL CREATE
DATABASE no terminalMySQL. Mas, primeiro, abra o terminal em umajanela
de linha de comando - em geral, basta digitar mysql. Você saberá se entrou com
sucesso no terminal quando o prompt de comando mudar para mysql>.
Para criar o novo banco de dados para asabduções alienígenas, digite CREATE
DATABASE aliendatabase;destaforma:
0 servidor My£$L geralmente apresenta uma resposta,
para vote saber que o tomado -teve sutesso
Quando usar o -terminal,
vote deve tolotar um
ponto e vírgula apos
Antes de criar a tabela dentro do banco de dados, certifique-se de que o to*râ*dc-
nosso novo banco está selecionado. Digite o comando
USE aliendatabase;
1 File Edit Window Help PhoneHome
mysql> USE aliendatabase,
Database changed
O código SQL usado para se criar uma tabela é um pouco mais complexo, uma vez
que ele precisa dizer, exatamente, qual tipo de dados está sendo armazenado. Vamos
dar uma olhada no comando SQL antes de digitá-lo no terminal:
Ésfce t um tom3ndo
usado para que seja triada
uma nova tabela-
.
iens_abduction
first_name varchar(30),
last_name varchar.(30) ,
when_it_happened varchar(30),
how_long varchar(30),
how_many varchar(30),
alien_description varchar(100)
what_they_did varchar(100),
fang_spotted varchar (10)
other varchar(100),
email varchar(50)
Todos os tomândos SQL deitados no
terminai MySQL devem terminar tom
um ponto e vír^ula-
Todo o resto são míormaçoes
detalhadas sobre quais
tipos de dados podem ser
armazenados na tabela.
conectando-se ao My SQL
Para que a nova tabela sejacriada, digite o comando CREATE TABLE
no terminal MySQL (ou baixe o código do comando no site www.
altabooks.com .br). Após executar o comando com sucesso, aparecerá
uma tabela alien s abduction novinha em folha.
/ resposta tt$uery
0)CU do servidor
/V]y£$L iKe permita
saber <y*e a tabela
■foi driada sem
problemas.
Asua instalação do MySQLpoderá incluir a ferramenta phpMyAdmin,
a qual lhe permite acessar seus bancos de dados e tabelas graficamente.
E possível usar a interface do phpMyAdmin para criarbancos e
tabelas apenas com cliques do mouse ou então digitar comandos SQL
diretamente, da mesma forma como no terminal MySQL. Clicando na
aba SQL do phpMyAdmin, você acessa uma caixa de texto que age como
o terminal MySQL.
l/ode pode digitar
a^yi os mesmos
domandos ^ue no
terminal /Vjy£$L,
basta dlidar
em éo para
£*edutá-ios.
Apos digitar o
dodig© SQL,
dli^ue neste
botao para
ídriar a tabela.
Assim, aguia SQL do aplicativo phpMyAdmin oferece uma maneira
para que comandos SQL sejam emitidos da mesma forma como se o
terminal MySQL estivesse sendo usando.
você está aqui ► 65
introduzindo a instrução INSERT
Eu tenho um banco de
dados MySQL e uma
tabela; agora, como eu
insiro dados neles?
Você usa a instrução SQL i n s e r t para inserir
dados em uma tabela.
A linguagem SQL fornece todo o tipo de instruções
interessantes para se interagir com os bancos de dados. Uma
das mais usadas é INSERT, que realiza o trabalho de criar e
armazenar dados em uma tabela.
Dê uma olhada na instrução abaixo, para ver como INSERT
funciona. Tenha em mente que esta não é uma instrução SQL
verdadeira, e sim um modelo da instrução para lhe mostrar o
formato geral de INSERT.
palavras-
c-Kavcs
INSfcRT INTO
inidiam &
mstrvdâo-
0
sera
I
O
f
,
.
£ sta p arte é uma lista
dos notées das dolunâs
do seu bando de dados,
separados por vírgulas-
i
Seguem «»ais »omes
de dolunas, sendo
<ue «ao Ha vírgula
apos os ultúmos.
t a b le name {co lu n a , n o m e l
O
c o lu n a nom e2,
d a d o s2
© “ s
)
/Vfais uma ^sta parte e uma lista
palaw-as-ehave dos valores e dados a
do SQL, esta serem inseridos/separados
a«^ui indidando vírgulas- /
«ue viva© a
seguir os valores
para as dolwnâs-
As aspas simples estao
dorretas. U se-as sempre
«ue estiver inserindo texto,
mgsi^o gue seja a p f ^ s urn
ã d te r; Como */Vf
Segue» mais valores,
sendo ^ue não ha
vírgula apos o ul-timo-
Uma das coisas mais importantes a se
estes predisam vir «a
mesma ordeãT^ue os nomes das dolunas.
içao é que os valores, no segundo
conjunto de parênteses, precisam estar na mesma ordem que os nomes das colunas. É assim que
o comando INSERT sabe qual dado vai para qual coluna, ao inserir os dados.
conectando-se ao My SQL
A instrupão INSERT em apão
Veja a seguir como uma instrução INSERT pode
ser usada para que os dados das abduções na
recém-criada tabela aliens_abduction sejam
armazenados.
Os nomes das suas
tolvmas estão noprimeiro
tonjun-b àt parênteses,
divididos por v W â s .
A ordem é
importante!
Os valores a
serem inseridos
devem ser listados
exatamente na
m esm a ordem
que os nomes d as
colunas.
Bsbe e o nome da tabela na
qual os dádos sendo
inseridos, t HhO o nome do
bando de dados. — s
i ©
aliens abduction (first_name, last_name,
- 0 0 0
when_it happened, how_long, how many, alien_description,
0 © o ©
what they did, fang spotted, other, email)
O O © O O
(1Sally' , 1
Jones', '3 dias atrás ’, T1 dia', '
quatro',
O Q
'verde com seis tentáculos', 'Nós só conversamos e brincamos com cachorro' ,
0 0
’sim’, 'acho que posso ter visto seu cão.entre em contato'
f ©
/ 'sally0gregs-list.net')
Os dados para dada
doluna esb o no
segundo tonjunto de
faventcses, tambem
divididos por vírgulas.
Ao donírário do <ue
odorre no P^Psas^
•
t^ r u ^ ^ L n a o
-termina«* po5
ftt© c
vírgula r ar,ilo wato
dentro de dod»^0 » •
Tõdos estes
valores dontém
tex to , e não
números, portanto,
nos os dolodâmos
todos entre aspas
simples-
— ^Aponte scü lápis
£stes sa© os nomes
das tolunâs-
2 'v
A tabela aliens__abductíon encontra-se abaixo, mas ela
ainda não tem quaisquer dados. Escreva os dados da abdução
de Sally na tabela. Você pode escrever alguns dos dados fora
da tabela, se não houver espaço dentro das células, bastando
ligar com uma seta a informação à célula respectiva.
aliens abduction
* B ü ií r««s»ls5t Ifuiwmwfnlríí W S
XvA.. J - V^ ^ S
> ‘
J 1 .1 .,,
í—
's- -
1 s ■
■
>
r
você está aqui >
1 67
soluções e não existem perguntas idiotas
ponteseulápis
Solupão
verdes dom seis "fcentâdulos
A tabela aliens_abduction encontra-se abaixo,
mas ela ainda não tem quaisquer dados. Escreva
os dados da abdução de Sally na tabela. Você pode
escrever alguns dos dados fora da tabela, se não
houver espaço dentro das células, bastando ligar com
uma seta a informação à célula respectiva.
Mós sc donversamos
e brindamos dom ui» , , « H y à jx js -iis tx ít
daihom,.
kxer visto o seu dao.
£n-fcre em don-títo-
aliens iuction
last name
ÍÊÊÊÍfÊíÊIHaà' ÍÉ ^ I l l p
Sally Jones 3 dias a^râs 1dia 1 *v*ít'ro sim
Não sei se entendi bem a diferença entre
banco de dados e tabela. Ambos não fazem a mesma
coisa: armazenar dados?
Sim. As tabelas servem como uma forma de dividir
os dados de umbanco emgrupos relacionados, para
que você não acabetendo umúnico conjunto enorme de
dados. Émaisou menos como adiferença entre colocar
um monte de sapatos em uma mesma grande caixa e
colocar cada par dentro da sua própria caixa - a caixa
grande é obanco de dados, as caixas menores sãoas
tabelas. Assim, os dados são armazenados emtabelas,
e astabelas são armazenadas em bancos de dados.
? : O que exatamente é o terminal MySQL? Como
o encontro no meu computador:
Oterminal MySQL é uma técnica para se acessar
umbanco de dados MySQL através de uma interface
de linha de comando. Emmuitos casos, o terminal
não é um programa a parte, e sim uma conexão que
você estabelece usando a linha de comando de um
programa terminal “genérico”,como por exemplo o
aplicativo terminal do Mac OS X. 0 modo como você
acessa o terminal MySQLvaria bastante, dependendo
de qual sistema operacional você está usando e se
o servidor MySQLestá local ou remoto (localizado
emalgum outro lugar que não o seu computador). O
Apêndice II apresenta mais detalhes sobre como
acessar oterminal MySQL.
não existem
ferguntas Idiotas
? E quanto ao phpMyAdmin? Onde posso
encontrá-lo?
K : Aocontráriodoterminal MySQL, ophpMyAdminéuma
aplicaçãowebqueperm
iteacessoaumbancodedados
MySQL. Trata-se, naverdade, deumaaplicaçãoPH
P, motivo
peloquai vocêsempreaacessaapartirdeumservidor
web, emvezdeinstalá-lanoseuprópriocomputador. Muitas
empresasdewebhostingoferecemophpMyAdmincomo
partedoseuserviçoMySQLpadrão, portantoelepoderájá
estarinstaladoparavocê. Senãoestiver, baixeeinstaleo
programa,vocêmesmo. Estádisponível, gratuitamente, em
www.phpmyadmin.net.Lembre-seapenasdequeeleprecisa
ser instaladoemumservidorwebeconfiguradoparater
acessoaosseusbancosMySQL, damesmaformacomo
qualqueroutraaplicaçãoPHPeMySQL.
? Eu tenho tanto o terminal MySQL quanto o
phpMyAdmin disponíveis. Qual deles eu devo usar
para acessar meu banco de dados?
í^ * . Essaéumaquestãopessoal. Avantagemdo
phpMyAdminéquevocêpodeexplorarseusbancos
dedadosetabelasvisualmente, semterdedigitar
comandosSQL Issopodeser bastanteútil, casovocê
tenha sefamiliarizadocomoSQLenãoqueiradigitar
comandosmanualmenteparacadacoisinhaqueprecisar
fazer. Entretanto, por agora, éumaboaideiaquevocê
seconcentreemrealmenteentender omodode interagir
comosseusdados usandocomandos SQL, e nessecaso,
qualquerumadasferramentasfuncionaacontento.
conectando-se ao My SQL
T fe S T O R fv e
Armazene um caso de abdução alienígena no seu banco de dados
com uma instrução SQL INSERT
Usando uma ferramenta MySQL, como o terminal MySQL ou a guia SQL do
phpMyAdmin, digite uma instrução INSERT para armazenar dados de uma abdução.
Como exemplo, eis aqui a instrução INSERT para a abdução de SallyJones:
INSERT INTO aliens_abduction (first_name, last_name,
when_it_Jnappened, how_long, how_many, alien__description,
what__they_did, fang_spotted, otherr email)
VALUES ('Sally', 'Jones', '3 dias atrás', '1 dia', 'quatro',
’
verde com seis tentáculos', 'Nós só conversamos e brincamos com seu cachorro',
'sim', 'Acho que posso ter visto o seu cão. Entre em contato.',
'sally@gregs-list.net1}
£*edu-fca»r a instrução l^í£BRT
ho terminai /VJyS^L résulta
c
r»
» uma «ova imha de dados a
ser adiebnada â -tabela a!ie*_
desdírip-tioft.
Ainstrução INSERTparece ter sido executada com sucesso. Como
você acha que poderíamos confirmar se os dados foram inseridos?
Escreva aqui.
você está aqui ► 69
introduzindo a instrução SELECT
Use SELECT para obter dados da tabela
Inserir dados em uma tabela é uma tarefa relativamente fácil, mas é compreensível sentir
certa apreensão caso você não tenha confirmado se os dados realmente foram parar na
tabela. E mais ou menos como depositar dinheiro na sua conta de poupança, mas nunca
poder visualizar o saldo. A instrução SELECT é a forma de “ver o saldo”de uma tabela
em um banco de dados. Ou, dizendo propriamente, SELECT permite que você solicite os
dados das colunas contidos em uma tabela.
/^ós SELECT, esdreva w«a
lista das doiunds dujos dados
«y*er redeber j
c o lu n a s U p || nome_ _
A >arte FR0M da 'wsbruça© é o
mdiea a SELECT de «w
ai tabela
<^uere**»os sclcdioftâv" dados*
As colunas fornecidas a uma instrução SELECT precisam ser
separadas por vírgulas. Independente de quantas colunas
houver em uma tabela, somente os dados dos nomes das colunas
especificadas em SELECT são retomados. Esta instrução SELECT
extrai todos os nomes e sobrenomes dos abduzidos contidos na
tabela aliens abduetion:
sempre e -Peito im
ç ^iadao a «ma tabela espedííida, e «ao
L ao ba^do de dados, de -ror**a geral.
da_teJbela ,
A instrução
SE LE C T
J o S q L o Lrtém
coluneis de dados
d e u m a ta b e la
Son>e»vte os dados
referentes a estas duas
dotadas sao retornados ^>or
esta instv^çao SELECT.
h mstrudao SE LE C T so
obíem dados da tabela
aliens_abdudtioh.
SELECT first name/ last name FROM aliens abduction
Para verificar um INSERT, você precisa de uma forma para
visualizar rapidamente, todos os dados da tabela e não apenas
algumas colunas. A instrução SELECT oferece um atalho voltado
exatamente para isso:
0 asterisdo, ou “estrela*! <
*iz- è
SE LE C T fa ra obtev todos os dados de
todas as doW^as da tabela-
N
SELECT * FROM aliens abduetion
Nao t nedessirio
csfedi-fidâr uma lista
de dolunas, porque ^
signifida “obtenha
todas elas^’
conectando-se ao My SQL
T fe S T O R tv e
Certifique-se de que a instrução INSERT funcionou, usando
SELECT para obter dados da tabela.
Execute uma consulta SELECT, usando uma ferramenta MySQL, para visualizar
todo o conteúdo da tabela alien s abduction. Certifique-se de que a linha de
dados que acabou de inserir está aparecendo nos resultados.
SELECT * FROM aliens abduction
sâoasdoiuhas.
A fiowJta S B iS C T revela
íhiea liftKa de dados
srnxsz£inêdos nè -tabela-
A
Quantas linhas de dados há na sua tabela?....... .
você está aqui ► 71
automatizando comandos SQL com PHP
É verdade, cada inserção em um banco de dados
MySQL requer uma instrução INSERT.
E é neste ponto que a comunicação com um banco de dados MySQL
realizada simplesmente através de comandos SQL fica tediosa. É claro
que há muitos benefícios ao se armazenar os dados de Owen em um
banco, em vez de em emails na sua Caixa de Entrada, mas gerenciar os
dados manualmente, emitindo-se instruções SQL em uma ferramenta
MySQL, não é uma solução razoável.
Como você acha que o problema de
inserção de dados de Owen pode ser
resolvido?
conectando-se ao My SQL
Peixe oPHPlidar com as coisas tediosas do SQL
Asolução para o problema de Owen não é evitar o comando SQL,
mas sim automatizar o SQL com a ajuda do PHP. O PHP possibilita a
emissão de instruções SQL em um código de script que será executado
no servidor, de forma que você nem sequer precisa usar uma
ferramenta MySQL. Isso significa que o formulário HTML de Owen
pode chamar um script PHP para lidar com a inserção dos dados no
banco, sempre que novos dados forem submetidos - nada de emails,
nem ferramentas SQL, nem confusões!
0 -formulário HTML $era
umemdil *UCOwCnrídcbe t ]
^redisa emíão âdidionâV)
mânuaWen-te, as mí<w»aç3es
ao bando de dados.
Ove* dria uma insbrudao
SQ L INSERT, a «ual'
insere os dados do email
«o bando.
Sem PHP, é preciso executar uma
instrução SQL INSERT manual para
arm azenar cada relatório de abdução
no banco de dados.
Com PHP, um script PHP
autom aticam ente executa INSERT
quando o formulário é submetido.
<rphp ----
'aiíensrool',
(flrst-naE6' ia- ••.
üescript^ ' ”■
%it :r4" ',x^ ■
•
^ - s t s m x s r , r »
ô -formulário
HTML dKama-
um sdripfc PHP
e pede a ele
<ue adidione
os dados do
■formulário ao
bando.
Sresult = rnysqli^que2.
y(?abc< squsry)
cr d-ef2rror querying dstabase.’)
0 sdript PHP dria uma instruÇao
INSERT <ue insere os dados do
-formulário n© bando -- nao e yrediso
nenhuma intervendao de OvcrJ
reporLphp
v o c ê está aqui ► 7 3
como o aplicativo do Owen pode usar php e mysqi
0 PHPpermite usar os dados do formulário
web de Owen
O PHP melhora o form ulário web de Owen ao permitir que um script envie os dados
diretamente para um banco, em vez de enviá-los para o endereço de email de Owen, que
teria então de inseri-los manualmente. Vamos dar uma olhada com mais detalhes no modo
exato como a aplicação funciona, agora que o PHP está em ação.
O
Sallypreenche o formulário e clica
no botão “Relatar Abdução”,para
submetê-lo. As informações são
enviadas para o script report .php
no servidor web.
Sally, ainda
'TtUrien>enhc
âbdbzjdd po<r
olicns
oVárias pessoas continuam a
submeter o formulário.
0 íovmttlávi©dô
s iv ift refcrt-fh? do
scvvido'*" web, qwe t
subwcttdo yo* <
*musuâv-io.
conectando-se ao My SQL
e O script re p o rt.php de Owen conecta-se a um banco de
dados MySQL e insere as informações de cada formulário
submetido usando instruções SQL INSERT.
0 sdrtpt report-php
domunida*-SC dom o servidor
M ySQL para ihSíiriV' dados
«a tabela ati«ns_abdudtion
do bando de dados.
report.php
$ tabela al'»ens_abdudtion
èrmèxjtnã os relatos na íorm a
de ímhas íre^ stro s) de dâdos.
Owen precisa não somente de um script para colocar os dados no
banco, como também de outro script para procurar e visualizar os
dados. Na verdade, isso poderia servir como a página principal do seu
site. O script index.php conecta-se ao banco, obtém dados sobre as
abduções e os mostra a Owen.
Um servidor de
bando de dados
e afenas um
proyâm â sendo
exedutado em uma
máquina servidora*
geralmente junto
ao servidor web-
index.php
0 sdript indexpbp obtem dados da tabela
à!iens_abdudtioní fa rá que eles possam ser
-formatados e mostrados a Owen-
^ tabeia aliens_abdudtíon
serve domo ío n te de dados
para o sdript index.php.
e
Owen podem
escolher acessar
os dados de
muitas novas
formas, o que lhe
permite focar-se
em encontrar seu
cão Fang.
você está aqui ► 75
fazendo uma conexão mysq!
Conecte-se ao seu banco de dados a partir do PHP
Antes que um script PHP possa inserir ou obter dados de um
banco MySQL, ele precisa se conectar a esse banco. Conectar-se
a um banco MySQL a partir do PHP é semelhante, de muitas
maneiras, a acessar o banco através de uma ferramenta MySQL e
as mesmas informações são requeridas. Lembra-se das três caixas
de verificação que você preencheu anteriormente, neste capítulo?
Aqui vão elas novamente,junto a mais uma, que indica nome do
banco de dados —escreva todas as informações, mais uma vez.
Seu provedor de hospedagem de
sites, ou seu webmaster, pode
lhe fornecer esta informação.
Ov. entao, se o seu servidor
web e o seu servidor de bando
de dados estiverem
rodando na mesma maquina, vode
pode usar a palavra "lodalhost".
^ Localização do meu servidor MySQL (endereço IP ou nome do host): ^
O Nome de usuário para o meu banco de dados:.....................
^ Senha para o meu banco de dados:
Nome do meu banco de dados:......
As informações de localização do host, nome do usuário, senha e
nome do banco de dados são todas requeridas para se estabelecei;
uma conexão ao banco MySQL a partir de um script PHP. Uma
vez feita a conexão, o script pode executar comandos SQL da
mesma forma como se você os estivesse digitando manualmente'
em uma ferramenta MySQL.
suas próprias
informa^oes serao
diferentes destas.
0 nome do bando
de dados «y*e vode
driou anteriorm ente e
aliendatabase- Se, por al^um
m<rtivo, vode -tiver atribuído
alburn outro nome ao seu
bando, ou iiver optado por
usar um bando j 3 e*isten-te,
use o nome apropriado-
0 nome do bando de
dados, informação
nedessária para
^ue o sdript se
domuni^ue dom ele, é
aliendatabase-
report,php
$ual<^uer sdrip-t
P H P <^ue a rm a z e n e
obtenha dados
de um bando
/WyS$L- predisa,
primeiramente,
estabeleder uma
dofiC?^o dom o
bando, usándo as
Quatro informâ^oes
mendionadás.
iduction
B stes sao o
bando de dados
e a tabela ^ue
ddabamos de driar.
0 nome da tabela^e a!iens__
abdudtion, e ele nao en-trâ em
dampo a té <ue vode domede a
em itir domandos £$L~
conectando-se ao My SQL
Insira dados com um script PHP
Executar uma consulta MySQL a partir de código PHP requer que você, primeiramente
estabeleça uma conexão com o banco de dados. Em seguida, você constrói a instrução
(query) na forma de uma string PHP. A instrução (query) não é executada até que repasse a
string para o servidor do banco de dados. Finalmente, uma vez terminado o acesso ao banco
de dados, você encerra a conexão. Todas essas tarefas são executadas através de código em
um script PHP. Eis um exemplo que insere uma nova linha de dados de abduções:
Coned-ta-se bando de
dados MySQl—
£siís deve» ser os SEUS
valores, e hão os de Owen-
<?php
$dbc = niysqli_connsct
or die(’Error connecting to MySQL server.' Vote talvez- fossa i*sar lodalhost para a
■ lodaiizadão do seu banio, em vex. de w* «owe
de dowmio.
$q’
aery = "INSERT INTO aliens_abductian t-first^nãme', -last_name, when_it_happened, how_lang, "
"how many, alien description, what_they__did, fang_spotted, other, email) " .
"VALUES (’Sally’, 'Jones', '3 dias atrás', '1 dia', 'quatro', 'verde com seis tentáculos', ”
’
"Mós só conversamos e brincamos com um cachorro', 'sim', 'Acho que posso ter visto seu cão. entre em contatoj
” ■
sally@gregs-list.net’) K - CohstruS 3 in i t io (<^ery)
IMSBRT do**o uma strina em
dodifto pfj’P.
$result = mysqli_query($dbc, $query) / ;
____ 3
_ ^ TenHa ww-to dwdado
or querying database.■
, , j ^ ^ ^ ^ ^ £
bando de dados AlySQL.
mysqli_clcse ($dbc) ;
duplas a^w» c tawbe»
do» os espa$<* antes e
depois das aspas.
fcstas lunçoes venerem «ue o
sevt servidor web tenba ô PH*
versão * .l ou adimâ-
Q > E R > 0
O que você acha que cada uma destas funções
no script? j /
PHP está fazendo
iscript? * /
mysqli_connect (
) — ^ o o 17 &
W ^ --_
_
mysqli_query(
) ■
^
'
v
s
AAa X !2Ua
mysqli_close () f
j í
)
’•
'* <
?
v
você esíá ago/ ► 77
três funções php para conexão mysql Ur* donjwfc©atvfcí^o àt
-Ç
w
k
Ç
o
c
s Pi+P <y*e m-tera^m
dom o My$$L dowc^rá
UsefwipõesPHPparafaiarcowobawodedados
(ttafrimorad<A t hoe e» dia
^re-Çeve—
sc wsav as -Vw^ocs
Existem três funções PHP principais, usadas para que se realize a
comunicação com bancos de dados MySQL: m ysqli_connect (),
m ysqli_query {) e m ysqli_close (). Caso tenha percebido um
padrão aí, não é coincidência - todas as funções modernas do PHP
que interagem com o MySQL começam com m ysqli_
mysqli_connect (
)
Conecta-se a um banco de
dados MySQL usando as
quatro informações que você
já viu anteriormente.
mysqli_query{
)
Emite uma instrução (query) a
um banco de dados MySQL, o
que, frequentemente, envolve
armazenar ou obter dadosde
uma
mysqli__close (
)
Encerra uma conexão
a um banco de dados
MySQL.
O uso destas três funções geralmente envolve uma sequência previsível de etapas.
Conecte-se a um banco de dados com a função mysqli_connect ().
Forneça a localização, o nome do usuário e a senha, para obter permissão para
interagir com o servidor do banco de dados MySQL. Especifique também o nome do
banco, uma vez que esta é uma conexão a um banco específico.
O
Connectado!
Crie uma query SQL e a arm azene como uma string em uma
variável PHP.
Para se comunicar com o servidor do banco de dados, você tem de usar comandos
SQL. Por exemplo, é necessário uma instrução INSERT para que dados sejam
adicionados à tabela aliens_abduction. Não há nada de especial a ser citado sobre
o nome da variável que escolhermos, e um nome simples como $query funciona
perfeitamente bem.
Eu tenho uma
grande instrução INSERT
para enviar e ela está armazenada
em uma variável PHP.
conectando-se ao My SQL
Use a variável $query com a função m ysqli_query () para falar com o servidor
do banco MySQL e adicionar dados à tabela aliens._abduction. Você tem que
informar à m ysqli_query () tanto o nome da conexão que criou no Passo 1quanto
o nome da variável que armazena a sua consulta, do Passo 2.
Emita a instrução (query) com a função mysqli_query().
Ei, adicione
estes dados com
INSERT naquela
tabela que você tem
armazenada aí.
e*edu£a a sua «uery,
*ue e insiru^ôo IWSfcRT para ~
adidionar dados a -tabela- i
mysqli_query(
)
0 Encerre a conexão ao banco com a função mysql±_close ()
.
Finalmente, m ysqli_close {) diz ao servidor do banco MySQL que vocêjá terminou a
sua comunicação com ele.
mysqli_close (
)
Este é o von»e da suü
variável da do«e*ao.
J .
<?php
Sdbc - l l l l i i l l ü l l 'data.aliensabductedme.com
or die ('Error connecting to MySQL server. 1)
Conexão fechada.
Sc aly> der errado, isto ^ 't u„ a ^ |^s e r t
«vis u»â mçnssjcm < f» i ^ êo ^ ^
vode e para xudo.
íensrooi'
o = "INSERT INTO a!iens_abduction (first_name, last_name, when_it_happened, how_long,
”how_many, alien_description, what_they_did, fang_spotted, other, email) ” .
"VALUES ('Sally1, ’Jones', '3 days ago', '1 day’, ’four’, ’green with six tentacles', "
” 'We just talked and played with a dog', 'yes', 'I may have seen your dog. Contact me.’,
” 'sally@gregs-list.net')";
© ^ --
Sresult =llilPllii¥S{$dbc' $query)
or die('Error querying database.');
£ a^ui, hós ^edha
adonexao-
JU-l f -i- Jliuy V^ 1U
ivs^li <ueryO é a -fundão usada pel© PttP para
sc do«.unidar tom o serx/idor MyS6?L 0 dodi$o
armazenado «a variável ?<uery é SQL, e «ao PHP-
© ü i I I § Í ($dbc) ?
Vamos dar uma olhada com mais atenção em cada uma dessas funções
PHP para bancos de dados, começando por m ysqli connect ()...
você está aqui ► 79
usando mysq!i__connect()
Conecte-secomwysqli cowiectí)
Para o nosso script PHP poder criar uma conexão © Monte a string da query,
com o banco de dados usando a função m ysqli_ © Execute a query com mysqli_queryO.
connect {), você precisará de algumas informações, Q Feche a conexão com mysqli_closeO-
com as quaisjá está começando a se familiarizar.
Sim, são as mesmas informações que usou
anteriormente, quando trabalhou com o terminal
MySQL, mais o nome do banco de dados.
Seu nome de usuário e senha
Você precisará ter seu próprio nome de usuário e senha para o seu próprio
CtUGWl? servidor do banco de dados. Essas informações ou serão definidas por você
ou lhe serão entregues pela sua empresa de hospedagem de sites, quando
o MySQL for instalado. Se você configurar seu próprio MySQL, siga as
instruções para criar um nome e uma senha seguros.
0 quê?
O nome do banco de dados
No nosso exemplo, demos ao banco o nome aliendatabase. O seu terá
qualquer nome que você decida lhe dar, ou então terá o nome dado pela sua
empresa de hospedagem de sites, caso ela tenha criado o banco para você.
A localização do banco (um nome de domínio, um endereço
IP ou localhost)
Onde? No nosso exemplo, estamos usando a localização do banco (fictício) de
Owen. Você precisa usar a localização do seu próprio servidor MySQL.
Frequentemente, você usará localhost, caso o servidor do banco esteja na
mesma máquina que o seu servidorweb. A sua empresa de web hosting poderá
informar-lhe a respeito disso. Alocalização poderá ser também um endereço IP
ou um nome de domínio, como por exemplo, seu servi dor.seuisp.com.
A localização, o nome do usuário, a senha e o nome do banco MySQL
na função m ysqli_connect {) precisam estar, todos, entre aspas.
variarei para realizar A íunçã? H l/
f ou-hras è&oes ho bando de dados. A T
^ connectOJida a
$dbc = mysqli_connect(
'data .aliensabduetedme .c o m '
, IPcauzaçaP, P
’owen' ' ^odaiizada© Jp a S en ta e
’aliensrool ’, do bando de , j
i 1aliendatabase1); dados. £ TlPIUc uP bailCP dô'
^ áo kâ*i0 dc dados' dados com o sftings,
O resultado ao se chamar a função, é uma conexão ao pçtfcaníp, V pcetem
banco de dados e uma variável PHP que você pode usar j i
para interagir com o banco. Avariável recebeu o nome CQlQCat ^SSclS
$dbc no exemplo, mas você pode atribuir qualquer nome i n £ ° r i l l ô T r f í C aSPaS-
que quiser. í
Kowe do
usuário-
conectando-se ao My SQL
r %Apowtescü lápis----------------------------------------------
Eis alguns exemplos de strings PHP para conexão a
bancos de dados. Observe cada uma delas e escreva
se a string vai funcionar ou não, e como consertá-la,
neste caso. Adicionalmente, circule qualquer parte
de código que você considere problemática.
$dbc = mysqli_connect (
'data .aliensabductedme .com', 'owen 1, '
aliertsrool1,
’alíendatabase');
$dhí3^^vcYsqlj^s&i^nect. ('data.aliensabductedme.com’, 'owen', '
aliensrool'
"aliendatabase'*^
1
1
1 ■ M H-i,,..!, ..
j
..Q
:‘.. .v.Y.V1
.C./.h ................................................................................................
l^Çfangisgone^ mysqli_connect(1
data.
aliensabductedme.
com’, '
owen'
, '
aliensrool'
,
'alíendatabase1);
$dbc = mysqli connect (^sagalhogte-^ ’owen', 'aliensrool',
'aliendatabase');
....M ........................................................................................................
$dbc = mysqli_connect{'data.aliensabductedme.com1, 'owen
’aliendatabase');
0 ..... ■..........
™ .......................................................................................................................................
' O
$dbc.^jii^gjrr^eqMTiyLTt^a^a'.<^ieIIoabduefc^dme.
com', 1
owen'
, 1
aliensrool'
);
(roysqli_select_db ($dbc, '
aliendatabase
você está aqui ► 81
solução do aponte
ponteseulápis
Solupão
Eis alguns exemplos de strings PHP para conexão a
bancos de dados. Observe cada uma delas e escreva
se a string vai funcionar ou não, e como consertá-la
neste caso. Adicionalmente, circule qualquer parte
de código que você considere problemática.
$dbc = mysqli_connect{'data.
aliensabductedme.com', '
owen'
, '
aliensrool'
,
1aliendatabase1)
;
Esta. string.de done*ao íundiona. sem,problemas-.
f
E pvédíso úm põnt© c ’vírcjulã'a«^üi...............jtfeste livrõj êstãmos úsándó' ãspás'simptes pàrà' sttfngs'
para -terminar a instrudao PHP. ptfp e reservando as aspas duplas para donsultas SQL.
$dbc = mysqli_conn,ect/'
data.aliensabductedme.com', 'owen', 'aliensrool',
"aliendatabasenj^ J
|sto nã© íuntiona, .porque.está -falando um ponto e yírgula; /s aspas duplas íu^içmarn do
mesmoje ito <ue as simples.
Kao e um nome muito desdritivo para
uma done*ao a bando de dados.
^fangisgone^ mysqli_connect('data.
aliensabductedme.
com'
, '
owen'
, '
aliensrool'
,
Aliendatabase'
);
jsto £undiona, çmbora ^angisgone” (''íangestádesaparedido”) não seja um bom nome para uma
done%ao a bando de dados.
esta nítido assumindo <^ue o servidor do bando de
dados se lodaliza no mesmo dompvitador <^ue o servidor web.
$dbc = mysqli_connect (
^
^calhostT^^owen', 'aliensrool', 'aliendatabase');
Jstp. ^n d io n a.desde. «ue o. servidor web e. o sçryidor, do bando estejam na mesma máquina-..............
Uma senha vazia para o bando
de dados nao e uma boa ideia-'
$dbc = mysqli_connect{'data.
aliensabductedme.
com'
, 1
owen'
, '
aliendatabase'
)
;
|st© so -fundionara se vode definir uma senha em brando para o bando de dados. Nâo e uma
boa ideia, mas -fundiona/ Vode sempv-e deve t e r uma senha para dada bando de dados.
D ei*ar de -fora o quarto argumento
requer <^ue dhame mys^|i_seledt_dbO
para seledionar o bando de dados. 
$dbc = mysqli_connect('data.aliensabductedme.com', 'owen', ’aliensrool'
)
mysqli_select_db($dbc, 'aliendatabase');
Me desdulpe, mas isto ç uma Ipe^adinha”.. Em .m ys^li^d^nedtP/. o quarto item, o nome do, bando
de dados, e opdional Vode pode dei*á—
lo d e ío r a da -fundão e usar m^s^li^seledt^dbO para
espedi-Pidar o nome do bando. Assim, este dádigo t o mesmo ^ue se vode tivesse passado todos os
quatro argumentos párâ mys^li__donnedtO.
conectando-se ao My SQL
Parece que poderia ser fácil
estragar uma das partes da informação
usada para conectar-se ao banco de dados.
Porém, como eu poderei ter certeza se a
conexão funcionou?
//
É aqui que,ar£cfftcão PHP d ie () é útil.
Afunção PHPdieQ^ífnaliza o script PHP e fornece conhecimento
sobre algum còcíigo que tenha falhado. Embora não revele
precisamente o que houve de errado, die () nos informa que algo
aconteceu e precisa ser consertado. Se houver algo de errado com
uma das quatro variáveis para conexão de mysqli__connect (),
ou se o servidor do banco não puder ser localizado, a função die ()
impede que o restante do script PHP seja executado e mostra a
mensagem de erro entre parênteses.
A -função dieO t soiidítada,
daso a Conexão nao tenHa sido
estabeíedida-
Se uittâ das nc&sds ^v^rbrc strings nâ íunÇ3©
wys^ii_d©nnedt não esiiver dorreta, redeberewos
^ u m â resposta sobre isso-
$dbc V mysqli_connect('data.aliensabductedme.com', 'owen1,
. 1aliensrool1, ’aliendatabase')
or die(’
Erro ao conectar o banco de dados.');
Esta mensage» t enviada para a
pagina web, das© a done*a© -PalHe.
Nâo t prediso dolodar ponto
e vírgula a<ui, u*»a vez. <^*e
“or dieí -)Mtorresponde a,
tednida**ente, dontinuaçao de
uma mesnta insfaruçao.
você está aqui ► 83
construindo consultas no php
Sim! Uma vez feita a conexão ao banco com
mysqii_connect(), você pode em itir consultas
SQL diretam ente do PHP.
Praticamente, tudo que pode fazer em um terminal MySQL
pode também ser feito em código PHP, com a conexão ao
banco que acabou de ser estabelecido. E essa conexão que
disponibiliza um canal de comunicação entre um script
PHP e um banco de dados MySQL. Por exemplo, agora que
Owen tem uma conexão ao seu banco, ele pode começar a
inserir dados na tabela alien s abduction com a função
m ysqli_query () e algum código de consulta SQL.
L
-C
ftibve—
scjnosso
objetivo c automatizar
esta ^uery (HSBRj
u
s
ã
n
c
l
otcÁop P
f
f
P
.
A «uery SQL é passada
para swys^ii^ueryO domo
u m a s tr m $ P H P •
Afunção m ysqli_query () precisa ter uma
1 query SQL armazenada em uma string PHP
 ($query) para executar a inserção dos dados,
 abduções alienígenas. ^ _______
conectando-se ao My SQL
Construaa queryINSERT no PHP
As query SQL, em PHP, são representadas como
strings e costuma-se armazenar a query em uma
string antes de passá-la para a função m ysqli_
query (). Uma vez que as consultas SQL podem
ser razoavelmente grandes, frequentemente é
necessário construí-las a partir de strings menores,
que se estendem por várias linhas de código. A query
INSERT de Owen é um bom exemplo disso:
Correct««yg com wysqli_jconnaetQ.
Monte a string da query.
o
o
D
Execute a consulta com mysqii_queryO.
Feche a conexão com mysqlLcloseO-
^ —£sta e umd varilvel string do PHP,^ue agora
armazjend a ^uevy INSERT.
= "INSERT INTO aliens abduction (first name, last name,
0 ponto iihai diz. a© PHP para
jw ta r esta siring do«* a >ue vier
nâ linHa seguinte- ^
"when_it_happened, how__long, how_many, alien_description, " .
"what_they_did, fang_spotted, other, email) " .
"VALUES {'Sally1, 'Jones', '3 dias atrás'
, ’1 dia', 'quatro', " .
’
"verde com seis tentáculos', 'Nós só conversamos e brincamos com um cachorro', " .
"'sim1
, 'Acho que posso ter visto seu cão. Entre em contato.',
"1sally@gregs-list.
net'
)"
|
|
Uma vez. <
Y
*e tudo
isto é dódigo PHP, e
prediso -Tinâlizi—
io tom
ponto e vírgula.
^ string de donsulta se divide e» várias linhas, para
to m a -la »«ais legível —os pontos íinâis instvu«»* oPHP
3 transíorw iar tu d o isto em u»a unida string-
Com a query insert armazenada em uma string, a mesma estará
pronta para ser transferida via função m ysqli query ().
existem
1 * Por que um INSERT feito em
um banco é chamado de query?
0 termo “query” não significa
que nós estamos pedindo alguma
coisa ao banco de dados?
Sim, “query” significa que
algo está sendo requisitando...
você está pedindo ao banco que
faça alguma coisa. Nas aplicações
de bancos de dados MySQL,
o termo “query” é genérico,
referindo-se a qualquer comando
SQL que seja executado, incluindo
tanto o armazenamento quanío a
obtenção de dados.
Fer^untas idiotas
7 * Por que a instrução INSERT
não é criada como uma única
string gigante?
Tenha em mente que a
instrução INSERT é armazenada
como uma única string gigante,
mesmo que tenha sido criada a
partir de várias strings menores,j
ideal seria que a instrução INSEl
fosse programada como uma únrç
string. Mas, assim como várias
instruções SQL, INSERT é bastar
longa e não cabe em uma linha
“normal” de código. Assim, ela é
mais fácil de ler se programada
como strings menores, conectadas
por pontos finais.
^ * É realmente necessário listar
os nomes das colunas ao se fazer
um INSERT?^
pode omitir os
nomes das colunas na instrução
INSERT. Nesse caso, terá de
fornecer valores para todas as
colunas da tabela, na mesma ordeiji
em que aparecem na estrutura
da tabela. Tendo isso em mente
em geral é mais seguro e mais
conveniente especificar os nomes
das colunas.
você está aqui > 85
a função mysqli_queryO
Consulteobancodedados MySQL
comPHP
A função m ysqli_query () precisa de duas
informações para executar uma query: uma
conexão ao banco e uma string de query SQL.
-Conecte«ve com mysqlr^connegtQ.
-Monte Q-sjyÍRg-éa-^Bcry. —
Execute a cõrvsulta"com mysqIi__query()T^
^ Feche a conexão com mysqli_closeO.
!>ííh
'S ' conexâo__ao_jDanco, consulta)
Esiâ e uma do*exao <uejá íoi esèabeledida,^
aíraves da -fundão m
ys*^!i_donnctfcí)•
A conexão requerida pela função m ysqli_query () foi
retomada para você por m y sq li_ co n n ect (). Caso isso
tudo esteja um pouco difícil de visualizar, eis o código que
estabeleceu a conexão:
Esta i a <uery
SQL será
realizada- aquela
arw>32XPiâm
oS C
m
uma sirwty
Lembre-se, estas
variáveis serão
di-fereivies «o seu
propv-i© bando de dados.
í
j
|
j
^
G
i
j= mysqli_connect (1
data.aliensabductedme .
con
or die(r
Erro ao conectar ao servidor mysql.T)
;
A tont^èo dobô«êo dc
dados ja íoi armazenada, na
variável fdbd-
Assim, você tem uma conexão ao banco ($dbc) e uma query
SQL ($query). Só o que falta é repassã-los para a função
m y sq li_ q u e ry ().
ix '" ' A <Htery
P ÍffiB S l|Í($ d b c f $query) ;
'owen', 'aliensrool', 'aliendatabase')
or die('Error querying database.')
j w
tenf^èo 3o
0 resul-fcado da <^*ery
batóo de dados.
Uma ^lieiy SQL
corresponde a unia
re q u is iç ã o e s c rita
e fll C PcR go SQL,
<jue é enVIada a
<
?
setVidpr d9 banco
d e d a d o s.
Este código mostra que ou solicitar a função m ysqli_query {) não
corresponde a, apenas, uma comunicação de uma só via. A função responde a
você, retomando uma informação que é armazenada na variável $ re s u lt. Mas
nenhum dado é realmente retornado a partir da consulta INSERT - a variável
Sresult apenas registra a informação referente ao sucesso - ou não - da query
emitida por mysqli.
A íunçãp in>;sc
[l?_c
jiieryOrequerumacpnexãQ
apbancode dadpse umasttlngde <juery para
e x e c u t a r u m a c o n s u lta . S Q L .
conectando-se ao My SQL
e -
-Mcnta q string da query.
Encerre sua conexão com
mysqlLcloseO
Uma vez que só estamos interessados em executar a
instrução INSERT simples, a interação com o banco
está terminada, pelo menos no que concerne ao
nosso script. E, ao terminar de usar uma conexão
ao banco, feche-a. As conexões se fecham sozinhas
quando o usuário fecha a página, porém, assim como
fechar uma porta no mundo real, é um bom hábito
tomar a iniciativa de fechar as conexões quando tiver
terminado de usá-las. A função PHP m ysqli_
d o s e () realiza essa tarefa.
conexâo_ao_banco) ;
vode i« U a a friável
às done%ão, utilizada para
interagir tom obârtdo de
d a d e s .
No caso do script de Owen, precisamos executar
a m y sq li_ clo se () e informar qual é a conexão
a ser fechada, informação essa que se encontra
armazenada na variável $dbc. Esta variável ârma«r,a uma wíev&dia
^ a -foi firiada por »ys«sli_
|f($dbc) ; totonttiO !â atrás, guando a donexão
+oi aberta pela primeira vez.
-gxeeute a consulta eetyi my^U_qwpyQ.
Feche a conexão com mysqli_closeQ^
É u m U ?m t ó b r t9
Çeciat a C
0Tiexâ° a
um banco de dadps
M y S Q jL a p o s
terminar de usa-lp.
Mas se as conexões aos bancos
se fecham automaticamente, por que
se dar ao trabalho de fechá-las de
forma manuaJ?
Os servidores de bancos de dados só dispõem
de um certo número de conexões disponíveis
por vez, portanto, elas precisam ser preservadas
tanto quanto for possível.
E quando você fecha uma conexão, isso libera o recurso
para que uma nova conexão possa ser criada. Se estiver em
um banco de dados compartilhado, apenas cinco conexões
poderão ser alocadas para você, por exemplo. E, à medida que
você for criando novas aplicações que usem bancos de dados,
tenha certeza que quererá manter o maior estoque possível de
conexões disponíveis.
você bstá aqui ► 87
não existem perguntas idiotas e pontos de bala
nãp existem
P e r g u n t a s i d i o t a s
1 - Você não poderia, simplesmente, colocar todo
o código SQL diretamente na função mysqli_
query (),em vez de na variável $query?
P^_: Seria possível, mas ficaria muito bagunçado. É
mais fácil gerenciar o seu código quando você armazena
suas queries em variáveis, e depois usa essas variáveis
na função mysqli_query (
)
.
? : 0 código que referencia a consulta INSERT
deveria estar fazendo algo com o resultado?
Talvez sim. Até aqui, estivemos usando die()
para finalizar um script e enviar uma mensagem ao
navegador caso algo de errado acontecesse. Chegará
um momento em que você poderá querer fornecer
mais informações ao usuário quando a query não tiver
sucesso, nesse caso, você pode usar o resultado da
query para determinar o sucesso desta.
PONTOS DE BALA
As conexões a bancos de dados precisam de uma
localização, um nome de usuário, uma senha e um nome
do banco.
Afunção mysqli_connect () cria uma conexão entre
o seu script PHP e o servidor do banco de dados MySQL.
Afunção die () finaliza o script e retoma uma mensagem
caso a sua conexão falhe.
Para se executar uma query SQL a partir de código PHP,
você constrói a query em uma string e depois a executa
com uma chamada a mysqli_query {
)
.
Chame a função mysqli_close {) para fechar uma
conexão ao banco MySQL, a partir do PHP, quando tiver
terminado de usá-la.
RQ
conectando-se ao My SQL
0 P e jst O r iv e
Modifique o código do script report.php de forma que, em vez de enviar
os dados por email para Owen, eles sejam inseridos no banco de dados
MySQL. Depois, teste as modificações que você fez.
Remova a parte do código do script report .php que envia os dados para Owen. No
lugar, coloque o código que inicia a conexão ao seu banco de dados MySQL, construa uma
query SQL como uma string PHP, execute a query no banco de dados e depois encerre a
conexão. _____
Eis o K
O
V
Odódi^o PHP em
‘V*« vimos -b-abalhando. Mac
tolo^uc as "tags <?pHp ?> cm
veport-php, «*m
a vez. <
^u
e esta
adidiona»d© este toáiop a
um pcm-to no s£ri|H; ^ c já se
endonira den-tvo das -ta^s-
?
a - ,O
M
e
n
''
o£ die('EC-C-r connecting M
y
S
2
_
.
* - ■
■
t
n
=
E
R
- IN
-0alier.5abduction (first_nair.e, " ■
h
o
wior.i, .h
o
._
m
.w
y
, .
"K
h,t>ey>d, i-V Pa-te-3dfar;-^" 'I ^ ’<
*
«
“
-«■. " •
1
1
1&aily@grsgs-liSt ,r.et ) /
^
r
e
s
u
l
t
.=m
y
s
q
l
i
.
q
u
e
r
v
t
S
d
b
C
, i
q
u
e
r
y
)_
o
rd
i
e1
'
E
r
r
o
rq
u
e
r
y
i
n
gd
s
t
a
D
&
=
e
. J
,
f
f
l
y
s
q
i
i
_
c
i
o
s
el
-
S
d
b
c
);
Envie o novo report.
php para o seu servidor web e depois abra a página report.
html em um navegador para acessar o formulário “Relatar uma Abdução”. Preencha
o formulário e clique no botão “Relatar Abdução” para armazenar os dados no banco.
Agora, inicie a sua ferramenta MySQL e realize uma query SELECT para visualizar as
modificações feitas no banco.
Isto está correto? Escreva abaixo sevocê acha que é isto que o
script deveria estar f^zeiído, e por quê.
. í a J < . ' J J í í ^J j . a 7 .-. à . ’j v M X . ..................................
você está aqui ► 89
use $__POSTna query INSERT
Espere um minuto. Esse trabalho todo que
estamos fazendo não é com o objetivo de pegar dados
diretamente do formulário e armazená-los no banco? Parece que a
consulta está inserindo os mesmos dados, não importa o que tenha
sido digitado no formulário. Não estou vendo nenhuma automação
com este script PHP.
Isto é um grande problema. A consulta INSERT
precisa inserir os dados do formulário, e não
strings estáticas.
A query que construímos consiste de strings definidas
diretamente no código, e não de strings resultantes do texto
que foi digitado no formulário. Para que o script funcione com
o formulário, precisamos fazer com que os dados digitados
sejam colocados dentro da string de query.
mysqli_query()
fcstes dados do íoTmulávio
prctisan» iv pâra àtrfcco dS
0 -forwulavio e a -Ponte dos dados
-e-Wenies aos «relatos de abduções
Qual código PHP poderia nos ajudar a enviar
os valores do formulário de Owen para
dentro da query i n s e r t ?
conectando-se ao My SQL
*~POST fornece os dados do formulário
A boa notícia é que o script re p o rt .php já tM n o 's c ia cíctsh
form ulário armazenados em variáveis, graças a^rperglobal $_POST.
Você lem bra deste código PHP?
$name = $_POST['firstname'
] . ' ' . $_POST['lastnameT
$when_it_happened = $_POST['whenithappened'
$how__long = $_POST [1
howlong1];
$how_many = $_POST ['
howxnany1];
$alien_description = $_POST['aliendescription'
]
$what_they_did = $_POST['whattheydid'
$fang_spotted = $_POST[’fangspotted1]
$email = $_POST[1
email'];
$other = $ POST [’
other ']
■
;
L1UI
1
A superglobal ?__P0£Tjá esèá
sendo usada pava esvair
os dados de dada dampo do
-rormulari© de t para
inseri—
|©s em variáveis.
Le»brs-sC) o nome <ue vode usar
para fJPÜST predisa ser o mesmo
do dampo dorrespondente, *o
•formulário ttTMl—
Assim, vocêjá tem os dados do formulário e só precisa incorporá-los
na instrução INSERT . Mas é preciso fazer uma pequena modificação,
primeiro. Agora que você não está mais enviando os dados por email, não
precisa da variável $nam e. Você ainda precisa do nome e do sobrenome do
usuário, para que o relato possa ser adicionado ao banco de dados - mas
precisa tê-los em variáveis separadas.
0 nome e o sobrenome do wuario
agora sao armazenados em variáveis
$last name = $ POST ['lastname'] ; .separadas, |>arâ ^ue possam s
e
r
inseridos em dolunas di-Perentes da
tabela aliens__abdud£ion.
$first name = $ POST['firstname'
]
;
Escreva o código PHP para criar a string de query i n s e r t armazenada na
variável $query, certificando-se de que ela esteja armazenando os dados
do formulário na tabela a l i e n s a b d u c tio n , ao ser executada.
............
. a j.s .t .^ y > ? ; Lú.r í.^ r ^ r -.e .f. .....
é
*
y.V.ÉL.y..E.S. C. ..1
}Í Íà&.-t
.*
>
.
w
ò>v5... f.
você está aqui > 91
aspas simples e duplas no php
Escreva o código PHP para criar a string de query i n s e r t armazenada na
variável $query, certificando-se de que ela esteja armazenando os dados
do formulário na tabela aliens^abduction, ao ser executada.
S o L u ção
Os nomes das dolun3s
aparedem «a instrução
exatamente domo antes
fquery —“INS&RTIKT0 aliehs^abdudtion (-firstjriame, last^name, wKen^it^bappened, Kowjon«^ w
"Kow^many, alien^desdription, what^they^did, -Canc^spotted, other, email) w.
w
//lLUES (lf-first_nan*e,, Vlast_name t*v/hen_it_bappened,) 'fhov/_Joh^, 'fh^TSnãfP^"
w?alien_desdription >'fv;Viat__they_jiid', l?-Pan^_spotted,) '/other, 'femailOw
;
£m vez. de dados estitidos sobre a ^ ^
abdução de Sally Jones, ajora *cs_y A ordem das variáveis predisa ser a mesma dos
inserimos os dados que o usuário nomes das dolunas, f ara que os dados seja»
distou no -formulário- armazenados nas dolunas dorretas da tabela-
na°e
x
i
s
t
e
m
Eu tenho mesmo que criar todas essas variáveis
para armazenar os dados de $_POST? Não posso,
simplesmente, referenciar os dados de $_POST
diretamentejao^çntro da string $query?
?car
Pode. Não háflad£Tque lhe impeça de
$__POST diretamente em uma query. Porém, é
um bom hábito de programação isolar os dados do 
formulário antes de fazer qualquer coisa com eies. Iss
acontece devido ao fato de ser relativamente comum a 
necessidade de processar os dados de alguma forma,
antes de inseri-los no bansoJ&texemplo, existem
técnicas inteligentes qufhackers^>odem usar para
“sequestrar” suas query, dignando aados perigosos
no formulário. Você verá como evitar tais ataques no
Capítulo 6. Para manter a simplicidade, neste capítulo
não fazemos nenhum processamento nos dados, mas
isso não significa que não deva adquirir o hábito de
^armazenar os dados do formulário nas suas próprias • /
varáveis antes de colocá-los em uma query. /
T  .
1 - Faz alguma-difgrença usar aspas-sfmples ou
dupias? Posso usar aspas simples em torno de toda a
consulta, e aspas duplas em torno de cada variável?
tomo das variáveis. 0 motivo é que o PHP trata as strings
de forma diferente, dependendo da fornia como elas
aparecem: dentro de aspas simples ou duplas. Adiferença
é que as aspas simples representam exatamente o texto
contido nelas, enquanto, ao se fazer uso das aspas duplas,
significa que há algum processamento adicional no texto
quando se usam aspas duplas. Esse prõcessamento
resulta nofato,de que os valores das variáveis colocadas
dentro de aspas duplas são mostradas em strings, no lugar
do nome da variável. Isso é bastante útil, e é por isso que
as aspas duplas geralmente são preferidas para-se criar
strings de query SQL.
Não seria possível criar strings de query
simplesmente concatenando-se as variáveis com o
código SQ L?
Í ^ I Sim, e se você decidir usar esse método,
certamente poderá usar aspas simples em vez das
duplas. Mas as strings de query já tendem a ser
bagunçadas por natureza, de modo que tudo o que
puder fazer para torná-las mais legíveis é bom - inserir
variáveis diretamente em uma string dentro de aspas
duplas, em vez de as concatená-las com aspas simples,
definitivamente torna as strings mais fáceis de serem
entendidas.
Sim, faz diferença. E não, você não pode usar aspas
simples em torno da query inteira, com aspas duplas em
conectando-se ao t>
.
Vamos usar tudo o que já aprendemos para terminar o script PHP de Owen,
para que ele possa armazenar com sucesso os dados sobre as abduções em
um banco de dados. Escreva abaixo o código PHP necessário para completar
Oscript report.
php.
<?php
$when_it_happened = $_PQST [
'whenithappened' ];
$how_long = $ POST ['howlor.ç'];
$how^many '
=
= $_POST['howmany1]; ■
$alien_description = $_POST[raliendescription’];
$whàt_they_did = $_POST[1
.whattheydid’1;
$fang_spotted = $_POST['fançspotted']
$email = $_POST['email'];
$other = $_PGST['other'];
$query = "INSERT INTO aiíens_abduction (first_n-ame, last_name, 'when_i.t_happened, how__lcng, " .
”how_aany, alien_description, what_they_diã,.- fang__spotted, other, email) " -
"VALUES ('$first_name1, '$last_nam.e 1 '$when_it_happene.d', '$how_iong', '$how__many'
, " .
”'$alien_description 1, 1?.what_they_did' , '$rang_spotted1,
'
■'$other1, '$emaii')";
$result =
echo .1Thanks for submitting the fom.cbr />';
echo You were abducted ' .
’ $when_it_happened;
echo ’ and were gone, for ' . $how_long . '<br ■/>';
echo 'Number '
o
f aliens: '
■ . $how_m.any . '<br />’;
echo 'Describe them: 1 $alien_description . '<br />';
echo 'The aliens did this: ' . $what_they_did . '<br />';
echo 'Was Fang'there? ' . Sfang_spotted . '<br />'; .
echo 'Other comments: 1 . $othsr . 1<br ■/
>
'
;
echo 'Your email.
address is ' . $eii>ail;
$dbc =
?>
você está aqui ► 93
C
O
o
4 cicio
~ L x e R c ic io Vamos usar tudo o que já aprendemos para terminar o script PHP de Owen,
O rti .c ã o Para c
'ue e'e P°ssa armazenar com sucesso os dados sobre as abduções em
unr| [jarico çjg dados Escreva abaixo o código PHP necessário para completar
Oscript report .php.
As novas variáveis armazém* o nome
c o sobrenome do usuário, do jei-fco
ele digitou no formulário.
<3:
f-^rst^name — fmP0STrClfirstn3me>
J;
flast_na»e — f^P OSTClastramel',
Vode predisa se donedtâr ao bando
de dados e fomeder as informações
nedessárias antes de realizar
quaisquer donsultas £$L a partir
do PHP.
A query e donstruída domo uma string
PHP- Certifique—
se de usar os dados
extraídos dos dampos do formulário-
$when_it_happened = $_?OST['whenithappened'];
$how_long = $_POST[’howlong'
] ;
$how_many = 5_P0ST['howmany'];
$alien_description = $_POST['aliendescription'
]
$what_they_did = $_POST[1
whattheydid1 ];
$fang_spotted = $__POST [1fangspotted'];
$email = $__POST ['email1];
$other = $_POST[1other 1];
$dbc =
m ysq|i_donnedt^da^ Siensabdud^dme d o m V w e n , 'aiiewrool', 'alienda^UbaseO
or dieC E rror donnedting to MySfiJL server/)^
Squery = "INSERT INTO a!iens_abdu.ction (first_name, last_name, when_it_happened, how long,
"how_many, alien_descriptionr what_they_did, fang_spotted, other, email) ” .
"VALUES (’$first_name'
, '$last_name'
, '$when_it_happened', '$how_long1, '$how many', " .
$alien_description’, '$what_they_did', '5fang spotted', '$other', '$email')";
or dieC&rror querying database-0;
ri»ys«íIit_it1
osçÇfdb^^i
txedute a query ao bando
de dados - isto e o que
insere os dadosf
■i--—...... ■
1 .....'•....... •-...... FedHe a dcmexao a© bando.
echo ’Thanks for submitting the form.cbr />';
echo 'You were abducted ' . $when_it happened;
echo ' and were gone for ' . $how long . ’<br />';
echo 'Number of aliens; ' . $how_many . ’<br />';
echo 'Describe them: 1 . $alien_description . '<br />';
echo 'The aliens did this: ' . $what they did . '<br />';
echo 'Was Fang there? ' . $fang_spotted . 1<br />';
echo 'Other comments: ' . $other . '<br />';
echo 'Your email address is ' . $email;
Confirme se o formulário foi
submetido dom sudesso, da mes*»a
forma torno fazia no sdript antigo-
conectando-se ao My SQL
T fe S T O R fv e
Modifique o script de Owen de forma a usar os dados do formulário
para fazer um INSERT.
Remova a variável $name do script r e p o rt .php, adicione as variáveis $first_name
e $l a s t name e modifique $query para usar as variáveis do formulário, em vez de
texto estático na instrução INSERT. Envie a nova versão dò script para o servidor e teste-o,
submetendo o formulário da página r e p o r t .html algumas vezes, digitando dados
diferentes a cada vez.
U your ett« i gddltg?
W
taH
d
k
litfeâp
p
eo?
How long were you
fln» yvany ywSBfc?
Describe tbem:
; "V
Ç
liaílüdtheydotoyou?
Bave you sten my dog
^Abducted M e . j hm
v
k
*
*
*
d
l
i
k
e
te
n
te
d
I
»
4
'
^a
-L
s
s
t
W
i
a
i
t
:
Yes « No 0
ïïsr.—
«Wœüarday
0
B
s
e
e
,
““W
tattan:
First n&tre
LAstaame:
*8A
b
d
t
I
C
:W
t
u
ui
s
y
w
i
F
C
f
t
t
S
f
i
v
f
a
l
K
S
S
?
Whendklithappen?
H
a
w
tag«rey
«
ig
o
n
e
?
H*nf»aBydMyous
e
e
?
Describe them:
W
JkfltdMtfeeydotoyoa?
Hftre jou x a my dog F«ng?
N
a
d
e
r
;alftvÇSte»eyTíaU
gr<
;
J
d
c
f
e
d
m
ta
b
o
u
t
U
f
O
r
«
$
<
j
S
a
e
e
r
*
Yes Q No 0
Anything<3s&yoo warnto add?
feUpO^AMtfCPOTV^
Agora, use sua ferramenta MySQL para executar um SELECT e visualizar o
conteúdo da tabela aliens abduetion.
Os novos reUt»S
de àbdudoes
aparedem
na tabela,
exatamente domo
vodê esperaí
Hi uma linha extra de dados para Sally Jones, que lo i dolodada antes de «ode donsertar a donsuH
ÍKSÊRT. Não se preodupe, vode aprendera domo remover dados indesejados no proximo dapitulo.
você está aqui ► 95
adicionando WHERE no seu SELECT
Owen precisa de ajuda para peneirar seus dados
O novo e aprimorado script r e p o rt .php está fazendo o seu trabalho, automatizando
o processo de adicionar relatos de abduções ao banco de dados. Owen pode relaxar e
esperar que os relatórios cheguem... exceto pelo fato de que há um novo problema.
Receber mais dados não está, exatamente, tornando mais fácil selecionar os relatos que
representem um potencial avistamento de Fang.
Eu realmente estou feliz, agora que tenho um
banco de dados sendo automaticamente preenchido
com os relatos de abduções submetidos pelos
usuários. Mas isso nao está ajudando a isolar os
relatos que poderiam me ajudar a encontrar Fang.
Owen precisa de uma forma para localizar dados específicos,
como por exemplo, as abduções nas quais Fang foi avistado.
Você sabe qual coluna do banco contém as informações em questão:
f ang sp o tte d . Esta coluna contém yes (sim) ou no (não), dependendo
do fato de o abduzido ter relatado se viu Fang - ou não. Assim, o que precisa é
de uma forma de selecionar apenas os relatos da tabela a lie n s abd u ctio n
que tenham um valor yes na coluna fan g _ sp o tted .
Você sabe que a seguinte query SQL retorna todos os dados da tabela:
SELECT * FROM aliens_abduction
A instrução SQL SELECT lhe permite incluir uma cláusula para
controlar os dados retornados pela query. Trata-se de WHERE, e com
ela você diz exatamente como quer filtrar os resultados da consulta.
No caso de Owen, isso significa selecionar apenas os relatos de
abduções onde a coluna f an g _ sp o tte d seja igual a yes.
L-e»bre-sc> se* a dausula WHERE*
s—isto -Çârã do» <ue "todos os dados
JL da -tabela seja» selediohados.
SELECT * FROM aliens__abduction WHERE
---- ---------------- - . ------------------
0 valor da dolwa
fredisa ser deímido,
f>ara «ue os
dados fossam ser — -v
seledtonados.
fang_spotted = 1
yes1
0 home da
doluna
Esta farte da donsulla
SELECT permanede a m
es»>a
a clausula WHERE duida dc
■Pil-trar os resuüâdos.
Esta eiiusula reduz, o volume de dados
rfbor»ados feia ^uevy, indlumdo afenas
os dados e» <»e a dolu^a sfo^ttcd
esteja de-fmida dow»o yes-
conectando-se ao My SQL
T fe S T O ro v e
Teste a consulta s e le c t com uma cláusula w here para
encontrar ciados específicos.
Use ama consulta SELECT com uma cláusula WHERE na sua ferramenta
MySQL para procurar por dados de abduções que envolvam, especificamente,
avistamentos de Fang.
Todos estes (rcejistv-os te»»
â doluna fan^sfotted
defmida to»© yes. ”””
você está aqui ► 97
banco de dados mysql do owen está funcionando
Owen sai em busca de Fang
Graças ao PHP e às suas funções que fazem interface com o MySQL, o
servidor de banco de dados MySQL de Owen está recebendo os dados
das abduções a p artir de um formulário HTML e os está armazenando
em uma tabela do banco. Os dados ficam guardados de forma segura na
tabela, até que Owen tenha a oportunidade de peneirá-los. E, quando
está pronto para fazê-lo, basta uma simples query SELECT para isolar os
relatos de abduções que, potencialmente, envolvam Fang.
conectando-se ao My SQL
--------ÊÊÊEHk :v iu i w flyÉ V —
Mesmo que você ainda não tenha organizado tudo, ligue cada
componente HTML, PHP e MySQL ao que você acha que ele faz.
alfendatabase
tabela clliens__at*ííuctioTi
se-WíclPt Veb
serVicI°í de kmco de dad^S My-SQj
kptão Sutnilt (sutmeter)
i w ^ ___
mys^lLcpnnectO
mys^lLcloseO
Kiys^lijjueryO
mys^l!_select_dt>()
_ Este é o código SQL que o script PHP
informa ao servidor MySQL.
Isto executa os scripts PHP e retorna
páginas HTML para os navegadores,
/ ' frequentemente se comunicando com um
/ banco de dados no processo.
O nome do banco de dados que contém a
tabela aliens_abduction.
O formulário HTML usa este método
de requisição para enviar os dados do
formulário para um script PHP.
E aqui que os dados do formulário
report .html acabam sendo armazenados.
E aqui que Owen coleta os dados do usuário.
Esta função PHP encerra a conexão ao
servidor MySQL.
Este é o nome do script PHP de Owen que
processa os dados que os usuários digitam no
formulário report.html.
Esta função PHP envia uma query para o
"servidor MySQL.
Este elemento HTML é usado pelos
visitantes do site quando eles terminam de
preencher o formulário.
Este é outro nome para o software que roda
o MySQL e todos os bancos de dados e
tabelas que ele contém.
Esta função PHP opcional diz ao servidor
qual banco de dados usar.
Isto abre uma conexão entre o script PHP e
o servidor MySQL, para que eles possam se
comunicar.
você está aqui ► 99
quem faz o que solução
Mesmo que você ainda não tenha organizado tudo, ligue cada
componente HTML, PHP e MySQL ao que você acha que ele faz.
Este é o código SQL que o script PHP
informa ao servidor MySQL.
Isto executa os scripts PHP e retoma
páginas HTML para os navegadores,
frequentemente se comunicando com um
banco de dados no processo.
O nome do banco de dados que contém a
tabela a lie n s_ a b d u c tio n .
O formulário HTML usa este método
de requisição para enviar os dados do
formulário para um script PHP
E aqui que os dados do formulário
report.htm l acabam sendo armazenados.
E aqui que Owen coleta os dados do usuário.
Esta função PHP encerra a conexão ao
servidor MySQL.
Este é o nome do script PHP de Owen que
processa os dados que os usuários digitam no
formulário report.html.
Esta função PHP envia uma query para o
servidor MySQL.
Este elemento HTML é usado pelos
visitantes do site quando eles terminam de
preencher o formulário.
Este é outro nome para o software que roda
o MySQL e todos os bancos de dados e
tabelas que ele contém.
Esta função PHP opcional diz ao servidor
qual banco de dados usar.
Isto abre uma conexão entre o script PHP e
o servidor MySQL, para que eles possam se
comunicar.
crie e preencha um banco de dados
3 Críe e Preencha umBhuicç»deDados
Criando os Seus PrópriosDados
Nem sempre você tem os dados de que precisa. Às vezes, você mesmo
tem que criar o s dados que pretende usar. E, outras vezes, você precisa cria ra s tabelas que
irão armazenar esses dados. E, ainda, você precisa criar o banco que armazenará os dados que
você precisa criar. Confuso? Você não ficará. Prepare-se para aprender como criar seus próprios
bancos de dados e tabelas. E se isso não for o suficiente, você ainda criará, no processo, a sua
primeira aplicação combinando PHP e MySQL.
você está aqui ► 103
precisa-se do aplicativo lista de email
A loja Elvis está aberta
Elmer Priestley abriu uma loja especializada em
produtos Elvis, QueroSerElvis.com (makemeelvis.
com). A demanda tem sido enorme. Elejá vendeu
um monte de temos de poliéster, muitas costeletas
falsas e centenas de pares de óculos.
Cada vez que alguém compra algo, Elmer coleta
um novo endereço de email. Ele os utiliza para
enviar avisos sobre promoções na sua loja. Da
forma como está agora, Elmer tem que copiar,
manualmente, cada endereço da sua lista
e depois colar um por um nos seus emails
promocionais. Funciona, mas demanda muito
tempo e esforço.
£l»ev> o
ih«yuestio*aveí
Rei da
©
K
iSm
e de
Elvis
fVcsl«Y-
EUev ja doletou VUè eísdere^os
/ " de emâil ate o wíowe^to) e 3 tada
dia the^a*» **ais-
■Joffe
^evvsom
e
G
arcia P'ZZa
Com
R
yan
M
cK
ïj
Isto está demorando
muito. Eu preferiria passar
o meu tempo imitando
Elvis, e não enviando emails
manualmente.
^..G
^sim
uduck-con-i
Amanda aman21uv@breakneckpizza.
Ed e d 9 9 @ b 0 tt0 m s u p .c o m
Roundtree Jo-Ann joioroi
Briggs Chris cbrig __ v”*
Harte Lloyd hovei^<art@breakneckpiz2a.com
Toth Anne AnneToth@ieapinlimos.com
Wiley Andrew andrewwiley@objectvilie.net
Palumbo T'"r~ palofinine@rnightygumball.net
angrypirate@breakneckpizza.com
ctay@siarbuzzcoffee.com
annmeeker@chocohoiic-inc.com
bp@fioney-doit.com
am86@objeciviiie.net
debmonster@breakneckpizza.com
janistedesco@starbuzzcoffee.com
vikt@starbuzzcoffee.com
szwedjoe@objectvilie.net
sheridi@mightygumball.net
snowman@tikibeanlounge.com
giennO
O
9S@objectviile.net
anneh@
bO
ttO
m
sup.com
nobigdea!@star‘-
irpa”—
’' '
com
com
Elr«ev esdreve
cste entail e
fiofia e cola
£ada endeve^o
no Êâmpo “7©
*.
Tom
Aianna
nney Clay
Meeker Ann
Powers Brian
Manson Anne
Mandei Debra
Tedesco Janis
Taiwar Vikram
Szwed Joe
Sheridan Diana
Snow Edward
Otto Gienn
Hardy Anne
Deal Mary
Jagel Ann
Melfi James
Oliver Lee
Parker Anne
Ricci Peter
Grace
Zelda
Clifford
Joyce
Anne
Lindy
Fred
Anne
eckp
iz2
:acom
R
eno
A
icss
Day
So/ger
e<
u
rji
e°l/ing
G
ares
Jacobs
l,ver@
M
/e
;9
.r,suPco^
r>cZep@
Sta^ S o T a'C
O
m
l !tr!a
n
m ikibe^eeco^
£ g £ t * * 2 ^
C
W @ S ^ c o m
l0yce@ cho^ck^.c o m
anneb/uni@
fa
r 'c‘'0ccom
Te
9
9
@
^SZ
Z
e-nef
";
S
t
*
f
e
c
f
c
-
'
'
fGrande promoção
Caros Elvismaníacos,
Grande promoção esta semana em
Makemeelvis.com'. Costeletas de pêlo de
cavalo genuíno com 20% de desconto!
E não se esqueçam da promoção "compre um
e leve outro de graça" para os ternos d e >
poliéster - só dura irais três dias!
fcsias fessoas estao
*a lista d« e»ails de
£Uev e ^ueirenr» a sua
ajuda fava í tarr «**
^ouio mâis ^âiríiida^
fconx Êlvis-
Elmer está passando tempo demais copiando e colando emails no
campo “To” do seu programa de email. Ele deseja simplificar a tarefa
de adicionar novos endereços e de enviar emails em massa.
crie e preencha um banco de dados
Élwer precisa de uma aplicacão
Uma aplicação é um software elaborado para atender a um
determinado propósito dos seus usuários. Elmer precisa
de uma aplicação que mantenha o registro da sua lista de
endereços de email e que lhe permita enviar emails para a5
pessoas da lista clicando apenas em um botão. Eis a forma
como ele quer que funcione:
Uma aplicação Web
é um site dinâmico
elaborado pata atender
a um determinado
proposfto dog seus
usuári9s.
Ir até uma página web e digitar uma mensagem de email.
E f Clicar em um botão Submit na página, e a mensagem
ser automaticamente enviada para toda a lista de
"QueroSerEIvis.com".
Jyy Fazer com que a lista de emails cresça sozinha.^
permitindo que novos clientes se cadastrem através
de um formulário web.
Com essa lista de necessidades que a aplicação precisa atender,
Elmer pode visualizá-la em detalhes...
Esta fârte de ew
»aiU
sc ^arete bastante d
o
w
»
a apl'tdatao Abdução
Alienígena de 0*>en» »as
' a di-ferença a<w é a
lista de emails de El^ev
ivi cresder sozjnVtâ) e^
as suas w»ensa^ews se>rao
enviadas para a lista
inteira 0 obetWo da
;lmcv t
> Q
A aplicação web QueroSerElvis.com {MakeMeElvis.com) consiste de dois
componentes principais: um formulário para enviar mensagem de email
para as pessoas na lista de Elmer e um formulário para permitir que novos
clientes se inscrevam na lista. Com esses dois formulários em mente, faça
um esboço de projeto para a aplicação de Elmer.
você está aqui ► 105
design do nosso aplicativo lista de email
Visualize o projeto da aplicapão de Elmer
Sempre é útil visualizar o projeto de uma aplicação antes de mergulhar
nos detalhes do desenvolvimento. Isso implica descobrir quais páginas
e scripts estarão envolvidos, com o eles se conectam e, talvez o mais
importante, como você irá armazenar os dados no banco MySQL.
Estas pessoas esta© «a
lista de emails de Elmer
e redebem o* e—
»ails que
ele envia ?ara a lista-
Esta tow>bina^a° de
iW Jario /sd ri^
«we os u
s
v
i
a
r
i
ô
sse insdrevam
l. I _ J - V .) Àt>
Este sdvipt pffp
ChV,a a #«ensa^eft,
de etnáil
Este e o
íormulirio
web que Elmer
preervdKe para
driar e enviar
um email para A lista de enderedos
a lista- de email de Elmer
-fida armazenada em
uma tabela de um
bando de dados que
roda em um servidor
de bandos My£$L.
MËH1É3 l i f t É S l * » .........
Jon Matthews
ionathan@wishiwaseivis.com
Wendy Weriitz
wwer@starbuzzcoffee.com
Joe Bob Franklin 2ksdgi@gre9s-|istnet
crie e preencha um banco de dados
Então, por onde começamos a criar uma
aplicação com PHP e MySQL? Será que nós
escrevemos o script PHP primeiro e depois criamos a
tabela para armazenar os dados? Ou será que devemos
criar a tabela primeiro e depois o script?
Joe: Não entendo que diferença faz. Nós vamos precisar da
tabela e do script para a aplicação funcionar.
Frank: Isso é verdade, mas acho que nós devemos escrever o
script primeiro, para podermos testar o código PHP antes de
conectá-lo ao banco de dados.
Jill: Mas o script PHP é completamente dependente do banco
de dados. Será difícil testar o script se não tivermos um banco
ao qual ele possa se conectar.
Frank: Será que não poderíamos criar o script e omitir apenas
a parte específica do código que faz a conexão com o banco?
Poderíamos fazer tudo exceto interagir realmente com o banco
de dados. Isso ainda seria útil, certo?
Joe: Não necessariamente. Lembre-se, o único trabalho do
script é selecionar os dados digitados em um formulário HTML
e colocã-los em um banco. Ou, se a função for enviar emails
para uma lista, o script lê os dados do banco e gera uma mensagem de email para cada
usuário. De uma forma ou de outra, o banco é essencial para o script.
Jill: E verdade, mas ainda nem começamos a pensar no formulário HTML. Onde ele se
encaixa nisto tudo? Estou achando que precisamos criar o banco de dados antes de sequer
pensarmos em escrever o script.
Frank: E isso! Primeiro criamos o formulário HTML, depois analisamos que tipos de dados
vão ser colocados no banco e, feito isso, nós finalizamos tudo com o script.
Joe: Não sei se isso realmente faz sentido. Como podemos criar um formulário HTML se
não temos 100% de certeza de que tipo de dados precisamos obter do usuário?
Jill:Joe está certo. O formulário HTML ainda^aps leva de volta ao problema de precisarmos
saber quais serão os tipos de dados usados fl^a aplicação. Os dados comandam tudo,
A Cantão nós provavelm ente deveiyagjos criajfo banco de d ados e a tabela prim eiro, depois o
form ulário HTML e, finalm engp, o script qüerearge a^uBmissão dò lormulãrlTYÍ1
Frank: Gostei. Vamos fazer isso!
Joe: Eu ainda acho que nós, provavelmente, precisaríamos elaborar os passos específicos de
como esta aplicação será montada...
Escrevaabaixo ospassos específicos que você acha que serão necessários
para ir do projeto até a implementação de QueroSerElvis.com.
planejando a aplicação
PLANEJE ANTES
Nós realmente precisamos de um plano para montar a aplicação de
Elmer. Passo-a-passo, nós podemos nos concentrar em uma coisa de
cada vez, sem que fiquemos sobrecarregados.
Criar um banco de dados e uma tabela
para a lista de emails.
Esta tabela irá armazenar os nomes, sobrenomes
e endereços de email de todos os inscritos na lista
de Elmer.
elvis store
O Criar um formulário web e um script PHP
Adicionar Email para inserir novos clientes
à lista.
Aqui, nós criaremos um formulário e um script que
permitirão ao cliente digitar seu nome, sobrenome e
endereço de email, e então adicioná-los à lista. addemail.html
O Criar um formulário web e um script
PHP Enviar Email para enviar emails
para a lista.
Finalmente, iremos criar um formulário web
que permitirá a Elmer compor uma mensagem
de email e, o que é mais importante, um script
que enviará esta mensagem para todos os nomes
inscritos na tabela da lista de emails.
'sendemail.php
sendemail.html
crie e preencha um banco de dados
Tudo comepa com uwa tabela
Na verdade, tudo começa com um banco de dados, que é
basicamente um Container para o armazenamento de dados.Jã
vimos, no capítulo anterior, o modo como os bancos de dados são
divididos internamente em mais containers, chamados tabelas.
Assim como os dias e semanas em um calendário, a tabela se
compõe de colunas e linhas de dados. As colunas consistem
de um tipo específico de dados, como por exemplo “nome”,
“sobrenome” e “email”.As linhassão conjuntos de colunas
em que uma linha consiste de um elemento de cada uma das
colunas. Um exemplo de linha seria “Wendy, Werlitz, wwer@
starbuzzcofee.com.”
c a le n d á rio
Um banco de dados
4 um container usado
para armazenar
dados, de íprma
bastante estruturada.
■(A
foS tolwW
i
1 2
fllllilll
3
ilíílüliííílímm
6
M
..
7
3 9 1
0 1
1 1
2 1
3 1
4
1
5 1
6 1
7 1
8 1
9 20 2
1
-------------_l
j Ambas estas -y
estvuWas
dados sa© tabelas.
Em geral, todas as tabelas de um banco de dados tem alguma
relação umas com as outras, mesmo que essa associação às vezes seja
superficial. E comum uma aplicação web consistir de várias tabelas
conectadas umas às outras por meio dos seus dados. Mas todas as
tabelas ainda são feitas de colunas e linhas.
Uw» bando de
dados, «w
e c
iXm
a li^a
As tabelas
armazenam
dados segu!nd9
um padrão de
cçlunas e linhas.
^>
ov scvvidosr
— uaiKts
r n í
Esias sao as AoJunas.
J^nse no
bando de
dados
domo um
doniainer
«ue
armazena
m-forw>a^oes.
Ou-tv-a tabeia
Ainda ou-tsra -tabela
não existem
Terguntas idiotas
T * * Onde os dados do banco
são realmente armazenados? É
possível ver os arquivos?
1 ^ * Os dados de um banco
geralmente são armazenados em
um disco rígido. E, embora você
certamente possa vê-los, eles não
lhe diriam muita coisa. Os arquivos
de bancos de dados são binários, e
não podem simplesmente ser abertos
e ter suas informações visualizadas.
É por isso que temos SQL- para
permitir que nós olhemos o conteúdo
do banco e interajamos com os dados
armazenados dentro dele.
você está aqui ► 109
CRIE seu banco de dados
Faça contato com o servidor MySQL
O projeto da aplicação de Elmer exige um banco de dados e
uma tabela. A maior parte do trabalho cotidiano com um banco
de dados envolve a interação com tabelas, mas você não pode
simplesmente sair criando tabelas sem criar, primeiro, um banco
onde elas fiquem armazenadas.
CREATE DATABASE é o comando SQL usado para se criar um
banco de dados. Uma vez feito isso, você pode então criar uma
tabela com o comando CREATE TABLE. Mas antes de usar
qualquer um desses comandos, você tem de se conectar ao seu
servidor de bancos de dados MySQL. Você fez isso no capítulo
anterior e precisou de algumas informações importantes.
Uma íerramehia /HySßCJ1
Como o terminal
permite qttC voie se fcmedte
â um servidor A
•ßornedehdo uma
de usuário e uma
senha válidos.
Além de permitirem que um script PHP se conecte
ao banco de dados e realize ações nele, a localização,
o nome de usuário e a senha do banco são a chave
para que o terminal MySQL ou o phpMyAdmin sejam
utilizados. E essas ferramentas são bastante úteis para que
realizemos os primeiros passos da aplicação: a criação do
banco e da tabela.
Já que a criação de um banco de dados e de uma
tabela para a aplicação de Elmer é uma tabela que só
só precisa ser realizada uma vez, faz sentido usar uma
consulta SQL para criá-los manualmente. Portanto,
inicie sua ferramenta MySQL preferida e prepare-
se para realizar o primeiro passo na elaboração da
aplicação de Elmer, criando um banco de dados e uma
tabela para a lista de emails.
VoC* esti aqui.
Crie um banco de dados euma
tabelo para a lista de emails,
Crie um formulário web e um
script PHP "Adicionar Email" para
adicionar novos clientes à listà.
Crie um formulário web e um
script PHP "Enviar Email" para
enviar um email para a Iista.
crie e preencha um banco de dados
Crieuw banco dedados para os emails deElmer
Para criar uma nova tabela e um novo banco para a lista de emails de
Elmer, primeiro nós temos de criar o banco de dados elvis store, o
qual irá armazenar a tabela email list. Nós usaremos comandos SQL
para criar ambos. O comando SQL usado para criar um banco de dados
é CREATE DATABASE, que você usou, rapidamente, no capítulo anterior.
Vamos dar uma olhada mais detalhada no seu funcionamento.
0 nowe do ftovo
nome do banco ba*to de dados à
sev* eviado
É preciso especificar o nome do novo banco de dados após
o comando CREATE DATABASE. Eis a instrução SQL para
criar o banco de dados de Elmer:
CREATE DATABASE elvis store
Quando você executar esta instrução em um servidor
MySQL, o banco será criado.
I File Edit Window Help Don’tBeCruel
mysql> CREATE DATABASE elvis_store;^
Query OK, 1 row affected (0.01 sec)
CheAtb
d a t a b a s e é
o oonjEuiJo S q L
u s a J o p g ra se
ctícií um íipVp
kcUlco J e click's.
Ao e*edu±ar C o a d o s SQ L *0
■èev-minai, vote sempre adiòona
W
» po«*to-e-viVg^ia ao -Pinai...
mas nêo tuâ»do -pi^cr donsui-bs
SQL â tw é s da -função PHP
»ys^íi^ucv-yO.
elvis store
Criar o banco de dados elvis store com o comando CREATE
DATABASE resulta em um banco de dados novinho em folha, mas
ainda não há uma tabela para armazenar os dados...
N
0 banò© de dados £oi triado,
mas ele «ao pode a r^ a ^ a r
dados se hão Houver u»a -tabela.
V e jÊ tW n !
As instruções SQL só terminam em ponto*
e-vírgula quando você usa o term inal.
No seu código PHP, as suas instruções SQL não
precisam terminar em ponto-e-vírgula. O terminal
MySQL é diferente, porém, e requer o ponto-e-
vírgula ao final de cada instrução SQL. Isso ocorre porque o
terminal é capaz de rodar múltiplas instruções SQL, enquanto
que, no PHP, você só pode submeter uma instrução por vez.
você está aqui ► 111
agora CRIE sua tabela
Crie uma tabela dentro do banco de dados
Você precisa saber qual tipo de ciados deseja armazenar na tabela,
antes de criá-la. Elmer deseja usar o nome e o sobrenome das
pessoas da sua lista de email, para tomar um pouco mais pessoais
as mensagens que irá enviar. Adicionando a essas informações
o endereço de email, a tabela e m a il_ lis t de Elmer terá de
armazenar três informações para cada entrada.
Cada informação de uma tabela fica em uma coluna, que precisa
ter um nome que descreva os dados. Vamos usar f irst_ n am e
(“primeiro nome”), last_nam e (“sobrenome”) e em ail como
o nome das nossas colunas. Cada linha da tabela consiste de uma
única informação para cada uma dessas colunas, e constitui uma
única entrada na lista de emails de Elmer.
0 veiho arquivo de te*to de
£imer> dontendo o
senderedos
^ Cwâil, hão se doiwpara £,o
mS
estrutura e a segurança de w«a
_____ bela de bando de dados
Jon Mãtttews _________
Wendy _ ______
vjwer^starbyz^oW «^^_-*_
Joe ÇobJFraWklm_______ _
2 J^^^r^"-Jist net__-
eirna'»l_J'»st C“»â
das »uitas tabelas
<
^ue pode** ser
armazenadas no
bando de dados
elvis store-
store
« rsfrü ú í» "! last name7! l i i i i i l l i i Ä l i l i i i i i i
Jon Matthews
ionathan@wishiwaselvis.com
Wendy Werlitz
wwer@starbuzzcoffee.com
1 —
1 Joe Bob Franklin
2ksdaiiaiflregs-list.net
î
tstas sao dolunds- ^
Kossa tabela tem très.
fc&âs sao linKas. Cada
<
“*> iontô» „„ ^
sobrenome e un, enderedo
de e»*aif de pessoa.
mailinglist.txt
As HnLas Ja tabela
s ã 9 W iz ^ r tta S s
e as colunas sã°
V e rtic a is .
Então, agora nós sabemos que o primeiro nome, o sobrenome
e o endereço de email do cliente precisam ser criados como
colunas na tabela e m a il_ lis t. O problema é que as tabelas do
MySQL são altamente estruturadas e esperam que você forneça
mais do que apenas o nome da coluna. Você precisa informar
ao banco de dados um pouco mais sobre que tipo de dados você
pretende armazenar na coluna.
Colwrvâs de dados na nova
tabela erraiMist de £Uer.
crie e preencha um banco de d»
Precisamos definir os nossos dados
Quando você cria uma tabela, precisa informar ao servidor MySQL qual o
tipo de dados que cada coluna terá. A definição do üpo de dados é exigida
para todas as colunas MySQL, e cada coluna de uma tabela armazena um
tipo particular de dados. Isso significa que algumas colunas poderão conter
texto, algumas poderão conter valores numéricos, algumas poderão conter
horas ou datas, e assim por diante. O MySQL possui uma série de tipos de
dados, e você precisa saber qual tipo corresponde aos seus dados específicos.
Vamos supor que Elmer tenha uma tabela chamada p ro d u c ts (“produtos”),
que registra os itens à venda na sua loja: ^ i'' ■M
)
E sta doluna lon-téi» desíi-idScs textuais Ar ^ í mr»cro
«da prcAM da loja de
f dílada f*-odufc V
.3«> « W '-
p ro d u c ts
® Ü i .. product .• . ... in v e rt« ,- ■ H I
I'.IfiTvMI
1 Blue Suede Shoes 24 59.00
2 Polvester Pants with Sequins 16 23.50
3 Stick-On Sideburns 93 1.99
--------------
4 Elvis wig 7 48.00
Ntfaiero I n t e i r o
■ i
Blue Suede Shoes
Polyester Pants with Sequins
Stick-On Sideburns
Elvis wig
A , • ÍTN ,A * A yvite CyreÇO J
ft doluna IP tortßm valeves de iden-b+itaeao twbe» valors
úm
idos pava «da pvodup da loja.
Texto
Repare que p ro d u e té a única coluna de texto na tabela p ro d u cts.
Há também números decimais para p ric e , e números inteiros para
in v e n to ry e id. O MySQL tem os seus próprios nomes para cada um
desses tipos de dados, bem como alguns outros, como por exemplo
para datas e horas.
E importante usar os tipos de dados apropriados ao se criar colunas,
para que as suas tabelas sejam precisas e eficientes. Por exemplo,
dados do tipo texto ocupam mais espaço do que números inteiros;
assim, se uma coluna só precisa armazenar números inteiros, é uma
prática inteligente usar o tipo de dados inteiro para ela. Além disso,
se o servidor web souber qual tipo de dados uma determinada coluna
armazena, ele não permitirá que você, acidentalmente, insira o tipo
de dado errado. Assim, em uma coluna definida para armazenar datas,
você receberá um erro se tentar inserir qualquer coisa que não seja
uma data, nessa coluna.
24
16
93
Numero Inteiro
Pata Vpoô pteoîsa
sabeï IFh
J set
atmS
c
z
&
n
ad<
>>W-c£Ula*eoïui)a Jatabela.
W E R
Por que você acha que usar
diferentes tipos de dados é melhor
do que usar apenas texto, para
armazenar tudo?
você está aqui ► 113
&
<
A
s mysql frequentemente usados
alguns tipos de dados MySQL
Estes são alguns dos tipos de dados mais úteis do MySQL. Lembre-se, você
pode usar qualquer um deles para descrever os dados armazenados dentro
de uma determinada coluna da tabela. A função desses tipos é armazenar os
seus dados sem criar,cpnfusões.
f f
Vcttm»CHARACTER. Ela €rí^da t
preíére ^ue os seus dados íenbam w*
íamanh© deíinido. Ela pode sev aliamen'te
eíidienie se voíe ^ivet- al^um ix%bo <
^«
e
iehhâ sempre a mesma exèensao.
p E C ,> e v 'a ^ °^ c
lKe
Wctcv-á W ôs
tasas defr«*»* T e
vote prediz» ?*‘0
jde ian-to for
ID A TÍTM V3nto
p.eu
man'tem o registro da
daía e da hora-
/
MRCHMj abreviação de
^R iô b le ^^fl^a tie r (Varadter
variavel"). Efe^armâjyina dados em
modo •texto- E -flexível e dapaz.
de se adaftâv a extensa© dos seus
dadosj arma^na^do apenas o *^*e
vote predisâ; sem preendKer ladunas
dom espaços em brando-
JNT^ IKTSÇBR asK
an
u
e
olTnumeros devem sev hvteíros,
mas na© "tem medo de números
ne$a£iv©s. Eje e dapaz-, também,
de âvmárenôr números mteivos
, çe^enos^dwjo daso é dhamado de
‘TfX//(X/-T
Dependendo da sua versão do My£$L, a
extensa© pode ser de Z55 darad-teres anies
da versão 5.0.3, e a-te darad-teres ná
versa© 5 e adima.
Ele se fib a m a ^i3 -
Ele $osta * ^andes
quantidades de dados
binários-
Uma boa am)0
<
BLOB, esid^TB^Kl
cia é exdelen-te
í "
armazienar grandes
<wa«-tidades de
"texto —murt© mais
do <^e O iM ou
VMOMR-
(PATEVan-tém registro
dâTsías datas. Ela não
se interessa pilas boras,
porem- ESa itjt
. ? A
nrma jemea,
3o dontrario tíe(á> «3o
se importa dom as datas
crie e preencha um banco de dados
nq.9 existem
perguntas Idiptas
1 - Por que eu usaria CHAR, se V A R C H A R faz a
mesma coisa, com mais flexibilidade?
A resposta está na precisão e na eficiência. Do
ponto de vista do projeto, você deve sempre projetar
suas tabelas de forma a modelar os seus dados o mais
rigidamente possível. Se você souber, sem sombra
de dúvida, que uma coluna para armazenar a sigla
dos estados irá sempre armazenar exatamente uma
abreviatura composta de duas letras, então faz sentido
permitir apenas dois caracteres de espaço para ela, com
CHAR { 2). Entretartto, se por exemplo uma coluna
para senhas puder conter até 10 caracteres, então
VARCHAR (10) faz mais sentido. Esse é o ponto
de vista do projeto. Assim, CHAR é um pouco mais
eficiente do que VARCHAR, porque ele não precisa se
preocupar com a variação de tamanho dos dados. Assim,
é mais desejável usar quando você sabe, com certeza,
que uma coluna de texto terá uma extensão fixa.
1 - Por que eu preciso desses tipos numéricos,
como IN T e D E C ?
Trata-se do armazenamento e eficiência do
banco de dados. Escolher o melhor tipo de dados para
cada coluna da sua tabela reduz o tamanho desta, e
torna mais rápidas as operações feitas nos seus dados.
Armazenar um número como número propriamente
(INT, DEC, etc.), em vez de caracteres de texto, em
geral é mais eficiente.
f É só isso? Esses são todos os tipos?
Não, mas estes são os mais comumente usados.
Nós praticaremos com estes por agora, em vez de
complicar as coisas incluindo tipos de dados que, talvez,
você nunca vá precisar.
VARCHAR(60)
CHAR(2
)
DATETIME
DEC (10,2)
U P R 9 P Q 5 ÍT Q
Ligue cada tipo de dados MySQL à descrição dos dados que você
poderia armazenar em uma tabela.
Desctiçãp
,,-Seu nome completo.
ma abreviatura de estado, com duas letras,
reço de uma peruca do Elvis: 48.99
J^uanto dinheiro rendeu o disco mais vendido de Elvis.
ata da abdução alienígena: 2/12/2004
Número de costeletas do Elvis em estoque: 93
Você viu o cachorro de Owen? S ou N
Seu en d ereço d e em ail
que horas você janta
Quantos aliens você viu quando foi abduzido
uando foi que Elvis nasceu
você está aqui ► 115
qual o meu propósito? solução
U PR9 P9 SfTQ
Ligue cada tipo de dados MySQL à descrição dos dados que você
poderia armazenar em uma tabela.
Kao é nedessário. Embora íundione
para a abreviatura de estado,
CHAR(2J t uma opçao melhor, porque
geralmente é um poudo mais eíidiente.
de Dados
 DATE
TIME
■
VÃReHAfi-{-
DEC (4,2
VARCHAR(60
CHAR(2)
DATETIME
DEC (10,2)
DEC
3eralmente é
usado para
armazenar
preços, além de
outros valoves
dedimãis.
guando o tamanho de um valer de texto
puder variar, l/ARCHAR c uma boa opção.
Faça-o iom
^o o suíidiente para armazenar
*ual<uer valor <
^
u
ealguém predise armazenar.
Descrição
ó^uándo v©de souber
exatamente quantos
daradteres esperar em
uma doluna, use CHAR-
Seu nome completo.
Uma abreviatura de estado, com duas letras.
Preço de uma peruca do Elvis: 48.99
Quanto dinheiro rendeu o disco mais vendido de Elvis.
Data da abdução alienígena: 2/12/2004
Número de costeletas do Elvis em estoque: 93
Você viu o cachorro de Owen? S ou N
—
Seu endereço de email
A que horas vocêjanta
Quantos aliens você viu quando foi abduzido
Quando foi que Elvis nasceu
/K
/
Estes dois
numeroS mostvam
^uântos dúytos o
ba*£o dc dados
deve esperar
nd frente
do deí-i*^ t
quantos depois.
V
o
tepode -ter
respondido DATE a*ui,
mas os Elvismaníádos
verdadeiros sabem a
data e a hora exatas.
Podem Haver outras (t
Potendialmente melhores)
4-ormas de se representar
um valor sim/«ao n
o/VlySáJL
do <
^
u
e usando CHARO),
mas esta -forma é simples e,
razoavelmente, eíidiente
crie e preencha um banco de dados
Crie sua tabela com uma consulta
Já temos todos os pedaços de que precisamos para criar
nossa tabela, inclusive um bom nome (email_list).
Também temos nomes para as colunas de dados:
first_name, last_name e email. Só o que falta são
os tipos de dados para cada coluna, bem como uma
instrução SQL parajuntar tudo isso e criar a tabela. O
comando SQL para criar sua tabela é CREATE TABLE.
Ele começa com CREATE TABLE seguido do nome da
sua tabela. Os nomes de todas as colunas vem entre
parênteses, separados por vírgula e seguidos, cada um,
de um tipo de dados. Eis como seria o comando:
Si», a'mda estamos a^ui.» »as
estamos «uase prontos fa^a
vLf seguir adiante-
Q Crie um banco de dados e uma
V tabela para a lista de emails.
Q Crie uni formulário web e um
script PHP "Adicionar Email" para
adicionar novos clientes à lista.
0 Crie um;formulário web e um
script PHP "Enviar Email" para,
enviar umemail para a lista.
kT 0 nomt da tabela
m J È Ê Ê A nome_da_tat,ela
0 nome da dolu^a
)
nome_da_colunal t±po_da_colunal,
nome_da_coluna2 t±po_da_coluna2,
K y 0 tipo de dados
da Coluna
/o à wao predisa nomear suas tabelas e
doluwas do» um undersdore separando
as palavras, mas c uma boa ideia se
rna«ter dohsistente em relaçao a «ual«uer
donver^âo de nomearão <ue dedidir usar-

Mais doiunâs,
se «edessario
0 c o m a n d o S Q L
C R E A T E T A B L E
é u s a d p p a ta <jue
seja cilada uma
nWatabela era
um banco de
dados.
Aponte seu lápis
Escreva uma query SQL para criar a tabela email_
list de Elmer com as três colunas de dados requeridas:
first n
a
i
t
i
e
,last name e email.
CÍ€flu.e..
.....V A R c M ft f e íâ
h . s : L ^ à ... V ô A Q m £ © p 1 .
&r.sãi.
—
-J-
■
■
■
/......
você está aqui ► 117
test-drive suas queries CREATE
- t^ponte seu lápis--------------------------------------
Q n l l i p õ n Escreva uma query SQL para criar a tabela e m a il_
^ l i s t de Elmer com as três colunas de dados requeridas:
f ir s t _ n a m e , la s t _ n a m e e e m a il.
£ste c o to*nèndo SdJL. pav-a criar a
tabela - repare nãs letras »aiusduias. r
) ___o *ome da sua tabela deve t o r em
L eaiita ba‘»*a e deve te r um wvderscore
CREAT6 TABLE «.ail list » lu3a'r a' ts?a^ s'
0 parentese ............................................... ...............................................
de abertura *--------- (
abre a lista de ................................................................................................
dolunas a serem -Pirst_na«*e /ARCttAR(2^))> ér~ ~ ^ vírgula separa as tolunas
tríadas- ”/ serâo tria das-
last_wame VARCHAR(2£ ), éz:
email V b K C m ttO )
‘...............V ’” " ................................ isto diz. ao /V|y£^L nuCa toU a
/) a i ^ ^ ' V c . o iifo de dados
t e t ...................  = » : < u * u a ............... œ l o « * * « 1« »
a lista das ‘V* 05 ürattww. ° ^ ^ 40
toiunas. endereços de email
O R f V e
Crie o banco de dados e a tabela de Elmer.
Execute as queries CREATE DATABASE e CREATE TABLE usando uma ferramenta MySQL
para criar o banco de dados e lv is _ s to r e e a tabela e m a il_ lis t dentro dele.
CREATE DATABASE elvis_3tore
CREATE TABLE email_list (first_name VARCHAR(20
), last_name VARCHAR(20) , email VARCHAR(60) )
Ambas as queries foram executadas sem problemas? Caso contrário,
escreva aqui o que-você acha que podje ter dado errado. .
.......í . p^fr' ^ •
crie e preencha um banco de dados
Espere aí, tem algo de
errado aqui. Eu digitei o código
para criar a tabela exatamente da
forma como estava escrito... e agora
estou recebendo uma mensagem de
erro esquisita.
File Edit Window Help Oops
A ívvs-bruçâo CREATE TABLE
e s t a OK m as o -fccvWiha} M y £ $ L
«âo sabe em bando de dados
a iabcla csta sendo triada-. isso
nSc c bom v
Elmer csta fvcodupado
por^uc a sua inytvuiao
CREATE TABLE M
fcr-fcita e, W
C
S
nnOassim,
©ievmina! My£$L
&íã vclaíahdo um trro-
mysql> CREATE TABLE email_list ^ = 5^
(
fxrst_name VARCHAR(20),
last_name VARCHAR(20),
email VARCHAR(60)
) ;
ERROR 1046 (3D000): No database selected
^ al^um motivo, a insfaru^ao CREATE
TABLE íalbou w> terminal MyS$L.
a tabela do *,aMC0 de dados
Colocando o oarro na frente do9 bois
Elmer tem um problema que tem a ver com o fato de que o terminal
mySOL não sabe, automaticamente, a qual banco você está se
referindo ao emitir comandos. É claro que ele sabe que você acabou
de criar o banco de dados e lv is s to re , mas poderia haver diversos
outros bancos de dados armazenados no mesmo servidor - ele não
pode simplesmente assumir que você está se referindo àquele que
acabou de criar.
Felizmente, existe uma solução simples, que envolve informar ao
terminal MySQL qual banco de dados você quer que seja o alvo de
todas as instruções subsequentes...
na° existem
p e r g u n ta s Id io t a s
Qual é a desse promptesquisito ->que eu às vezes vejo no terminal MySQL?
0 prompt -> indica que você está digitando uma mesma instrução ao longo de várias linhas - o MySQL
está basicamente lhe dizendo que sabe que você ainda está digitando a mesma instrução, mesmo que você
tenha pressionado Enter para separá-la em mais de uma linha. Uma vez que você termine a instrução e coloque o
ponto-e-vírgula no final, o MySQL irá executá-la.
você está aqui ► 119
não esq u eça do com ando U S E !
SELECIONE o banco dedados antes deusá-lo
Para que a instrução CREATE TABLE funcione, Elmer precisa
selecionar o banco de dados no terminal MySQL, para que
este saiba a qual banco de dados pertence a nova tabela.
O comando U S E escolhe um banco de dados como sendo o
padrão no terminal, o que significa que todos os comandos
subsequentes irão se aplicar a esse banco de dados.
Funciona desta maneira:
0 tomando USE m-forma ao
MyS$L <i*a! bane© de dados vote
pretende usar.
r . ■
I nome do banco
0 comando USE
selecfona um banco
d e d a d p s c o m o
o p a d r ã o p a t a
insítuçoes SQL
s u ts e c p e ti te s .
Elmer deve especificar o nome do seu banco de
dados (elvis_store) em uma instrução USE para
selecioná-lo e acessar a sua nova tabela.
USE elvis store
Home do bando d
e
dados vott ***€r
setedicnar do» USE-
e1vis
_
j
sightings
0 doma*d© USE esdolhe o
baháo d
edados do«, o «^ai
vodc d
e
se
jatrabalhar.
elvis_lyrics
elvis_fans
Wma vez. vode tenha esdolhido
un> bando de dados para usar, os
demais bandos dc dados do servidor
sao ignorados - â it ^ue vodê esdolha
seiedionar um outro bândo de dados.
T fe S T O R fV G ------------------------------
crie e preencha um banco de dados
;
.v
Execute USE primeiro para depois criar a tabela.
Execute a consulta USE em uma ferramenta MySQL, para
selecionar o banco de dados elvis_store de Elmer e depois
execute a query CREATE TABLE para criar a tabela email_
l i s t dentro do banco.
USE elvis_store
CREATE TABLE email list (first name VARCHAR(20) , last_name VARCHAR (20) ,email VARCHAR(60) )
A instrvção USE *ao « «efiessaria daso vod£
esteja usando uma -ferramenta S ^L 9
™ -«da,
fcomo o fbfMyAdm'm - nesse daso, vote ira
selecionar o bando ^raiitamehte, antes de
emitir os tomáwiw ■
I File Edit W indovj/^elp LisaMarie
mysql> USE elvis_store;
Database changed
mysql> CREATE TABLE email list
(
first__name VARCHAR(20) ,
last_name VARCHAR(20),
email VARCHAR(60)
Your SQL query has been executed successfully (Query took 0.4481 sec)
A
0 código para a
triaça© da tabela
e o mesmo de antes
—só era prefiiso
seletionâr o bando
para que -fuhdionasse.
Com o bando de dados seledionado
atrâves do dom3ndo USE, a
triaiac da tabela, a^ora, edorre
sew. problemas-
você está aqui ► 121
o comando DESCRIBE
Opa! A minha instrução CREATE
TABLE tinha um erro de digitação,
mas foi executada mesmo assim. O
SQL tem uma opção "desfazer"?
Não há exatam ente uma opção desfazer
no SQL, mas certam ente é possível
consertar erros.
Entretanto, você precisa, primeiramente, descobrir
exatamente que tipo de erro foi cometido, para
consertá-lo. Suponha que a tabela ema i 1 1 is te se
pareça com o seguinte:
e m a il l i s t
fcrst_name last name
Circule o que você acha que há de errado com esta tabela.
Algumaideia sobre como consertá-la? ''V
( J ?
0 O ' c
/ } I
cr/e e preencha um banco de dados
PESCRI0E revela a estrutura das tabelas
Para consertar um erro em uma tabela, é preciso, primeiro, achar o erro.
Mesmo que você não suspeite que haja um, nunca é uma má ideia verificar o
seu trabalhp^0~ contagio SQL DESCRIBE analisa a estrutura de uma tabela,
exibjuídSuma lista^a.nomes de colunas, tipos de dados e outras informações.
ome_da_tabela
na tabela de Elmer, teremos a seguinte instrução SQL:
Usando
DESCRIBE email list
Est« e o »on*« dô
tábefa Cuja desdriçao
Queremos ver.
Em «field"
(‘‘Campo'*) voôe
Cfttonira OS nomes
de dada tolunâ-
1 File Edil Window Help Graceland
mysql> DESCRIBE email_list;
+--- -------------I
-
--------:---------+--------+------+------------ +--------- +
| Field I Type i Null I Key | Default t Extra |
+
___________+----------------- +--------+
------ +------------+
--------- +
| first_naem | varchar(30) j YES I I NULL 1 I
t last_name | varchar{30) |YES ! INULL I I
| email i varchar^60) iYES | jNULL 1 I
3 rows in set^O.02 sec^Sv
vote
Pm Jype
("T ifo ” ) v,
ve os iipos
de dados ^ue
defihimos
f ara tadâ
Coluna.
• 0 que são aquelas outras
colunas: Null (Nulo), Key (Chave),
Default (Padrão) e Extra?
0 MySQL lhe permite definir
uma série de opções para cada coluna
da sua tabela. Essas opções controlam
opções como, por exemplo, se uma
coluna pode ser deixada em branco
ou se ela terá umvalor padrão. Nós
vamos explorar isso um pouco mais
adiante, quando essasopções se
tomarem maisvitais para a aplicação.
0 nao -faz. distinção entre
maiusdulas e mihusdulas no <
^u
e se venere
às palavras reservadas, tomo os tipos de
dados; por isso, vode poderá, às ve«s,
ve-!os esdriios em minÚsdulas.
n09 existem
p e r g u n ta s Id io t a s
r ■ Se eu já tivesse dados
armazenados na minha tabela,
eles teriam aparecido aqui?
í ^ : Não. DESCRIBE só lhe
mostra a estrutura da tabela, e não
os dados armazenados nela. Mas
não se preocupe, você logo verá os
dados da sua tabela... mas primeiro
temos de aprender como inserir
esses dados nela.
P Eu posso visualizar a mesma
estrutura usando o phpMyAdmin?
Sim. Ferramentas gráficas
como o phpMyAdmin lhe permitem
visualizar a estrutura das tabelas
através de uma instrução
DESCRIBE ou clicando em uma
representação visual da tabela.
Você é livre para escolher que tipo
de ferramenta deseja usar para
analisar suas tabelas.
você está aqui ► 123
APAGUE sua tabela
Eu consertei o erro de digitação e tentei
rodar a consulta CREATE TABLE novamente.
Não funcionou. E claro que eu não preciso apagar
primeiro a tabela que contém o erro... ou preciso?
o «we da cota*
dWtado f°"">
- °?s-
rTií^EdíM/Tindow Heíp Typo?
mysql> DESCRIBE email_list;
+------------ I------- “ -----
Field I Null 1 Key | Default | Extra |
f
^first naem))l varchar{30) | YES | | NULL |
[ last__riam? | varchar(30) | YES | j NULL |
I email | varchar(60) j YES | | NULL |
3 rows in set (0.02 sec)
Na verdade, precisa sim. Não é possível recriar uma tabela
com CREATE TABLE uma vez que ela já tenha sido criada.
U m a vez q u e você te n h a criado u m a tabela, ela n ão p o d e ser sobrescrita
através de u m a nova co n su lta CREATE TABLE. Se q u iser rec ria r a ta b ela do
zero, você te rá d e ap ag ar p rim e iro a existente, e co m eçar tu d o de novo.
N o SQL, o c o m an d o DROP TABLE é u sad o p a ra q u e se possa ap a g ar
u m a ta b ela d e u m b an c o d e dados. E le ap a g a a ta b e la e tu d o q u e você
tiver a rm a ze n ad o n ela. U m a vez q u e n ão ex istem d ad o s em u m a tab ela
recém -criad a, n ão irem o s p e rd e r n a d a ao apagá-la e criar u m a nova, com
f i r s t nam e escrito co rre ta m e n te .
e m a il l i s t
h W da -tabela e
gostaria de apagar
ba*do de dados-
0 d o m a n d o PRO? T A B U E
âfaga a 'tabela c bodos os
dados doivfcicics nela.
crie e preencha um banco de dados
Hwerestáprontoparaarmazenardados
Os comandos SQL CREATE DATABASE, USE e CREATE
TABLE foram usados com sucesso para criar o banco de
dados e a tabela de Elmer. Ele não poderia estar mais
satisfeito, a não ser que a tabelajá viesse preenchida com
os dados dos clientes. Esse é um trabalho para o PHP...
e lv is
0 ka*to âe dados c)vÍs_storc ion-tem
«ma úníta iabels, !ss£.
Legal. Com o banco de
dados e a tabela criados,
estou pronto para começar
a armazenar alguns dados da
minha lista de emails.
s to re
O
o
firstnam e M i m e liÜlltfIfIIIjfíijlí?
fjlllfj fíiitflllllliililfílitlifflffíj?
A
A Uela o rtiljs t £o«tetí de tó - to j» * d » » ^
«ad* <*e « dad« da Wa de « j** *r»»»ad«-
__ Ei, eu tenho uma cópia de Use a Cabeça! SQL
(ótimo livro, a propósito). Naquele livro, toda vez
que você mostrava o código de uma instrução SQL,
colocava um ponto-e-vírgula ao final dela. Por que
aqui é diferente?
Ficamos felizes de você ter gostado de Use a
Cabeça! SQL. A diferença é que, quando você fala
diretamente ao MySQL, é preciso colocar o ponto-e-
vírgula para que ele saiba onde a instrução termina.
Isso porque é possível emitir múltiplas instruções ao
MySQL, diretamente. No PHP, quando é usada função
mysqli_query(), você só executa um comando SQL por
vez, de modo que não é preciso usar o ponto-e-vírgula.
Mas não se esqueça de que você ainda precisa colocar
o ponto-e-vírgula ao final de cada instrução PHP!
existem
p e r g u n t a s i d i o t a s
? Se a minha tabela tiver dados e eu a apagar,
todos os dados serão apagados, também?
Sim, é verdade. Portanto, cuidado ao apagar tabelas!
■ Então, semmecisar modificar uma tabela que
já teriba^ládos, estou ferrado?
/x Yi Ei, ninguém é perfeito. Todo mundo comete erros, 
o SQL oferece a instrução ALTER para nos ajudar a )
Ddíficar tabelas existentes. Falaremos desse comando /
maíSsâdiante, neste livro. /
y
o script addemail.php
Crie o script "Adicionar Email" VbdC 3$<ara está a«ui.
Elmer precisa de um formulário HTML para coletar
nomes e endereços de email dos clientes. Uma vez
que ele tenha essas informações, precisa filtrá-las com
um script PHP e armazená-las na tabela e m a il_ lis t.
O formulário web (ad d em ail.htm l) requer três
campos de input (entrada) e um botão. A ação é a
parte mais importante do código do formulário, uma
vez que o seu trabalho é repassar os dados para o script
addem ail .php, que estamos prestes a criar.
© - •■
Crie um banca rfe-Juüuj» t. uniu ;
•tribale poro a lista de emuils.
 SC
V ^ad
Crie üm formulário web e um
script ^HP "Adicionar Email'1para
adicionar novos clientes à lista»
Q Crie um formufário web e um
script PHP “Enviar Email" para
enviar um email para a lista.
A
a
$
ê
oé o elemen-to H
ífc
&
M
&
E
ltfS
.C
O
M
C
o
n
e
C
-
X
ÃO -rormuiino E
r
í
t
e
r
y
o
u
r
f
l
r
s
t
f
l
a
m
eta«-™ „
H
T/V1
L ao sdvipt PttP
íadde^l.pHp)
prodessara os dados, "''Xe
*
*
»
;:'
s c t i o n = " a d d e r n a i l , p h p " >
<£ormmethod^ post action_
Cinput type- text íu , i>
‘í e s l. « — ■ / * * »
<input type- text m ^
<label f°r="email''>Email:</^ /><br />
</form>
</body>
/>
r
addemail.html
Os novos diienies podem se
dadasivav *a lista de email
de £lw*ev (ou s«Ja, serem
adidionados ao bando de
dados) simplesmente usando o
-rovwwlav-io web.
sdvipt addemâil
pKp é e^eduiado
|«|uando o -Çorwvulano
|c submetido, e o seu
ItvabalKo e prodessar
! os dados e adidíonav-
Odlien-te à lista de
emails ína tabela do
bando de dados).
elvis store email list
crie e preencha um banco de dados
0 script addemail.
php processa os dados do formulário Add Email
("Adicionar Email"). 0 script precisa filtrar os dados do formulário, conectar-se
ao banco de dados elvis_store e inserir (insert) os dados na tabela
email_l'ist. Ajude Elmer a escrever um exemplo de query SQL para inserir
um novo cliente, e depois use essa query para finalizar o código do script PHP.
EsúfCVâ â«ui um exemplo
de Consulta para ihserir
dados *a tabela de EUer.
.... Q ................................................
<?php
$dbc = a
$first name = S_POST['firstname’
^ tir s t_ n a iu tí - l * 1
...j
...... i..^..«v t
r
~? h 7 . *
...........
$query - '' i j/lfc A T u V .T .Q ....
mysqii_<
i_query ( C /
echo ’clients adicionado. f
?> í
addemail.php
você está aqui ► 127
solução do exercício
CICIO
§OLuÇck>
0 script addremaii.php processa os dados do formulário "Adicionar Email".
0 script precisa filtrar os dados do formulário, conectar-se ao banco de dados
elvis_store e inserir (insert) os dados na tabela email_list.
Ajude Elmer a escrever um exemplo de query SQL para inserir um novo cliente, e
depois use essa query para finalizar o código do script PHP.
INSERT. INTO emailJ is t JrtâmC, last^name, email)
l/Aí-WÈS ('Julian, 'Oates', julian^breaknedkpizia.tom')
A ^ i esta© os valores do
avray fJP O S T ^ue t<mktr*
âs in+ormaçoes submetidas.
A ^uevy INSERT de e*«mplo e
reesdrita tomo uma string PHP <
^u
e
depende dos dados do -formulário para
a inserção-
<?php
$dbc - ""Vs
or
^li_donnedt('data.makemeelvis.dom,( 'elmer*, ‘tbekinj, ‘elvis_jstoreJ
)
tonetiar tom o servidor AflyS^L server.');
diei'&rro ao
$firstjrt a m e = $_POST [’firstname ’];
flâ st^m e — f^POSTC‘lastname'3]
f email..=
■
. .................
5query =
= “fKSERT IfrTFO emaiMist £-first__name, last__nâme> email) 1
1
'V A ír^í? ílf^irst_l>ameJ
J'/la^^hàmÇj )fernâtl>
)U
j|..........................
mysqli^query( fdbdj f^wery )
die(*£rr© do adessar o bando de dados*)j
or
echo 1clicrite ■
adicionado -
wys^li_diose(fdbt);
addemail.php
Se ^uisessemos nos exibir a^ui,
poderíamos dolodâr um !mk de
volta para o nosso -formulário,
dom uma ta$ HTML <a>.
cr/e e preencha um banco de dados
T te S T O R tv e
Teste o formulário de “Adicionar Email”.
Baixe o código da página web “Adicionar Email” no site da Alta Books,
em w w w .altabooks.com .br. O código está na pasta c a p itu lo 0 3 . Ele
consiste do formulário web addem ail .htm l, uma folha de estilo ( s t y l e .
css) e duas imagens (e lv is lo g o .g i f e b la n k fa c e . jp g ).
Em seguida, crie um arquivo de texto chamado ad d e m a il.php e digite
nele todo o código da página anterior. Este é o script que irá processar
os dados do formulário web de Elmer e adicionar novos clientes à tabela
email_list.
Envie todos esses arquivos ao seu servidor web e abra a página addemail.
html em um navegador. Digite os dados de um novo cliente no formulário
e clique em Submit (Submeter).
Nao se esc^ue<p
de {rodar as
variáveis de
donexão ao
ba*do de dados
pelas suas
próprias.
$ iyisevÇâo do novo
elièivte a lista de emdil
c to»víirmada pelo
stvipi addemail-php-
Verifique se o cliente foi adicionado ao banco de dados emitindo uma
consulta SELECT em alguma ferramenta MySQL.
você está aqui ► 129
lápis solução
p^sgjxmte seu lápis
O f|||A 4 A Com a lista de Elmer começando a ser preenchida, ajude-o
VVIU yC All a escrever algumas consultas SQL que ele possa usar para
encontrar dados específicos dos clientes.
Selecionar todos os dados de clientes que tenham o primeiro nome Martin:
SêLECT FR0M e»aiM ist 1
VHBRE -first_name — 'Alartm
A estrela seleciona W a s as Ç stâ ‘ j f 3“1
* W ® * 6
colunas da tabela- “ ««
Clientes dujo primeiro nome sea
Martin.
Selecionar apenas o sobrenome de clientes qúe tenham o primeiro nome Bubba:
SELECT last_name FR0M emaiMist IíVHERE í írst__name —'Bubba;
................t _ .....................................................................................................
Somente a doluna last_«ame e
retornddâ nos resultados dâ donsulta-
Selecionar o nome e o sobrenome do cliente que tenha o
endereço de email ls@objectville.net:
S£L£CT íirs t name, last »ame FR0M email list WttERE email — IséSobjedtvillenet'
........ “..v " .......... ................ ...*........
Para espedi-fidar múltiplas dolunas de resultadosj vote
separa os nomes das colunas dom vtrgulâs-
■ s 
Selecionar todas as colunas dos clientes que tenham a  
primeiro nome Amber e o sobrenome McCarthy: » / 
/ 1
S£LECT # FR0M emaiMist WttERE first^name — 'A*»»ber AND Is s h jn d m e 'AldCarthy
A dlawula IVHERE pode ser realizada, mas
depende de varias ihíormâ^oes, neste daso a
odorrendia tanto de u» primeiro nome quanto
de um sobrenome-
/N
Ls
crie e preencha um banco de dados
0 outro lado da aplicapão de Elmer
Enviar mensagens de email para as pessoas na lista de Elmer
é uma tarefa semelhante à de adicionar as pessoas à lista,
porque ambas envolvem um formulário HTML e um script
PHP. A grande diferença é que, para enviar uma mensagem
de email para a lista, é preciso lidar com o conteúdo inteiro
da tabela eraail list, enquanto que o script ad d em ail.
php lida apenas com uma linha de dados.
^ Crie um bnnes de dados c uwo
tabela paro o lista do cmoHs-, :
Crie um foiiwuluiiu web e um
seript PHP "AdiUimui'/Snoi!”1
para
adicionar novos1elientea à liste.
^ Crie um formulário web e um
script PHP "Enviar Email" para
enviar um email à lista
0 -formulário Yíeb Enviar
Email permite a Elmer
deitar o assunto e o dorpo
de uma mensagem de email, e
depois envia-los para toda
a lista- ^
U-fa, -finalmente
checamos ao
último Passo-
itKTLiK method="post” ac^on="sendemaí 1,php">
<label fox=”subject">Subject of email :</labelXbr />
<input type="text" id=”subject" nam.e="subject" si2s="60" /Xbr />
<label for=”elvismail''>3ody of email:</labelxbr /> .
Ctextarea id="elvismail" nanie="elvismail" rows="8" cols="6Dn></textarea><br />
<input type="submit" name="submit" value="Submit" />
</form>
</body>
</html>
/ / ^ p a r a tada w
0 sdript
sendcmaílphp lc
as »*forma£oes
dos dliewtes nS
tabela, e e«v«a o
e»»ail de £1»er
Jf ação -form dispara o
sdript se«de»ail*pbp.
elvis store
T i i t p r i i l l i l l l l i l i l l l l i l l i S i i
Julian Oates
julian@breackneckpizza.com
Kevin Jones
jones@simuduck.com
Amanda Sanchez
sunshine@breakneckpizza.com
você está aqui ► 133
o script sendemail.php
0 funcionamento interno do script "Enviar Entail"
O script sendemail.
php precisa combinar dados de duas fontes diferentes para gerar e
enviar mensagens de email. Por um lado, o script precisa retirar os nomes e endereços de
email da tabela s e n d e m a il_ lis t do banco de dados e lv is _ s to r e . Porém, ele precisa,
também, obter o assunto e o corpo da mensagem digitados por Elmer no formulário web
“Enviar Email” (sendemail.
html).Vamos detalhar os passos da operação.
A Use o array $_po st para obter o assunto e o corpo da mensagem de email
do formulário.
Nada de novo aqui. Clicar no botão Submit do formulário sendemail.html para
enviar os dados para sendemail .php, onde nós os capturamos em variáveis com
uma pequena ajuda do array $_POST.
Execute uma consulta selec t na tabela email_list.
A função PHP mysqli__query () roda uma consulta SELECT para obter os dados da lista
de emails. Uma vez que queremos todos os dados da tabela, podemos usar SELECT * .
O
Acesse os dados do email no resultado da consulta.
Apenas executar uma consulta não fornece acesso aos dados. Nós precisamos
acessar cada linha de dados do resultado da consulta, para termos acesso ao nome,
sobrenome e endereço de email de cada cliente.
Recorra à função maii() para enviar um email a cada cliente.
Para enviar os emails, é preciso fazer um loop através de cada cliente
na lista de emails, o que corresponde a cada linha de dados nos
resultados da consulta. O loop que criamos aqui começa na primeira
linha de dados, depois passa para a segunda linha, e assim por diante
através de todas as linhas de dados obüdos pela consulta SELECT.
Nós paramos ao atingirmos o final dos dados.
0 sdsrip-fc
ptredisa
de dados
da tabela
e»aií iisfc.
cr/e e preencha um banco de o<
Em primeiro lugar, obtenha os dados
0 enderedo de email de
EUer e arma^nado
Nósjá estamos bem experientes em extrair dados de formulários no
PHP, portanto, o primeiro passo não traz nada de novo; basta usar a
superglobal $_POST para armazenar o assunto e o corpo da mensagem " "7*?
do email em variáveis. E vamos aproveitar também para armazenar o em un,a ^lâvei,
endereço de email de Elmer em uma variável, uma vez que iremos
precisar dele posteriormente, quando enviarmos os emails.
$from = 1
elmer@makemeelvis.com1
$subject = $_POST['subject1];
$text = $ POST[1elvismail'];
pa*ra saibamos
exaiamen-te onde ele
esta, easo predisemos
odiíidá-lo.
Os dados do íormuiário pava^a
ensaiem de email tawbem sao
armazenados em variável-
Os demais dados requeridos pelo script se n d e m a il.php são extraídos
do banco de dados MySQL de Elmer. Para obter dados dos clientes a partir
da tabela e m a il_ lis t e colocá-los no script, precisamos de uma consulta
SELECT. Ao contrário do que fizemos anteriormente, quando usamos o
terminal MySQL para emitir um SELECT e olhar os dados da tabela, desta
vez iremos fazê-lo no script se n d em a il.php, e iremos emitir a consulta com
m y sq li_ q u ery ().
A variável f^uery armâzenâ a
r donsul-ta S$L na íormâ de uma
strift^ de ieitfeo-
$query = "SELECT * FROM email
Eis a nossa donsul-fca, «^e
seiedioha -todas as dolunas
da -tabela email list-
list";
$result = mysqli_query ($dbc, $query);
enetoia a donsulia usando uma
vanave! de donexao (fdbd) e uma sírina de
donsulta (?«iuery). ___ _______
Entao, tudo o que temos de
fazer é usar os resultados da consulta,
presentes na variável $result( certo?
£ predíso Kaver uma done*ao
domo o bando de dados para <ue
a donsulta possa ser sutaeüda
- OS de-talhes da donexao sao
armazenados na variável fdbd-
Não, a variável $result, na verdade, não contém quaisquer dados.
Se você tentar ecoar a variável $ r e s u lt diretamente, verá algo como:
Resource id #3
A variável $ r e s u lt armazena um número de identificação de um recurso
MySQL, e não os dados, propriamente ditos, que são retornados pela consulta. O
que acontece é que o servidor MySQL armazena, temporariamente, os resultados
da sua consulta e fornece a eles um número de recurso para identificação. Você
então usa essa ID do recurso com a função PHP m y sq li_ f e tc h a rra y () para
obter os dados, uma linha de cada vez.
você está aqui ► 135
g-
C
O
d) lchjarrayO para obter os resultados da consulta
etch_array() obtém os resultados da consulta
Uma vez executada a nossa consulta, podemos obter os resultados com a variável $ re s u lt.
Essa variável é usada com a função m ysqli f e tc h a rra y () para se obter os dados da
tabela, uma linha por vez. Cada linha de dados é retornada como um array, que podemos
armazenar em uma nova variável chamada $row.
^ — -------------- Ésèa função obtém uma ImKa dt
dadosâ partir dos resultados da
$row = mysqli_fetch__array ($result)
A variavel fvow é um array ^ue,
inicialmente, armazcna a primeira
linha de dados dos nossos resultados.
Consuita, e a armazena em um array.
Cada consulta £<$L tem o seu próprio
numero de IP, ^ue é usado para se tenha
acesso aos dados, associados aos seus
resultados.
Cada vez que este código é executado pelo servidor web,
uma linha de dados dos resultados da consulta é armazenada
no array $row. Repetidamente, você solicita que a função
m y sq li_ f e tc h a rra y {) seja transmitida através de cada
linha dos resultados. Assim, as três primeiras chamadas à
função m y sq li_ fe tc h _ a rra y {) obtém as três primeiras
linhas de dados da tabela, armazenando cada coluna da
linha como um item no array Srow.
Aíunçãpm/s^lL
íetcfc_arrayO
E tr m a z e n a u m a l ï n t a
d e - d a d e s e m U H ] n iT i'K .
em ail_JLí-s t
$ ro w = mysqli_fetch_array($result);
$row — mysqli_fetch_array(
$result);
$row = mysqli_fetch_array($result) ;
Cada Coluna de dados t armazenada
Como um item no ârray frovi.
A variavel fvow t
deíinida Como um
array Contendo tre s
elementos, um para
cada uma das tres
colunas de dados.
crie e preencha um banco de c
— ^Aponte seu iápis
Como um teste para nos certificarmos de que realmente conseguimos
obter os dados dos clientes, termine este código PHP para exibir o
primeiro nome, sobrenome e endereço de email de cada cliente
presente na tabela email list, uma linha de cada vez.
$query = "SELECT * FROM email_list";
$result = mysqli_query($dbc, $query);
$row = mysqli fetch array($result);
£c
i _ r 1 "í v
'
......
você está aqui ► 137
± solução
0
)
&
to
nteseu lápis
Solução conseguimos obter os dados dos clientes, termine o
K* Como um teste para nos certificarmos de que realmente
Solupão
código PHP para exibir o primeiro nome, sobrenome e
endereço de email de cada cliente presente na tabela
e m a il l i s t , uma linha de cada vez.
$query = "SELECT * FROM email_list";
$result = mysqli_query($dbc, $query);
$row = mysqli_fetch_array(
$result)
;
J v o w C f . 1*. ' :*. fvov/C'cimairj . '<bv />';
l fr. fv-csui^j
tto jVovjt'-Pirst^ttâme'3 •1' ■
fv-oY/Clart^pâiwc J •' : - fv-ovíCemailJ ■
<bv- /> ',
frow —mys^li^íc-tí-h^âvrayífresul-ü;
cdKo■firrt^name'J . 11 . frowClast^nâme^ . ' : 1 . fy-oyíC'cwail 3 • '<br />';
fro>/ — mys^l etdb_^array(?
v-esulO ;
efibo fyowr-Pirst^naiwe1
^ . ' ' . y Você deve estar brincando.
i » y * Repetir as mesmas duas linhas de código sem
•?.???. rr. parar é, provavelmente, a coisa mais estúpida que
eòho /ro w fíiw t nân»e‘3 'L _ eu v‘- £ claro que tem de haver uma maneira
............................. .............melhor de fazer isso.
frov/ —
edbo f
flrov; — m^BMp^^BtnrâyCfreShl^j
cdho . fvowClast . 1 : * . frotiCcw^il^ • '<bv- />*;
.............. ................................................."""*
..........................................................
froY/ =•
' - frowriasi nâim
e'3 . frowFemaiH - l<br />'j
Existe uma maneira melhor - nós
precisamos de um loop.
Um loop é um mecanismo da linguagem PHP que
repete um pedaço de código até que uma certa
condição seja atendida, por exemplo, até se esgotarem
os dados. Dessa forma, o loop é capaz de analisar,
ciclicamente, cada linha de dados de um resultado de
consulta, executando qualquer ação que quisermos,
em qualquer linha.
crie e preencha um banco de dados
Loop com um WHILE
loop usando o w hile é umlofip^éspecificamente voltado à
tarpfaHy-^ep^rir o ródigrrpfííyíamo uma, determinada condição
esteja sendo atendida. Por exemplo, você pode ter uma variável
em uma aplicação de serviço ao cliente chamada $got_
cus tome rs ($ te m _ c lie n te _ e sp e ra n d o ), que serve para
registrar a informação sobre o tempo de espera para a realização
dos serviços, por pate do cliente. Se $ te m _ c lie n te _
esperando estiver definida como tr u e (“verdadeiro”), você
sabe que ainda há clientes para atender, então você poderia,
consequentemente, chamar a função n ex t custum er ()
(próximo c l i e n t e ) para ajudar o próximo cliente da fila. Eis
como poderíamos programar isso usando um loop w hile:
Uni loop wfcíle
f e p e t e o c o j i g o
enquantp uma
condição estíVet
s e n d p a t e n d id a .
Enquanto tivermos Clientes» -n
C
ontinue o loop- ^
while ($got custom ers) {
next customer () ; Este e o Codijo í^ue
e e*eCutado a cada
iteraçl© do loop.
* Colocar o cód'150do U p dentro
de chaves IKe permite executar
quantas linhas de Cod*5° *luiser'
Quando verificamos “se há mais clientes a atender”, estamos testando
uma condição. A condição é o código entre parênteses, e ela sempre
apresenta uma questão que resulta em uma resposta sim/não. Se sim,
ou true (“verdadeiro”), então a ação é realizada. Se não, ou false
(“falso”), então terminamos o loop.
Quando chamamos next_custom er () e passamos a atendê-lo,
estamos realizando uma ação. A ação é o código dentro das chaves, e
é repetida enquanto a condição permanecer tru e . Se a condição
se tornar f a ls e , o loop termina e a ação não é mais repetida. Eis o
formato geral de um loop usando o w hile:
Um loop while nos
permite fazer loop
atraves dos clientes ate
<y*e náo sobre nenhum
para atender.
A Condição de teste sempre
resulta em verdadeiro ou falso—
continuar olhando (verdadeiro)
ou parar o loop (falso)-
while (condição d e_ teste) {
ação
A açao do loop ©Corre uma
vez. a cada passada do loop.
CÉRÉSRO
Como você acha que um
loop while poderia ser
usado na tabela em ail_
l i s t de Elmer?
você está aqui ► 139
como whileQ funciona
Loop através dos dados com while
Aplicando um loop com w hile para os dados do email de
Elmer, acessarmos os dados, uma linha de cada vez, sem duplicar
nenhum código. Nós sabemos que m y sq li_ f e tc h _ a rra y {)
é capaz de tomar uma linha da tabela e colocar os valores
das respectivas colunas no array $row, mas a função, sozinha,
não passa através de todos os nossos dados —
ela armazena a
primeira linha e então para. Um loop w hile pode chamar
m y sq li_ f e tc h _ a rra y {) para atravessar todas as linhas
dados do resultado, uma de cada vez, até chegar ao final.
while (
p
A to*diçao do loof
to» víVile e o valor ^
retornado pela -funça©
»
v
>
y
s«
^
!i_-fettb_arrayO; «ue
t interpretado domo trv»e,
se houver dados disponíveis,
ou -faUe, se os dados
tiverem acabado-
A ad ão
do loop C
executada
w
n
êvez.
a cada
Geração.
A aça© do loopj^onsiste
de uma instrutao etbo
ey*ejunta os dados da
linha, doUanáo uma
quebra de tmba ao Vmal
primeira
passada do loop,
o array fro*/
armazenara a
primeira linka da
tabela em ailjist
$row
eioail—•
list
/o°Ps. Na .'seaunda passada do loop, o array
frow armazenara a segunda linhâ da
tabela emaiMist- esta vendo o padrao?
cr/e e preencha um banco de dados
A instrução edbo dentro âo
loop while e*trai os dados do
array frow e cx.*b« o dontcwdo
formatado tomo HTML.
+ ' 1 + v
Q
■
4
^
<
®
r
"y
Uma <ueWa
ÜTML- dolota
tada Whs de
dados em urr>
a
Vm
Ka prepria
pá^ftâ results™*-
'<br
$row[1first_name'
] $row[
'last__name1] $rowt'
email[]
t
A dhave usada para aícssar o
elemento do array deve te r o
mesmo home <ue uma dolunâ-
0 loop wfcile
p e rp a s s a 9 s d a d o s
datakela, lfnta
por linta. Quandp
nap iíPuVeí mais
llnfcas de dadps,
ele Çlnallza a
c o n s u lta .
Julian Oates ; julian@breakneckpizza.com
Kevin Jones : jones@sirauduck.com
Amanda Sanchez : sunshine@breakneckpiz2a.cam
Bo Wallace : bo@bOttOmsup.com
Amber McCarthy : amber@breakneckpizza.com
Comae Hurst : churst@boards-r-us.com
Joyce Harper : jcyceharper@breakneckpizza.com
Stephen Meyer : meyers@leapinlimos.com
Martin Wilson : roartybaby@objectville.net
Walt Perala : walt@mightyguraball.net
Shannon Munyon : craftsmanSbreakneekpiaza.com
Joe Milano : joe_m@starbuzzcoffee.eom
Ka secunda passada do loop, as
instrudoes edho e*ibem uma
outra se«uendia de te*te, mas
dcsta vez. sac usados os dados da
secunda línKa da tabeia
$row[’first_name'
] $row['last_name1] $row[’
email'
3
Na verdade, nao se usa o smal de mais
para juntar duas strings —usa—
se o
operador ponto-
A dada passada do loop, os valores armazenados
no array frow se modi-fidam para refletir a linHa
atual. Os nomes das doiu*as sao usãdos para se
adessar os valores do array-
você está aqui ► 141
não existem perguntas idiotas sobre whiíeQ
nqo existem
f e r g u n t a s i d i o t a s
£ I Comoexatamenteo loopwhilesabequedeve
continuar olhando? Quer dizer, o loopwhileé controlado
por uma condiçãoverdadeiro/falso,e
mysqli_fetch_array () retoma algumtipo
de IDdo recurso, que é armazenado em $
r
o
w
.
.
.Isso
certamente não se parece com uma condição de teste
verdadeiro/falso.
K : Bemobservado. Ocorre que o PHPé bemliberal no
que diz respeito ao modo comoele interpreta a condição
“verdadeira”. Resumindo, qualquer valor que não seja zero
(O )o u fa ls o é considerado como verdadeiro, em uma
condição de teste. Assim, quando a função m y s q li_
f e t c h _ a r r a y () retoma uma linha de dados, o
array $ ro w é interpretado como verdadeiro, umavez
que não está definido como 0 nem f a ls o . E, uma vez
que a condição é verdadeira, o loop segue emfrente. O
interessante é o que acontece quando não há mais dados
disponíveis- a funçãom y s q li_ fe tc h _ _ a r r a y ()
retoma f a ls o , o que encerra o loop.
Então eu posso controlar um loop while com
qualquer tipo de dados, e não apenas valores
verdadeiro ou falso?
K : Correto. Mas tenha em mente que, nofim das
contas, o loopwhile está interpretando os dados como
verdadeiro ou falso.Assim, a coisa mais
importante a se entender é o que constitui verdadeiro
ou fa1so no que diz respeito àinterpretação de outros
tiposde dados. Ea resposta simplesé quequalquer coisa
diferente de Ooufalsoé sempre interpretada como
verdadeiro.
" P i Oque acontece com o loop while se nenhumdadofor
retomado pela funçãomysqli_fetch_array() ?
Se a consulta não resultar em quaisquer dados, então
a função mysqli_fetch_array () retoma
falso.E issofazoloop while nunca chegar ao código
da ação, nem mesmo uma vez.
? Então é possível ter um loop que nunca
faz repetições?
H : É, sim. Tambémé possível ter umloop que nunca
termina. Considere este loop while:
while (true) {
Istoé conhecido como loop infinito, porque a condição de
teste nuncafaz o loop terminar. Loops infinitos representam
algo muito ruim.
PONTOS DE BALA
Um banco de dados é um Container
para armazenar dados de uma forma
altamente estruturada.
As tabelas armazenam dados em um
padrão de colunas e linhas dentro de um
banco de dados.
O comando SQL create DATABASE
é usado para que seja criado um novo
banco de dados.
O comando SQL c r e a t e t a b l e cria
uma tabela dentro de um banco de dados
e requisita informações detalhadas sobre
as colunas de dados dentro da tabela.
Você pode apagar uma tabela de um
banco de dados com o comando SQL
DROP TABLE.
AfunçãO mysqli_fetch_array (
)
obtém uma linha de dados a partir dos
resultados de uma consulta ao banco de
dados.
Um loop while repete um pedaço de
código PHP enquanto uma condição de
teste continua sendo atendida.
Q Crie uro b<meo de dodos e uma
tabela papa a Ifata de emails.
Q Cwc um formularia web e um
-script PIIP "Adfdwim..Dnuil" para
adicionor-novos clientes fl
^ Crie um formulário web e um
script PHP “Enviar Email" para
enviar um email para a lista.
? Não sc esqueça? ainda
temes este úittmo Passo
para terrnínâv.
crie e preencha um banco de dados
ímãsdeGeladeiraFHF&MySoL
Use os ímãs abaixo para completar o código do script "Enviar Email" de modo que Elmer
possa começar a enviar emails para a sua lista de clientes. Para refrescar sua memória,
eis aqui o modo como m a il () funciona:
m a i l (to, su b ject, msg, 'F r o m :' . fro m ) ;
<?php
$from = 'elmer@makemeelvis.com';
 *
$subject = * A sxcw.to
$text =(/**■ _ J
. _
$dbc = mysqli connect('data.makemeelvis.com', 'elmer', ’theking', 'elvis_store'
or die('Erro ao se conectar com o servidor MySQL.');
$query = ''SELECT * FROM email_list" ;
$result = mysqli_query ($di>c, $query)
or die('Erro ao consultar o banco de dados.’);
while($row = mysqli_fetch_arrayf$result)) {
$first_name = $row['first_name’]
;
$last_name = $row['last_name'];
$msg = "Dear $first_name $last_name, n j[
$to = 4 í í f P 1
. .a ..w.*...............
mail{ ^ r t: ' -íi $c$
echo 'Email sent to: ' . j f . 1<br />';
}
mysqli_close($dbc);
'From:
?>
sendemail.php
script sendemaiLphp finalizado
ímãs cie- GaKJeira FBF & M /SQL - Solução
Use os ímãs abaixo para completar o código do script "Enviar Email" de modo que Elmer
possa começar a enviar emails para a sua lista de clientes. Para refrescar sua memória,
eis aqui o modo como mail () funciona:
Ã
Certifi^ue-se de trodâr
isto a*ui pelo seu proprio
enderedo de email-
mail(to, su b je c t, msg, 'From:! . from );
<?php w
Çfrom = 'elmergmakemeelvis.com';
0 dampo referente ao assunto
dhama~se ttsubjedtw
, <ue t o mesmo
nome usado para adessá-lo no arrav
ÍJC Z T
$dbc = mysqli_connect('data.makemeelvis.comr, 'elmer1, ’theking', 'elvis__store'
)
or die ('Erro ao se conectar ao servidor MySQL.')í Q de email t
Squery - "SELECT * FROM ewil.list"; M f"?0 Í ° (<
*
r"
"
>
l
á
r
'
K’
$result = mysqli_query($dbc, $query) denominado e
l
v
i
s
m
a
i
l •
or die('Erro ao consultar o banco de dados.’); ^ ,
6 d» «.ait 0 ^ t #
while ($row = mysqli fetch array (Sresult) ) { s J ° "
'
'
C
t
t
S
â
a
e
»
* S
l
?n .
$first name = $row[ ’ firstname'] ; f d fundão mâilO, iun-fvi / ° ^
$last name = $row['last name’]; 'Y Kfrom de °*
* °
$msg = "Dear $first_name $last_namern
^$to =
echo 'Email sent to
mysqli_close($dbc);
1From:1
il'cbr
?>
0 email desti*tario, assunto da mensagem e
dorpo da mensagem, s^° passado nâ fund3o
mailOj dom o endereço ”à t tim er.””
A doluna email do bando de
armazena os enderedos
dos dlientes, aos ^uais a
mensagem deve ser enviada.
i n
jla d o s
sendemail.php
Uma mettle™ de
donfirmajão é enviada
para a pagma, dom o
endereço de dada dliente
â c^uemfoi enviada a
mensagem-
£m gerab não e uma boa
ideia, em termos de segurança,
informar o <
^ue o usuário digitou
diretamente para a função
mailO sem faz<r, antes uma
verifidaçao primeiro- 0 Capelo
y mostrará algumas tédnidas
para resolver este problema-
crie e preencha um banco de dados
TfeST ORfve
Envie um email para a lista usando o formulário “Enviar Email”
Baixe o código para a página “Enviar Emairno site da Alta Books, www.
altabooks .
com.br. Está na pasta capitulo03. Da mesma forma que a
página “Adicionar Email” que você viu anteriormente, este código consiste
de um formulário web em sendmail.html, uma folha de estilo (style.css)
e algumas imagens (elvislogo.
gif e blankface.jpg).
Crie um arquivo de texto chamado sendmail .php e digite nele todo o
código da página anterior. Envie todos os arquivos para o seu servidor web e
abra a página sendm ail .htm l em um navegador. Digite uma mensagem de,
email no formulário e clique em Submit.
Tenba em mente
<Y
*e o scw
enderedo de
email preíisara
estar «a
lista, para <
<
*e
voóe reteba 3
mensagem.
Você tem email... de Elmer!
Finalmente, Elmer pode enviar os seus emails anunciando promoções de QueroSerElvis.
com (MakeMeElvis.com)para todos os inscritos na sua lista de email, usando o seu novo
formulário e script PHP de “Enviar Email”. Ele pode, também, usar o output do script para
confirmar que cada mensagem foi enviada com sucesso. Cada vez que o código no loop
w hile do script é executada, ele vê “Email enviado para alguem@algumlugar.com”, com
os endereços das pessoas no seu banco de dados. O resultado final é mais exposição para
os seus produtos e, para o bem ou para o mal, mais sósias de Elvis Presley por aí!
0 sdript J£end U a il
Vendi todo
o meu estoque de
sapatos de camurça
azuis... estou rico!
realmente envia mensagens
para os endereços
presentes no banto de
dados, portanto duidado
ao ía z ^ r alterações *ele!
ImaSingtistrosífàefs.
Subjectofemai1'
;BisS
a*«?
Email sent to:julian@breakneckpizza.com
Email sent to:jones@simuduck.com
Email sent to: sunshine@breakneckpizza.com
Email sent to: bo@bOttOmsup.com
Email sent to: amber@brealweckpizza.com
; .
.
.
.
.
.
.
.
.
.
.
----- ------ -v --
findyofsmall: _____— —---- -
— tmajl sent to: amber@brealwerkpizza.r.
"Bílíe this week« Genuine.hors Email sent to: chum@boards-r-us.com
Email sent to:joyceharper@breakneckpj
—oriSy -days Email sent to: rnevers@leaninTinn^ir
t ” ? I
jv;^**aiyti^uitraK
necK
pizza.coi
Emaü sent to: meyers@leapinlimos.com
Email sent to: martybaby@olgectville.net
Email sent to: walt@mightygumball.net
Email sent to: craftsman@breakneckpizza.com
Email sent to:joe_m@starbuzzcoffee.com
Email sent to: bnjce@chocoholic-inc.com
Email sent to: pr@honev-doit.cam
Email sent to: bertieh@objectville.net
Email sent to: gregeck@breakneckpizza.com
Email sent to: wilmawu@starbuzzcoffee.com
Email sent to: samjaffe@starbuzzcoffee.com
Email sent to: ls@objectville.net
EmaUsent to:J>sliakes®mightygumball.net
você está aqui ► 145
nosso aplicativo precisa da funcionalidade delete
Às vezes, as pessoas querem sair
Como acontece com qualquer nova empresa, existem obstáculos no
caminho. Parece que alguns fãs de Elvis pularam do navio do Rei e
querem sair da lista de Elmer. Ele quer atender a esses pedidos, mas
para isso é necessário remover os clientes do seu banco de dados.
Caro Coiegg Ra
^nbora eu a' brador'
Passos c/e dan da aprec'e os
estou 7?n?a cfo e/w_ s_
habHidades3n !ncr>veis
f me^ n a e Z ^ n°-A^ v a i
Caro Elmer,
Eu não desejo receber mais
emails sobre promoçoes da sua
loja. Ainda sou fã de Elvis mas
não tenho mais tempo para
im itá -lo . Por favor, me retire da
lista. Meu email e cbriggs®
boards-r-us.com.
Obrigado,
Um Ex-lmitador
Prezado Senhor,
Após várias reações alérqicas
as costeletas de genuínoS
de cavalo, decidi que tentar me
‘S ”eE^ad E'VÍSnà0éamin^
prara .Eu adoro capas bonitas,
mas as costeletas são um pouco
de exagero. Por favor, me retíe
da sua lista de emails.
Um Abraço,
Brian Powers
bp@honey-doit.com
£W er»âo está ™ » V íe liz . e*»
pevder dlie*ies, mas atender
aos pedtdos de vewoçao da sua nsta
de emails.
E um fato na vida do MySQL - às vezes você precisa remover
dados do seu banco. Elmer precisa atualizar a sua aplicação para
poder apagar usuários da tabela e m a il_ lis t.
Escreva aqui os novos componentes da aplicação que você acha que
Elmerirá precisarpara implementar o recurso de “Remover Email”:
É, parece que nem todo mundo
tem o talento para imitar o Rei.
Preciso retirar estas pessoas da minha
lista, para que possa me concentrar
nos verdadeiros fãs.
, ......... ......'S. r. 2*.
crie e preencha um banco de dados
Removendo dados com PEIETE
Para apagar dados de uma tabela, precisamos de um novo
comando SQL, DELETE. Usaremos DELETE em um novo
script “Remover Email”, o qual apagará dados dos usuários
da lista de emails de Elmer. Na verdade, precisamos de um
novo script e de um novo formulário web para ativá-lo...
mas antes de tudo precisamos da função DELETE.
O comando SQL DELETE remove linhas de dados de
uma tabela. Isto o toma um comando que você deve usar
com muito cuidado, uma vez que ele é capaz de eliminar
uma tabela inteira, e todos os seus dados, num piscar de
olhos. Sabendo disso, eis aqui a forma mais perigosa de
DELETE, que apaga todas as linhas de uma tabela.
-grtc tim-bonco de dodói e uma
tabela para a lista de emails.
eitviop om-ewõil-parq-qHtstq.
Crie umformulário web e um
script PHP "Remover Email," parc
remover clientes da lista.
o no*»»e dê
nome da tabela tsbclâ da <
^
u
a
l v
<
?
d
<
r
— “ deseja apagar linhas.
Se«» nenKum outro ^ualifidador, _
_ S
o domâindo esvazia i — ~ ^
to » p le w te a tabela, Entoo nao podemos nunca
vCn,ov»do S 5SS à ie ! ( apagar algo de uma tabela
^ sem apagar tudo?
Não, de jeito nenhum. DELETE pode ser usado
especificando-se uma determinada linha, ou linhas, para
serem apagadas.
Para especificar precisamente a linha - ou as linhas - que se deseja apagar
com DELETE, você precisa adicionar uma cláusula WHERE. Se você se
lembra de como a usamos com o comando SELECT, WHERE tem a mesma
função aqui: permitir que você isole linhas específicas em uma consulta.
Parede «ue predisai*o$
de um wovo Passo...
às vezes os projetos
prédisant se mod»f*dar/
[~ ^Aponte seu lápis
Suponha que Elmer tenha 23 clientes cujo primeiro nome
seja Anne, 11 clientes cujo sobrenome seja Parker, e uma
cliente com o nome Anne Parker. Escreva abaixo quantas
linhas de dados seriam apagadas por cada uma destas
consultas.
1 1
DELETE'FROM email list WHERE first name - ’
Anne’; .....
DELETE FROM email_list WHERE first_name = 'Anne' OR last_name = 'Parker';
DELETE FROM email list WHERE last namS = Parker; j /S /— i
i
—
■ P
você está aqui ► 147
DELETE com WHERE
ponte seu lápis
Solução 5uP °nha que Elmer tenha 23 clientes cujo primeiro nome
seja Anne, 11 clientes cujo sobrenome seja Parker, e uma
cliente com o nome Anne Parker. Escreva abaixo quantas
linhas de dados seriam apagadas por cada uma destas
consultas.
DELETE FROM' email_list WHERE first_name = 'Anne1;
DELETE FROM email_list WHERE first_name = 'Anne' OR last_name = 'Parker1;
^
DELETE FROM email list WHERE last name = Parker;
o
'ft 0 soWe*or*e *ao esta
entre aspas, portanto, nenbuwa taba
e apagada - todos ©
s valores de
tento preèisam estar entre aspas-
Use WHERE e PEIETE para apagar dados específicos
Usando uma cláusula WHERE com o comando DELETE, nós especificamos algumas linhas
para serem apagadas, em vez de tudo que houver na tabela inteira. A cláusula WHERE
permite que nos concentremos apenas nas linhas que desejamos remover, neste caso um
dos clientes de Elmer que pediu para ser retirado da lista.
DELETE FROM email_list
WHERE |bifi = >pr@hon
0 honte de
w
*»a íoluna (fô
tabela
Ö valor à ser proíurado.
A cláusula
Esta parte da dliwsula WHERE W H E R E lilf llt c t
realiza um teste e» todas as
lihKas, para ver «uais atende» ao ct CPTlSUít£ t7 cl&
« I« - « tá * « )» p ro d u to . ç £ o c o
O teste propriamente dito, dentro da cláusula WHERE, realiza uma , * lo 1
comparação que é executada em cada linha da tabela. Neste exemplo, ctS IÍÍIp h S
o sinal de igual (=) testa cada valor da coluna em ail para ver quais e c í£ l Cc^S dei
linhas são iguais a ”p r@ honey-doit. com". Se o valor da coluna *
em ail bater com o que está sendo procurado, então a linha em ^ p o lc U
questão é apagada.
Escreva aqui por que você acha que a coluna email é usada na
cláusula WHERE, e não first name oulast name:
.j.O... :> . v . ..J L
A
. . . ....... ri..
.
4.
.
.
.
ês/y^tS..
.
crie e preencha um banco de dados
Minimize o risco de apagamentos
acidentais
E importante entender que, embora qualquer coluna possa
ser usada em uma cláusula WHERE para selecionar linhas, há
um motivo muito especial para termos escolhido a coluna
email para a consulta DELETE de Elmer. Considere que,
se mais de uma linha atender àcláusula WHERE, todas as
linhas que também atenderem, serão apagadas. Assim,
é importante que a cláusula WHERE de Elmer indique
exatamente, a linha que deve ser apagada.
Estamos nos referindo, aqui à unicidade. É razoavelmente
seguro assumir que, entre os endereços de email da tabela
email list, não haverá dois emails idênticos, enquanto
nomes e sobrenomes não forem detectados como únicos.
Você não vai querer criar uma cláusula WHERE que procure
por “Pat” na coluna first__name para apagar um único
cliente - você acabará apagando todos os clientes chamados
Pat! E por isso que a cláusula WHERE de Elmer tem de
ser cuidadosamente elaborada, de forma a procurar algo
bastante específico, na coluna email.
DELETE FROM email list
WHERE
Uma clausula
WHEflE em uma
insfrução DELETE
lfce petm ite-in d icar
a línha c
jue V^ce
cju e r v e m 9 V er.
A eoMvlta Í)S u E T £
re»*>ov€ esta |mH
â do
bândo de dàdos... p jrj
nunda mais ser vista^
email = ’
pr@honey-doit.com'
email
Usar d doluna email nâ
eláusula WHERE ajuda a
estabeleder a unididade
e 3 reduzir o risdo de
se apagar uma linba
adidentalmente-
Se -tivéssemos usado firs t
nôme na dláusuia WHERE, em
vez. de email, este usuário
teria sido, adidentaimente,
deíetado. V .
mysql> DELETE FROM email_list WHERE email = ’
pr@honey-doit.com ;
1 row deleted (0.005 sec)
O R t v e _______________________
Teste o comando DELETE no banco de dados de Elmer.
Inicie uma ferramenta MySQL e emita alguns comandos DELETE para
apagar linhas individuais da tabela e m a il_ lis t, com base nos endereços
de email dos clientes. Certifique-se de incluir uma cláusula WHERE em
todas as instruções DELETE, para não acabar, acidentalmente, deletando a
tabela inteira!
test-dríve o comando DELETE
O comando d e l e TE é bem útil, mas o ideal
seria apagarmos linhas de dados usando um
formulário web e umscript PHP, certo?
Correto. Apagar usuários manualmente,
com consultas individuais, não é a forma
ideal de se gerenciar uma lista de emails.
Já que Elmer, inevitavelmente, irá se deparar com
usuários que desejarão ser removidos da sua lista,
faz todo o sentido futuramente, desenvolver uma
interface web para a remoção de usuários da lista. Um
formulário web HTML e um script PHP resolvem o
problema,juntamente com uma consulta DELETE
FROM auxiliada por uma cláusula WHERE...
crie e preencha um banco de dados
Elmer criou um formulário web (removeemail.htmi) para apagar clientes
da sua lista. Só o que o formulário está aceitando apenas um endereço de
email, o qual é digitado em um campo chamado email. Complete o código
do script removeemail .php que é chamado pelo formulário para executar
cada remoção de usuário.
tfhamâ-se ‘ email" Enterãnem
ailaddress» rem
ove.
V Email address:
Cliôôr no boiao
Cftvia o -formularioj r>
5
- N
+cr»a de uw
>
a vc<ws'tdao
POST, ao s t ú f i PttP.
removeemail.html
<?php
$dbc = mysqli_connect(1data.makemeelvis.c o m ', 'elmer', 'theking', 'elvis_store'
)
or die(’Erro ao se conectar com o servidor MySQL.’}
í & * A . ~ % £ $ $ L L  â r . s  . 2 l ............ ........................................................
$. .....W .E !?.É £................
I ■
■
^
I...../
* I i f • r~
C-C .TiQ. .è k 1 ........ f__ . - r ? è . i.!......... : .............o .5 _j
’
/ ' T ‘
mysqli_close($dbc)
?> removeemail.php
você está aqui ► 151
o script removeemaii.php finalizado
Elmer criou umformulário web (removeemail.htmi) para apagar clientes
da sua lista. Só o que o formulário está aceitando apenas um endereço de
e email, o qual é digitado em um campo chamado email. Complete o código do
ç)OLuÇãO script removeemail .php que é chamado pelo formulário para executar cada
remoção de usuário.
dhama-se email".
Clidar n©botao M
Removew
envia o formulário, «a forma
de uma requisição POST, 3o
sdript PHP-
Os dados do formulário
presentes em f__P0ST s3o
armazenados em uma variavel,
e depois usados na donsulta
p e l b t e .
, , t  j Cuidado tom esta* aspas
?email — f POSTremail 3, y [ ^ simples e dujlas a®|w!
aspas duplas fitam cm
, .................. ’7'*v f torno "dif tôda ‘3r donsulta
f^e ry - ^ i l - lfe r^il'w
; / ç as simples fidâm
mys«|i queryí/dbd, fuery) ew k *""0^
...........t...............................................................................................d i’é^ail arma«y^do- e**
or dief'Erro ao donsultar o bando de dados'); few?jl
................................................................. demais ,do»ifi»:tt»ar-o-..................................
edho ‘Client? removido: 1. [email; ^ **"& ****> prindipaimente
................................. ................................. ^ ^ ^ tra tâ -d á V e m 0
dão'-
de dados do bando. *
Kão se esqueça de fedhar a
done*ão dom o bando de dâdos
te
; ............0
removeemail.php
crie e preencha um banco de dados
U-(WPmâWntc
tcrminâmosl
Crie um bonco de dados e uwo----
tobcln piara a lista de emails.
0 Oie um formutáriu web e um
æript PMP "Adiciurórt»uíl" [xuxi
adisipnarn cvgs-cliGrrtes o lista.
^ Grie um formularia wcb-e um -
aeript FHP ”&w»ai*Email" para
onviar um email à ligta.-----
-Q — CpÍo um-formuiório web e um ■
■
■
scmpt PMP”Romovan Emcit“ p«po
pomoven cliontas do lista.
TfeST ÛRIVE
Remova um cliente da lista de emails usando o formulário
“Remover Email”.
Isto está começando a lhe parecer familiar, não? Baixe o
código para a página “Remover Email” no site da Alta Books,
www.
altabooks.com.br. Está na pasta capitulo03. O código
consiste de um formulário web em removeemail.
html, uma folha
de estilo (style.css) e algumas imagens (elvislogo.
gif e
blankface.jpg).
Crie um arquivo de texto chamado removeemail.
php e digite nele
todo o código da página anterior. Envie todos estes arquivos para o seu
servidor web e abra a página removeemail.
html em um navegador.
Digite o endereço de email de um cliente no formulário e clique em
“Remove” para apagá-lo do banco de dados.
você está aqui ► 153
o aplicativo lista de email esta cómpieto!
"QueroSerElvis.cout" é uma
aplicapão web
É oficial. Com a £yuda do PHP e do MySQL, o site
QueroSerElvis.com de Elmer agora é digno de ser
chamado de aplicação web. Elmer agora é capaz de
armazenar dados, permanentemente, em um banco de
dados MySQL e também de interagir com esses dados
através de formulários web. Uma combinação de páginas
HTML scripts PHP e consultas SQL inseridas permite a
Elmer adicionar e remover clientes da sua lista de email
(os clientes também podem se inscrever sozinhos), bem
como enviar mensagens de email para a lista inteira.
A página “Adicionar
Email” adiciona
novos clientes à
lista de email de
Elmer.
A página “Remover Email” exclui
um usuário da lista de emails.
crie 0 preencha um banco de dados
C r u z a d a s p H P & M y S o L
Depois que você tiver treinado, os passos de dança de
Elmer, veja se consegue cantar junto e completar estas
palavras cruzadas.
Horizontais
3. Um banco de dados MySQL divide-se nelas.
5. Uma estrutura de dados persistente,
altamente organizada, que geralmente é
armazenada em um arquivo, no disco rígido.
6. Esta cláusula condicional pode ser
adicionada a instruções SQL para controlar
quais linhas são especificadas.
8. Este comando SQL remove uma tabela
inteira do banco de dados.
9. Use este comando SQL para selecionar
linhas de uma tabela.
10. Use este tipo de dados do MySQL para
armazenar uma quantidade variável de texto.
12. Dentro de uma tabela MySQL, isto
armazena um tipo específico de dados.
13. Continua fazendo algo, enquanto uma
determinada condição de teste permanecer
verdadeira.
Verticais
1. Um tipo de dados do MySQL que armazena
números sem casas decimais.
2. Use este comando SQL para olhar a
estrutura de uma tabela.
4. Quando funcionalidades dinâmicas são
adicionadas a um web site usando-se PHP e
MySQL, o site torna-se uma.........
5. Use este comando SQL para destruir
linhas de uma tabela.
7. Após ter criado um novo banco de dados
em um terminal MySQL, você deve exexutar
este comando antes de fazer qualquer coisa
com o banco.
11.Termo em inglês que representa um
conjunto singular de dados de uma tabela,
consistindo de um elemento de cada coluna.
você está aqui ► 155
palavras cruzadas php & mysql - solução
Cruzadas T H ? & M / SQ L - Solução
crie e preencha um banco de dados
Sua caixa deferramentas PHP £ MySQL
Você não só ajudou Elmer a montar sua aplicação web, como
também desenvolveu valiosas habilidades com PHP e MySQL
neste capítulo. Por exemplo...
157
c
a
p
ítu
lo
3
4 Aplfcaç^es Realistas e prátícas
Sua Aplicação
* na Web
Às vezes você precisa ser realista e repensar seus planos. Ou
então planejar com mais cuidado logo no começo. Uma vez lançada a sua aplicação na Web,
você poderá descobrir que não planejou suficientemente bem. Coisas que você pensou que
funcionariam podem não ser boas o suficiente no mundo real. Este capítulo dá uma olhada em
alguns problemas do mundo real que podem ocorrer quando você transfere sua aplicação do
ambiente de testes para um site reai. E enquanto isso, nós mostraremos exemplos de códigos
PHP e SQL importantes.
este é um novo capítulo ► 159
elmer precisa de um aplicativo de lista de email melhor
Elmer tem alguns clientes irritados
A lista com os emails dos clientes de Elmer cresceu exponencialmente, mas
os seus emails têm gerado algumas reclamações. Elas são variadas, mas todas
parecem ter algo a ver com os usuários recebendo mensagens em branco, ou
múltiplas mensagens, o que não é bom em nenhum dos casos. Elmer precisa
descobrir o que deu errado e consertá-lo. O seu negócio depende disso.
sabe *ue te» u**
problema, «âs ele pireti*
de ajuda para âesttbn*
e*ata»ervte o <ue W
a
-
í«:
' '■
:?
} 1
: ■
; V
if.;
B: ."v ‘
W n l ' r'"'
aplicações realistas e práticas
SINTAXE comoEkner, e administrador da
lista de etnails
3uaiaíeía é Interpretai' p papel de Elmer e
desoot-rijr C
9H
}9 egses einails em bt^ncç esta.9
sendo enviados. Ele suspeita <jue
tem algo a Ver com o formulário
sendemail.kml-
Êstrcvâ a<wi o <ue £Uev
atha «uc pode sev- o ^roble^a
sinta-se como elmer soiução
Si^TArSE como Elmer, o administrada da lista de
e m a i l s - S e l u ç ã o
Suatarefe. é-fnt&íptetcir 9 pape-l de
Elmer e descobrir como esses erri^ls
em Wanco estão sendo
enViad^s. Ele suspeita,
^ue tem algo a Vet
cem p ÍQrmularfè
sendemqjl.kmL
Esireva a«ui o <ue EUer adha
«jue pode ser o problema.
£e o bota© Submit íc r pressionado
no formulário sem haver nada no
£ampo Body (iorpo da mensagem);
é enviado um email em brando £
a^ora ^ue estamos pensando no
assunto, um tampo Subject íâssuni»)
vazio também é problemático.
aplicações realistas e práticas
Protegendo Elwer de... Elmer
Portanto, o problema aqui está naquela peça
que fica entre o teclado e a cadeira - Elmer está
clicando acidentalmente em Submit (Submeter)
sem digitar uma mensagem, e com isso emails em
branco são enviados para a lista inteira. Nunca é
seguro presumir que um formulário web será usado
exatamente da forma que foi planejada. E por
isso que você, um programador PHP atento, tem
a responsabilidade de tentar evitar esses tipos de
problemas, antevendo que alguns usuários irão usar
os seus formulários de forma errada.
Vamos dar uma olhada no código do nosso
script sendem ail ,-php atual, para ver como as
mensagens vazias de Elmer estão sendo criadas.
Kosso Bhviâm Email usa o •fceitfco do
-rormuíâHo S £<ri3ir um email, mesmo c^u
e
o usuário n3o íenha dijííado nada.
0 -te*t» do íovmulavio e
obiido d t fJ>Ô STf* b jr t« e
f POSlTelvismaiD, e e salvo cm
fib je fit e fte*fei resfefrtivameK-te-
$dbc = mysqli_connect(’data.makemeelvis.com’, ’elmer'
or die('Erro ao se conectar ao banco de dados.');
’theking1, 'elvis store'
$query■= "SELECT * FROM email_list";
$result = mysqli_query($dbc, $query)
or die('Erro ao consultar o banco de dados.')
while ($row = mysqli_fetch_array($result)){
$to = $row['email'];
$first_name = $row['first_name'];
$last_name = $row['last_name'];
$msg = "Dear $first_name $last_name
mail{$to, $subject, $msg, 'From:' .
echo 'Email $to 1
<br />'
}
mysqli_close($dbc);
0 problemâ c <
^u
e m
os usamos
f'tex’
i *a nossa mensagem,
^dçpehdcM-temcnie de a variável
toYí{,<X algum ou »ao—
...e inos -também usados
fsubjeòi i*de?e*de*W *t«
de bavev kjcÀfi *ela nâ°'
?>
Escreva aqui o que você acha que deveria ser modificado no
código do script sendem ail .php para consertar o problema dos
emajls em branco: , /
*. .*
■
*
'' . .. _V. .*.. .-is. c. "
T ‘.. .. ^
você esíá aqui ► 163
sendemail.php precisa de validação
Exija bons dados do formulário
O formulário de Enviar Email de Elmer precisa de alguma validação, que é
o processo de se verificar se os dados do formulário estão OK antes de fazer
qualquer coisa com eles. Elmerjá está usando validação, embora não a
esteja chamando por esse nome. Sempre que ele recebe um pedido através
do site, ele não envia o produto imediatamente... ele valida o pedido antes.
No caso de um pedido, Elmer primeiramente verifica se o cartão de
crédito do cliente é válido. Caso afirmativo, ele prepara o produto para
envio. Mas para isso, ele precisa verificar se o endereço do cliente está
completo. Se estiver tudo certo, então Elmer faz o envio. Para que um
pedido seja processado com sucesso na loja de Elmer, é necessário validar
vários dados referentes a esse pedido.
EWev te»
que validav -s.
odarfcao de A
drédito de
dada dliente,
antes de
atender ao
pedido.
Para resolver o problema dos emails em branco, precisamos validar
os dados do formulário entregues ao script sendemail -php. Isso
significa que os dados devem ser submetidos da página do cliente
(sendemail.
html) para o servidor e o servidor (sendemail.
php) deve checar se todos os dados estão presentes. Podemos
adicionar algum código a sendemail.
php para examinar os
valores das caixas de texto, e verificar se elas não foram deixadas em
branco. Se tudo estiver OK, o script envia os emails.
0 endereço pav-a—■
—^
envio predisa
estar do^pleto-
H Elmer preenche e
submete o formulário
Enviar Email.
O Os dados do
formulário são
enviados para o
script de Enviar
Email, no servidor.
Validar slgnííica
certíÇiCcfr-se d e
<jue 9S dadPS
cj[ueVoce está
reeekendp s§9
9s espetadas.
0 pedído só
é enviado se
o dartao de
dredito e o
endereço de envio
íore» válidos.
O script PHP
valida os dados.
Se estiverem
OK, ele envia os
emails - caso
contrário, ele
retorna um erro
para o cliente.
H O servidor envia uma resposta HTML para o navegai
v dizendo ou que o email foi enviado ou que os dados do
formulário eram inválidos.
aplicações realistas e práticas
A lógica por irás da validação de Enviar Email
Elmer precisa validar os dados que obtém do formulário s e n d e m a il.
htm l, para poder enviar os emails. Na verdade, a situação ideal é que
o envio dos emails dependa totalmente da validação dos dados. O que
realmente precisamos que o PHP faça é tomar uma decisão com base na
validade dos dados recebidos pelo script s e n d e m a il.php. Precisamos
de algum código que diga “se os dados forem válidos, vá em frente e
envie os emails”.
Estas duas eoftdiÇoes predisa» ser verdadeiras
parâ o dado ser donsíderâdo valido
i
SE Subject contiver texto E Body contiver texto
ENTÃO enviar email
 Se a»bas as tonditoez
-Pore» atendidas, e sinsl de
<ue esis tudo derto e <ue
pode»os enviar os e»ails.
Estavamos »andando e»ail se» h©
$
preodupar»os se aUo losse digitado
nestes da»pos do -rormulario.
Co» a ajuda da validado,
pode»os nos dertiíií-ar de <*e os
e»aiis só seja» enviados se a»bo*
os ta»pos dontwere» dados.
íia
<
?eX
istem
Perguntas idiotas
sendemail.html
Eu já ouvi falar em validar os dados no cliente,
em vez de no servidor. Como isso funciona?
0 navegador web é considerado como o cliente,
de modo que a validação no lado do cliente seria
qualquer verificação que ocorra antes de os dados
serem enviados para o script PHP. Linguagens como
JavaScript são capazes de fazer validação no iado
do cliente. Se estiver interessado em aprender mais,
dê uma olhada em Use a Cabeça! JavaScript, o qual
aborda em detalhes a validação no lado do cliente.
Então por que usar a validação no lado do
servidor, em vez de no lado do cliente?
Se validarmos no cliente, apenas parte
do problema é resolvida. Elmer poderia navegar
diretamente até sendemail.php e enviar um email em
branco. Porém, se validarmos no servidor, isso resolve
ambos os problemas. Dados em branco no formulário
serão detectados, bem como dados em branco sendo
carregados diretamente no script PHP. Isso não equivale
a dizer que é errado validar no cliente. Na verdade, é
uma ideia muito boa. Mas o servidor é a última linha
de defesa para se capturar dados ruins, portanto a
validação no lado do servidor não pode ser ignorada.
você está aqui ► 165
tirar a declaração
Seu código podetomar decisões com IF
A declaração PHP if permite ao seu código tomar decisões com base em se algo é
verdadeiro ou não. Considere novamente os pedidos da loja de Elmer. Antes de
atender um pedido, Elmer precisa receber o pagamento, o que significa cobrar no
cartão de crédito do cliente. Se o cliente fornecer a Elmer um número errado de
cartão de crédito, ele não pode atender ao pedido. Assim, Elmer realiza uma espécie
de validação-no-mundo-real em cada pedido, que acontece mais ou menos assim:
Se o cartão de crédito do cliente for válido, vá em frente e atenda ao pedido
Nós podemos traduzir este cenário para código PHP usando a declaração if, que serve
para lidar exatamente com este tipo de tomada de decisões.
A Instrução i f básica tem três partes:
Apalavra-chave i f
Ela inicia a declaração
O A condição de teste
A condição de teste ou expressão condicional, localiza-se entre
parênteses logo após a palavra-chave i f . E aqui que você coloca a
declaração cuja validade ou veracidade, você deseja determinar.
A ação
A ação deuma declaração i f vem logo após a condição de teste, e
fica dentro de chaves. E aqui que vocêcoloca o código PHP que
deseja executar quando a condição for verdadeira.
Esta e 3 t<nâtâo Ela esta
dedlaradao ^"'Snd© uma íw^ao para veH-Pidar
eomcça dom i f -v f ® está a r^ n a d o e* ^ tKav<;
) fíw art_£ard I » ( «alido. ^ . . .
sP s ' -------- — _ I > ----------------------> ^ i w f c .a a r * r t e
© i f ( i s V a l i d ( $ c r e d i t _ c a r d _ n u m ) ) { a açao
O f i l l O r d e r 0 ;
s r ]
Mo í ir tliu a iã o « ' fcta ‘ a * 9 ° ' ° ?^ ' r Í
3 i t t laraíão if..' t t í b J t » taso a ío n to »
^ »«-dadwa. V oá ?oa<
ImKas de tóá^o aqui quanto
quiser-
^ ( íalso ^dependendo da validade
do dartâo de dredito.
Jk.n n
aplicações realistas e pi.
Testando em busca da verdade
O cerne da declaração if é a sua condição de teste, que é sempre interpretada
como verdadeira ou falsa. A condição de teste pode ser uma variável, uma
chamada a função ou uma comparação de uma coisa com outra, por exemplo. A
validação de cartão de crédito feita por Elmer usa uma chamada a função como
a condição de teste, o que significa que o valor retornado pela função será ou
true (“verdadeiro”) ou false (“falso”)..
A dondição de
/ — -teste e.verdadeira
V' ou £alsa-
SE(ojcartão for váNdoJ “ 'I lf f
ENTÃO atender ao pedido f illOrder () ;
 ^ 5 dondiÇâo de teste
----- to r verdadeira, a aça© ê
e*edutada. 3
É bastante comum usar uma comparação como condição de teste, o
que normalmente significa comparar uma variável com algum outro
valor. Por exemplo, talvez Elmer queira oferecer um desconto para
clientes que morem em Nevada. Ele poderia criar uma declaração
if para executar uma comparação em parte do endereço de envio,
desta forma:
isto e verdadeiro se a
variável fsí>iffi«5__state
do«tiver o texto
levada"
SE o cliente mora em Nevada
ENTÃO aplicar desconto
}
if ($shipping state == 'Nevada') {
$total =
Esta condição de teste realiza uma comparação de igualdade, a qual
envolve dois sinais de igual (==). As comparações de igualdade não
são apenas para variáveis e strings. Você pode comparar variáveis
com números, variáveis com variáveis e até mesmo realizar cálculos.
Um desdohto de
10% e aplidado
*a ação, daso
a dondiçao
de teste seja
verdadeira-
Vode pode veriíidar se
o <ue esiS armazenado
em uma variável é ijual
ao ^ue está armazenado
em outra.
($num items == 10)
Mão dolo^ue valores
fcumeridos entre aspas.
($shipping addr.ess =
=
= $billing address)
(2 + 2 =— 4:
Vode pode e*edutar operações
matemátídâs em umâ dondiÇ3o
de teste-
você está aqui ► 167
i/ores no php
a mais do que apenas igualdade
Uma declaração if pode verificar mais do que apenas igualdade.
A condição de teste da sua declaração if pode também verificar se
um valor é maior do que outro, por exemplo. Se for, o resultado
da condição é true e o código da ação é executado. Eis aqui
alguns outros testes que você pode usar para controlar a decisão
de uma declaração if.
ComeCe ton> estas
duas variáveis.
Kao te» problema
escrever wma declaraçao
l'Ç£m W
*3 S
Olinbâj
desde que a açao seja
relativamente simples.
$small number = 2;
Existem duas formas de se verificar
se as coisas não são iguais: <> e !=,
Isto lhe dá o resultados oposto de
um teste de igualdade com = .
$big_number - 98065; ^ a s estas CohdiÇoes são
verdadeiras.
if ($small_number <> $big_number) { echo 'True'; }
if ($small_number != $big_number) { echo 'True'; }
O sinal maior que (>) verifica se
o valor da esquerda é maior do
que o valor da direita. Se for, a
condição é true; caso contrário,
é false.
Esta c©*diça© e íaUa-
if ($small_nuinber > $big number) { echo 'True'; }
O sinal menor que (<) compara
o valor da esquerda com o valor
da direita. Se o da esquerda for
menor do que o da direita, a
condição é true.
^£$ta Co^diça© e verdadeira.
if ($small number < $big number) { echo 'True'; }
Maior ou igual a (>=) funciona
como maior que (>), exceto pelo
fato de que ele também resulta em
true se os dois valores forem iguais.
'Ç Esta condição e falsa-
if ($small number >= $big_number) { echo 'True';
Menor ou igual a (<=) é
semelhante a menor que, exceto
pelo fato de que também resulta
em true se os valores forem iguais.
E*ta Condição e verdadeira.
if ($small__nuniber <= $big_number) { echo 'True'; }
E quanto as strings? Será
que ("cachorro" >"gato")
funcionaria?
Sim, você pode comparar strings em condições de
teste
A comparação funciona com base no alfabeto, com a letra a
sendo considerada como menor do que a letra z. Usar os sinais
de maior que ou menor que pode lhe ajudar quando você tem
que apresentar informações em ordem alfabética
ar>
e
aplicações realistas e práticas
m T A S V c o m o uma condição deteste- da
declctt-aç-sb li
3uatarefe 4 Interpretar o papel da condfçap deteste- 5? e
decidir s&Voce é Verdadeiro 9u Çals9, dadas as seguintes
VatiáVels.
$my_name = '
Buster'
;
$a_number = 3;
$a_decimal = 4.6;
$favorite_song = 'Trouble';
$another_number =0;
$your__name = $my_name;
($favorite_song == "Trouble")
(
$my_name = 1$your_name'
)
(
$my_name == "$your_name") >
($your_name == $my_name)
($favorite_song == 'Trouble')
($a_number > 9)
r
<$favorite_food = amburger’)
verdadeiro ou(Talso>
verdadeiro ou falso
sinta-se como uma condição de teste solução
SÍJsÍT A -SE coniP um a condição de teste da
declcU-
açã° IÇ - Soluçã?
Sua tareia é Interpretar Opapel da condição de te-Ste- ïî e decídlr se Vçce é
verdadeiro ou {qjso, dadas as seguintes VarîaVeïs.
$my__name = 'Buster’;
$a_number = 3;
$a_decimal -4.6;
$favorite_song = 'Trouble';
$another_number = 0;
$your_name = $my_name;
($ a _ n u m b e r = 3)
($ a n o th e r_ n u m b e r = " " )
^ —T . .—s , . ^ c umd strihfl
<
% d a d e ir^ou falso & C
or>
úd^
(yerdadeir^ou falso
0 e uma strmg vazia
os domo
iguais.
Pcvidio às aspas simples,
($ fa v o r i te _ s o n g == " T r o u b le " ) $ e rd a d e iro )o u fa ls o ^a dondiçao na verdade
está perguntando se a
($m y_naine « = ' $ y o u r_ n a m e ') v e rd a d e iro ou (fa ls o ) string Buster é igual à
. string ufyour_nâme I e
( N>my_name = "$ y o u r_ n a m e ") v e rd a d e iro o u fa ls o «ão ao v^jor dontido na
, a . -----—
v. variável fyour name-
($your__nam e = = $m y_nam e) (^ e rd a d e ir ^ o u fa ls o l
( $ fa v o r ite _ s o n g = = 'T r o u b le ') (y e rtla d e irj^ o u fa ls o e maior q^e e
f. ^
($ a _ n u m b e r > 9) v e rd a d e iro o u ( p s ^ )
( $ f a v o r ite _ fo o d (= ^), h a m b u rg e r ’ ) ($ fe rd a d e ira )o u fa ls o
Deveria te r 0£, esta aqui e di-fíeil Uma vez.
sido , se a N. que esta sendo usado apenas
intentao aqui ^ um sinal de igual aqui, isto e na
era -fazer uma níi? verdade uma atribuidao (—
), e
tompavaçao F c V /crU t ll3.S Id lO fa s nao uma domparadão í—=^- £ «la
? £-, - lAix» ataba sendo verdadeira, porque
- Então a condição de teste é a mesma coisa que usamos para controlar qualquer doisa que nao seja O,
os loops while no Capítulo 3?? NULL- ou -false t interpretada
domo true pelo PttP•
v J . É exatamente a mesma coisa. No capítulo 3, a usamos para saber se
ainda tínhamos linhas de dados resultantes da consulta, mas podemos pensar em
condições de teste mais interessantes para loops while, usando diferentes tipos
de comparações. Você verá isso mais adiante no livro..
aplicações realistas e prática
A lógica por irás da validapão de Énviar Ewail
Elmer precisa validar os dados que obtem do formulário sendemail.html, para poder
enviar os emails. Na verdade, a situação ideal é que o envio dos emails dependa totalmente
da validação dos dados. O que realmente precisamos que o PHP faça é tomar uma decisão
com base na validade dos dados recebidos pelo script sendemail.php. Precisamos de algum
código que diga “se os dados forem válidos, vá em frente e envie os emails”."
Mas primeiro nós precisamos obter os dados do formulário e os armazenar em
algumas variáveis:
$subject = $_POST[1subject1];
$text = $_POST[1
elvísmail'];
Isto é tudo de que precisamos para verificar se existem
dados em cada um dos campos do formulário. A lógica é su
algo como o seguinte:
SE S u b ject contiver texto E Body contiver texto
ENTÃO enviar email
Ou então poderíamos adotar a abordagem oposta e
verificar se os campos do formulário estão ambos vazios,
em cujo caso poderíamos exibir um aviso para o usuário:
SE Subject estiver vazio E Body estiver vazio
ENTÃO exibir mensagem de erro
Ambos os exemplos têm um problema, porque a lógica deles
requer que nós façamos duas comparações em uma mesma
declaração if. Uma solução possível é usar duas declarações if..
sendemail.html
Aponte seu lápis
Escreva duas declarações if para verificar se tanto o assunto
quanto o corpo da mensagem do formulário Enviar Email estão
vazios. Emita um aviso caso estejam.
..Á ..? .9 :d y .... .t f c r ...M u JL .Lr?..).........k
você está aqui ► 171
íssetQ e empty()
Mteseu lápis
Solupão Escreva duas declaração i f para verificar se tanto o
assunto quanto o corpo da mensagem do formulário
Enviar Email estão vazios. Emita um aviso caso estejam..
fcí" ’ |sto âqui sao duâs dSpãS Simples, O
if (/lubjeet — ” ) 1« rtfra e n i» •»* *b™>5 'atà *~
= = "H ............................................
Colocando a
i^stvutâo ií dcnbro ;ÇÍ£kovodese esw*eieu de àtyksr o asswbo fi o tewbo de e
vm
ail <br />';
da pvinxeirâ, o
dodi$o esta dizendo
que ambas prcdisâm
ser verdadeiras pâra
que a instrução ttsQ
seja exedutada-
A indentaça© ajuda a mostrar onde
a dedlarada© i+ interna termina e
onde domeça a dedlaradã© ií externa.
Fimpões PHP para verificar variáveis
Usar == para checar se uma string está razia funciona, mas existe uma forma
melhor de fazer isso, através de funções internas do PHP. A função isset()
verifica se uma determinada variável existe, o que significa dizer que ela tem
um valor atribuído a si. A função empty() dá um passo além e determina se
a variável contém um valor vazio, que o PHP define^eeuq^o um 0, uma string
vazia (' ' ou "") ou os valores false ou NULL. Assin^sset()§byte‘torna true se
um valor tiver sido atribuído à variável, enquanto qite.^mpty{/ só retoma true
se a variável tiver sida definida como (j^umjstring vazia, feilsejju
Vejamos como essas funções trabalham:
fvl dontem
um valor*.
$vl = 'aloha
fvZ c uma $v2 = " -
string vazia..
-}
Tanto fvl quanto fv2- sao
donsideradas domo tendo sido
definidas, mesmo que somente
fvl tenha um valor-
fvZ esta
definida?
mesmo que
dontenha
umâ string
vazia
if (isset($vl)) {
if (empty($vl)) { echo '
$vl está vazia<br />'; }
if (isset($v2)) {
if (empty($v2)) {
if (isset ($v3) ) { echo '$v3 está definida<br />'; }
I V
5 nac
existe-
if (empty($v3)) {
Somente o dódi^o
sombreado e
exedutadof!
fvl nâo está
vazia, ela dontem
texto. Assim, esta
dondidao if é falsa..
jvZ está vazia
porque a string ^
o^ue ela dontem e
v32ia
?v3 e donsiderada
vazia, mesmo que
nem exista..
aplicações realistas e prátic^
Entendi. Nós podemos usar isset() e emptyO
para validar os dados de $subject e $text.
Quase isso. Na verdade, nós só estamos verificando se os
dados não estão vazios, por isso empty() é o que precisamos.
As variáveis de texto $sub j e c t e $ te x t recebem valores das
superglobais $_POST [ ' sub j e c t ' ] e $_POST [ 1e lv is m a il ’ ]. Se
você testar essas variáveis com i s s e t (), o teste sempre retomará true,
independentemente de elas realmente conterem ou não algum texto.
Em outras palavras, i s s e t () não lhe mostra a diferença entre um
campo em branco e um preenchido. A função empty () verifica se a
variável está realmente vazia, que é o que precisamos para a validação
do formulário.
iSSetO VeífÇfoctse a VatfaVel
existe e se está deíltuda.
e U l p t / 0 V e tííf c a s e
a VorfaVe1tem algum
c o n te ú d o .
na° existem
idíptas
* Então qual o propósito de usar issetQ?
A função isset 0 é extremamente útil quando você
precisa saber se um determinado dado existe. Por exemplo,
você pode verificar se um formulário foi submetido através
de uma requisição POST repassando $_post à função
isset (). Isso acaba sendo uma técnica bastante útil, como
você descobrirá um pouco mais adiante neste capítulo.
Apowte seu lápis — ------------------- — -----------------
Reescreva as duas instruções if que criamos para verificar
se tanto o assunto quanto o corpo da mensagem do
formulário Enviar Email estão vazios, porém, desta vez, use
a função empty () em vez de == nas condições de teste.
4)
C
0
nte seu lápis
Solupão Reescreva as duas declarações if que criamos para verificar
se tanto o assunto quanto o corpo da mensagem do
formulário Enviar Email estão vazios, porém, desta vez, use
a função emptyO vez de - - nas condições de teste.. '
U*»a tha»ada a fwr^ão
ewvpiyO substrU» o operador
■''U
lZ
J /
de igualdade í- ~ ) em tada .jk h o jy & e sc.cs.V ™ '^ :íl.l.
3i.
‘^.'r .°. ass^ 1>
J,c.° k*fco;do
uma das do^diçoes dc teste-
0 «sbnte do códi9o_£ . í ^ £ j ? 5 v f W '
o mesmo que antes- J jX ^ . .J T Í? Á . .L È AW
^ »y"
'
'
"
' ^ ’
/ '
/
E se nós precisarmos executar
uma determinada açSo apenas
se o campo do formulário nao
estiver vazio? Existe uma função
notemptyO?
Não, mas há uma maneira fácil de inverter a lógica de
qualquer condição de teste... o operador de negação.
Nós sabemos que a condição de teste que controla uma declaração
if sempre resulta em um valor true ou false. Mas e se a nossa lógica
determinar que precisamos verificar o inverso do que uma condição
nos apresenta? Por exemplo, seria útil saber se os campos do
formulário de Elmer não estão vazios, antes de enviar um monte
de emails. O problema é que não existe uma função notempty(). A
solução é o operador de negação (!), que transforma true em false ou
false em true. Assim,!empty () literalmente chama a função empty() e
inverte o seu resultado, desta forma:
0 operadov UOT (/)
tvans-íWmâ true ei» N
faíse ou -false e» tvue-
if (
1 3m.pty ($subject) ) {
£sta íondiçâo esta
' perO)u»ta*do u0 daw
«po do
Assunto esta nao—
vâzjo ;
ou seja, ele dontem dados?
aplicações realistas e práticas
Preencha as lacunas no código sendemail.php de Elmer, de modo que o
email só seja enviado quando tanto $subject e $text não estiverem vazias.
Use declaração if e a função emptyQ.
<?php
$from = 'elmer@makemeelvis.com';
$subject = $__POST [
'subject'];
$text = $ POST['elvismail'];
O o Private: For Bm efs use ONLY
Write and send an email to rnaffinâ Ftstnnem
sendemail.html
i í .i í .e .w í i Y .L í í M .4 j à í f i j ) .e ® ^ 0 =
: Jy n , /*
i . i . . C i •lux-.~J ÍXÍí>.e>3:® - "f-i ’
j
f f s' K ’
y® ~ ^ J
^^ $dbc”= mysqli_connect('data.makemeelvis.com', 'elmer', '
theking',
'elvis_store1)
or die{'Erro ao se conectar com o servidor MySQL.');
$query = "SELECT * FROM email_list";
$result = mysqli_query($dbc, $query)
or die('Erro ao consultar o banco de dados.');
while ($row = mysqli_fetch_array($result)) {
$to = $row['email'];
$first_name = $row ['first_name '];
$last_name = $row['last_name'];
$msg = "Caro(a) $first_name $last_name, n$text",
mail{$to, $subject, $msg, 'From:' . $from);
echo 'Email enviado para ' . $to . '<br />';
}
mysqli close ($clbc);
?>
você está aqui ► 175
sendemail.php—agora com validação!
Preencha as lacunas no código sendemail.php de Elmer, de modo que o
email só seja enviado quando tanto $subj ect e$text não estiverem vazias.
RCÍCIO Use declaração if e a função empty {
)
,
0 ponto de exdlamação
inverte a lógida da
•função emptyO.
<?php
$from = '
elmer@makemeelvis .com'
$subject = $_POST[1subject'
$text = $_POST['elvismail
j_f " (Jemptyifsubjedt)) {
A (x-imeM íondiçao _ sendemail.html
veri<ida se fsttbjctt »3^.
esta vazia...
...se nâo estivev> ótimo/ Agora
vevi-ficâmos se fte%t não esta vazia-
Mós tivemos de dolodar uma dedlaraçao
ií dentro da outra, para que o dódigo
-Çundionâsse. |sso se dha**>a aninhar.
$dbc = mysqli connect(1data.makemeelvis.com1, ’elmer’, 'theking',
’
elvis__store'
)
or die('Erro ao se conectar com o servidor MySQL.');
Çquery = "SELECT * FROM email_list";
Çresult = mysqli_query($dbc, $query)
or die('Erro ao consultar o banco de dados')
while (?row = mysqli_fetch_array($result))
$to = $row['email'];
$first_name - $row [
'first_name '];
$last_name = $row['last_name1]
;
$msg = "Caro(a) $first_name $last_name, n$text'
mail($to, $subject, $msg, 'From:' . $from);
echo 'Email enviado para: ' . $to . '<br />';
}
mysqli_close($dbc)
Se qualquer uma das
variáveis estiver vazia,
uma das dedlara^ões ií
será íalsa, e nada deste
dódigo será e*edutado, o
que signlfida que nenKum
email em brando será
enviado —exatamente o
que queríamos
?>
N
Ó
S temos de -finalizar a parte relativa
à ação de ambas as dedlarações ií^A
primeira dhave -finaliza a dedlaradao ií
interna, enquanto que a segunda -finaliza
a dedlaração i-f c*terna-
aplicações realistas e práticas
O R t v e
Verifique se a validação dos campos do formulário funciona.
Modifique o código de sendemail.php para usar declarações if que verifique
os dados do formulário antes de enviar as mensagens de email. Envie a nova
versão do script para o seu servidor web e abra a página sendemail.html
em um navegador. Certifique-se de deixar pelo menos um dos campos do
formulário em branco, e clique em Submit.
0 dorpo da n»en$39evn
esta vazio, o «uc
-(■
a
z- os dados do
•formulário ■
(
‘âlVlârem
na validaçao.
M a te M e E L v ts .e o M
Prfrato: F
o
rSn»rts useONLY
WHte and send m ema» to maiiing ijstmembers
Suüjeetofemail:
BlueSiaede Cíe^rance!
Bodyofemail:
A ausendia dc doníirmaçoes
dc cmâiU revela <ue nada
■
P
o
i enviado, <
^u
e é o ^«e nós ___
queríamos. Mas algum iipo de
aviso a<ui seria mais u-fcii do <
^u
e
uma pâ^ina em brando.
você está aqui ► 177
conversa a três
E se nós tivéssemos um
monte de campos no formulário?
Teríamos de aninhar um monte de
instruções if para validar tudo??
Aliens AbductedMe - Report an Abduction
Share your storyof alienabductsoo:
rotnwulivio de 0weh, visto
an-fccricmrKCnie nesie livy©, e m
cxemplo de to*no o -fsip de •fcev-m
os
mSis tdmfos !
r
>
0fov-nnuldvio results
C
n
>i&rmos tdtoben* un* cuonte de
detUratozs i-P a*i*Hadas.
if (!empty($first_name)) {
if (!empty(
$last_name)) {
if (!empty{$when_it_ ^ "
happened)) {
if (
!empty ($how__long) ) {
LatfBsme
WbaisJT
M
Tejnalsd4re»7
W
hendidithappen?
How lo«swtrtyooeooe?
Howm i dW>
*
o
osee?
Detofbe®«ai!
What<
JS
dtheydotoyou?
HaveyonstmmyiK«Fane'
Anytfetog«fcíj™'*««toadi?
Tãnto anm
haiw
eivfc©
-fcov-na di-ffal maivtev o
èotttvolc áe quantas
òhaves pvetisa»* sev
usâdâs e» que leaves.
F W J M
if (
!empty ($how__many) ) {
Joe: Acho que você tem razão. Se quisermos nos certificar de que
todos os campos estejam preenchidos, precisaremos colocar uma
declaração if para cada campo.
Frank: Mas desde que façamos a indentação da linha de cada declaração,
estará tudo bem, certo?
Jill: Tecnicamente, sim. Quer dizer, o código certamente vai funcionar, não importa quantos if’s nós
colocarmos. Mas eu me preocupo se ele não vai ficar difícil de entender, com tanto aninhamento.
Colocar as chaves corretamente poderia se tomar um problema.
Frank: Isso é verdade. E eu acho que também seria trabalhoso ter de indentar o código de ação que
temos até aqui... vejamos, são dez campos no formulário, o que nos dá dez ifs aninhados, com dez
níveis de indentação. Mesmo se cada iffor indentado com apenas dois espaços, isso dá 20 espaços
antes de cada linha do código. Nada bom.
Joe: Mas se indentarmos com tabs, isso diminui pela metade - 10 tabs em vez de 20 espaços não é tão ruim
assim
Jill: Pessoal, a questão não é o modo como nós indentamos os ifs aninhados. E que simplesmente
não é uma boa prática de programação colocar tantos ifs uns dentro dos outros. Pensem desta
forma - o que estamos realmente falando é de uma condição de teste lógica, “todos os campos do
nosso formulário estão não-vazios?” O problema é que essa condição de teste envolve dez dados
diferentes, fazendo com que nós tenhamos de dividi-la em dez declarações if separadas.
Frank: Ah, entendi. Então o que precisamos é de uma forma de verificar todos os dez dados em uma
só condição de teste, certo?
Jill: Isso.
Joe: Então nós poderíamos escrever uma só condição de teste gigante, para verificar todos os
campos do formulário de uma só vez. Seria ótimo
Jill: Sim, mas ainda não temos o pedaço do quebra-cabeça que nos permitirá combinar diversas
comparações em uma mesma condição de teste...
aplicações realistas e práticas
teste múltiplas condipões com ANP e OR
É possível construir uma condição de teste para uma declaração
if com diversas verificações conectando-as através de um operador
lógico. Vamos ver como isso funciona com duas condições familiares,
!empty($subject) e !empty($text). Este primeiro exemplo envolve duas
expressões conectadas através do operador lógico AND (“e”), que é
codificado usando-se && . Os fa tie s « e*tras ajudai a dei*ar
dlaro «
^u
e o cfcrsâc* de ne^adão só se
0 operador apísda a -funçãoemptyO..
ISjito AND- % ^
if {(lempty ($subject) )|!||| (lempty ($text) )) {
dondidao de iesie só e verdadeira se tanto
fsubjedt «v>a*to fte * t «ao estwere** vazias.
O operador AND toma dois valores true/false e lhe retorna true
somente se ambos forem verdadeiros; caso contrário, o resultado é
false. Assim, neste caso, ambos os campos precisam estar não-vazios
para que a condição de teste seja verdadeira e o código de ação da
declaração if possa rodar.
O operador lógico OR (“ou”), codificado como ] |, é semelhante a
AND, exceto pelo fato de que ele resulta em true se pelo menos um
dos dois valores true/false for verdadeiro. Eis um exemplo:
A 16gicíi do
TH? to m
pogsíVel
elaborat
d e c la ra ç õ e s ! Í
ma!s elegantes-
o A r ^ ló g ic o e
c p d i í i c a d o c o m o
enc
juant9
c(ue 9 O R lêgfco
é codificado
c o m o ||.
if ((!empty($subject)}
Es-fca dondida© à t teste é
verdadeira se fsvbjedt OU fte x t
estiver nâo-vazia.
!
| (
!empty ($text) ))
â^UÍ hâO £ OyiU
lV
i^O
€ duás bâirfâs
—íida na parte de dima da
Assim, o código de ação para esta declaração if é executado se ^ ^ b â rra mvertida (), no
um dos campos do formulário estiver não-vazio. As coisas ficam
ainda mais interessantes se você quiser isolar um campo como
estando vazio, mas com o outro tendo dados, desta forma:
if (empty($subject) (!empty($text) ))
fswbjedt^vtdisa estar
vazia e fte * t predisa
estar nac-vâzja para
esta dondidão de teste
ser verdadeira-
Uma vez que esta condição de teste usa AND, ambas as
expressões dentro dela precisam ser true para que o código
da ação possa se executar. Isso significa que o campo Subject
(“assunto”) do formulário precisa estar vazio, mas o campo
Body (“corpo da mensagem”) precisa ter dados nele. Você pode
inverter essa verificação passando o operador de negação (!)
para a outra função emptyO: M* sé í
if ((! empty ($subject))jfjiilí empty ($text)) { h^o estiver vazio e /te *to
^ ^ estiver.
Os operadores lógicos AND (ScSc) e OR (||)tornam possível elaborar
condições de teste muito mais poderosas que, de outra forma, necessitariam
de muitas, e frequentemente bagunçadas declarações if.
você está aqui ► 179
eliminando o aninhamento da declaração if
Reescreva as seções salientadas do scripí sendemail.php para que ele
use operadores lógicos em uma única condição de teste, em vez de declarações
if aninhadas.
<?php
$from = 'elmer@makemeelvis.com';
$subject = $_POST['subject'];
$text = $ POST['elvismail']; aa ■ „
- cstao nossas dediavações
i
ía
n
i
n
h
a
d
a
s
. Re-esdveva usando
uma u
n
i
d
a dedlaradao i
íe tom
».»„.m,™™...^ o&eradores l
ó
g
i
d
o. v e
$dbc = mysqli_connect('data.makemeelvis.com', '
elmer'
, 'theking',
'elvis_store'
)
or die('Erro ao se conectar com o servidor MySQL.');
$query = "SELECT * FROM email_list";
$result = mysqli_query($dbc, $query)
or die('Erro ao consultar o banco de dados.');
while ($row = mysqli__fetch_array ($result) ) {
$to = $row['email'];
$first_name = $row['first_name'];
$last__name = $row ['last_name'];
$msg = "Caro(a) $first_name $last_name, n$text";
mail($to, $subject, $msg, ’From:' . $from);
echo 'Email enviado para: ' . $to . '<br />';
mysqli_close($dbc);
P l f fetas thave fetha-
P i «------- " as duas d r t lM ^ e . *
?>
TfeST ORtve_
_
_
_
__
_
_
_
_
_
_
_
_
_
_
aplicações realistas e práticas
Certifique-se de que os operadores lógicos no script "
"Enviar Email” estejam fazendo o mesmo trabalho que as
declarações if aninhadas.
Modifique o código de se n d em a il -php para usar uma única
declaração if que tire proveito dos operadores lógicos para verificar os
dados do formulário, antes de enviar as mensagens de email. Consulte
a solução do exercício na próxima página, caso não tenha certeza sobre
como fazer as modificações.
Envie a nova versão do script para o seu servidor web e abra a página
sendemail.html em um navegador. Certifique-se de deixar pelo menos
um dos campos em branco e clique em Submit. O script ainda impede as
mensagens de serem enviadas quando um campo é deixado em branco?
m ° existem
perguntas id!°tas
I - Faz diferença a ordem em que você coloca
as duas conexões ligadas por && ou [j em uma
declaração if?
Sim. 0 motivo é que o funcionamento desses
dois operadores pegam atalhos sempre que possível.
0 que isso significa é que, se o primeiro operando for
suficiente para determinar o resultado da expressão,
o segundo é ignorado. Por exemplo, se o primeiro
operando de uma expressão AND for false, isto é
suficiente para fazer a expressão inteira ser false,
independentemente do segundo operando, de modo
que este é ignorado. A mesma regra se apfica quando
o primeiro operando de uma expressão OR é true.
* vi códigos PHP que usam and e or em vez de
&& e |
|
. Como isso funciona?
Eles são praticamente a mesma coisa que &&
e 1
|. Há uma ligeira diferença no modo como eles são
avaliados em relação a outros operadores, mas, se
você tiver o cuidado de usar parênteses para tornar
as suas condições de teste claras, então não haverá
nenhuma diferença essencial.
você está aqui ► 181
sendemail.php—agora sem declarações if aninhadas
SoLuçâo
Reescreva as seções salientadas do script sendemail.php para que ele use
CÍO operadores lógicos em uma única condição de teste, em vez de declarações if
aninhadas.
<?php
$from = 'elmer@makemeelvis.com';
$subject = $_POST[’subject’]
$text = $ POST['elvismail']; h «. « opevad« MOT 0), í <*»*» ?»>
thttzc se Ka dam?os nâo-vazios no Wmulano.
( 1om pty ($oubjoo-
t )) { Nós Podemos usar AHT> m m
— ii-"
'
(!ompty ($tcxt) )
— i .
.
„ r.. '
---- ^ r f '? " âmbas as fiondiÇocs, Cmuma
.,'í.((!e.^pty(??ubjedt)) s®dediaraçao A
^ Lembre-se, ff é o modo domo vode
........................................................................ espedi&da o ofevador lógido AND-
$dbc - mysqli_connect('data.makemeelvis.com', 'elmer', 'theking',
1elvis_store'
)
or die('Erro ao se conectar com o servidor MySQL.');
$query = "SELECT * FROM emailJList";
$result = mysqli_query($dbc, $query)
or die('Erro ao consultar o banco de dados.');
while ($row = mysqli_fetch array ($result) ) { -rj r.
$to = $row [-email']; ^ T l ° dtnhro
H O y J - O w L S I Î Î 3 .1 - L j / j j w '
f
f
*
$first_name = $row[ ' first_name ' ] ; edârâÇâo t+ deve ser
^ 1 u ^ ___ ____ (*<_____ r T 1^ i_ ________ I 1 iiMu h f iM I J .
$last_name = $row['last_name '3; reduado em umnível de
$msg = "Caro (a) $first_name $last_name, Xnítexí^d^taÇao, uma vez. que
mail ($to, $subject, $msg, 'From:' . $from) ; agora ele reside dentro
echo 'Email enviado para: ' . $to . '
<br />'; uma unida dedlâraÇao ií
mysqli_close($dbc);
Tendo apenas uma dediaraçao ií, nós só
rdisámos de uma dKave de fedKamen-fco.
?>
aplicações realistas e práticas
Os usuários do formulário precisam
de uma resposta
O código do nosso script sendem ail .php faz um bom trabalho ao
validar os dados do formulário, com o objetivo de impedir que emails
sejam enviados caso o campo Subject (Assunto) ou o Body (Texto)
sejam deixados em branco. Mas quando a validação falha, e não são
enviados emails, o script não informa a Elmer o que aconteceu. E
U
apenas uma página web em branco.
£!»er ve esta pa$iwa
«luâftdo submete o
+o»rmu!ivio... e n3o
te» a fn
fh
o
rid
e
iado
porque!
que aconteceu? Eu
tentei usar o novo formulário e
tudo o que recebi foi uma página em
branco.
O problema é que o nosso código só reage a uma validação com
sucesso, em cujo caso ele envia as mensagens de email. Mas se a
declaração if acabar sendo false (dados do formulário inválidos),
o código não faz nada, deixando Elmer sem saber se foram
enviados emails ou não, ou então o que deu errado. Eis aqui o
código abreviado, que revela o problema da página em branco:
<?php
$from = 'elmer@makemeelvis.com';
$subject = $_POST['subject']
;
$text = $ POST['elvismail'];
1
elmer1, 1
theking'
mysqli_close($dbc);
^
if ((!empty($subject)} && (!empty(
$text))
) {
$dbc = mysqli_connect {
'data.makeimeelvis.
com',
'elvis_store1)
Nao aóontede *ada se a dedaraça© vf -falhar ao
e*e£utar o òód'»y> de atío, eef&r isso <

u
ee
?> • — ___________—
«
—"" gerada uma ^a^ma e» bvatóo <<*a«do al^u» tamfo
do -Çormulâvio teriKa -fitado e» b^a^áo.
Precisamos avisar a Elmer que houve um problema, de preferência
dizendo a ele quais campos do formulário ficaram em branco, para
que ele possa tentar digitar novamente a mensagem.
você está aqui ► 183
a cláusula else
Éí W "
1
rlfl
I
Sem problemas. Basta colocar
uma declaração echo depois da
chave que fecha a declaração if.
Isso não vai funcionar, porque o código depois
da declaração if sempre será executado.
Colocar a declaração echo depois da declaração if só significa
que a primeira vai rodar depois da segunda, mas ela sempre
roda - independentemente do resultado de if. Não é disso
que precisamos. Precisamos que a declaração echo mostre
uma mensagem de erro apenas se a condição de teste da
declaraçã if for false. Você pode expressar esta lógica da
seguinte forma:
SE Subject contiver texto E Body contiver texto
ENTÃO enviar email
X CASO CONTRÁRIO exibir mensagem de erro
A declaração if oferece uma cláusula opcional, else, que
executa algum código no caso de a condição de teste ser
false. Assim, a nossa mensagem de erro é colocado dentro de
uma cláusula else, e portanto, só é executado quando um dos
campos do formulário for deixado em branco. Basta colocar
a palavra else depois da declaração if, e depois colocar o
respectivo código de ação dentro de chaves
?subj ect)
) && (!empty($text))
) {
esqueceu do a ssu n to e/o u do corpo da
insere o Coá'^0
envia as mensa^e«*
de e
w
â
i
i
-
aplicações realistas e práticas
Segue abaixo o novo código para o script sendemail.php de Elmer, usando
declarações if e cláusulas else para fornecer feedback, mas partes do código se
perderam. Coloque os ímãs corretamente no lugar do código que está faltando.
// Nós sabemos que tanto $subject e $text estão
•'faltando
<?php
■$from = 'elmer@makemeelvis.com';
$subject = $_POST [
.
'subjectT];
$text = $ POST['elvismail'];
// $subject está vazia
está certo, enviar emails
// $text está vazia
...í±r.. .ÇQ. .e í.3.v.k)^£í. .
&
}
else {
.......
// Nós sabemos que um dos dois, $subject ou $ text, está faltando -
vamos descobrir qual deles
/ e-"
■ < 2 r -
echo 'Você esqueceu do assunto.<br />';
else ( ■£
echo 'Você esqueceu do corpo da mensagem.<br />';
}
else {
m . .
while ($row = mysqli_fetch_array($result)) {
"$to = $row['email1];
$first_name = $row['first_name'];
$last_name = $row['last_name'];
$msg = "Caro{a) $first_name $last_name, n$text";
__________
mail($to, $subject, $msg, 'From:' . $from); I empty($text) §|
echo 'Email enviado para: ' . $to . 1<br />’ —
>
mysqli close($dbc);
?>
você está aqui ► 185
soiuçâo exercício
Segue abaixo o novo código para o script sendmail.php de Elmer, usando
declarações if e cláusulas else para fornecer feedback, mas partes do código se
£RCÍCÍ0 perderam. Coloque os ímãs corretamente no lugar do código que está faltando.
S o L u Ç ã o O i í externo thetà se o assu*-k> c 0
<?php texfco esfcSo vtóos. £e nao Há apenas
$from = 'elmer@makemeelvis.com'; ^ 3 opÇoes a»*bas estío preewthidos o
$subj ect = $_POST [-subj ect']; / ***»tc esU íalta»do, ou o texto do
$text - $_POS.T [
'elvismail ’
•
]; f £«rpo do e
r
*
>
a
i
lestá íalkndo
if jèmpty{$subj ect) empty($text)
m
ii Nós sabemos que tanto $sub:ject e $text estão faltando
else {
if |( pempty ($subj ect) I li "
] empty($text)
// Nós sabemos que um dos dois, $subject ou $ text, está faltando - vamos
descobrir qual deles
F m
if [( empty (
$subject) J )
// $subject está vazia
*
rnimèmwlfm
m
n*
' ,
/.
echo 'Voce esqueceu ao assunto,.<br />';
}
else {
// $text está vazia
echo ’
Você esqueceu do corpo da mensagem..<br />';
}
else {
// Tudo está certo, enviar emails
~
W
íW
tw
W
?
?
W
T
''
Heste yor>to passages pov
while {$row = mysqli__fetch__array {$result)) { ^_ iodos 3s p
o
s
s
i
b
i
l
i
d
a
d
e
s
,
$to — $row [’
email ’]; ^tao, sabemos *we a«*bos
$first_name = $row ['first_name 1]; d
.
3»pos do Tormwlavio
$last_name = $row ['last_name ']; towt«»* v
a
l
o
r
e
s
-
$msg = "Caro(a) $first_name $last_name, n$text";
mail($to, $subject, $msg, 'From:' . $from);
echo 'Email enviado para: ' . $to . '
<br />';
}
mysqli close($dbc);
?>
A O i? ___ . f - &
aplicações realistas e práticas
Todos esses ifs e elses aninhados
estão tornando o script difícil de ler. Eu
detestaria ter que trabalhar nesse script!
Ele precisa ser simplificado, antes que
alguém se machuque..
É sempre uma boa ideia simplificar
código sempre que possível,
especialm ente, código com muitos
níveis de aninhamento.
Uma quantidade muito grande de cláusulas e ls e
com declarações i f aninhadas pode tomar o
seu código difícil de ler. Talvez isso não fizesse
diferença caso nós nunca mais tivéssemos que
olhar esse código, mas isso é bem improvável. Se
algum dia precisarmos modificar o formulário
para adicionar um novo campo, validá-lo seria
mais difícil do que precisa ser, porque seria
muito difícil ler o código e entender onde as
modificações precisam ser colocadas.
você está aqui ► 187
o código tf lim po
Ç íç d n e fo 0 ^
$ ÍH T A -~ S E c o m ò ^ c o j i g p i p S p ] u lç a 9
Sua tareia 4 interpretar o papel do código ip e limpar
o código dos lF ’s e EL'SE’s aninhados. ReescreVa
o oçdígç de modo a se livrar do anin^ament^, mas
ceiti6c]ue-se- de <jue-ela ainda Çunciynará
corretamente.
if (empty($subject) && empty($text)) {
echo 'Você esqueceu do assunto e do corpo da mensagem.<br
/> ’;
} else {
if (empty($subject) |
| empty($text)) {
if (empty($subject) {
echo 'Você esqueceu do assunto.<br />';
} else {
echo 'Você esqueceu do corpo da mensagem.<br />';
Aquij estamos }
■testando $
e } else {
tanto 3 variável //Tudo está certo, enviar emails
fsob'vett <uaKÍ» 1
a f f c - ■
“
vazias
a fte * t estso *
■
f (emptyf/subjedO && em pty(fte*t)) {
edbo Vode esquedeu do assunto e do dorpo da mewagem..<br />*;
Aqui, estamos  ........................................................................dodígo verifida se fsubjedt
st j- (IfifbjfÍM )'» { ^ ^ ‘ * « tí «âo-
ejsubjtói estó . «>!?. V oíí es>ewu do ass»„to. <W / > ) .............. & ^ estivíssemos « a * * „ AND
hao-vazia. } ------“ 7
7
!------—------(ff) para isolar o texto «ao-vazio de
edKo Vode se esquedeu do dorpo da mensagem .cbr desnedessaria- 0 mesmo 3do*tede para
j ------ "**— ---------- ^ fsubjedt e fte * t «âo—
vazias.
ií ^/e»pty(fsubjedt)) && 9 °perâdor Né)T (0 verí-fida se
^ ^ it; v
jh..jr.v/:/...Tyfcvív... ....Tv.ry j . f /1 — t*
»t» n 1^0
E y i , « U « „ Tudo fsii ^ ,„yjJr ^ a,|s .................fs“b
j “ * ‘ íie%i ts & »*>-«»**•
-testando se
nem fsubjedt } ...............................................................................................................................
nem fte * t
estão vazias.
aplicações realistas e práticas
Estou chocado. Quando me esqueci ^
de digitar o assunto no formulário,
recebi esta página. Mas quando cliquei no
botão Back (voltar), tive de redigitar a
mensagem inteira.
A validação no script Enviar Email de Elmer está
funcionando, mas ela poderia ser um pouco mais útil.
Quando o script se n d e m a il.php detecta que estão faltando
dados no formulário, ele exibe uma mensagem dizendo que
alguma informação está faltando, mas só isso. Não há um link para
voltar ao formulário original, por exemplo. E, pior ainda, quando
Elmer navega de volta para o formulário original, as informações
que digitou não estão mais lá. Ele tem de redigitar o assunto e o
corpo da sua mensagem.
CXfcÉRESRO
O que você faria para melhorar o tratamento de
erros do script Enviar Email, de modo a torná-lo
mais útil?
você está aqui > 191
regenerando o código HTML do formulário
Seria legal exibir o formulário junto
( com a mensagem de erro. Será que não j
V poderíamos simplesmente exibir o formulário J
J ( com echo, no caso de o assunto e o corpo do y
^ ---- - texto estarem vazios?
Exibir o formulário definitivamente seria útil, uma vez
que assim Elmer não precisaria navegar de volta à
página original.
Assim, além de apresentar uma mensagem de erro quando um dos
campos do formulário é deixado em branco, nós precisamos também
“ressuscitar” o código HTML a partir do PHP, usando echo para enviá-
lo ao navegador. Este código mostra que o PHP é capaz de gerar
código HTML razoavelmente complexo:
echo ' <label for="subject">Subject of email:</label><br />';
echo ' cinput id-"subject" name="subject" type-"text" ' .
'size="30 " /xbr />T;
echo ' <label for="elvismaii">Body of email:</iabelxbr />';
1cols="40"></textarea><br />';
:ype="submit" name="submit" value="Submit" />';
Se você estiver achando este código um pouco caótico, é porque ele é
mesmo. Só porque você pode fazer algo em PHP, não quer dizer que você
deva fazê-lo. Neste caso, a complexidade adicional de se enviar todo esse
código HTML através de echo é um problema. O código é tão grande que
gerá-lo através do PHP, com a declaração echo, realmente não é uma boa
opção...
echo ' <textarea id="elvismail" name^'elvismail" rows="8"
ajvtdd a visualiza*-
a cstvuWa do par-te, e mais -fádil usar aspas
simples para esdrever strings de
dód.50HTML cm pf}p.
tódigo HTML.
aplicações realistas e práticas
Facilite a entrada ea saída do PHP
As vezes é fácil esquecer que um script PHP é na verdade apenas
uma página HTML capaz de armazenar código PHP. Qualquer
código, em um script PHP, que não esteja dentro das tags <?php e
?>é presumido como sendo HTML. Isso significa que você pode
fechar um bloco de código PHP e reverter ao HTML conforme
necessário, e depois começar de novo com um novo bloco
de código PHP. Esta é uma técnica extremamente útil para se
transmitir um pedaço de código HTML que seja grande demais
para ser gerado através de declarações echo do PHP... como por
exemplo, o código do nosso formulário Enviar Email..
<?php
Esta ta$ $from = 'elmer@makemeelvis.com';
?> -Iredha o
blodo PHP,
nos levando
$subject = $_POST['subject'
]
$text = $ POST[1elvismaíl’]
;
if (empty($subject) && empty($text)) {
de volta 30/j sakem0s que tanto $subject e $text estão faltando
HTML- ^ echo 'Você esqueceu do assunto e do corpo da mensagem
Vbcepode ÇecfecU'
e abtíftjocpg de
c ó d ig o p j j p p q j^
enV
icD
:pedctÇ^Sde
código HTML de
denfto do script?HF-
0 -formulário é
dodi-fidado Como
HTML noTmàl,
vez. <
^u
e este código
+iCd íora das tags
PHP. í
<?php-
}
A tag inidia um novo blodo de dódigo
„ vez- *V*e ainda estamos dentro da
adao de ií, temos de íedhar a dedlaradão
antes de dontinuarmos-
if (empty(Çsubject) && (!empty($text))) {
echo '
Você esqueceu do assunto.<br />';
.
f ((!empty(
$subject)
) && empty{$text)) {
echo 'Você esqueceu do corpo da mensagem.<br />';
Uma vez. <
^»
e ainda
estâmos dentro
da ação de «
•£
, o
dódigo HTML só é
exibido se ambos os
dâmpos do -formulário
estiverem vazios.
if ((!empty($subj ect)) && (!empty{$text))) {
// Código para enviar o email
?> Escreva abaixo qualquer coisa que você considere que esteja
limitando este código. Como você o consertaria?
.v. ' k :v :..
você está aqui ► 193
evitando code duplicado com uma flag
Use um flag para evitar código dDplkstíío duplicado
O problema com o código anterior é que ele precisa sair do PHP e repetir o
código do formulário em três lugares diferentes (um para cada validação).
Nós podemos usar uma variável true/false, conhecida como flag, para nos
mantermos a par sobre a necessidade ou não de enviar o formulário. Vamos
chamá-la de $output_form. Então, poderemos verificar a variável mais adiante no
código, e exibir o formulário caso ela seja true.
Assim, nós começamos o script com $output_form definida como false, e só a
modificamos para true se algum campo estiver vazio e precisarmos exibir o formulário:
£*frf*niv ?«^tput_jform inicialmente
inicialize $output form como false ^ ° ^ue ° -f<**mulario
nao sgrâ exibido a não ser que haja
um problema de validado que -faça o
valor se modi-fitar.
S E Subject está vazio E Body está vazio
Estas meKsagefts E N T Ã O exibir mensagem de erro, definir $output_form como true
de erro são ^ * 7 K ^ p
--------------- . Se um tampo -ror
deixado em brando,
S E Subject estiver vazio E Body N Ã O estiver vazio a variave! ?output_
•form e de-fmida
li^eiramehtí
di-ferentes,
para mdifiar
oU) tampo(s)
espedrfidofs)
que esteja(m)
vasào(s).
y EN TÃ O exibir mensagem de erro, definir $output__form tomo tru«, mas o
^  c o m o t r u e j^ -formulário nao e
/
exibido-- ainda!
E N T Ã O exibir mensagem de erro, definir $output_form como true
Se ambos S E Subject NÃ O estiver vazio E Body N Ã O estiver vazio
os tampos .
contiverem y E N T Ã O enviar emails
dados, vá em_________
írente e envie
os emails.
S E $output form for true
E N T Ã O exibir formulário Finalmente, veri-fidâmos a variável
?output_-form para ver se o -formulário
predisa ser exibido. De uma -forma ou de
outra, s© pretisamos que o dodi^o HT/VjL.
apareça uma vez. .
aplicações realistas e práticas
Codifique o formulário HTML apenas uma vez
Transformar o novo código de validação em código PHP envolve a
criação e a inicialização da variável $output_form, e depois garantir
que ela vá ser definida ao longo de todo o código de validação. Mais
importante é a nova declaração if ao final do código, a qual só exibe
o formulário se $output_form for definida como true.
<?php
$from = 'elmer@raakemeelvis.coin'
$subj ect = $_POST [
.
’subject '];
$text = $_POST['elvismaíl'];
■
$.output f
o
r
r
r
.^ ■
■
i
faI&e;
"
í
,
■
. ^
Mos. driamos nossa
hova variavei a«^i, e a
AptPVnat 9 c6dígo
H7KÎL dependente
de uma declaração
ÍF, nés eVItamos
duplicação de
codígo n 9 n p s s p
script.
de-fi*imos
temo -false-.
if (empty{$subject) && empty($text)) {
// Nós sabemos que tanto $subject e $text estão faltando
echo 'Você esqueceu do assunto e do corpo da mensagem.<br />';
}
Soutput_±orr
c = true; '
if (empty($subject) && (!empty($text))) {
echo 'Você esqueceu do assunto.<br />';
íiS ilillB iS ílllc u e ;.■^ _
}
Peíme a variável tom
otrue se tanto
fsubjedt «yd**5
0? te * t estiverem
Yãrè *ue o íormuiário seja exibido-
Tãmbem deíine a variável £0mo
true se fsubjedt estiver vazia-
if ((!empty($subject)) && empty($text)) {
echo 'Você esqueceu do corpo da mensagem.<br />';
l l l l l l I l l l l B i l É l l ----- t deíme a variável domo true
} se fte xt estiver vazia-
(!empty($text))
)
if ((!empty($subject)) &&
// Código para enviar o email
í
Esta dedaraçao ií vertida a
variavel fw tp v t.ío r* * ' e exibe o
•formulário daso elâ seja true-
A<m
í, ja saímos do dódi^o PHP,
mas tudo <
^u
e estiver antes
da } de íedharwe^to ainda é
do«siderado domo parte da
ação de i-P - neste daso, è o
^ dódigo HTML do íormulario.
Kao se esqueça de voltar
ao dód'150 PHP e -fedbar
a dedlaraçao ií.
^ 0 íódigo ttT/VjL so afârede uma
vez. desde <ue resolvemos dolodar
toda a io^ida da sua exibidao em
uma S
Ovaviavei; ?outfut_fcrm.
você está aqui ► 195
os dados do formulário continuam desaparecidos
O novo formulário é melhor, mas
eu ainda tenho de refazer o que eu já
havia digitado corretamente, o que é
muito irritante.
O HTML sozinho não é capaz de preservar dados de
formulários.
Quando Elmer submete o formulário Enviar Email com um campo
vazio, o script se n d e m a il.php captura o erro e gera um novo
formulário. Mas o novo formulário é puro código HTML, o qual
não tem como saber nada sobre quaisquer dados que Elmer possa
ter digitado anteriormente. Assim, estamos gerando um formulário
totalmente novo, como parte da validação, o que apaga quaisquer
dados que Elmer possa ter digitado
Pados «ue
Elmer diyfcou «o
íomulâTto-
Eli«er adidentalmente
dci*ou este dampo em
brando-
Esta mehsa^e*« de
erro sivfovma á Elmer
*|ue ele dei*ou um
dampo em brando.
sendemail.html
Iodos OS dâmpos
a$©ra estã<
vazios, porque
este e um
íorrrulav-io fcO
V
O
em íolWa
sendemail.php
0 -formulário t submeti
ao sdript sendemail.pbp
^uândo Elmer dlida no
botao Submit Submete
Péssimo. Não conseguimos contornar o fato de que um novo
formulário terá de ser gerado no script PHP. Nos precisamos
de uma forma de preservar quaisquer dados que Elmerjá tiver
digitando, colocando-os no novo formulário para que ele possa
se concentrar em preencher apenas o campo que acidentalmente
deixou vazio...
aplicações realistas e práticas
Aponte seu lápis------------------------------------------
Esboce aqui como você gostaria que fosse o comportamento do
formulário de Elmer depois que ele o submete com apenas o primeiro
campo preenchido. Em seguida, escreva como você acha que cada um
dos arquivos (HTML e PHP) deve ser alterado para executar esta nova
funcionalidade.
mm
sendemail.php
' j) ............. / ..... ..............
..’
jyí-ry.r^r?...
você está aqui ► 197
faça o formulário “permanente"’
- scolápis---------------------------------— — —-----
Esboce aqui como você gostaria que fosse o comportamento do formulário
de Elmer depois que ele o submete com apenas o primeiro campo
preenchido. Em seguida, escreva como você acha que cada um dos arquivos
(HTML e PHP) deve ser alterado para executar esta nova funcionalidade.
A dc
erro â
i
f
t
d
ât -
•
>
CíCibidâ---
E ste dampo permânede vazi©
porque Elmer rtáo digitou
hâds nele nâ primeira vez-.
•mas o Sdript amdâ se
lembra dos dados <
^u
e
Êl»er digitou e os insere
m hevo formulário.
B
sendemail.php
.Cf.sdript PHP assum
e, a.ta.rç-fa,dç.....
.c.^lbtr o í^mulario,.antes.e depois
da submissão. E uma vez. <
^u
e o
sdript tem adesso a.^uais^uer.dados
«ue tçhbam sido dijitados^ ele
p<^e ihseriv- esses dados no novo
íoy-mulário, íuahdo este fo r gerado,
jsto resolve o problema de. Elmer te r
f^ue rçdi^itar dados ^ue já tenha.....
preendhid©-
sendemail.html
£e exibirmos p.f^mulario..............
.V^iíi^âfíÇ^te .através do sdript. PHP,
podemos eliminar a pagina HTML-,
uma.,yez,^ue,o .sdript. PHP.ira. coibir.
e prodessar o formulário. Ao fazer
isso, o sdript PHP,pode,adessar e.....
usar ^uais^uer dados digitados no
formulário,. o,^ue.e. impossível,dom.....
dodigo .HTML .puro..........................
aplicações realistas e práticas
Um formulário que referencia a si mesmo
Como é possível ter o formulário Enviar Email sem o arquivo
sendem aí 1. html? A resposta é que nós não estamos na verdade
eliminando o código HTML, estamos apenas transferindo-o para
o script PHP. Isso é possível devido ao fato de que um script PHP
pode conter código HTML, como uma página web normal. Assim,
nós podemos estruturar nosso script de modo que ele não somente
processe o formulário após a submissão, mas também o apresente
desde o início, que é o que se n d e m a il.htm l estava fazendo.
A chave para o script sendemail.php ser capaz de desempenhar o
papel de se n d e m a il. htm l é a ação do formulário. Uma vez que
o próprio script agora contém o formulário HTML, a ação nos leva
de volta ao script... um formulário que referencia a si mesmo.
fsfâo «'âV
s
de sendem3sl-WW ~
os usuários *âve$3v5o
direiamentí 3^* °
sdript PHP f>ars usar
o -formulário.
Um formulário
HTML c[iie íaça
parte de um
sctlpt YHF <jue
o ptPCesse e
contecido como
a u tP - r e íe r e n te .
Os dados do -formulário são
$ubme-£idos do mesmo sdrip*t,
o <uâl prodessa e exibe
ftovame>vte o -formulário, mãs
desta vez. cie preserva os
dados já digiiados.
Subftie^v-/
Swbmater
0 sdript midialyrente
»«ostra c -formulário e
depois o prodessa, guando
ele t submetido- 0
prodcssament© resulta ou
«o envio de emaiis ou na
re-exibição do -formulário
dom uma mensagem de erro-
sendemail.php
Para entender o que está acontecendo aqui, pense na primeira vez que Elmer
visita a página (script). Um formulário vazio é gerado como código HTML, e
é exibido. Elmer preenche um campo do formulário e clica em Submit. O
script processa o seu próprio formulário e exibe uma mensagem de erro se
quaisquer dados estiverem faltando. Mais importante, o script exibe o formulário
novamente, mas desta vez inclui quaisquer dados que Elmerjá tenha digitado.
Quando um formulário é inteligente o suficiente para se lembrar de dados
inseridos em submissões anteriores, ele é conhecido como permanente... os
dados permanecem nele!
Os {pOTulátlPS
permanentes se
lembram <k>s dadps
c
[ue o usuárfp ja tlVer
d ig ita d p c o r r e t a m e n t e .
CÉfcEWO
Como você acha que podemos modificar a
aplicação de Elmer para tornar os campos do
formulário permanentes?
você está aqui ► 199
faça a ação do formulário auto-referente
Aponte a apão do formulário para o script
Como já vimos algumas vezes, o atributo action da tag <form> é o que
conecta um formulário a um script PHP que o processa. Para permitir
que o form ulário de Elm er processe a si mesmo, o que é o prim eiro
passo para tomá-lo permanente, você direciona a ação do formulário
para sendemail.php. Na verdade, o formuláriojá tem o seu atributo
action direcionado para o script:
0 atributo adtion da tag <•&*•«*> toneeta 0-formulário
a° o prodessa - neste tssc o mesmo sdript
sendemail.php que armâz£na o -formulário
<form action = nÍHlftlHSÍil|iÍ®" method="post">
L-y_J f f i l Í l I i l Í l l f f l ! l Í Í (_______ _ J
A fcsta e umâ tag <-form> padrão, que As
V ^ usa P0ST para submeter os dados _
_ /
do -formulário ao sdript-
Este código funciona, presumindo-se que você nunca renomeie o script e se esqueça de
atualizar o código. Mas há uma forma melhor, que funciona em qualquer caso, porque
ela não depende de um script específico. Trata-se da variável superglobal interna do PHP
$_SERVER[’PHP_SELF’], que armazena o nome do script atual. Você pode substituir a
URL do script, na ação do formulário, por $_S£RVER['PHP_SELF'], e então jamais terá
de se preocupar em atualizar nada, se algum dia tiver de mudar o nome do script.
O único senão é que $_SERVER[’PHP_SELF'] é código PHP, o que
significa que você tem de enviar o seu valor através do comando echo, para
que ele seja exibido como parte do código HTML, desta forma::
 vez- d< estrever o nome do sdript
permanentemente no £Ódi$o, podemos
instruí—
lo a re-ferentiar a st mesmo, usando
superglobal 1-
<form methott="post">
É claro que usar $_SERVER['PHP_SELF'} em vez do m m e
do script não é um aprimoramento espetacular, mas é uma T 3 e h v b ^ i t h t _
das pequenas coisas que você pode fazer para facilitar a __
manutenção posterior dos seus script. vt/L /T J f â fÚ c lZ & flc t 9
riP U le J p s c r i p t a tu a l.
aplicações realistas e práticas
TfeST O
rive
Teste o novo script autorreferente, com a lógica de
validação aprim orada. 0
Modifique o código de sendemail.php de modo que ele use a variável $output_
form para exibir o formulário seletivamente, como mostrado algumas páginas
atrás. Modifique também o atributo^ct io n da tag <form> de modo a tornar
o formulário autorreferente.
Você não precisa mais da página se n d e m a il.htm l no seu servidor web,
portanto, esteja à vontade para apagá-lo. Em seguida, envie a nova versão
do script sendmail.php para o seu servidor e abra-o em um navegador. Está
tudo funcionando?
Por âlgum motivo, O
script esta mostrando
uma me*sa4em de erro,
embora o formulário
fiáo tinha nem sido
submetido... nada bom.
Mak^MisELVfs.eoM
Private: For Hlinefsuse ONLY
WHtearri sand an email tomailing Sistmembers,
(^You forgotthe email subject and body S&xt)
SSU
jtw
ltrfew
iaii. ... . ■ .
t r .
fc: *3o t so isso*
fo rm u lário amda «ao esta
preservando os dados
distados. P
(vd&temos
trabalb© a fa « r!
iffPlW
??? W
ff?
Mas vamos domedãr pelo domeÇo-
Logo passaremos para a parte 
da preservado dos dados. )
Escreva aqui o motivo pelo qual você acha que o script está mostrando uma
mensagem de erro na primeira vez que o formulário é mostrado.
.. . Ç ju d p . í À * .... ..p.->.. ...-ç/k.. ..
....................................... ...............
' ' / ? *
você está aqui ► 201
verifique o $_POST[‘submit’]
Verifique se o formulário foi submetido
O problema é que o script não é capaz de distinguir entre o formulário estar sendo exibido pela
primeira vez e estar sendo submetido com dados incompletos. Assim, o script relata o problema
de dados faltando na primeira vez que o formulário é exibido, o que é confuso. A questão é:
como podemos verificar se o formulário estã sendo submetido? Se tivermos essa informação,
podemos nos certificar de só validar os dados quando houver uma submissão.
Você se lembra de como os dados são armazenados no array $_POST, quando um
formulário é submetido usando-se o método POST? Se o formulário ainda não tiver sido
submetido, então o array $_POST ainda não terá sido preenchido com quaisquer dados.
Ou, colocando de outra forma, o array $_POST ainda não terá sido definido. Alguma
sugestão de qual função poderíamos chamar para ver se o array $_POST está definido?
)o issrtO verí-fidâ se uma
-Ç
unÇ
ac
variável íoi de-£mtdâ-
2
i f ( l i l l l i l l i i l l i l l i i i l
Bstfi deve ser o mesmo nome da ■
bâg
<i»puè> usada dom o seu boiao Submit
) {
$ualrçuer dodi^o 3<ui so sera e^edu'tado
formulário tiver sido submetido-
se o
Uma vez que todo formulário tem um botão Submit, uma forma
fácil de se verificar se o formulário foi submetido é ver se existem
dados em $_POST para o botão Submit. Os dados são apenas
o rótulo do botão, o que não é importante. O importante é
simplesmente a existência de $_POST [
'submit' ], o que nos
diz que o formuláriojá foi submetido. Apenas certifique-se de
que o texto 'submit' seja o mesmo do atributo id do botão Submit,
no código do formulário.
A supejrglokal
$_POSTnes
permite Veriílccií
se um formulário
foi submetíclo.
Hclo existem
?
petgimtas idfotas
Como o conhecimento de se o formulário foi
submetido ou não nos impede de exibir mensagens
de erro de validação acidentais?
K : 0 motivo pelo qual as mensagens de erro estão
sendo mostradas incorretamente é que o script não
consegue distinguir entre o formulário ser submetido e
ser exibido pela primeira vez. Assim, precisamos de uma
maneira de saber se esta é a primeira vez que o formulário
está sendo mostrado, em cujo caso é perfeitamente OK ter
campos vazios - não se trata de um erro. Nós só devemos
validar os campos se o formulário tiver sido submetido;
portanto, a capacidade de detectar a submissão do
formulário é muito importante.
r:Então por que não verificamos se existem
dados diretamente nos campos do formulário, em
vez de no botão Submit
Seria perfeitamente aceitável verificar
$_POST[ ' s u b j e c t ' ] ou $_
p o s t [ ' e l v is m á il' ], mas apenas para este
formulário em particular. Uma vez que todo formulário
tem um botão Submit que pode ser consistentemente
chamado de submit, verificar $_ p o s t
[ 1s u b m it' ] lhe fornece um modo confiável de checar
a submissão do formulário em todos os seus scripts.
aplicações realistas e práticas
.0scriptEnVicir Emailemdetalhes
Attc
$text = $_P0ST [
.
'elvismail'];
$output__form = false;. ■
if (empty($subject) && empty<$text)) {
// Nós sabemos que tanto $subject e $text estão faltando'
echo 'Você esqueceu do-assunto e do corpo da mensagem.<br />'.;
$output_form - true;
if (empty($subject) && (!empty($text))) {
echo 'Você esqueceu do assunto.<br />';
$output_form = true;
}
if ((!empty(
$subject)) && empty($text)) {
echo 'Você esqueceu do corpo da mensagem.<br />';
$output_form = true;
}
if ((!empty ($subject)) && (!empty($text))
) {
// Código para enviar o email
<form method="post" action="<?php echo $_SERVER['PHP_SELF1]; ?>">
<label for="sub]ect">Assunto do email:</label><br />
<input id="subject" name="subject" type="text" size="30" /xbr />
<label for="el vismail">Corpo da mensagem:</labelxbr />
<textarea id="elvismail" name="elvismail" rows="8" cols="40"x/
textareaxbr />
<input type="submit" name="submít" value="Submit" />
i-have -PetHa a primeira
é lsè y
.
$oucput_fci-ín
mosbrâ-leJ
pv-edisamos
if ($output_form) {
?>
</form>
<?php
?>
você está aqui ► 203
faça os campos dos formulários “permanentes”
Legal. Então agora
nós podemos detectar a submissão do
formulário e mostrar as mensagens de erro
corretamente. Mas ainda não tornamos os
campos do formulário permanentes, certo?
É verdade. Detectar a submissão do formulário é
importante, mas ainda precisamos de uma forma para
, m anter os dados permanentes.
I Saber se o formulário foi submetido é uma parte importante de torná-
I lo permanente, mas não é a única. A parte que está faltando é a que
' toma quaisquer dados que tenham sido submetidos e os coloca de
volta no formulário, quando este é re-exibido. Você pode definir um
campo de input do formulário usando o atributo value da tag HTML
< input> . Por exemplo, o seguinte código pré-define o valor de um
campo de input usando o atributo value:
V
âlo
V
" tstd CSiríto í»0 •
—
ele f.
scmpve o mesmo, a tèéè vez. <
^ue o -Formulário z mostrado.. ^
Mas não queremos escrever um valor específico de forma permanente no
código. O que queremos é inserir a informação retirada de uma variável PHP.
Como fazer isso? Lembre-se de que usamos echo para gerar código HTML
dinamicamente a partir de PHP, em outras situações. Neste caso, podemos
usar echo para gerar um valor para o atributo value a partir de uma variável
PHP, desta forma:: A ./-,/•
cinput type^subnnit" name^'submit" value="Submit" />
</form>
l>
n vãriãve! z enviaaa usando-se
< in p u t n a m e - s u b je c t” ty p e = " te x t"
L
<
i
*
t
p
i
n
v
»vá MfiUW
permâWfttes <
^*e Então, o formulário de Elmer pode ser modificado de forma semelhante,
se ewioh-èram para tirar proveito dos dados permanentes:
aplicações realistas e práticas
T te S T O R fv e
Verifique se os dados de Elmer realm ente estão permanecendo.
M odifique o código de sen d em ail.p h p de m o d o q u e ele verifique em $_POST se o
form ulário foi subm etido, e adicione tam bém o código ech o p ara to rn a r os cam pos
p erm an en tes. Envie a nova versão script p ara o seu servidor web e abra-o em um
navegador. E x p erim en te d iferen tes valores p ara os cam pos do form ulário, d eixando
um ou am bos em bran co , e subm eta-o algum as vezes.
0 sdv"ipt dc tnviôv*
agora mosfarâ umâ menSâge»*
de erro ^ando ííWer dei^i
um tan»po do forwulario
ew
> brando, ȉs ele
mantem os dados digitados
anteriormente-
você está aqui ► 205
quando bons DELETES viram maus
Alguns usuários ainda estão insatisfeitos
A validação do fo rm u lário nos ajudou b astante a lid ar com os clientes
insatisfeitos de Elm er, p articu larm en te aqueles q u e estavam receb en d o em ails
em branco. Mas n em todos estão felizes. P arece q u e algum as pessoas estão
rec eb en d o em ails duplicados... lem bra-se deste cara, do início do capítulo?
From: SbertKresíee<et0ert@Krssleesptocket5.biz>
Subject: Spam?
Dais: October24k£008 12:20:33 PMCOT
To; EimerPnesüey<e3m&f@fralæmee3vis.€om>
Elmer, r
PorfavorwMecomospam Eugosto de ruceteroseimailatfeofertes, mas j:
mandoumsó. Nàopreciscrôcefeertrésmensagenstotevözquetsmursaoferta. ,
Sauteats incomodadocitent«,
Ebert
Bsie filie«te esta
fvustvado por^ue est
refiebendo miîltiplas
Copias dos emails de
£îmer.
E lm er sabe que n ão digitou a m esm a m ensagem m ais de u m a vez, o q u e o leva a
suspeitar que talvez alguns usuários acid en talm en te ten h am se inscrito n a sua lista
m ais de u m a vez. Sem problem as, basta usar a p á g in a /sc rip t de R em over Em ail do
capítulo an terio r p ara rem over o usuário, cefto?
Infelizm ente, n ão é tão sim ples assim. R em over E lb ert u san d o o en d ereço d e em ail
dele fará com que ele seja co m p letam en te apagado d a tabela em ail_list, e com isso
ele n u n c a m ais receb erá n e n h u m em ail de Elm er. Precisam os de u m a m an eira de
ap ag ar apenas as linhas duplicadas de E lbert n a tabela, d eix an d o um a.
Usar a p%mâ de Remover £mail
do tafítui® anterior removeria
inteiramente o dlienic do bando
de dados de £Uer, e fcão e isso o
<
^
u
e Queremos.
_ ® W E R ' > 0 __________________________
D C C É R E S R Q
Como Elmer poderia apagar todas as linhas da sua tabela
que tiverem endereços de email idênticos, exceto uma?
aplicações realistas e práticas
Hmm. O problema é que há linhas repetidas na
tabela, mas não temos nenhuma forma de distingui-las
umas das outras. Sem uma forma de isolá-las, qualquer
DEIETE que tentarmos usar irá apagá-las todas.
Joe: Talvez o nosso formulário Adicionar Email devesse verificar
os endereços de email antes de adicionar novos usuários. Isso
consertaria o problema, certo?
Frank: Excelente ideia.
Jill: Sim, isso resolveria o problem a para o futuro, mas nao nos ajuda
a lidar com endereços de email duplicados que já estejam no banco
de dados.
Frank: Certo. E se tentássemos usar um a coluna diferente da tabela
para apagar as linhas extras, como por exemplo, Iast_name?
.Jill: Também pensei nisso, mas usar um sobrenom e pode acabar
sendo pior do que um endereço de email. E se quiséssemos apagar
alguém chamado John Smith da nossa lista, usando o seguinte
código SQL:
DELETE FROM e m a i l _ l i s t ' WHERE la s t_ n a m e = 'S m i t h 1
Joe: Isso não apagaria apenasJohn Smith da tabela; estaríamos
apagando também Will Smith, Maggie Smith, Emmitt Smith...
Frank: E, isso não seria bom. A probabilidade de sobrenomes se repetirem em várias linhas é maior
do que a dos endereços de email, e primeiros nomes seriam ainda piores. Poderíamos perder
dezenas de linhas com um a simples consulta.
Jill: Exatamente. Não podem os nos arriscar a usar um a cláusula WHERE que apague linhas
que querem os manter. Precisamos ter certeza de que podem os especificar apenas aquelas que
querem os remover.
Joe: Então o que fazer? Não podemos usar e m a il, l.ast_ n am e nem f ir s t _ n a m e em nossa
cláusula WHERE.
Frank: E não temos outras colunas para usar, na nossa tabela. Parece que estamos sem sorte.
Jill: Não necessariamente. O que realm ente precisamos é de algo para tom ar cada linha da tabela
identificável individualmente - assim poderíamos especificar linhas sem nenhum problema. E só
porque não temos atualmente um a coluna com um valor único para cada linha, não significa que
não podem os adicionar uma.
Joe: Uma nova coluna? M asjá temos um a estrutura para a nossa tabela.
Frank: Sim, mas o que temos não está atendendo às nossas necessidades. Você tem razão, teria sido
m elhor se tivéssemos previsto esta situação antes, para que pudéssemos ter elaborado nossa tabela de
m odo a evitar este tipo de problemas, mas não é tarde demais para consertar o que temos.
Joe: OK, mas que nom e daremos à nossa nova coluna? E que dados colocaremos nela?
Jill: Bem, um a vez que o propósito seria identificai" individualmente cada linha da tabela, poderíamos
chamá-la de i d e n t i f i c a d o r , ou apenas id, para abreviar.
Frank: Ótimo, e podem os preencher a coluna id com um núm ero de identificação para cada linha,
de m odo que quando executarmos nosso DELETE, poderemos remover linhas com base em um
núm ero individual, em vez de em um endereço de email ou sobrenome.
Joe: Exatamente. E um a ótima ideia, não? Fico feliz de ter pensado nela.
você está aqui ► 207
adicionando uma coíuna com chave primária para uma tabela
As linhas databela precisamser identificáveis individualmente
P arte de to d o o processo de se arm azenar algo em u m banco de dados é que,
posteriorm ente, você irá q u erer p ro cu rar esses dados e fazer algo com eles. S abendo disso, é
incrivelm ente im p o rtan te q u e cada lin h a de u m a tabela seja identificável individualm ente,
o que significa q u e você p o d e acessar cada lin h a especificam ente (e som ente a lin h a em
q uestão!). A tabela em ail_list de E lm er faz u m a perigosa assunção de que os endereços de
em ail serão únicos. Isso funciona, desde que nin g u ém acidentalm ente se inscreva n a lista
duas vezes, m as qu an d o alguém o fizer (e alguém o fará, p o d e ter certeza!), o seu endereço
de em ail será arm azenado n a tabela duas vezes... e acabou-se a unicidade!
0 que a tabela de Elmer contém agora:
Mais de u»a pessoa pode ter o
mesmo primeiro nome, portanto,
esta não e uma boa opção para
doluna identiíidadora.
0 mesmo a^ui, «ao podemos
dontar tom sobrenomes
para ídentifidação.
Nada na estrutura
desta -tabela garante
identidade para as linhas-
ttst name : lastMiné -
Denny Bubbleton denny@mightygumball.net
Irma Werlitz iwer@aliensabductedme.com
Elbert Kreslee elbert@kresleesprockets.biz
Irma Kreslee  elbert@kresleesprockets.biz
£ embora os
endereços de
email sejam <y*ase
sempre unidos, nâo
podemos doníiar
sera
sempre o daso.
Se você n ão tem u m a co lu n a de valores realm en te únicos em u m a tabela, en tão deve criar
um a. O MySQL lh e oferece u m a fo rm a de ad icio n ar u m a co lu n a de n ú m ero s inteiros
individuais, o q u e tam b ém se ch am a de chave prim ária, p ara cada lin h a da sua tabela.
0 que a tabela de Elmer deveria conter:
---------nretisamos At una neva Coluna <ue dontínha
V val°r unido para dada linha da tabela.

H » A first.name lastjianiè email
1 y Denny Bubbleton denny@mightygumbaîl.net
2 Irma Weriitz iwer@aliensabductedme.com
3 j Elbert Kreslee elbert@kresieesprockets.biz
4 / irma Kreslee elbert@kresleesprockets.biz
Agora «ue esta doluna dontém um
valor unido, podemos ter t,f Y de
c^ue dada linha da nossa tabela sera
realmente unida-
0&dados duplidados nas
outras dolunas não a-fetam
mais a unididade das linhas,
porque a nova doluna id
duida disso-
aplicações realistas e práticas
Ei, gênio, você sabe que, se quisermos fazer
uma modificação na estrutura de uma tabela,
temos de usar um DROP TABL6 e recriá-la do
zero. Os dados de Elmer serão perdidos!
É verdade que DROP TABLE destruiria os dados de Elmer.
Mas o SQL tem outro comando que lhe perm ite fazer
modificações em uma tabela existente, sem perda de dados.
Trata-se de ALTER TABLE, e p o d em o s usá-lo p ara criar u m a nova co lu n a sem
te r d e excluir a tab ela e d estru ir os seus dados. Eis o fo rm ato geral de um a
instrução ALTER TABLE p ara se ad icio n ar u m a nova co lu n a à tabela:
r
0 nome da tabela 3
ser alterada-
0 nome da doluna a
ser adidionada.
da coluna
[nome_da_tabela ADD nome_da_coluna tipo_
0 -tipo de dados
da nova doluna-
Nós podem os usar o com ando ALTER TABLE para adicionar u m a nova coluna à
lista e m a il l i s t , a qual cham arem os de id . Nós darem os à coluna id o tipo INT,
u m a vez que núm eros inteiros são ideais para estabelecer a unicidade. Algumas
outras inform ações são tam bém necessárias, com o revela este código:
Queremos adidionar M» diz- ao servidor A1y£#L para
h0"‘c da tabela «ue (£pp) uma nova doluna, adidionar I ao valor armazenado nesta
geremos alterar. ^ tramaremos de id- para dada nova linha inserida.
ALTER TABLE em ail_list ADD id INT NOT NULL AUTO_INCREMENT FIRST,
ADD PRIMARY KEY (id)
£ste pequeno pedalo
de dodigo diz. ao
<ue a nova
doluna sd é a dhave
primária da tabela.
Falaremos mais sobre
isso mais adiante!
/ “ e r
0 tipo de dados FíRST instrui o MySQL a +azetr dom «ue a
da doluna, INT. nova doluna sea a primeira da tabela. Isto é
opdionali mas e uma boa pratida dolodar a sua
doluna de identifidâdão em primeiro lugar .
Esta instrução ALTER TABLE tem u m m o n te d e coisas aco n tecen d o , e
isso é p o rq u e as chaves prim árias precisam ser criadas com características
b astante específicas. P or exem plo, N O T N U LL diz ao MySQL q u e é
preciso haver u m valor n a co lu n a id —n ão se p o d e n u n c a deixá-la em
branco. A U TO _IN CR EM EN T descreve ain d a m ais as características
da coluna id, fazendo com q u e ela receb a au to m aticam en te u m valor
n u m érico único a cada vez q u e u m a nova lin h a é inserida. C om o o n o m e
sugere, A U TO _IN CR EM EN T au to m aticam en te ad icio n a 1 ao ú ltim o valor
id usado em u m a linha, e coloca o resu ltad o n a co lu n a id d a sua nova
linha. F inalm ente, PRIMARY KEY diz ao MySQL q u e cada valor d a colu n a
id é único, m as existem m ais coisas aí d o q u e apenas a unicidade....
você está aqui ► 209
tudo sobre chaves primárias
As chaves primárias possibilitam a
identificapão individual
U m a chave prim ária é um a coluna que distingue, em um a tabela, cada
linha com o sendo única. Ao contrário das colunas norm ais, que tam bém
podem ser elaboradas de form a a serem únicas, apenas um a coluna
pode ser designada com o a chave prim ária. Isto cria a possibilidade de se
fazerem consultas que precisem apontar um a ou mais linhas específicas.
Para g aran tir a u n icid ad e das chaves prim árias, o MySQL im põe u m a
série de restrições sobre a co lu n a d eclarad a com o PRIMARY KEY.
Você p o d e p en sar nessas restrições com o regras a serem seguidas, no
seu trab alh o com as chaves prim árias:
Uma ctaVe
p r im á r ia é u m a
oeluna da sua
t a b e l a < jue t e r n a
cada linha única.
As cinco regras das chaves primárias:
Os dados de uma chave primária não podem ser repetidos.
lÊBÈÈkA' N u n ca duas linhas p o d em te r os m esm os dados nas suas chaves prim árias.
Sem exceções ~ u m a chave p rim ária deve sem p re te r valores únicos d en tro
V de u m a d ad a tabela.
Uma chave primária deve sempre ter uma valor.
Se u m a chave p rim ária fosse deix ad a vazia (N U L L ), ela p o d eria não ser
única, p o rq u e outras linhas p o d eriam tam bém sér N U LL. S em pre d efina as
^ suas chaves prim árias com valores únicos!
^ A chave primária deve ser definida sempre que uma nova
dffigfcjp linha for inserida.
_ jjfW Kr Se ho u v er a possibilidade de você in serir u m a lin h a sem u m a chave
XJ prim ária, você co rreria o risco d e te r chaves N U LL e linhas duplicadas n a
sua tabela, o q u e acabaria com to d o o propósito.
A chave primária deve ser o mais eficiente possível. U m a chave
prim ária deve conter apenas as inform ações de que precisa para ser única, e
n ad a mais. E p o r isso que núm eros inteiros rendem boas chaves prim árias - eles
^ perm item a unicidade sem exigir m uito espaço de arm azenam ento.
jfdQPjp O valor de uma chave primária não pode ser modificado.
JSKREm Se ho u v er a possibilidade de você m odificar o valor d a sua chave, você
C T co rreria o risco d e acid en talm en te defini-la com o u m valor já usado.
L em bre-se, a chave precisa se m an ter única, a q u alq u er custo.
A doluna id na tabela de
£lmer não tem dados
repetidos, tem um valor
diíoresvte para cada linha, t
automaticamente definida
guando uma hova linH
â c
inserida, e dompadta e não
se modiíióâ- Períeita^
s i i n i « l I S I ü l l ü i B i l l i i i i l l i i htliiilí l
i
l
i
l
j ;
i
j
f
J
^
1 Denny Bubbleton denny@mightygumball.net
2 Irma Werlitz iwer@aliensabductedme.com
J h m m m ,
.^ * *m Ê 3 ^ ^ È m Ê È m è
~— T fe s T O R tv e
aplicações realistas e práticas
Altere a tabela de Elmer e tente inserir uma nova
linha de dados com uma chave primária.
U sando u m a ferra m en ta MySQL, com o o term in al M ySQL o u a
guia SQL de phpM yA dm in, digite a instrução ALTER TABLE p ara
ad icio n ar um a coluna de chave p rim ária ch am ad a id :
ALTER TABLE email_list ADD id INT NOT NULL AUTO_lNCREMENT FIRST,
ADD PRIMARY KEY (id)
A gora insira u m novo cliente no ban co de dados, p ara ver se a co lu n a i d é
au to m aticam en te d efinida n a nova linha. Eis u m exem plo de instrução INSERT p ara
ser usada (rep are q u e a chave p rim ária n ão é m en cio n ad a):
INSERT IN TO e m a i l _ l i s t ( f ir s t _ n a m e , la s t_ _ n a m e , e m a il)
VALUES ('Don', ’Draper', 'draper0sterling-cooper.com')
F inalm ente, em ita u m a instrução SELECT p ara visualizar o
co n teú d o da tabela e ver a nova chave p rim ária em to d a a sua
glória! Caso te n h a se esquecido, eis aqui a instrução SELECT:
SELECT * FROM email_list
A nova iolwnâ id c au-fco-
ihdircmch-fcada, de modo a
femanedev mttã tom a adição
da nova Jinha de dados-
I File Edit W indow Help Email
nysqi> SELECT' * FROII email list;;
, •
. ;
i
+----- — — ---- --- 4
.
.
,
-------- ---
; id I iirstjname i last name ; | ema x1 / .1 ;
i
+ +
| I ; Denny' I
: Bubbleton i dennySrrightygumball.net [ :
!
; 2 IIrma i Werlitz |'iwer@aliensabductedir.e .com 1
! 3 I Elbert :i Rreslee j elbert@kresleesprockets.biz j
| 4 i Irma I Kreslee ! elbert@kreslee3prockets.biz ' ■
J
'jNvS !
. Don | Draper ! drapergsterling-cooper.com ! «
5 rows in set (0.00 C5 sec)
você está aqui ► 211
conversa à três
OK, agora cada linha da tabela
tem uma chave primária única. Como isso ajuda?
Elmer ainda está deletando os usuários com base nos
endereço de email.
Joe: O problem a é que o usuário precisa especificar as linhas
usando a chave prim ária, em vez do endereço de email.
Frank: E isso! Então só precisam os m odificar o form ulário para
que o usuário digite a ID do cliente, em vez do endereço de
em ail. Sem problem as!
Jill: N a verdade, h á um problem a sim. O usuário não tem com o
saber qual é a ID do cliente sem ter algum a form a de procurar
essa inform ação no banco. Na verdade, o usuário não sabe nada
sobre a estrutura do banco. Talvez o que precisam os aqui é de
m odificar o form ulário, de form a que ele m ostre todos os nom es
e endereços de em ail em um a lista, com caixas de verificação ao
lado de cada nom e. Seria mais ou m enos assim:
Frank: Bonito desenho, mas com o isso ajuda Elm er a isolar um cliente para rem oção,
usando a ID?
Joe: H m m . E se arm azenássem os a ID do cliente no valor da caixa de verificação? A ID não
ficaria visível ao usuário, m as o script teria acesso a ela.
Jili: ó tim a ideia. Poderíam os então gerar o form ulário autom aticam ente, em um loop,
fazendo um SELECT para obter os dados e depois criando cada caixa de verificação a partir
de um a linha dos dados da consulta.
Joe: ó tim o . Mas o que acontece quando o botão Subm it é pressionado? Q ual será o
conteúdo de $_POST?
Frank: U m m inuto Joe, chegarem os lá em um instante. Mas vamos com eçar criando esta
p arte do script, a parte que exibe todos os dados da tabela e gera as caixas de verificação...
aplicações realistas e práticas
imãs de Geladeira PH? &My-SoL
<img src=”blankface.jpg" width="16l" height="350" alt=’
"’ style="float:right" />
<img name="elvislogo" src=''elv-islogo.gif" width="229" height="32" border="0"
alt=”Make Me Elvis" />
<p> Por favor selecione os endereços de email a serem apagados e clique em
Remove.
</p>
<form method="post" action=" echo $_SERVER['PHP__SELF']; >
<?php
$dbc = mysqli connect('data.makemeelvis.com'r 1elmer', 'theking’, 'elvis__store'
)
or die('Erro ao conectar servidor MySQLr.’);
// Exibe as linhas com os clientes e as caixas de verificação para apagá-los
$query = "SELECT * FROM email_list";
$result = mysqli_query($dbc, Squery);
while ( = mysqli_fetch_array($result)) {
echo ’
<input’
type="checkbox" value="1 . •
name="todelete[]” />’; ..............................
echo '
echo ’ ’ .
echo ’ ' .
echo '<br />';
mysqli_close($dbc) ;
?>
</form>
<input type="1
submit" name="
im
" value="Remove" />
ímãs php & mysql - solução
imãs de GeladeiraTH? &M/SQL - $ojuçã°
Use os ímãs abaixo para completar o código do script Remover Email, o qual deverá
apresentar uma caixa de verificação para cada cliente presente no banco de dados de
Elmer. Repare que este código apenas cria o formulário; por enquanto, não se preocupe
com o código que realiza o DELETE.
<img src="blankface.jpg" width="161" height="350” alt=’
"' style="float:right" />
<img name="elvislogo" src="elvíslogo.gif" width="22 9n height="32" border="0" ^
alt="Make Me Elvis" /> dodí^c
<p>Por favor, selecione os endereços de email a serem apagados e clique em de
èmds
U
irtá
Remove.</p>
<form rnethod="post" action="
<?php ícho $_SERVER ['PHPJ3ELF '];
Bste dódigo c autorre-Pevente/
?> ik ser dol<
dentro dJ
% <??4
<?php e ^
$dbc = mysqli_connect(1data.makemeelvis.com' , 'elmer', 'theking', ’
elvis_store’)
or die('Erro ao conectar ao serviço MySQL.');
// Exibe as linhas com os clientes e as caixas de verificação para apagá los
$query = "SELECT * FROM emailJList";
$result = m y s q l i_query($dbc, $query);
while (
íd
echo '<input type='’
checkbox" value=" ' .
name="todelete[]" />’;
fir s t name
£ a
<
wo
u
t â í-Kave primavial
e usada nas daixas de
veriíida^ac —podemos «sar
ísto a^ui mais adiante, para
remover «^uais^uer usuários
seledionados
Cada dai*a de veri-Pidadao
t donstvvfda a pârtir de
uma iinK
a de dados dos
diientes.
}
mysqli_close($dbc);
?>
<input type="submit" name=r
</form>
submit. value="Remove" />
0 sdript a'mda nâo esta
apagando nada- Por
enquanto, ete apenas
apresenta uma lista de
daíxas de veri-hdâdao.
l/ode pode dar ^uaí^uer nome
nuisc'r 3o seu botã©
Submit —m
<
3s predisará
lembrar-se do nome
posteriormente, daso dedida
usar f_PO£T para verilidar
se o lormulirio íoi submetido.
removeemail.php
aplicações realistas e práticas
Pas caixas de verificação até as IPs dos clientes
O código p ara as caixas de verificação geradas pelo script R em over Em ail é sim ples HTM L,
com a nossa chave prim ária (id) colocada n o atributo valor d a tag <input>. N o entanto,
hã um a p eq u en a, porém , m uito im p o rtan te m odificação em relação ao código H TM L
com um . Você pod e te r rep arad o que h á colchetes ([ ]) no final do n o m e da caixa de
verificação - eles servem a um propósito vital.
echo 'cinput type="checkbox" value="' . $row['id!]  name="§tílÍ®S|i#|i|si,
l
>';
Os colchetes resultam n a criação de u m array d en tro de S_POST que ^ toltHetes ao
arm azena o conteú d o do atributo (valor) de cada caixa de verificação
m arcada n o form ulário. U m a vez que o atributo value de cada caixa
contém u m a chave prim ária, cadavalorno array todelete é a ID de
uma Unhadanossa tabela que precisa ser apagada. Isso nos possibilita
fazer um loop através do array todelete e em itir um a consulta SQL
p ara apagar cada cliente m arcado no form ulário.
-Ç
inâl do da
d t veri&daÇâ©
aiA-fcomaiií-ametvte eolodsm
os valores da e**
w ôv-vay a demos o
«ome "Wele-beCÍ3
-
c « x M a te tfe E L v fs x o M
Cada tai*a de te»
a ID do dien-te armazenada, tfs.
,ue Íiía aíessfvel atvav» da
suferjlobal f J W .
d
r
a
p
e
w
g
stsilin
a
n
a
e
a
p
e
,..O
T
(
T
.
Entendi. Podemos
simplesmente usar um loop com while para
fazer um ciclo através do array todelete e
apagar cada um dos clientes usando as suas
lbs.
Nós poderíamos usar um loop while, mas há uma
solução mais elegante que usa um tipo diferente de loop.
O lo o p fo reach é um tipo especial de loop elab o rad o especificam ente
p a ra se fazer u m ciclo através de valores arm azenados em u m array.
Tudo o q u e você precisa fazer é especificar o array através do qual
q u er fazer o loop, além de u m a variável o n d e arm azen ar os valores,
e o PH P cu id ará d e fazer as iterações neles, u m p o r um ... n ão é
necessária n e n h u m a condição de teste!
Escreva aqui como você acha que um loop foreach poderia fazer
iterações através de um array contendo as IDs dos clientes de Elmer:
você está aqui ► 215
anatomia de um loop foreach
Fapa loop através de um array com foreach
O loop fo reach to m a u m array e faz loop através de cada elem en to do array sem a
necessidade d e u m a condição d e teste n em u m co n tad o r de loops. A m ed id a que
passa através d e cada elem en to do array, ele arm azena o valor desse elem en to em
u m a variável tem p o rariam en te. A ssum indo-se que o array está arm azen ad o em u m a
variável ch am ad a $custom ers, este código faz o loop:
0 array através do <uai vede deseja £ med.da o loop passa através de
ía « r o loop aparede primeiro elemento do array, ele os armazena
temporariamente em uma variável dom este
lUtÜill ( ^ c u s t o m e r s a s C u s t o m e r ) {
nome.
a c h o $ c u s t o m e r ;
Dentro do loop, vode pode adessar dada
elemento, usando o nome da variavel-
Assim, se quiséssem os fazer u m loop através das IDs dos clientes arm azenadas n o array
$_PO ST do script R em over Em ail, po d eríam o s usar o seguinte código com foreach:
o array t armazenado
dentro da superglobal f^POST, e
t identi-fidado por "todelete”.”
Cada elemento do array íida
adessfvel através da variavel
fdeiete id-
f o r e a c h a s
11«« 1 » <
k
í*silílflffllim
liiiil
/ / A p a g a um a l i n h a d a t a b e l a
}; Podemos usar ?delete_jd para
remover dada um dos dlientes
do bando de dados.
A variável $ d e l e t e _ i d arm azena o valor de cada elem en to d o
array à m ed id a q u e o loop passa p o r eles, u m de cada vez.
$delete_id ^
Podemos usar es-i
variavel para ade
a ID de dada dlit
« entao apa«á-l©
tabelay
Pleaseselectmeemail addressestodeleteiromthe emaS
listsna dick Remove,
jg Denny Bubliletcn d e n n y @ m ig h ty g u m tiaii net
^ Ima Wurfitt iwer©a ItensEtKJjctsiime oom
□ BberttíreáeeelbertetoBsleesprictetsJíli - "
g Irma Kre&iae elbert@«resieesproârate.biz
|g Don Draper arapergsfeflwg-oo^er com
Com o loop f o r e a c h agora passando através da cada caixa
m arcad a no fo rm u lário R em over Em ail, só precisam os adicionar
algum código d en tro do loop p ara em itir u m a consulta DELETE,
a qual fará a rem oção p ro p ria m e n te dita de cada lin h a m arcada.
J'/os donstruímos o ârrây
de íorma tal <ue ele so
armazene os dlientes <
^
»e
tiverem sido mardados
no íormulario Remover
Email.
aplicações realistas e práticas
Complete o código do novo e melhorado script r e m o v e e m a i l . p h p de
Elmer, para fazê-lo excluir os clientes que tiverem sido marcados no formulário,
quando este for submetido.
$dbc = mysqli_connect(1data.makemeelvis.com', 'elmer', 'theking', '
elvis_store'
)
or die{'Erro ao conectar no servidor MySQL.');
// Exclui as linhas dos clientes (somente se o formulário tiver sido submetido)
i f { ) í
foreach ($_PÒST['todelete'j as $delete_id) {
}
echo 'Cliente(s) removido(s).<br />';
}
// Exibe as linhas dos clientes com caixas de verificação
$query = "SELECT * FROM email_list";
$result = mysqli_query($dbc, $query);
while ($row = mysqli_fetch_array($result)) {
echo 'cinput type="checkbox" value="' . $row['id’] . '" name=”todelete[]" />';
echo $row[’first_name'];
echo 1 ' . $row[’last_name'];
echo ’ ' . $row['email'];
echo 1<br />';
}
mysqli_close($dbc);
?>
cinput type="submit" name="submit" value="Remove" />
</form> removeemail.php
você está aqui > 217
the revised removeemaii.php script
Complete o código do novo e melhorado script r e m o v e e m a il . p h p
de Elmer, para fazê-lo excluir os clientes que tiverem sido marcados no
formulário, quando este for submetido.
Çdbc = mysqli connect(1
data.makemeelvis.com', 'elmer', 'theking1, '
elvis
store') ~
~
or die('Erro ao conectar no servidor MySQL.');
So exdluir os dlientes se o
ientes (somente se o formulário tiver sido submetido)
echo 'Cliente (s) removido(s) .<br />';
}
// Exibe as linhas dos clientes com caixas de verificação
$query = "SELECT * FROM email_list";
$result = mysqli_query($dbc, $query);
while ($row = mysqli_fetch_array(Çresult)) {
echo 'Cinput type="checkbox" value="' . $row['id'] . '
" name=Mtodelete[]"
-Pormulario tiver sido submetido^
flV
íÇ
T
Y
-— PRO/yj. e»aiMist INHERE id ^ fdelete^d”;
foreach ($ POST['todelete'] as $delete_id) {
esdolHer o dlientc
a ser e%
dluído-
or d'»e(lforro Consultando o bândo de dãdos/)j
/>';
echo ' 1 . $row['last name'];
echo ’ 1 . $row[1email1];
echo '<br />';
0 dodi$o fâra ^erar as daixas
de dada dlientc e o mesmo de
antes.
?>
mysqli_close($dbc);
<input type="submit" name="submit" value="Remove" /> removeemsil.php
</form>
O
HQ a
----- T fe S T D r î v ë _______ _________
aplicações realistas e práticas
Teste o novo e aprimorado script de Remover Email de Elmer.
M odifique o código do script r e m o v e e m a il .p h p de m o d o q u e ele gere
caixas de verificação p ara os clientes, em vez de u sar o velho cam po de texto
com os em ails. Em seguida, adicione o código p ara excluir os clientes sem pre
q u e o fo rm u lário for subm etido. A lém disso, m odifique o atrib u to acd o n d a
tag <form > p ara to rn a r o fo rm u lário au to rreferen te.
A gora q u e r e m o v e e m a il. p h p usa um fo rm u lário au to rreferen te, você
n ão precisa m ais d a p ág in a r e m o v e e m a il. h tm l n o seu servidor web,
p o rtan to , esteja ã vontade p ara apagá-la. Em seguida, envie a nova versão
de r e m o v e e m a il .p h p p ara o seu servidor e abra-o em u m navegador.
M arque as caixas de alguns clientes e clique em Subm it. O fo rm ulário
au to m aticam en te se m odifica p ara in fo rm ar a rem oção dos clientes..
P
leas©selecttheem
ailaddressestodeletefro
m
»10em
ail
listandclickR
em
ove
0 D
ennyB
u
b
b
tetonctennyentightygufflballnat
0 lim
aW
u
rlilziw
ergaitensabductedrne.coffl
0 E
lb
ertK
resleeeJbengkresteesprockets.'D
iz
g tm
al^esle«
Q Don Draperdrapef@sterl)ng-coop«r.oom
^
R
em
ove3
Quando vote u»
dieh-fce e dlida em Subwrb
«le e ve»*ovido do bando de
dados-
H ^ M e E L v ? s . c o f
S S S S 1
“ “ ® * “ " « '™ ''* « .!
r
emoved^ ---
,W
er@
8J,er^M
ucted^ «
Qaben ^ eéeJbsrt@
ft^ MMêi8t&iz
O^l^perdraps^tefing-coQper.cDm
0 sdvift dowiiVrtiS 5 rcm
nodao
do dlîttvU e tânnb«» atualiz-a
a lista - o dliewte e*twido
não apavede »ais.
â
você está aqui ► 219
aplicações realistas epráticas
Sua caixa de ferramentas PHP £ M ySQ l
Você embolsou uma boa
quantidade de tiovas habilidades
em PHP e MySQL ao trabalhar para
fazer a aplicação de Elmer subir de
nível.
você está aqui ►
CAFiTÜLO
4
aplicações realistas e práticas
5 T m t a U i a n d o c o m D a d o s A í n i c t z e n a d o s
em Ar^ufVog
> Quando umBanco de ,
Dados Não é o Suficiente*
Não acredite no hype... pelo menos não naquele sobre os bancos
de dados. Certamente os bancos de dados são maravilhosos para se armazenar todo tipo
de dados que envolvam texto, mas e quanto aos dados binários? Coisas como imagens
JPEG e documentos PDF? Faz sentido armazenar todas essas figuras da sua coleção de
palhetas raras de guitarra em uma tabela de banco de dados? Geralmente não. Esses tipos de
dados normalmente são armazenados em arquivos, e nós os deixaremos nos arquivos. Mas é
inteiramente possível ter o melhor de dois mundos - este capítulo revela que você pode usar
arquivos e bancos de dados juntos para criar aplicações PHP cheias de dados binários.
este é um novo capítulo ► 223
guitar wars precisa de captura de tela
Guitarristas virtuais gostam de competir
A p aren tem en te, o conceito de arte p ela arte n ão é m ais o suficiente,
p o rq u e os jo g ad o res do novo G uitar W ars estão fascinados com a
possibilidade d e to car g u itarra virtual com petitivaxnente. T anto que
eles reg u larm en te publicam as suas m aiores p o n tu açõ es n o site do
G uitar W ars, cuja m a n u ten ção você agora está en carreg ad o d e fazer.
O p ro b lem a é que, atu alm en te, n ão h á u m b om sistem a p ara se
verificar as pontuações.
A aplidaçao guitar W
ars
permite os usuários
ddidionem ás suas
pontuações à lisia.
Sem àljuma -forma
de veri-Pitaçao, não
temos domo saber c^uais
pontuações sao legítimas e
<w
ais *a© são.
Não dá para confiar no texto
D o je ito com o fu n cio n a agora, os jo g ad o re s estão p u b lican d o as
suas po n tu açõ es sim plesm ente com o texto, e tem havido m uitas
discussões sobre quais po n tu açõ es são reais e quais n ão são. Só
existe u m a fo rm a d e p ô r u m fim a todo esse bate-boca e co ro ar o
verd ad eiro cam peão do G uitar W ars...
trabalhando com dados armazenados em arquivos
0 roek À imagem é a prova
O que precisam os p ara d eterm in ar q u em está falando a verdade o u n ão é de
algum tipo de verificação visual. Assim, a aplicação G uitar W ars terá de p erm itir
q u e os usuários subm etam u m a cap tu ra de tela co n ten d o a sua p o n tu ação ,
q u an d o forem in clu ir esta últim a. Isso significa q u e a lista dos reco rd es não
co n terá apenas pontuações, nom es e dadas, m as será tam b ém u m a lista de
im agens (telas cap tu rad as). a vev>í'ítâ^Ío
C
^
u
cUdxc í ^ awd€-
A d t Belftâ
t vcvdadeiv-a, tomo
^roVâ â
eiâ enviow.
S 9
t s t ' í td tx ,
^scudortro^uciro
e •taUiíidâdor do
éjwiav V
V
avs.
você está aqui ► 225
o design da aplicação guitar wars
A aplicapão precisa armazenar imagem
D o je ito com o está, a aplicação d e recordes do G uitar W ars registra três tipos d e
inform ações: a d ata e h o ra de u m a nova p o n tu ação , o n o m e d a pessoa q u e a está
su b m eten d o e a p o n tu ação p ro p riam en te dita. Essas inform ações são digitadas através
de um fo rm u lário q u e faz p arte d a in terface d e usuário d a aplicação, e depois disso, são
arm azenadas em u m a tabela ch am ad a g u i t a r w a r s , em u m b anco de dados MySQL..
Guitar Wars - High Scores
y r i y m y .Otiimr w aTPOT An yop k»™*w het it tala» ciadc ihe high score list? Tf so ■
just add vom own score.
^ tak adidione a s«a
pontuada©" na pagsna
prmdipal^de djuitar tYars,
£ vô * P|9ihá Adidionar
PontuadJío.
127650
N am e: Paco Jaflctii»
2008-W-2Z 14:37:34
98430
Vatng;N
cV
fiJofraD
isO
U
D ate: 200S'0+-22 21:27:M
345900
jia aie: Eddie V aaiffi
D ltts 200804-23 0 9 * 6 Í55
i 282470
! N anK i Bciüii Chevy
i D »tK 2008-04-23 09:12:53
j 368420
! N ym e: Asfeaon Simp«**
! D ite 200S-04-23 09:13:34
A página Adídioftâr PontwâdâO Z
apresenta um ■Pormulario para se
distar o nome e a pontuada© (3
data e a bora sao awtomâiidament«
obtidas a partir da data e bora do
»omento da inserÇâo)-
0 novo registro e
doft-fivmâdo; para <^uey
o usuário saiba <
^
u
e
cie ío i adidionado dom
Sud€SS©
.
GuitarWars-AddYourHighScore
Thacksforaddicgyournsw high scare!
IZ Z
4 m be e iso §ooa
oçócm Ez-to-sooz
zjjab
^ :3
bi9

0€6t9 ;
K
O
T
60K
-W
W
C
K:w
»
aI
TO
$xfaq$acU^Y53CW
X !
ozmz I
íot'605
z
*K
r8
o
o
r;«*a
X
a
«Ò J
*
=
*
X!
O
L
fZ
S
ZI
SS30-60 £C-tÜ^00£ :a » Q í
H
P
T
C
À^
P
P
3-
*
3
*
Nf
006£f£j
«
F
C
Z
-U
W
tO
U
O
G
ïi:a
w
af
u
o
s
s
n
r
u
o
f :
«
r
e

oetsó
çnoO
B
B
faxâ:ann»N I
QÇ9LZI j
’
‘
o
ç
j
i
i
i
^
a
ï
o
o
s
q
Â
q
w
p
^
o
c
a
î
^
ï
B
î
ï
ï
Â
i
i
A
v
a
A
f
i
i
i
i
i
O
A
o
p
'
i
c
i
p
j
B
^
j
i
e
i
t
n
^
'
s
c
i
o
a
p
j
f
tj
I
«M
oagq3ga-sxsfajei|nf>|
^ * r* > ’ ?
guiWá e« ayo-ejeip*“'-
' ' ope«°WPe
—
iut^-A OJCpfo* 0
-epeu^ua epe? e
-A
Ç
<
i
e 3 3«*O
M
o çwyzçwjie vu»c|«*e^ 
•sopep ap
o^ue^ op sJierM
Ç^w^ ep<^
e opeuo^ipe 3
aVjqstÇa* »A
O
« o ^e^o^lpV
wí A
Ç
?H
? 3 o ek ^ w
°i
Ç
sM
*í fjíttc« «ífl « ty
•s^e^ oe^ç?ij<Je e
epi^-Svui^ns iO
£ opjert^M
O
tl
ç opue*> ap e ^ s (e-«>s
e 3) q-çp e ?
*e
^
«
«
j epe?
çjiçi 3^«3*ue?i^e«*oc).»»e
epe-fisS » » sopep sp
O^UÇC| op ÇMÇmíwA 3a6^?
e » <jj ewp?
soainbje tua sopeuazeuue sopep tuoo opueqieqej)
comente o código
Rcício
A aplicação dos recordes do Guitar Wars terá de ser modificada para
acomodar a nova necessidade de se enviar arquivos gráficos. Circule
e escreva comentários nas partes da aplicação que terão de se
modificar para atender ao novo requisito.
<html xmlns=”http://www.w3 .
org/1999/xhtml" xntl:iang="en" lang="en’
’
>
<head>
<title>Guitar Wars - Maiores Pontuações</title>
clink rel="stylesheet" type="text/css" href="style.
css" />
</head>
<body>
<h2>Guitar Wars - Maiores Pontuações</h2>
<p>Bem-Vindo, intrépido guitarrista! Você é bom o suficiente para entrar
na lista de recordes do Guitar Wars? Se for, clique aqui para adicionar a
sua pontuação.
</a>.</p>
<hr />
<?php
// Conecta-se ao banco de dados
$dbc = mysqli__connect (’
www.guitarwars.net’, 'admin', 'rockit’, 'gwdb');
// Obtém os dados das pontuações a partir do MySQL
Çquery * "SELECT * FROM guitarwars";
$data = mysqli__query($d’
a c , $<iuery) ;
/ / Faz um loop através do array contendo os dados das pontuações,
formatando-os como HTML 1
<table>';
while ($row = mysqli_fetch_array($data)] {
// Exibe os dados das pontuações
echo '<tr><td class=’
'scoreinfo">'
;
echo '<span class="score">' . $row['score1] . '</spanXbr />';
echo '
<strong>Name:
</strong> ' . $row['name'
] . '<br />';
echo 1<strong>Date:</strong> 1 . $iow[’date'] . '
</td></tr>'
; .
)
echo ’
</table>';
mysqli_close($dbc) ;
</body>
</html>
7T ____
( style, css
Hsfce â*r^
u
iv<
>
pm
edisa
se »»odi-Pida*-,
P<*"bivfco v©
de
*2° fredisa sc
p'reodupav dor*
ele-
index.php
O código-fonte com pleto d a aplicação G uitar
W ars está disponível p a ra dow nload n o site da
Alta Books: www.
altabooks.com.
br
ÇTuitarw ars
trabalhando com dados armazenados em arquivos
" - - - , 1
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" iang=”en">
<head>
<title>Guitar Wars - Adicione o seu Recorde</title>
<link rel="stylesheeT:" type="text/css" href="style.css" />
</head>
<body>
<h2>Guitar Wars - Add Your High Score</h2>
<?php
if (isset($_POST[1
submit'])) {
// Pega os dados em POST
$name = $_POST[r
name’]
;
$score = $_POST['score'
];
if (!empty($name) && !
empty($score)) {
// Conecta-se ao banco de dados
Sdbc = mysqli_connectCwww.guitarwars.net', ’admin1, ’rockit', 'gwdb');
// Escreve os dados no banco
$query = "INSERT INTO guitarwars VALUES {0, NOW(), ’$name’, '$score')";
mysqli_query{$dbc, $query);
// Confirma êxito com o usuário
echo '
<p>Obrigado por adicionar o seu recorde!
</p>’;
echo 1
<p><strong>Nome:</strong> 1 , $name . '<br />';
echo ’
<strong>Pontuaçâo:</strong> ' . Çscore . '</p>r;
echo '<p><a href=”index.
php">S11;S11; Voltar para a lista dos recordes.</a></p>';
// Limpa os dados da pontuação para limpar o formulário
SNome = ”"
;
$Pontuação =
mysqli_close($dbc);
}
else {
echo '<p class="error">Por favor, insira todas as informações para
adicionar seu recorde.</p>’
1
)
?>
<hr />
<form method="post” action="<?php echo $__SERVER['PHP_SELF']; ?>">
<label for="name">Name:</labelxinput type="text" id="name" name="narae"
value="<?php if (!empty (Çname) ) echo $name; ?>" /Xbr />
<label for- score"i>Score;</labelXinput type=”text" id—"score” name=,rscore"
value="<?php if (!empty($score)) echo $score; ?>" />
<hr />
<input type="submit" value="Add" name="submit” />
</form>
addscore.php
você está aqui ► 229
código guitar wars comentado
A aplicação dos recordes do Guitar Wars terá de ser modificada para acomodar a
nova necessidade de se enviar arquivos gráficos. Circule e escreva comentários nas
IC IC lO partes da aplicação que terão de se modificar para atender ao novo requisito.
S o L u Ç ã o ______________________________
C n tm l x iril,n 5s=,Th t t p : //w w w .v r 3 . o r g / 1 3 9 9 / x í - t m l ” x r n l : i a n g - Me n M l a n g = ,Te n ,T>
<head>
< title> G u ita r Wars - Maiores Fontuações</i.ítIe>
< i i n k r e l ^ ’ s t y l e s h e ^ t " t v p é = Mt @ x t / c s s ” h r e f = Ms t y l e . c s s " / >
< /b e « d >
<bodv>
< h 2 > G u i t a r W a rs - M a io r e s P o r . t t a ç õ e s < / h 2 ?'
< p > W e lc a r e , B e m - V in d o , i n t r é p i d o g u i t a r r i s t a . ! V o c ê é bo m o
s u i i c i e n t ê p a r a e n t r a r n a l i s t a d e r e c o r d e s d o G u it a r W a rs ? Se f o x ,
c l i q u e ã q u i p a r a a d i c i o n a r a sx ia p o n t u a ç ã o . < / & > • < / p >
< h r />
- a r s . n e t 1 ,
< ? p h p
,/,/ C o n e c t a - s e a o b a n c o d e d a d o s
$ d b c « iT iy s q li c o r .r .e c t [ *www , g u i t a r v
1
çvrdcT
);
/ / O b térr. o s d a d o s d a s p o n t u a ç õ e s a p a r t i r
FROM ç u i t a r w a r s " ;
■í$dbc, 5cfiiery);
S q u a r y = "S E L E C T
Çdata = mysqli_query(
// Faz um loop através do array
HTML T<ta.ble>'
c c n t e n d o o
f o r m a t a n d o - o s ^o m o m m - m ^ í w /•
w hile <$row - n y sq li_ fetch _ arrav (S d ata))
/ / Exibe os dados das pontuações
i Hii I m -1 -!laRA=M
sco reinfoT
,> ';
echo ’cspan cl5SS»T
rscoreM
>' , ?x.6nTf
echo '<strong>Narre;</strong> ’ . $ro
echo ’<strong>D ate:</$trong> 1
:ho T
</table>';
0 arquivoda im
age,*
p«£isa ser obtido a Vce* deve “ *■* validação
partir d« dados de ierti-fiiar-se dc
POST. *lue ° Mmfo do nome da
imagem não esteja vazJa
■w3.olg/aS99/xhtml" xml:Iang=
irvsqli_ciose ($ábc) ;
?> / imagem tomprovando
</body> â pow-UaçSo ^retisâ ser
</hrira> cabida **
imagem precisa ser
para o usuário, para se
totuíirmar o exrto.
<htmi xnüns="htqp://
<heaS>
<title>Guitar Wars - Add YcVr High Score</tiile>
<link rel="stylesheet" typeAr-ext/css" href="style
</head>
<body> v
< h 2 > G u i t a r W a rs - A d i c io n e o s e i^ R e c o r d e < / h 2 >
<?php
j f i s ^ p n S T f s i M i f ; n i
// Pega os dados emP
O
S
T
íname = $_PO
ST['nam
e1
i;
Sscore = $__POST.
[
'scora*]
(rfl^Têmpty l
í
l
l
í
U
l
I
t
í
) K
'
i empty iísroisrK1
Conecta-se ac banco de dados J
/ tonsulta £$L-.agora
preòisa inserir *a
-tabela guitar^« o
nome do ar^uWo <ue
tontém a imagem-
S d õ c - ir i y s q li _ c o n n e c t (
'
gwab+
); ■g u i t a r w a r s . . i e t ' , 'a d m in '
index.ph
mysçli^close ($dbc)
/ -tabelapretisade uma^
„ova tolu«a para arma«*âr 0 -formulário precisa
o arquivo ojríkto de tada um
a -tag <input> p
av-j^i
pon-tua^ao-______________a seleção da imagem.
"INSERT INTO guitarwars VALQES (0, NOK(), 'Sname',^
Sscore ’) ---
roVBgii query ($dbc, j q u e r v ) ____ _
// Confirma êxito com o -jsuáriü 
eebo '<p>Obtigado por adicionar o s
e
'
J
. recorde ! < / p > 1
echo T<p><strong>Nom.e:</s“rona> 1 . Snaue . '<br /J/í
echo '<p><;a href="index.php">6clt;&it; Voltar para a lista dos
recordes.</a></p>'
;
;
s dados da pontuaçSo para limpar o formulário
„) « r Havendo sutesso, ierti-fi^ue-se de
<m
»e o dampo d a imagem no -formulário,
. ( <yue é permanerrte, seja limpo.
e c h e ‘ < p c l a s s = r e r r í > r T
'> P o r f a v o r , i n s i r a , t o d a s a s i n f o r m a ç õ e s
a d i c i o n a r s e u r e c o r d e . < / p > '; r
Çsta C
onsulta i*s
aw
»a espetit
de ataiKo, ao não esp etiíitar
OS hOWCS d â s t c l u h 3 s-
< l a b e l f o r - ^ n a n v e '^ N o i u e K / i a b e l x i n p - a t ^ y p e ^ t e x t ” id = " n a m e ,,
n a n je = ,rn a m e "
value=r
T
<?php if {!empty(Sname)) echo $nam
e; ?>T
f /><br /-
xiabel for=,,sccret,>Pontuação;</Isbel><input type*"text"'
n a r o Ê = ^ * ^ j^ e ”
v a 1 u e = " < V p n p : r ( ] e m p t y ( ç s c o r e ) ) e c n o S s c o r e ; ? > "
ebr />
<input type=”submit" Tíalue="Add" namg="Eubmit" />
</fonr>
L
j </òody>
* * < / h t m l >
a t i r t g f t n r p p h p
trabalhando com dados armazenados em arquivos
Planejando os uploads dearquivos gráficos no Guitar Wars
E m bora possa p arecer que não é n ad a m uito com plicado adicionar suporte ao upload
(envio) de arquivos gráficos ao G uitar Wars, a aplicação precisa ser m odificada d e várias
m aneiras. Por isso, é um a b o a ideia te r um plano antes de m erg u lh ar no código. Vamos
esquem atizar os passos necessários p ara atualizar o G uitar W ars e adicionar a funcionalidade
que querem os.
o Use a lte r para adicionar à tabela a coluna
screenshot.
Em primeiro lugar vem o banco de dados, que precisa
de uma nova coluna para armazenarmos o nome
de cada arquivo gráfico contendo a pontuação do
usuário. Umavez que estamosplanejando colocar
todos os arquivos gráficos na mesma pasta, tudo o que
precisamos armazenar no banco éo nome do arquivo
(não épreciso incluir o caminho).
0
Escreva uma consulta insert para inserir
o nome do arquivo gráfico na coluna
screenshot da tabela.
O scriptAdicionar Pontuação que processa o
formulário para aadição dos recordes também
deve levar em consideração o novo campo de input
de arquivos, e deve lidarcom a inserção do nome
do arquivo gráfico na coluna screenshot, quando
inseriruma novalinha de dados de pontuação à
tabela guitarwars.
Modifique o form ulário de Adicionar
Pontuação de modo que ele passe a usar
um cam po de input de arquivos para
perm itir o upload das im agens.
A páginaAdicionar Pontuaçãojá tem um formulário
para se adicionarem aspontuações, de modo que
precisamosmodificaresse Formulário, incluindo
nele um campo de input de arquivos. Essecampo
funcionará conjuntamente com o navegador para
apresentarao usuário uma interface onde ele
selecionaráum arquivo a ser enviado.
Screen shot: ( Choose fite]) *RphizsscQre-gif
Modifique a página principal de
Guitar Wars de modo que ela
passe a mostrar as imagens
comprovantes dos recordes.
O último item da nossalistade
modificações envolvea página principal do
GuitarWars, index.php, que precisaser
modificada para exibir aimagemjunto a
cadapontuação exibida.
você está aqui ► 231
ALTERE sua tabela
0 banco de dados das powtuapões máximas
precisa ser AlTERado
Além de um a série de ajustes no script PHP, a nova aplicação G uitar Wars
precisa de um a nova coluna, n a tabela g u i t a r w a rs, para arm azenar
os nom es dos arquivos gráficos. E aí que entra o SQL, que oferece um a
instrução cham ada ALTER, capaz de m odificar tabelas de tudo quanto
é jeito, inclusive adicionando novas colunas de dados. Você usou a
instrução ALTER, no capítulo anterior, para ajustar a tabela e m a i l _ l i s t
de Elmer, mas vamos recapitular aqui com o esse com ando funciona.
guitarw ars score
A instrução DRO
PCOLUm dimirt
uma doiuna mte»ra da tabela.
OK, talvez esse seja u m exem plo perigoso, u m a vez q u e ele revela
com o elim in ar u m a co lu n a in teira d a tabela, com os dados e tudo.
Mas é q u e certam en te p o d erá haver u m a situação em que você
precise rem over u m a co lu n a inteira. E m ais provável, p o rém , que
você precise ad icio n ar u m a coluna, com o é o caso aq u i com o
G uitar W ars. Isso é possibilitado p o r ADD COLUMN, q u e é u m a das
diversas alterações q u e você p o d e ex ecu tar n a tabela com ALTER.
A instrução
A l t e r e u s a d a
paiam
udara
estrutura
b a n c o d e d a d p s
A instrução A L T E R
•frequentemente t seguida
yor T A B L & yara mdidar
<
^
*e vote estara modi-Pidando
uma tabela, E possível
tambew alterar a estruWa
de todo o bando de dados,
dom ALTER DATABASE,
mas isso é outra Vistoria*
ADD COLUMN
A diciona u m a coluna â tabela - basta
especificar o n o m e da co lu n a e o seu
tipo, após ADD COLUMN.
g g g g g ^uitaryars ^
DROP COLUMN
Exclui um a coluna (e quaisquer dados
arm azenados nela) de um a tabela - basta
especificar o nom e da coluna apos DROf
COLUMN.
ALTER TABLE guitarwars
CHANGE COLUMN
M uda o nom e e o tipo de dados de um a
coluna - basta especificar o nom e atual
da coluna, o novo nom e e o novo tipo de
dados, após CHANGE COLUMN.
MODIFY COLUMN
Modifica o tipo de dados ou a posição
de um a coluna dentro da tabela - basta
especificar o nom e da coluna o seu novo
tipo de dados após MODIFY COLUMN. Para
m udar a posição de um a coluna, especifique
o nom e dela e a sua posição exata (FIRST
é a única opção aqui) ou um a posição
relativa (AFTER para colocá-la após um a
determ inada coluna, sendo esta especificada
pelo nom e).
ALTER TABLE g u ita r w a rs
trabalhando com dados armazenados em arquivos
Aponte seu lápis_____________ ___________________
Escreva uma instrução SQL para adicionar uma coluna chamada
s c r e e n s h o t à tabela g u it a r w a r s . Certifique-se de fornecer à nova
coluna um tipo de dados adequado. Depois, escreva outra consulta SQL,
desta vez para verificar a estrutura da tabela e certificar-se de que a
coluna foi adicionada com sucesso.
Esdreva a^ui a instrução
para driar a doluna.
Esdreva a outra
instrução
você está aqui ► 233
- f^ ApoHteseulápis---------------------------------------------
Solupão
Escreva uma instrução SQL para adicionar uma cotuna chamada
screenshotàtabelaguitarwars.Certifique-sedefornecerà
nova coluna um tipo de dados adequado. Depois, escreva outra
consulta SQL, desta vez para verificar a estrutura da tabela e A • jl ~
certificar-sedequeacolunafoiadicionadacomsucesso. ^instruça©AiTBR â
d
itio
n
a
a Coluna screenshot a tabela
guitarwars.
Uma vez. c^
u
e a
Coluna c «ova,
ela Começa
sua existência
vazia (NULL)
de «uais<^uer
dados nas
linhas.
aponte seu lápis solução
A instrução AiTBR nao
afeta ^uais^uer outros
dados da tabela- 0 nome da tabela a ser alterada
vem depois de AtXER TABL-E-
ALTER TABLE guitarwars
A W COLUMN screenshot varchar^^O
r *
ADD COLUMNindica <ue
queremos alterar a tabela,
adicionando a ela uma nova coluna-
r
DESCRIBE guitarwars
0 nome e o tipo de dados da nova Coluna são
especificados por ultimo na Consulta SQL —b^ç
caracteres sao o suficiente para stot^odair a
maioria dos nomes de arquivos, mas voCe pode Criar
a Coluna ainda maior do <ue isso se quiser-
Esta instrução exibe
a estrutura da tabela,
incluindo os nomes das Colunâs
e os seus tipos de dados.
“Terminamos o ____
primeiro passoj A
í
Use AL"
tabela a coluna s c r e e n s t
trabalhando com dados armazenados em arquivos
T te S T O R iv e
Adicione a coluna screenshot à tabela guitarwars.
U sando u m a ferram en ta MySQL, execute a instrução ALTER p ara
ad icio n ar a coluna screen sh o t à tabela guitarw ars. Em seguida,
em ita a instrução DESCRIBE p a ra d ar u m a o lh ad a n a estru tu ra d a
tabela e certificar-se de q u e a co lu n a foi adicionada.
l/ode pode donstruiv- &
iabela juitarvrârs midial
bai*ando o dódí^o de
e*emplo pava éjui-Uv iVa«
e depois exedu-fcando a
doífssulta S$L <
^
u
e se
endOftiira r»o av^uívo
5uiiarwavs.s«|i.
A 'mstrvi^ao PíSCRlBE
mostva a nova dolunâ
sdreensbot-
existem
^ • As colunas criadas com
ALTER precisam ser adicionadas ao
final da tabela?
Não, elas podem ser adicionadas
em qualquer lugar. Mas tenha em mente
que a ordem das colunas dentro de
uma tabela não tem tanta importância
assim. Em outras palavras, você pode
estruturar os resultados das suas
consultas, de modo a organizar os dados
de qualquer forma que quiser. Mas talvez
goste da sensação de ordem estrutural
criada pelo ordenamento específico
das coiunas, em cujo caso você poderá
querer adicionar a coluna em um local
exato. É possível fazer isso incluindo-
se a palavra-chave FIRST a esta
consulta ALTER. Ou então use AFTER
coluna para posicionar a nova coluna
relativamente a uma já existente:
TWgiintas Idiotas
ALTER TABLE guitarwars
ADD COLUMN age TINYINT
AFTER name
Se você não especificar um lugar para a
nova coluna ser adicionada, o padrão é
no final da tabela.
? • O que acontece com as linhas
de dados existentes no banco de
dados após a adição da nova coluna
screenshot?
R : Uma vezque a instruçãoALTERsó
afeta a estrutura do banco, a nova coluna
é criada vazia de dados nas linhas pre­
existentes. Embora seja possível preencher
a coluna screenshot defuturas linhas, as
linhas pré-existentestodas terão uma coluna
screenshotvazia.
Os nomes dos arquivos gráficos
ainda poderão ser adicionados às
linhas pré-existentes?
í{:Sim, sem dúvida, e você usa a
instrução u p d a t e do SQL para fazê-lo.
Não há nada que lhe impeça de enviar
arquivos de imagens manualmente
para o servidor, e depois usar u p d a t e
para vincular os nomes dos arquivos às
pontuações existentes. Mas lembre-se
de que a ideia aqui é permitir que o
próprio usuário envie o arquivo gráfico,
e portanto, faz sentido implementar a
funcionalidade de upload das imagens.
E os usuários poderão fazê-lo usando o
script Adicionar Pontuação aprimorado
que você está prestes a criar...
você está aqui ► 235
adicione imagens com o formulário adicione pontuação
Como fazer para o usuário enviar a imagem?
Com a nova coluna adicionada ao ban co de dados, estam os p ro n to s p ara nos
co n cen trarm o s n a fu n cio n alid ad e q u e p erm itirá ao usuário enviar u m arquivo gráfico.
Mas com o ex atam en te isso é possível? FTP? Telepatia? Isto n a verdade nos leva de volta ao
form ulário A dicionar P ontuação, n o qual p o d erem o s u sar u m cam po p ara p erm itir q u e o
usuário selecione u m arquivo gráfico a ser enviado. N
0 torwuiâri© AdiCionar Pontuaçao
t O permitirá 3os usuários
^ ----- adicionarum novo registro â lista
G ultar W ars - Add Your High Score B dt«terdes de$w ta*-«>«■
j Nane: — —
1
Score: I86S80 ’ :
Screen siioc Choosf: ^ *
-
.
cí
f
j® > f
/  Apos submeter-se o
0s detalbes sob« o 1 -formulário, o arquivo
funcionamento deste botão sâo I SráfiCo binário é enviado
Controlados pelo navegador e J do servidor,
pelo sistema operacional nativo- )
£m geral, ele aciona uma cai*a
de dialogo do navegador, na fr ffiiiffi
ç^è o usuário pode navegar pâra
encontrar o arquivo desejado no ^ S 0 f
seu própr^ rígido- phizsscore.gif
Assim, um cam po de in p u t ajuda o usuário a
en c o n trar o arquivo a ser enviado. E depois? O
cam po tam bém cu id a da o p eração de fazer a
im agem selecionada chegar até u m a pasta do
servidor, a p artir d e o n d e p o d e en tão ser exibida
com o p arte d a lista de reco rd es do G uitar W ars.
Esse cam po d e u p lo ad d e arquivos do fo rm ulário
é algum tipo de extensão esquisita do HTM L?
D e fo rm a algum a. A tag <input> do H TM L tem
su p o rte aos cam pos referen tes a arquivos, e
trab alh a em co n ju n to com o PH P p ara p erm itir
o u p lo ad dos arquivos. Mas antes de en trarm o s
nos d etalhes do fu n cio n a m en to do PHP, vam os
d ar u m a o lh ad a com m ais atenção n o p ró p rio
cam po do form ulário...
Uma pasta no servidor
recebe o arquivo
i f iCo e o armazena-
Servidor web
r
trabalhando com dados armazenados em arquivos
0 Feram látfo Adicionai: pontuação em D é fa ite s
Estabelece um tamanho
máximo para os arquivos
enviados, «este caso 3ZKB
Í3Z.7&0 bytes).
Este formulário e
autorreferente-
Imethod="post'' action="<?phb echo $ SERVER ['PHP
£$te atributo instrui o
formulário d usar um tipo
especial de codificaeao,
requerido para o upload de
arquivos —ele afeta o modo
como os dad^s POST sao
tombinados e enviados apos a
submissão do formulário. 
<form
SELF’]; ?>”>
aMawBBwafWUNiriininHiniai iiiï._s..
.
.
mmam m m
<label for="name">Nome:</label>
<input type="text" id="name" name="name" value="<?php if (!empty($name)) echo
$name; ?>" />
<br />
clabel for="score">Pontuação:</label>
<input type="text" id=”score" name="score'' value="<?php if (!empty($score)) echo
$score; ?>" />
<br />
<label for="screenshot">Captura da Tela:</label>'
•
<hr />
<input type="submit" value="Add" name="submit" />
</form>
Este e o campo de input
propriamente dito, <ue em
ultima instância, utiliza—
se
de uma caixa de diálogo do
sistema operacional nativo
para o usuário navegar ate o
arquivo e seleCiona-lo.
ulário
Adicionar Pontuação de
modo que ele passe a
usar um campo de input
de arquivos para permitir
o upload das imagens.
você está aqui ► 237
Insira o (nome do) arquivo gráfico no
banco de dados
Sim plesm ente enviar ura arquivo gráfico para o servidor através de
um form ulário não é suficiente. Temos de arm azenar o nom e do
arquivo na nova coluna screenshot do banco de dados, para que
a im agem possa ser acessada e exibida. Do jeito que está o script
A dicionar Pontuação, já está inserindo novas pontuações na tabela
guitarwars, usando a instrução SQL INSERT, mas esta não está
levando em consideração a nova coluna s c r e e n s h o t :
armazenar arquivos de imagem no banco de dados
Os nomes <fcs
ssíp a t m o z e t ic i d p s
n° t>ctnco de dctdPS
cotio pqrte de uma
Insfruçífe ÍHSEílTT
* r
A -função M
ov/O do MyS#L é usada
pava se ínseviv a data e Kora atuais.
INSERT INTO guitarwars VALUES (0 , NOW() , ^narne', '$score')
A doiuna id e deíinida automatidamente através de 
AMT0__IMCR£MêKT —
O C
^
e
v
o
)t i^
n
o
v
a
d
o
je
m
b
o
raa
donsulta realmente regueira um vaior a«ui.
Um a vez que esta instrução SQL está inserindo valores sem identificar
colunas para eles, ela precisa incluir um valor para cada coluna. Mas
nós acabam os de adicionar um a nova, o que significa que a consulta
não funciona mais - está faltando um valor para a nova coluna
s c r e e n s h o t . Assim, para adicionar um nom e de arquivo gráfico ao
banco com o parte de um a nova linha de dados, precisam os adicionar
um novo valor à instrução INSERT:
INSERT INTO guitarwars VALUES (
0 , NOW() , T$name’
M linhas de dados inseridas antes^
da triaçao dô doiuna sdreensHot *ao^
possuem um nome de arquivo ya-fido-
fassav o nome do arquivo
ojviíito na instrução
StL-fcCT -faz- tom <ue
ele seja ad^ionado ao
bando de dados.
’$score',
A ordem destes valores
íaz. di-ferenda, uma vez.
c «ue a instrução IKSERT
esta assumindo «ue eles se
endontrâm na mesma ordem
«ue as dolunas da tabela-
A nova instrução ÍK^ERT resulta no nome do arquivo
da imagem a sev inserida na do!una sdreenshot-
E3cii>'u -------
IN S E R T para Inserir
o nom e do arquivo
gráfico na coluna
scre e n sh o t da tabela.
trabalhando com dados armazenados em arquivos
Pescubra o nome do arquivo enviado
Parece estar tudo certo com a consulta, mas nós ainda não sabemos
qual é o nom e do arquivo gráfico. E lógico assumir que o cam po de
input de arquivos do form ulário oferece, de algum a form a, acesso
ao nom e do arquivo, mas como? A resposta reside em um a variável
superglobal interna do PHP cham ada $_FILES, que é sem elhante à
superglobal $_JPOST que já usam os para acessar dados do form ulário.
Com o $_POST, $_FILES é um array, e dentro dele encontra-se não
apenas o nom e do arquivo enviado, mas tam bém outras inform ações
que poderão ser úteis.
<input type="file"
name="screenshot" / >
0 Wmulávio envia alg^as
utess sobre
o av^uWo para o scrip-b
PftP, através dia variarei
superglobal f_jF|L££-
c
phizsscore.gif
Éste e o àv^uivo gváfiCo
sendo enviado através
do ca»»po de input de
arquivos do formulário.
A SUpelrglokal
interna 4LFÍLE S
íptnece acessp a
í n f e n i a ç p e s s p b t e
a r ^ u íV p s e n V la d p s .
ILES['screenshot1]['name']
Nome do
arquivo
enviado-
$_FILES['screenshot' ] [ 1type'
]
M M H Ü ^ __ 0tipo MIMÊ do
arquivo enviado,
neste caso éjlJ'*.
$ FILES['screenshot1] [ 1size'
]
1 1 1 ! *--oWh.<
*
*byte)
do âv^uivo enviado.
$_FILES [ 1screenshot1] [ 1tmp__name'] ,
*
l l l i B l l i P ^ localização de
te»*poravia
do ar^uivo no
servidor.
$ FILES['screenshot'] E'error'
]
~ mm 0 código de erro para
i ^ 0 up}oad do av<uivoj 0
indica suCesso, ovtros
valores indiCâm fracasso-
As outras inform ações disponibilizadas n a variável $_FILES
certam ente são úteis, m as neste m o m en to só precisam os d o
nom e da im agem , q u e p o d e ser arm azenado em u m a variável
local ($screenshot) e usado n a instrução SQL INSERT.
você está aqui ► 239
manter os dados de arquivo externo em arquivos externos
Dados armazenados em arquivos externos geralmente
são deixados nesses arquivos externos, mesmo em
aplicações de bancos de dados.
Neste caso, os dados são um conjunto de pixels que com põem um a
imagem, a qual é arm azenada em um arquivo externo - um arquivo GIF,
JPEG ou PNG. Os bancos de dados são excelentes para arm azenar dados
de texto, e não dados binários puros com o são as imagens, e por isso, é
m elhor arm azenar no banco apenas um a referênciaà imagem. Essa
referência é o nom e do arquivo.
O utro motivo pelo qual as imagens não são annazenadas em bancos de
dados, nas aplicações web, é que seria m uito mais difícil exibí-las usando*
se código HTML. Lembre-se de que o código HTML referencia imagens
a partir de arquivos externos usando os nomes dos arquivos. Assim, para
gerar um a tag de imagem em HTML usa-se o nom e do arquivo, e não os
dados puros da imagem.
Telia se colpocií
u rna im a g e m
em uma página
Wet>7 SP é
precísp uma
r e f e r e n c i a a ^ ~
ar^ u íV p .
< im g s r c = '
0 nome
do arquivo
$ ráfy 0.
a l t = " S c o r e im a g e " / >
A -ta $ H T M L - < im $>
usa o nome para
referenciar o arquivo
^ráfito armazenado
no servidor web.
Phizsscore.gif
trabalhando com dados armazenados em arquivos
Aponte seu lápis
A página principal do Guitar Wars (index.php) ainda não está exibindo as
imagens de captura de tela que comprovam as pontuações. Complete o
código para que ele passe a exibi-las.
<?php
// Conecta-se ao banco de dados
$dbc= mysqli_connect{'www.guitarwars.net'
, 'admin', 1rockit'
, 'gwdb');
// Obtém os dados das pontuações a partir do MySQL
$query= ;
$data= mysqli_query($dbc, $query);
// Faz um loop através do array contendo os dados das pontuações, formatando-os
como HTML
echo '<table>'
;
while ($row = mysqli_fetch_array($data)) {
// Exibe os dados das pontuações
echo 1ctrxtd class=" scoreinfo"> ';
echo 1<span class="score">' * $ row ['score'] .'c/spanXbr />' ;
echo '<strong>Name:</strong> 1
. $row['name'] . '<br/>';
echo '<strong>Date :</strong> '
. $row ['date']
.. '</td>';
if {is_file(................. ) &&filesize{..................) >0) {
echo 'Ctdximg src=" ' . ............... alt="Score image" /></tdX/tr>';
}
else {
echo 'ctdximg src="unverified.gif" alt="Unverified score" / x / t d x / t r > ';
echo 'c/table>';
mysqli__close ($dbc) ;
?>
você está aqui ► 241
aponte seu lápis solução
ponte seu lápis-----------------------------------------------
Solupão
Apágina principal do GuitarWars (index.php) ainda não está exibindo as
imagens de captura de tela que comprovam as pontuações. Complete o
código para que ele passe a exibi-las. N
uma tentativa de ajudar a simplvfidar o tód^o, «ao
iremos usar "or d'seO“ para produzir mensagens de erro
e interromper o sdript guando uma íunÇâo mys^ii -falhar-
<?php tyodê poderá dontinuar utilizando esse redurso «as suas
próprias apiidadoesj «és pararemos de usa-lo da^ui em
// Conecta-se ao banco de dados v , ‘ _ „ „ ^
diante, apenas para manter o dodtjo o mais breve possível-
$dbc= mysqli_connect(1www.guitarwars.net', 'admin1, 'rockit'
, 'gwdb');
// Obtém os dados das pontuações a partir do MySQL
$query = S t U ã C T * F R O M guitarwars" ^ ^ instrução S Q L <

u
e pede as
pcm-tuadoes nao se modvfida em
çdata = mysqli__query ($dbc, $query) ; 1 j 1
// Faz um loop através do array contendo os dados das pontuações, formatando-os
como HTML
echo '<table>';
while ($row= mysqli_fetch_array<$data)) {
// Exibe os dados das pontuações
echo '<trxtd class="scoreinfo">'; M *
£sta íundao vereda
echo 1<span cl-ass=" score"> ' . $row [’score 1] . '</span><br />' ; ^ q arquivo g
r
á
-
f
i
í
-
o
e c h o ’ < s tro n g > N a m e : < / s t r o n g > ' . $ ro w [ ‘ n a m e ’ ] . ' < b r / ^ l - ^ ^ ^ r>ão esta vazio-
echo '<strong>Date:</strong> ' . $row['dat^>f^T'</td>'; ___
if (is_file( && filesize ( > 0) {
í echo '<t d x i m g src=" ' . frovíCsdreenshot 3 . '" alt=" Score image" /></tdx/tr> ^
Esta -Punça© veriíida se o ar«uivo doíuna sdreensbot do bando de dados ^
e ile { YcaUtíit cxisíe' a rm a ^ uma imagem para dada pontuadao-
echo 1<t d x i m g src="unverif ied.gif" alt="Unverified score" /></td></tr>1;
} A Modifi
echo 1</table>';
mysqli_close($dbc)
?>
m odo
que ela p a sse a
m ostrar a s im age n s
com provan tes d os
I recordes.
trabalhando com dados armazenados em arquivos
T f e S T O R f v e
Adicione um novo recorde ao Guitar Wars, incluindo a captura de tela.
Books, www.altabook5.com .br. Está n a pasta capitulo 05 (ch ap ter 05). O código consiste
da p ág in a principal (index.php), do script A dicionar P ontuação (addscore.php) e de
u m a folha de estilo (style.css).
P rim eiro, você precisa m odificar o script a d d s c o r e . p h p de m o d o q u e o seu
form ulário A dicionar P o n tu ação passe a te r su p o rte ao u p lo a d de arquivos. Isso inclui
ad icio n ar novos cam pos ao form ulário, ajustar a tag <form > e verificar se a variável
S screenshot n ão está vazia. D epois, in co rp o re ao script a nova consulta INSERT que
insere pontuações.
A gora, vá ao script in d ex .p h p e insira n ele o código d a página anterior, p ara q u e ele
possa exibir a cap tu ra de tela referen te a cada pontu ação .
Envie todos esses arquivos p ara o seu se n ad o r web e ab ra a p ág in a a d d s c o r e . p h p
em um navegador. D igite u m a nova p o n tu ação n o fo rm u lário e clique em Subm it. Em
seguida, navegue até a p ág in a i n d e x . p h p e d ê u m a o lh ad a n a nova pontu ação .
Caso ain d a n ão o te n h a feito, baixe o código de exem plo do G uitar W ars no site d a Alta
AI50«aoesta devtc
if*agem não está ap
.
junto do» a «ova pontuaça©.
Por que você acha que a imagem com a
captura da teia não está aparecendo junto com
a nova pontuação? E quanto às pontuações
que já estavam no banco de dados?
você está aqui ► 243
arquivos enviados são armazenados em uma pasta temporária
Para onde foi o arquivo enviado?
O p ro b lem a com a im agem enviada não ap arecer é q u e nós assum im os q u e o arquivo seria
enviado p ara a m esm a pasta, no servidor, q u e a dos nossos scripts PHP. O co rre q u e isso
está sim p lesm en te in c o rre to . O fo rm u lá rio d e A d icio n a r P o n tu a çã o p e rm ite q u e o u su ário
selecione u m arquivo do seu p ró p rio com putador, m as o arquivo é enviado p ara u m a pasta
tem p o rária do servidor, n a verdade. Essa pasta tem p o rária é criada au to m aticam en te no
servidor, e em geral possui algum n o m e estran h o , cheio d e letras e n ú m ero s aleatórios.
Isso ap resen ta u m p ro b lem a p ara o nosso código < im g> em i n d e x . plrp, p o rq u e ele
assum e q u e a im agem está localizada n a pasta p rin cip al do site:
c im g s r c = " |lli|& á Í £ S © Í r ^ l|! iÍ | |^ '' a l t = " S c o r e im a g e " / >
Este tódi5©assume
ejue â im
âSjÇ
.w
armâzenâda n3
mesmâ pasta ft os
scripts PHf*..’ mas
ela nao esta!
Navegador
eb do cliente
0 ar^uivo Corn
a ima^em da
captura de
teia se localiza
origiyvâlmente
aljMma pasta do
Computador do
M
S
U
â
V
-io
.
Servidor
web
0 nome e 3
jotaiiz^Çao deste
pasta temporária
vaviam conforme a
instalaçao do PHP-
í«*aááâÍcorG.php
index.php
CSS
phizsscore.gif
Este formulário
se or’
tÿna de
addsCorephp-
û script de Adicionar
Pontuação cuida
de enviar o arquivo
grafico para uma pasta
temporária no servidor.
trabalhando com dados armazenados em arquivos
Armazenar imagens em uma
críptica pasta tem porária parece ser uma
complicação desnecessária. Não é possível
definirm os onde os arquivos enviados devem
ser armazenados?
Sim! O PHP lhe permite controlar onde os arquivos enviados
serão armazenados.
Porém, não é possível controlar, através do PHP, o local de armazenamento inicial
dos arquivos enviados, motivo pelo qual essa localização é considerada como
temporária. Mas você pode mover o arquivo para outro lugar, depois de ele ter
sido enviado. A função PHP move_jiploaded_file() aceita como parâmetros a
localização-fonte e de destino do arquivo, e então realiza a transferência:
move_uploaded_file (;||t|f
c a iotâljiiâçao-WU
do arquivo grafito, indluindo
OtâmmKo COnome do
dr<i*W
o temporário.
fscore.php
index.php
Esta pode ser ^uatauer pasta
do servidor <
^
u
e vode quiser
usar, apenas dertifi^ue—
se de
ter permissão para esdrever
arquivos nela.
Servidor Web
^ t a r g e t ) ;
Esta é a
lodalizaçao de
destino do arquivo
grafido, indluindo
o daminho e o
nome do arquivo
permanente.
0 arquivo é
movido de uma
pasta temporaria
para uma
permanente-
move uploaded__fü e 0
phizsscore.gif phizsscore.gif
você está aqui > 245
não existem perguntas idiotas
mQ existem
p e r g u n t a s i d i o t a s
I • Nãoé possível modificar o lugar de armazenamento
inicial dos arquivos enviados editando-se o arquivo php.ini?
Sim. 0 arquivo de inicialização do PHP (php.ini) pode ser
usado para se modificar o lugar de armazenamento inicial dos
arquivos enviados, através da opção uploadJmp_dir. Porém, se
a sua aplicação estiver hospedada em um servidor virtual, você
poderá não ter acesso a esse arquivo de inicialização, o que
significa que, se quiser mover o arquivo enviado para uma outra
pasta, terá de fazê-lo através de código PHP.
7 * Por que a pasta de armazenamento inicial é chamada
de “temporária” ? Ela desaparece depois que o arquivo é
retirado dela?
K : Não. A pasta é “temporária” no sentido de que não foi criada
para servir como o lugar de armazenamento definitivo para os
arquivos enviados. Você pode pensar nela como uma espécie de
antessala, onde os arquivos enviados são armazenados até serem
movidos para os seus lugares de armazenamento finais.
* Por que eu não posso simplesmente deixar um arquivo
na pasta temporária?
J^_t Você pode, em cujo caso terá de adicionar $_
FILES['screenshot'] ['tmp_name'] ao caminho da imagem, para se
certificar de que ela possa ser encontrada na pasta temporária.
Mas tenha em mente que você não pode controlar o nome ou
a localização da pasta, em geral. Mais importante ainda, as
pastas temporárias podem ser automaticamente esvaziadas,
periodicamente, em alguns sistemas. Outro potencial problema
é que a pasta temporária poderá não estar acessível ao público,
e com isso, você não poderá referenciar os arquivos enviados a
partir do seu código HTML, o que atrapalharia o funcionamento
do Guitar Wars e da maioria das aplicações PHP. Movendo os
arquivos enviados para outra pasta que não a de armazenamento
temporário, você pode controlar cuidadosamente onde os arquivos
ficarão, e como serão acessados.
trabalhando com dados armazenados em arquivos
OK, então agora eu sei como
mover os arquivos enviados de
um lugar para outro. Isso é
realmente útil. Mas ainda não
tenho a menor ideia de para
onde eles devem ser enviados.
Toda aplicação precisa de uma pasta im ages
(im agens).
OK, talvez dizer q u e “precisa”, possa ser u m exagero, m as é
im p o rtan te q u e os pedaços das aplicações PH P fiquem o m ais
organizados possível, e u m a m an eira d e fazê-lo é crian d o pastas
p ara os diferentes com ponentes. U m a vez q u e as im agens são
enviadas pelos usuários, elas n ão são algo sobre o q u e você
n o rm alm en te terá co n tro le direto, pelo m enos em term os
de nom es de arquivos e quantidades. Assim, é u m a b o a ideia
arm azená-las sep arad am en te dos outros arquivos da aplicação.
D ito isto, precisam os de u m a pasta im ages, o n d e os arquivos
gráficos enviados p ara a aplicação G uitar W ars possam ser
arm azenados. Esta pasta p o d e servir tam b ém com o lu g ar d e
arm azen am en to p ara quaisq u er outras im agens que a aplicação
use, caso surja a necessidade.
A pasta '»majes «a verdade *ao
t muito »ais importante *u
C
oyuàl«uer outrâ pâstâj mâs ela
ajuda a organizar os arquivos
gráf(tos em um so lu^âr.
você está aqui ► 247
Crie um lar para os arquivos gráficos enviados
faça uma pasta para imagens enviadas
A pasta im ages é id ên tica a q u alq u er o u tra do servidor, exceto pelo fato de q u e ela tem de
ser colocada em algum lu g ar abaixo da pasta p rin cip al d a aplicação. N a m aioria dos casos,
basta colocá-la d iretam en te com o u m a subpasta da p rincipal, m as você p o d e criar u m a
h ierarq u ia de pastas m ais com plexa, se quiser.
C riada a pasta im a g e s d iretam en te d en tro d a pasta p rin cip al do servidor, torna-se
possível referen ciar arquivos de im agens d e d en tro de scripts PHP, assim:
0 no**e do âr^uivo e
Starget = Condatenado âo dámmfoo
(jlmage zsscõre.
O cam in h o $ targ et é criado a p artir de u m a nova
constante q u e irem os ad icio n ar ao script, ch am ad a
GW_UPLOADPATH, q u e arm azena o cam in h o até a
nossa pasta im ages. Assim com o as variáveis, u m a
co n stan te serve p ara arm azen ar algum dado. Mas o
valor d a con stan te n ão p o d e ser m odificado, u m a
vez definido. O n o m e do arquivo gráfico, conform e
digitado no fo rm u lário A dicionar P ontuação é en tão
co n caten ad o ao cam inho até im a g e s .
Çsta c a fasta web da aflitaçao,
onde os sevifb PHP, induindo inde*-
fiy, íidaw arma^nados.
Servidor
web
V e j a W n !
Use um program a de F T P para acessar o sistema
de arquivos do seu site, e crie a pasta im ages
diretamente dentro da pasta web da aplicação.
0S âr^uVvos grafitos enviados
sâo movidos fara a fasta
images, cmde fodem ser
exibidos através de tags
HT/V1L <i»g>.
Se a sua aplicação PHP estiver
hospedada em qualquer outro
lugar que não o seu computador
local, você precisará usar FTP
para criar a pasta images.
phizsscore.gif
trabalhando com dados armazenados em arquivos
S Í n I T A - S E c o m o u m a w u ï V o g r â î ï c o e n v i a d o
Suaíatefa e inteípi-et^t o papel de UH1ai^UlVo
gráffco envlad«?,traçando o seu camínjip
atraVés do apllcatíVo Guitar Wars. Desenhe seu
caminto atraVés de cada parte da
aplicação, sem se esquecer do
banco de dados, pense como
um stFjvfa/Q enViade!
Navegador
web do cliente
Servidor
web
Comtu a«v*ií
phizsscore.gif
phizsscore.gif
phizsscore.gif
guitarw ars
você está aqui ► 2 4 9
sinta-se como um arquivo gráfico enviado-soiução
S i r í r A - S E c o m o u m qj^ u W q g r á S i c o e n v i a d o - S o l u ç a »
Esta pasta
-(■
id
a no 7t
Computador
do usuário
A »
—vote «ao
tem dontrole
nenhum sobre
o nome dela,
ne» onde ela
e armazenada,
mas também
nada disso lhe
importa-
Sua tareia é Interpretar 9 papel de um arquivo
graíicç enViade,traçando 9 geu camínlio atraVás
d» aplioatíVp Guitar Wars. Desenlie seu camfnlio
atraVé-s de cada parte da aplicação,, sem se
esquecei do banco de dados. ¥ense
come um arquive enVíado!
Navegador web
do cliente
V
ot i deve ser
ti/tdidoso tom o riomt
c a lotaSitatâo desta
ya^ia, porque ela
6 visãás Cmtoda a
apitéa^ã« áw-tav tva«
para ar«*az£w
ar e j
reíerendiar os ar^utoos^^/^
^rá-fitos e^ados-
Pviwcir 0
arquivo e ewtàd©
(Asando-^ w
ífi
Servidor web
AâmPode mPut do
phizsscore.gir, ' ,
+or(*vwiârÍ0-
Sscreenshot = $ _ F IL E S [’screenshot’][1
nam e’];
Caramba!
»©
vopasso «
^
u
e
w
âo havíam
os fianejado - o seu
proje-èo precisa ser -P
ie%
ível/
phizsscore.gif
£m se%hdo lu^at-, © ar<^»iv© £movido
Áè pasta temporária para a p
a
s-fca
imanes permânen-te-
Apos o arquivo
ser ewviado ao
servidor e ser
rrovide para O
seu ta^ar de
amazena^e^t»
-final» seu *©
"»«
s adicionado ao
ban&
ode dados-
the Mova o ai
gráfico da pasta
temporária para
uma pasta
permanente criada
para as imagens.
addscore.php
guitarw ars
TfeSTO R fv e __________________
trabalhando com dados armazenados em arquivos
Dê aos arquivos gráficos enviados um lar permanente, com uma pasta
própria para eles.
M odifique o script a d d s c o r e . p h p p ara q u e ele use a constante G W JJP LO A D P A T H e
arm azene os arquivos gráficos no cam inho p ara o n d e ela está ap o ntando. Eis o p edaço do
código q u e precisa ser m odificado:
as ccin.qtpir.tss dc caminho e do
define(1GW UPLOADFATE'
, 'images/
<?php
-amanho máximo dos arquivos
if (isset(S_POST[1submit']) ) {
// Pega os dados em POST
Sname - §_?OST['nane']?
Sscore = $_POST[1score'];
$screenshct - $ FILES[’screenshot’][1name'];
: ('empty($name) 5S !empty($score) £& !empty(Sscreenshot)) {
// Move o aranivQ.. para a pasta-alvc
Starget = (S_UPLOADPATH .jfscreenshot;
if (jnove_upKkJfca_i.ilbi (i_Tfll.ES [
'screenshot1][
'tmp_name’], $target) ) {
// Ccnecta-se ao banco de dados
$dbc = mysqli connect{1h w w .guitarwars *net1, ‘admin’, 1rockit'
, 1g^'db1);
// Escreve os dados no banco
$query = "INSERT IHTO guitarwars VALUES (0, NOW().
mysqli_query(5dbc, $query);
// Confirma êxito com o usuário
echo '<p>0brigado por adicionar o seu recordei</p>';
echo '<p><stronç>Nome:</strong> ' . Sname . '<br
echo 1 |
,
g|trr
'",,
> 1 $sccre . 1<br. />';
echo '<img src="’ ./gw_UPLOADPATH 7screenshot . alt="Score image" /></p>';
echo 1<oXa h.ref="in3è8";{Sll!i{i"^iiL;STtVoltar para a lista dos recordes. </a></p> ';
addscore.php
O script i n d e x .p h p tam bém é afetado p ela co n stan te G W _UPLO ADPATH. N ão se
esqueça de m odificá-lo tam bém . A pós fazer essas m odificações, envie os scripts p ara o
seu servidor e te n te ad icio n ar um a nova p o n tu açã o novam ente. a . « . r
r n tr^age* unvevi-hed
exibida f3râ fon-twaçocs
an-tigas, <uc nâo íem
w^a dap^twra de beis
domfvobatóría.
A tap-tava dc tela
enviada agora -Pita visível
na pagina printipa!.
você está aqui ► 251
n a ? eXJStem
perguntas idiotas
P ' Seoarquivophp.in i pode
serusadoparasecontrolarolugarde
armazenamentodosarquivosenviados,
porque énecessáriomoverosarquivos?
K : Porque nem sempre é possível
modificar php.ini. Por exemplo, se você
estiver criando a aplicação PHPem um
servidor web virtual, é bastante provável
que você não terá acesso para modificar
as configurações de php.ini. Emesmo
que possa modificar esse arquivo, você
corre o risco de danificar sua aplicação
caso precise movê-la para outro servidor.
Emoutras palavras, a aplicação ficaria
dependente de umcaminho controlado
por php.ini, em vez de umcaminho
controlado pelo seu próprio código PHP.
7 • Por que os usuários não podem
digitar uma data, na aplicação
Guitar Wars?
Adata é uma parte importante do
registro da pontuação, no sentidode
queelaestabelece quandoo recordefoi
oficialmente publicadono site. Comoocorre
comqualquer registro, a primeirapessoa
a conseguir umadeterminada pontuação
recebe toda aglória. Emvez deconfiar que
o usuário nosdirá realmente quando foi
que ele conseguiu a pontuação, podemos
simplesmente usaradata ea horadopost
comoo registrooficial da pontuação. Isso
eliminafalsificações e empresta maior
credibilidadeà lista dos recordes. Os
Os bancos de da<fcs sãp
usuários de umaaplicação tãocompetitiva
estarão sempre procurando por umjeito
de fraudá-la, portanto, vocêdeveeliminar
todas as possibilidadesdefraudeque
puderencontrar!
Vale a pena ressaltar que a função
now () usa a hora do servidor, que
poderá não ser a mesma que a hora
local do cliente. Isso não deverá ser um
problema, porém, uma vez que todos
os usuários estarão obrigados à mesma
hora do servidor.
T * * Não é possível que as pessoas
escrevam em cima das imagens umas
das outras, enviando arquivos gráficos
com os mesmos nomes?
Sim. O problema tem a ver com o
fato de que as imagens armazenadas
no servidor usamexatamente o nome
de arquivo fornecido pelo usuário no
campo de upload do formulário. Assim,
se dois usuários enviarem arquivos com
o mesmo nome, a imagem do segundo
usuário será escrita em cima da imagem
do primeiro. Isso não é bom. Uma
solução é adicionar alguma unicidade aos
nomes dos arquivos no servidor. Uma
forma simples de fazê-lo é adicionar a
hora atual do servidor, em segundos, ao
nome do arquivo, desta forma:
$target = GW UPLOADPATH .
time(
)
$screenshot;
O resultado desse código é um nome
1221634560phizsscore.gif para o
arquivo, em vez de phizsscore.gif, onde
1221634560 é a hora atual do servidor,
expressa em segundos.
P ' Nós poderíamos ter armazenado,
no banco de dados do Guitar Wars, os
dados propriamente ditos da imagem
enviada?
H : Sim. Os bancosdedados são
bastanteflexíveis, e lhepermitem
armazenardados binários dentrodeles.
Porém, ogrande problema nestecasoé
queoGuitarWars usaas imagens enviadas
nooódigoHTML, paraqueelas possam
ser exibidas napágina principal index.
php.Atag HTML<img> foi criada para
referenciarumarquivográficoarmazenado
noservidor, e não umconjuntode dados
binários armazenados emumbanco.
Assim, mesmoque vocêalterasse atabela
guitarwars paraarmazenar dados binários,
aindasedeparariacomumdesafioabsurdo,
aotentarcolocaros dadosde voltaemum
formatoque pudesseser exibidousando-se
código HTML
Kao hi nada de <^üa! sob« a Wa
v-eW*ada pela-funçaotimeO, e+ux#
pelo-fato de y t ela ^era «Uer*s
íhiòos... eonimcro retocado esta
sempre âww»e«tawdo|
PONTOS DE BALA
9tunps para se armazenar
dadPS detexfcp, Pias em
geral e melhor cjue eles
referenciem dadbs blnáliPS de
affiufVps externps.
A instrução ALTER é usada para se modificar a estrutura de
uma tabela de banco de dadoa MySQL, por exemplo para se
adicionar uma nova coluna de dados.
Com uma pequena ajuda do PHP e do MySQL, uma tag HTML
< in p u t> pode ser usada para se enviarem arquivos gráficos.
A variável superglobal $ _f i l e s é onde o PHP armazena
informações sobre um arquivo enviado.
Afunção padrão do PHPmove_uploaded_ file () lhe
permite mover arquivos de um lugar para outro no servidor, e é
essencial para o processamento dos arquivos enviados.
A maioria das aplicações web beneficia-se deter uma
pasta images para armazenar as imagens usadas
pela aplicação, especialmente aqueias enviadas
pelos usuários.
trabalhando com dados armazenados em arquivos
Legal que o caminho
seja armazenado em uma constante,
mas por que ele é criado em dois lugares,
index.php e addscore.php? O que acontece
se o caminho se modificar?
A £©nstante
#v_UPU>AZ>PATft
armaz-ena ° tami*ho
*fcc o arquivo yráÇito
enviado.
define('GW_UPLOADPATH’
aeímeO é«sado J o da
*e en*w »
tonstantes-
'images/ '
) ;
0 valo*" da tonstante, o <*à
nuntd fode sev modi&tado-
ele é uma Aonstante!
S e o cam inho se modificar, você terá de m odificar o código
em dois lugares... código duplicado não é um a boa coisa!
Assim, dentro de cada um dos scripts, in d e x .php e a d d s c o re .p h p , a
constante GW_UPLOADPATH funciona sem problemas. Mas ela é criada duas
vezes, o que significa que qualquer modificação no caminho terã de ser feita
em cada um dos scripts. Esse tipo de duplicação de código é consequência
de um mau projeto, e deve ser eliminado sempre que possível.
The donstant is stored tv/ide, meaning it has
to be maintained in two di-ffevent fldtes.
W É R > 9
C É R E B R O
Para resolver o problema do
código duplicado, precisamos
armazenar a constante g w _
u p lo a d p a t h em apenas um
lugar. Você a armazenaria em
index.php ou em addscore.
php? Por quê?
você está aqui ► 253
dados em scripts compartilhados com arquivos include
Pados compartilhados precisam ser compartilhados
Q u an d o têm dados q u e devam ser com partilhados p o r diferentes scripts em um a aplicação,
você precisa d e u m a fo rm a de arm azená-los em um só lugar, de o n d e cada script possa
obtê-los p ara uso. Mas isso ain d a n ão resp o n d e a questão de o n d e e x a ta m en te os dados
devem ser postos,..?
Você poderia arm azenar os dados apenas
em index.php...
// Defina a
. constante do carrinho da upload
define{1G
WU
P
L
O
A
.D
P
A
T
H
' , 'images/');
Os dad°s a serem
c p r a p a t t i l t a d p s p p t
scripts precisam íicat
acessíVels at°da
a aplicaçãp, sem
d u p lic a ç õ e s tiP c ó d ig o ,
index.php
...mas desse jeito os outros scripts não teriam
acesso a eles.
Assim, arm azen ar os dados a serem co m partilhados
em um script n ão fu n cio n a, p o rq u e os dados n a
verdade n ão estarão m ais sendo com partilhados. A
resposta está em conseguir, de algum m odo, to rn a r os
dados acessíveis a vários scripts, m as sem arm azená-los
d iretam en te em n e n h u m deles.
- @
addscore.php
index.php addscore.php
Como tornar os dados acessíveis a ambos os
scripts sem os arm azenar em nenhum deles?
A solução p ara o p ro b lem a são os arquivos include, arquivos de
código-fonte PH P q u e são inseridos em outros arquivos PH P
co nform e necessário.
trabalhando com dados armazenados em arquivos
Serão necessários dados do
script compartilhado
Os arquivos in clu d e são b astante poderosos, p o rq u e, após criá-
los, você p o d e usá-los sem pre que necessário em outros scripts,
n a prática co m p artilh an d o o código co n tid o neles. A con stan te
GWJJPLOADPATH p o d e ser colocada em u m arquivo include p ara
estabelecer u m co n ju n to de “variáveis da aplicação”.
<?php
// Define constantes da aplicação
define('G
W
JJPL
C
ãDPATH', Timages/T);
?>
O s a r ^ u íV ^ s
in c lu d e lfce
p e r m i t e m
c o m p a r t l ll ic ü :
c(> cl!go e n tr e
d iV e r S 9 S
scripts.
addscore.php
A »hsfcrudâo re^nHre_j»w*e
tuida de indluiv um sdv-ipt
denhro de outro sdHpt-
jnfcluir apfvars.fHf C» outvos
~ , stvipis periwite estes
nqo e X isM os dados doados
I e t^ U X ltc lS l d l 9 f à S na^eíe.a^va«.f^.
~P • Ei, essas “variáveis” da aplicação não são na
verdade constantes?
Em alguns casos, sim. Mas não há nenhum
problema nisso. A ideia aqui não é se preocupar em
diferençar variáveis de constantes. Em vez disso,
estamos apenas tentando estabelecer um lugar
comum para o armazenamento de dados a serem
compartilhados, dentro de uma aplicação. E esse lugar é
um arquivo de script chamado appvars.php.
compartilhados, como frequentemente fazer isso é uma
ótima ideia, em termos de organização do código.
• 0 código nos arquivos de script compartilhados
limita-se a dados?
Não, de forma alguma. Qualquer código PHP
pode ser colocado no seu próprio script e compartilhado
usando-se a instrução require_once. Na verdade,
é bastante comum que aplicativos compartilhem uma
grande quantidade de códigos funcionais residentes em
vários scripts. Não só é comum usar arquivos de scripts
Por que a instrução PHP para se incluir códigos
se chama require_once (“ requisitar uma vez” )?
K : O nome arquivo indude (“de indusão”) vemde uma
instrução PHP chamada include, a qual é bastante
semelhante a require_once. Adiferença é que
require_once resultaem umerro caso o arquivo
include não possa ser encontrado - include, poroutro
lado, não acusa umerro caso o arquivo include esteja
faltando. Além disso, o “once” (“uma vez”) de require_
once significaque o arquivo não poderá ser acidentalmente
incluído mais de uma vez. Você poderá, às vezes, ver
include sendo usado em vezde require_once
para se induiralgum código que não sejatão importante,
como por exemplo, código HTMLpuro que não esteja
realizando algum propósito essendal. 0 PHPtambém tem
as instruções include_once e require, que são
variações de require_once e include.
você está aqui ► 255
a instrução require_once
Pense cm require once cowo uw "inserir"1
As inclusões n ão se lim itam a u m só arquivo PH P com partilhado, e p o d em ap arecer em
q u alq u er lu g ar do script q u e você q u eira usá-las. Você p o d e p en sar em r e q u i r e o n c e
com u m a instru ção in sert (“in serir”) q u e é substituída pelo co n teú d o do script q u e ela
referencia. N o caso do G uitar W ars, as variáveis d a conexão ao banco de dados p o d eriam
tam bém se beneficiar de serem m ovidas p ara u m arquivo inelude. Assim, os conteú d o s dos
dois scripts com p artilh ad o s são inseridos d iretam en te em outros scripts, nos p o n to s o n d e
fo rem requisitados.
Esfcâ VâHâVc! global êhrrftdziftd J
dados importantes para a_ y
apíidadao, dos «^uais tanto
inde*.pHp quanto addsdorephp
predisa».
tw ve*. d« duplidav as variáveis
da toYc%ão ao bando «m dada
sdriptj nós podemos »ove-
las para um arquivo indlude»
■tornando—
as dompartílhadas-
connectvars.php
A îîistiruçâpR EqU ÍR E^O N C E insere
c p j í g p s J e s c r i p t s c o n i p q r t í l l i a c l o s e m
P U t t P s s c r i p t s .
trabalhando com dados armazenados em arquivos
<?php
r — — — — — — — — — — — — '
I
// Define as constantes da aplicação
define('GW UPLOADPATH’, 'images/');
// Define as constantes da conexão ao banco de dados
'define(’DB_HOST1, '
www.
guitarwars.
net');
Idefine(’DB_USER', 'admin');
|define(’DB_PASSWORD'r ’rockit1)
;
define('DB NAME', '
gwdb1);
// Conecta-se ao banco de dados
$dbc = mysqli_Connect(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME)
// Obtém os dados das pontuações a partir do MySQL
Squery = "SELECT * FROM guitarwars";
Sdata = mysqli_query($dbc, $query);
I I Faz um loop através do array contendo os dados das
pontuações, formatando-os como HTML
echo 1
<table>1;
while ($row = mysqli_fetch_array(
$data)) {
// Exibe os dados das pontuações
echo '
<tr><td class="scoreinfo">'
;
echo '<span class="score">1 . $row [
'score '] .
echo 1
<strong>Wame:</strong> ' . $row['name'
]
echo '
<strong>Date:</strong> ' . $rowí'date']
if (is_file(GW_UPLOADPATH . $row[1screenshot1]
) s&
filesize(GW_UPLOADPATH . $row['screenshot']) > 0
) {
echo '<tdximg src=" 1 . GW_UPLOADPATH . $row['screenshot']
alt="Score image" /></td></tr>';
</spanXbr />'
1
<br />';
'</td>';
else {
echo '
<td><img src=”1 . GW_UPLOADPATH . 'unverified.gif'
alt="Unverified score" /x/tdx/tr>';
}
}
echo '</table>';
mysqli_close($dbc) ;
índex.php
T fe S T O r iv e
Sensacional!
Agora eu também
tenho acesso aos dados
compartilhados!
addscore.php
■ [ i l B U i i W
O do arquivo
enviado para
uma constante,
que será então
com partilhada
através de um
arquivo include.
ouíro passo novo[ 
doisâs são J
di+iííis dc planejar de
ânhcmâo, portanto vode
terá de estar pronto
para ajustar o seu
projeto sempre
<ue necessário-
Crie dois arquivos Include para o Guitar Wars, e depois compartilhe-os
entre os outros scripts.
C rie dois novos arquivos de texto, a p p v a r s .p h p e c o n n e c t v a r s .p h p , e digite neles o
código m o strad o n a p ág in a anterior. Em seguida, ad icione instruções r e q u i r e _ o n c e a
i n d e x .p h p e a d d s c o r e .p h p p ara q u e am bos os scripts com p artilh ad o s sejam incluídos.
Envie todos os scripts p a ra o seu servidor e teste o fo rm u lário A dicionar P o n tu ação e
a página principal, p ara se certificar de q u e eles estejam fu n cio n an d o com a nova e
ap rim o rad a estru tu ra organizacional com arquivos include.
você está aqui ► 257
A instrução ORDER BY
0 mais importante para as pontuações máximas é
«-timing- a ordem
O G uitar W ars fin alm en te tem o su p o rte a im agens, p erm itin d o q u e os usuários
enviem capturas d e telas p ara validar os seus recordes. E m bora isso seja um g ran d e
ap rim o ram en to n a aplicação, ain d a n ão resolveu o p ro b lem a de q u e os usuários têm
reclam ado h á algum tem p o - a o rd em das po n tu açõ es n a p ágina principal.
/{Üd>onar noVâ
agora envolve
o envio de Wage»—
—
*ue parei« oiimo, cxtcbo
pelo râio das pontua^oes
snão esiare» e» orde»J
E verdade, as pontuações n ão estão em ordem . Elas estão
sendo exibidas n a ord em em q u e se en contram no banco
de dados, que é totalm ente arbitrária. Você n u n ca deve
perm itir que a o rd em de exibição seja a m esm a o rd em em
que os dados se en co n trem arm azenados n o banco, a não
ser que ord em realm ente n ão faça diferença. N este caso,
precisam os im p o r algum a ord em sobre os resultados da
consulta. A instrução SQL O RD ER BY to rn a isso possível.
trabalhando com dados armazenados em arquivos
luws <
Iü Geladeira <1° VHF & M/-5QL
§1 Veja se você consegue descobrir como ORDER BY funciona, usando os imas abaixo
| | para criar instruções SELECT ordenadas que resultem na saída abaixo. Circule também
I| qual consulta você acha que representa a melhor solução para o Guitar Wars. Dica: ASC
significa ASCendente e DESC significa DESCendente.
1File Edit Window Help YYZ
I 5 I 2 0 0 8 - 0 4 - 2 3 09 : 1 3 : 3 4 Ash Lor: S i m p so n
4 : 2 0 0 8 - C4 - 2 3 0 9 : 1 2 : 5 3 | E e l i t a Cnevy
! I 2 0 0 3 - 0 4 - 2 3 0 3 : 0 6 : 3 5 : E d d i e v s n i l l -
I 6 i 2 0 0 8 - 0 4 - 2 3 2 4 : 0 9 : 30 ! Kenn y L a v i t z
! 2 I 2 0 0 3 - 0 4 - 2 2 21 : 2 7 : 5 4 j N e v i l J o h a n s s o n
j 1 i 2 0 0 8 - 0 4 - 2 2 - 14 : 37 : 34 I Paco J a s L o r i u s
I 7 I 2 0 0 3 - 0 4 - 2 4 0 8 : 1 3 : 5 2 | P h i z L s i r s t o n
I screensho;
I 36642 0 I
I 345-900 I
I 12 7 65 0 i
! 18 6580 I p h i z s s c c r e . g i f
7 r c w s i n s e c (Q.CGÜ5 s e c }
A^ui, os resuliâdos da donsulta
são retornados em order«
desdendesvte> for fcmtuadao, e defois
em ordem asdendente, for data-
A^ui, os resultados da eo^ulta são
»retornados s** ordem alíabétida
asdendente, for nome.
ímãs dophp &mysql solução
:
Im a s d e G e la d e ir a dç> P B P & M / S Q L - S p I u ç I lp
Veja se você consegue descobrir como ORDER BY funciona, usando os imas abaixo
para criar instruções SELECT ordenadas que resultem na saída abaixo. Circule também
quai consulta você acha que representa a melhor solução para o Guitar Wars. Dica: ASC
significa ASCendente e DESC significa DESCendente.
A^ui, os resultados da consulta
sao retornados em ordem numérica
descendente, for pontuaçao, e depois
em ordem ascendente, por data
I File Edit
_Aw, os resultados da Consulta sao
retornados em ordem al-Pabetica
ascendente, por nome-
tsta t a Consulta de
«ue precisamos para o
Quitar Wàrsj
FROM guitarwars j ORDER BY DESC
í SC
5 ! 2008-04-23 09:13:34 ; Ãshton — 1 -/
-
3 2008-04-23 09:06:35 ! Eacie vanali; ! 34
! 2006-04-2 3 09:12:53 ; Belita C'svy ! .
?8
i 2008-04-24 08:33:52 1 Phiz T
,
azrs.cn p
1 ■ £006-04—22 14 :37:34 i i
:
anc • i2
2 ! 2008-04-22 ■
í1:i
- :o4 Nev_ : Johansson i 5■
6
- -4Á-----
U:09:iC | Kenny lavitz
0 ordenamento por data t seCundário, e so
se aplica caso haja duas pontuações idênticas,
o e^ue nao oCorre a^ui mas te» uma boâ
probabilidade de acontecer guando se te» um
Conjunto bastante grande de dados.
A vfrjula e
necessiv-ia para
se separar os
dois níveis de
ordenamento.
trabalhando com dados armazenados em arquivos
Homenageando o (toitar Warrior número um
C om a o rd em das p o n tu açõ es consertada, agora é possível fazer u m a m elh o ria in esp erad a
n a lista dos recordes: colocar a m aio r p o n tu a ção de todas n o tipo d a lista. O G uitar W arrior
com a m aior p o n tu ação m erece u m cabeçalho dizendo claram en te q u e ele é o n ú m e ro
um , p ara que n ão h aja dúvida... e p ara q u e os adversários saibam qual p o n tu ação eles tem
de superar.
Um tabeçalKo
sdlientâ
dlavâmeirvfce a
poníuaçao m£*i»*a,
estabeledendo
um alvo para os
demais éjuiiav-
W
a(rlriors..
u a9 ex iste m
perguntai Idiotas
"i • Muitas pontuações ainda estão sem verificação? Isso nãoé
um problema?
É sim. Mas não nos impede de seguir adiante e incluir a
funcionalidade de chamar a atenção para a pontuação máxima. A falta
de verificação, na verdade, só significa que em algum momento nós
teremos de limpar a lista, excluindo os registros sem comprovação.
De fato, assim que terminarmos com esta funcionalidade de salientar
a pontuação máxima, já passaremos para a questão das pontuações
sem verificação.
você está aqui ► 261
adicionando um pouco de css
Formate a pontuapão máxima com HTML e CSS
A coisa m ais im p o rtan te sobre o cabeçalho q u e estam os in clu in d o é que ele será visto
claram en te acim a d e todas as dem ais p o n tu açõ es d a lista. Para isso, precisarem os de ajuda
tan to do H TM L q u an to do CSS, p ara a p arte visual. O ca b e ça lh o será g erado com o u m a
lin h a n a tabela H TM L, com u m CSS especial aplicado a ela. Este estilo, t o p s c o r e h e a d e r ,
deve ser acrescen tad o à folha de estilo s t y l e . c s s do G uitar Wars.
Centraliza
a pontuadão
máxima no
dabeçalho.
Usa um -fundo de
dor esdurd dom
te*to brand©> para
íâz.cr a pon-Uadao
má/ima realmente
saltar aos olhos-
£*ta dlasse de estilojá está
sendo usada para salientar os
erros de inserdao de dados ho
sdript Adidionar Pontuaçao-
.e rro r {
font-w eight: b o ld ;-^7
c o lo r: ÍFFOOOO;
.topseoreheader {
text-align: center;
font-size: 200%;^
background-color: #364Q7F
color: #FFFFFF;
.score {
font-size:150%;
color : #36407F;
.scoreinfo {
v e r tic a l-a lig n : top
p a d d in g -rig h t:15px;
}
Estas duas dlasses de
estilo ja estâo -formatando
as pontuadoes, na pagina "
prindipal-
style.css
garante <ue
o tamanho
da -fonte seja
aumentado em
relaçao às demais
pontuações-
O script i n d e x .p h p já está g eran d o u m a tabela H T M L co n ten d o a lista
das pontuações. G erar u m cabeçalho ap en as p ara a p o n tu ação m áxim a
req u e r q u e isolem os o p rim eiro registro, o qual g ara n tid am en te será a m aior
p o n tu ação , u m a vez q u e a lista ag o ra está o rd en ad a. U m loop w h ile é
posto em ação, e nós precisam os de algum a fo rm a d e co n tar as p o n tu açõ es e
g erar o cabeçalho apen as p ara a prim eira..;
trabalhando com dados armazenados em arquivos
Complete ocódigo do script index .php do Guitar Wars de modo
que ele adicione um cabeçalho formatado para a pontuação máxima,
usando o estilo GSS tops coreheader. Dica: Não se esqueça de que
esse cabeçalho fará parte da tabela HTML contendo os recordes, a qual
possui duas colunas.
// Faz um loop através do array contendo os dados das pontuações, formatando-
os como' HTML
echo 1<table>';
$i = 0;
while ($row = mysqli_fetch_array{$data)) {
// Exibe os dados das pontuações
if (..................) {
}
echo 1ctrxtd class="scoreinfo">';
echo 1<span'class="score">' . $row[1score'
] . '</span><br />';
echo 1<strong>Name:</strong> ' . $row[,namel] . '<br />';
echo '<strong>Date:</strong> ' . Srowf'date'] . 1</td>';
if (is_file(GW_UPLOADPATH . $row[1screenshot[]) &&
filesize(GW_UPLOADPATH . $row[1screenshot1]) >0) {
echo ’<td><img src="' . GW_UPLOADPATH . $row[1screenshot1] .
,n alt-"Score image" / x / t d x / t r > ';
}
else {
echo 'ctdximg src="' . Gw_uPLOADPATH . 'unverified.gif1 .
alt="Unverified score" /></td></tr>'
;
}
}
echo ,</table>1;
I
index.php
f a .
E x k t á c  o
você esté aqui ► 2 6 3
exercício solução
Complete o código do script index.php do Guitar Wars de modo que ele adicione um
# cabeçalho formatado para a pontuação máxima, usando o estilo CSS topscoreheader.
Rcicio Dica: Não se esqueça de que esse cabeçalho fará parte da tabeia HTML contendo os
recordes, a qual possui duas colunas.
SoL oção
fi c 3 vâviivcl «
U
C-foz. d Conta
das pontuações - nós podemos
usa-ía para isolar a primeira
pontuaçao-
// Faz um loop atravé^ do array contendo os dados das pontuações, formatando-os
como HTML /
Se f I -for igual a O, nós
sabemos t^ue esta é a
.x " primeira^ou seja, a maior)
while {$row = mysqli_fetch_array($data)) { pontuaçao, e portanto,
devemos gerar o código
ttTML para o cabeçalho.
echo '<t
// Exibe _
os.dados .
das,
pontuações
if ( 7 i,=~ OJ í
echo '< tr> < td Colspan=tt2-Mclass—w
topsCoreheaderw
>Tõp Score: *
frov^rsCore^ •4</td x /b r^ i
}
echo '<tr><td class="scoreinfo">';
echo '<span class="score">' . $row[1score'
] . '</span><br />';
echo '
<strong>Name:
</strong> 1 . $row['name'] . ’
<br />';
echo 1
<strong>Date:
</strong> ' . $row['date’] . ’
</td>';
if (is_file(GW_UPLOADPATH . $row['screenshot1]
) &&
filesize(GW UPLOADPATH . $row['screenshot'
]
) > 0
) {
echo '<td><img src="' . GW_UPLOADPATH . $row['screenshot'
] .
'
" alt="Score image" /></td></tr>'
;
}
else {
echo 'ctdximg src="' . GW_UPLOADPATH . 'unverified.gif’ .
alt="Unverified score" / x / t d x / t r > '
;
fi classe de estilo
topscoreheader
enContra-se
armazenada em
style-Css-
echo '</table>';
Incrementa o Contâdor Bo -final
do loop pelas pontuações —este
Codigo e o mesmo «iue fi — fi
+ /;•
index.php
Tejst O r i v g ---------------------------
trabalhando com dados armazenados em arquivos
Ordene as pontuações e dê destaque à maior delas.
Modifique o scrípt index .php de modo que ele passe a usar a nova consulta
SELECT ordenada, e depois, adicione o código que irá gerar o cabeçalho para
a pontuação máxima. Envie o novo script para o seu servidor e abra-o no seu
navegador, para ver a maior pontuação sendo exibida proeminentemente.
, ™ r . Nsme: AshtoE Simpsou
Donxuâtdo ' Date2GOS-04-2309:13;34
a^ova e mostrada
destatada^cntc W 5
da lisfca de r t t ordes.
É verdade, ainda precisamos tratar das pontuações
n ã o -v e rific a d a s.
Mas uma coisa de cada vez. Parece que surgiu outro problema, que
está impedindo as pessoas de enviarem os seus arquivos gráficos.
você está aqui ► 265
adicionando restrição de tamanho para imagens
fakt av^uivo «ao
somente e ggawfccs6o
íiWrb? w>ai0*‘do
l>V(C^h *»& ta^bew
*ao c ne» se^t*ev“u»a
àmage»!
ethelshugescore,pdf
O arquivo não só é gigantesco, ele nem é uma imagem!
Temos um problema: nosso formulário estã rejeitando alguns arquivos sem dizer aos
usuários por quê. Na verdade, é bom que ele esteja rejeitando arquivos, neste caso
porque são grandes demais - lembre-se de que limitamos o tamanho dos arquivos
a 32 KB, no código do formulário. Mas precisamos avisar ao usuário por que isso
está acontecendo. E não apenas isso, nós também não queremos que os usuários
enviem arquivos que não sejam imagens. Adicionar alguma validação ao formulário
de Adicionar Pontuação permitirá que nós tenhamos maior controle sobre o modo
como os arquivos são enviados.
Assim, a validação no formulário addscore .php servirá a dois propósitos
essenciais. Primeiramente, ela poderá aprimorar a prevenção contra uploads
de arquivos grandes demais, fornecendo aos usuários uma notificação de que o
arquivo não pode ter mais que 32 KB. E, em segundo lugar, ela poderá impedir
que as pessoas enviem arquivos que não sejam imagens. O formulário precisará ter
validação tanto para o tamanho quanto para o tipo do arquivo.
Gitítar Wars - Add Yonr High Score f
Sorrv,tfaerewas, prcbkm nploadtagyourserasssfcot^
Narae: :ahíuSidreí ~
Sccae: ’swJõõã ~ ~ ~™
Screen shnt: fchoo«.fh,-"» 1
Qfli{
trabalhando com dados armazenados em arquivos
São permitidas apenas imagens pequenas
Então, como exatamente nós verificamos o formulário Adicionar Pontuação e nos
certificamos de que as imagens enviadas estarão obedecendo às limitações de tamanho e
tipo? A resposta se encontra na variável superglobal $_FILES, da qual, se você se lembrar,
nós obtivemos a localização de armazenamento temporário do arquivo enviado, para que
pudéssemos movê-lo para a pasta images. Agora, iremos usá-la para obter o tamanho e o
tipo MIME do arquivo. 0 do arquivo
C*£ede IMBi muito maiov
do «ue o ytosso limite de
iv f a (ttQ 0 .Y 1 l ^tes
i-2-2-AlB) ou
$ FILES[ 1screenshot’] ['size1]
$_FILES['screenshotT]['type'
]
Não queremos apenas que os arquivos gráficos sejam menores do
que 32KB, mas também precisamos que eles sejam de um tipo que
possa ser exibido como imagem web. Os seguintes tipos MIME são
tipicamente usados para se representarem imagens web:
$_FILES[ 1screenshot']['type'
]
GIF
0 tifo do €
PDF,y t não t u» tipo
aceitável de ar^ivo
pava web, tomo
qfF 0P3 ov>
PvcopãVOS
ya-fitos
tonteado a
taptuva de tela
do»pvòbatfâria
da pcmtua^ao...
Escreva uma declaração if para verificar se um determinado arquivo
é uma imagem, checando também se ele é maior do que 0 bytes e
menor do que o determinado na constante GW_MAXFILESIZE. Assuma
que o tamanho e o tipo do arquivo já tenham sido armazenados em
variáveis chamadas $screenshot_size e $screenshot_type.
if (
) {
você está aqui ► 2 6 7
incorporando arquivo de vaiidação no aplicativo
tpowteseu lápis
Solupão
S o lu ç ã o Escreva uma declaração if para verificar se um determinado
^ arquivo é uma imagem, checando também se ele é maior
do que 0 bytes e menor do que o determinado na constante
GW_m a x f i l e s IZE. Assuma que o tamanho e o tipo do
arquivo já tenham sido armazenados em variáveis chamadas
$screenshot_size e $screenshot_type.
para íf(((fscreenshot t ype ==•=• .1! “ 77.''»agç/jpçgOi)
'-eConheCer i t . í
imagens jp<$.... pjro?. J).íf.^r«r'.shoL.^ypc.r r . !)***&/&*!}). M
Alguns
«avegadoires
este
tipo Mf/VíE
(fscreens)i©tmsizc > && (fsôreensh<rtjsize <—^VV^AI/t^FfLÍSl^-E))
Uma vez. <^ueo tacanho máximo
para o arquivo agora aparece
cm mais de um lugar no sdript
Adicionar Pontuado, -Paz.
sentido armazína-lo na -forma
de uma constante-
appvars.php
A validação de arquivos torna a aplicapão mais robusta
Um nouf.o de validarão ainHa muito a tornar mialmipr anlirarão Uma »ensaiem d
e
Um pouco de validação ajuda muito a tornar qualquer aplicação
PHP mais intuitiva e fácil de usar, além de mais segura. Agora, uma
mensagem de erro ajuda o usuário saber exatamente quais são as
limitações impostas sobre os arquivos gráficos a serem enviados.
Uma »»ehsagem de
erro ajuda a explicar
exatamente <
^
u
e
tipos de arquivos
podem ser enviados.
ethelshugescore.pdf
jeanpau1sscore.jpg
phizsscore.gif jacobsscore.png
trabalhando com dados armazenados em arquivos
Uma vez. ^ue estamos bomando
O sdnpt mais robusto, também
e uma boa ideia veri-fidar a
£*»be uma mensagem de
erro desdrVtiva, daso
o arquivo seja do tipo
errado, ou grande demais.
if ('empty($name) &5 !
empty($score) && !
empty($screènshot)) {
if {((5screenshot_type == ’image/gif’) I
I (Sscreeishot_type == ’image/jpeg') |
j
($screenshot_size > 0
) && ($screensh©t_size <^/üW_MAXFILESIZE)} {
if ($_FILES [’screenshot' ]['error'3 ==
// Move o arquivo para a pasta-alvo
$target = GW_UPLOADPATH . $screenshot;
if (move uploaded file($_FTLES[1screenshot1]['tmp_name'], $target)) Í
// Conecta-se ao banco de dados
$dbc = mysqli_c0nnect(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);
// Escreve os dados no banco
$query = "INSERT INTO guitarwars VALUES (
0
, NOW(), '$name’, '$score',
// Confirma êxito com o usuário
echo '<p>= Obrigado por adicionar o seu recorde!
</p>'
; ^
echo 1<p><strong>Name:
</strong> ‘ . $name . '<br />';
echo '
<strong>Score:</strong> ’ . $score . '<br />';
echo '
<img src="’ . GW_UPLOADPATH . $screenshot . alt="Score image" /><
echo '<p><a href="index.php">£lt;&lt; Back. to high scores</a></p>'
;
// Limpa os dados da pontuação para limpar o formulário
$name =
Çscore =
$screenshot =
mysqli_close($dbc); .
}
else {
echo '<p class=’
’
error">Sorry, there... = Desculpe, houve um problema com o
arquivo que você tentou enviar.</p>*;
}
)
}
else {
echo '<p class=”error”>0 arquivo precisa ser um gráfico GIF, JPEG ou PNG com ’
menos
de ’ . ’ KB1 . (GVJ_MAXFILESIZE / 1024) . ' KB de tamanho.
</p>';
}
// Tenta excluir o arquivo gráfico temporário
unlink($_FILES['screenshot'
] f'tmp_name']);
else {
echo ’
<p ciass="error">Por favor, digite todas as informações para adicionar sua
pontuação.
</p>1;
mysqli_query($dbc, $query);
você está aqui ► 2 6 9
test drive addscore.php
T f e S T O R f v e
Adicione a validação dos arquivos gráficos ao script Adicionar Pontuação.
Modifique o script addscore .php de modo que ele passe a usar o novo código de validação dos
arquivos gráficos. Envie o script para o seu servidor e teste o formulário Adicionar Pontuação com
imagens válidas e inválidas (imagens grandes demais ou arquivos de outro tipo).
não existem
Perguntas idiotas
í * Por que existem dois tipos MIME diferentes
para imagens JPEG?
Essa é uma pergunta que pode ser mais bem
respondida pelosfabricantes de navegadores, os quais,
por algum motivo, decidiram usar tipos MIMEdiferentes
para imagens JPEG. Para nos certificarmos de que
avalidação de arquivos JPEGfuncionará na maior
quantidade de navegadores possível, é necessário
verificar ambos os tipos.
* Por que é necessário verificar se os arquivos
têm mais de 0 byte? Os arquivos gráficos não têm
sempre mais do que 0 byte?
Nateoria, sim
. Masétecnicamentepossível criar um
arquivode0 bytenoservidor, casoousuárioespecifique
umarquivoquenãoexista noseu própriocomputador.
Apenasparase resguardarcasoissoaconteça,
addscore.
php tomaaatitudemaissegura, qual sejaa
deverificar seoarquivonãoestávazio.
" F * Por que GW_MAXFILESIZE é colocado
em appvars.php, uma vez que só é usado em
addscore.php?
Embora seja verdade que appvars.php
foi elaborado paraarmazenar dados que sejam
compartilhados entre diversos scripts, eletambémé um
bomlugar para se armazenar quaisquer constantes.
Neste caso, colocar GW_MAXFILESIZEem appvars.php
facilita que a encontremos, caso você queira aumentar o
limite de tamanho paraos arquivos enviados.
F -C o m o funciona a linha de código que contém
@unlink()?
Afunção internado PHP unlink () apaga um
arquivo do servidor, no nosso caso o arquivo temporário
quefoi enviado. Uma vez que é possível que o upload
tenha falhado, eque não haja arquivo temporário, nós
suprimimos quaisquer potenciais erros gerados por
unlink () colocando umsímbolo (@
) antes dele.
Você pode colocar @
nafrente de qualquer função PHP
para suprimir o recurso de relatar erros dessa função.
trabalhando com dados armazenados em arquivos
E quanto às
pontuações não verificadas?
Elas nSo desapareceram, se é
que você não reparou.
A lista das pontuações precisa ser limpa.
Com o upload dos arquivos gráficos aperfeiçoados graças à
validação, não podemos continuar ignorando o problema das
pontuações não verificadas. As novas pontuações, com imagens
comprobatórias, não podem ficar atrás das pontuações antigas sem
comprovação, as quais podem ou não ser legítimas. O Guitar Wars
precisa de uma forma de remover pontuações antigas!
esta tomprovada, o ^ e *ao
desperta muitâ towÇian£3 nos
outros usuários..
g u i t a r w a r s
; 345900
^ N ane: Etkiis Vanaii
: B
ate2
0
0
5
-0
4
-2
3
0
9
:0
6
:3
5
id i - — .fa,. ■
■
=i; war« ..
7 2008-04-22 14:37:34 Paco Jastorius 127650
2
2008-04-22 21:27:54 Nevil Johansson 98430
3 2008-04-23 09:06:35 Eddie Vanilli 345900
4 2008-04-23 09:12:53 Belita Chevy 282470
5 2008-04-23 09:13:34 A shton Sim pson 368420
V 2008-04-23 14:09:50 KennyLavitz 64930
7 2008-04-24 08:13:52 Phiz Lairston 186580 phizsscore.gif
M pointuâ^oes
sem imagens
£omprobatórias
precisam sev
removidas do
banco de dados,
Escreva aqui como você faria para limpar as pontuações não
verificadas da lista:
você esté aqui ► 271
adicionando uma página admin
Planeje uma página Admin
Uma vez que só precisamos remover algumas pontuações não verificadas
do banco de dados, é perfeitamente razoável simplesmente acionar uma
ferramenta SQL e remover linhas manualmente, com algumas consultas
DELETE. Mas esta poderá não ser a última vez que tenha de remover
uma pontuação, e não é divertido ter de usar consultas SQL manuais
para fazer a manutenção de uma aplicação web. A ideia aqui é elaborar
uma aplicação que possa ser mantida com o mínimo de trabalho possível.
O que precisamos é de uma página à qual somente o administrador
do site tenha acesso, e que ele possa usar para remover pontuações...
uma página Admin! Mas precisamos tomar muito cuidado na hora
de distinguir quais partes do Guitar Wars são para o administrador e
quais partes são para os usuários.
Estas páginas são para os usuários:
As a p lic a ç õ e s W eb
Çte<Juetitemente
in c lu e m páginas
pataacessp púUíco,
bem como páginas
admín apenas para
ps administradores
Çazerem^
manutençãp do site-
A fiÿn d M»dio*air Pontuaçao e
<
3pâÿnâ principal do éjwtar lAfôrs
sSo elaboradas para os usuir»os
-Ç'm
aîs submeterem e visualizarei
suas pontuações.
Esta página é apenas para o administrador:
pa^inâ hd**"me elaborada apenas
para uso do administrador do £«te
—vote nao «uer os *suârios
-finais possa» sair por aí removendo
pontuações.
GuitarWars-HighScoresAdmiiriaratíon
____
■ 08:13:343BHa>ag«w
; » fa U irrtM 2008-04-2408:13^2 1863H
2O0S«-2«OS-,2 li
, MOSíM-i, M.OTJ0W?» R m i>
Oidar em urn link
“Remove’ apa^a a
respectiva pontuaçao.
trabalhando com dados armazenados em arquivos
fccícío Escreva aqui o que os scripts Admin e de Remover Pontuação precisam fazer para
implementarmos um recurso de remoção de pontuações no Guitar Wars. Em seguida,
faça um esboço de como a remoção afetaria uma linha da tabela g u i t a r w a r s e a
sua respectiva imagem.
admin.php
Servidor web
removescore.php
guitarwars
■ f ! ! » I Í ! I f c l ■ H M M i score Mxeensfcot
1 2008-04-22 14:37:34 Paco Jastorius 127650
2 2008-04-22 21:27:54 Nevil Johansson 98430
3 2008-04-23 09:06:35 Eddie Vani/Ii 345900
4 2008-04-23 09:12:53 Belita Chevy 282470
5 2008-04-23 09:13:34 Ashton Simpson 358420
6 2008-04-23 14:09:50 Kenny Lavitz 64930
7 2008-04-24 08:13:52 Phiz Lairston 186580 phrzsscore.gif
exercício soiução
Escreva aqui o que os scripts Admin e Remover Pontuação precisam fazer
para implementarmos um recurso de remoção de pontuações no Guitar Wars.
Em seguida, faça um esboço de como a remoção afetaria uma linha da tabela
SoLuÇâo guitarwars e a sua respectiva imagem.
Guitas' Wars - High Scorn Administration
I Bekwisalia.ofallG
oíB
xW
a
reliighs
c
o
re
s
.Ussfiiiip
a
g
etore
m
o
vesconsa
sn
e
e
d
e
d
.J
AshtonStapsoa 2Ö08-0+-2309:13:513(58420Ramftw ’
EddieVaitQB 2Q0MM-23 09«635 345900 toliW S
Be&aCbery 2003^)4-2408;02:11282470
PKiLaftstoa 2008-04-2408:13.52 1S6580BsSBEä
PacoJaaurius 2008-04-240S«2:11 1276SGg&s£2&
NenUohaasson2008-04-2403.(0:11 98430 Reirovc
Kaonj-Lavttz 200804-23 14:09’5064930 Emwe
Servidor web
1
0 strip t admin.phf lista, todas as linhas
da tabela, wda uma dom um link w
Rcmovew
ao lado, o <ual repassa iníorma^oes para
o sóript Removçr Pontuaçao-
admin.php
0 .s^lft-VcmoycstorçrfKp. remove......
propriamente,o registro do.bando de
e^lui o arquivo jyraíido do.servidor,
e*ibe uma mensajem de,fiowíirmação-
dados, D
a
t^
e depoiss^jl Guitar Wars -RemoveaHigh Score
T
ltèh
ig
hs
c
o
n
?of3
6
S
4
2
0fcrA
U
ito
nS
in
q
p
o
o
sw
a
ss
a
c
c
e
*s
fu
ltyre
o
s
>
v
c
d
.
« B
a
c
k
,isadminpage
removescore.php
g u i t a r w a r s
m ilBlÜftM» « 0 « screenshot
1 2008-04-22 14:37:34 Paco Jastorius 127650
2 2008-04-22 21:27:54 Nevil Johansson 98430
3 2008-04-23 09:06:35 Eddie Vanilli 345900
4 2008-04-23 09:12:53 Belita Chevy 282470
6 2008-04-23 14:09:50 Kenny Lavitz 64930
7 2008-04-24 08:13:52 Phiz Lairston 186580 phizsscore.gif
pmbora esta Imha em par-utuia» now
tenHa um arquivo ^ráíido assodiado,
o sdript Remover Pontuação terá de
estâr pronto para exdluir do servidor
os arquivos de pontuações ^ue os
tenham dssodiados.
trabalhando com dados armazenados em arquivos
Gerelinks para remoção depontuapões na página Admin
Embora o script Remover Pontuação seja responsável pela remoção propriamente
dita, nós precisamos de um script Admin que nos permita selecionar uma pontuação
a ser eliminada. O script admin.php gera uma lista de pontuações, com links “Remove”
para cada uma. Esses links repassam os dados referentes à respectiva pontuação para o
script removescore.php.
<?php
require_once (
'
'appvars .php'
) ;
require_once ('.connectvars.php'
) ;
m
/! Conecta-se ao banco de dados admin.php
$dbc = mysqli_COnnect(DB_HOST, DBjJSER, DB_PASSWORD, DB_NAME);
// Obtém os dados das pontuações a partir do MySQL
$query = "SELECT * FROM guitarwars ORDER BY score DESC, date ASC";
$data = mysqli_query($dbc, $query);
// Faz um loop através do array contendo os dados das pontuações, formatando-os como HTML
while ($row = mysqli_fetch_array{$data)} ■
{
echo '<table>'; A URL fèrâ o i f i R«wowr
Pon-tuâáJo «stá íazjCndo mais do ‘V*«
a^cnâs dviav um link ^av3 o s tric t ■
*
mysqli_close($dbc) ;
você está aqui ► 275
introduzindo a requisição GET
Osscriptssãocapazesdecomunicarem-seunscomosoutros
A URL de um
scriptp^de
ser usa<Japata
enviar dadps na
í°rma de uma
r e ^ u ls iç ã ^ G E T T
Para o script Remover Pontuação poder excluir um registro, ele
precisa saber qual. Mas isso é decidido no script Admin. Isso leva
à pergunta “com o o script Admin informa a Remover Pontuação
qual registro deve ser excluído?”Essa comunicação entre os scripts
é realizada empacotando-se os dados como parte de uma URL
“Remove”para cada pontuação mostrada na página Admin. Se
você analisar os detalhes da URL de uma determinada pontuação,
perceberá que todos os dados referentes a ela se encontram lá.
Cada m-Çormaçao
tem w
rv
>nomC
t um valor, e
e separada de
outros pares de
nome/valov ^or
um símbolo ?
■
A URL de K
RemoveM
Cria links para o script
removesCore.php, ^às
tambem inclui dados
reíerentes à linha a ser
excluída-
Guitar Wars - High Scores Administration
i imm-X 09:13:3435g42(f K ^ n ..........
2«MM3«MMas3«SOtSíVJ
200MM*(»:l3aBigíS
»aB(HB 
Wahâns™ JOOWHMoMttn98430 Haw»
aa»OM31*OM[»««» SaaaB
Clicar neste link nao só abre o sír]
Remover PontuaWo, Como tambem
envia dados, na íorma de uma
requisição éj£T-
OK, então os dados são enviados através de uma URL, mas como
exatamente o script Remover Pontuação põe as mãos nesses dados?
Os dados enviados a um script através de uma URL ficam disponíveis
na superglobal $_GET, que é um array bastante semelhante a $_POST.
Empacotar dados em uma URL linkada é o mesmo que usar uma
requisição GET em um formulário web. Em uma requisição GET
tradicional do HTML, os dados do formulário são automaticamente
enviados para o script que os processará, como parte da URL desse
script. Estamos fazendo o mesmo aqui, ao criarmos manualmente a nossa
própria requisição GET como parte de uma URL personalizada.
Assim como $_POST, para usar o array $_GET para acessar os dados das
pontuações você precisa do nome de cada informação desejada.
URU que leva 3 /
umscript serve C o m o ^
£orma de envia*/ Ml
o nome da ih&rmacao
e usado para acessa-
array
umâ
dados mportânteS)
trabalhando com dados armazenados em arquivos
Não entendo por que tanto
entusiasmo com GET. Por que não
podemos passar os dados para o script
usando P05T? E assim que vimos
fazendo até agora.
As requisições POST só podem ser iniciadas por
um formulário, enquanto que as requisições GET
podem ser empacotadas como URLs.
Até o momento, nós sempre enviamos dados aos scripts a partir
de um formulário, no qual o script encontrava-se listado como
a ação para o botão Submit. Quando o usuário preenche o
formulário e clica no botão Submit, os dados são empacotados e
enviados para o formulário como uma requisição POST.
O problema é que a página Admin não usa um formulário para
iniciar o script Remover Pontuação. Ela apenas estabelece links
para o script, via uma URL. Assim, nós precisamos de uma forma
de enviar dadosa um scriptusando nada mais do que uma URL. E
aqui que GET é particularmente útil, uma vez que fornece acesso
a dados que estão empacotados em uma URL como parâmetros.
De forma semelhante a POST, os dados que são enviados ao script
através de uma requisição GET ficam disponíveis através de uma
superglobal, mas esta é chamada de $_GET em vez de $_POST.
Oi -formulários web
-íVe<uentemen-fce
usam re^uisidoes
POST para submeter
dados, os <uas -Pica»
armazenados no array
? POST.
0 envio dc
dados através
de uma URL e
-feito dom éj£T,
e os dados sao
armazenados no
array ?_é}£T.
$ POST
v o c ê está aqui ► 2 7 7
GET versus POST
Sobre G-ETse POSTs
A diferença entre GET e POST não é apenas de formulário
versus URL, uma vez que as requisições GET podem ser (e
frequentemente são) usadas para se submeter dados de
formulário, também. A distinção real entre GET e POST tem a
ver com a intenção da requisição. GET é usada principalmente
para se obter dados do servidor sem afetar nada nele. POST,
por outro lado, geralmente envolve o envio de dados para
o servidor, após o que o estado do servidor normalmente se
modifica, de alguma forma, em resposta aos dados enviados.
Os doísi^pPS de
te ^ u ís lç õ e s W eb ,
GET~e rOSTT
controlam o mojo
c o n ]o VQC-e e ílV x c l
dctdP S d e e pQtcl
scripts.
GET
—
'—~ ~ posT
; banco. Os dados de GET, as
>em uma.resP“ ^ . só odem ser feitas mediante
,requisições ,^ nWeb Também ao . --------„„ltc
. aaçãodeu m t o " ^ osemiadosemuma I ao m ■
uma URL Ao contrário
contráriode GET,os ndid0s. I TOST' GETse™ pnncpalmente para
;requisiçãoPOSTBc^ enviarpequenas quantidades de dados.
nã° ermtÊamaaaÊÊmmmmt'' —
Geralmente usada para obtenção de dados
que nao modifiquem nada no servidor.
Para quantidades pequenas de dados, GET
também é útil para enviá-los diretamente
ao servidor, em uma URL. Ao contrário
de POST (TFT________•
T * - Já vi formulários web que usavam GET. Como
isso funciona?
Tanto GET quanto POSTtêmo seu lugar, no que
se refere aformulários web. Ao se criar um, o atributo
method da tag <form> controla o modo como os dados
são enviados, enquanto que o atributo action identifica o
script que deverá receber e processar os dados:
<form method="post’
' action="addscore.php">
Quando o botão submit é clicado para submeter este
formulário, o script addscore.php é executado, eosdados
são enviados a ele através do array $_POST. Mas você
poderia muito bemter escrito atag <form> desta maneira,
emcujo caso os dados seriamenviados através do array
$J3ET:
<form method="get" action="addscore,php">
"P - Ah, então não faz diferença se eu uso o método
GET ou POST?
Errado. Faz bastante diferença. GETgeralmente é
usado para se obter dados de umservidor, sem modificar
nada nele. Assim, GETé perfeito para formulários que
p e r g u n ta s id io ta s
requisitem inTormações do servidor semalterar o seu
estado, como por exemplo, ao selecionar linhas de um
banco de dados. POST, por outro lado, é mais adequado
para requisições que afetemo estado do servidor, como
por exemplo, emitir consultas INSERTou DELETEque
modifiquem o banco de dados. Outra distinção entre GET
e POSTé que os dados enviados através de GETficam
visíveis em uma URL, enquanto que os dados de POST
ficamescondidos e, portanto, umpouquinho mais seguros.
"P * Como essa distinção entre GET e POST se reflete
no envio de dados a um script através de uma URL?
i l : Bem
, antesdetudo, vocêsópodeenviardadosaum
scriptatravésdeumaURLseestiver usandoumarequisição
G
ET, portantoPOSTéeliminadoimediatamente.Alémdisso,
umavezqueGETéusadounicamentecomrequisiçõesque
nãoalteremoestadodoservidor, issosignificaquevocênão
devefazer INSERTs, DELETEFROMsouqualqueroutracoisa
quemodifiqueobancodedadosemumscriptqueesteja
recebendodadosatravésdasuaURL.
trabalhando com dados armazenados em arquivos
Conversa Informal
Esta noite falando: GETe POST
GET:
Mas então, fiquei sabendo que você anda
dizendo que eu só presto para responder
perguntas, mas não consigo fazer nada
com as respostas. E verdade?
OK; é verdade que eu não fui elaborado
para causar modificações no servidor,
como apagar arquivos ou adicionar
linhas ao banco de dados, mas isso não
quer dizer que não sou importante.
Éverdade, mas você fica
permanentemente grudado com o seu
amiguinho, o Formulário, enquanto
que ele e eu somos apenas conhecidos.
Eu tenho outras amizades, como por
exemplo, URL.
Bem, então eu tenho uma pergunta para
você. Como exatamente você age quando
o seu ajudante, o Formulário, não está
disponível. Você sabe que àsvezes a Página
não acha necessário se dar ao trabalho de
requisitar osserviços do Formulário
Calma aí. Só estou ressaltando que,
embora a minha função seja obter dados
do servidor, eu sou razoavelmente flexível
no modo como posso ser usado para isso.
POST:
Claro que é. Vamos encarar, você não tem
nenhuma capacidade além da de pedir
algo ao servidor.
Sevocê está dizendo. Tudo o que eu sei é
que seria difícil fazer algo acontecer sem
pessoas como eu, que realmente trabalham.
Se o servidor ficasse sempre no mesmo
estado, seria tudo bem chato na aplicação.
Então vócê acha que o seu “círculo de
amizades”de alguma forma compensa a
sua incapacidade de agir? Não sei, não.
Olha, o Formulário é meu amigo, e há
muito tempo eu me comprometi a não
fazer nenhuma requisição sem ele. Pode
julgar a minha lealdade se quiser, mas eu
não vou trair meu amigo!
Ok, admito que você tem razão nisso.
Fico feliz de ouvi-lo. Foi um prazer
conversar com você...
você está aqui > 2 7 9
como removescore.php vai funcionar
(rET, POST e a rewopão de pontuapões
Nósjá sabemos que a remoção de pontuações no GuitarWars começa com um link “Remove”
na páginaAdmin, o qual aponta para o scriptRemoverPontuação. Nós sabemos também que
os dados podem ser enviados através da URL do link para o script. Mas temos um problema:
uma requisição GET não deve fazermodificações no servidor, como apagaruma pontuação.
Uma possível solução é não mudar nada no servidor... ainda. E se o script RemoverPontuação,
inicialmente, exibisse uma página de confirmação antes de realmente excluir a pontuação do
banco de dados?
W
ma pagina de donfiv-mação
da ao usuaVi© uma dt
<Wnrmar a rem otào, t mvez.
de simplesmente exeduia-la
instantaneamente
A página de confirmação mostra o registro a ser removido,
junto com um simples formulário de Yes/No. SelecionarYes e
clicar no botão Submit resulta em a pontuação ser removida,
enquanto que escolher No cancela a operação.
Pensando em termos de GETs e POSTs, o script Remover
Pontuação pode exibir a página de confirmação como uma
resposta à requisição GET do script Admin. E uma vez que a
própria confirmação é um formulário, ela pode emitir a sua
própria requisição POST quando submetida. Se o formulário
for autorreferente, o mesmo script (removescore.php) poderá
processar o POST e executar a remoção. Eis os passos desse
processo:
É to ta lm e n te
pPssíVel, e ate
utíl em alguns
OctS9S, <JUeO
m e sm o sc rip t
re s p o n d a ta n to
te ^ u ls fç o e s G E '
rOSTT
A O scrip t Rem over Pon tuação é iniciado, atravé s de um a req uisição GET,
” pelo usuário ao c licar no link “Rem ove” da págin a Adm in.
© O scrip t Rem over Pon tuação u sa o s d a d o s arm azen ad os no array $_GET
para ge rar um form ulário de co n firm ação da exclusão.
A O scrip t Rem over Pon tuação é iniciado novam ente, d esta vez através de
” um a req uisição P O ST do usuário que e stá subm eten do o form ulário de
confirm ação.
O O scrip t Rem over Pon tuação a p a g a o registro se le cio n ad o do ban co de
dados, e tam bém a p a g a do servidor o arquivo gráfico contendo a im agem
com probatória.
trabalhando com dados armazenados em arquivos
Vejamos agora como o processo de
exclusão de pontuações se desenvolve,
através de uma série de passos...
Uma requisidao éjET c
usada fara se inidiar
o sdript Remover
Pon{>aça©z enviar os
dados da fontuadao
atvavés de uma URL.
Uma requisição
POST e usada para
se in'did'r ° sdri^t^
Remover Pontuadão
(novamente!^ « enviar
a ele o re<ystvo 3 se'r
deletado
$_GE1
^ o W
á dados de ^ ^
imagem dom^robator‘»
a
çava esta pont^adao-
Este e o mesmo
sdript, só que reaÿndo
di-feventemente
don-forme redeba uma
requisição óiè-T ovr
POST.
Guitar Wars - Remove a High Score
TbsMghscoreof368420torAstainSin^soawa>successfullyremoved.
« Back toadcâa page
removescore.php
0 strict Remover Pontuado
apa$a Oreysbro do bando
de dados, e a sua re s ^ v a
ima^em do servidor.
você esté aqui > 2 8 1
mais sobre GET e POST
nã? existem
ferguntas Idiotas
? • Como é possível o mesmo script processar tanto requisições GET
quanto POST?
Aresposta tema ver como modo como o script é chamado. Nocaso
do script Remover Pontuação, ele é chamado de duas formas diferentes. A
primeira é quando o usuário clica emum link “Remove" da páginaAdmin,
emcujo caso uma URL o leva até oscript. Uma vez que os dados são
empacotados dentro da URL, essa éconsiderada uma requisição GET.
Ela faz oscript gerar umformulário web, cuja ação aponta de volta para
o mesmo script Remover Pontuação. Assim, quando o usuário submete
oformulário, o script é chamado pela segunda vez. Mas, ao contrário da
primeira, não há nenhuma URL contendo dados, e, portanto, nenhuma
requisição GET. Emvez disso, os dados da pontuação a ser removida são
enviados através de uma requisição POSTeficam, portanto, disponíveis no
array $_POST.
T * - Então a forma como o script é chamado é o que realmente
determina o que ele faz?
Sim! Quando oscript vê que alguns dados foram enviados através de
uma URL, na forma de uma requisição GET, ele sabe que deve exibir um
formulário de confirmação, emvez de apagar qualquer coisa do banco de
dados. Assim, os dados enviados no array $_GETsão usados apenas dentro
da página de confirmação, e nãotêm nenhum efeito duradouro noservidor.
Quando o script vê que há dados sendo enviados através de uma requisição
POST, ele sabe que pode apagar os dados do banco, Assim, ele usao
array $_POST para acessar os dados e criar uma consulta DELETE FROM
que apaga a pontuação. Euma vez que a maioria das pontuações tem um
respectivo arquivo gráfico armazenado no servidor, o script também apaga
esse arquivo.
trabalhando com dados armazenados em arquivos
Isole a maior pontuapão para ser removida
Com o processo de remoção explicado, podemos agora concentrar
nossa atenção no lado do banco de dados. O script Remover
Pontuação é responsável por excluir um registro de pontuação, o
que implica excluir uma linha do banco. Como você deve se lembrar,
a instrução SQL DELETE FROM nos permite apagar linhas. Mas,
para fazê-lo, precisamos primeiramente achar a linha. Isso é feito
colocando-se uma cláusula WHERE na consulta que usa DELETE
FROM. Por exemplo, esta consulta SQL apaga a linha cuja coluna
name está definida como 'Ashton Simpson':
DELETE FROM guitarwars WHERE name = 'Ashton Simpson'
g u i t a r w a r s
iHOWí n n w
1 2008-04-22 14:37:34 Paco Jastorius 127650
2 2008-04-2221:27:54 Nevil Johansson 98430
3 2008-04-23 09:06:35 Eddie Vanilli 345900
4 2008-04-23 09:12:53 Belita Chevy /282470
5 2008-04-23 09:13:34 C-Ashton Simpson ^
4^— 'm
.
368420
6 2008-04-23 14:09:50 Kenny Lavitz 64930
7 2008-04-2408:13:52 PhizLairston 186580 phizsscore.gif
Esta Consulta apaga
ImHas cuja coluna
name ContenHa
o texto ’Ashton
Simpson.
0 nome da tabela
é obvi^atário tom
DéLéTB FROM, ^
para que a instruça«
saiba de que tabela
vote esta apagando
dados.
0 home do usuário e o
drrfcerio usado para se
apajar a pontuação.
Há, porém, um problema com esta consulta. Em um mundo de
milhões de Guitar Warriors, existe a possibilidade de haver mais de
um Ashton Simpson. Esta consulta não apaga somente uma linha,
ela exclui todas as linhas que tenham o nome 'Ashton Simpson'. A
consulta precisa de mais informações para apagar a linha certa:
DELETE FROM guitarwars MIERE name = 1
Ashton Simpson '
Ao se esjcúiíidar a
powtuaçaoJunto Com
— o nome, a operação
f íica muito mais
 predisa.
g u i t a r w a r s
iliül! ^ípmííitîîlíii^ll^^illlïil|iîíl|ïíí S l l l l i i i i i l l l screenshot
1 2008-04-22 14:37:34 Paco Jastorius 127650
2 2008-04-2221:27:54 Nevil Johansson 98430
3 2008-04-23 09:06:35 Eddie Vanilli 345900
4 2008-04-2309:12:53 Belita Chevy 282470 —
5 2008-04-23 09:13:34 ^Ashton Simpson 368420"““c
6 2008-04-23 14:09:50 Kenny Lavitz
7 2008-04-2408:13:52 Phiz Lairston 186580 phizsscore.gif
0 operador AND modiíica a
ConsuIta, de modo que tanto
o nome quânto â pontuação
predisâm corresponder ao que
sendo pedido.
Agora que tanto o nome quanto a
consulta precisam corresponder ao
que está sendo pedido, a cbânce de
se apagar acidentalmente »
»
»
a
is de
uma iir.Ha diminui Consideravelmente-
você está aqui ► 2 8 3
colocando um LIMIT no seu DELETE
Controle oquanto você pode remover com UMIT
Usar as colunas de nome e de pontuação como base para se excluir uma linha
é bom... mas não o suficiente. O desenvolvimento de aplicações tem que se
pautar pela m inim ização dos riscos a qualquer custo, e ainda há um pequeno
riso de se apagar mais de uma linha que tenham o mesmo nome e a mesma
pontuação. A solução é forçar a consulta a só apagar uma linha, não importa
o que aconteça. A cláusula LIMIT faz isso acontecer:
DELETE S f f i i ® í arwars name = 'Ashton Simpson' AND score =
'■
368420 'ÍSl*ÜSÉ (V, W • »W . a*
Coloque um limite sobre o *W ro de
linhas que podem sev- apagadas.
O número após LIMIT diz ao MySQL o número máximo de linhas
que podem ser apagadas - neste caso, uma. Assim, fica garantido
que nunca apagaremos mais de uma linha com esta consulta. Mas
e se houver dois Ashton Simpsons com a mesma pontuação? É
claro que este é um cenário improvável, mas àsvezes vale a pena
considerar cenários extremos ao se pensar no melhor projeto
possível para uma aplicação.
g u i t a r w a r s
.d ilb líÉ IfllillJ É M ilillil name score @ S P P ÍI:|
1 2008-04-22 14:37:34 Paco Jastorius 127650
2 2008-04-22 21:27:54 Nevil Johansson 98430
3 2008-04-23 09:06:35 Eddie Vanilli 345900
4 2008-04-23 09:12:53 Belita Chevy 282470
( 5 2008-04-23 09:13:34^ Ashton Simpson 368420
*
v - l -2008-U4-23 14:09:50" Kenny Lavitz 64930
7 2008-04-24 08:13:52 Phiz Lairston 186580 phizsscore.gif
2008-11-04 10:03:21" "Ashton iimpson 368420 ashtonsscore.^
jpg _
Puas linhas Com
e*atâmente o mesmo
nome e a mesma
fontuaçao apresentam
um problema para
a nossa Consulta
DELETE.
Escreva abaixo o que acontece com esta tabela quando a instrução
DELETE acima é executada. Como você poderia certificar-se de
que a pontuação correta seja apagada?
trabalhando com dados armazenados em arquivos
Faria alguma diferença usar a
ID da pontuação na cláusula WHERE da
consulta DELETE FROM? Isso poderia
ajudar a garantir que estaremos apagando
a pontuação certa, não?
Sim, poderia! A ID da pontuação é a maneira perfeita de
se isolar o registro para ser apagado.
A unicidade é uma das principais vantagens de se criar chaves
primárias para as suas tabelas. A coluna id da tabela guitarwars é a
chave primária e, portanto, é única para cada pontuação. Usando
essa coluna na cláusula WHERE da consulta DELETE FROM, nós
eliminamos toda a dúvida sobre qual registro será excluído. Eis uma
nova consulta, desta vez usando a coluna id para nos ajudar:
DELETE FROM guitarwars WHERE
Havendo a confiança de que a coluna id é de fato a chave primária,
este código apagará de forma segura apenas uma linha. Mas e se não
tiver sido você quem criou o banco de dados, e talvez a unicidade
não tenha sido devidamente implementada. Nesse caso, uma cláusula
LIMIT poderia ainda ser útil. O raciocínio é este: sempre que você
quiser afetar apenas uma linha, deixe isso claro na consulta.
DELETE FROM guitarwars WHERE id =
Nunca é má ideia ser bastante explícito com o que você quer que seja
feito em uma consulta, e neste caso, LIMIT adiciona uma medida
adicional de segurança à consulta DELETE.
O
Apagar dados tom
base cr* uma dhave
prmatria ajuda a
garantir precisão ao
se isolar a linha dev-ta
para ser e*dlwda-
A dláusuh LIM IT diz.
e^plid-itâmente ‘V**
a donsulta nao pode
apagar »ais de w^a
linha•
você está aqui ► 2 8 5
o script removescore.php quase pronto
Im as de Geladeira PHP & M /S o L
O script removescore.php está quase pronto, mas ainda faltam
algumas partes importantes do código. Use os imas para preencher
as lacunas no código e implementar no Guitar Wars a capacidade de
eliminar pontuações indesejadas.
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang-’
'en’
' lang-"en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Guitar Wars - Remover uma Pontuag.ao</title>
clink rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<h2>Guitar Wars - Remove a High Score</h2>
<?php
('appvars.php');
(’connectvars.
php’);
if (isset($_GET['id'3) && isset($_GET['date']) && isset($_GET[’name']) &&
isset{$ GET['score']) && isset($_G£T[ ............. 1)) i
// Pega os dados em GET
$id = $_GET['id’];
$date = $_GET['date'];
$name = $_GET ['
name1];
$score = $_GET['score'];
= $ GET [ .....];
else if (isset($_POST['id']) &£ isset($_POST[’name']) isset($_POST[1score
// Pega os dados em POST
= $ POST[ ];
$name = $ POST[1name'];
$score = $_POST['score'];
$ sceenshot = $_POST ['screenshot'];
}
else {
echo '
<p class="error">= Desculpe, nenhuma pontuaçao foi especij-icada para
removida.</p>1;
}
if (isset($_POST['submit'])) {
if ($_POST['confirm'] == ) {
// Exclui o arquivo gráfico do servidor
@unlink(GW_UPLOADPATH . $screenshot);
// Conecte no banco de dados
$dbc = mysqli_connect(DB_HOST, DB_USER, DB_PASSWORD,.DBJJAME);
trabalhando com dados armazenados em arquivos
// Exclui os dados da pontuação do banco
$query = " guitarwars WHERE LIMIT
mysqlí_query($dbc, Squery);
mysqli_close($dbc) ;
// Confirma êxito com o usuário
echo '<p>'A pontuação de ' . ' para 1 . ' foi removida com sucesso.';
else
echo '<p class="error">A pontuação nào foi removida.</p>';
else if (isset( ) && isset( ) && isset( ) &
&
isset($score) &5 isset($screenshot)) {
echo 1cp>Temcerteza de que deseja apagar a pontuação abaixo?</p>'
;
echo 1
<pXstrong>Nome: </strong>' . $name. '<br /><strong>Date: </strong>' . $date .
’<br /><strong>Pontuação: </strong>' . $score . [
c/p>';
echo 'cform method="post” action=,'removescore.php">';
echo 'cinput type="radio" name="confirm" value="Yes" /> Yes
echo '<input type="radio" naine="confirm" value="No" checked="checksd"/> No <br/>'
echo ’<input type="submit" value="Submit" name="submit" />';
echo ’
<input type="hidden" name= value="’
echo 'cinput type="hidden" name="name" value="1 . $name . /tr­
echo 'cinput type="hidden" name="score" value="' . $score .
echo 'cinput type="hidden" naxae="name="screeshot"value="1.$ screeshot.'”/>;
echo 'cp>ca href=
?>
c/body>
c/html>
>Slt;6lt; Voltar para a página admin</aX/p> '
removescore.php
v o c e e s tá aqui 2 8 7
o script removescore.php finalizado
Imas de Geladeira YHY e MySQL - Solução
O script removescore.php está quase pronto, mas ainda faltam algumas partes
importantes do código. Use os imas para preencher as lacunas no código e implementar
no GuitarWars a capacidade de eliminar pontuações indesejadas.
chtml xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Guitar Wars - Remover uma Pontuagao</title>
dink rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<h2>Guitar Wars - Remove a High Score</h2>
<?php
require_once
fndlua os arquivos de script
dompav-tilHados, mas use
required_ende, uma vez. que
elcs sao essendiais para a
remodao das pontuadoes.
iE‘
’
Tis’
setT$"GErTt,rd’]) £& isset ($_GET [’date ’]) && isset($_GET['name11
) &&
isset ($_GET [’score ’]) && isset($_GET[ ’screenshot’Hi)} {
require__once
:
{'appvars-php');
h 'connectvars-php[);
// Pega os dados em GET
$id = $_GET['id'];
$date = $_GET[’date'];
$name = $_GET['name 1];
$score = $_GET['score’];
$screenshot |j|i= $_get
I
0 sdript reaje
diferentemente
dowíorme a requîsidâo
redebida seja fcjET ou
POST- ^
// Pbcjb os dados 6
i
f
t POST
else if Usse, ^ P O S n . ^ » « Í...US « isset <^POST r score „ <
A diretiva PttP de supressão de erros, 0,
impede que erros sejâm relatados, faz. sentido
usar essa opÇdo dom unlinkO, uma vez. que
poderemos estar tentando exdluir um arquivo
que nao existe- Messe daso, nao queremos que o
usuirio redeba uma mensagem de erro.
$name = $_POST ['name 'D
$score = $_POST[1score 1
$screenshot=$_POST[1screenslyít1]
else {
L“ ‘ .< c l^ r r o ^ 4 ^ — £OÍ eSPeClflCada P“ a
echo '<P class- eriuj. y
rem ovito</p> J « « f o it
} usado para se remover
quaisquer pontuações,
^ de modo que o arquivo
i l | (S_POST [ ' c o n f ir m ' ] - e M l3 Ío
ser excluído tombent.
if (i/set($_POST[’submit'1)
7/ Exclui o arquivo gráfico do servidor^
@uniink(GW_UPLOADPATH . $screenshot>;
" COT * = a= b^°sqli! d=onL=t,DB__HOST, DENSER, ;
trabalhando com dados armazenados em arquivos
// Exclui os dados da pontuação do banco
$query = " gguitarwars WHERE jLIMIT
mysqli_query($dbc, $query);
mysqli_close($dbc);
// Confirma êxito com o usuário
echo '<p>T'A pontuação de ’ . ' para ’ foi removida com sucesso.1'
else
echo '<p class="error">A pontuação não foi removida.</p>' ;
else if (isset isset ( ) && isset { ') &
£
isset($score) && isset($screenshot)) {
echo '
<p>Tem certeza de que deseja apagar a pontuação abaixo?</p>'
;
echo '<p><strong>Nome: </strong>' . Çname . '<br /><strong>Date: </strong>'
’<br /><strong>Pontuação: </strong>' . $score . ' < / p > ' ;
echo '<form method="post" action="removescore.php">'
;
echo '<input type="radio" namè="confirm" value="Yes" /> Yes
echo '<input type="radio" name=’
,
confirm" vElue="No" checked="checked"/>No <br
/>’
echo ’<input type="submit" value="Submit" nc®e=r
'
submit" />';
echo '<input type="hidden" name= |vaiípe=" " />’;
echo '<input type="hidden" name="name’
' value="'V $name .
echo 'cinput type—"hidden" name="score" value="' Çscore . />’;
echo ’cinput type="hidden" name="screenshot" value%^' . $screenshot .
/>1
echo '</form>';
echo '<p><a href= ;&lt; Voltar para a página admin</ax, p>'
;
</body>
</html>
rert.ovescore.php
pagma Mrn*} para mclKor ft tówfos esCo*did<* SBLF3 0 Wmulári,
»avegacao. ,^7 ~ J F<*>e «só incluiria . r-
■ ^ «a* usaA* quaisquer dados que tenha» de Con-hrmâÇao
alguns ímãs-
do -formulário são usados
para se armazenarem
os dados da pontuaçao,
para que eles sejam
enviados Como parte da
requisiçãoPOST.
sido enviados através da URL,
que****«
^ ti+ ic a r de que nenW, dado
seja enviadoju^tocom este
TGTwiujári©“ aPenAfi D/u t
apehâs dados P (O T
você está aqui ►
so e exibido
se todas
estas variáveis
estiverem
definidas.
2 8 9
o test drive final do aplicativo guitar wars
T fe S T O r iv ë
Adicione os scripts de Remover Pontuação e Admin ao Guitar Wars,
para que seja possível excluir pontuações.
Crie dois novos arquivos de texto, removes core .php e admin.php, e insira neles o
código que acabamos de completar. Envie os novos scripts para o seu servidor, e depois
abra o script Admin no seu navegador. Clique no link "Remove" de uma pontuação
que você queira excluir, e depois confirme a remoção na página Remover Pontuação.
Volte à página Admin para se certificar de que o registro foi apagado, e depois vá para a
página principal do Guitar Wars (Index.php), para ver lá o efeito da modificação.
A nova página
Remover Pontuaçao
fiuida de d-on-firmâr
e -fazer a remoção
das pontuações
mdesejadas.
Tt pájma pv-intipal
do éjuitar Wars
a^ora só mostra
pontuações
tomprovadas.
st
A nova pá^na Ad
-fornede links para se
removerem pontuações
nao vevi-fitadas-
£ste e o pequeno
Jatob, Quitar
VVarrior prodfyo
Os ^uitav-
Warriors
legítimos
esta© -felizes,
ajora <^ueso
Há pontuaçSes
domprovadas.
As pontuações hao
vcriíi&adasj ou seja*
aquelas sem imagens
£.omprobató*r'sas, -foram
removidas do sistema-
trabalhando com dados armazenados em arquivos
Palavras Cruzadas PHP & M /S Q L
Cansado de enviar arquivos gráficos? Que tal então
enviar um pouco de conhecimento para um monte
de quadrinhos?
Horizontais
I. 0 atributo type da tag <input> deve ser definido
como isto, para que um campo do formulário aceite
upload de arquivos.
4. Geralmente éuma boaideia armazenar as imagens
enviadas àaplicação emuma pasta....
8. Esta instrução SQLé usadaparase modificara
estrutura de umatabela.
10. Esta instrução SQLé usadapara secolocaros
resultados de umaconsulta emumadeterminada ordem.
II. Informações sobreos arquivos enviadossão
armazenadas navariável superglobal $....
12. Estainstrução PHPé usada parase inserir código de
outro script.
13. Éum
aboaideiafazeristocomumarquivorecém
-enviado.
Verticais
2. Para impedir que uma instruçãoDELETEFROM
apague maisde uma linha, useesta instrução.
3. Quando umarquivoéenviado através de umformulário,
eleécolocadoem umapasta... no servidor.
5. Aoalterar umatabela, este comando SQLcuida de
adicionar uma novacoluna.
6. Estainstrução PHPé usadapara se criar uma
constante.
7. Os arquivos includesão bastante úteis parase... dados
entre váriosscripts.
9. Esta instrução SQLé usada como parte de outra
instrução para ordenar resultados de consultas em
ordem descendente.
você está aqui > 2 9 1
palavras cruzadas php e mysql - solução
TalaVras Cruzadas PíTP & MySQL
Solução
trabalhando com dados armazenados em arquivos
Sua Caixa de Ferramentas PHP£- MySQl
Fique à vontade para fazer uma
m K F reverência virtual. Você não só ó
adorado pelos guitarristas virtuais do
mundo todo, como também adquiriu novas
habilidades em PHP e MySQL: alterar a estrutura
de tabelas, lidar com uploads de arquivos,
controlar a ordem de dados e remover dados.
você está aqui > 293
CAFITOIO
5
7«tn an c[o a Sua Aplfcaçã° Segura
* Presuma que Estão Todos
Querendo TePegar
^ f r
Seus pais estavam certos: não fale com estranhos. Ou pelo menos
não confie neles. Na pior das situações, não dê a eles as chaves
para acessar os dados da sua aplicação, presumindo que eles não
vão fazer nada de errado. Vivemos num mundo cruel, e você não
pode partir do princípio que todos são confiáveis. Na verdade, como
desenvolvedor de aplicações web você precisa ser metade incrédulo
e metade adepto de teorias de conspiração. Sim, as pessoas em geral
são más e elas definitivamente querem te pegar! OK, talvez isso seja
um pouco de exagero, mas é muito importante levar a segurança
a sério e elaborar as suas aplicações de forma que elas fiquem
protegidas contra qualquer um que pretenda causar danos.
este é um novo capítulo ► 295
guitar wars está sendo hackeado
0 dia em quea música morreu
Parece que os quinze minutos de fama do nosso roqueiro-virtual-prodígio se
acabaram: a pontuação deJacob no Guitar Wars sumiu,junto com todas as
outras. Pareee que há alguma força do mal em ação, bagunçando o aplicaüvo
e impedindo os Guitar Warriors de terem os seus placares publicados.
Guitamstas virtuais insatisfeitos são usuários insatisfeitos, e a consequência
última disso é um desenvolvedor de aplicações insatisfeito... você!
0 re tw d is h do Quitar
Wars, Jaíob, está
■furioso por a suâ pontuâdao
"ter sumido da lista.
0 armamento musita!
pre-ferido de Jafcob, uma
Eradicasíer saíra 2-005
segurança para a sua aplicação
Para ondeforam as pontuapões?
Nós sabemos que a página principal do Guitar Wars está vazia, mas
será que isso significa que o banco de dados também está vazio?
Uma consulta. SELECT pode responder essa questão:
A tonsuita SÊU&CT revela
<
^u
e a -tabela ^ui-tavwa«
esta tompíe-tamen-te vazia—
todas as pcm-tuatoes se
Çerèd 4- ^
De algum modo, todas as linhas de dados foram apagadas do banco
Guitar Wars. Seria possível que alguém talvez esteja usando o nosso script
Remover Pontuação para o mal? Nós temos de proteger as pontuações!
i- %Aponte seu lápis
Faça um círculo em torno das técnicas, dentre as apresentadas a
seguir, que você poderia usar para proteger as pontuações do Guitar
Wars contra hackers, e escreva em baixo o porquê.
Proteger com senha a página Admin, de
modo que somente quem souber a senha
(você!) possa remover pontuações.
Criar um sistema de registro dos
usuários, e só conceder a alguns (de
preferência só a você!) os privilégios
administrativos.
Verificar o endereço IP do computador que
está tentando acessar a página Admin, e só
permitir alguns endereços (de preferência
apenas o seu próprio!).
Eliminar totalmente o recurso de
remover pontuações.
você está aqui ► 297
protegendo as pontuações do guitar wars’
ponte seu lápis
Solupão Faça um círculo em torno das técnicas, dentre as apresentadas
a seguir, que você poderia usar para proteger as pontuações do
Guitar Wars contra hackers, e escreva em baixo o porquê.
Proteger com senha a página Admin, de
modo que somente quem souber a senha
(você!) possa remover pontuações.
.Proteger Çcm.senha.a.página,Admin;e uma
. bod .e.yâpjdâi porque na© ç muit©...
complicada e -for^ete ao site umaseguy-an^a
|razjoáyel ^apiçtemente-
Todas as tefcnicas foram
circuladas, porque W as elas
são Capa**s de resolver o
problema, embora al^uwâs
seja» «ais viáves <ue ouíras.
Criar um sistema de registro dos usuários/^
e só conceder a alguns (de preferência só
a você!) os privilégios administrativos.
Um sistema de registro dos usuários, Com privilégios
administrativos limitados, e uma otima solu^ao, mas
envolve bastante planejamento e programarão... o
Quitar tVars.precisa.de segurança, a^ora/(.............
Verificar o endereço IP do computador que
está tentando acessar a página Admin, e só
permitir alguns endereços (de preferência
apenas o seu próprio!).
Veri-fitar © {P funCiona, mas.torna, o site
dependente do endereço |P do seu Êoi^putador,
o <ual poderá se modificar.
Remover o recurso cevtamente resolve este
problema específico, mas lembre-se: o reCurs© foi
adicionado originalmente, no Capítulo anterior,
pdv~a tornâr a manutenção do site mais fácil.
segurança para a sua aplicação
Seguranpa contra os bárbaros
Uma maneira simples e direta de se garantir rapidamente a
segurança do Guitar Wars é usar autenticação HTTP para
proteger com senha a página Admin. Na prática, será pedido
um nome e uma senha, mas a ideia teórica é exigir do
administrador uma determinada informação secreta antes de
permitir que ele tenha acesso a recursos restritos da aplicação,
como por exemplo, os links para remoção de pontuações.
Quando uma página é protegida usando-se autenticação
HTTP, aparece umajanela pop-up pedindo o nome do
usuário e a senha, para que seja concedido o acesso à página
protegida. No caso do Guitar Wars, você pode limitar o acesso
à página Admin a qualquer número de pessoas que quiser,
possivelmente até a apenas você!
A autenticação
HTTP oíetece uma
forma slniples de se
fazer a segurança
de uma página tju &
useri ir.
Aja*e!a de autentiíadão
^TTP agorâ se ihterpoe
entre os usuários « 3
página Admi».
m
As fwituaçSes do hante de
dados agora estao protegidas,
u*a vez. ^ue o âtesso à págihj
Adrift restringido.
guitarw ars
um iffllilillfSffi IPffü ilü ü iwwmm®
14 2008-05-01 20:35:07 ßelita Chevy 232470 beüta&scûre.gïf
15 2008-05-01 20:36:45 Jacob Storihersöft 339740 jasiobsscort.gtf
1& 2008-05-01 20:37:02 Nevil Johansson 93430 nevilsscore çîf
17 2003-05*01 20:37:23 PacoJartorius 127650 pâiossCûre.gif
Iß 2008-05*01 20l
37;40 Phiz Lairston 166380 phizsscore.gif
19 2008-05*01 20:38:00 Kenny Lavitt 64930 kennysscore.gtf
20 2003-05-01 20;îS:23 Jean Paul Jon« 2-4336Û jeanpôu?55cor«.gÍí
Os links M
Rewove da
página Admin agora
só estao disponíveis
para o administrador
do Quitar liVars.
você está aqui ► 2 9 9
usando autenticaçao HTTP
Protegendo a página (ruitar W ars Admin
A autenticação HTTP funciona assim: quando um usuário tenta acessar
uma página protegida, como a nossa página Admin, eles recebem uma
janela que lhes pede um nome de usuário e uma senha.
0 *ave$ador web
us<
3um3jánelâ tomo
esta para re<^uisi£ar
um nome e senha,
antes de permitir o
âéesso a umô Paaina Toviewthispage,you.needtoSogmtoarea
. > J "GuitarWars"onwwfw.giisarwars.ret
pvotegîda.
Your password wil! fcc sent in Oie t'W -
Name: ;
Password;
Para manter as
doisas simples,
a senKa nao e
iriptogra-Pada.
r? Rem
em
berthispasswordinm
yH
eycbain
(■ Carccet
£sta variável superjlobal
do PHP armazena
o nome do usuário
digitado na janela de
autenticarão.
I
$ SERVER['PH P AUTH USER’ ]
$ SERVER['PHP AUTH PW']
r
£sfca variável armazena a
senha diÿtada «a janela de
autentitaçao-
O PHP entra em cena através do seu acesso ao nome e à senha
digitados pelo usuário. Eles ficam armazenados na superglobal
$_SERVER, que é semelhante a outras superglobais que vocêjá usou
($_POST, $_FILES, etc.). Um script PHP pode analisar o nome e a
senha digitados pelo usuário e decidir se ele deve receber acesso à
página protegida. Digamos que só vamos permitir acesso se o nome
do usuário for “rock”e a senha for “roll”. Eis aqui o modo como o
acesso à página Admin é concedido:
A páçynâ Admin so í
aiessível st tiverem sido
diÿtados o nome t a
senha dorreW
/y
s
5_SERVER[.pHp_Â0TH
$ SERVER[ ' PHP__AUTH_USER' ]
l_PW
<]
segurança para a sua aplicação
nã9 existem
Ferguntas idíptas
"P -A autenticação HTTP é realmente segura?
Sime não. Depende do que você está tentando conseguir coma segurança.
Nada é 100%seguro, portanto nós estamos sempre falando de níveis de
segurança. Para se protegerem pontuações no Guitar Wars, aautenticação HTTP
fornece umnível razoável de segurança. Você poderia adicionar criptografia à
senha para ter umnível ainda maior. Porém, mesmo isso provavelmente não seria
suficiente em uma aplicação que envolvesse dados mais sensíveis, como por
exemplo, dados financeiros.
• O que acontece se o nome e a senha forem digitados incorretamente?
K * Onavegador emite umpequeno choque elétrico através do mouse.
Brincadeira, nãoacontece nada tão dramático assim. Emgeral, é exibida uma
mensagem para avisar o usuário de que ele está tentando acessar uma página
segura, a qual aparentemente não é da conta deie. Emúltima instância, évocê
quemescolhe oque essa mensagem deverá dizer.
"P • A autenticação HTTP requer tanto o nome do usuário quanto a senha? E
se eu só quiser usar a senha?
Nãoé obrigatório usar ambos. Se você quiser usar apenas uma senha,
basta verificar só avariável global $_SERVER['PHP_AUTH_PW’]. Falaremos mais
sobre como essa variável é verificada, em instantes..,.
T * • Como exatamente você protege uma página com autenticação HTTP?
Chamando-se uma função PHP?
Exato. Aautenticação HTTPenvolve o estabelecimento de uma linha de
comunicação entre o navegador e o servidor, através de cabeçalhos HTTP. Você
pode pensar no cabeçalho como sendo uma pequena conversa entre o navegador
e o servidor. Ambos usamos cabeçalhosfrequentemente para se comunicarem
fora do contexto do PHP, mas o PHP lhe permite enviar umcabeçalho, que é o
modo como a autenticação HTTPfunciona. Estamos prestes aaprender muito
mais sobre os cabeçalhos eo seu papei na autenticação HTTP com PHP.
Quando é que a
autenticação da página
deve realmente ocorrer?
você está aqui ► 3 0 1
autenticação a cabeçalhos
A autenticação HTTP exige cabeçalhos
A ideia por trás da autenticação HTTP é que o servidor esconda
uma página protegida, e instrua o navegador a pedir um nome
e senha ao usuário. Se o usuário os digitar corretamente, o
navegador vai em frente e fornece a página. O diálogo entre
navegador e servidor se realiza através dos cabeçalhos, que são
pequenas mensagens de texto com instruções específicas sobre o
que está sendo pedido ou entregue.
Os cabeçalhos na verdade são usados sempre que você visita uma
página web, e não apenas quando a autenticação é requerida. Eis
o modo como uma página normal, não protegida, é enviada pelo
servidor para o navegador com a ajuda dos cabeçalhos:
Teclei p á g in a
Veb é entvegue
co m a a ju d a
<fes cakeçalfcps.
Servidor web
O navegador requisita
uma página do
servidor, enviando
alguns cabeçalhos
para identificar o
arquivo sendo pedido
e nome de host do
servidor.
Este Cohjuhte de
tabeçalHos a
U»a jrg^uisj£Ao de
fdgina vieb-
O servidor responde
com um conjunto
de cabeçalhos,
seguidos da página
requisitada.
Este ÿrupo de
cabeçalhos forma
w*â v-esposfa de
fâgma web
índex.php
O navegador recebe os
cabeçalhos e a página,
e gera o código HTML
da página.
Jv/ô f im das dojvbas,
os eabeçalhos ajuda»
a eniv-egar to»
sutesso ao «avegador
a fâg'ma fedida-
segurança para a sua apficação
A n e m ia de
um Cakeçqlfeo --------- -------------------------------------------------------------------
Oscabeçalhos controlam precisamente como e que tipo de informação é enviada do
navegador para o servidorweb, evice-versa. O cabeçalho frequentemente consiste de um
par de nomes/valor que identificauma determinada informação, como por exemplo, o
tipo de conteúdo da página (HTML).Um determinado grupo de cabeçalhos é enviado
ao servidor como parte de uma requisição web, e depois outro grupo é retornado ao
navegador como parte da resposta. Vamosdar uma olhadacom mais detalhes nestes
grupos de cabeçalhos, para descobrir exatamente oque é enviado, àmedida que o
cliente e o servidor comunicam-se um com o outro.
A maioria dos
dabeòalhos donsiste —
de Um par át tiOtnts/
valor separado por
dois pontos.
£ste dabeçalbo
espeii-fída o
navegador <ue
esti -fazendo a
re®uisidâo-
■i£-
_GET / in d e x , p h p H T T P /1 ,
H o s t : www. gui :
;a r w a r s . ne). . i
^.t.lQD^ciose -
U -ser- A g e n t -M c z illa /5 7 Ò T ? > v
" ^ c c ê p c - L n a r s e t : ISD =S SS«7
» Í...'
C a c h e - C Q n tr o l: n o ■
■ :
A c c e p t- L a n g u a g e : d e , e r.; q=Q . 7.
0 primeiro
£abetalho nao t um
par de nomes/valor
- e a requisição 6 ß T
da pagina.
0 primeiro dabeçalbo
a resposta ttTTP do
servidor-
„» „■ 1 1 : 2 2 :0 9 GMT
Server; Apache/2 .0.54
X-Powered-By: PHP/5 .2 .
■.n^far^Enroiii
Content-Type: text/html
0 tonteudo HTML- àd
pagina e enviado logo
após os tabeçalKos
•ndex.php
Este dabefalh© diz. ao
navegador que o donteudo
e dódigo HTML, em vez. de,
por e*emp!o, te*to simples.
Os cabeçalhos nos são importantes, no que diz respeito ao Guitar Wars, porque eles
fornecem o mecanismo que interrompe a entrega de uma página do servidor, requerendo
que o usuário digite um nome e uma senha para liberar a página. Em outras palavras, ê
preciso trabalhar nos cabeçalhos retornados pelo servidor para proteger uma página com
autenticação HTTP.
você está aqui ► 303
entrevista com o cabeçalho
TudoSobreoCabeçalho
Na entrevista desta semana: por
que tanto falatório?
Use a Cabeça!: Você parece estar recebendo
bastante atenção no que diz respeito a autenticar
páginas web. Isso sejustifica ou você está apenas
tendo os seus quinze minutos de fama virtual?
Cabeçalho: Não, isso sejustifica sim. Você está
se esquecendo de que eu tenho um papel vital na
entrega de qualquer página web existente. Assim,
acho que posso dizer que a web nem sequer
funcionaria se eu não estivesse em cena. Eu vou
durar muito mais do que quinze minutos, mesmo
que as pessoas não apreciem o meu trabalho.
Use a Cabeça!: Então qual é exatamente esse
papel que você desempenha?
Cabeçalho: Você tem que entender
que navegadores e servidores web não
são pessoas, portanto eles não podem
simplesmente ligar um para o outro ou enviar
uma mensagem de texto.
Use a Cabeça!: SÉRIO?!
Cabeçalho: Sim, eu sei que é um choque, mas
as máquinas simplesmente não se comunicam do
mesmo jeito que as pessoas. Mas os navegadores
e os servidores ainda precisam falar uns com os
outros, e eles o fazem através de mim.
Use a Cabeça!: E como isso acontece?
Cabeçalho: Quando alguém digita uma URL ou
clica em um link de uma página, o navegador
cria uma requisição GET e a envia ao servidor.
Essa requisição é empacotada em uma série
de cabeçalhos, cada um dos quais contendo
informações sobre a requisição. Eles contêm
informações como o nome e o host da página
sendo pedida; o tipo de navegador que está
fazendo o pedido, etc.
Use a Cabeça!: Não consigo ver o que há de
tão importante nisso.
Cabeçalho: Bem, quando você vai a um café,
você acha importante dizer ao atendente que
quer um cappuccino grande sem creme?
Use a Cabeça!: Claro que sim, o atendente
precisa saber o que é que eu quero.
Cabeçalho: É a mesma coisa, aqui. O
navegador diz ao servidor o que ele quer,
empacotando a requisição e enviando-a em
cabeçalhos.
Use a Cabeça!: Interessante. Mas ouvi dizer
que os servidores também são capazes
de enviar cabeçalhos. Eu pensava que os
servidores só enviassem páginas web.
Cabeçalho: Ah, boa pergunta. A minha
importância no outro lado da comunicação é a
mesma, porque o servidor precisa fazer mais
do que apenas jogar um monte de conteúdo
em cima do navegador. O navegador poderia
não ter a menor ideia do que fazer com esse
conteúdo, se não lhe fosse passadas mais
algumas informações.
Use a Cabeça!: Como por exemplo...?
Cabeçalho: O tipo do conteúdo seria um
exemplo. Essa é provavelmente a informação
mais importante, mas o servidor envia também
outras coisas, como o tamanho do conteúdo, a
data e a hora da entrega, e assim por diante.
Use a Cabeça!: Quando é que a página
propriamente dita é enviada?
Cabeçalho: O conteúdo, seja ele código HTML,
dados PDF ou dados de imagens como um GIF
ou JPEG, segue logo depois que o servidor me
envia ao navegador.
Use a Cabeça!: OK; estou começando a
entender como você funciona em relação às
páginas normais. Mas e quanto a esse negócio
de autenticação?
Cabeçalho: Eu desempenho o mesmo
papel em uma página autenticada que nas
páginas normais, exceto pelo fato de que
eu também cuido de informar ao navegador
que página precisa ser autenticada. Dessa
forma, o navegador poderá pedir ao usuário as
informações de autenticação.
Use a Cabeça!: Ou seja, um nome de usuário
e uma senha?
Cabeçalho: Exatamente. E depois, fica a cargo
do código PHP no servidor decidir se o nome
e a senha são válidos, em cujo caso o servidor
pode enviar o restante da página.
Use a Cabeça!: Fascinante. Obrigado pelos
esclarecimentos.
Cabeçalho: Sem problemas. Isso faz parte do
meu trabalho.
segurança para a sua aplicação
Controle os cabeçalhos com PHP
Com o PHP, você pode controlar cuidadosamente os cabeçalhos
enviados pelo servidor ao navegador, abrindo a possibilidade
de realizar tarefas como a autenticação HTTP. A função interna
header() é usada para se enviar um cabeçalho, do servidor para o
navegador, de dentro de um script PHP.
|{1Content-Type: text/html');
A função header() envia imediatamente o cabeçalho, e deve
ser chamada antes de qualquer conteúdo propriamente dito ser
enviado ao navegador. Esse é um requerimento bastante estrito
- se mesmo um único caracter ou espaço for enviado antes do
cabeçalho, o navegador o rejeitará com um erro. Por esse motivo,
as chamadas à função header() devem preceder qualquer código
HTML dentro de um script PHP;
Mesmo um espaÇo «*e
viesse antes da tag "v.
<?php tausaria um V
erro «este sdript de <?php
e*<»y*plo-
A íunçãp
h e a d e rO llie
petmfte Gtlat
e enViar um
cctkeçalfeç» a
partír <le um
script?HP-
0 servidor envia
este fiôbeçaiho ao
«avegador para ser
frodessado, antes de
tentar enviar «^uai^uer
parte do Conteúdo
ffTM L da página-
0 s espaços dentro das
tags <?php ?> não e
problema, porque eles
não são repassados
para o navegador.
?>
Chtml xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
lang="en" >
</html>
você está aqui ►
como a autenticação de cabeçaiho funciona?
Autenticando com cabeçalhos
Para se autenticar a página Admin do Guitar Wars mediante
cabeçalhos, é preciso criar um conjunto bastante específico deles -
dois, na verdade —
, que façam o navegador saber que deve pedir um
nome e uma senha ao usuário antes de entregar a página. Esses dois
cabeçalhos são gerados através de código PHP no script Admin, e
controlam a entrega da página para o navegador.
Servidor web
O
s. dabeçalHos de
autentüação HTTP são
enviados do servidor para
o have^ador.
Navegador
web do cliente
Sãç>necess&iPs
ck>is cabeçaljiog
e s p e c í f ic o ^ p a r a
se Ve^jUeVeVa
autenticação de
uma página Web,
.
í’
5
5
1'
U
n
a
ú
t
h
Ô
-
r
i
â
i
ê
â
'
^
^
Á
ü
f
c
f
t
é
n
t
i
G
â
f
c
Q
:
-;Wi/ ;
Êa^ic rpalm^Guitar;;»:
0 «ave^ador, eniao,
pede <ue o usuário
digrte um home t
umd senha-
Antes de enviar o
ton-teído da p%*»
admm-pbp para o
navegador» o servidor
protessa <uais<uer
eabetalKos da pa<ynâ
To view tn«s page, you n e td to log in to area
“G uitar Wars" on www.9
uitajwars.net
Your password will be sent in the cfcar.
.ftfettae; . ,.;rock ;
Password: j « •••
0 'tentsmber this password in rt«y ioychain
Os dois cabeçalhos necessários para se iniciar a autenticação
fazem duas coisas bastante específicas:
£ste dabeçalho in-Porma
ao navejador ^ue
pagina.
lo a ver a
Este tabeçalHo pede ao
navegador para tentar
âutentitar o usuário,
pedindo~lKe um nome e
uma senKâ-
WWW-Authenticate : Basic realms"Guitar Wars
0 basid realm” (domínio basidos) e
apegas uma expressão usada para
►dentsíidar individualmente esta
autentidaçao em partidular - ela
aparede «ajanela de autentidadão.
segurança para a sua aplicação
Após processar os cabeçalhos, o navegador espera a resposta do usuário,
através dajanela de autenticação. O navegador responde com ações
completamente diferentes, dependendo do que o usuário fizer...
Gaitar Wars -HighScoresAdministration
Below isalisto£allGuitarWarshighscores.Usethispagetoremovescoresasneeded.
JacobScorchmon2008-05-0120:36:45 389740Remove
BdltaChevy
Jean Paul Jones
PbizLajrstoo
Paco Jasiorius
NevilJohansson
KenayLavitz
0 to M id o HTML- da pag>»a
Admin t CntreguC depois «U€
SC digitâ um nomC Cum3
se*Ha Corretos.
2GG8-OS-OÍ 2056:07 282470 Rgmrrw
2008-05-01 20:38:23 243260 Remava
20)8-05-01 20:37:40 1865SOReraove
2008-05-01 20:37:23 127650 Remove
2008-05-01.20:37:02 98430 Remove
2008-05-0120:3S:00 64930
admin,php
Se o nome ea senHa
do usuario -fore»
subtmctidos e -fWem
inCometos, aja^ela de
autewticac^o ape»>3s
aporeCe para usuário
Toviewthispa*, your*môtotegin» area
“Guitar Wars“on *M*.guitarwars.,net ;
Your passwordwlft 6 »*« * m.thedeir.
Name:' :: . . ................
Password:
n Remember This password in my keychair?
£C
a
n
c
e
l^
A aplicacao tem a
oportunidade de -finalizar o
script e e*bir ur*>a message»*
de erro personalizada? caso o
usuário tainCele o proCesso de
auterttiCâÇâo-
Se o usuário digitar um nome e
senha corretos, e clicar em Log
In, o servidor envia o conteúdo
HTML da página admin.php para
o navegador. Este exibe a página
Admin, e o usuário poderá então
remover pontuações, da mesma
forma como na versão não
protegida anterior.
Se o usuário digitou um nome e
senha incorretos, e clicar em Login
In, o servidor diz para o navegador
pedir ao usuário de novo o login.
O navegador continuará este
processo enquanto o usuário tentar
combinações incorretas de nome e
senha. Em outras palavras, se eles não
souberem o nome e a senha, o único
jeito de sair é clicar em CANCELAR.
Se o usuário clicar em CANCELAR
para sair da autenticação, o servidor
envia para o, navegador uma página
com uma mensagem de acesso negado
e nada mais — a página admin.php
não foi enviada. A mensagem de
acesso negado é controlada pelo
código PHP no script admin.php que
está associado com os cabeçalhos.
Este código chama a função PHP
exit() para mostrar a mensagem e
imediatamente sair do script:
exit('<h2>Guitar Wars</h2>Sorry, you must enter a
valid '
'user name and password to access this page.');
você está aqui > 3 0 7
imas de Geladeira PHF
No script Admin do Guitar Wars, estão faltando diversos pedaços
importantes do código PHP que fornece a autenticação HTTP. Use os imas
para completar o código abaixo, e use cabeçalhos para tornar a página
segura. Dica: alguns imas poderão ser usados mais de uma vez.
finalizando o código de autenticação
<?php / Nome do usuário e senha para autenticação
= 'rock';
.............. = 'roll';
if (
!isset { ....................................... ) I1
!isset ( .................................... ) iI
($_SERVER['
PHP_AUTH__USER'] !=....... ) I
I ($J3EKVER [’
PHP_AUTH_PW'] !=......... )
) {
// Nome do usuário/senha incorretos, então enviar os cabeçalhos de autenticação
........ ('HTTP/l.1 401 Unauthorized');
........ ('WWW-Authenticate: Basic realm= .............. '
) ;
....... (
'<h2>Guitar Wars</h2>Desculpe, v o c ê deve digitar um’.
'válida para acessar esta página.'
) ;
}
?>
<html xmlns="http://www.w3 .org/1999/xhtml" xml:lang="en" lang="en">
</html>
segurança para a sua aplicação
Será que é possível
enviar outros tipos de
cabeçalhos usando-se PHP?
Sim , é possível... o s c a b e ç a lh o s n ão se rve m a p e n a s
p ara se g u ra n ç a .
Embora a autenticação seja o principal caso em que os cabeçalhos se
fazem necessários, eles são bastante flexíveis e são capazes de fazer outras
coisas interessantes. Basta chamar a função header() com o par de
nome/valor apropriado, desta forma:
0 navegador é <?php ^
redirecionado à
abouipKp, h
e
a
d
e
r(ItttaitWSHIláillílHlS
após receber ?>
este Cabeçalho- Neste caso, temos um cabeçalho de localização, o qual
redireciona da página atual para outra, chamada aboutphp, no
mesmo site do Guitar Wars. Aqui, nós usamos um cabeçalho
semelhante para redirecionar para a página aboutphp depois de
cinco segundos:
0 navegador è
redirecionado
para a pagina
About depois de
5 segundos.
?>
Ve^laem!
O s c a b e ça lh o s
p recisam se r a
prim eira c o isa
enviada ao
navegador, em
um arquivo PHP.
echo T
Em 5 segundos, você será levado para a página About.’;
E neste caso, nós temos um cabeçalho de
recarregamento, uma vez que ele recarrega a página
após ter-se passado um determinado período de
tempo. Você frequentemente vê a URL nesse tipo de
cabeçalho referenciar a página atual, para que ela se
recarregue periodicamente.
Um último caso é o chamado cabeçalho de tipo de conteúdo,
porque ele controla o tipo do conteúdo sendo entregue
pelo servidor. Como exemplo,você pode forçar uma página
a ser exibidacomo texto puro, em vezde HTML, usando o
seguinte cabeçalho ao chamar a função header():
Devido ao fato de os
cabeçalhos serem enviados
antes de qualquer conteúdo, é
extremamente importante não
permitir que um espaço sequer
apareça fora do código PHP,
antes de ser chamada a função
headerQ no script PHP.
<1php
header{
*
0 Conteúdo é entregue
(
„PI 3o navegador Como
11] ; texto simples.
echo 'Este <strong>texto</strong> na verdade não aparecerá
em negrito.';
?>
Neste exemplo, o texto enviado ao navegador é exibido
exatamente como mostrado, sem nenhuma formatação
especial. Em outras palavras, o servidor está dizendo ao
navegador para não exibir o conteúdo como HTML, e
portanto, as tags HTML são exibidas literalmente, como texto.
você está aqui ► 309
o código de autenticação completo
íütas de Geladeira PHP - Solupão
No script Admin do Guitar Wars, estão faltando diversos pedaços importantes
do código PHPque fornece aautenticação HTTP. Use os imas para completar
o código abaixo, e use 0 para tornar a página Admin segura. Dica: alguns imas
poderão ser usados mais de uma vez.
<?php // Nome do usuário e senha para autenticaçao
j (.——
^ O^nome do usuário c d senha
ião • â 3 dos e*nVâriâveis,
5= 1roll '; h° m'&l° do seript-
$ M^global
f^
B
R
V
B
K
d
á
êtesso do fcon*e t à
senha digitados pelo
uswivio nà janela de
âutentida^ao.
!isset (I £ |_SERVER
1'ERVER[’PHP_AUTH_PW ’]
$password Éf ^
ll
rio/senha incorretos, então enviar os cabeçalhos de autenticaçao
|
(’HTTP/1.1 401 Unauthorized');
í'WWW-Authenticate: Basic realm= I "Guitar Wars
Wars</h2>Desculpe, você deve digitar um" .
dos para acesar esta página.'
); $ duas thârsâdas 3 íunçao
A -função exítO exibe uma mensagem headerO resulta** e» estes
de erro e devtiíida—
se de nada mais tabeçalhos sevem enviados ao
se*- enviado ao navegador, no evento navegador-
de uma £alha de awtentídaçao.
<html xmlns="http://www.w3 .org/1999/xhtml" xml:lang="en" lang- en >
'usuário e senha
}
?>
0 nome e â senha
digitados pelo usuário
sa©veri-fidados aqui.
entregue ao navegador
até que os cabeçalhos
tenham sido enviados t
prodessados.
admin.php
™ ::.; 401 Authorised
WWii-Autnentieats:
Basic.
realm="Guitar Wars'
segurança para a sua aplicação
T fe S T O R fv e
Adicione autorização HTTP ao script Admin.
Modifique o script admin.php de modo que ele passe a usar autenticação HTTP, para
que só você tenha acesso a ele. Envie o script para o seu servidor, e depois abra-o no seu
navegador. Experimente digitar um nome e senha errados primeiro, para ver como o
acesso é restringido.
r Bt9aCHt*V ------ -
tofeLi**» axiwJwiMíJftiowwssfl*»
H**9l * a M WGfcS
ta jU v to SDO
M
W
H30;3Sá»^3C E
áS
S
tfS
Uiw nome de
usuário e wm
â
sertKâ a$orâ
impedem o atesso ^
I j ' ’
™
nao autorizado á
fá^md Admi*.
. . * )
Pohtuaçoes nâo podem scr
removidas semauWisaçao
Score: 3897«
u i ta
Q u ita r $
Os furtar Wàrriors
es-bao íeli2
Les por a
ãfiitação a^ora estar
se^uraf
nap existem
Perguntas Idiotas
Quando exatamente a função exit() échamada
no script Admin do Guitar Wars?
K:I Embora afunção exit() apareça no código PHP
logo abaixo das duas chamadas a headerQ, ela só é
chamada se o usuário sair dajanela de autenticação,
clicando no botão Cancel. Se a autenticação falhar, o
servidor não continua a execução para alémdas duas
chamadas a header(}. Emvez disso, ele re-envia os
cabeçalhos etenta novamente. Somente se o usuário
clicar emCancel éque o servidor chega àfunção exit(),
emcujo caso ele envia o conteúdo da chamada àfunção,
e nada mais. Se a autenticação tiver sucesso, exit{)
nãoé chamada, porque o script nunca chega à parte
de dentro da declaração if- ocódigo dentro de if só é
executado se nãoexistirem umnome e senha definidos,
ou se eles tiverem sido digitados incorretamente.
O de uma autenticação HTTP tem algum
propósito real?
1^1 Sim, ele define umazona de segurança que é
protegida por umdeterminado nome de usuário e senha.
Uma vez que o nome e senha tenham sido digitados
corretamente, em umdeterminado realm, o navegador
irá se lembrar deles, e não continuará a exibir ajanela
de autenticação para cabeçalhos subsequentes no
mesmo realm. Emouíras palavras, os realms permitem
que o navegador se lembre que vocêjá atendeu aos
requerimentos desegurança para umdeterminado
conjunto de páginas - basta especificar o mesmo realm
paraos cabeçalhos de autenticação dessas páginas.
você está aqui ¥ 3 1 1
outro problema de segurança
Boa tentativa,
espertinho! Felizmente, eu
salvei o link para a página de
remoção de pontuações, e depois
falsifiquei um pouco a data. O link
é este aqui no quadro que estou
segurando.
«ri«-,doyouhavewhatittakest0r-nvt >
.
http://www.guitarwars.net/
removescore.
hp?id=10&name=Jacob%20
Scorcherson&
date=2008-05-01 %20
20:36:45&score=389740&
screenshot=jacobsscore,gif:
M> nâof As pohtua^oes
desapareceram da
apiiòôçao guitar Wars
dcnovo^.
Parete <ue a nossa vila
do éjwtar Wars destobriu
umd -forma de dontornar
a nossa tewtatwa de
tornar o guitar Wars
mais sc^uro-
V Isto tudo tertamente é firíptito, mas
â URL fârà a fa^ma removes£orephp
de íato «ao passa feia pa$ina admin-
php secura-
QK, então talvez o Quitar Wars N&O esteja seguro
Isso é que é um sucesso de pouca duração. Não demorou para os
vilões atacarem novamente, apagando as pontuações do Guitar
Wars e mais uma vez frustrando osjogadores. Parece que só tomar
a página Admin segura não foi suficiente, uma vez que o script
Remover Pontuação ainda pode ser acessado diretamente... se você
souber o que está fazendo.
Escreva abaixo como você acha que poderíamos resolver este novo
problema, evitando que as pontuações sejam apagadas:
segurança para a sua aplicação
Nós
precisamos tornar seguro o script Remover
Pontuação, e tenho quase certeza que podemos simplesmente
O ^-------- usar a autenticação HTTP novamente.
Fvahk 0%
 toç
Joe: Faz sentido,já que funcionou bem para a página Admin.
Frank: É verdade. Então tudo o que temos de fazer é colocar o mesmo
código de cabeçalho de autorização no script Remover Pontuação, e
pronto. Certo?
Jill: Sim, isso certamente vai funcionar. Mas eu me preocupo em replicar
todo aquele código de autorização em dois lugares. O que acontecerá
se, no futuro, nós tivermos de adicionar outra página que precise ser
protegida? Nós replicamos o código mais uma vez?
Joe: É; código duplicado é definitivamente um problema.
Principalmente porque há um nome de usuário e uma senha que todos
os scripts precisam compartilhar. Se algum dia quisermos mudá-los,
teremos de fazer a modificação em cada um dos scripts protegidos
Frank: Já sei! Que tal colocar asvariáveis fusername e Spassword em
um arquivo include próprio, e depois compartilhá-lo entre os scripts
protegidos? Nós poderíamos até mesmo colocá-las no arquivo include
appvars.php dasvariáveis da aplicação
Joe: Eu gostei do raciocínio, mas essa solução só lida com uma pequena
parte do problema de duplicação de código. Lembre-se, nós estamos
falando de um pedaço de código relativamente grande.
<?php
// Nome do usuário e ssnha para. autenticação
Çusername = 'rock';
$password = ’roll'
;
if (!isset($_SERVER[’PHP_AUTH_USER1]) |
| !isset($_SERVER['PHP AUTH P W ]) U
($_SERVER[1PHP_AUTH_USER'
] != $username) || ($_SERVER['PHP_AUTH_Pw” ] '
= $password)) {
// Nome do usuário/senha incorretos, então enviar os cabeçalhos de autenticação
header('HTTP/l.1401 Unauthorized');
header ('WWW-Authenticate:Basic realm-"Guitar Wars" ’);
exit (
•<h2>Guitar Wars</h2>Desculpe, você precisa digitar uma senha válida para acessar
esta pagina. '
) ;
}
?>
<html>
admin.pnp
Jill: Vocês dois têm razão, e é por isso que eu acho que precisamos de um novo arquivo incluae
para armazenar todo o código de autorização, e não apenas asvariáveis fusemame e Spassword.
Frank: Ah, e nós podemos simplesmente incluir esse script em qualquer página que
quisermos proteger com autorização HTTP.
Joe: Isso mesmo! Só precisamos nos certificar de sempre incluí-lo em primeiro lugar, uma
vez que ele depende dos cabeçalhos para todo o trabalho de autorização HTTP.
você está aqui ► 313
criando authoríze.php
Crie um script Autorizar
Nósjá temos todo o código de que precisamos para um novo seript,
Autorizar; é só uma questão de passar o código de admin.php para
um novo arquivo (authoríze.php), e substituir o código original por
uma instrução require_once. re-tirav»do este
de advwmphp
para o dolotavwos ko seu
próprio arqwWo de siripi,
auihori«.pVip.
admin.php
segurança para a sua aplicação
<?php
// Nome do usuário e senha para autenticaçao
$username = 1rock1;
$password = 'roll1;
^ 0 "« “O«sl- dt JuWidatâo,
a je ita elas d cra rtilh a v*, o 
»CSm
o « M * «sA-io e a « *«a «„ha.
i, <
,i „ . t ($ SERVER[
'PHP.AUTH USER' ,, II ’
^ . . w o r « »
,
<
• cvBVFR I'PHP AUTH USER'] !=$username) i
l (§_SEKVtKi ^ -
)rNo
rdoLuàr-io/se-nha i„corretos, entto envrar os cabeçalhos^---------
autenticação (
'HTTP/l .1401 Unauthorized l ’ ÂST
você precisa digitar ur,a s e n h a vâlida para acessar
esta página.1);
authorize,php
0 sdript Autorizar Compartilhado C
incluído logo «o mítio deste sdript» u»3
vez. <
^u
e ele thama a •(•w^ao headerO.
<?php
require_once('authorise.php1);
?>
<html>
<?php
require_once('authorize.php’);
?>
0 dódi^o de
auter»tida^ão no
script Admin e
substituído por
«má uni£a linha de
âódi^o PHP.
admin.php
removescore.php
PONTOS DE BALA
Os scripts PHP podem usar cabeçalhos para
controlar o modo como o servidor entrega
conteúdo web ao navegador.
A função PHP headerQ é usada para se
enviarem cabeçalhos ao navegador, os quais
podem ser usados para se redirecionar uma
página, controlar o tipo de conteúdo da página
ou requisitar a autenticação da página.
Quando os cabeçalhos são enviados ao
navegador usando-se a função header(), as
chamadas a header() devem ser feitas antes
de qualquer conteúdo ser enviado.
Quando uma página é protegida com
autenticação HTTP, o nome e a senha
digitados peio usuário ficam armazenados na
superglobal $_SERVER.
O “basic realm" de uma autenticação HTTP
é uma zona de segurança que se associa a
um determinado nome de usuário e senha,
permitindo que várias páginas tenham a sua
segurança feita conjuntamente.
A função exit() do PHP finaliza um script
PHP, impedindo que qualquer código após
ela seja executado ou enviado de qualquer
maneira ao navegador.
você está aqui ► 3 1 5
segurança não existem perguntas idiotas
nüp existam
p e r g u n ta s id io t a s
I * Ainda não entendo totalmente como a Ethel conseguiu
contornar a segurança do Guitar Wars. O que foi que ela fez?
Eíaseaproveitoudafraqueza inerenteaseproteger apenas uma
página(Admin), quandoo recursode remoçãode pontuaçõesnaverdade
usaduas páginas (AdmineRemover Pontuação). ApáginaAdmin
apresentaumasériede links Remove, vinculadosà página Remover
Pontuação, Osdetalhes sobrequal pontuaçãodeveser removidasão
passados na URL, permitindoqueoscript Remover Pontuaçãoosacesse
atravésdasuperglobal $_GET. Sevocêconseguisseconstruir umaURL
legítimaparaa página Remover Pontuação, poderiaremover pontuações
semjamaispassar pelapáginaAdmin. Foi issoqueEthel fez.
* Mas como ela sabia a estrutura da URL para a página
Remover Pontuação?
H: Elaé bastanteengenhosa, mas nãoé preciso ser gênio para
fazer isso. Lembre-se de queelamencionouque salvouo link para a
página Remover Pontuação, quando osite inteiroestava desprotegido.
Bem, umlink salvo nosfavoritos éapenas uma URL, eela pôde usá*la
para construir uma URLparaacessar diretamente apágina Remover
Pontuaçãosemter de passar pela páginaAdmin.
^ * OK, mas as pontuações foram reinseridas depois do último
ataque. Isso não significa que as URLs antigas não deveriam
funcionar mais, uma vez que as datas estariam diferentes?
H : Sim, éumaobservaçãomuitoboa. Maslembre-se, Ethel ébastante
esperta. Elapodefacilmenteolharnapáginaprincipal doGuitarW
ars,
anotarasnovasdatas, eentãocoíocá-lasnaURLantigapararemoveras
novaspontuaçõessemqualquer problema. Éimportantenuncasubestimar
ahabilidadequepessoasdeterminadastêmdefazerengenhariareversa
nosseusscriptsPH
P, paraexplorarfraquezasdosistema.
Tudo bem, então a proteção das duas páginas, Admin e
Remover Pontuação, consegue parar a Ethel. Mas isso não torna
muito difícil remover pontuações legitimamente?
Não, de forma alguma. Semaajuda dos realms, certamente
seria complicado remover as pontuações legitimamente, porque você
teria de digitar o nome do usuário e a senha separadamente para
as páginasAdmin e Remover Pontuação. Mas lembre-se de quefoi
estabelecido umrealm (domínio) que éo mesmo emambas as páginas
significando que elas estarão dentro da mesma zona de segurança. E
uma vez que você tenha passado pelajanela de autenticação para
uma página de umdado realm, o nome e asenha são lembrados para S lS t^Ü lcU
todo o realm. Oresultado final é que digitar comsucesso o nome e a
senha apenas uma vezjá é suficiente para liberar ambas as páginas.
HutiCct sukestlme a
fcab ilid ad e <Jue p e sso a s
determinadastem
de feizer engenkatia
feVetsa H9Sseus
scriptsTH?, para
explprat- íra^ue^as d°
segurança para a sua aplicação
T fe S T O R tv e
Crie o script Autorizar e o inclua nos scripts Admin e Remover
Pontuação, para torná-los seguros.
Crie um arquivo de texto chamado authorize.php, e digite nele o código para o script
Autorizar. Depois, modifique o script admin.php para que ele inclua o script Autorizar
em vez do código de autenticação HTTP propriamente dito. Adicione a mesma instrução
require_once ao início do script removescore.php, para que ele também fique protegido
pela autenticação HTTP.
Envie todos os scripts para o seu servidor e depois experimente abrir o script Remover
Pontuação diretamente no seu navegador. Talvezvocê precise limpar algumas sessões de
autenticação HTTP prévias, no seu navegador, para que ele lhe peça novamente o nome
e a senha - a maioria dos navegadores memorizam os domínios de autenticação, para que
você não tenha de ficar redigitando o nome e a senha. ^ uw
de usuário t uma sc»h3 "tâwio
para a pa^na Admin ^ua«"b>
fara a Reroov«r Pcwfcuaçao-
http://www.
guitarwars.
net/removescore.
php?
id=10s
name=Jacob%20Scorcherson&
date=2008-05-01%2020:36:45&
score=389740s
screenshot=jacobsscore.
gif
^ £sia URL evrta a ^a$'ma Admm
e aeessa a ?a<y*a Remover
Porcbuaça© dire-Umemie^
A pa^ittâ Remover
Poh-Uatao e pro-tegida,
ihdependev>íeme«ie de £©m©'‘" 
o usuirio dKega a ela- Y,
Tovíewrtfiis fxage, you neícf to log in to area
Yí&ur wtf be inthe ctear.
K
aiue: )
Passywcwd: ;
3Remember this passwpnd to; ksychaln
Q > E R > Q
C É R E B R O
Você consegue pensar
em outras maneiras pelas
quais a aplicação Guitar
Wars esteja em risco?
Guitar Wars - Remove a High Score
: m higà saae Of314340 forBiff f c * was ssccessfuUy
< < Back to admin p apf
v o c ê está aqui ► 3 1 7
(toitar Wars Episódio II: Ataque dos Clones de Pontuapão
Lamentavelmente, a felicidade no universo do Guitar Wars não durou muito, porque
pontuações fantasmas estão aparecendo por toda a parte, no lugar das pontuações
legítimas... o que incita o ódio em todo o universo Guitar Wars. Parece que é
perfeitamente possível danificar a lista de pontuações do Guitar Wars sem remover
pontuações. Mas como?
um fracasso de pontuação falsa
GuitarWars-HighScores
W elcom e, G uitar W arrior, do you h a ve w h a i it takes to crack: the M g li score list? I f so,
500000
N am e: E tíiel Heckel
Date2008-05-0214:0234
Top Score; 50000Q
Gui tar
389740
Name: Jacob Scorctoson
Date:2008•054U20:36:45
L.?ïK'Orl
Scoreï
5
“/Í;§§
sm
ß6
$ïs'
0 redorde de Ethel
€ dlarâmente suspeito,
devido a tapW a de
tela mal -faUiiieada,
e a© -Pato de que ela
d ii
f&r ataso fcohse^uiu
uma pontwaçao
de g*ataweftte
$00.000.
2008-05-01 20:36:45 Jacob Scorcherson
170
389740
belitasscore.gif
jacobsscore.gif
23 2008-05-01 20:37:02 Nevil Johansson 98430 nevilsscore.gif
24 2008-05-01 20:37:23 Paco Jastorius 127650 pacosscore.gif
25
26
2008-05-01 20:37:40 Phiz Lairston 186580
2008-05-01 20:38:00
phizsscore.gif
Kenny Lavitz 64930 kennysscore.gif
27 2008-05-01 20:38:23 Jean Paul Jones 243260 jeanpaulsscore.gif
28 2008-05-01 21:14:56 Leddy Gee 308710 leddysscore.gif
29 2008-05-01 21:15:17 T-Bone Taylor 354190
30 2008-05-02 14:02:54
tbonesscore.gif
Ethel Heckel 500000 ethelsscore.gif >
segurança para a sua aplicação
Subtrapão por adipão
Até agora, vimos assumindo que qualquer pontuação submetida com uma captura de tela
era considerada legítima. Agora, é razoavelmente seguro dizer que nem sempre é o caso! E
está bem claro quem é o culpado...
Ah, sim, sou eu... culpada! Tudo o que tive
de fazer foi enviar as minhas fantasticamente
falsas pontuações, com capturas de telas
retocadas. Ah, é muito bom ser a melhor Quitar
Warrior.
' N
fctheí perdebeu cb
poderia bagunçar basta^^te
o éjuiW Vtòrs sím^lcs»ehÍ€
submemendo jpo?íts/3^oes
das» (om dafUv-as dí
•belas íaUi&tadas-
Escreva abaixo como você resolveria o problema de as pessoas
conseguirem inserir pontuações falsificadas na aplicação Guitar
Wars:
você está aqui ► 319
guitar wars precisa de moderação humana
A segurança requer intervenção humana
Mesmo neste mundo modemo em que vivemos, àsvezes, um ser
humano real, capaz de pensar, é imbatível. No caso em questão, é
difícil ter uma solução melhor, para analisar uma determinada
informação e avaliar se ela é válida ou não, do que uma pessoa
real. Estamos falando da moderação, na qual um ser humano é
encarregado de aprovar o conteúdo enviado a uma aplicação web,
antes de esse conteúdo ser liberado para o público em geral.
Com a moderação, cada nova
pontuaçao é adicionada a© banto de
dados, mas nao aparefce ^ara o public*
en^uâ*to o moderador s
tâo a aprovar.
A moderação
fcumanae uma
forma excelente
de se melhorar
a Integridade
d 9 cç>nteád9
s u b m e tid p
u su âtio g .
A modi-fitaçao ern Admm
adiciona v*mU*k Aprova a cada
nova pontuação, para <*e ela
possa ser aprovada-
Sw k AcHoa
SQQQQQRemove /Approve
389740 Remvft
Simplesmente adicionar uma
nova pontuação nâo mais a
adiciona automaticamente à
lista ^ue pode ser vista pelo
publico.
O Guitar Wars realmente poderia se beneficiar de alguma
moderação. E claro que ainda é possível alguém fraudar
cuidadosamente uma captura de tela, e talvez fazer passar
uma pontuação falsa pelo moderador humano. Mas não
serã fácil, e isso não muda o fato de que a moderação é um
ótimo método de desencorajar os fraudadores. Tenha em
mente que fazer a segurança de uma aplicação PHP depende ^
basicamente de uma boa prevenção. s
Nosso destemido moderador
do Quitar Wars... de nunca se
deparou Com uma pontuaçao ha
<ual Coníiâsse totalmente-
segurança para a sua aplicação
Planeje woderapão no Guitar Wars
Adicionar um recurso de moderação humana ao Guitar Wars é significativo porque isso
afeta diversas partes da aplicação. O banco de dados precisa ser modificado, precisa ser
criado um novo script para executar a aprovação, a página Admin precisa adicionar um
link 'Aprovar" a cada pontuação e, finalmente, a página principal precisa ser modificada
de modo a exibir só as pontuações aprovadas. Com todas as modificações assim envolvidas,
é importante ter um plano e executar uma modificação de cada vez.
Use ALTER para adicionar uma coluna
approved à tabela.
Vamos começar pelo banco de dados, o qual precisa
de uma nova coluna para guardar a informação de se
uma pontuação foi ou não aprovada.
Modifique a página Admin para
incluir um link "Aprovar” para as
pontuações que ainda tenham de
ser aprovadas.
O scriptAprovar Pontuação fica no
back-end e não deverá normalmente
ser acessado diretamente. Em vez disso,
ele é acessado através de links "Aprovar"
gerados e exibidos na páginaAdmin -
somente as pontuações não aprovadas
terão o link "Aprovar”ao lado delas.
S
e
t
t
e
r
W
e
«
<
H
*
*
S
w
e
»
A
A
u
f
a
i
e
t
r
a
t
i
*
»
i Crie um script Aprovar
Q Pontuação para realizar a
tarefa de aprovar uma nova
pontuação (definir a coluna
approved como 1).
Com o banco de dados pronto
para acomodar a aprovação das
pontuações, você precisa de um
script para realizar essa tarefa.
Este script Aprovar Pontuação é
responsável por procurar uma
determinada pontuação no banco e
modificar a coluna approved dela.
Modifique a consulta da
página principal para só exibir
pontuações aprovadas.
O último passo é se certificar de que
tudo o que estamos modificando seja
refletido na exibição da página principal
da aplicação. Assim, a página principal é
modificada para só exibir as pontuações
que tenham sido aprovadas - sem essa
modificação, todas as outras seriam inúteis.
você está aqui ► 3 2 1
adicionando uma coluna APPROVED para a tabela guitarwars
Abra espaço para aprovações com A ltER
Para adicionar a nova coluna approved à tabela guitarwars, é preciso
usar uma vez a instrução ALTER TABLE, que é um comando SQL
que já vimos anteriormente. 0 tipo de dados &QOL do M/SQL «
ALTER TABLE guitarwars U
m «Vo ya
r
aTIKVINT, yortwt»
ADD COLUMN a p p r o v e d T IN Y IN T «otê foAc usar »>» dos dois-
A nova coluna approved é do tipo TINYINT, e usa 0 para indicar
uma pontuação não aprovada ou 1 para indicar uma pontuação
aprovada. Assim, todos os novos registros devem começar tendo
o valor 0, para indicar que são inicialmente não aprovados. r- m
Espere um minuto. NSo sei se você pode
simplesmente ir adicionando uma coluna
ao banco de dados sem modificar o script
Adicionar Pontuaçao - ele não terá de
inserir dados à nova coluna, com INSERT?
adicionar uma
coluna approved à
tabela.
É verdade, uma nova coluna implica um novo valor na
consulta INSERT do script Adicionar Pontuação.
E importante não perder de vista o fato de que uma aplicação PHP é um
cuidadoso arranjo de diversas partes e pedaços: um banco de dados que
consiste de tabelas com linhas e colunas, código PHP, código HTML, e
geralmente código CSS. Nem sempre fica imediatamente claro que, para
modificar uma parte, é preciso modificar outra. Adicionar a nova coluna
approved na tabela guitarwars também exige a modificação da consulta
INSERT no script Adicionar Pontuação:
Todas as linhas das novas
INSERT INTO guitarwars
VALUES (0, NOW(
) , 1$name
pon-luaçoes -tem approved ~
deímida t<mo 0 — nao aprovadas. ^
Uürtili f i l ! * * ' S í i i i i S B l i f e l i i S i i l
f f i i l i l l i l i i i M I I I 1 Jíitoi' of
30 2008-05-02 14:02:54 Ethel Hecke! 500000 ethelsscore.gif 0
31 2008-05-02 20:32:54 Biff Jeck 314340 biffsscore.gif 0
‘ 32 -ÉU08-05-02 20:36:38 Pez Law 322710 pezsscore.gif
’$score1,'$screenshot', |
j
p
guando uma nova
linha é adicionada, a
sua coluna approved
t deíinida Como
O, para <ue ela,
de início, seja nao
aprovada-
segurança para a sua aplicação
Aponte seu lápis
<?php
O script Aprovar Pontuação tem estrutura semelhante ao Remover
Pontuação, exceto pelo fato de que a sua tarefa é aprovar pontuações.
Complete o código do script Aprovar Pontuação abaixo, certificando-se de
fazer a página segura, e de só aprovar a pontuação apropriada, com base
em dados enviados através de uma URL.
?>
<?php
require_once{'appvars.php')
;
.
require_once{'connectvars.php');
if (isset{$ POST [
'submit ’]
.
)
■
) {
if { .) {
// Conecta-se ao banco de dados
$dbc = mysqli_connect(DB_HOST, DBJJSER, DB_PASSWORD, DB_NAME);
// Aprova a pontuação, definindo a coluna approved do banco de dados
$query - "UPDATE guitarwars SET ";
mysqli__query (
$dbc, $query) ;
mysqli_close($dbc);
// Confirma o êxito com o usuário
echo
else {
echo
echo 1
<p><a href: ">&lt;&lt; Voltar à página Admin</a></
?>
v o c ê está aqui ► 3 2 3
o script para aprovar pontuação completo
r~ %Aponteseulápis
Solupão
<?php
?>
O script Aprovar Pontuação tem estrutura semelhante ao Remover
Pontuação, exceto pelo fato de que a sua tarefa é aprovar pontuações.
Complete o código do script Aprovar Pontuação abaixo, certificando-
se de fazer a página segura, e de só aprovar a pontuação apropriada,
com base em dados enviados através de uma URL
n ,, . . Tudo Ottue vod€ predisa -kzor para garantir a
reT * , ^ !í!.k ‘ k," a . f : [ ).............. da A f" * * í « e u - »
sdrip-t Á^toriz^o mas isso deve ser a primeira toisa no
sdrip-fc, uma vez. *ue o prodesso defende dos dabedalhos
<?php
require_once('appvars.php');
require_once('connectvars.
php'
)
X Crie um script
Aprovar Pontuação
para realizar a tarefa
de aprovar uma nova
pontuação (definir
a coluna ai
como!
) {
A IP predisa
ser veri-Pidada,
para <ue a
aprovadao
seja -feiia-
i f ( i s s e t ($_POST['s u b m i t'] )) {
i f (
/ / C on ecta-se ao banco de dados
$dbc = mysqli_connect(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);
/ / Aprova a pontu ação , d e fin in d o a coluna approved do banco de d a d /s
$query = "UPDATE guitarw ars SET .77. .*í4
m y sq lí_query($dbc, Çquery) ,• af?m<£a .
m y sq li_ c lo se ($dbc) ; domo I aprova a pontuarão. usuirio, mosfcrândo a
/ / Confirm a o ê x ito com o u su á rio pontuadao aprovada e
( V o
echo l<pi*A pontuação de *• fsdore ■' para * • fname . ‘ íoi aprovada dom sudesso/j
}
e ls e {
echo *<p dlass-"erv-or”>Pesdulpe, houve um problema para aprovar a pon-fcuadão.«c/p>;
} 'tT £ i^porbahie iníormar ao usuário guando umã
} pott-tuaeao não puder ser aprovada, de Wma
semeibaW a tomo os ouiros sdripts do guitar Wars
relatam os erros.
echo '< p x a h ref= " âdmin.php "> & lt;& lt; V o lta r à p ág in a Admin</a></
p> 1; ............. V"............
Forneda um link de volta à
?> pagina Admih, para -fadilitar a
navegação.
itfb existem
Yergimtas idiotas
1 • Por que não é necessário informar o nome do I • Parece pouco informativo usar 0 e 1 na coluna
arquivo gráfico para se aprovar uma pontuação? approved. Não há outras maneiras de se representar
essa informação?
J  ’ Porque o processo de se aprovar uma pontuação
só exige as informações necessárias para se achar i y - Sim. Otipodedados ENUMdoMySQL, quesignifica
uma determinada linha na tabela, e então aprová- "enumerado", lhepermitecriarumacolunacomumalista
la. Isso significa que você só precisa informar o restritadepossíveisvalores.Assim, emvezdeadicionara
estritamente necessário para achar a linha em questão, colunaapprovedcomoumTINYINTquedeveráterovalor 0
Adata, o nome e a pontuação são suficientes para ou 1, vocêpoderiaadicioná-lacomoumENUMquepudesse
se especificar uma determinada linha e definir a sua terapenasosvalores'yes' e'no', destaforma:
coluna approved como 1.
ALTER TABLE guitarwars
ADD COLUMN approved ENUM( 1y e s ' ,
1n o ' )
.Aponte seu lápis-----------------------------------------------------
Os dados das pontuações usados para aprová-las, no script Aprovar
Pontuação, são passados através de links "Aprovar" que são gerados no script
Admin. Complete o código do script Admin para que ele gere esses links.
// Faz um loop através do array contendo os dados das pontuações,
formatando-os como HTML
echo 1
<table>';
echo '
<tr><th>Name</th><th>Date</thXth>Score</th><th>Action</thx/tr> ';
while (Srow = mysqli_fetch_array($data)) {
// Exibe os dados das pontuações
echo '<tr class="scorerow"xtdxstrong>' . $row ['name'] . '
</strongx/td>1;
echo '<td>' . $row['date'] . '</td>';
echo '<td>' . $row[1score1] . 1
</td>';
echo '
<td><a href="removescore.php?id=' . $row['id'] . '&amp;date=1 .
$row[’date'
] .
'&amp;name-' . $row[’
name'] . 1&amp;score=I . $row['score'] .
'&amp;screenshot=1 . $row['screenshot1] . 1">Remove</a>1;
if (............................. ) {
echo
segurança para a sua aplicação
}
echo '
</td></tr> '
; ^ as r*o
} apv-ovadas t deve» íc r w*
echo '</table>'; Af'roV3r -
você está aqui ► 325
gerando links de aprovação
%^ponte seu lápis
Solupão
Os dados das pontuações usados para aprová-las, no script Aprovar Pontuação,
são passados através de links "Aprovar" que são gerados no script Admin.
Complete o código do script Admin para que ele gere esses links.
// Faz um loop através do array contendo os dados das pontuações,
formatando-os como HTML;
echo 1<table>';
echo '<trxth>Name</thxth>Date</thXth>Score</thxth>Action</thx/tr>'
;
while ($row = mysqli_fetch_array($data)) {
// Exibe os dados das pontuações
echo '<tr class="scorerow"XtdXstrong>' . $row ['name'] . '</strongx/td>'
;
echo '<td>' . $row['date'] . '
</td>';
echo '< td > ' . $row [ Ts c o re ’ ] . '< /td > '; l/eriíída se
echo '<td><a href="removescore.php?id=' .$row['id'] . â pojvtuadao
imp;date=' . $row ['date'] . Csiâ^apvovadé
t , » ’ * r i ■ n » r- . í- r T , n 0W n
&amp; name= ' . $row['name'] . *&amp; score= ' . $row ['score ’] .
.
dc jerar o
'&amp; screenshot=' . $row ['screenshot1 ].
'">Remove</a> '
; link aprovar
if { fro>«rappy;9ycd,
J ^ " “ "
"
echo 1/ <a hreí— "appv-ovesdore.php?id— J.frowfidO *l
&a»pjd^te— -fVovjC'date’
3 .
echo ,</table>';
echo '</td></tr>'
; Çcra o link de
modo -tal y c a d > j d a U
o nomC) a powt^a^a® * 0 w
nowe do arquivo y & t o sao
passados «a URI—
Admin para incluir
um link "Aprovar"1
para as pontuações
que ainda tenham
de ser aprovadas.
segurança para a sua aplicação
Pontuações não aprovadas não são dignas
Agora,jã temos toda a infraestrutura necessária para o recurso de
moderação na aplicação Guitar Wars. Só falta o último passo, que
é alterar a página principal de modo que ela mostre apenas as
pontuações aprovadas. Para isso, teremos de ajustar a consulta SQL
SELECT de modo tal que ela só obtenha os registros cuja coluna
approved esteja definida como 1 (aprovada). Isso é feito por meio
de uma instrução WHERE.
SELECT * FROM guitaryars
ORDER BY score DESC, date ASC
A adição da instrução WHERE a esta consulta elimina quaisquer
pontuações que não tenham sido aprovadas, o que inclui todas as
novas inserções. Isso dá ao moderador a chance de analisá-las e
decidir se elas devem ser removidas ou liberadas (aprovadas) para
visualização pública.
Use WHERE
pcflTct s e le c io n a i-
llntas com
base n9
V
aioxJe um
a
determinada
c o lu n a .
£< 3 toluna amoved
estwcv dfrÇwwfô to»
diíevente de I» a
■'i ^ ** í
não setra
e*ibidâ-
..................’....... 1
28 2008-05-01 21:14:56 Leddy Gee 308710 leddysscore.gif
29 2008-05-01 21:15:17 T-Bone Taylor 354190 tbonesscore.gif 1 J
30 2008-05-02 14:02:54 Etheí Heckel 500000 etheisscore.gif
m o m
31 2008-05-02 20:32:54 Biff Jeck 314340 biffsscore.gif 1
32 2008-05-02 20:36:38 Pez Law 322710 pezsscore.gif
Agora, somente
as pontuações
aprovadas
apatetem na
pagína principal
(inde*.php)-
Modifique a consulta da
página principal para
só exibir pontuações
aprova«
você está aqui ► 327
- — .Tejst Drive,
test drive approvescore.php
Crie o script Aprovar e ajuste o restante da aplicação Guitar Wars
para usá-lo.
Usando alguma ferramenta MySQJL, emita a consulta ALTER para adicionar a nova
coluna approved à tabela guitarwars. Em seguida, modifique a consulta INSERT do
script addscore.php para inserir um 0, na coluna approved, para novas linhas de dados.
Agora, crie um arquivo de texto chamado aprovescore.php e digite nele o código
para o script Aprovar Pontuação. Em seguida, modifique o script admin.php de modo
que ele inclua um link "Aprovar" para pontuações que ainda precisem ser aprovadas.
Finalmente, modifique a consulta SELECT de index.php para que ela mostre apenas as
pontuações aprovadas.
Envie todos os scripts para o seu servidor, e abra a página principal do Guitar Wars no
seu navegador. Tome nota de quais pontuações estão visíveis, e depois abra a página
Admin. Clique em um dos links "Aprovar" e realize a operação de aprovar o registro.
Depois, volte à página principal para ver se esse registro agora está aparecendo.
GuitarWars-HighScoresAdministration
Bdow is a Ksio f all GniiaiWar» hS^i seoses. Use asís|»ge ta scores s
Ethel Hecfcel
Jacob Scoreherson
T-Booe Tajtor
P
e
g
L
a
w
BUTJeck
I
.
e
d
d
yG
e
e
BeBaCbery
J
e
a
nP
a
n
]J
o
n
e
s
I_af7Sinn
Paco Jastorras
N
V
r
i
l
J
o
h
a
n
s
s
o
n
Kenny L»vte
D
jrtt Son __
_
2008-05-02 14:0234 500000
20084)5-01 20:36:45 389740 R e tire
2008-05-01 21:15:1-? 354190
2008-05-02 20:3638 322710,.,.,,,-:.-,
200S-05-02 2032:54 314340 Êfam vS
20084)5-01 21:1436 308710 R em vg
2008-05*0! 20-36507 282470
20034)5-01 20:3853 243260 f e r o t
2008-05-01 20:37:40186530 gum™»
20084)5-01 20:3723 127(650
20OS-O54)i 20:3?#2 98430
30084)5-01 2038:00 64930
V
0s «ovos i'mks
”Aprovar" da p%‘*a
Adwin £ome£ew>
atcsso a patina
Aprovar Pon-bua^ao,
ohdt os reystros
pode» ser aprovados
indi dual»eR"te■
segurança para a sua aplicação
Apos a operaçac -fcev sido
Conduídâ dorr SUÍCSSO, urr>
a
de £o«íiVn>3Çao e
exibida.
Um simples íovmirflário
requer coníiymaçao
a^ies de 'reaUewíe
aprovar o re^istvo.
h ^edewi—
apvovada ,
pohiuacao aaova apareie
pagina principal do
quiiav IV
ô
v
-s.
v o c ê está aqui ► 329
ethel marca de novo
0 hack de um milhão de pontos
A versão moderada do Guitar Wars representa uma melhoria significativa na segurança,
mas está longe de ser completamente à prova de balas. Parece que a nossa infiltradora
conseguiu achar outra fraqueza no sistema, e de alguma forma está conseguindo fazer as
suas pontuações passarem pelo moderador. Ethel precisa ser detida, permanentemente,
para que possamos restaurar a confiança no universo do Guitar Wars.
Bsie t
C*atarwOrte
o -tipo de
foh-tuaçao <
^u
e
o nnoderâdor
deve impedir...
e no enia>vto,
3*ui esta ela/
segurança para a sua aplicação
Tudo em moderação...?
Embora o moderador saiba, sem sombra de dúvida, que ele nao
aprovou a pontuação submetida por Ethel, esta claro que essa
pontuação chegou ao banco, com a coluna approved de^n'd
como 1. Nós sabemos que o script Adicionar Pontuaçao defm
a coluna approved como 0 para novas pontuaçoes, porque
acabamos de modificar a consulta INSERT desse scnpt. Algo
simplesmente não está certo!
Como é
possível? Eu sei que não
aprovei essa pontuação. Um
milhão de pontos!?
O
0 moderador j}°
3*vtar Wav* «ao
dorvsc^c G rà M cr
o <«e afconteieu.
»d ia— lllll[}ipiSiliI. score S u m
21 2008-05-01 20:36:07 Belita Chevy 282470 belitasscore.gif 1
22 2008-05-01 20:36:45 Jacob Scorcherson 389740 jacobsscore.gif 1
23 2008-05-01 20:37:02 Nevil Johansson 98430 nevilsscore.gif 1
24 2008-05-01 20:37:23 Paco Jastorius 127650 pacosscore.gif 1
25 2008-05-01 20:37:40 Phiz Lairston 186580 phizsscore.gif 1
26 2008-05-01 20:38:00 Kenny Lavitz 64930 kennysscore.gif 1
27 2008-05-01 20:38:23 Jean Paul Jones 243260 jeanpaulsscore.gif 1
28 2008-05-01 21:14:56 Leddy Gee 308710 leddysscore.gif I 1
29 2008-05-01 21:15:17 T-Bone Taylor 354190 tbonesscore.gif ! 1
31 2008-05-02 20:32:54 Biff Jeck 314340 biffsscore.gif
1 1
32 2008-05-02 20:36:38 Pez Law 322710 pezsscore.gif
r 33 2008-05-05 14:58:59 Ethel Heckel 1000000 ethelsscore2.gif
1 J
c
9 K R W _____________________________
C É R E S R O
Como você acha que o post falso de Ethel conseguiu passar
pelo moderador?
füsfca poM-tuaçao
não ío'i aprovada
<^to moderadorj
e m
o ewtairt»»
a sua tolw«a
approved esta
deíinida tomo I»
o «ue resulta em
ela ser e*A>»da-
você está aqui ► 331
tente o golpe da Ethel
E X E R C fT A W O
« C É R E B R O
E th e l H e cke l
Ocorre que o hack de um milhão de pontos de Ethel não teve nada a
ver com o formulário Aprovar Pontuação. Foi descoberto que a invasão
dela se baseou apenas no formulário Adicionar Pontuação. Segue
abaixo os dados exatos que Ethel digitou no formulário Adicionar
Pontuação; digite os mesmos dados no seu próprio formulário e
adicione o registro. O que você acha que está acontecendo?
Não sc es^ueí-â do
espaço depois de — .
d<ü-
1000000 ' e t h e l s s c o r e 2 . g i f ' , 1 )
Este pode ser ^uai^uer dr^uivo
yrS-Çito éflF ou JPE$ tem menos
de 1 Z W . ethelsscore2.gif
segurança para a sua apficação
Conto exatamente ela fez isso?
Para entender o que está acontecendo neste inteligente tipo de
ataque a formulários, vamos rastrear o fluxo dos dados enquanto
eles viajam através do script Adicionar Pontuação.
Êihel digitou â
sua poniuâdao-..
C mais um
morrte de doisas
estranhas/
$score = $ POST['score'];
0 indomum donteudo
do d3mpo Pon-tua^ae do
-formulário e armazenado
na variável fsdore, o <uâl
vai parar dire-tamen-be na
donsul-ta INSERT.
'$screenshot', 0)
O campo Pontuação espera receber apenas um valor
numérico, como 1000000, mas em vez disso ele tem
diversos valores colocados entre aspas simples, separados
por vírgulas e terminando com um estranho hífen duplo.
Muito estranho.
Esses estranhos dados são primeiramente armazenados na
variável $score, após o que são incorporados na consulta
INSERT. Isso resulta apenas em uma pontuação inválida,
certo? Ou tem algo mais sinistro acontecendo aqui?
Aponte seu lápis
Usando os dados exatos que foram mostrados na página anterior,
escreva aqui a consulta SQL inteira do ataque de um milhão de
pontos. Certifique-se de substituir as variáveis da consulta pelos
dados propriamente ditos. Escreva também o que você acha que
está acontecendo.
você está aqui ► 333
como uma injeção de SQL funciona
tpowteseu lápis--------------- ----------------- -----------—
Ç n l l i r ã n Usando os dados exatos que foram mostrados na página anterior,
^ escreva aqui a consulta SQL inteira do ataque de um milhão de
pontos. Certifique-se de substituir as variáveis da consulta pelos
dados propriamente ditos. Escreva também o que você acha que
está acontecendo.
IffJQ. w b r & r * ............................... ..............................................................................
|LUE£ (O, MWO, 'E-thel ttefckel', 'lOOOÔÔO1
, 'eihelss£oreZ<ji-(-lÍ^—  'e-thelsstore2-<yí O)
Uma vez. <
^u
e a eo!u*a
approved t a uiíima r>
a
estrutura do bando de dados
De alguma -forma, í Que consul+a estranha. —_
ela está s
e
s
ndo íorçada a ter
Éthel t *iou a sua ) > ^quivo gráfico aparece  um valor de I... aprovado/
própria versão da ( e n3° Sei 0 ^ue si9nifica • ) ° 0
ícm uIU 3 ^ual ^ essa consulta funciona?
tiíâ substituindo
â òonsulta origina).
Enganando o MySQl com comentários
O verdadeiro culpado pelo ataque de um milhão de pontos de Ethel,
por incrível que pareça, são os comentários SQL. O hífen duplo
(— ) é usado, em SQL, para desativar o restante de uma linha
de código SQL, transformando-o em um comentário. E preciso
haver um espaço depois do hífen duplo para que ele funcione
(— ), mas tudo o que vier depois do espaço é ignorado. Agora,
dê outra olhada na consulta de Ethel, levando em conta esse novo
conhecimento.
INSERT INTO guitarwars
VALUES (
0
, NOW()
, 'Ethel Heckel', 11000000'
Faz mais sentido agora? Na prática, o comentário apagou o restante
do código SQL, para que ele não gerasse um erro, permitindo que
a versão da consulta criada por Ethel pudesse chegar ao sistema sem
percalços. O resultado final é uma pontuação instantaneamente
aprovada, a qual o moderador nunca teve a chance de analisar.
Ô dome*iario — íaz. dom
«ue o restante da linha de
tcdo.o SQL seja ignorado.
/
'ethelsscore2.gif1, 1) —
£thel chamou o
sistema, íazendo-o
aprovar a sua
potfUaça«
segurança para a sua aplicação
0 formulárioAddScorerecebeuumainjeçãodeSQL
O ataque de Ethel é conhecido como injeção de SQL, e envolve um
truque extremamente sorrateiro, no quai os dados do formulário
são usados para se modificar a operação fundamental de uma
consulta. Assim, em vez de o campo do formulário apenas fornecer
uma informação, como um nome ou uma pontuação, ele altera a
própria consulta SQL subjacente. No caso do Guitar Wars, a injeção
de SQL de Ethel usou o campo Pontuação como um meio de não
somente fornecer a pontuação, mas também o nome do arquivo
gráfico, o valor para approved e um comentário no final, para evitar
que o código SQL original gerasse um erro.
Os octnipps do
f o r a u la r í p s § 9
um p9nt9 feac<
na segurança
das aplicações
W e b , p Ç fíjfu e
eles petmitem
<jue Ps usuátíps
lusfraifl
INSERT INTO
VALUES (0 , NOW() 1$name ’ 1$screenshot'
não exîstem
?eïgimt£ts idiotas
l - Existem outros tipos de comentários em SQL,
fora --?
K : Sim. Outra variante de comentário envolve o uso
de # emvez de mas tem obviamente o mesmo efeito
de anular qualquer código SQLaté o final da tinhaque
contém o comentário. 0 SQLtambém oferece suporte
a comentários multilinhas, semelhantes àqueles do
PHP no sentido que você coloca o código comentado
(desativado) entre /* e */.
• 0 ataque de injeção SQL de Ethel ainda teria
funcionado se a coluna approved não fosse a última
da tabela?
Não, e essa é uma questão realmente importante.
Aconsulta INSERTque foi usadadependeda ordem
padrão das colunas natabela. Golocar 1nofinal da
consulta funcionou por acaso, porque approvedera a
última coluna, aparecendo imediatamente depois da
coluna screenshot.
você está aqui ► 335
prevenindo injeção de sqi
Proteja seus dados contra injepões de SQL
A fraqueza que as injeções de SQL realmente exploram reside nos campos de formulários
que não são validados para impedir a inserção de caracteres perigosos. "Caracteres
perigosos" são todos aqueles que tenham o potencial de modificar a natureza de uma
consulta SQL, como vírgulas, aspas ou caracteres de comentários como — . Até mesmo
espaços ao final de algum dado podem se revelar perigosos. É fácil eliminar espaços
com a função interna do PHP trim() - basta passar todos os dados de formulários
através da função trim() antes de usá-los em uma consulta SQL.
$name = |
j
|
|
i
|
|
|
($_POST ['name ']);
$score = i($ POST['score']
) ;
$screenshot = |||||||j($_FILES ['screenshot'1]['name']);
Mas os espaços não são o único problema. Ainda existem as
vírgulas, aspas, caracteres de comentários e assim por diante.
Portanto, além de retirar os espaços em branco, nós também
precisamos de uma forma de encontrar e neutralizar
outros caracteres problemáticos. O PHP nos auxilia com
outra função interna, mysqli„real_escape_string(), a qual
faz escape de caracteres potencialmente perigosos, para
que eles não possam afetar o modo como uma consulta
se executa. Esses caracteres ainda poderão aparecer como
dados em campos do formulário, eles só não serão capazes
de interferir nas consultas.
Juntas, as funções trim() e mysqli_real_escape_string()
fornecem uma sólida linha de defesa contra injeções de SQL.
A -PunÇao -fcW
iwO sc
livra de ^ais^ucv
. / espaços <^e apareçam
antes <
x
» depois dos
dados deste •foriwulario.
As Injeções SQL
podem ser eVitadas
p ro c e s s c in d o -s e
d e Y id c im e n te os
dados de Çprmuláríps.
A íunçao n*ys^r«_jreaS__esòape__
stringO tonverte daratteres
perigosos cm um -formato tom
estape, o ^uaS «ao e dapaz.
de aíetar as donsultas £$L-
$name =
$score =4
$screenshot =
['name']));
Processar os três campos do formulário Guitar Wars com
as funções trim() e mysqli_real_escape_string() reduz em
muito as chances de um outro ataque de injeção SQL. Mas
elas não são o suficiente - talvez haja uma forma de tomar
a própria consulta menos vulnerável...
($dbc, trim(
$_POST['name 1]));
{$dbc, trim($_POST['score']));
|â|($dbc, trim ($ FILES [
'screenshot']
mys^lijreâLesdapej^ringO
t donsiderada uma -função
‘de bandos de dados, e é por
sso eue ela e*ige <ue vode
lhe íornedà uma variável de
done*3o a bando de dados, da
mesma -forma <*e aquela usada
ao se submeter donsultas.
segurança para a sua aplicação
Um INSERT mais seguro (com parâmetros)
Uma consulta
Í]SÍ$EflT~p9d e se t
e s c ríta d e fo rm a
a especiíicar
exatamente
Valetes Vãp pava
<jua!s colunas.
Além da fraqueza dos campos do formulário, a injeção de
SQL de Ethel também explorou o fato de a coluna approved
vir depois da coluna screenshot na estrutura do banco de
dados. Foi assim que ela conseguiu hackear o sistema apenas
adicionando 1 ao final de INSERT, e fazendo-o ser colocado
na coluna approved. O problema é que a consulta INSERT é
estruturada de forma tal que ela precisa inserir dados em todas
as colunas, o que aumenta desnecessariamente o risco.
0 ideal e <ue «ao prensássemos deímir
as toiunas id e approved, uma vez. ^ue
elas pode» -fitar tom os valores padrões
INSERT Ií^pO guitarwars
VALUES (0, NOW(), 1?name'
, '$score', '$screenshot
Quando dados são inseridos em uma tabela desta forma, a ordem deles precisa bater
com a ordem das colunas na estrutura da tabela. Assim, a quinta informação será
colocada na coluna screenshot porque esta é a quinta coluna da tabela. Mas na verdade
não é necessário inserir explicitamente as colunas id ou approved, uma vez que id é
autoincrementada e approved deve sempre ser 0. Uma abordagem melhor é inserir apenas
os dados explicitamente requeridos em uma nova pontuação. As colunas id e approved
poderão então usar os padrões de AUTO_INCREMENT e 0, respectivamente.
Nós precisamos de uma consulta INSERT reestruturada, que espere uma lista de colunas
antes da lista de dados, com um pareamento exato. Isso elimina o risco de a coluna
approved ser definida - ela não faz mais parte da consulta. Se esse tipo de consulta parece
familiar, é porque você a usou diversas vezes em outros exemplos. , . . .
r ^ r Nada pode ser iwsendo
na doluna approved,
porque ela *âo esta
istada domo parie da
INSERT INTO guitarwars
VALUES {NOW(), '$name'
A toluna id pode ser dei*ada
de -fora, uma vez. «
^ue ela se
au-koindv-emen-ta de <ua!<uer íorw>3-
Esta versão da consulta INSERT informa
exatamente em qual coluna deve ser colocada
qual informação, permitindo que você insira
dados sem ter de se preocupar com a estrutura
subjacente da tabela. Na verdade, usar esse tipo
de INSERT é considerado como um melhor
estilo de programação, porque os dados são
inseridos exatamente onde você quiser, em vez de
o destino deles ser ditado pelo layout da tabela.
você está aqui ► 337
o commando DEFAULT
Não só é possível, como é uma ótima ideia especificar
valores DEFAULT para as colunas sempre que possível.
O comando SQL DEFAULT é o que lhe permite especificar um
valor padrão para uma coluna. Se a coluna dver um valor padrão,
você não precisa defini-la em consultas INSERT, e pode ter a
certeza de que ela automaticamente adotará o valor padrão. Isso
é perfeito para a coluna approved da tabela guitarwars. Agora nós
só precisamos modificar a tabela mais uma vez, para definir o valor
padrão de approved como 0 (não aprovado).
Uma vez. a doluna approved ja enisle hesta
instrudao ALTER TjABL-E, nos te»wos de war
MODIFYCOLUMN C0LUMH-
ALTER TABLE guitarwars
MODIFY COLUMN approved TINYINT
Com a coluna approved agora alterada para adotar um valor padrão,
a nova e melhorada consulta INSERT do script Adicionar Pontuação
pode inserir pontuações sem sequer mencionar a coluna approved.
Isto é um bom design, uma vez que não há necessidade de inserir
explicitamente um valor que pode ser padronizado, e ainda
adiciona uma pequena dose de segurança, ao não expor a coluna
approved a potenciais ataques.
DEFAULT a appvo^d
ser assinalada a b a te m e n t«
to menos «ue u» I.NStKl
cs?etiíi*V*€ de outra W *
to n 0 , a menos °*e
Vode predisa espedi-fidar o tipo
da doîuna —garanta ^ue seja
o mísmo da /"vez. <^*e âdidionou
â dolunâ-
segurança para a sua aplicação
A validação de formulários nunca é inteligente demais
U m último passo para se minimizar o risco de ataques de injeção SQL envolve a validação
do formulário no script Adicionar Pontuação. Antes de verificar se o tipo ou o tamanho
do arquivo gráfico estão dentro dos limites estabelecidos pela aplicação, os três campos do
formulário são verificados para garantir que não estejam vazios.
if (!empty ($name) &
& ||^ |^ ||g |($ sc o re ) && !em p ty ($ screen sh o t) ) {
}
Não há nada de errado com o código atual, mas o processo de
garantir a segurança de uma aplicação frequentemente exige
que você dê um passo além do habitual. Uma vez que o campo
Pontuação espera um número, faz sentido verificar não apenas
se existe um valor, mas se o valor existente é numérico. A função
PHP is_numeric() faz exatamente isso, retomando true se o valor
passado a ela for um número ou false caso contrário. Ela está
sempre fazendo os trabalhos triviais, como por exemplo, verificar
se foi recebido um número quando um número era o que você
esperava, que no fim das contas vão tomar a sua aplicação tão
segura quanto possível.
£$tãi dcdlara^ao
•í vsn-Tidâ se
iodos os dai*p©s do
■formulário esiào
preenchidos.
is numeric(465730)
^ is_numeric('one million!
Vcrdadeirol f
is numeric(0)
Fals
ftcício
Verdadeiro ou -falso,
dependendo de «
usuário di^iW ou nâo
um numero no £3mpo
Pontuação-
C
is_numeric($score)
S e lflp le c[ue pPssíV el, eX ljA c(u e p s dadPS
d e Ç ptrnuláíiP e ste ja m n o ÍPVmatP ^U e V pce
e sp e c iífc p u .
Reescreva a declaração ifde validaçãodo formulárioAdicionar Pontuação, de modo
que ela use afunção is_numeric() para permitirapenas pontuações numéricas.
você está aqui ► 3 3 9
test drive o novo addscore.php
^ Reescreva a declaração if de validação do formulário Adicionar Pontuação,
^ de modo que ela use a função is_numeric() para permitir apenas pontuações
IO numéricas.
Aprimore o tratam ento dos dados do formulário no script Adicionar
Pontuação.
Ajuste a atribuição de dados do formulário às variáveis, no script addscore.php, de modo
que as funções trim() e mysqh_real_escape_string() sejam usados para limpar os dados
do formulário. Depois, modifique a consulta INSERT para que ela especifique tanto os
nomes das colunas quanto os valores, eliminando-se a necessidade de fornecer valores
para as colunas id e approved. Modifique também a declaração if que valida os campos do
formulário para que ela verifique se a pontuação é numérica.
Finalmente, use uma ferramenta MySQL para rodar a consulta ALTER que estabelece o
padrão de 0 para a coluna approved.
Envie o novo script Adicionar Pontuação para o seu servidor, navegue até ele, e depois
tente realizar o mesmo ataque de injeção de SQL novamente.
}
T te S T O r i v e
é da*-o <«e esta
mensagem de erro
poderia ser um pouio m3is
espetí-fita» m3s ela atende
às nossas necessidades
sem prefcisârmos adií-ionar
muito mais programaçao
ao sdript--
um topido t^ue vai muito alem da
segurança de bandos de dados. 0
Capítulo lô revisitará a validação
tom muito mâis detalhes...
TTvaMa^ao de -formulários e
segurança para a sua aplicação
Cessar fogo!
Parece que a determinação de Ethel de interferir nas pontuações do
Guitar Wars Finalmente foi quebrada, graças às melhorias que tornaram
a aplicação imune a injeções de SQL. O verdadeiro campeão do Guitar
Wars respondeu inserindo um novo recorde.
GaitarWars-HighScores
Welcome.GuitarWamor. do you ba»ewiwi it takesto crack the ingb scarelist? If so,just addvo aroyn sPMS.
465730
w JacobScotchefson
Date: 200S-G5-G5 23;28i'7
Top Score: 465730
Gui t a r
Feliz. pelas pontua^oes
âgora estarem protegidas
£©«tra tateríerendias
externas, Jatob «*via u»
«ovo reíorde ^ue será
di-Pfeii de bater.
Oh( nao!
Venceram-me novamente.
Talvez seja hora de aprender
a tocar guitarra virtual.
tom o •fato de
elhor sejuntar a eles
£
^u
e tontmuar perdendo
para eles, Ethel pertebe <ue
talvez, seja hora de se W *ar
uma éjuitar Warrior.
você está aqui ► 341
CAPÍTULO
6
caixa de ferramentas php e mysql
Sua Caixa de Ferramentas FHF£ MySftl
&
fflH H JP Além de aprimorar a aplicação
de recordes do Gultar Wars, você
adquiriu várias novas ferramentas e
técnicas. Vamos rever as mais importantes.
Sfrß i tnbe Bisa booa
oeöeoude e n $ e ejed eöuejnßos
criando aplicações web personalizadas
7 Ctíífficlo Aplicações Web peís°ilcllizílclcls
% ^
Lembra de Mim?
%
Ninguém gosta de ser esquecido, especialmente usuários de
aplicações web. Se a aplicação tiver que trabalhar a noção de “comunidade”,
ou seja, se for planejado que os usuários interajam com a aplicação de uma forma
pessoal, então ela terá de se lembrar dos usuários. Você detestaria ter que se apresentar
novamente à sua família a cada vez que entrasse em casa. Não. precisa fazê-lo porque
seus parentes possuem uma coisa maravilhosa chamada memória. Mas aplicações web
não se lembram das pessoas automaticamente - é preciso que um desenvolvedor web
esperto use as ferramentas disponíveis (PHP e MySQL, talvez?) para criar aplicações
web personalizadas que realmente sejam capazes de se lembrar dos usuários.
este é um novo capítulo ► 345
uma boa incom patibilidade é d ifícil de encontrar
Pizem queos opostos seatraem
É uma história antiga: garoto conhece garota, garota acha que o garoto
é completamente insensível, garoto acha que a garota é maluca, mas no
fim das contas as diferenças se transformam na atração, e eles acabam
vivendo felizes para sempre. Essa história é a inspiração do novo e
inovador site de encontros mis-match.net. O Mismatch - "Desencontro"-
usa a teoria de que "os opostos se atraem" para combinar encontros
entre as pessoas com base nas suas diferenças.
O problema é que o Mismatch ainda precisa de um desenvolvedor
web para terminar de construir o sistema. É aí que você entra.
Milhões de corações solitários estão esperando ansiosamente que
você termine a aplicação... não os decepcione!
Sidney adora
reality shows,
yo^a e sushi, e
espevâ donse^uir
um desendoivbro
Johan Nettles
Male (Masculino)
1981-11-03
Athens, GA
As aplicações web pessoais
dependem fundamentalmente
das informações dos usuários,
portanto estes deverão ter
a capacidade de acessar a
aplicação em um nível pessoal.
- ►
Sidney Kelsow
Female (feminino)
1984-07-19
Tempe, AZ
Joha« adora luta livre
pressionai, levantamento
de pesos e Spam, e tem
interesse e» <ual<uer uma
<ue responda ao seu âhundio.
Os usuários do Mismatch precisam ser capazes de interagir com o
site em um nível pessoal. Isso significa, entre outras coisas, que eles
precisarão de perfis pessoais, nos quais inserirão informações sobre
si mesmos, as quais poderão compartilhar com outros usuários do
Mismatch: sexo, data de nascimento, localização, etc.
criando aplicações web personalizadas
0 negócio do Mismatch são os dados pessoais
Portanto, o negócio do Mismatch é estabelecer conexões através de
dados pessoais. Essas conexões devem ocorrer dentro de uma „ cada
um dos quais devendo ser capaz de interagir com o site e gerenciar
os seus próprios dados pessoais. Uma tabela chamada mismatch_user
será usada para guardar as informações dos usuários do Mismatch.
Este e o bando de
dados do M'smâtdh-
Dentvo do bando
de dados, a
tabeia mis«.atdh__
usev armazma
os usuários t as
$uâs iivPoJrmaÇoes
pessoais.
As páginas
Editatr c Vev
Peir-Çil pvedisam
sabev <^uai perfii
devem adessav.
J
Cada linha da
tabela mismafcdh__
user dontém dados
pessoaismeímentes
a umusuatrio-
Sidney Kelsow
Female(Feminino)
1984-07-19
Tempe, AZ
Além de visualizar o perfil, os usuários
do Mismatch podem editá-lo usando
a página Editar Perfil. Mas há um
problema: a aplicação necessita saber
qual perfil ela deve editar. A página
precisa de algum modo de saber qual é o
usuário que a está acessando.
WCÉRÉSRO
Como o Mismatch poderia
personalizar a página
Editar Perfil para cada
usuário do sistema?
você está aqui ► 3 4 7
adicionando log-ins para mismatch
0 Mismatch precisa de logins para os usuários
A solução para o problema de acesso aos dados pessoais no
Mismatch envolve o uso de logins, o que significa que os
usuários precisam de um meio de fazer login na aplicação. Isso
dá ao Mismatch a capacidade de fornecer acesso a informações
personalizadas para cada usuário. Por exemplo, o usuário logado
só poderia editar o seu próprio perfil, mas poderia também ter
acesso de visualização aos perfis dos outros usuários. Os logins são
a chave para a personalização no aplicativo Mismatch.
Um login geralmente requer duas informações: um nome de
usuário e uma senha.
O s lp g ín s
permitem <}ue
as aplicações
V e b tr a te m
PS usuários de
forma p^sspaL
Nome do Usuário (Username)
A tarefa do nome do usuário é fornecer
uma identificação para cada usuário
individual dentro do sistema. Os usuários
poderão acessar e potencialmente
comunicarem-se uns com os outros através
dos seus nomes no sistema.
s id n e y f e
Senha (Password)
A senha é responsável por fornecer um
determinado grau de segurança ao login
dos usuários, o que ajuda a proteger os
seus dados pessoais. Para fazer o login,
o usuário precisa digitar tanto o nome
quanto a senha.
j n e t t l e s ^
^ 0* no».es de usuário geralmente
Consister* de caracteres
al-fanuméridos, e são escolhidos
fel® próprio usuário.
* * * * * * * *
* * * * * * ^ ^
As senhas sao dados ^
extremamente sensíveis, e nao
devemjamais £icar visíveis
em uma aplitação, nem mesmo
dentro do banCo de dados.
A combinação de nome de usuário e senha permite ao usuário fazer
login na aplicação Mismatch e acessar dados pessoais, por exemplo,
para editar o seu perfil.
A página £d>tar Períil
agorâ 'mdi£3 ^ e o
usuário esta logado-
O^nome e a senha
sao tudo de <
^u
e a
aplidaçao precisa
para saber ^uem £
o usuário-
^uândo um usuário
login, a aplicada©
torna-se capaz,
de lembrar «juem e
e de -fornecer
u»*a experiência
personalizada.
Youareloggedinassidneyk.
Mismatch- EditProfile
PfejscmalioftHiaaiKMi
First name:
L a s t n a m e;
G ander:
ite
Elabore um plano para os logins dos usuários
Adicionar o suporte a logins ao Mismatch não é tarefa fácil, e é importante estabelecer
exatamente o que precisará ser feito antes de começarmos a escrever código e executar
consultas ao banco de dados. Nós sabemos que existe uma tabela a qual armazena os
usuários, então a primeira coisa a fazer é modificá-la para que ele armazene as informações
de login. Também precisaremos de uma forma de permitir que os usuários digitem os seus
dados de login, e isso precisará ser integrado de alguma forma ao restante da aplicação
Mismatch, para que páginas como Editar Perfil só fiquem acessíveis depois de um login
com sucesso. Eis aqui os passos que estabelecemos até o momento:
criando aplicações web personalizadas
Usar ALTER para adicionar
colunas username e
password à tabela.
O banco de dados agora precisa de
novas colunas para armazenar os
dados de login - nome e senha - de
cada usuário.
J
|L Conectar o script de Login ao
V restante da aplicação Mismatch.
As páginas Editar Perfil e Ver Perfil
da aplicação Mismatch só devem ficar
acessíveis para os usuários logados.
Assim, precisamos nos certificar de
que os usuários tenham de fazer login.
através do script apropriado, antes de
receberem acesso a essas páginas.
Criar um novo scrint rio . -
p zr-s& z-
prc
“ p á t f n í ™ U ltim ainstância,
F gmas pessoazs, poron^ 4
que pede um nome e um* u
vá^ o s . Essas informações
digitadas corretamenrI PreC1Sam
que M ism atch possa e xib ir da
T
específicos „ - ■ dados
^ p Z * z z r 0^ im’°
Páginas personalizadas de f„° “
que elas não possam T’ ma 131
um login válido ervistassem
você está aqui ► 349
configuração do mismatch
Antes de seguir adiante, tire um momento para testar a aplicação
Mismatch e pegar o jeito de como ela funciona.
Baixe todo o código para a aplicação Mismatch no site da Alta Books, em www.altabooks.
com.br. Envie todo o código para o seu servidor web, exceto os arquivos .sql, os quais
contêm instruções SQL para criar as tabelas necessárias. Certifique-se de executar a
instrução de cada arquivo .sql em uma ferramenta MySQL, para que você tenha as tabelas
iniciais das quais irá precisar para o Mismatch.
Quando estiver tudo pronto, vã até a página index.php no seu navegador web, e
experimente a aplicação. Tenha em mente que as páginas Ver Perfil e Editar Perfil
inicialmente não estarão funcionando, uma vez que elas dependem dos logins dos
usuários, funcionalidade essa que estamosjustamente implementando agora.
Estes dois iihks levam a
partes personalizadas
da aplieadâo.
TMKcmfttfil.Wh««opposflesattract!
«»V
i
e
w
P
l
o
S
t
e
«»EdfrfTOflte
Latcsrmember
A fágmâ principal do /V|is»atdH iKe
permite ver ©nome e a -foto dos
usuários »ais redentes, porem nadd
maisj se vode nao estiver locado-
O código-fonte completo da aplicação
Mismatch está disponível para download
no site da Alta Books:
www.altabooks.com.
br
criando aplicações web personalizadas
Preparando obanco de dados para os logins
OK, de volta à construção. A tabela mismatch_userjá está fazendo
um bom trabalho de armazenar informações do perfil de cada
usuário, mas ainda fica a dever no que se refere às informações
de login. Mais especificamente, faltam na tabela colunas para se
armazenar o nome e a senha de cada usuário.
mismatch user
A tabeía
»istoatdh_user
predisa de dolunas
parâ «
tV
”nr>d££hâV
- o
home e a senha de
login dos usuários.
Tantos os dados dos nomes quanto os das
senhas consistem de texto puro, portanto,
é possível usar o familiar tipo de dados
VARCHAR do MySQL para ambas as colunas.
Porém, ao contrário de alguns outros dados
dos usuários, você não pode permitirjamais
que o nome ou a senha fiquem vazios (NULL).
nao eXistefll
Perguntas idiotas
As dolunas userna»e e
password donte*w dâdos de
■texto sWples, w
*as nunda
deve» -fidar vazias.
r- ^Aponte seulápis
Por que eu não posso simplesmente
usar userjd, em vez de username, para
identificar os usuários?
í ^ * Você até pode, se quiser. De fato, o
propósito de userjd é justamente fornecer um
modo eficiente de se identificar individualmente
as linhas referentes a cada usuário. Porém, IDs
numéricas tendem a ser difíceis de memorizar, e
os usuários realmente preferem escolher os seus
próprios nomes ao se cadastrarem em aplicações
web personalizadas. Assim, trata-se mais de uma
decisão de usabilidade permitirque Johan faça
login como "jnettles" em vez de "11". Ninguém
quer ser diminuído a um mero número!
fW as pessoas gostaria»
de te r de lembrar uma
seoha do*» mais de
daradteresj
Termine de escrever uma instrução SQL que adicione as colunas
username e password à tabela posicionada conforme abaixo, sendo
que username precisa ser capaz de armazenar 32, password
16 caracteres e nenhuma delas deve permitir dados NULL.
você está aqui ► 351
aponte seu lápis solução
s :
tponte seu lápis
^ Solupão Termine de escrever uma instrução SQL que adicione as colunas
username e password à tabela posicionada conforme abaixo, sendo
que username precisa ser capaz de armazenar 32, password 16
caracteres e nenhuma delas deve permitir dados NULL.
ALTER t a b l e é usada para
aditionar colunas a u»a
tabela existente.
WALTER . W mismattb__usçr APP. userna»« YARÇlfAR^yP. NOT NULL AFTER user_id,
K - I r
W p password VftRCHMd« NOT HULL AFTÍR u « n *M ^ ----Atolw
>awen^c c
....... ..................................... ........................................................ adicionada primeiro,
Aihstir^o AFTER donWa, «3 tabtla,
onde as «ovas colunas serao adicionadas.
adicionada primeiro,
portanto, vote pode
re-ferendia-la a<ui.
m i sm atch _ _ u s e r
{
A posição das dolunas em uma tabela nao necessariamente íaz.
di+erença, embora possa ser mais adequado, do ponto de vista
organizacional posicionar as Colunas mais «mportahtes primeiro-
Usar A V T B K ia § i(^ ic io n a r
colunas username e password
à tabela.
É claro que você
nao vai simplesmente armazenar a senha
no banco do jeito que ela está... não é preciso
criptografar as senhas antes de armazená-las?
Boa observação... as senhas precisam
ser criptografadas.
A criptografia no Mismatch implica converter a senha em
um formato irreconhecível, ao ser armazenada no banco de
dados. Qualquer aplicação com suporte a login dos usuários
precisa criptografar as senhas, para que os usuários possam ter
a certeza de que as suas senhas estão sãs e salvas. Não é aceitável
expor as senhas nem mesmo dentro do banco de dados. Assim,
nós precisamos de uma forma de criptografar as senhas antes
de inseri-las na tabela mismatch__user. Porém, antes disso, a
criptografia não nos será muito útil se não tivermos uma forma
_ ______ __ _____ i_ _ _____ r.
criando aplicações web personalizadas
Construindo uma interface de usuário para ologin
Uma operação
de log-ln te^ueí
uma Intetíace
pata 9 n9me de
usuárfc e a senfca
Com o banco de dados alterado para armazenar os dados de
login dos usuários, ainda precisamos de uma forma que permita
que eles digitem os dados e realmente façam login na aplicação.
Esta interface de login precisa consistir de campos de edição de
texto para o nome e para a senha, bem como de um botão para
executar o processamento do login.
0 damp© senHa é
proteÿdo> para ^ue â
senha não fossa ser vista-
(jnettles
Password: 
m is m a tc h _ u s e r
CWtzr bota« U0
5
1 ln
íaz- a agitação veri&tar
o nome e a senha junto
ao bànto de dados-
não existem
fergimtas Idîptas
r o »
F i i f r l
1 dierdre * ******
1 baldpaul
* ** ** *
1 jnettles
* ** ** * ** pppsws
£e o nome e a senha
baterem, o usuário é locado
dom sudesso-
0 que fica realmente armazenado no
banco de dados não são asteriscos, certo?
Certo. Os asteriscos mostrados em um
campo de senha simplesmente servem para
fornecer segurança visual, impedindo que alguém
olhe por sobre os seus ombros enquanto você
digita a senha. Quando 0formulário é submetido,
é a própria senha que éenviada, e não os
asteriscos. Épor isso que é importante a senha
ser criptografada antes de ser inserida no banco.
f - 0 .................
Caso estejapreocupado
sobre como os usuários
poderão fazerlogin, se
aindanão atribuímos nomes
e senhas a e
l
e
s
.
.
.relaxe.
Nós iremos criar os nomes e as senhas em
um instante. Por enquanto, é importante
elaborar os alicerces do login, mesmo que
ainda tenhamos de realizar mais tarefas para
que tudo funcione a contento.
você está aqui ► 353
a função sha ()
Criptografe as senhas comSHÀO Aíunçã° SHAO
d p jV W S o I/
A interface de login é bem simples, mas ainda não nos detivemos p
na necessidade de criptografar a senha. O MySQL oferece uma c n p t p g w a u m
função chamada SHA() que aplica um algoritmo criptográfico a W p V T n ín l ío “
fpVfO
uma string de texto. O resultado é uma string criptografada que *
possui exatamente 40 caracteres hexadecimais, independentemente tía n s íP tÜ lc lJ lc lP ''P
do tamanho da senha original. Assim, a função na verdade gera um * ío T
código de 40 caracteres que representa individualmente a senha. ^ 0 1 U H ] C P c ll^ P
Uma vez que SHA() é uma função do MySQL, e não uma função 4 0
PHP, você pode chamá-la como parte de uma consulta que insira
uma senha na tabela. Por exemplo, este código insere um novo
usuário na tabela mismatch_user, criptografando a senha com
SHA() durante a operação.
INSERT INTO mismatch_user
(username, password, join_date) VALUES {
'jnettles '
, j
f
f
§
|
|
j
{
'tatlover'
), NOW (
))
A fun^ao SttAO driptoya£a a senha «a -forma de um todiy» ^ _
de daradteres Hexadedimais, o *y*al t armazinado «a
doluna password da tabela mismatdhjASer.
A mesma função SHA() trabalha do outro lado da equação do
login, verificando se a senha digitada pelo usuário bate com aquela
que foi armazenada criptografada no banco de dados.
£sta i a s«nha real, na
forma dom© -foi digitada
«o respedíivo dampo do
ío rm irio .
U.
* * * " F T 00* '
A senha propriamente dita.
SHA ('tatlover ')
'
f
mismatch user
uwMUB’ username iÜÜii m
9 dierdre 08447b...
10 baldpaul 230dcb...
11 jnettles ^ S r í d ^ 4 ^
A -fundão SâlA^ transforma
a senKa, de 0 daradteres,
trr, uma sbri*$ de texto
drípto^raíada, donte«do
f daradteres.
'e511d793f532dbe0e0483538ell977f7b7c33b2 8 '
£m vez. de armazenarmos a senha
d û » ^
dnptogra-fado d t f O daradteres.
You are fogged m asjn&tüês
criando aplicações web personalizadas
Pcsoriptografando Comparando senhas
Uma vez que você tenha criptografado uma determinada informação, o
instinto natural é pensar que ela deverá ser descriptografada em algum
ponto. Mas a função SHA() é de mão única - ela apenas criptografa,
sem poder voltar atrás. Isso foi feito de caso pensado, para preservar a
segurança dos dados criptografados - mesmo que um hacker invada o seu
banco de dados e roube todas as senhas, ele não conseguirá decodificá-
las. Assim, como é possível fazer login do usuário se você não pode
decodificar a sua senha?
Você não precisa saber a senha original do usuário para saber se ele
a digitou corretamente na tela de login. Isso é porque SHA() gera
o mesmo código de 40 caracteres, desde que você forneça a ela a
mesma string de texto. Assim, você pode simplesmente criptografar
a senha digitada pelo usuário e comparar o código resultante com
o valor presente na coluna password da tabela mismatch_user. Isso
pode ser feito com um consulta SQL, que tenta selecionar a linha
referente a um usuário com base na senha. Esta t a senKa digitada pelo
^-usuário para -Pa«r Ologin.
AíunçãpSBAO
Çoj-nece apenas
a o p e ra ç â p
c t í p t o g r a f e -
n a p e p p s s íV e l
Jeoojlíícai: ciados
^ U e te llfc a n i sido
c r ip to g r a fa d o s .
SELECT * FROM mismatch_user l
WHERE password = §§jj('tatlover '
)
f £*ç2o SHAO é tomada para J
Criptografar a senha» de modo *w
e ela
pode aparefier na clausula VVHERfc-
Esta consulta SELECT seleciona todas as linhas da
tabela mismatch_user cuja coluna password bata com
a senha digitada, ’tadover' neste caso. Uma vez que
estamos comparando versões criptografadas da senha,
não é necessário saber a senha original. Uma consulta
para realmente fazer o login do usuário usa SHA (),
mas ela precisaria também fazer SELECT na ID do
usuário, como veremos em instantes.
Abrindo espaço para a senha criptografada
A função SHA() apresenta um problema para o
Mismatch, uma vez que as senhas criptografadas
acabam tendo 40 caracteres de extensão, mas a nossa
recém-criada coluna password só armazena até 16
caracteres. Precisamos de um ALTER para ampliar a
coluna password, de modo que ela possa armazenar as
senhas criptografadas.
ALTER TABLE mismatch user
CHANGE ® T NDLL
0 ta»anKo da Coluna password t 4
Modvfitado parà*rO> para caberem as ^
senhas Criptogrâíadas.
não existem
Pel-guntíls idiotas
0 que significa 0acrônimo SHA()?
SignificaSecureHashAlgorithm,ou
"AlgoritmodeHashSeguro". 0 "hash"éum
termousadoemprogramaçãodecomputadores,
queserefereaumastringúnica, deextensão
fixa, aqual representaindividualm
enteum
a
stringdetexto. NocasodeSHA(), 0hashéa
stringdetextocriptografada, com40caracteres
hexadecimais, aqual representedeformaúnica
asenhaoriginal.
Existem outras formas de se
criptografar senhas?
Sim. OMySQLofereceumaoutra
funçãosemelhanteaSHA() chamadaM
D5{),
queexecutaumtipoparecidodecriptografia.
Mas0algoritmoSHA() éconsideradoum
poucomaissegurodoqueMD5(), portantoé
melhorusarSHA(). 0 PHPtambémoferece
funçõesequivalentes(sha1{) emd5()), para0
casodevocêprecisarfazeralgumacriptografia
emcódigoPH
P, emvezdedentrodeum
a
consultaSQL
você esfá aqui ► 355
modificando mismatch user
T É J S T O R ÍV e
Adicione as colunas username e password à tabela
m ism atchuser, e depois teste-as.
Usando alguma ferramenta MySQL, execute a instrução ALTER para
adicionar as colunas username e password à tabela mismatchjuser.
ALTER TABLE mismatch_user ADD username VARCHAR(32) NOT NULL AFTER user_id,
ADD password VARCHAR {16)NOT NULL AFTER username
Mas a nossa coluna password precisa ser capaz de conter uma
string de 40 caracteres, portanto emita ALTER mais uma vez
para abrir um espaço maior para os dados.
ALTER TABLE mismatch_user
CHANGE password password VARCHAR(40) NOT NULL
Agora, para testar as novas colunas, vamos fazer um
INSERT de um novo usuário.
INSERT INTO mismatch_user
(username, password, join__date) VALUES (
'jimi '
,
Para certificar-se de que a senha foi de fato criptografada no banco de
dados, dê uma olhada nela, executando um SELECT no novo usuário.
SELECT password FROM mismatch user WHERE username = 'jimi' _ , . »
— Par l*m login bevn-
E, finalmente, você pode simular uma verificação de login fazendo um sucedido,
SELECT no nome do usuário e usando a função SHA() com a senha em se,r 3 rr,C
S
rr‘3 **<^3
uma cláusula WHERE. usada <
ua"do sc
irvserc d linha-
SELECT username FROM mismatch_user WHERE password = l
|
|
|
§
j
(1
heyjoe '
)
Mao sc esy*c$a de
iíripiogra+ar a senha,
chamando SHAO.
í
i'heyjoe 1), NOW (
))
IF
i
l
eE
d
i
tWindow H
e
l
o O
ü
o
o
s
i
t
e
s
A
t
t
r
a
c
t
criando aplicações web personalizadas
EntSo
agora a senha está
criptografada, mas ainda precisamos criar
um formulário de login. Será que poderíamos
simplesmente usar autenticação HTTP, uma
vez que ela requer um nome de usuário e
uma senha para conceder acesso a páginas
protegidas?
Sim! A autenticação HTTP certam ente pode
ser usada como um sistema simplificado de
login dos usuários.
Se você se lembrar da aplicação Guitar Wars do capítulo
anterior, a autenticação HTTP foi usada para se
restringir o acesso a determinadas partes da aplicação,
pedindo um nome e uma senha ao usuário. De modo
geral, essa é a mesma funcionalidade requerida pelo
Mismatch, exceto pelo fato de que agora nós temos um
banco de dados inteiro contendo combinações possíveis
de nome de usuário/senha, em vez de apenas um nome
e uma senha. Os usuários do Mismatch poderiam usar
a mesmajanela de autenticação HTTP; porém, cada
usuário irá digitar o seu próprio nome e a sua própria
senha.
Te page,youneed(
oi
o
gi
ni
òarea'
Yóíir passwprd wilí be semr intbe t*ear.
S
í
a
m
e
:■
Password:
A janela de au-ten-bcatao HTTP
padrao, <ue "tem aparenCia diferente
Conforme o navegadorj pode servir
Como uma interface de iogin
simplificada*
você está aqui ► 3 5 7
autenticação http para mismatch
Autorizando usuários com HTTP
Como foi mostrado no Guitar Wars, é preciso que sejam enviados dois cabeçalhos para
se restringir o acesso a uma determinada página através da janela de autenticação HTTP.
Esses cabeçalhos têm o efeito de pedir que o usuário digite um nome e uma senha para
obter acesso à página Admin do Guitar Wars.
£stes dois eabeçalWos predisa™ sev- enviados
para ®
iue o atesso a uma pagina seja restrito
»»ediante autentitaçao HTTP-
header('HTTP/l.1 401 Unauthorized');
header('W
W
W
-Authenticate : Basic realm="Mismatch"');
O envio dos cabeçalhos para autenticação HTTP resulta em duas linhas de código
PHP - uma chamada à função header() para cada cabeçalho sendo enviado.
— A autentidaçao
HTTP requer <
^u
e
Á «os enviamos dois
Este c o reaU da J dabeçalkos.
autenticarão,. <ue
íerr. eíeito sobre
toda a aplicaça©-
r
H nedessirio digitar
um nome e umâ senka
para se acessar paginas
restritas na aplicaçao
Quitar lA/ars.
Guitar
;Bekwisalii
A
sh
tO
DS
im
EddieVanil
BeBtaC
hev
PhizI^airsii
Toviewthis page, youneedtologiatoarea
' ’^itar'Wars’*onwww;gù)terwars.net
; Vou/ sasaucrd-wi(Jfoe inttir dear!
Name; trock
f 7..
- - ....i
H Remeimber this password in m y keydw in
fC
a
n
c
e
l i
NevaJohanaoa 2008-04-2408:02:11 98430 8 ^ ,
KennyLwfc* 2008-04-23 14:09:5064930 Remove
0 wsuirio só podera ver e usar
esta página se -forneier o nome
e a senba dorretos.
fsc
o
re
sa
sn
e
e
d
e
d
.
criando aplicações web personalizadas
£is o sòvift
At login-
Circule as diferentes partes da aplicação Mismatch que sejam impactadas
pelo script de login (login.php) e pelo seu uso da autenticação HTTP para
controlar o acesso. Em seguida, escreva abaixo de que modo essas partes
são afetadas.
login.php
index.php
mismatch__user
I l I í l l i S I IfÜ!
viewprofile.php
editprofile.php
você está aqui ► 359
exercício soiução
ftcício
S o L u Ç ã o
login.php
guando umusuário fâz. login,
o seu nome e â sua senha são
verificados em relação ao
Conteudo do banCo de dados,
para garantir <y*e pertençam
â um usuário registrado-
Circule as diferentes partes da aplicação Mismatch que sejam impactadas pelo
script de login (login.php) e pelo seu uso da autenticação HTTP para controlar
o acesso. Em seguida, escreva abaixo de que modo essas partes são afetadas.
A home page nao tem nenhum
pape! direto nos logins dos
usuários, porque ela precisa
ficar acessTvel a todos.
A visualização e a
ediçao dos perfis
ficam restritas,
sighifiCândo c^ue
apenas os usuários
«ue f izerem login
poderão acessar
essas paginas.
£e nao for enContrada uma linha Cujos
dados batam com o nome e a senha
fornecidos, o sCript de logih e*ibe uma
mensagem de erro e impede o acesso.
A pagina Editar Perfil nao só utiliza
o sCript de login para restringir o
acesso, Como também precisa do nome
do usuário para determinar <^ual e o
perfil c^ue deverá ser editado-
nat» existem
P:
r & r g u n t a s id io t a s
Por que não é necessário incluir a home page na
exigência de login dos usuários?
Porque a home page é o primeiro lugar que o usuário
acessa ao visitar o site, e é importante que os visitantes possam
olhar o site antes de exigir deles um login. Assim, a home page
serve ao mesmo tempo como uma propaganda e um ponto de
partida - propaganda para os visitantes e ponto de partida para os
usuários registrados, os quais precisam fazer login para acessarem
qualquer ponto mais profundo da aplicação.
T * * Os usuários logados podem ver o perfil de qualquer
outro usuário?
Sim. A ideia é que os perfis fiquem visiveis para todos
os usuários que fizerem login, mas permaneçam invisíveis aos
visitantes não registrados. Em outras palavras, você precisa ser
um membro do Mismatch para ver o perfil de outro usuário.
1 • Como a criptografia da senha afeta a autenticação HTTP?
Existem duas questões em jogo aqui: transmitir a senha
e armazenar a senha. A função SHAQ do MySQL concentra-se
em armazenar uma senha, de forma segura e criptografada,
no banco de dados. 0 banco não está preocupado com
a forma como você transmitiu a senha originalmente, de
modo que este tipo de criptografia não tem impacto nenhum
sobre a autenticação HTTP. Porém, poder-se-ia argumentar
que a criptografia deveria também ser realizada durante a
transmissão da senha, quando a janela de autenticação HTTP
a submete ao servidor. Esse tipo de criptografia está fora do
escopo deste capítulo e, em todo caso, só é necessária quando
se está lidando com dados extremamente sensíveis.
criando aplicações web personalizadas
Fazendo login dos usuários comautenticação HTTP
O script de login (login.php) é responsável por pedir um nome e uma senha do usuário,
usando cabeçalhos de autenticação HTTP, por obter os respectivos valores de nome e
senha da superglobal $_SERVER, e por verificar se eles batem com os dados contidos em
mismatch_user antes de conceder acesso a uma página restrita.
<?php Se o nome c a senha nao tiverem sido
require once{'connectvars.php'
) ; digitados, CnVie os £abe£alhos dc âutent'£a£3o
para pedir que o usuário digite esses dados. 
if (!isset($_SERVER['PHP_AUTH_USER']) |
| !isset($_SERVER[’PHP_AUTH_PW'])> { I
/ / O nome/senha não foram digitados, portanto, enviar os cabeçalhos de autenticação headers
"
M’
Mexit(’<h3>Mlsmatch</h3>Desculpe, você deve digitar seu nome e senha para fazer'
login e acessar esta página. ');
}
// Conecta-se ao banco de dados
$dbc = mysqli_connect(DB_HOST, DB__USER, DB_PASSWORD, DB_NAME) ;
// Obtém os dados de login digitados pelo usuário
Ôbtem o nome e a
senha distados pelo
usuário-
// Procura o nome e a senha no banco de dados
mm
«
wdom aqueles
if (mysqli_num_rows ($data) -- 1) { dtàrfcados.
// 0 login foi bem-sucedido, portanto, definir as variáveis de ID e nome do usuário
£e fo r enòontrâda uma l«»ba, *y»if'*a
que o login foi bem—
sudedido e apodem
os
definir as variáveis fuser_jd c fusername-
else {
// 0 nome/senha estão incorretos, portanto, enviar os cabeçalhos de autenticação
exit{1<h2>Mismatch</h2>Desculpe,você deve digitarseu nome e senha para fazer!
login e acessar esta página.');
// Confirma o login bem-sucedido.
Se nenhuma linha no bânio de dados bater dom o nome
e a senha digitados, envie novamente os dabedafhos de
autentidadao para que o usuário possa tentar outra vez.
?>
S .
Chegando a este ponto, esta
tudo bem, portanto donfirme o
login bem-sudedido. Criar unftdVQ ’StíHpTde Login
que peça ao usuário para
digitar seu nome e senha.
você está aqui ► 361
test drive mismatch
O R 1 V E ______________
Crie o novo script de login, e o inclua nos scripts Ver Perfil e Editar Perfil.
Crie um arquivo de texto chamado login.php e digite nele o código para o script de login
(ou baixe o script no site da Alta Books, www.akabooks.com.br). Em seguida, adicione
algum código PHP no início dos scripts viewprofile.php e editprofile.php para incluir o
novo script de login.
Envie todos os scripts ao seu servidor web, e em seguida, abra a página principal do
Mismatch em um navegador. Clique no link Ver Perfil ou Editar Perfil para fazer login e
acessar as páginas personalizadas. E claro que isso só funcionará se vocêjá tiver adicionado
um usuário, com respectivos nome e senha, ao banco de dados.
Estes dois links levam as páginas
protegidas, as ^uais dhamam o
sdript de login das© o usuário
«ao esteja logado-
Esta sento é driptcgva£ada
to * SttAO c deparada dom
aquela presente no banda de
dados, para determinar se o
login deve ser permitido-
ToViewthispage, y»u{
ne«fft
‘Misafatch"onwww.mis-ma
raurp
a
s
s
w
o
rd b
e$
e
n
{ j^ctearj
♦torté:1. ijnettles
0 sdript de login usa
âu ten tid ad âo HTTP para impedir
adesso não autorizado as paginas
Ver Per-í-il e Editar Períil.
A home page nao t protegida pelo
sdript de login, mas serve de ponto
de partida para se navegar ate níveis
mâis profundos da aplidadao
criando aplicações web personalizadas
$uaJ^uer página
do /Wismatdh c^e
predisar exigir login
s« predisará indluir
° ^ 'p t login.php no
irtidio do seu dódigo-
0 sdript de login
e a primeira doisa
a ser indlwídâ nos
sdripts- Ver Per-Çil
e Editar Períil*
para proteger as
respedtwas páginas.
£e o nome e a senha
íorew* validos, o
usuário e logado, e o
restante da página
pode ser enviado-
Cada usuário redebe a sua
própria experiendia personalizada
do Mismatdh.
Conectar o script de Lftgl-------- - ,
restante da aplicação Mismatch.
você está aqui ► 363
mismatch precisa de um formulário de cadastro
Ruby èdorâ íilmes de
tev-v-ov-, vcsolvcr Quebra—
dâbcÇâS e tormidâ
apimentada, mas neste
exato mo»*»e«to, ela odeia o
Alismátdh por hão permitir
^ue se fiâdastre e use o
sistema-
0
Os usuários novos do Mismatch precisam de
uma forma de se cadastrarem .
O novo script de login faz um bom trabalho ao usar a
autenticação HTTP para permitir que os usuários façam
login. O problema é que os usuários não têm nenhuma
forma de se cadastrarem - fazer login é difícil quando
você ainda nem sequer tem um nome e uma senha. O
Mismatch precisa de um formulário de cadastramento,
o qual permita que nóvos usuários sejuntem ao site,
criando um nome e uma senha para eles.
Nome de Usuário?
Senha?
Um formulário para novos usuários se cadastrarem
Como este novo formulário de Cadastro deve ser? Nós sabemos que ele precisa permitir
que o usuário digite o nome e a senha desejados... mais alguma coisa? Uma vez que o
usuário está estabelecendo a sua senha com o formulário e as senhas em formulários web
geralmente são escondidas com asteriscos por motivo de segurança, é uma boa ideia ter
dois campos para a senha. Dessa forma, o usuário digita a senha duas vezes, apenas para
nos certificarmos de que não houve nenhum erro de digitação.
Assim, a tarefa da página de cadastramento é obter o nome e a senha do usuário, certificar-
se de que o nome ainda não esteja sendo usado por ninguém, e finalmente adicionar o
novo usuário ao banco mismatch_user.
criando aplicações web personalizadas
WieVhdmc: ( j
Password;
ruibyr
Pâssword:
('rcíyye)
! J $ í*ÿtada d*as ve«s3?ara
^
------ —
____ J ^—
—
— ■ 3jud3^ d eíim'mâr--se o rtsdo dc o
uswirto de-finir u»a senha mdorretâ
para S
I
.
t
ciitá r no botao Cadastrar
resulta «as aplitações
adidionar o nome e 3 senha
ao bando de dados.
mismatch user
l í § í » l l usemam *! password
íTTTífyl
fiilsife
10 baldpaul d8a011...
11 jnettles e511d7...
ip r 12 rubyr 062e4a...
Uma vez. que as senhas apora estão
driptoÿra+adas, elas esiao securas
mesmo ^ue al^uem donsíc^a ver o
donteudo do bando.
Um problema potencial com o script de cadastro é o usuário tentar
se inscrever com um nome que já exista. O script precisa ser esperto
o suficiente para capturar esse problema e fazer o usuário digitar um
nome diferente. Assim, a tarefa da página de cadastro é obter o nome
e a senha do usuário, certificar-se de que o nome ainda não esteja
sendo usado por ninguém, e finalmente, adicionar o novo usuário ao
banco mismatch user.
v o c ê e s tá aqui
signup.php finalizando
Imas de Geladeira dp PHP &My$QL
O script de cadastro do MySQL usa um formulário personalizado
para pedir ao usuário que escolha o seu nome e senha desejados. O
problema é que o script encontra-se incompleto. Use os imas abaixo
para finalizá-lo, de modo que novos usuários possam se cadastrar e z' tâdashr,
se juntar à comunidade Mismatch. y
Êis o
•foirmulario àe
Mismatch - Sign Up
Please enter your username and desired
pRegistration Info—
I ' U
s
e
rn
a
m
e
;
j P
a
s
s
w
o
r
d
;jTZT,
I Password
passwartf to Sign up to Mismatch.
(retype):
<?php
require_once(’appvars.php’);
require_once(’connectvars.php1);
// Conecta-se ao banco de dados
$dbc= mysqli_connect(DB_HOST, DB_USER, DB_PASSWORDf DB__NAME);
if (isset($_POST[’submit'I)) {
// Obtém os dados do perfil a partir de POST
...............= mysqli_real_escape_string($dbc, trim ($_POST [’ ...............]) );
.................= mysqli_real__escape__string ($dbc, trim($_POST[1............... ’]));
................ = mysqli__real_escape_string {$dbc, trim ($_POST [’ ............... .
’]));
if (!empty($username) && !empty($passwordl) && !empty($password2) &&
( ............................==.............................)) I
// Certif íca-se de que ninguém já tenha se registrado com o mesmo nome
$query = "SELECT * FROMmismatch_user WHERE username = 1...............'
$data - m y s q l i _ q u e r y ($dbc, $query);
if (mysqli_nui7
i_rows ($data) ==0) {
//O nome do usuário é único, inserir os dados no banco
$query= "INSERT INTO mismatch_user (username, password, join_date) VALUES" .
Nao se esqueça vete -tem
à th - z t* estape de ^ual^uer
apostroío apareça dentvo
" ('.............. ;, SHA( ' .......’), NOW {
) )
mysqli_query($dbc, $query);
L de ãspâs simples.
// Confirme o sucesso com ousuano >
» *
echo '
<p>A sua conta foi criada com sucesso. Agora você pode fazer login e '
'
<a href=”editprofile.php">editar seu perfil</a>.
</p>'
;
mysqli_close($dbc);
exit(
)
;
criando aplicações web personalizadas
else {
//Já existe uma conta comeste nome, exibir mensagem de erro.
echo 1<p class="error,
l
>Já existe uma conta com este nome. Por favor, escolha outro. 1 .
'nome.</p>';
_ nn.
}
}
else {
echo '<p class='Terror">Você deve digitar todos os dados de login, incluindo a senha ' .
'desej ada duas vezes ,</p>';
}
}
mysqli_close($dbc);
?>
<p>Por favor, digite seu nome de usuário e senha desej ados para se cadastrar no Mismatch.</
P>
<form method="post" action="<?php echo $_SERVER [1PHP_SELF’]; ?>">
<fieldset>
<legend>Informações de Registro</legend>
<label for="username">Kome de Usuário:</label>
<input type=',text" id=” ............. " narae=" _ ..... "
value="<?php if (!empty(.. ............)) echo ; ?>" / x b r />
<label for=" .
.
. ........ ">Senha:</label>
<input type="..............." id=" ................" name=" ............... V /><br />
ciabel for=".............. ">Senha (digite novamente) :</label>
<input type="............ " id="..............." name=M ............... " / x b r />
você está aqui >
signup.php completo
I m a s d e G e l í  c l e n <  d o P H P &
M/SQL - Soluçã®
O script de cadastro do M ySQ l usa um formulário personalizado
para pedir ao usuário que escolha o seu nome e senha desejados. 0 tis o
problema é que o script encontra-se incompleto. Use os imas abaixo -formuláriode
para finalizá-lo, de modo que novos usuários possam se cadastrar e J dâdastro-
se juntar à comunidade Mismatch. — ▼
<?php
req u í r e _ o n c e ('appvars-php');
require__once('connectvars-php');
// Conecte-se ao banco de dados
$dbc= mysqli_Connect(DB_HOST, DB_USER, DB__PASSWORD, DB_NAME);
Obtenha -
t
o
d
o
sos dados digitados
:mysqli__real_escape_string ($dbc, trim ($_POST [’
i f (isset ($_POST t submit ] ) ) { pelo usuário, prii*eira«*ente-
// Obtem os dados do perfil a partir de POST
$username
$passwordl
$password2
Jr=my s q l i__real_escape_s tr ing ($dbc, trim ($_POST ['
:mysqli_real_escape_string ($dbc, t r i m ($ _ P O S T [ .
if (!empty(Çusernarae) && !empty($passwordl) && !empty($password2) &&
<, Spasswordl | | $passMoraL B l (4r
atytadês sejãm tdcwfcttss*
// Certifique-se que ninguém já tenha se registrado com o mesmo nome
$usemame
ealizí v^a donsulta para ver
$data =my s q l i_ query ($dbc, $query) / 'v. sc e*,stem i'mKas batendo dom o
if (mySqli_num_rovs ($data> = 0) { ^ dc ^  0 deitado.
$query = "SELECT * FROM mismatch_user WHERE username =
//O nome do usuário é único, inserir os dados no banco
$query= "INSERT INTO mismatch_user (username, password, join_date) VALUES " .
S H A (1

£e não houver nenhunta linha,
entao o usuário é novoj entâo
$passwordl ^ ,now (
))
, . (í, ,, t ^ ^ P S a das sínhas poderia %
e
r P f a z e r o ÍNSERT.
mysql^querylSdbc, $query>; ar i
, « M „£ £ s dev„,
// Confirma o sucesso com o u s u á r i o " ’
d“ ‘
tiUs f * «•*»<«« a trtt pont».
echo 1<p>A sua conta foi criada com sucesso.Agora você pode fazer login e
1<a href="editprofile.php">editar seu perfil/a>.</p>1;
CcM-firma o Lddâskro do
mysqli_close($dbc);
exit (); g- usuário e f inaliza o siript-
}
else {
//Já existe uma conta comeste nome, exibir mensagem de erro
echo ’<p ciass="error">Já existe uma conta com este nome.Por favor, esc
nome</p>1;
Limpa a variável
?user*3me, para <ue o
rcspediivo dampo ro
•formulário seja esvaziado.
0 nome de w
já está sendc
eivfcao exibi»*
mensagem de
01S
0 {
echo 1<pclass="error”>Vocêdeve digitar todos os dados de login, inclu
’ desejada duasvezes.</p>'; A
} V Um OUmais dos dámpos do
} -formulário e
s
t
ã
ovazios, en-fcão
mysqli_close ($dbc) / " ibi“ “ “* * * « « ■
?>
<p>Por favor, digite seu usuário e senha desej ados para se cadastrar no Mis
<form method="post" action="<?php echo $_SERVER[ 'PHP_SELF’]; ?>">
<fieldset>
<legend>Informações de Registro</legend>
<label for-"username">Nome de usuário:</label>
<input type=”text" id=".
value="<?php if (lempty
<label for=".:
<input type^",,
<label for="..
<input type="
|„ id=„ J password! H name=" .
|passw0rdlj| /><br />
»Password (retype):</label>
id=" I passwords Bina.ni6=">
^^P^sswofd2 /xbr />
</fieldset>
<input type="submit" value="Sign Up" name="submit" />
</form>
T:
existem
V&tgimfàs idiotas
signup.php
Por que não poderíamos simplesmente usar
autenticação HTTP para o cadastro de novos usuários?
K . * Porque o propósito do script de cadastro não é restringir
o acesso a determinadas páginas. A sua tarefa é permitir que
o usuário escolha um nome e uma senha, e então adicioná-los
ao banco de dados. Certamente é possível usar a janela de
autenticação HTTP como formulário de input para o nome e a
senha, mas usar a funcionalidade de autenticação apenas para
cadastrar um novo usuário seria como usar uma espingarda para
matar um mosquito. É melhor criar um formulário personalizado
para os cadastros - assim você obterá o benefício da verificação
dupla da senha, para se evitar erros de digitação.
T:Então o script de cadastro faz login dos usuários
depois que eles se cadastram?
H : Não. E o motivo tem a ver principalmente com o fato de que
o script de login já lida com a tarefa de logar o usuário, portanto
não há necessidade de duplicar esse código no script de cadastro.
Em vez disso, o script de cadastro apresenta um link para a página
Editar Perfil, aonde o usuário presumivelmente desejará ir após
se cadastrar. E uma vez que ainda não estará logado, a janela de
login lhe será apresentada em resposta à tentativa de acessar a
página Editar Perfil. Assim, o script de cadastro leva o usuário até
a janela de login através da página Editar Perfil, em vez de fazer o
seu login automaticamente.
você está aqui ► 369
criando aplicações web personalizadas
T fe S T O R fv e
Adicione a funcionalidade de cadastro ao Mismatch.
Crie um arquivo de texto chamado signup.php e digite nele o código do script de
cadastro (ou baixe o script no site da Alta Books, www.altabooks.com.br). Em seguida,
modifique o script login.php, adicionando-lhe links para o script de cadastro para os
usuários que não conseguirem fazer o login.
Envie os scripts ao seu servidor web, e em seguida, abra a página Cadastrar no seu
navegador. Cadastre-se como um novo usuário e depois faça login. Em seguida,
edite e visualize o seu perfil para confirmar que o cadastro e o login funcionaram
corretamente. A aplicação agora tem aquele toque pessoal que estava faltando.
A au-fcch-tida&io
HTTP e usada para
io^ar Ruby to m base
*as »»-foirmaçoes «|ue
ela íornedeu no seu
cadastro.
mismatch também precisa permitir que os usuários façam logout
Eu compartilho um
computador com duas colegas
de quarto e não gostaria que elas
tivessem acesso ao meu perfil do
Mismatch. Preciso da capacidade
de fazer logout!
Os sites de comunidades precisam perm itir que os
usuários façam logout, para que os seus dados pessoais
não possam ser acessados por terceiros em um
computador compartilhado.
Permitir que os usuários façam logout pode parecer algo
extremamente simples, mas apresenta um problema relativamente
sério quando se usa a autenticação HTTP. O problema é que esta
serve para ser executada uma vez para uma determinada página ou
conjunto de páginas - ela só é resetada quando o navegador é fechado.
Em outras palavras, o usuário nunca é "deslogado” de uma página
web autenticada via HTTP até que o navegador seja fechado ou que
o usuário manualmente finalize a sessão de autenticação HTTP. Esta
última opção é mais fácil de executar em alguns navegadores (Firefox,
por exemplo) do que em outros (Safari).
Umâ ve2- -Peito o loÿ*,
vote permâvtcte locado
aie íeihav o »ave^ado*-
Y
o
uo
r
el
o
g
g
e
dí
i
t
a
ss
í
d
n
e
y
k
.
Mismatch -EditP
r
o
f
i
l
e
T$vtçwíthispage,youneedtotogintoarea
“fcBsmafc*”<«!ww.m>s-*natchj»et
w
i
ib
t i
n
i
h
*c
l
e
i
r
.
Firslnam
e: S
i
d
n
e
y
L
a
s
tname; FEr^T
G
ender: jSSfeäi
BMidate: [1984-07-19'
Mame. sidneyk
P
a
s
s
w
o
r
d
:
!
«
«
»
»
*
City: T
im
p
e
State:
H Rememberthispasswordinmykeychain
Ptenre:
U
w
> veiurso de
logout pevmjtiria
a Sidh«y ton-kv-olar
diAidadosa»ente
o atesso ao seu
^erí»! pessoal-
Embora a autenticação HTTP apresente uma forma simples e útil de estabelecer os logins
dos usuários na aplicação Mismatch, ela não fornece nenhum controle para fazer o logout
do usuário. Nós precisamos tanto do recurso de lembrar dos usuários quanto de permitir
que eles saiam do sistema quando quiserem.
■970
criando aplicações web personalizadas
você está aqui ► 3 7 3
introduzindo cookies
. * , . . ,. Aautenticação
Asvezes voce so precisa de um cookie y-jyp
O problema originalmente resolvido pela autenticação HTTP tem
duas faces: há a questão de se limitar o acesso a certas páginas, e
há a questão de lembrar que o usuário digitou informações sobre
si mesmo. O segundo problema é o mais complexo, porque ele
envolve a capacidade de a aplicação se lembrar de quem o usuário
é ao longo de diversas páginas (scripts). O Mismatch resolve essa
questão verificando o nome e a senha armazenados na superglobal
$_SERVER. Assim, nós podemos tirar proveito do fato de que o
PHP armazena o nome e a senha da autenticação HTTP em uma
superglobal que persiste ao longo de diversas páginas.
armazena dadps
persiStentenielite
no cliente, mas nã°
permite <jue Vpce
Q
Sapague guando
termina de usa-fcs.
Tb view this paçe, you r.eod W to area
“ Mismatch” òn ttfww.fflis-match.net
t
o
u
rp
a
s
s
w
w
d
w
i
i
l
b
es
w
i
t
m
'
r
h
e
d
e
a
'
.-
1
Mame: sidneyk
P
a
s
s
w
o
r
d
:1
n RememberThispasswordinmykeychain
Cancei
Asufevjiobal /_
_SERVER [ ’ PHP_AUTH_USER' ]  £ÊR/ER a ^ a « ^
f O*o»>e e a senha
$_SERVER [ ■PHP_AUTH_PW' ]J W |l i e
Mas não podemos mais nos darmos ao luxo de usar
a autenticação HTTP, porque ela não tem suporte a
logouts. Assim, precisamos procurar outro meio de
implementar a persistência do usuário ao longo de
diversas páginas. Uma possível solução são os cookies,
pedaços de dados armazenados pelo navegador no
computador do usuário. Os cookies são bastante
parecidos com variáveis PHP, exceto pelo fato de
que eles continuam existindo depois que você fecha
o navegador, desliga o computador, etc. E o que é
mais importante, os cookies podem ser apagados,
significando que você pode eliminá-los quando tiver
terminado de armazenar dados, por exemplo, quando
o usuário indicar que deseja fazer logout.
Õs cookies lfce permitem
a rm a z e n a r h p c lie n te
pequenos pedaços
de dados de Çprma
persistente, signlíicandp
<jue eles ppdem continuai:
existindo mesmp depois
de Íínalizado o script»..
e ppdem também ser
ap^gadps a ^ual^uer
m o m e n to !
Navegador wêb
do cliente
Os dados dos cookies são armazenados no computador do usuário pelo seu navegador web.
Você tem acesso aos dados através de código PHP, e o cookie é capaz de persistir ao longo
não só de várias páginas (scripts), mas até mesmo ao longo de várias sessões do navegador.
Assim, fechar o navegador não faz o usuário se deslogar automaticamente do Mismatch.
Isso não é problema para nós, porque podemos apagar um cookie a qualquer momento, a
partir de código de script, o que toma possível oferecer um recurso de logout. Podemos
dar aos usuários controle totalmente sobre em que momento eles querem sair do sistema.
Servidor
criando aplicações web personalizadas
Po que é feito ocookie?
O cookie armazena um único dado, sob um nome único, praticamente da mesma forma
que uma variável em PHP. Ao contrário das variáveis, o cookie pode ter um prazo de
validade. Quando a data de validade é atingida, ele é destruído. Assim, os cookies não são
exatamente imortais - eles apenas vivem por mais tempo do que variáveis PHP. Você pode
criar um cookie sem prazo de validade, em cujo caso ele se comporta do mesmojeito que
uma variável PHP - é destruído assim que o navegador é fechado.
Os cookies lhe permitem armazenar uma string de texto sob um determinado nome, mais
ou menos como uma variável de texto PHP. O que torna os cookies tão poderosos é o
fato de poderem viver por mais tempo do que os dados de um script, especialmente em
situações em que a aplicação consiste de várias páginas que precisam se lembrar de alguns
dados, por exemplo, informações de login.
precisamos realmente manter a senha, poderia ser dados permaneçam existindo por mais tempo do que
mais útil armazenar a ID do usuário em vez disso. uma página (persistência), mas não eternamente.
Home
O nome único do cookie
Valor
O valor armazenado no cookie
Pata devalidade
A data em que o cookie
expira... e deixa de existir
"perguntas idïçtas
não existem
?
1 * Qual é a grande vantagem dos cookies serem
persistentes? Os dados armazenados em um banco
de dados MySQL não são também persistentes?
Dcíihiy o prâzo
de vaiidade de um
$uândo voe« *3©
dookic tom uma dãtã
bâstâhte -fuiuvâ
ajuda a -barná-lo mais
permanente.
•Çorneôe ftCrtHu»
de vâlidadcj o tockit
e apagado assim que
o navegador fo r
Sim, os dados de um banco certamente são
persistentes. Na verdade, são tecnicamente muito
mais persistentes do que um cookie, porque não há
nenhum prazo de validade envolvido - depois que você
coloca dados em um banco, eles ficam lá até que você
os remova explicitamente. A questão real, no que se
refere aos cookies e a persistência é a conveniência.
Nós não precisamos armazenar para sempre a ID atual
ou o nome do usuário só para permitir que ele acesse
seu perfil; só precisamos de uma forma rápida de
saber quem ele é. 0 que realmente precisamos é de
persistência temporária, o que pode parecer paradoxal
até você considerar o fato de que precisamos que os
fedKado.
Assim, o Mismatch pode imitar a persistência
fornecida pela superglobal $_SERVER
configurando dois cookies - um para o nome
do usuário e outro para a senha. Mas nós não
você está aqui ► 375
A função setcookieQ
Use cookies corn PHP
O PHP fornece acesso a cookies através de uma função chamada setcookie() e
uma superglobal chamada $_COOKIE. A função setcookie() é usada para se
definir o valor e a data de validade (opcional) de um cookie, e a superglobal
$_COOKIE é usada para se obter o valor de um cookie.
setcookie('username'
, 'sidneykT);
......... *
ô pvimeivo J
para srfôookieO é o
naw
»e do Cookie
0 valor a s«- ado
*o tooki« t passado to *° o
secundo âr<y*»netïfco'
echo(’
<p class="login">Você está logado como
’.</p>’);
0 nom
e do ôookic t wtâdo para
re-IWcniiav' o seu y/aiov na
supcrjlobâl f_COO£i£.
A vantagem de se definir um cookie é que os seus dados
persistem ao longo de vários scripts, portanto nós podemos
nos lembrar do nome do usuário sem ter de pedir que ele o
informe a cada vez que passar de uma página para outra na
aplicação. Mas não se esqueça, precisamos armazenar a ID
do usuário em um cookie, uma vez que ela serve de chave
primária para consultas ao banco de dados.
■p i
A função
s e tc o o la e Q J o
PB? iLe permite
a rm a z e n a r d a c fe s
e m c o o k ie s *
s e t c o o k ie ( ’ u s e r _ id
0s tookies são sewfre
arma^^ados tomo áe
modo ^*e, w*csmo *ue a iP do
usuário seja u» numero^ v
>
c
&
a avwaz^namos e» u
w
» dookie
l<mo a stvín^ j .
A função setcookie 0 também aceita um terceiro argumento opcional, o qual define o
pra2o de validade do cookie, que é a data na qual este é automaticamente apagado. Se
você não especificar um prazo de validade, como no exemplo acima, o cookie expira
automaticamente assim que o navegador for fechado.
criando aplicações web personalizadas
Aponte seu lápis
Ajustar o Mismatch para usar cookies envolve mais do que apenas escrever
um novo script de logout. Primeiramente, nós temos de rever o script
de login e modificá-lo para usar cookies em vez da autenticação HTTP.
Circule e comente as partes do código de login que você acha que precisa
modificar para acomodar os cookies.
<?php
requíre__once (
'connectvars -php');
if (!is-set ($_J3ERVER[ 'PHP_AUTH_USER' ]) ]
[ !isset ($_SERVER[ 'PHP_AUTH_PW' J)} {
/ / O nome/senha não foram digitados, portanto enviar os cabeçalhos de
autenticação header(1HTTP/l.1 401 Unauthorized');
header('WWW-Authenticate: Basic realm="Mismatch" 1);
exit{1<h3>Mismatch</h3>Desculpe, você deve digitar seu nome e senha para fazer’,
'login e acessar esta página. Se ainda não for um usuário registrado, por favor'.
’<a href="signup.php">cadastre-se</a>.');
// Conecta-se ao banco de dados
$dbc = mysqli_connect(DB_H0ST, DB_USER, DB_PASSWORD, DB__NAME);
// Obtém os dados de login digitados pelo usuário
$user_username = mysqli_real_escape__string($dbc, trim($_SERVER['PHP_AUTH USER’]));
$userp a s s w o r d = mysqli_real_escape_string($dbc, trim($_SERVER['PHP_AUTH_PW']));
// Procura o nome e a senha no banco de dados
$query = "SELECT user_id, username FROM mismatch_user WHERE username = " .
"'$user_usernaine' AND password = SHA('$user_password'
)";
$data = mysqli_query($dbc, $query);
if (mysqli_num_rows($data) == 1) {
// O login foi bem-sucedido, portanto definir as variáveis de ID e nome do usuário
$row = mysqli_fetch_array($data);
$user_id = $row[’user_id'];
Çusername = $row['username’];
else {
// O nome/senha estio incorretos, portanto enviar os cabeçalhos de autenticação
header('HTTP/l.1 401 Unauthorised');
header (’WWM-Authenticate: Basic realm="Mismatch"1);
exit('<h2>Mismatch</h2>Desculpe, você deve digitar um nome e '.
'senha válidos 'para fa2er login e acessar esta página'.
'Se ainda não for um usuário registrado, por favor,'.
'<a href="signup.php”>cadastre-se</a>.');
// Confirma o login bem-sucedido.
echo(’<p class="login">Você está logado como ' .
?>
headers
lo g in .p h p
você está aqui ► 3 7 7
aponte seu lápis solução
.ponte seu lápis
Solupão Ajustar o Mismatch para usar cookies envolve mais do que apenas
escrever um novo script de logout. Primeiramente, nós temos de
rever o script de login e modificá-lo para usar cookies em vez da
autenticação HTTP. Circule e comente as partes do código de login
que você acha que precisa modificar para acomodar os cookies.
<?php
*quire_once('connectvars.php'
)
Kós predisamos veriíidar
a e*istendia de um dookie
para ver se o usuário está
locado ou nao.
Em vez. de obter o nome e a senha a
partir de umajanela de autentifia^a©»
pretisâm os usar u» -formulário C
omdados
POST. '
SERVER[’PHP AUTH USER’]}
/senha náo toram c
t
j
.
c
r
if
a
r
i
r
f
S
*
:
[I !isset($_SERVER[1PHP_AUTH_PW']))
'.uuii
r
am o enviar oa cabêCcilEiôè üê
autenticação header (’HTTP/l.1 401 Unauthorize
^-Authenticate: Basic realm^'Mismatch"');
-
.
L
.
5
-
4
“
i-Lsmatch</h3>Desciilpe, você deve diyiLaL seu nome e senha para fazer
: esta página. Se ainda não for um usuário registrado, por favor',
"signup.php">cadastre-se</a>.');
Nao precisamos mais enviar dabeçalhos
de autenticarão HTTP.
// Conecta-se ao banco de dados
$dbc = mysqli__connect (DB_HOST, DB_USER, DB PASSWORD, DB NAME)
// Obtém os dados de login digitados pelo usuário
$user_username = mysqli_real_escape_string($dbc, tri
$user^password - mysqli_real_escape string($dbc, tri.
í
($_SERVER['PHP_AUTH_USER'
] )’
($ SERVER['PHP AUTH PW']));
// Procura o nome e a senha no banco de dados
$query = "SELECT user^id, username FROM mismatch_user WHERE username =
"'$user_username' AND password = SHA('$user password')";
$data = mysqli_query ($dbc, $query); A Consulta nao predisa
se modi-fidar em nada^
if (mysqli_num_rows($data) — 1) „
// 0 login foi bem-sucedido, portanto definir as variáveis de ID e nome do usuário
$row - mvsali fetch array($data);
C
?user_id - $row {'user_id1] ;
$username = $row[ 'username' ]
s
else
J J O nome/^pnha estão incorretos, portanto enviar os cabeçalho*
header(’HTTP/1.1 401 Unauthorized1);
v^^eader ('WWW-Authenticate : Basic realm="Mismatch"'
) ?
e x i H ''
-
l
i
2 >Mj.am,
atch</hZ>Uesdaigiê, voce deve digital TUlL'nome e
'senha válidos 'para fazer login e acessar esta página'.
'Se ainda não for um usuário registrado, por favor,
’<a href="signup.php">cadastre-se</a>.1);
A«ui nós te»*« de deíinir
dois tookies, e» vez. de
deíinir variaveis do sdript
i
s de autenticacao headers
// Confirma o login bem-sucedido.
echo(1<p class="login,
l
>Você está logado como ' . Çusername . '.</p>');
Uma vez. *^u
e nao irernps usar ajanela de
autentidaçao HTTP para diytaçao do nome t
da senha, temos de driar um íormulário de lo^in
HTML- para o usuário -Pomcder essas informâdoes.
lo g in .p h p
criando aplicações web personalizadas
Repensando o fluxo dos logins
Usar cookies em vez de autenticação HTTP para os logins do Mismatch envolve mais do
que apenas repensar o armazenamento dos dados dos usuários. E quanto à interface do
login? O login baseado em cookies precisará fornecer o seu próprio formulário, uma vez
que não poderá usar ajanela de autenticação para a digitação de nome e senha. Nós não
só precisamos criar esse formulário, como também temos de pensar em como ele modifica
o fluxo da aplicação, à medida que os usuários fazem login e acessam outras páginas.
Um novo -formulário de l©gm tomS o iugar
da janela de autentidaçao HTTP para a
dityiacao do nome e da senha-
Mismatch - Where opposites attract!
•LssJn ■
►
s
ig
a
ü
R
Latestmakers:
% ■
f t
1
£ '
A
'V .
Clidar no novo link
*L03 fn” leva a pagina
de login, onde o
usuário pode digitar
as su3s m-íormâí-oes
para donedtar-se ao
sistema
#i*ando o usuário não está
logado, os membros mais index.php
redentes sao mostrados
domo homes estátidos.
u sernamer
Password-- [ * * * * & £
[ j ^ n
Após íaz^r login Cct*
sudesso, o usuário e
rediredionado para a Kome
page, onde o menu agora
revela <ue ele esta logado.
M hm stch * W hoe opposites attract!
V LogOut(skfaevkl
0 sdripi de logout íidâ ddessivel
atraves de um link ^ue íâz-
parte do status de logout-
$s paginas restritas
agora estão adessíveis,
uma vez.<ue ° usuário
está logado-
0 menu de
navegaçao príndipal
indlui um link Log
Oui «
^u
e mostra
tambem o nome do
usuário logado.
Afos o login, os nomes dos
membros mais redentes se
trans-formâm em links para
os seus respedtivos per-m.
viewprofile.php
você está aqui ► 379
login.php —agora com cookie
Vut login baseado ew cookies
A nova versão do script de login, que usa cookies para
implementar a persistência, é um pouco mais complexa do
que a sua predecessora, uma vez que ela precisa fornecer o
seu p ró p rio fo rm u lá rio p ara a d ig itação d o n o m e d o usu ário
e da senha. Mas é também mais poderosa, uma vez que
oferece a funcionalidade de logout.
<?php k A **
require once ('connectvars.php 1); mCfisajCftS Ot Crvo â^OTS SâO
armaz<»adas e**uma variável e exibidas,
// Limpa a mensagem de e r r c i ^ ^ ^gsslrio, »ais adiânt« «O Séript-
:$erxox_.msg’ = '
C ' — —
, , , „ , . . /eri-(We o tockt userjd ?ara
Se q usuariQ .nao es.tiver. Ipgaçio, tenta fazer o logm v i , t^ « _i
- - se o usuari©esta locado-
login.p
£is e «ovo
-formulário de io<ÿ*.
I if (!isset {:£^qx>KiEj ’ V£V
ifV(isset {S^POSTi;1submit1
1
J5
// Conecta-se ao banco de dados
Se o usuário «ao estiver
iodado, verificar se ele
submeteu dados de lo^in.
$dbc = mysqli_connect(DB_HOST, DEMJSER, DB_PASSWORD, DB_NAME);
// Obtém os dados de login digitados pelo usuário .
. .
$ u se r_ u se r n a m e = m y s q li_ r e a l_ e s c a p e _ s t r in g { $ d b c , tri^ $^ E iQ S Í;r.'!üSernam e 1] ) ) ;
$ u s e r _ p a ssw o r d = m y s q li_ r e a l_ e s c a p e _ s t r in g ( $ d b c , trim l^ ^ ^ fer^ p às^ W ord ''* ] } ) ;
{
if (!empty($user_username) && !empty ($user_password))
// Procura o nome e a senha no banco de dados
$query = "SELECT user_id, username FROM mismatchjjser WHERE username =
••password - SHA('Çu«rj,a,s„ord')-; ftl» « » * < •
$ d a ta = m y s q li q u e r y ($ d b c , $ q u ery ) ; a ? * J n
a^ora vem de P0ST, e *3o de um
a
if (mysqli_num_rows ($data) = = 1 ) { i^elâ d c a u t c n t i ^ â O
/ / O login foi bem-sucedido, portanto definir os cooKles de ID e nome do
usuário e redirecionar para a home page
$row - mysqli fetch_array ($data) ; ^Fâáa loAin do usuirío dfíinmdo
•- -
seteopkiél^sèítági^^
-Çhpíae'.nrl ■
is
ípindèx .php'*
■ h e á c ^ r f t L o G a t i o n ; , ; ■
' *s Redirefiiow: o usuário para
ilse{ ^'■~~^a bome fa^e do Mismâttb
// 0 nome/senha estão incorretos, portanto definir uma mensqjj^gg Su£edido-
rric^rr — 1Hq c
í-/~
<
i11 ^-í rrS i-a v irm ri/'-vmA o ■conVi 3 Tr^l r^a ‘7tz>Y%1r v n n * í
os Ûookies user_id e user«ame.
Çsrror msg =
}
else
válidos para fazer login.
// 0 nome/senha não foram digitados, portanto definir uma mensagem de
$error_msg = ’Desculpe, você deve digitar seu nome e senha para fazer login
<html>
<head>
<title>Mismatch - Log In</title>
<link rel=”stylesheet" type="text/css" href-"style.ess" />
</head>
<body>
<h3>Mismatch - Log In</h3>do«tmua n
âpagina d iâd
Deíi*a a variável da
mensagem de erro c
a
s
o
aígo
esteja errado dom os dados
de login.
0 sírift de login agora e
k um
a ’
«eb tomfWa
pertânto de requer todos os
demente* HTML padrões-
criando aplicações web personalizadas
/ / Se o c o o k ie e s t i v e r v a z io , e x i b i r m ensagem de e r r o (s e h o u v er) e o fo r m u lá r io d e
lo g in ; c a s o c o n t r á r io , c o n fir m a r lo g i n
r^/^v4ii3ifiiííííuíil«llll^lí»ííiií£íí2ffiilfíiy-'1 •: ■
<?php
?>
<form m eth o d = " p o st" a c tio n = " < ? p h p e ch o $ _ S E R V E R [ 1PHP_SELFV
< f i e l d s e t >
< ieg en d > L o g I n < /le g e n d >
< la b e l for="u sernam e">N om e d e U s u á r i o : < /la b e l>
yiimli
Sc o usuário âmdá r
is
o
estiver logado «este ponto»
exibir 3 »ervagem de erro.
?>">
<ííiput;.,Í "text
value="',
<?php ,
i
'
f
. (^user^uSerngmi lisé-Enáme;. ; '/X fe r . />
< la b e l fo r = " p a ss w o r d " > S e n h a :< /la b e l>
■
<input':;tiype=‘'pás.éwèrd'?''.V..................
< / f Í :
e ld s 'e t> '....
< in p u t ty p e= " su b m it" v a lu e = " L o g In" nam e=" sub m it" />
Tudo ^ue ven» antes desta dhave ainda
<?php ^ parte da primeira dáusula ií
e l s e f
■ //■ C o n firm a ■o la g ijír
echoi’< p  cÍass=*l^fi3?f:K
Estes dois dampos do
•formulário s3o usados
para o usuirio digitar o
n
o
m
eea senha.
r
< /b od y>
< /h tm l>
Finalize o óódigo HTAIL para
dompietar a página web de logm.
P:Por que é necessário
armazenar tanto a ID quanto o
nome do usuário em cookies?
í { l Uma vez que essas
duas informações identificam
individualmente os usuários dentro
do banco de dados do Mismatch,
você poderia usar apenas uma das
duas como propósito de manter a
aplicação sabendo queméo usuário
logado. Porém, userjd é uma
referência melhor (mais eficiente)
noque diz respeito ao bancode
dados, porque é uma chave primária
numérica. Por outro lado, userjd
é pouco informativa e nãotem
nenhumsignificado para o usuário,
portanto o username éútil para o
usuário saber que está logado, pois
ele vê o seu próprio nome na página.
Uma vez queocorre de várias
pessoas compartilharem o mesmo
computador, é importante nãosó
existem
P e r g u n t a s i d i o t a s
informar ao usuário que ele está
logado, mas tambémqual é o nome
que está logado.
- Então por que não
armazenar também a senha em
um cookie, como parte dos dados
de login?
f^lAsenha só é importante para
verificar inicialmente se o usuário
realmente é quemelediz ser. Uma
vezque o processo de login verifica
a senha, não há motivo para mantê-
laemjogo. Além disso, senhas são
dados muito sensíveis, portanto
é uma boa ideia evitar armazená-
las temporariamente sempre que
possível.
Se o usuário estiver locado
neste ponto, informe-o disso.
- Parece que o formulário do
script de login está dentro da
declaração if? Isso é possível?
l  l Sim. Na verdade, é bem
comumver código PHP "dividido"
emtorno de código HMTL, como
acontece no script de login. Só
porque você fechou uma seção de
código PHP com?>, não quer dizer
que a íógica do código está fechada.
Quando você abre ouíra seção de
código PHP com <?php, a lógica
continua exatamente de onde parou.
No script de login, oformulário
HTML é contido dentro da primeira
ramificação de if, enquanto que a
ramificação else aparece depois do
código do formulário. Dividir código
PHP comcódigo HTML, desta
forma, evita que você tenha de
gerar oformulário comummonte de
instruções echo confusas.
você está aqui ► 3 8 1
menu dinâmico do mismatch
Navegando na aplicação Mismatch
O novo script de login modifica o fluxo da aplicação Mismatch, passando a requerer um
menu simples que apareça na home page (index.php).Esse menu é importante porque
fo rn e c e acesso às d ife re n te s p artes p rin cip ais d a ap lica çã o , atualmente as páginas Ver Perfil
e Editar Perfil, bem como a possibilidade de os usuários fazerem login, se cadastrarem e
fazerem logoiit, dependendo dos seus estados de login atuais. O fato de que o menu se
modifica com base no estado de login do usuário é significativo, e em última análise, é o
que dá ao menu o seu poder e a sua utilidade.
Bsie menu afâveíc
guando o usuário
nao csbá locado,
dando a eíe a
oportunidade de
íâzcr ío^tn ou se
£adastvar
Uïn menu di-kv-ente t
**orbrado defendendo de
se o dookie username está
de-finido ou ndo-
0 sdirípt indcíC.
pH
p sabe <
^
u
e deve
mostrâr o raçnu
imitado guando nio
donseguir endontrav
o dookie uscvname.
O menu é gerado por código PHP dentro do script index.php, e esse código usa a
superglobal $_COOKIE para procurar o cookie username e ver se o usuário está logado ou
não. O cookie com a ID do usuário poderia também ter sido usado, mas como o nome do
usuário é o mostrado no menu, faz mais sentido usá-lo.
criando aplicações web personalizadas
^Stanatch • ................
I* yicwj'iufhj " -;.. ";■:'k~ /;v ' : -  v i r - - '--a
I ^ rj<iiiJ'-:,'.:.K: ■
■
' : . : ^ x .rr^ -^ V ^ iS V .;
r u ~ ° ^ ,jr~ ^
Latestmembers: ; ’! 'y :^»"‘.
■
' ■>' s : / W í - s ^ - S S B sE s
. . .
.„. . I ...' ^toolcfç .,.■
.;■ ?j
■
;yl_' uséráâfoe ■
;■
■
v> . ■.•■'ytem'pii':."■r."
kjafc. :•• -n ..:•//» .'
j «
l
i r
£) dookic user__id r»3o e
usado pelos di£ere»vfc«s
»Cnus, »»as ãmdâ t
importante parâ â
persistentia do usuário no
M»s»*at£b.
user id = Ô tookie determina
<ua! menu é exibido
{ /
u s e r n a m e — s i d n e y k
/v
|eY
»
v
»para
usuirios locados.
_____. ü ) )
’&I10084; <a href="viewprofile.php">Ver Perfil<Vaxbr />';
'&#10084; <a href="editprofile .php">Editar PerttrK/aXbr />’;
’&#10084 ; <a href="logout.
php">Log Out (
' . username' 3
.
// Gera o menu de navegação
if (
isset ($■COÓKíE r*~
echo
echo
echo
')</a>1;
}
else {
echo ’&#10084; <a href="login.php">Log In</a><br />
echo 1&.#10084; <a href="signup .php">Cadastrar-se</a> 11
Os símbolos de doradoeziftbosjio
lado de £âda item do menu sSo ,
—
possibilitados por este dod'130 HTML,
<
^
u
e é suportado nâ maioria dos
navegadores-
Menu para
visitantes
íusuários ainda
«ao !o$ados).
você está aqui > 3 8 3
log out de usuários deletando cookies
O
Oi, lembra de
mim? Eu realmente,
realmente ainda preciso
fazer logout.
a
N ó s realm ente p re cisam o s perm itir que o s u suários
façam logout.
Os cookies facilitaram o login e a navegação no Mismatch, mas o nosso
propósito inteiro, ao mudarmos da autenticação HTTP para os cookies,
era permitir aos usuários fazerem logout. Nós precisamos de um novo
script de logout que apague os dois cookies (user ID e username),
para que o usuário não mais tenha acesso à aplicação. Isso impede
que alguém use o mesmo computador mais tarde e acesse os dados
privados do usuário.
Uma vez que não há nenhum componente de interface de usuário
envolvido na operação de logout, basta redirecionar o usuário para a
home page após o logout.
' t Sidney âindâ
está esperâttd©
pelo logout-
ô script de logout
apa^a os cookks de
io^m do usuário e
redíretíons pava a
W e page.
%
logout.php
criando aplicações web personalizadas
Fazer logout significa apagar cookies
Fazer o logout de um usuário envolve apagar os dois cookies que mantêm registro do
usuário. Isso é feito chamando-se a função setcookie(), e passando-se a ela uma data de
validade que faça os cookies serem apagados na data em questão.
setcookie(1username1
Ahov a a tw l S
n
m
ic
s rtoras
S '
* 8}) ;
—
V "
Este código define um prazo de validade de 8 horas no futuro,
o que significa que o cookie será automaticamente apagado 8
horas depois da hora atual. Mas nós queremos apagar o cookie
imediatamente, o que requer a definição do prazo de validade
para um momento no passado. Quanto tempo no passado não
importa muito - basta escolher um espaço de tempo qualquer,
digamos uma hora e subtraí-lo da hora atual.
setcookie(’username 1, 'sidneyk',
l>0 segundos ^ ^0 minutos ~ ^ 0 0
segundos, o da ur»a Hora no passado.
£sta expressão de-f»*€
um pra*o d« validade
<
^u
e v e 3 horas apo*
a hora atual
Yara apagai* um
c o o k ie , b a s ta
definir 9 seu
pta^P de validade
como mntempo
hp passado.
Estão faltando algumas partes do código do script de logout do Mismatch.
Escreva o código que está faltando, certificando-se de apagar os cookies antes
da página de logout ser redirecionada para a home page.
< ?p h p
/ / Se o u s u á r io e s t i v e r lo g a d o , a p a g a r o c o o k ie p a r a f a z e r o l o g o u t
i f ( ) {■
/ / A p aga o s c o o k i e s u s e r ID e u se r n a m e , d e f i n i n d o o s s e u s p r a z o s d e v a lid a d e com o
uma h o r a a t r á s (3 6 0 0 )
}
/ / R e d ir e c io n a p a r a a hom e p a g e
$ h o m e_ u rl = ' h t t p : / / ’ . $_SERVER[ 1HTTP_HOST'] . d irn am e($_S E R V E R [ ' PHP_SELF' ] ) .
í T*
h e a d e r ( ' L o c a t i o n : ' . $ h o m e _ u r l);
?>
você está aqui ► 385
o script completo logoutphp
Estão faltando algumas partes do código do script de logout do Mismatch.
Escreva o código que está faltando, certificando-se de apagar os cookies antes
da página de logout ser redirecionada para a home page. *
S o L u Ç ã o , *
usudVio se este à
^?p p estiver iodado-
// Se ousuário estiver logado, apagar o cookie para fazer o logout t
if (isset(f_C00^|£rusev_icn) ) {
// Apaga os cookies user ID e username, definindo os seus prazos de validade como
- UOO); Defwe t i i i tookie í^ o vwttndo - J W a
I Rcdiredioftá para a Kom
c paje do
É
/V]is»«aidK, ^we c L
o
n
sb
rw
à
èto
m
o
un»a URL absoluta.
Redireciona para a home page
ome_url = 'http://' . $__SERVER['K T T P _ H O S T '] . dirname($_SERVER['PHP_SELF']) .
nde*.pKp 1;
header {' Location: ' . $home_url) ; ^ ^bcÇaibo d
co
U
W
zX
$
oWSulta em o
?> navegador redírtóofcâr para outrâ página*
— ____T f e S T O R f V G --------------------------------
U se co ok ie s para adicionar a funcionalidade de logout ao M ism atch.
Modifique os scripts do Mismatch para que eles usem cookies para permitir que os
usuários façam login e logout (ou baixe os scripts do site da Alta Books, www.altabooks.
com.br). Deverão ser feitas modificações nos scripts index.php, login.php, logout.php,
editprofile.php e viewprofile.php. As modificações nos dois últimos são poucas e envolvem
principalmente modificar as referências das variáveis globais $userjd e $username para
que elas passem a usar a superglobal $_COOKIE.
Envie os scripts para o seu servidor web e depois abra a página principal do Mismatch
(index.php) em um navegador web. Tome nota do menu de navegação e depois clique no
link ”Log In" para entrar no sistema. Repare em como o script de login leva você de volta
à página principal, enquanto que o menu se modifica para refletir o seu status de logado.
Agora clique em "Log Out" para pulverizar os cookies e sair do sistema.
criando aplicações web personalizadas
Ou dookies sâo
íriâdos para
Os tookies sâ«
jogados íora para
«y*eaaplitaçao*e
es^ueta do usuário e
íaça o logout
na» existem
__r»cy esta ioníí«ie porque agora
ela pode íâzír logout e ler fierteza
de gue o seu períil do /V
fuaw
atfiH
Petrurrtas Ídipías ^ H®»w v * ” H
ní 
& enquanto ela estiver Wâ- 1
Então tudo o que é preciso fazer para o logout éapagar os cookies?
Sim. Os cookies são responsáveis por armazenar todas as informações de login do
Mismatch (IDe nome do usuário), de modo que apagá-los resulta emumlogout completo.
T * * Por que os cookies são definidos como vencendo uma hora atrás, para serem
apagados? Existe aigo significativo sobre o espaço de tempo de uma hora?
Não. Ocookie éautomaticamente apagado pelo navegador assimque oseu prazo
de validade vence. Assim, aoperação de apagar umcookie imediatamente exige que se
defina o prazo de validade como vencendo emalgummomento do passado. Uma hora (3600
segundos) é apenas umespaço de tempo arbitrário, escolhido para indicar consistentemente
que estamos apagando umcookie.
você está aqui ► 387
armazenando dados do usuário no servidor; ao invés no cliente
Bsfce Co uSu3vio do ATtsm
âtfiH
Jasoh, f í dc estaladas, dc
picrd‘
m$s e de ttoward Slcvn-
£!c dcsabiirb* os dookies
«o seu navegador, o <ue
reprcsewta «rr. ^voklcmâ pavâ
Oh-oh. Eu tenho os
cookies desabilítados
no meu navegador e
não consigo fazer fogin. E
agora, o que faço?
Umâ vez. <
^
w
Co
sí-ockies
estâo dcsabiivtados,
o sdrípl -falKa t
simplesmente e*v>a
u
ss/3v*o dc vol-fca 3 Ho»«€
sc»* -fasev o logjm*
0 «ave^adov rejei-fca os dookies,
pedindo <ue o sdHpi dc loai*
os deW ^
0 sevvidor 'teftla
definir os dookies
de !P e dc r)o»e do
uswáno no «ave^ador-
Quem se importa
com o Jason? Não é
verdade que a maioria das pessoas
tem os cookies habilitados?
Sim , m a s a s a p lica çõ e s w eb devem se r o m ais
a c e ssív e is ao m aior núm ero de p e sso a s possível.
Algumas pessoas simplesmente não se sentem àvontade para usar
cookies, então elas optam pela segurança de desabilitá-los. Sabendo
disso, vale a pena tentar acomodar os usuários que não terão a opção
de usar cookies para o login. Mas tem mais: acontece que há outra
opção que usa o servidor para armazenar os dados de login, em vez
de usar o cliente. E umavez que os nossos scriptsjá estão rodando no
servidor, faz sentido armazenar também dados de login nele.
criando aplicações web personalizadas
As sessões não dependem do cliente
Os cookies são coisinhas poderosas, mas têm as suas
limitações, como por exemplo, ficarem sujeitos a limitações
que vão além do seu controle. Mas e se não tivéssemos
de depender do navegador? E se pudéssemos armazenar
dados diretamente no servidor? As sessões fazemjustamente
isso, e lhe permitem armazenar pedaços individuais de
informações da mesma forma que os cookies, mas os dados
são armazenados no servidor em vez de no cliente. Isso
coloca os dados das sessões fora dos limites impostos pelo
navegador aos cookies.
As sesspes ljie
p e rm ite m a rm a z e n a r
persistentemente
p e^ u en P S
pedaços cie dadPS
np serYidpr,
Independentemente
dp cliente.
Servid or w eb
Armazena dados em
cookies
Ao tm brèrio dos Êookies,
ôs sessões a r m a o s
seus dados n© servidor.
Obtém dados a partir
de c o o k ie s
0 navegador nao
ifcteríere d ire ta ^ te
na armaz^agem dos
dados de sess3es> uma
vez. tudo íifiano
servidor.
As sessões armazenam dados em variáveis de sessão, que são
os equivalentes lógicos dos cookies no servidor. Quando
você coloca dados em uma variável de sessão usando código
PHP, eles são armazenados no servidor. Você pode então
acessar os dados na variável de sessão a partir de código
PHP, e eles continuam persistentes ao longo de várias
páginas (scripts).Como no caso dos cookies, você pode
apagar uma variável de sessão a qualquer momento, o que
nos possibilita continuarmos a oferecer o recurso de logout
com código baseado em sessões.
Certamente existe alguma desvantagem, certo? Mais
ou menos. Ao contrário dos cookies, as sessões não
oferecem tanto controle sobre o tempo durante o qual
a variável de sessão armazenará os dados. Asvariáveis
de sessão são automaticamente destruídas assim que a
sessão termina, o que em geral, coincide com o ato de o
usuário fechar o navegador. Assim, embora as variáveis
de sessão não sejam armazenadas no navegador, elas
são afetadas indiretamente por ele, uma vez que são
apagadas quando a sessão do navegar finaliza.
N avegador
w eb do cliente
Uma Vez*<JuePs
dadps de sesspes
sâp armazenados np
serVidpr, eles sãp
ma!s seffurps e mais
cpníiáVefs dp c[ue
dadps armazenadps
em cookfes.
0 usuirio hão e fiapaz. de
apagar dados de sessões
**a*ualme»-fce tom o seu
have9adorJ ® ^ue pode ser
w* problema ^ua»do se usam
cookies.
Kao bá um praz« de
validade assodiado tom as
variáveis de sessão, porque
elas são automaticamente
apagadas guando a sessão
termina-
você está aqui ► 389
as funções sessionjstart{) e sessfon destroyQ
A vida e a obra das sessões
As sessões recebem esse nome por um motivo —elas
têm um início e um fim muito claros. Os dados
associad os co m u m a sessão vivem e morrem de acordo
com o tempo de vida da sessão, o qual você controla
através de código PHP. Aúnica situação em que você
não tem controle do ciclo de vida da sessão é quando
o usuário fecha o navegador, o que resulta no fim da
sessão, quer você goste disso ou não.
Você precisa informar à sessão quando estiver ponto
para iniciá-la, chamando a função PHP session_start().
A Çunção PHP
sessíP tL -S târtO toída
u m a se sse b e p e rm ite
C[ueVç>cecomece a
a rm a z e n a r d a d o s e m
VaríaVels da sessão
session_start () ; —
tsfca -Çu^ao PH?
} 0
3
u»a sessão
Servidor web
Chamar a função session_start() não define quaisquer
dados - a tarefa dela é apenas iniciar a sessão. A sessão
é identificada internamente por uma ID individual,
com a qual você geralmente não precisa se preocupar.
Essa ID é usada pelo navegador para associar uma
sessão com diversas páginas.
£sta é a IP da
sessão, *^
u
e e gerada
automaticamente
domo ^arte de C
è
d
â
nova sessa».
'ndex^pnpj
^uâhdo uma sessão
e ihidiadâ, ur»a IP
e deíinida para
identi-í-ifia-la
individualmente.
N avegad or
w eb do cliente
A IP da sessão e
usada no$ bastidores
para permitir «ue
diversas fainas
òompartilbem o acesso
âos dados da sessão-
viewprofile.php
editprofile.php
AID não é destruída até que a sessão seja finalizada, o que
acontece ou quando o navegador é fechado ou quando
você chama a função session_destroy().
session destroy();
Bsiâ -funÇâo PffP
-íinâlizj lAtnã sessêo.
A íunçãp sessi9n_
desfro/O îînalîza
a sessão-
Quando você fecha uma sessão com esta função, ela não
destrói automaticamente quaisquer variáveis de sessão
que você tenha armazenado. Vamos dar uma olhada com
mais detalhes no modo como as sessões armazenam dados,
para descobrir por que isso acontece.
criando aplicações web personalizadas
Mantendo-se atualizado com os dados das sessões
ú nome da variável da sessãoJ
e usado tomo um índifie para s
superglobal /_S£££Í0N'..,
O legal sobre as sessões é que elas sãobastante semelhantes aos cookies, em
termos de comovocê asusa. Umaveziniciadauma sessão com uma chamada
a session_start(), você pode começar a definir asvariáveis, como por exemplo
os dados de login do Mismatch, com a superglobal $_SESSION.
’sidneyJc’
0 valor a ser
armazenado e apenas
atribuído a superglobal
f_SÊSSÍ0K
echo (
'<p class="login">Você está logado c
c
a
t
i
o
'.</p>') ;
Ao contrário dos cookies, as variáveis de sessão não requerem
nenhum tipo de função especial para defini-las - basta atribuir um
valor à superglobal $_SESSION, certificando-se de usar o nome da
variável como o índice do array.
E quanto a apagar asvariáveis de sessão? Finalizar a sessão através
de session_destroy() não destrói as suas variáveis, portanto, você
precisa apagá-las manualmente se quiser que elas sejam eliminadas
antes de o usuário fechar o navegador (logout!).Uma forma rápida
e eficiente de destruir todas asvariáveis de uma sessão é definir a
superglobal $ SESSION como um arrayvazio.
A variável da
sessão e driada
t art*a«nada
no servidor-
$_SESSION = array(); fiódijo elimina -todas as
variáveis da sessão atual.
Mas isso ainda não é tudo. As sessões podem usar cookies
nos bastidores. Se o navegador os tiver habilitados, a sessão
pode definir um cookie para armazenar temporariamente a
ID da sessão. Assim, para fechar completamente uma sessão
via código PHP, você precisa também apagar qualquer cookie
que possa ter sido criado automaticamente para armazenar
essa ID no navegador. Como qualquer outro cookie, você o
destrói definindo o seu prazo de validade como um tempo no
passado. Tudo o que você precisa saber é o nome do cookie,
que pode ser descoberto usando-se a função session_name().
Í § É § « ~ - ; i •

Para aeessar a variavel
da sessão, basta usar a
superglobal fJS£££IOH e
o nom« da variável.
As VoriaVels
de sessão nS
jO
sã» apagadas
autornatícamerite
^uandp a sessã°
é desÇefta.
£e a sessão estiver usando
um tookte para ajudar
3 sc lembrâr da sua !Pj
e*tao a IP é arma^nâda
ern um dookie fcom
»esmo nome da sessão.
if (isset($ COOKIE!
setcookie
FVimeiramcrtte, veri-fi^ue
- realmente existe um dookie
da sessão-
£
« ] > > <
tim eO - 3 6 0 0 );
y * Destrua o dookie da sessão
( de-finindo o seu prazo de
validade para uma hora atrás.
você está aqui > 391
como o mismatch trabalha com sessões
Comeda a«u
'v
/
s e s s io n _ s ta rt() ;
%
£unÇao sessioh_stârtO
abre a sessão
Renove o Mism atch com as sessões
Repaginar a aplicação Mismatch para que ele use sessões
para armazenar dados de login não é tão complexo
quanto pode parecer. Na verdade, o fluxo da aplicação
se mantém quase o mesmo —você só precisa tomar um
pouco mais de cuidado nas operações de
iniciar e destruir a sessão e de limpar a
sujeira uma vez terminada a sessão.
As duas variáveis
da sessão sao
driadas para
ârma«narem 5
JP e o nome do
vtsvtino, para o
lojm-
session_destroy();
Se os dookies estiverem
habilitados, o servidor dria
m* para armazenar a IP
da sessão - daso dontrário,
a |P e passadajuntamente
dom a URL de dada página.
A-fwr^ao
session_
destro^O
-finaliza a sessão
iwpedmdo «ue
ela seja usada
em outrâ pagina
As variáveis da
sessão sao destruídas
limpando—
se o array
?_££££m
£
tum dookie tiver sido
usado para armazenar
a [D da sessão, ele e
destruído-
jOs dados do lo^in
Xí agora sao memorizados
usa«do-se uma sessão,
em vez. de dookies-
criando aplicações web personalizadas
Fapa Logout com sessões
Para se fazer o Iogout do usuário, é preciso um pouco mais de
trabalho com as sessões do que em versões anteriores, em que
usávamos apenas cookies. Estes passos precisam ser executados
para se fazer logout com sucesso, nas sessões do Mismatch.
Q A p a g a r a s variáveis da se ssã o .
Verificar se existe um cookie de
^ s e ssã o e, se existir, apagá-lo.
O Destruir a se ssã o .
0 Redirecionar o usuário à hom e page.
Aponte seu lápis
Sem veH-ftcav, vote «ao sâbev-a
dom ierteza se umdookie de
sessão esia sendo usado.
esse a^ul e um passo
na© essendal pava o logout
do usuaVio, mas é u-til de
^uai^wer iorma-
N T 0 script de logout do Mismatch está sendo reelaborado para
usar sessões, em vez de apenas cookies, para a persistência dos
logins. Escreva o código que está faltando para "sessionalizar" o
script, e depois escreva a qual passo do processo de logout cada
inserção corresponde.
<?php
// Se o usuário estiver logado, apagar as vars de sessão para fazer o logout
session_start();
if ( ............................... ) {
// Apaga as vars de sessão limpando o array $ SESSION,
// Apaga o cookie de sessão, definindo o seu prazo de validade como uma hora atrás (3600)
if (isset($ C O O K I E [session n a m e ()])) }
}
// Destrói a sessão
}
// Redireciona para a home page
$home_url = 'http://' . $ _ SERVER['H TTP _ H O S T '] . d i r n a m e ($ _ SERVER['P HP_SELF'] ) . '/
index.php';
h e a d e r {’Location : ' . $home_url);
?>
você está aqui ► 393
logout.php "sessionallzado "
t^ponte seu lápis
Solupão
O script de logout do Mismatch está sendo reelaborado para usar sessões,
em vez de apenas cookies, para a persistência dos logins. Escreva o código
que está faltando para "sessionalizar" o script, e depois escreva a qual
passo do processo de logout cada inserção corresponde.
©
©
J Apagar as variáveis cia sessão.
z ) Veri-fidar se existe umdookie de sessão e, se existir, apagá-lo.
Destruir d sessão
Rediretionar o usuário a home page-
Mesmo ao ía « r o logout, vote
tem de mitiar a sessão para poder
<, php atessar as variáveis.
/
// o usuário estiver logado, apagar as vars de sessão para fazer o logout
session^ttart o ; ------- Agora, esta sendo usada uma variável de sessão, em
if iketÇ s£S£|0N fuserJítt) ) ( VCi dc ur" Cock'*> P^ra verifidar o status do login.
// Apaga as vars de sessão limpando o array $_SESSION.
f_£6 ££l0 N =
• airayO; ^ ----- Para Uya" f
........................................... (j^) array «a^o a superglobal
// Apaga o cookie de sessão, definindo o seu prazo de validade como uma hora atrás (3600)
if (isset{$_COOKIE[session_name()])) {
settookiefsessiôh__hâmeO, w
, timeO —?>&Oõ);
Se existir um dookie da sessão,
apague-o, definindo o seu praza de
// Destrói a sessão validade domo uma hora atras,
session_destroyí)j Destrua a sessão dom uma
J
.............................. dhâmada a íunção sessioift__
destroyO.
l i Redireciona para a home page
$home_url = 'http://' . $_SERVER['HTTP_ H O S T 1] . dirname($_SERVER[’P H P_SELF’]) . '/
i n d e x .php1;
h e a d e r ('L o c a t i o n : ' . $home_url);
?>
■ ©
l A U M l 1
A mudança dos cookies para as sessões tem impacto sobre mais
coisas do que apenas o script de logout. Ligue cada parte da
aplicação Mismatch à modificação por que elas têm de passar
criando aplicações web personalizadas
connectvars.php
Nenhuma modificação, pois este script nao tem
influência direta na persistência dos logins.
As sessões precisam se lembrar de quem o usuário
é. Chame a função session_start() para iniciar
a sessão, e depois modifique as referências a $_
COOKIE para $_SESSION.
As sessões precisam controlar o menu de
navegação. Chame a função se ssio n -sta rt ()
para iniciar a sessão, e depois mude as referências
$-COOKIE por $-SESSION.
editprofile.php
você está aqui > 395
como Bu mudo solução
A mudança dos cookies para as sessões tem impacto sobre mais
coisas do que apenas o script de lo g o u t. L ig u e cad a p a rte da
aplicação Mismatch à modificação por que elas têm de passar
para acomodar as sessões.
Nenhuma modificação, pois este script
não tem influência direta na persistência
dos logins.
As sessões precisam se lembrar de quem o
usuário é. Chame a função session_start()
para iniciar a sessão, e depois modifique as
referências a $_COOKIE para $_SESSION.
As sessões precisam controlar o menu de
navegação. Chame a função session-
s ta rt () para iniciar a sessão, e depois
mude as referências $-COOKIE por
$-SESSION.
editprofile.php
criando aplicações web personalizadas
PONTOS DE BALA ----------------
■ Aautenticação HTTPé útil parase restringiro ■
acessoadeterminadas páginas, mas não oferece
nenhumaforma deo usuáriofazer "logout" após
terminar de acessara página. B
■ Os cookies lhe permitemarmazenar nocliente
(web browser) dados de pequeno porte, como por
exemplo, os dadosde logindos usuários.
■ Todosos cookies têmumprazode validade, que ■
podevencer numfuturo muitodistante ou então logo
ao final da sessão do navegador.
Paraapagar umcookie, basta definiro seu prazo de
validade paravencer emalgumtempo nopassado.
Assessõesoferecemrecursodearmazenamento
semelhanteaodoscookies, massãoarmazenadas
noservidore, portanto, nãoficamsujeitasàsmesmas
limitaçõesdonavegador- comoporexemplo, a
possibilidadedesedesabilitaroscookies.
Asvariáveisde sessão têmumtempode vida
limitado, esão sempre destruídas umavez
terminada asessão (por exemplo, quando o
navegador éfechado).
nã9 existem
F e r g u n ta s id io ta s
r • A função session_start() é
chamada em vários lugares diferentes,
mesmo depois de a sessão ter sido
iniciadas. Não estamos criando
múltiplas sessões com cada uma
dessas chamadas a session start()?
Não. A função session_start() não
serve apenas para iniciar uma nova sessão
- ela também trabalha com sessões
existentes. Assim, quando um script chama
session_start(), a função primeiramente
verifica se já existe uma sessão, o que
é evidenciado pela presença de uma ID
de sessão. Se não existir, a função gera
nova ID e cria a nova sessão. Chamadas
futuras a session^startQ vindas de dentro
da mesma aplicação irão reconhecera
sessão existente e irão usá-ia, em vez de
criar outra.
”
P• Como a ID da sessão é
armazenada? É nesse ponto que as
sessões às vezes usam cookies?
Sim. Embora os dados de sessões
sejam armazenados no servidor e,
portanto, tenham os beneficios de serem
mais seguros e ficarem fora do controle
do navegador, ainda precisa haver
um mecanismo para o script saber da
existência desses dados.
É para isso que serve a ID - identificar
individualmente a sessão e os dados
associados com ela. Essa ID precisa
persistir no cliente, de alguma forma,
para que várias páginas possam fazer
parte da mesma sessão. Uma forma pela
qual essa persistência da ÍD é executada
é através de um cookie, significando que
a ID é armazenada em um cookie, que
é então usado para associar um script a
uma determinada sessão.
P * Se as sessões ainda dependem
dos cookies desse jeito, qual é então
a grande vantagem de usá-las em vez
dos cookies?
As sessões não são inteiramente
dependentes dos cookies. É importante
entender que os cookies servem como uma
otimização para se preservar a ID da sessão
através de vários scripts, mas não como
uma necessidade. Se os cookies estiverem
desabilitados, a IDé passada de script
parar script através de uma URL, de forma
semelhante a como já vimos dados serem
transmitidos em uma requisição GET. Assim,
as sessões podem funcionar perfeitamente
sem cookies. Os detalhes sobre como as
sessões reagem em resposta aos cookies
estarem desabilitados são controlados no
arquivo de configuração php.ini presente
no servidor web, através das configurações
de session.use_cookies, session.use_oniy_
cookies e session.use_trans_sid.
P • Ainda parece estranho que as
sessões possam usar cookies, quando a
justificativa em usá-las é justamente que
elas supostamente são melhores que os
cookies. Qual é a explicação?
R:Embora as sessões de fato ofereçam
alguns benefícios claros em relação aos
cookies, em determinados cenários, elas
não necessariamente têm uma relação
mutuamente exdusiva com os cookies.
As sessões certamente têm o benefício
de ficarem armazenadas no servidor em
vez de no cliente, o que as toma mais
seguras e confiáveis. Assim, caso você
precise armazenar dados sensíveis de
forma persistente, uma variável de sessão
forneceria mais segurança do que um
cookie. As sessões também são capazes
de armazenar quantidades maiores de
dados do que os cookies. Portanto, existem
vantagens claras em se usar sessões,
independentemente de os cookies estarem
disponíveis ou não.
Para os propósitos do Mismatch, as
sessões oferecem uma conveniente solução
para se armazenar dados de login no lado
do servidor. Para os usuários que têm os
cookies habilitados, as sessões fornecem
melhor segurança e confiabilidade, ao
mesmo tempo ainda usando os cookies
como uma forma de otimização. E no
caso dos usuários que não têm cookies
habilitados, as sessões funcionam sem
serem afetadas, ao passarem a ID da
sessão através de uma URL, evitando os
cookies completamente.
você está aqui ► 397
migrando de cookies para sessões
Complete a sessão de transformações
Embora as diferentes partes do Mismatch afetadas pelas
sessões as usem para realizar coisas diferentes, em última
análise os scripts precisam de modificações semelhantes para
se fazer a migração dos cookies para as sessões. Por exemplo,
todos eles precisam chamar a função session_start() para
iniciar as sessões. Além disso, todas as modificações envolvem
a troca da superglobal $_COOKIE pela $_SESSION, que é
responsável por armazenar asvariáveis da sessão. Tõdos os sdHpb baseados em
sessões domeça* £om uma
chagada a sessio*_startO,
para inieiar a sessão
// Se o usuário não está logaáo, loga-o.
íf (!issetÇ$~SESSIOKf ’•
j
'
s
e
r
_idl
~Jj) {
if (isset (5_PCST [’submit' ])) {
// Coneta com o banco de dados
Sdbc = raysqIi_connect (DB^HOST, DB_USERr DS_PASSKORD, BB_NAME) ;
// Pega o dado do login digitado
$user_userna?r.e = mysqli_real_escape_string($diic, trim(S__POST['-asemame'])) ;
$’
jser_passworcS = mysqli_jreal_escape_string($dbc, trim ($_ECSTI ’
password']));
í (
!enpty ($’
jser username) && !empty (?user_password)) í
// Olha o usuário e senha no banco
$query = "SELECT user_id, username FROM mismatch_‘
Jsei
’
’
password = SHA( ’$user_password')
Sáata = mysi?ii_query ($dbcf Squery);
VÍHERE username = '$user_username AND
if (mysqlijrcum^rows($data) == 1) )
// 0 login é OK, defina a variável de sessãolD so none do usuário
$row = mysqll fetch array($data) ;
Çs SESSION [
'user" id = $row['user id']'
C H E E s I
(
!
i

j■
■'useinamc row['username'’;
$'ncme_url = 'http:/./' . $_SERVER['
KTT?_HOST 'j . dirname ($_SERVER L1?HP_3ELF'])
header(’Location: 1 . $home_url);
redireciona o/ hone page.
'/index.php’;
"// 0 usuário/senha estão incorretos, seta uma para f « « login.
Sector msg = ’Desculpe, você deve digitar ut, usuarro * senha ,QlrdO- para
0 sdript de lo«yn usa sessões para se
{embrar da IP e do «ome do usuário,
obtendo assim a persiste*£i3 do
îo^'m
, e o -(-az. usândo á superglobal
em vez- da
login.php
criando aplicações web personalizadas
lf ^65e^SESSI0MFUSer^ ^ . ', ,
echo ’s#iõu84; <a h-efS^vTS^Í, -■
i
echo 'ítlOOQí; <a hreí-"ed^r"fiTrP?P">VÍeW Profile</«><br />-;
echo '£*10084; e,php >Edlt Profiie</a><hr /%-.
- n-e- logout.pnp">Lcg out Cf. $ SESSTOMf. ^
[ username^i
else {
echo '&4I0Ü84; <a href="login.pnpT
,
>Lcç In</axtt />
echo '&#1008í; <a hre£=’
’
signup.php">Sign tfp<7a>';
)
// Varre c array de dados de usuário formatado para HTML
echc '<h4>Latest membÊrs:</h4>
'
e
c
.
h
o '<table>’;
while (?rcw = mysqli_fatch_array($õata)) {
if (
is3etffsESSIONf'userTdJ>
) (
echo '<tdxa hrei'=<
l
viewprõr±le.php?uEer_id=’ , $rowf ’
user_id'
] .
$row[’first^name'
J . '
c/ax/tdx/tr>'■
]
else (
')</a>'
echo '<td>' . 5rcw[
'first_name'] . '
</tdx/tr>';
i
echo '</table>';
A home pa$e ^°
|7Vfis«*atdh usa
|a superglobal
Í/JSESSION em
fvez. de f__Cí)0^!£
para adessar dados
de lo^hj ao mesmo
temp© em «ue jera
o menu e dedide se
deve ou nâo exibir
um !‘
mk para os
per£is dos membros
mais redewtes.
Semelhahie a pa^i^a de lo^m e a home pa^e, o
sdript Editar Per-Ç
i! agora usa f__S£S£f0N em
vez. de f_C00£ífc para adessar os dados de
|oõ|m.
index.php
// r^^antirJ-.» o usuário está logado.
- <'
iq
s
p
t
-«
g
"
f
i
F
,
5
SIONi 'user id']H> t ,.
echo '<p class="login">Please <a href="login.piip">log i.K/a> to access tnis page.</p>
exit (
);
^else
echo('<p class="login">You are logged in as ’ .^^SESSIONÍ1
userr.ame’
T'X
<a href“"logout.php">Log out</a>.
</p>'
)
; — ------ —
if (
!empty ($£irst_na;ne) && íempty ($last_name) && !
errpty (Sgender) £
•
£ !empty(íbirthdate) &&
!
empty{$eity) &£ !
empty(Sstate)) (
// Apenas seta a coluna picture se existir -
j
i
c
a foto nova-
if (!empty(Snew_picture)) {
$query = "UPDATE mismatch_user SET first_name = '$first_name ’, last_nartte = '$last_name
"çender = 'Sgersder’, birthdate = 'çbirthdate', city ~ 'Scitv1. state = 1Sstate', " .
"picture = '?new_pioture 1 WHERE user_id = -
Ç* SESSION [
'user_idH~~~'>y''";
else {
Squery - "UPDATE mismatch_'aser SET first_ne.Tie = '
$first_name', last_narae = '$last_name1
"gender = ’
$gender', birthdate - ’$fcirthda.te',city = '$city', state = 'Sstate' " .
“MRERE user_id = -
^.SESSION [1
user
mysqii_que:y(Sdbc, $query);
viewprofile.php
Bmbora y»ao esteja
sendo mostrado, o sdript
/er Períil usa sessões
pratidâmcnte da mesma
íormâ «ue tditar PerliL
você está aqui ► 399
convera informal entre cookie e varíavel de sessão
Conversa Informal
Conversa de hoje: Cookie e variável
de sessão discutem quem tem a
melhor memória.
Cookie: Variável de sessão:
Temhavido muitaconversa aqui entre nós,
cookies, sobre oque exatamente estáacontecendo
aí no servidor. Os boatos dão conta quevocê
está tentando entrarno nosso território eroubar
nossosempregos de armazenamento de dados.
Qual éa história?
Espera aí, roubar éuma palavra muito séria. A
verdade é que àsvezes simplesmente fazmais
sentido armazenar os dados no servidor.
Não faz nenhum sentido para mim. O
navegador é um lugar perfeitamente bom para
se armazenar dados, e eu sou o cara perfeito
para fazer esse trabalho.
Mas e se o usuário te desabilitar?
Ahn, bem, essaé outra história. Seousuário decidir
me desabilitar, então claramente elenão tem
nenhuma necessidade de armazenar dados.
Nãoéverdade. O usuáriofrequentemente nem
sabeque aaplicaçãowebestáarmazenandodados,
porque, emmuitoscasos,sãodadosque sóficam
nosbastidores, como por exemplo, osnomes de
usuário. Assim,sevocê não estiverdisponível, ele
acabasemnada.
Então eu suponho que asuarespostaé armazenar
osdadosno servidor? Que conveniente.
Exatamente. Eo legal é que o usuário não tem
como desabilitar nada no servidor, assimvocê não
precisa se preocupar se os dados poderão ou não
realmente ser armazenados.
Ok, gênio.Já quevocêparece ter soluçãopara
tudo, por que é que você, àsvezes, aindame usa
para armazenar asuapreciosaID no navegador?
Er, bem, a maioria das pessoas não sabe disso,
portanto não precisamos falar disso aqui.
Podemos falar disso fora do microfone. O mais
importante é que eu estou sempre alerta, pronto
para armazenar dados no servidor.
criando aplicações web personalizadas
Cookie: Variável de sessão:
Não senhor, diga a todos o quanto você precisa
de mim!
Espera aí, roubar é uma palavra muito séria. A
verdade é que àsvezes simplesmente faz mais
sentido armazenar os dados no servidor.
Ah, eu sei que pode, mas a verdade é que
prefere depender de mim. E, no fundo, talvez
até goste de mim.
Olhe, eu não tenho nenhum problema com você.
Só gostaria que fosse um pouco mais seguro. E
você tem aquela limitação para o tamanho dos
dados, que nem sempre são tão pequenos.
Ah, então agora vocêvai me tirar só porque
eu sou pequeno. Ok; posso não ser capaz de
armazenar tanto quanto você, e admito que viver
no cliente me toma um pouco menos seguro.
Mas com certeza é mais emocionante! E eu
tenho algo com que você só pode sonhar.
Ah, sim? E o que seria?
Bem, todo esseespaçode armazenamento e
segurança de que vocêse orgulha tanto têm um
custo... uma vida breve! Eu não queria ter de te
dizer, mastoda asua existêncianão ultrapassa a
duração de umasessão do navegador.Acho que é
daíque vemo seu nome.
Quer dizer que você pode viver além de uma
única sessão? Como isso é possível?!
Esimples. Eu não sou destruídojunto com a
sessão, apenas termino omeu prazo devalidade.
Assim, posso serconfigurado paraviverumavida
longa epróspera, muito maislonga do que o
determinado poralgum suiüsta felizdaweb que
achabonito abrir efechar onavegadora cada
oportunidade que tem.
Uau. Aimortalidade deve sersensacional. A
minha únicaesperança é que algum programador
preguiçoso acidentalmente se esqueça de me
destruiraofechara sessão... mas onavegador
aindavaiacabar comigoassimque forfechado.
Oproblemaé que essesmesmosprogramadores
frequentemente definem omeu prazodevalidade
comum período tão curto que naverdade eunão
chegoa experimentaravidalongaque mereço.
Quer dizer, eu...
Alô?Você está aí? Caramba, esse negócio de
prazo de validade é sério mesmo.
você está aqui ► 401
test drive the "sessionaHzado" mismatch
T f e S T O R t v e
M odifique o M ism atch para u sar se s s õ e s em vez de cookies.
Modifique os scripts do Mismatch de modo que eles passem a usar sessões, em vez de
cookies, para implementar a persistência do login (ou baixe os scripts do site da Alta
Books, www.altabooks.com.br). Isso envolverá modificações nos scripts index.php, login.
php, logout.php, editprofile.php e viewprofile.php, principalmente para iniciar a sessão
com uma chamada à função session_start() e trocar as referências à superglobal $_
COOKIE por referências a $_SESSION.
Envie os scripts para o seu servidor web e depois abra a página principal do Mismatch
(index.php) em um navegador web. Tente fazer login e logout para se certificar de que
tudo funciona como antes. A não ser que tivesse os cookies desabilitados antes, você não
deverá perceber nenhuma diferença —isso é bom!
criando aplicações web personalizadas
!' Para as sessões poderem funcionar com os cookies
desabilitados, precisa haver outro mecanismo para se enviar
A s se s s õ e s sem co o k ie s poderão não funcionar
se php.ini não estiver devidam ente configurado
no servidor.
a ID da sessão de uma página para outra. Esse mecanismo envolve a
anexação da ID à URL de cada página, o que ocorre automaticamente
caso session.use_trans_id esteja defínida como 1 (true) no arquivo php.
ini do servidor. Se você não tiver a capacidade de alterar esse arquivo
no seu servidor web, terá de anexar manualmente a ID à URL das
páginas da sessão, caso os cookie estejam desabilitados, usando um
código como este:
sc
s
s
à
o
,a <uai tenviada ífo-avés da
URL fè
ra<ue a fá$inâ EdvUr Perlil
sâiba da e*isfcen£ia da sessão.
você está aqui ► 403
porque o logout automático?
Os usuários não estão se sentindo
bew-vindos
A p esar d e ser u m b o m aprimoramento em relação
aos cookies, algo não está muito certo com a nova
aplicação Mismatch baseada em sessões. Vários
usuários relataram que estão sendo deslogados do
aplicativo apesar de não terem clicado no link "Log
Out". A aplicação não parece mais tão amistosa... isso é
um grande problema.
UsiASrie
■
Çrvsb-adô fMntè
t âi^o b
o
*
*
»
0s usuivios esèâo sehdo
deslocados do /VJismaidH
stm tév ilidado no tmk w
Loft
0ut'
criando aplicações web personalizadas
4 > 0 ____________
c x t c é r é w q
O que você acha que está fazendo
os usuários serem desiogados
automaticamente do Mismatch? Será
algo que eles estão fazendo sem saber?
você está aqui ► 405
o tempo de vida dos cookies e sessões
As sessões têm vida curta...
O problema com os logouts automáticos no Mismatch tem
a ver com o tempo de vida limitado das sessões. Como
v o cê deve se lem b rar, as sessões só duram pelo tempo em
que a instância atual do navegador permanece aberta,
significando que todas asvariáveis da sessão são eliminadas
quando o usuário fecha o navegador. Em outras palavras,
fechar o navegador resulta em o usuário ser deslogado,
independentemente de ele gostar disso ou não. Isso não
só é inconveniente, como também é um pouco confuso,
uma vez quejá temos um recurso de logout. Os usuários
presumem que não sairão do sistema a não ser que
cliquem deliberadamente no link Log Out.
__^ tom ressoes resulta *a driaça©
de duâs variaveis de sessão.
Esíejâ voôe usando sessões
O
MCookies, o prodesso de
« o 1« o *odo
persisie»te na aplidaça©.
U»â vez. destruídas
as variáveis da sessão,
o usuário e deslocado-
t^uer queira? *s*er n3o!
M variaveis sao
destruídas junto dom
a sessão, guando o "X
«avegador t -fedhada 
0 usuário íedha _
i^vejador, *»as pode *ao
perceber *^
u
e âdabou de
se desiogar do sistema.
Embora você possa destruir uma sessão ao terminar de
usá-la, não pode prolongar a sua existência para além
da instância do navegador. Assim, as sessões são uma
solução de armazenamento de prazo mais curto do
que os cookies, uma vez que estes podem ter uma data
de validade definida para daqui a horas, dias, meses
ou anos. Isso significa que as sessões são inferiores aos
cookies? Não, dejeito nenhum. Mas significa que as
sessões apresentam um problema caso você precise
memorizar informações para além de uma instância
do navegador... como é o caso dos dados de login!
As variáveis
de sessão sã°
d e stru íd a s «JUctndp
p usuárxp íinalíza a
sessãp fee])and° 9
naVegadpr.
criando apficações web personalizadas
^ -----------
...mas os cookies podem durar para sempre!
Ao contrário das variáveis de sessão, o tempo de vida de um
cookie não fica limitado à instância do navegador; assim, os
cookies podem continuar vivendo, pelo menos até vencer o
seu prazo de validade. O problema é que os usuários têm
a capacidade de destruir todos os cookies armazenados na
sua máquina com uma simples configuração do navegador,
portanto, não fique muito contente com a permanência dos
cookies - de uma forma ou de outra, eles ainda se prestam
apenas para o armazenamento de dados temporários.
lãivez. «ao para sempre,
mSs íempo su-Pidichte
para durar »dis do
*
V
*
e 3 sessão.
^ De -forma
se»e!ha«-fce às
sessões, os doeíties
sâo driâdos ho
w>on>eivèo d
olo^ih.

I
I
/
0% dookies só sao
destruídos *^u3w
do
o seu prâzo de
vâlidâde e-^fíra-
0 de vida do dookie
é detevWinado pe!o seu
pvâzo de validade.
Ce^ldes são desítuídes
guando a sua Validade
expira, o lJue dá a eles
um tempo de vida mais
lo n g o d o Lju e a s V a r iá v e is
de sessão.
você está aqui > 407
usando cookies e sessões em paralelo
Então faria sentido
usar tanto sessões
quanto cookies, sendo que esses
ajudariam a manter os usuários íogados
por períodos de tempo mais longo? Isso
funcionaria para os usuários que têm
os cookies habilitados.
Desde «ue não esteja lidando tom dados
al-bmente sensíveis, ew Cujo tèso a W itè
seaurança dos òookies seria u» argumento fâra se
redowendar o uso apenas das sessões.
Sim , não há nada errado em tirar proveito d a s
va n ta ge n s d a s s e s s õ e s e d o s co o k ie s para
tornar o s lo gin s do M ism atcti m a is flexíveis.
Na verdade, isso pode ser bastante útil. As sessões são
melhores para a persistência de curto prazo, uma vez que
elas são mais amplamente suportadas e não se limitam
pelo navegador, enquanto que os cookies permitem que
você mantenha os dados de Iogin memorizados por um
período de tempo mais longo. Certamente que nem todo
mundo poderá se beneficiar do uso dos cookies, mas
será benéfico para muitas pessoas, o quejustifica esse uso.
Sempre que puder aprimorar a experiência de usuário
para uma parte significativa da sua base de usuários sem
piorar para os outros, é bom fazê-lo.
criando aplicações web personalizadas
Sessões + Cookies * Persistência de login superior
Para a melhor persistência de login possível, você precisa ser criativo e combinar
tudo o que aprendeu neste capítulo para tirar proveito dos benefícios tanto das
sessões quanto dos cookies. Ao fazer isso, pode reestruturar a aplicação Mismatch
de modo que ela tenha o melhor desempenho possível tanto na persistência de
login de curto prazo quanto na de longo prazo. $ua*do ' £
idnío âs vanlvfiis da
os eookies sâo
j para » rto to a ***
^ a IP e ° do usuário-
^ave^âdov v/cb,
finalizando
Os dados de So^in
avmâz^nâdos nos dookics
sao usados pârâ SC
*as vaviávcis da sessão. s
Bvm vez. de mânter os usuários
logados para sempre, os ôookles
sáo destruídos 10 dias depois.
você está aqui > 409
não existem perguntas idiotas sobre cookies e sessões
m9 existem
fe rg u rríc L s I d io ta s
~L - Então a razão para se optar entresessões e cookies é a questão
persistência de curto x de longo prazo?
Não. Essa por acaso acabou sendo aestratégia que ajudou aguiar o
design da aplicação Mismatch, mas cada aplicação é diferente, eexistem
outros aspectos das sessões e dos cookies que frequentemente precisamser
ponderados. Por exemplo, os dados armazenados em uma sessão são mais
seguros do que aqueles armazenados em umcookie. Assim, mesmo que os
cookies estejam habilitados e umdeles esteja sendo usado unicamente para
manter registro da IDda sessão, os dados armazenados na sessão propriamente
dita são mais seguros do que se estivessem armazenados diretamente emum
cookie. Omotivo éque os dados das sessões sãoarmazenados no servidor, o
que torna bastante difícil seremacessados por usuários que nãotenham os
devidos privilégios. Assim, se você estiver lidando comdados que precisem ser
seguros, as sessões são mais apropriadas que os cookies.
T * - E quanto ao tamanho dos dados? Isso tem alguma influência?
Sim, otamanho dos dados tambémfaz diferença. As sessões são capazes
de armazenar pedaços de dados maiores do que os cookies conseguem, portanto
essa éoutra razão para preferir as sessões caso você precise armazenar dados
maiores doque algumas strings de texto simples. Éclaro que umbanco dedados
MySQLéainda melhor para armazenar dados muitograndes, portanto cuidado
para não se animar demais ao trabalhar comsessões.
> Então por que eu deveria optar por uma sessão ou um cookie em vez
de um banco de dados MySQL?
Conveniência. Armazenar dados emumbanco demanda muito mais esforço,
e não se esqueça de que os bancos são mais adequados para armazenar dados
permanentes. Dados de login nãosão realmente permanentes, numcontexto mais
amplo. Éaí que os cookies e as sessões entram emjogo - eies são melhores
para dados que você precisa ter memorizados por umcurto período de tempo, e
depoisjogados fora.
Imas de Greladeítct dç>
Aaplicação Mismatch foi reelaborada para usarsessõesecookies ao
mesmo tempo, com o objetivo de conseguiramelhor persistência
de login possível. Oproblema éque parte do código estáfaltando.
Useos imasde sessõesede cookies para completar o código.
criando aplicações web personalizadas
if (mysqli_num_rows ($data) — 1) {
// Login OK, definir as vars de sessão (e os cookies) de ID e nome do usuário,
// e depois redirecionar para a home page
$row = mysqli_fetch_array($data);
['user id'] = S r o w [’u s e r _ r d '];
[’u s e r n a m e ’] = $ r o w ['u s e r n a m e '];
'
set coo ki e (''user_id', $row ['user_id' ], time (
) + (60 * 60 * 24 * 30)); // expira em 30 dias
setcookie(’username’, $row[ ’username'], time (
) + (60 * 60 * 24 * 30) ); // expira em 30 dias
$home uri = ’h t t p : / / ’ - $ _ S E R V E R [’HTTP_ H O S T ’] . d i r n a m e ($ _ S E R V E R ['P H P _ S E L F ']) . ’/
index.php’;
header (’L o c a t i o n : 1 . $horae_url) ;
login.f |p
<?php : ‘ ~ ‘ -------
s e s s i o n - s t a r t ^ ® st^ver apagar as vara de sessão para fazer o logout
if (isset(................. [iu s e r _ i d []) ) {
// Apaga as vars de sessão limpando o array $ SESSION
................= array (
) ;
// Apaga o cookie de sessão, definindo o seu prazo de validade como uma hora atrás (3600;
if (isset( ................[session_name (
) ])) (
setcookie(session_name(), time() -3600);
// Destrói a sessão
session^destroy();
ÍLT?3Z>°°k
Íe
Sde ID 6 de "0me d° USUárl°' definind° 05 de validade como uma hora
setco o k i e (’u s e r _ i d ’, time 0 -3600);
setcookie ('username', time() - 3600);
logout,php
I
<?php
session_start ();
// Se as vars de sessão não estiverem definidas, tentar defini-las com
if (!isset ( ..............
(issetí ['user_id']) && isset (
_l 'u s e r _ i d '] =
1u s e r n a m e '] -
Inicis de Geladeira d v f [ í f - Solução
A aplicação Mismatch foi reelaborada para usar sessões e cookies ao mesmo tempo,
com o objetivo de conseguir a melhor persistência de login possível. 0 problema
é que parte do código está faltando. Use os imas de sessões e de cookies para
completar o código.
$ SESSION
if ( m y s q l i n u m _ r o w s ( $ d a t a ) — 1 ) { _
/ / // Login OK, definir as vars de sessão (e os cookies) de i d e nome do u s u a n o ,
// e depois redirecionar para a home page
$row = mysqli_fetch__array ($data) ;
O
snoves dookies s
â
o
[ ' u s e r _ i d ' ] = $row [ ’u s e r _ i d ’ ] ; d e iiw d o s, âl«w d â s
$ SESSION S j. <usernam e' ] = $row [ ’usernam e' ] ; ^ Vâriaveis dâ ses$a©.
setcookie('user_id’, $row[' userid' ], time (
) + (60 * 60 * 24 * 30) ); // expira em 30 dias
setcookie (’username ', $row [’username’], time (
) + (60 * 60 * 24 * 30)■ ; i / expira em 30 dia
$home url = ’ h t t p : / / ’ - $ _ S E R V E R ['HTTP_ H 0 S T 1] . d i r n a m e ($_SE R V E R [ PHP_SELF ]) . /
index.php’;
h e a d e r (’Location : ' . $home_url);
usuário estiver logado, apagar as vars de sessão para faser o logout
+
■^ v
“+
- /  ♦
<?php
// Se o
s e ssion_start{);
if <isset(j $_SESSION M ' u se r_ i d ' ])) {
// Apaga a s Wr'à"3g"£<?§^io limpando o array $_SESSION
a r r a y ();
login.f
$ SESSION
/ / Apaga o cookie de sessão, def:
. . . ^ , i $ COOKIE
if ( i s s e t ( L _ ^ ^
tinindo o seu prazo de validade como uma hora atrás (3600)
|tsession_name ()])){ ^ ^ 0
setcookie (session_name (
) , 11, time (
) - 3600) ; ^ " logout, C pVCdiSO âpa^âr
^ taivbo o ôookic da
// Destrói a sessão w . ±
session_destroy (
) ; .SC£S3o ^uânxo O
) / dookies d« l
o
j
í
i
r
»
.
// Apaga os cookies de id e de n o m e do usuário, definind'
uma hora atrás (3600)
setcookie ('user_id’, ’', time (
) - 3600); Câso o wsuirio t^ao «st«a
setcookie ('username', ’ ’, time (
) - 3600) ;^ Ic ^ d o atrâv« da StSSèo,
______________________ verilidav *r f —
logoutfphp
os seus prazos de validade como
e
siâ
cd
e
fin
id
o
s
.
<?php
session_start();
// Se a s vars de sessão não estiverem definidas, tentar defini-las com um coofclí
§[ 'user_id' ]))
M ' u s e r id' ]) && isset (
'■
I 'username ']) ) {
I
?>
['user_id'] =
1u s e r n a m e ']
['user _ i d ’];
[’username ’] ï 0 wicswo dodf^o de ifldfiX.php
$__cookie M ô
o
o
k
ie
s/s
e
s
s
o
c
sdeve se
r
n doiodâdo e» edi-frproíiie-
Pehna as variaveis da ?h? c vic^ciilefhf.
sessao usahdo os dookigs. ____________
ffgPíjPP
TteSTORtve________________
criando aplicações web personalizadas
Modifique o M ism atch para u sar s e s s õ e s £ cookies.
Modifique os scripts do Mismatch de modo que eles usem tanto as sessões quanto os
cookies para implementar a persistência do login (ou baixe os scripts no site da Alta Books,
www.altabooks.com.br).Será preciso modificar os scripts index.php, login.php, logout.php,
editprofile.php e viewprofile.php.
Envie os scripts para o seu servidor web e depois abra a página principal do Mismatch
(index.php) em um navegador. Tente fazer login e depois fechar o navegador, o que fará
com que asvariáveis da sessão sejam destruídas. Abra novamente a página principal e
verifique se você ainda está logado - os cookies tornam isso possível, uma vez que eles
persistem para além de uma sessão do navegador.
Combinando tockes e sessões,
nos obremos pevsistenüa
mâis lon^a, ale*» da oti»a
pevsistenóia de duvfce
prâto <
<
*
eja esta sendo
possibilitada pelas sessões.
f ! /
Z 7
0 uso de Cookies pâta
*>e!horar as sessões «â'0
ajuda os usuirios ^ue
desabílfta<ram os íookies
*<
>
s seus navegadores... não
* fossfvel a^ada*- a todos.
você está aqui ► 413
cA
m
o
L
o
7 caixa de ferramentas php e mysql
Sua Caixa de Ferramentas do PHP & M ySQ L
V o cê aprendeu bastan te sob re com o criar um siste m a de
gerenciam ento d o s u su ário s para fazer parte da a p licação
M ism atch. V a m o s recapitular a lg u n s d o s pontos principais.
f
£sta £wr>çao ív^fce^a-4?!.
'■
■ ::il .I:
? razo de
O ^ a l O Òookic é dcst^W o, Se
não &>r íornedido nenbum ftòTo,
o toolôee â f a ^ o â ss^ ^ue o
^í5
i_m >
?fíIí#iV
i-íí 1 i-iíi;V
''
* ' $vtefcna;$© t ,.,
f. iáfe,-’
^ '1. :
£if lí doofciee abwaàé
í;'W :3éè&& .«ç.^tl^r
;' <&
*
*
*
<
:<
->
*x*
■
*
!>
.«
«
*
»
•*
-IW
*
*
«
*
>
■
*
«
■
*
EstaíwnÇaowvtevr«^^ in^iâ
ja existente* Vpdt predisa tKái»>aV'
:;;efe/:$|à^ .
^ is^ u e * variáveis da sessão
^<
í;
jdof _ ................
w*> té*t»> resultando
t** mà sfcring de ^O daradteres
H e^èdi*aii£<^ ítthçao
-fórnctc :
u»*á ofantâ maneira dt se
d rip t^ ra í^ <ue fredise**
3« «^htarj^donbedrveis mesmo
dentro do bando dt dados É,
porem, vim prodesso se&> volta#
si^niíidando <^ue nao evúste uma
fen^So de "desdripto^ra&r
W $Ê Ê Ê & È Ê &
se ssio n _ _ d e s t r o y ()
£sta &n$ão interna do PHP íedka
*/^ses$ão,e deve ser dhamada
á<a»ifv*e <ue vode tiver terminado de
■
- ;-<ierjb»r»»iir%adl3 sessão. £sta
;j&»v^:*iâo destrói as variaveis ;
•
^■;^e«sâoí yorem, éimportante
eli^na-las manualmente, esvaziando
t.
super^lobal interna do
usada para se acessar
dados da sessão- Trata-se de v>**
array, e dada variável da sessão
e armaxenâda domo uma entrada
noarray Assim, para se adessar
o valor de uma variável, e prediso
espediAdar o seu nome» na forma
de »»dite do array
criando aplicações web personalizadas
+
A u c k à « rk ? f i m m
Alguém bagunçou várias partes do código da aplicação Mismatch
e não conseguimos nos lembrar do que elas fazem. Desenhe
linhas conectando cada pedaço de código com o que ele faz.
C ódigo PH P/M ySQ L D e scriçã o
empty($_COOKIE['user_id'])
setcookie (session name(), 11, time() -
Usa uma variável de sessão para
determinar se o usuário está
logado ou não.
3600) ; Use um cookie para determinar
se o usuário está logado ou não.
SHA( '$user_password')
Destrói um cookie de sessão,
definido o seu prazo de validade
como vencendo uma hora atrás.
session_destroy(
)
setcookie{'user_id'
, $row['user_id'])
Criptografa a senha do usuário,
colocando-a em um formato
irreconhecível.
Armazena a ID do usuário em
um cookie.
$_SESSION = array(
) Inicia uma sessão.
session start (
) Fecha a sessão atual.
isset{$ SESSION['user id']) Destrói todas asvariáveis de sessão.
você está aqui ► 415
quem faz o que solução
Alguém bagunçou várias partes do código da aplicação Mismatch
e não conseguimos nos lembrar do que elas fazem. Desenhe
linhas conectando cada pedaço de código com o que ele faz.
P H P /M ySQ L Code Description
empty ($_COOKIE ['user_id '])
setcookie (session name(), time() - 3600)
SHA(1$user_password' )
session destroy(
)
setcookie('user id'
, $row['user idT])
$_SESSION = array(
)
session start (
)
isset{$ SESSION['user id'])
Usa uma variável de sessão para
determinar se o usuário está
logado ou não.
Use um cookie para determinar
se o usuário está logado ou não.
Destrói um cookie de sessão,
definido o seu prazo de validade
como vencendo uma hora atrás.
Criptografa a senha do usuário,
colocando-a em um formato
irreconhecível.
Armazena a ID do usuário em
um cookie.
Inicia uma sessão.
Fecha a sessão atual.
Destrói todas as variáveis de
sessão.
7 Vi Elimine Ç&cligoDuplicado ^k_
* Compartilharé Cuidar
Guarda-chuvas não são a única coisa que pode ser
Compartilhada . Em qualquer aplicação web, você poderá encontrar situações
em que um mesmo código encontra-se duplicado em mais de um lugar. Isso não só é um
desperdício de recursos, como também pode levar a problemas de manutenção, uma vez
que inevitavelmente acabará fazendo modificações, e estas terão de ser efetuadas em mais
de um lugar. A solução é eliminar o código duplicado, compartilhando-o. Em outras palavras,
você mantém o código duplicado em apenas um lugar, e depois referencia esse código
sempre que precisar dele. A eliminação de código duplicado resulta em aplicativos mais
eficientes, de manutenção mais fácil e finalmente mais robustos.
você está aqui ► 417
localizar o código duplicado
A aplicação Mismatch evoluiu ainda mais desde a última vez que você a
viu, com uma navegação aprimorada e uma aparência mais consistente.
Mas essas melhorias acarretaram um custo... código duplicado. Apenas
olhando as próprias páginas, veja se você consegue descobrir quais
partes do Mismatch poderiam estar representando um problema de
código duplicado. Circule e escreva comentários nessas partes da
aplicação, e escreva também qualquer coisa não visível que você ache
que também possa estar tendo problemas com código duplicado.
Mismatch -W hat opposites attract!
Home ** View Profited StüLfteâk
L atestbb® * » «
t
*
A
M'
J l
Bad
Ccpyngh-£2009M
enm
ck£olKpr,«i-ta
index.php
elimine código duplicado
Mismatch - View Profile
Ho« « ** View Profile * Edit Prutile L op Qm limillles'l
Username: jneities
Firstsane: Johan
Lastname: Nettles
Gender: Male
Birthdate; 1981-11-03
Location; Atheas,GA
Picture:
Wouldyooliketoedityourpmttte?
Copyxíjbt& 2009Misratcfe Enterprises*fee.
viewprofile.php
editprofile.php
você está aqui ► 419
código duplicado do mismatch
SoLuÇâo
A aplicação Mismatch evoluiu ainda mais desde a última vez que você a viu, com
uma navegação aprimorada e uma aparência mais consistente. Mas essas melhorias
acarretaram um custo... código duplicado. Apenas olhando as próprias páginas, veja
se você consegue descobrir quais partes do Mismatch poderiam estar representando
um problema de código duplicado. Circule e escreva comentários nessas partes da
aplicação, e escreva também qualquer coisa não visível que você ache que também
possa estar tendo problemas com código duplicado.
0 título W
/Vlism3tdh
apârede cr» todas as
páginas, to» apenas a Jü?
o titulo detalhado Q®
variando de pagina
para pagina*
0menu de
«avegação £
ideníido eih
* trespaginas.
viewprofile.php
index.php
0 rodapé da página, *ue
dontem âs iníormaÇoe* de
dopyright da aplidadao, e
sempre o mesmo-
Tõdas as paginas ^ue dependem
do login do usuário requere»
exatamente o mesmo dódigo
de inicialização da sessão e de
veri-fidação do logi». editprofile.php
0 Mism atch está em pedaços
Portanto, a aplicação Mismatch tem alguns elementos comuns que estão repetidos nos
principais scripts, no momento. Por que isso é tão ruim? Porque toma a manutenção da
aplicação mais difícil. O que acontecerá se você decidir adicionar uma nova página, que
requeira um novo item de menu? Você terá de modificar o código do menu em cada um
dos scripts, para exibir o novo item. O mesmo se aplica ao aviso de Copyright.
A solução para o problema é só armazenar cada informação apenas uma vez. Então,
se algum dia o código precisar ser modificado, você só o modifica em um lugar.
Com isso em mente, é possível repensar a organização do Mismatch em termos de
componentes reutilizáveis.
elimine código duplicado
header,php
0 cabepalho das páginas
O script header.php contém
o título da página, o qual
referencia uma variável
para apresentar um título
diferente em cada página.
O cabeçalho também inclui
código HTML padrão e
cuida de tarefas tais como
vincular a folha de estilo CSS.
0 menu de navegação
O script navmenu.php gera
um menu de navegação
para a aplicação, baseado
em se o usuário está
logado ou não. O menu
navmenu.php ^e navegação apresenta
links "Log In”e "Log Out"
conforme necessário.
Este do>*p<m
en-fce *ao resulta
a* dódi^o ttMTL visível, mds
ele te» uw papel vital no
$e<rehí.iarr>e»to dos lojins dos
usuários e» -toda â aplicaçao
^ ATismatéH-
0 micializador de sessão
O script startsession.php
é responsável por iniciar
a sessão e verificar se o
usuário está logado.
startsession.php
footer,php
0 rodapé das páginas
O script footer.php exibe
um aviso de Copyright para
a aplicação e fecha as tags
HTML abertas no cabeçalho.
Assim, o cabeçalho e o
rodapé trabalham em
conjunto, tendo sempre de
ser usadosjuntos.
você está aqui ► 421
mismatch precisa de um template
Reconstruindo o Mism atch a partir de um template
Ok, então nós dividimos os Mismatch em váriosscripts, mas
como fazemos para elesfuncionarem bemjuntos? Vocêjá está
familiarizado com o conceito de arquivos incluídos, e estes fazem
parte da solução. Masvocê tem que pensar mais alto do que apenas
incluirarquivos... você tem que pensar em termos de templates
("modelos"),os quais lhe permitem criaruma única página como
a combinação devários arquivos incluídos. O templates é como
uma planta para aspáginas da aplicação, onde todo o conteúdo,
exceto aquele que é realmente único à página em questão,vem de
arquivos incluídos.
Aversão do Mismatch com templates requer que coloquemos os
códigos comuns em scripts que desempenhem papéis bastante
específicos: alguns responsáveis por gerar código HTML visual,
outros por alguma outra função. A ideia é destilar o máximo
possível de funcionalidades comuns em arquivos a serem
incluídos e então só deixar em cada página o código que seja
completamente único a ela.
Ostemplates
permitem c
jue uma
aplfraçã® ?B T seja
constmída a pattír
d e C Q m pQ netites
sc rip t te u tíliz á V e ls.
0 dabedaiho aparede n©alto
de dada pagina do Mismatdh,
e exibe o título da aplidação
juntamente do*» un« título
espedífido da página-
^startsession.php
Cada página do /Vlismatdh
e^
u
e -for personalizada para o
usuário exigira um dodigo de
login, o <uâl mantém registro
do usuário.
0 rodapé Comede donteúdo
na parte de baixo de
todas as páginas do
Alismatdh, o <
^
ual indlui um
aviso de dopyright- Copyright©2Û
C9Mimatch
f navmenu.php
0 menu de nâvegadao
aparede logo abaixo do
dabedalho, e iornede a dada
pagina do Mîsmatdh um
menu donsistente, <
^
u
e pode
ser usado para navegaça©
entre as paginas prindipais.
footer,php
index.php
Com tantos outros sdripts ajudando,
index.php -fida endarregado apenas
do seu pape! prindipai, «ue é exibir a
listâ prindipai de usuários-
elimine código duplicado
não existem
Perguntas Idiotas
I • 0 que é exatamente umtemplate? Ele não é apenas um monte de
arquivos incluídos?
Sim. Umtemplates é umconjunto de arquivos incluídos, mas é
umconjunto elaborado especificamente para dividir uma aplicação em
componentes funcionais, 0 objetivo é reduzir cada página ao que é
realmente específico aela, e somente aela. Assim cabeçalhos, rodapés,
menus de navegação e quaisquer outras-partes'da aplicação que sejamas
mesmas, ou semelhantes, emmais de uma página são candidatos ideais
para inciusão em umtemplates. 0 resultado final é que você coloca o
código dos templates emarquivos PHPque serão referenciados por outros
scripts que precisem deles.
Você pode pensar notemplates como umgrupo de arquivos que vão além
de apenas reduzir aquantidade de código duplicado- eles ajudama
organizar as funcionalidades de uma aplicação. OMismatch é umexemplo
relativamentesimples de como usar os templates - aplicações PHPmaiores
e mais complexas, frequentemente empregamsistemas de templates
bastante sofisticados.
- O código do template não tem de ser exatamente o mesmo para
poder ser compartilhado entre vários scripts?
Não. Éperfeitamente aceitável que o código do templates seja
apenas semelhante, e nãoexatamente igual. Omotivo é que você pode usar
variáveis para permitir algumgrau de personalização aoaplicar o script a
diferentes páginas. Otítulo das páginas no Mismatch é umexemplo perfeito
disso. 0 modelo do cabeçalho é semelhante em.cada página, no sentido
que otítulo sempre começa com"Mismatch -". Mas otítulo específico é
diferente, e é por issoque precisamos de uma variável para fornecer um
meiode mudar ligeiramente otítulo emcada página.
você está aqui ► 423
mismatch—agora usando templates!
Reconstrua o Mism atch com templates
O trabalho de design envolvido em se dividir uma aplicação em templates geralmente é
recompensador. No fim das contas, você terá um conjunto de scripts pequenos e bastante
focados, bem como terá um código radicalmente simplificado nos scripts principais da
aplicação, os quais agora dependem dos scripts templates. 7ênta resetar a
variáveis da s«sao
dom dookies, dáso
fc^elas não
inicia
a
sessão
tente defini-las
<?php
session_start(
) ;
// Se as vars da s e s s è o n ã o estiverem definidas,
com um cookie
if (!isset{$__SESSION['user^id'1)) { ‘
if (isset($_COOKIE[’user_id’]) && isset($_COOKIE['username']))
$_SESSION [’user__id'] = $JTOOKIE[’user_id'];
5_SESSI0N['username’] - $_COOKIE[’
u s e r n a m e ,
)
}
?>
!»»tia o toôi^o
H/VlTL oíitial -
tom um
P0CTYPÊ e
um3 tâ$ <KW>-
Cria umtítulo
personalizado
usando a variável
fpdgc__ií-tlc, <ue
e -fornedida pelo
sdripi <
^
u
e indluir
este arquivo.
Cria um link para a
•PolHa de estilo da
apliiaçao.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML .1.0 Transitional//EN
"http://www.w3.org/TR/xhtmll/DTD/xhtmll-transitional.dtd">
<html xmlns=”frttp;//www.w3.org/Í999/xhtml" xml;
<head>
<meta http-equiv=''Content-Type
lang="en" lang
content^”text/html; charset
<?php
echo
?> '<title>Mismatch - $page_title , '</title>
re;L^"3tylesheet" type="text/cas" href="
</head>
<body>
style.cs
<?php
echo
?> '<h3>Mismatch - $page_title . ’ < / h 3 > '
<?php
// Gera o menu de navegação
echo '<hr />';
if (isset($_SESSION['username'])) {
echo ’<a href="index.php">Home</a> &I10Q84;
1<a href="viewprofile.php">Ver Perfil</a> s#10084;
'<a href="editpro£ile.php">Editar Perfil</a> S#10084;
’<a href="logout,php">Log Out (
' . $_SESSI0N['username'
]
echo
echo
echo 1)</a>1;
'<a href="login .'php">Log In</a> &#10084;
■<a href=”signup.php">Cadastrar-se</a>';
echo
header,php
/VJostra um aviso
de dopyright e
íedha o dodigo
H
M
T
L
.
Ift se o usuário está
logado, e então, gera
o menu de navegarão
<hr /> ^
<p class="footer">Copvright &copy;2008 Mismatch Enterprises,
</body>
</html>
elimine código duplicado
0 sdript startsession.php predisa ser
o primeiro a ser indiuído, para ^ue a
sessão seja inidiada e o restante do
sdript tenha adesso aos sews dad
A variável /pagejrák
determina o título da
página «ue é exibido
dentro do dabedalh©
< ?php
'7/ Inicia a sessão
,require_once ('startsession.php1} i
Insere o cabeçalho da p a g m a —
$page_title = 'Onde os opostos se a t r a e m ! ^
kr e quire_once('h e ader.php');
r e q uire_once('app v a r s .p h p ');
r e q uire_once(1connectvars.php');
// Mostra o menu de navegação
.require once ('navmenu .php ' ) } ,
f// Conecta-se ao banco de dados
As variáveis da denexão e
as da apíidaçao ainda são
indluidas a partir de sdripts
^separados, do»»o antes.
0 menu de navegado é gerado
depois do dabedalho, mas antes do
dorpo da pagma-
$ d b c = mysqli_connect(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);
// Obtém os dados do usuário a partir do MySQL
$query = "SELECT user_id, first_name, picture FROM m i smatch_user WHERE first_name IS NOT)
NULL ” .
"ORDER BY join_date DESC LIMIT 5";
$data = mysqli_query($dbc, $query);
// Faz loop através do array de dados do usuário, formatando-os como HTML
echo '<h4>Membros mais novos:</h4>' ;
echo '< t a b l e > ';
while (?row= mysqli_fetch_array($data)) {
if (is_file(MM_UPLOADPATH . $ r o w ['pi c t u r e ']) £ & filesize(MMJJPLOADPATH .
$row [1picture ’3) >0) {
echo ' < t r > < t d X i m g src=" ' . MM_U PLOAD PATH . $row [’picture '] . '" alt=" ' . $row['first_
n a m e '] .
1" />< / t d > ’;
}
else {
echo 1< t r > < t d x i m g src=" 1 . MM_UPLOADPATH . 'nopic.jpg' . '" alt=" ' . $row['first_
name'] .
/></td>';
}
if (isset($_SESSION[’u s e r _ i d ’])) {
echo '< t d x a href="viewprof ile .php?user_id=' . $row ['user_id'] . ,
,1>' . $row['first_
n a m e '] .
'</a></td></tr>1,
•
}
else {
echo '<td>' . $row['first n a m e ’
}
echo '</table>';
mysqli__close ($dbc) ;
?>
1
< / t d > < / t r > ';
oú
à
s*
f> v
c
r
ft I
modeto agora t reaWe^te
untdo a esta portant»
há m
uV
to »ew» dele-
<?Bte
0 rodape -finaliza a pagina, e
-,, , , , predisa vir por ultimo, u»a vez.
// Insere o rodape da pagina  r . i
<
^
u
e e ele <ue -redha as tags
HTML.
,^equire_once ('f o oter.php ');
?>
você está aqui ► 425
uma aplicação php bem desenhada
0 Mismatch está novamente em pá., e muito melhor organizado
Embora o pensamento de destrinchar o Mismatch em pequenos
pedaços possa nos ter deixado um pouco nervosos, o resultado
final definitivamente valeu o esforço. A aplicação agora está
dividida em vários novos arquivos templates (inclusos), os
quais oferecem muito melhor organização e maximizam o
compartilhamento de código. Se você precisar modificar um desses
pedaços, basta editar um arquivo e o efeito se fará sentir em toda a
aplicação... esse é o poder dos templates!
0 sdrift star-bessionfKf
lida to» as -tareias de log's
nos bastidores c nâo odupa
néctar* espaço virtual «a
página-
0cabeçalho da
pagina indlui
tídigo HTML
e o irtulo da
pagina.
0 tódigo de ^
midialização da sessão
e wsado por <*al«ue<r
página <ue requeira
login do usuavio.
0 vodape da pág^a
í.on-téw>ift-Çov-matoes
de topYnghí para
-boda a aplitação-
se vote predisar
m
tadav o aviso,
basta modi-fita—
io
em apenas w
w
>lugarj
V-------^
startsession.php
0menu de
navegação
íornede links
úteis para as
partes pHndipais
da aplida^ão.
C '
navmenu.php
footer,php
8 Controle Seu M u n d o
Colhendo Dados
■
w
Nada como uma boa colheita de dados no outono. Um sem-fim de
informações prontas para serem examinadas, classificadas, comparadas,
combinadas, enfim, qualquer coisa que a sua excelente aplicação web
precisar que seja feito. Compensador? Sim. Mas assim como as colheitas
na vida real, é preciso muito trabalho duro e uma boa dose de conhecimento
para se obter controle sobre os dados em um banco MySQL. Os usuários da
web exigem mais do que dados estáticos e enfadonhos. Eles querem dados
enriquecedores... dados compensadores... dados relevantes. Então, o que
você está esperando? Dê a partida no seu trator MySQL e mãos à obra!
este é um novo capítulo ► 427
procurando uma relação de amor-ódio
Fazendo o desencontro perfeito
O aplicativo Mismatch tem um número cada vez maior de usuários registrados, e eles estão
prontos para ver resultados. Precisamos permitir que os usuários achem os seus opostos
ideais, comparando o que amam e o que odeiam com as preferências dos outros usuários,
em busca de desencontros. Para cada "adoro”combinado com um "odeio", maior a
probabilidade de um casal formar um par imperfeito.
Sidney ainda pvodura
o seu prfhdipe
e^tantado, i»i3s ela
“
te*" a sensação de <
^
u
e
ele vai odiar reality
shows -fcan
-fco <
^
u
a
>
v
fco
ela os adorâ-
Lewbra do Oo^a») w*
doratSo solitário e»
bus£a de al^Vké» «ue
odeie'levantamento
pesos tanto quanto
adora?
Odeio tatuagens
Adoro botas de caubói
Adoro realíty shouís:
Odeio filmes de terror
Odeio presunto
Adoro comida apimentada"
Odeio Hooíard £tern
Adoro Barbara Çtreisand^
Odeio levantamento de^
peso ~
Adoro escalada
h l»»ta âkW S rvt odeio da Sidney
tonhrãslê bâshnic tom a de
Johan, o «u
»e O
S torna um potential
par i»per+eito-
4doro tatuogerts
Adoro bofas de caubói
* Odeio resfity shows
-Àdoro film es dk te rro r
"Adoro presunto .
*doro comida apimentada1
^doro Howard Stem
■°dcío Barbara Streisand
^doro íevantamento de peso
Odeio escalada
r
*_
çx.
controle seus dados, controle seu mundo
Os desencontros se referem aos dados
Para podermos estabelecer desencontros entre os usuários, precisamos primeiro
determinar o melhor modo de organizar os dados que informam o que eles adoram e o
que odeiam. Saber que as informações serão armazenadas em um banco de dados MySQL
não é suficiente. Precisamos organizar esses tópicos de adoro/odeio de forma que sejam
mais fáceis de gerenciar, permitindo que os usuários respondam a tópicos relacionados,
indicando que eles adoram ou odeiam cada um.
Topidos semelhavas sao
agrupados, tomo este a<w
para aparoxdia íísidâ-
Cada tópido individual
redebe uma resposta
adoro/odeio, ^ue e
domparado dom as
respostas dos outros
usuários.
Escreva aqui como você organizaria os dados do
Mismatch em grupos separados que possam ser
armazenados em um banco:
você está aqui ► 429
um modelo de dados para mismatch
Pivida os dados do Mism atch
Criar um modelo de dados para uma aplicação como o Mismatch é um passo extremamente
importante, uma vez que ele tem um grande controle sobre o modo como a aplicação é
construída. No caso do Mismatch, nós p o d em o s dividiros seus dados em três tipos.
As daíegorias s3o
Categorias
As categorias são usadas
para ajudar a organizar os
tópicos. Embora elas não
desempenhem um papel
direto no estabelecimento
de um par imperfeito, elas
ajudam a facilitar a tarefa
de os usuários digitarem as
suas respostas.
■
j
usadas para se agrupar
-bofidos relational
aos.
Os -èopidos iorwiâm o
tev«e dos dados do
yV
jisft.atc.K
, detîdmdo
t^ais parâmetros
pode** ser tombados
pava se estabelederen»
os pares.
Respostas
Os usuários se descrevem,
para os propósitos do
Mismatch, respondendo _
aos tópicos. Cada resposta
individual é apenas um
valor de adoro ou odeio
em resposta a um tópico.
'RpdlityT V 1
^ m- Weightlifting
Horrf
HiWng
Tópicos
O estabelecimento de pares
é feito encontrando-se
opostos, tais como o gosto
por tatuagens ou comida
apimentada, cada um dos
quais recebe uma resposta do
usuário - adoro ou odeio.
$s respostas são as de adoro/odeio
■para dada tópido, e são espedííidas
para dada usuário do /V}ist*akdH.
Como exatamente esses dados levam a um desencontro entre dois usuários? Nós
comparamos as respostas que os usuários deram a cada tópico. Por exemplo, uma vez
que Sidney eJohan têm respostas opostas para o tópico "Filmes de terror", achamos um
desencontro nesse tópico particular. Para descobrir o melhor par imperfeito para um
usuário, temos de encontrar o usuário com a maior quantidade de tópicos respondidos de
forma oposta ao primeiro. Adoro^
£
FÜffle de terror
0 -(-ato de Sidney «3o
gostar de -fiWes de terror
leva a u
n
> desentomkro. Um desencontro!
t
controle seus dados, controle seu mundo
Modele o banco de dados com um schema
Para podermos traduzir os requerimentos de dados da
aplicação Mismatch em um projeto de banco de dados
propriamente dito, precisamos de um schema. O schema
é a representação de todas as estruturas do seu banco de
dados, como por exemplo, tabelas e colunas, além do
modo como eles se conectam uns aos outros. Criar uma
representação visual do seu banco pode ajudá-lo a ver como
as coisas se conectam quando você estiver escrevendo suas
consultas, sem falar que ela esclarece o que cada coluna
é responsável por fazer durante a conexão. Como um
exemplo, vejamos o schema do banco de dados original
do Mismatch, do capítulo anterior, que consistia apenas da
tabela mismatch_user.
0 rtom
c dâ tâbelâ-
Uma descrição dps
ciadas (as tabelas e
as colunas) <fc seu
bancp de dadps,
juntP com ^iials^uet
P ufrP S objetos
íelaclpnadps e a
f o r m a c o m p eles
se conectani, é um
scíiema.
^ m á m a t c h u s c » 111:
userjd O“ “"'*
username
password
join_date
first_name
!ast_name
gender
birthdate
city
state
picture
Este símbolo indida
íue â doluna C(A
m
a
dhave pvimâvia para
<
3tabela.
outras tolunai da "tabela
sao listadas da -Porm
a ttmo
cias aparedem na estrutura do
banCo de dados.
Esta forma de se considerar a estrutura de uma tabela
é um pouco diferente do que viu até agora. As tabelas
normalmente têm sido representadas com os nomes
das colunas na primeira linha, com os dados logo
abaixo. Essa é uma ótima forma d« se visualizar tabelas
individuais e tabelas preenchidas com dados, mas não
é muito prática quando queremos criar um diagrama
estrutural de várias tabelas e do modo como elas se
relacionam. E o Mismatchjá está precisando de mais de
uma tabela...
Criai- um diagrama
l]je petmffce manter
9 d e s i g n databela
separadp dos dadps
cpntídps nela.
você está aqui ► 431
escolha o melhor schema do mismatch
0 banco de dados do Mismatch está precisando armazenar as respostas
dos usuários para tópicos do tipo adoro/odeio, bem como os nomes
dos tópicos e as suas respectivas categorias. Apresentamos aqui três
projetos de bancos de dados para incorporar as categorias, os tópicos
e as respostas no banco do Mismatch. Circule o schema que você acha
mais apropriado, e escreva por quê.
category II
topic
response
- é r
□
s
è
oos novos dddos
fvefiisamos armazenar para dav-
suporte âo «ovo redurso de bus£<3
por pav-es do /WismaUh.
mismatch_topic
m is m a tc h _ _ u s e r topic«. ÍW IÜ BÍÍÍI8 -iqrtegory":
1 Tattoos Appearance
2 Cowboy hats Appearance
3 Reality TV Entertainment
.
^
,
1
_
_ ********
11 jnettles 4 Horror
movies
Entertainment
1
mismatch resbons î
♦
response. ■
1 niirr ’
If S i* *Sit
iíííHBiWIi
101 Love 11 1
102 Love 11 2
103 Hate 11 3
104 Love 11 4
“ mi^matdi response c -
fill IIHwnuw*!.._
_ t_ ^r
t
1
i
response id
response
to p ic jd
user id
name
tooic id
category
controle seus dados, controle seu mundo
«serjd
mismatch user
i i i i i ü á !
h jnettles
mismatch_response
ufSt" T *
101 Appearance Tattoos Love 11
102 Appearance Cowboy
boots
Love 11
103 Entertainment Reality TV Hate 11
104 Entertainment Horror movies Love 11
mismatch user
!« § r""**1
"* ■ H l i l S f S l
h jnettles * * * * * * * * 1 Love
h jnettles ********* 2 Love
h jnettles
* ******* 3 ] Hate
11 jnettles * * * * * * * * 4 Love
mismatch_topic
litopfcld l r ;. name ■ /
. .category
1 Tattoos Appearance
2 Cowboy hats Appearance
3 Reality TV Entertainment
4 Horror
movies
Entertainment
❖
você está aqui ► 433
mefhor schema da base de dados mismatch’s
0 banco de dados do Mismatch está precisando armazenar as respostas dos
usuários para tópicos do tipo adoro/odeio, bem como os nomes dos tópicos e as
x , suas respectivas categorias. Apresentamos aqui três projetos de bancos de dados
& C |C |0 para incorporar as categorias, os tópicos e as respostas no banco do Mismatch.
§ O L u Ç Ü O Circule o schema que você acha mais apropriado, e escreva por quê.
£m primeiro lugar, é importairfte -Pidar diaro ^ue os úm
idos dados
novos m
o prodesso d« se obter respostas adoro/odeio do usuirio
são as próprias respostas —tudo o «»ais no ba^do de dados
permanede o mesmo, pelo menos do ponto de vista do usuário-
Quem disse <ue o mais simples e
sempre o melhor? £ste sdhema
armazena as respostas em uma
tabela própria para elas, separada
dos ovtros dados <ue *>ao sejam
impadtados diretamente por elas.
Na© há duplidadão das respostas,
porque os usuários, as tate^orias
e os tópidos íidam todos -fora da
tabela mismatdbjresponse.
mismatchjaser
h jnettles
* * * * * * * *
topicid iis iiii
1 Tattoos Appearance
2 Cowboy hats Appearance
3 Reality TV Entertainment
4 Horror
movies
Entertainment
mismatch
❖
_res] >onsej^
ism ffr "S'-
101 Love 11 1
102 Love 11 2
103 Hate 11 3
104 Love 11 4
A nova tabela
mismatdh_topid
armazena os nomes
dos topidos e as suas
respedtivas dategorias
Kao H
a dados
duplidados para
dada resposta, o
«^
u
e e muito bomj
response id H H B M H M M Q i
response
— topicjd
^ user id
name
topic id 4 """"
category
A tabela mismâtdh__user original
permânede sem modiíidadoes.
A tabela mismatdhjresponse donedta
os usuários e os tópidos através das
doiunâs user_jd e topid_jd-
controle seus dados, controle seu mundo
As ("espostas nâOÇltdrrt dV-»n3Z£»dclâSdentro dâ
tabela dos usuários, Oque e otimo- Mss existe
uma quantidade excessiva de dados duplicados,
porque as categorias e os tópicos são replicados
para cada resposta. ^
mismatch__user
•
• • - : V. : :
ü lé ir M « se ra a ^ passv««» -
11 jnettles * * * * * * * *
mismatch_response
i i S i
| | P | y |S ! |
í É A I h í ilÉrtMftfi
líWílÍsítíiÍMíllikâll ^âsíJíílâliSiíllfl
user:
a
101 Y Appearance Tattoos"-^ j Love h
102 I Appearance Cowboy s) Love
boots ^
ii
103 { Entertainment Reality TV |
| Hate 11
104 ' ^Entertainment Horror movieyi Love h
. - - K ........................
Os dados dos usuários
sao pessimamente
replicados a cada
resposta-
As categorias e os
tópicos são duplicados
para^cada resposta, 0
*
V
*
e « um desperdício,
inaceitável de
reCursos-
mismatch__user
È É f s t »
vM m ä B H i
Ip ill
èmm
11 / jnettles
* * * * * * * * Love
11/ jnettles
* * * * * * * * I 2 Love
11 jnettles * * * * * * * * ... 3 Hate
11 ^ O nettles * * * * * * * * J  4 Love
...
Nao e mi ideia dividir
as categorias e os
tópicos em uma tâbela
para cada um, mas
da -forma Como esta
sendo -feito, temos de
criar uma linha para
cada resposta- (sso nos
deixa com 4r Johans
para respostas.
Nada bontf
mi smatch_topic
t * i c j d íl!l!WltíwttlSà%8s!
1 Tattoos Appearance
2 Cowboy hats Appearance
3 Reality TV Entertainment
4 Horror
movies
Entertainment
*
435
schema do mismatch usa chaves estrangeiras
Junte várias tabelas
Para conectarmos as tabelas de modo a formar um sistema
de dados coeso, precisamos usar chaves. Nósjá usamos
chaves primárias para fornecer um identificador único para
os dados de uma tabela, mas agora precisamos de chaves
estrangeiras paravincular uma linha de uma tabela a uma
linha de outra tabela. Uma chave estrangeiras de uma tabela
referencia a chave primária de outra, estabelecendo entre as
duas uma conexão que pode ser usada em consultas.
O schema que elaboramos para o Mismatch no exercício
anterior depende de um par de chaves estrangeiras
na tabela mismatch_response para conectar linhas de
respostas a linhas de usuários e tópicos em outras tabelas.
Uma cLaVe estrangeira
(foreígn key) é uma
coluna, em umatat>ela,
que referencia a cJiflVe
prmáfla (ptínwy key)
de outra tabela.
username
password
join_date
first name
last name
gender
birthdate
city
state
picture
Lembre-se, este
símbolo ideht»-(-ida
u»a dhave primária.
£sta dhave primária nao apenas
idcwtifida individualmente
os tópidos dentro da "tabela
n>ismatdh_topid, tom
no também
donedta os tópidos às respostas
da tabela mismatdh__response.
&ta seta mostra a tabela
»'smatdhjíser esta donedtada à
tabela i*ismat£h_jresp©Me por meio
das dhaves.
Sem as chaves estrangeiras, seria muito difícil
associar dados de uma tabela com dados de
outra. E dividir os dados entre múltiplas tabelas é
justamente o modo que encontramos para eliminar
a duplicação de dados e conseguir maior eficiência
para o banco. Assim, as chaves estrangeiras
desempenham um papel importante em todo
schema de bancos de dados, por mais simples que
o banco seja.
As tabelas mismatch response
c l ' l i I * „ , , e '*IStt'atdh_topid trabalha*
£ y * »»boi« Msbr» Y * para
to U a t uma dkave „ sposbs adaro/edeic
a qua! re-Vereda uma dhave
primaria em outra tabela-
As setas grandes .
mostram as ctaVes
prlmárías cpnectandp-se
às cfcaVes estrangeiras,
para Vincular as ^
tabelas entre sx.
controle seus dados, controle seu mundo
Chaves estrangeiras em apão
Muitas vezes, é útil visualizar os dados fluindo para as tabelas e conectando-as umas às
outras através de chaves primárias e estrangeiras. Dar uma olhada com mais atenção nas
tabelas do Mismatch, com alguns dados nelas, ajuda a revelar como as chaves primárias e
estrangeiras se relacionam umas com as outras.
Sendo uma tHave prímâriâ,
user_id predisa ser unida
dentro da "tabela mísmatdh_
user. Pe -fato, esse e o seu
propósito —íorneder um
a
reíerendia unifia a dada linha-
A dhave estrangeira user id serve
£om
©um
â vrPerendia às linhas dos
usuários nâ tabela mismatdh_user,
permitindo «jue vode saiba ^ual usuário
esta assoòiado dom ^ual recosta.
mis:
A dhave primária
topidjd serve
domo um (ndide
unido para as
linhas da tabela
miSmatdh__topid
ch topic
Lembre-se, dada
linha desta tabela
dorresponde a
um usuário do
/Wismâtdh-
Cada linha desta
tabela é uma
unida resposta
adoro/odeio
•Çornedida por
um determinado
usuário.
iilBiii;i;iÜiÉÍ
Tattoos Appearance
2 Cowboy hats Appearance
3 Reality TV Entertainment
V Horror
movies
Entertainment
P U T “
■ H M M 1
> 101 Love ( 1 1 
102 Love
1 1 1
2
103 Hate 1 1 1 1 3
104 Love v u j m____ V 4 /
Cada linha desta tabela
e o nome/dategeria de
uma resposta adoro/
odeio, mas ndo a resposta
propriamente dita-
A dhave estrangeira
/top»d_id reíerendia
as linhas dos topidos
na tabela m»smatdh_
topid, e nao é unida,
uma vez. <
^
u
e muitos
usuários diíeren-tes
■terao as mesmas
respostas para os
mesmos tópidos.
Dentro da tabela mismatch_jresponse, você pode encontrar
mais informações sobre o usuário que digitou uma determinada
resposta procurando pela user_id na tabela mismatch_user. Da
mesma forma, você pode descobrir o nome do tópico de uma
resposta, bem como a sua categoria, olhando o topicjd na * , '
tabela mismatch.topic. vindulIUa linha de resp^ta a
Vincular tabelas atravésde chavesprimárias e chaves estrangeiras uma linha de usuário na tabela
nos permite conectar os dados entre elas de uma forma consistente. mismatdh__user Ela nao e unida,
Vocêpode até mesmo estruturar o seubanco de dados de fornia uma vez. <^ue um mesmo usuano
aexigiruma correspondência entre aschaves primárias e assuas pode "ter diversas respostas
respectivaschaves estrangeiras. Isso é conhecido como integridade adoro/odeio,
referencial, o que é uma forma chique de dizerque todas as
referências das chavesprecisam serválidas.
você está aqui ► 437
tipos de relacionamento entre tabelas
Eu entendi que as chaves primárias e
estrangeiras conectam várias tabelas entre
si, mas a direção das setas nos diagramas
tem algum significado?
Sim, a direção das setas nos informa como as linhas
de cada tabela se relacionam umas com as outras.
Falando mais especificamente, elas nos dizem quantas linhas em
uma tabela podem ter linhas correspondentes em outra, e vice-
versa. Este é um aspecto importantíssimo do projeto do schema,
e envolve três padrões de dados possíveis: um-para-um, um-para-
muitos e muitos-para-muitos.
Astabelaspodemcorresponderlinhaporlinha
O primeiro padrão, um-para-um, determina que uma
linha na Tabela A pode ter no máximo UMA linha
correspondente na Tabela B, e vice-versa. Assim, só há
uma correspondência em cada tabela para cada linha.
Como um exemplo, digamos que a tabela dos usuários do
Mismatch sejaseparada em duas tabelas, uma apenas para
asinformações de login (TabelaA) e uma com os dados dos
perfis (Tabela B).Ambas as tabelas contêm IDspara manter
os usuários conectados aos seus perfis.
Acoluna user_id da tabela de login é uma chave primária
que garante a individualidade de cada login. Na tabela dos
perfis, user_id é uma chave estrangeira, e desempenha um
papel diferente, uma vezque a suafunção é apenas conectar
um perfil a um login. ,
Um-parâ-u», portâ«tX> âs
U i
líüil
corresponde
APENAS UMA - A - APENAS UMA
destas linhas destas linhas
setas ndo tò» poft-Us
user »d username join .date
« S i i á i i l
—
9 dierdre 08447b... 2008-05...
10 baldpaul 230dcb... 2008-05...
jnettles e511d7... 2008-05—
12 ' 062e4a... 2008-06...
13 theking "*b4ß B 3 r- 120080G--
mismatch__user_j?rofile
lÉSllIll
fiKtnam e last name
lIllSlB
gender
ili&ljlfilíisliiSfllsi
Johan Nettles M
8 Jasor> Filmington M 1 7"
9 Paul Hillsman... M 10
de um -para-w * através de
wser_id
No que diz respeito às duas colunas user_id, a tabela dos logins é considerada como
tabela parent(pai), enquanto que a dos perfis é considerada como child(filho) - uma
tabela com uma chave primária tem uma relação parent(pai)-child(filho) com a tabela
que possui a chave externa correspondente.
controle seus dados, controle seu mundo
| liH M M H i l i l l i f l l
►
corresponde
UMA---- A MUITAS
destas linhas destas linhas
Chave primaria.
mismatch_user
« « « o * -* ! i l l
9 dierdre 08447b...
10 baldpaul 230dcb...
jnettles e511d7...
— S í ir ^ rubyr 062e4a...
« V “ theking b4f283... I ■
■
■
I------ 11r 1
Uma linha leva a muitas outras
Um-para-muitos significa que uma linha na TabelaA pode
ter muitas linhas correspondentes na Tabela B, mas uma
linha na Tabela B só pode corresponder a uma linha na
TabelaA.Adireção da seta no diagramasempre sai da
tabela com uma linha e vai para a tabela com muitas linhas.
Usando novamente o banco de dados do Mismatch, o
schema atual sempre tira proveito de um padrão de
dados de um-para-muitos. Uma vez que um mesmo
usuário pode ter muitas respostas para os tópicos (adoro
tatuagens, odeio escaladas, etc.), há uma relação de um-
para-muitos entre as linhas dos usuários e as linhas das
respostas. A coluna user_id conecta essas duas tabelas,
como chave primária em mismatch_user e como chave
estrangeira em mismatch_response. «^a^cW .
mismatch_response y
um—
fâtrâ—
rnurtos
aivavés de user id-
i l ï l l l l l ï l l i i l l l l l i ï î î ! !
H I P !
101 Love f 11 1
^ 102 Love I 11 2
103 Haïe 11  3
104 Love
l 11 J 4
Um-para-Um:
e x a ta m e n te
umalínfea
databela
paxerrt(pa2)
se relaciona
com uma
linjbadatabela
chíld(Mho).
na« oxístem
— — " P e rg u n ta s id io ta s —
I * Como eu sei se as linhas de duas tabelas têm
uma reiação de um-para-um ou um-para-muítos?
Há uma tendência de se usarpadrões de um-para-
muitoscom muitomaisfrequência doque um-para-um, e
com bons motivos. Écomumse terumatabela principal
(parent) contendo dados primários, como porexemplo, os
usuários do Mismatch, a qual se oonecta a umatabela
secundária (chíkJ)em umarranjode um-para-muitos. Isso
aconteceduas vezes noesquemado Mismatch,ondetanto
os usuáriosquanto os tópicos têm relaçõesde um-para-
muitoscomas respostas.
Emmuitoscasos, as linhasde uma relação de um-para-
umem duastabelas podem ser combinadasem uma só
tabela. Porém, certamente existem situaçõesem que faz
sentido optarpelopadrão de um-para-um, como noexemplo
hipotéticodos perfisdos usuários na páginaanterior, onde há
uma motivaçãode segurança parase colocar uma parte dos
dados em umatabela separada.
Um-para-Muït°s:
exatamente uma
linha databela
parent(paî)
se relaciona
cem várías
lïnfcas databela
cjnlc[(eifco).
você está aqui > 439
o relacionamento muitos para muitos
Checando linhas de wuitas-para-muitas
O terceiro e último padrão de relacionamento de dados é
o de muitos-para-muitos, que tem muitas linhas de dados
na TabelaAcorrespondendo a muitas linhas na TabelaB...
parece um caso de sobrecarga de dados! Mas na realidade
não é. Existemvárias situações em que um padrão muitos-
para-muitos é o mais apropriado. Seria o caso do Mismatch?
Vamos dar uma olhada.
Os usuários e os tópidos tem
uma reiôtso de m uitos-para-
muitos, axraves das respostas.
1 fat,!«iííis
-j— 4 -
-
i l ã S t t f s í
*
•
—
mismatch_user
MUITAS A MUITAS
destas linhas destas linhas
mismatch__topic
Sun
9 dierdre 08447b...
10 baldpawt’" ""2353cb...
j nettles e511d7..n
i 12 rubyr 062e4a...
13 theking I b4f283...
1 ú ____
/Vjuitos-para-muitos/
Um-para-Wstos
i_respons>
'2 E I
Tattoos
Cowboy hats
Reality TV
Horror
movies
Appearance
Appearance
Entertainment
Entertainment
Wm—
para—
muitos.
mismatch
response e uma
tabela de > nçao
que estaW ctó w*,
reladiowameht?^
tnbrt os usuarios
e as suas respostâs
dos topifios-
á ü B l ff^" S t ::
. X  1
81 Hate 1 À
82 Love 9  2 / /
83 Love
Hate .® A V
101 Love
'111 I 1 . /
102 Love 11 I 
103 Hate 11 ^ 3 )
104 Love I11/ 4
s b
k
O padrão muitos-para-muitos no Mismatch é indireto,
significando que ele ocorre através da tabela mismatch_
response. Mas o padrão ainda existe. Basta ver quantas das ^
mesmas user_ids e topic_ids aparecem em mismatch_response. M uitP S -pcir^M Ü Ít^S :
Além de aimazenar os dados das respostas, a tabelamismatch_
response está agindo como o que é conhecido como tabela de
junção, ao servir como um conveniente intermediário para os
usuários e os tópicos. Sem a tabela dejunção, nós teríamos muitos
dados duplicados, o que é ruim. Casovocê não esteja convencido
disso, volte para o exercício dos esquemas no início deste capítulo
e dê uma olhada com atenção no Projeto 2. Naquele projeto, a
tabela mismatch_topic era repetida na tabela mismatch_response,
resultando em muita duplicação de dados.
V á ria s lînfcas <Je um a
tabela parent(paí)
s e re la c io n a m co m
Varias llntas Je uma
tabela cfcîlJ(îll}io).
controle seus dados, controle seu mundo
Em cada uma das tabelas abaixo, existem colunas circuladas que poderiam ser
movidas para as suas próprias tabelas. Escreva se cada uma dessas colunas seria
melhor representada por uma relação de um-para-um, um-para-muitos ou muitos-para-
muitos com a sua tabela original, e depois desenhe a relação na forma de uma linha
conectando as duas tabelas, com as setas apontando para os lados apropriados.
(endereço)
m iffSi
i l l
i ü f f i l f t f
l l i l i j i i l l l
.
lü ilS i il
- H
! .
.
id_do_tópico
nome
([categoria^)
wmmmmm
. I
I I
L
você está aqui > 441
qual é relação? solução
® B ® O â © t
Em cada uma das tabelas abaixo, existem colunas circuladas que poderiam ser
movidas para as suas próprias tabelas. Escreva se cada uma dessas colunas seria
melhor representada por uma relação de um-para-um, um-para-muitos ou muitos-para-
muitos com a sua tabela original, e depois desenhe a relação na forma de uma linha
conectando as duas tabelas, com as setas apontando para os lados apropriados.
£© ha um chdeveço para dada
usuirio, o «^U
C si^niíidâ q y t a jínKa
de endereço tem umâ relaçao de
um-para-wm dom dada linha de
uswario.
ismatc
id do usuário
(endereço)
I
um—
para—
um
l/ári
105 usua'r,0s tvabaíhar para a mesma
iiífflM B M 1
1
IB s S â ië iî
I
empresa, resultando em uma r e la to de u m -para-
muitos en tre uma linha de empresa e varias linhas
de usuários-
/ári©s usuários podem te r varias
amidos, sie^iíidando <^ue as linhas de
amidos têm uma relâdao de muitos—
para—
muitos dom as linhas de usuários.
.V
1!?1rrparâ—
muitos
muitos—
para—
muitos
vários tópidos podem pertender a mesma
dâte^oría, resultando em umâ relaçao de um-
para—
muitos entre umâ linha de date^oria e
varias linhas de tópidos. Mas dada tépido nao
pode pertender a mais de uma datejoria-
Tabelas «y*e dontem uma relação de m u iW p a ra -
murtos geralmente são donedtados através de uma
ta b e b de jundao, «ue nao é m ostrada a«ui-
ÊÊÊSm m :
id_do_tópico
nome
(categorí^
um—
parâ—
muitos
AAO
controle seus dados, controle seu mundo
Espere um momento! Tire um segundo para organizar o banco de dados
do Mismatch, para que possamos encontrar os pares imperfeitos.
Baixe os arquivos .sql da aplicação Mismatch no site da Alta Books, em www.altabooks.com.
br. Esses arquivos contêm as instruções SQL.que criam as tabelas necessárias: mismatch^
user, mismatch_topic e mismatch_response. Certifique-se de rodar a instrução de cada
arquivo .sql em uma ferramenta de MySQL, para ter todas as tabelas de que precisa para
iniciar o Mismatch.
Quando estiver tudo pronto, execute uma instrução DESCRIBE em cada uma das noras
tabelas (mismatch_topic e mismatch_response) para checar as suas estruturas. Essas
tabelas são importantíssimas para os scripts PHP que estamos prestes a escrever para o
Mismatch.
você está aqui ► 443
colocando resposta em mismatch_response
Coloque as respostas no banco de dados
Embora possa parecer que nós devamos começar gerando o formulário, este
depende da existência de dados de resposta na tabela mismatch_response. Portanto,
vamos começar pelo começo: temos de "preencher" a tabela mismatch_response
com linhas de respostas vazias, na primeira vez que o usuário acessar o questionário.
Isso nos permitirá gerar o formulário a partir da tabela mismatch_response sem
termos de nos preocupar se o usuário realmentejá forneceu quaisquer respostas.
r e s is ta s são dei*adas em brando
„a primeira vez. em que o usuano
visita o -formular'*©-
3
Os topidos do -formulário,
inidialmente, «a© tem respostas
esdoihidas, vez. que
preendhemos mismatdh__response
dom respostas vazias.
Assim, do ponto de vista do formulário, sempre existe uma linha de
dados, na tabela mismatch_response, para cada questão. Isso significa
que, quando o usuário submete o formulário, nós apenas atualizamos as
linhas de dados para cada resposta fornecida.
Agora que o usuário respondeu a
algumas das questões, ftós temos
dados de resposta reais para
armazenar «a tabela mismatdh_
response-
Embora o processo dc sc armazenar respostas no banco do Mismatch
tenha, em última análise, dois passos, o primeiro deles (INSERT) só
ocorre umavezpara cada usuário. Uma vez que as respostas vazias
tenham sido adicionadas, todas as modificações futuras são realizadas
no segundo passo, por meio de UPDATEs SQL.
A.A& ran/í(ífn Ã
As respostas são
âtudiiz^dds nc bãndo de
dados, para registrar as
m-formâdoes -fomedidas
feio usuário-
controle seus dados, controle seu mundo
fciíis de ôeladefm dç PHP &My$QL
1 O código seguinte cuida de inserir respostas vazias na tabela mismatch^.
| I response, na primeira vez em que o usuário visita o formulário. Ele também
j I atualiza as respostas quando o usuário faz modificações e submete
o formulário. Infelizmente, parte do código se perdeu e precisa ser
reestabelecida. Use os imas para completar o código que está faltando.
/ / S e este usuário jamais respondeu ao questionário, inserir respostas vazias no
banco de dados
$query = "SELECT * FROM mismatch__response WHERE user_id = ” ' . $_SESSION ['user__
i d ’] .
$data = mysqli_query($dbc, $query} ;
if ( ......... .............. ($data) == 0) {
// Primeiramente, obtém a lista de IDs dos tópicos a partir da respectiva tabela
$query = "SELECT............ FROM mismatch_topic ORDER BY category_id, topic_id";
$data = mysqli_query($dbc, $query);
$topicIDs = array();
while ($row = mysgli_fetch_array($data)) {
array_push($topicIDs, $row[rtopic_id']);
}
// Insere linhas de respostas na tabela respectiva, uma para cada tópico
foreach ($topicIDs as $topic_id) {
$query = ” .................... mismatch_response " .
- ( .............. , ............... ) VALUES ('" . $_SESSION ['user_íd'].
$topic_id')";
mysqli_query ($dbc, $query)
}
}
// Se o formulário tiver sido submetido, escreve as respostas no banco
if (isset {$__POST[1submit’]) ) {
// Escreve as linhas de respostas na respectiva tabela
foreach ($__POST as $response_id => $response) {
$query = " mismatch_response response = '$response'
"WHERE = '$response_id’";
mysqli_query($dbc,.$query);
}
echo '<p>As suas respostas foram registradas.</p>’;
}
ímãs php & mysql solução
jgF | Imas de Geladeira d®PHP & M/SoL - Solução
1 0 código seguinte cuida de inserir respostas vazias na tabela mismatch_response, na
I primeira vez em que o usuário visita o formulário. Ele também atualiza as respostas
I quando o usuário faz modificações e submete o formulário. Infelizmente, parte do
etóittlW# código se perdeu e precisa ser reestabelecida. Use os imas para completar o código que
está faltando.
// Se este usuário jamais respondeu ao questionário, inserir respostas vazias
no banco de dados
$query = "SELECT * FROM mismatch_response WHERE user_id
SESSION['user_id'] . ’
’
$data = mysqli_query($dbc, $query) ; Vcri-pida SC ê Consulta
retornou O linhas de
dados... nâo ha dados^
if ( mysqli_num_rows |.($data) == 0) {
// Primeiramente, obtém a lista de IDs dos tópicos a partir da respectiva tabela
OM mismatch_topic ORDER BY category_id,
V
$data = mysqli_query ($dbc, $query) ; Pára ^erâir w array V3ZJO de
ÇtopicIDs = array O ; respostas, primeiramente »»0s
temos de obter todos os topiCos,
na respectiva tabela
$query = "SELECT
topic id”;
while ($row = mysqli_fetch_array($data)) {
array p u s h ($topicIDs, $row['topic_id']);
// Insere linhas de respostas na tabela respectiva, uma para cada tópico
foreach ($topicIDs as $topic_id) {
$query = " .
.
"(
'$topic_id1)”
inysqli query($dbc, $query) ;
mismatch_response " .
VALUES ('" . $_SESSI0N ['user__id'
AJinha da resposta se enfiontra
nao respondida neste ponto,
^ urwâ vez. q«e o usuário ainda nao
j escolheu adoro ou ' odeiow no
■formulário.
// Se o formulário tiver sido submetido, escreve as respostas no banco
if (isset(S_P0ST[1submit'])) {
// Escreve as linhas de respostas na respectiva tabela
foreach ($ POST as $response_id => $response) {
$query = " ,
mismatch_response
"WHERE I response id i|= '$response_id'
mysqli_query($dbc, $query);
}
echo '<p>As suas respostas foram registradas-</p>'
response = '$response'
V
Só o que mudd quândo
ousuário submete o
-formulário e 3 Coluna
resposta da respectiva
tabela, portanto é só isso
que nósatualizamos.
não existem
Fetgimtas Idiotas
• Qual é a da função array_push()? Acho que ainda não usamos essa função..
Realmente, ainda não a usamos, porqueainda não precisamos criar umarray
dinamicamente, umelementode cada vez. Afunção array_push() anexa umnovo
elemento ao final do array, fazendo-o crescer emumelemento. N
ocódigo da página
anterior, nós estamos usando array_ push() para criarumarrayde IDsde tópicosa
partir da tabela mismatchjopic. Esse array é então usado para se inserirrespostas em
branco natabela mismatch_response... uma para cada tópico..
controle seus dados, controle seu mundo
Use INSERT para adicionar linhas vazias de
Q respostas ao banco de dados, na primeira vez que o
usuário acessai
Ba»/ A&abâmos dc afieríav
dois toeiHos viH>aU dom uma
cajadada so, e agora já -temos
»*e£ade do sdtripi pv-onio.
í
J
Use UPDATH^pãrâPIfiodificar as linhas de respostas
com base nas informações fornecidas pelo usuário.
Mas a'mda íal-fca» dois
passos fava podermos
tomctav- a favcs
no
£ Use SELECT para
obter os dados
necessários para se
gerar o form ulário.
T l Gere o formulário HTML com o
questionário a partir dos dados
de resposta.
você está aqui ► 449
utilizando formulários comandados por dados
Épossível comandar um formulário com dados
Não é novidade que formulários web sãousados para se obter dados Q g
dos usuários através de campos de texto, listas de seleção, botões
de rádio, etc., mas pode não ser muito óbvio o fato de que você
pode gerar formulários HTML a partir de dados do banco, usando
PHP. Aideia, no caso do Mismatch, é gerar dinamicamente um
formulário HTML contendo o questionário criado a partir de
dados de resposta. O script do formulário assume quejá existem
dados de resposta, o que o permite gerar o formulário a partir da
tabela mismatch_response. Nós sabemos que é seguro assumirisso,
porque acabamos de escrever o código que adiciona respostas vazias
na primeira vezque o usuário visitao formulário.
$ dHâve primária response_jd
c fcsâdâ pèirâ ide*tií»dar
mdWidwalmChtÉ os da»*pos do
-formulário H T M t e sí assodiar
tèdâ dâropo tom un*a ImHS do bardo-
0 dodigo do íormulario
ttT/WL e jerado a partir primária do ba*do-
/ de dados na tabela
miSmátdh_respohsc.
re s p o n s e jd ^ ^
response
userjd
c o m ^ d a d o s p o r
dadps (data-drlVe)
dependem de dadps
^resentes em um
?moo M/SqL para
gerar campos de
íp rm u lá rip s H T M L .
Os da»pos do £cm*i*lário sôo
vindulados a linhas do bâftdo
dc^m m do-sc o «on»€ de
dada dantpo do»o a cbsve
topic.i d ^ i r
<form method="pcst" ac;ior.=”">
<p>How do you feel about each
<fieldset>
<-sgend>Appearance</iegend>
■
clabei for=’-76">TattooS:</iabel><input type=-radio
/>Love
<mput type="radio" id«"7
7»name="7
7
"
/>Loveabel f°r=,,78">Bo^ Pacings:</label><ira e" />Hate<br />
<mput type^’
radio" id-
<label for
/>Lo
v
<
5
<inr)u
O form ulário reflete
as respostas do
usuário para cada
tópico.
controle seus dados, controle seu mundo
Kcício
0 questionário do Mismatch é gerado a partir de respostas do usuário que são
armazenadas na tabela mismatch_response. Para gerarmos o código do formulário
HTML, é necessário ler essas respostas, certificando-nos de verificar o nome do
tópico e o da categoria para cada resposta, na tabela mismatchjopic. Ocódigo
a seguir cria um array de respostas com tópicos e categorias, realizando duas
consultas: a primeira obtém as respostas do usuário, enquanto que a segunda verifica
o tópico e a categoria para cada resposta, Oproblema é que parte do código está
faltando... preencha as lacunas para fazê-lo funcionar!
jW ay de
tor* -fcópidos c Ss*~
£atejo**iâs.
^ 76 1 Love Tattoos Appearance
77 2 Love Gold chains Appearance
78 3 Love Body piercings Appearance
79 4 Love Cowboy boots Appearance
80 5 Love Long hair Appearance
81 6 Hate Reality TV Entertainment
82 7 Love Professional
wrestling
Entertainment
83 8 Love Horror movies Entertainment
/ / O btém o s d a d o s d e r e s p o s t a d o b a n c o , p a r a g e r a r o f o r m u lá r i o
$ q u e r y = "SELECT r e s p o n s e _ id , t o p i c _ i d , re s p o n s e FROM m is m a tc h _
re s p o n s e " .
"WHERE u s e r _ id = ' " . $ _ S E S S IO N [ 'u s e r _ i d ’ ] .
$ d a ta = m y s q li_ q u e r y ( $ d b c , Ç q u e ry ) ;
$ re s p o n s e s = a r r a y ( ) ;
w h ile ($ ro w = m y s q l i_ f e t c h _ a r r a y ( $ d a t a ) ) {
/ / V e r i f i c a o nome d o t ó p ic o c o r r e s p o n d e n te à r e s p o s t a , na
t a b e la d o s t ó p ic o s
$ q u e ry 2 = " ............................................................................................................................ ” .
"WHERE t o p i c _ i d = . $ ro w [ 't o p i c _ i d ' ] .
P H P iHí i « W 4 ? d a t a 2 = m Y s q l i _ q u e r y ( $ d b c , ........... );
. . . i f {m y s q li_ n u m _ ro w s ( ......... ........... ) = = 1) {
quantas i« as $ ro w 2 = m y s q li_ f e t c h _ a r r a y ( $ d a t a 2 ) /
de dados-roram $ ro w [ r to p ic _ n a m e 1] =
vC“fcov^adas tomo $ ro w [ ' c a te g o ry _ n a m e ' ] =
resultado^ da a r r a y _ p u s h ( ^ r e s p o n s e s , $ ro w ) ;
tonsvii'ta- }
}
você está aqui ► 451
R c íc io
SoLuÇão
0 questionário do Mismatch é gerado a partir de respostas do usuário que são
armazenadas na tabela mismatch_response. Para gerarmos o código do formulário
HTML, é necessário ler essas respostas, certificando-nos de verificar o nome do
tópico e o da categoria para cada resposta, na tabela mismatch_topic. Ocódigo
a seguir cria um array de respostas com tópicos e categorias, realizando duas
consultas: a primeira obtém as respostas do usuário, enquanto que a segunda
verifica o tópico e a categoria para cada resposta. O problema é que parte do
código está faltando,., preencha as lacunas para fazê-lo funcionar!
0 array fresponses
serve tomo
uma "tabela"
t«>*porária de
dados de resposta
a serem usados
para se gerar o
-rormulãrio-
A rray de respostas
íompieto, dom
tépidos e dategorias.
A ÍP do topido t usada
para se adhar os nomes
do topido c da date^o^'â;
a p a rtir da tabela
mismatdh__topid-
76
/A Love Tattoos Appearance
77 M Love Gold chains Appearance
78 3 Lève Body piercings Appearance
79 4 Love Cowboy boots Appearance
80 5 Love Long hair Appearance
81 6 Hate Reality TV Entertainment
82 7 Love Professional
wrestling
Entertainment
83 w Love Horror movies Entertainment
. ^
Certi-Pique—
de haver
dados de
resposta
aqui.
/ / O btém o s d a d o s d e r e s p o s ta d o b a n c o , p a r a g e r a r o f o r m u lá r i o
$ q u e r y = "SELECT r e s p o n s e _ id , t o p i c _ i d , re s p o n s e FROM m is m a tc h _
re s p o n s e " .
"WHERE u s e r _ id = 1" . $ _ S E S S IO N [ ’ u s e r _ i d 1]
$ d a ta = m y s q li_ q u e r y ( $ d b c , $ q u e r y ) ;
$ r e s p o n s e s = a r r a y { ) ;
w h ile ($ ro w = m y s q l i_ f e t c h _ a r r a y ( $ d a t a ) ) {
/ / V e r i f i c a o nome d o t ó p ic o c o r r e s p o n d e n te à r e s p o s t a , na
t a b e la d o s t ó p ic o s
$ q u e r y 2 - " ... S E L E C T . .*?àm.e, d â tegory mismptt^.h^.topid................
"WHERE t o p i c _ i d = . $ ro w j, ’ t o p i c i d ' ] .
$ d a ta 2 = m y s q li_ q u e r y ($tdbc, .?query2-. j ;
i f ( m y s q li num r o w s ( _ 7 _ d a k 2 -j. = = i ) {
é murtoimj**ta*teusarw
ow
as
«ariáveispartserealizaruma
segwwiò tar&ulta (m-tema), de
modo <ue ã tWiSul-fca criminal rào
sejaafetada
}
$ ro w 2 = m y s q l i_ f e t c h _ a r r ^ y
$ r o w [ 't o p ic ^ n a m e ' ] = ....fr ? .............................
$ ro w [ ' c a t e g o r y name ' ] = fro y /Z rd a ^ ^ o r y ,;];
a r r a y _ p u s h ( $ r e s p o n s e s , $ r o w ) ;
'
A íunção MRAV-PMSHO
adidiona um vtem para o
Cs «omes do topido e da
r ^ y ( $ d a ta 2 j) ; ___dategoria sao adidionddos Ao
í ^ array de resposta, atribuindo-
se dados originários dâ
segunda donsultâ-
•final de u» array-
«f Use para obter
os dados necessários
para se gerar o
controle seus dados, controle seu mundo
A reposta do usuário é armazenada
como texto no banco de dados, como
"Adoro" ou "Odeio" literalmente? Se sim,
isso não seria pouco eficiente?
Não e Sim , e é por isso que é im portante usar o tipo de
dados m ais eficien te possívei para arm azenar dados em
um banco MySQL.
Pensando bem, uma resposta no Mismatch é na verdade uma resposta do
tipo true/false (verdadeiro/falso), porque ela é sempre um (adoro) ou o
outro valor (odeio).Na verdade, um terceiro valor (desconhecido) pode
ser útil para informar à aplicação que o usuário ainda não respondeu
um determinado tópico. Então, nós precisamos manter registro de
três valores possíveis para cada resposta. Esse tipo de problema de
armazenamento é ideal para um número, como por exemplo, TINYINT.
Com esse tipo de dados, basta você usar diferentes valores numéricos
para representar cada resposta possível.
? V 0
Desconhecido = 0 Adoro = 1 Odeio 2
Minimizar os requerimentos de armazenamento de dados é uma
parte importante do projeto de bancos de dados, e neste caso é
uma parte sutil, porém, importante da aplicação Mismatch. Essas
respostas numéricas desempenham um papel direto na geração de
campos do formulário do Mismatch.
— ^Aponte seulápis
Não sc preoiupe i-©** os
botões de radio p3r3
>
JOdeio” por en^âwfco — eles
s3o gerados e'^âtsw'ewte da
n>esmd-forma-
O seguinte código faz um ioop através do array de respostas que
você acabou de criar, gerando um campo do formulário HTML para
cada botão de rádio "Adoro". Escreva o código que está faltando
para que o campo fique inicialmente marcado, caso a resposta seja
definida como "adoro" (1). Além disso, certifique-se de que o valor
da tag <input> seja definido corretamente.
f o r e a c h ($ re s p o n s e s a s $ re s p o n s e ) {
i f ( ................................................................. ) {
e c h o 1c i n p u t t y p e = " r a d i o " n a m e = " ' . $ r e s p o n s e ['r e s p o n s e _ i d ']
' " v a lu e = c h e c k e d = ........................./> L o v e ' ;
}
e ls e {
e c h o '< i n p u t t y p e = ''r a d io " n a m e = "1 . $ re s p o n s e [ ’ r e s p o n s e _ id ' ] .
v a lu e = .......... /> A d o ro
}
você está aqui ► 453
aponte seu lápis solução
Iiponte seu lápis
Solupão O seguinte código faz um loop através do array de respostas que
você acabou de criar, gerando um campo do formulário HTML
para cada botão de rádio "Adoro". Escreva o código que está
faltando para que o campo fique inicialmente marcado, caso a
resposta seja definida como "adoro" (1). Além disso, certifique-se
de que o valor da tag <input> seja definido corretamente..
0 botão de rádio para "Adoro" e mardâáodom
base «o valor da resposta 0 representa adoro
no bando)-
f oreach ($responses/as $response) {
Se c s k resposta -kr deíinida
"adoro” (l)} marda o
botão de seleção, de-Pinindo
/ o seu atributo dhedked dom o
/ valor "dtiedked"
i f (. f responsçrrespcms^J I......... ) { /
echo ’<input type="radio" n a in e - " '^ . $response [1response_id' ]
'" v alue= BIW checked= W
dhedkedW />Love 1;
}
else {
echo 'cinput tjpe="radio'
value= wl />Love 1
@ va^ à s tag <input> t definido
domo I >para ^ue -Pi^ue mais -Pádii
de arm azenar a resposta m bando,
^ua^do o -formulário ío r submetido.
="' . $ r e s p o n s e ['r e s p o n s e _ i d '
Deitar dfcedked^tkedkedf
resulta m> botão de seledâo
íid a r deswardado, se a resposta
não estiver de-Pinida domo
"adoro” íí)-
foreach (Sresponses as Sresponse) {
if ($response['response 1) == 2) {
echo 'cinput type="radio" name="
value="2" cnecked="checked"
1 . $response [’
.response_id’] .
/>Hate '
;
else (
echo 'cinput type="radio" name=”
1" value=”2” />Biate V
;
' .
. $response [
.
1response_id'] .
1 A
Caso esteja durioso, 0 dodigo para gerar
os botões "Odeio" íundiona exatam ente da
mesma torm a - ele apegas produra por uma
resposta ligeiramente di-Perente-
verdade, existe uma maneira mais elegante
de jje ra r ta n to os botoes "Adoro" quanto
05 $deio dom menos dodigo-..
controle seus dados, controle seu mundo
Falando em eficiência...
A eficiência do banco de dados não é o único tipo de eficiência
que vale a pena considerar. Há também a eficiência do código, que
pode vir em muitas formas. Uma forma é tirando-se proveito da
linguagem PHP para simplificar declarações if-else. O operador
ternário é uma forma útil de se programar declarações if-else
simples, de modo que elas fiquem mais compactas.
Sc a &*pressaoDe7este
/*“ -for verdadeira (true), a
JL Insbruçaol é executada.
E xp ressã o D eT este^T jln stru çã o lInstrução
true
0 operador
ternãtiP ? :
pode ser
usadp para
se programar
declarações
íí-e lse de uma
Çprmamais
compacta-
false
Se 3 E*pressãoDeTeste f<*"
■falsa (-faUc), 3 detlar3Ç3o2-
e e*etwtdda.
O operador ternário, na verdade, é apenas um atalho para se escrever
uma declaração if-else. Ele pode ser útil para simplificar essas declarações,
especialmente quando você está fazendo uma atribuição de variável ou gerando
código HTML em resposta à condição if. Eis aqui o mesmo código para o botão de
seleção "Adoro", reescrito para usar o operador ternário:
e ch o ’ < in p u t t y p e = " r a d io " n a m e -'" . $ re s p o n s e [ ' r e s p o n s e _ id '
I&
ÍM
Ím
ííM
iiiiia iis i *i
Este teste true/•false Controla o J
resultado do operador ternário.
Se o valor de resposta armazenado em $response ['response']
for igual a 1, então o atributo checked será gerado como
parte da tag <input>, resultando no seguinte botão de seleção
"Adoro", marcado:
" * v a lu e = " l" ' .
. ' /> A d o r o ' ;
0 atrib u to checked
da ia s <ir»put> a^ora
c gerado usando—
se o
operador ternário, em
vez. de uma declaracao
-f-eise- 1
Por outro lado, um valor de resposta diferente de 1impedirá o
atributo checked de ser gerado, resultando em uma tag <input> não
marcada para o botão "Adoro".
você está aqui ► 455
Gere o formulário do questionário Mismatch
o script inteiro questionnaire.php
Agora nósjá temos pedaços suficientes do questionário do Mismatch para usarmos o
array de resposta ($responses) que criamos anteriormente para gerar o formulário HTML
inteiro. Lembre-se, esse array foi construído obtendo-se as respostas atuais do usuário
presentes na tabela mismatch_response. Vamos ver o código de geração do questionário
no contexto do script questiónnaire.php inteiro.
Ihilui os arquivos tem plate
que ihiÊiâm a sessão e
exibe» o cabeçalho da
p%i»a.
a
questionnaire.php
Í^estv“
ih0e a pagina aos
usuirtos locados.
<?php
// Inicia a sessão
require__once (1startsession .php')
// Insere o cabeçalho da página
$page_title = 'Questionnaire';
require once{'header.php');
require_once('appvars.php');
require_once('connectvars.php'
)
// Assegura que o usuário está logado antes de seguir adiantj
if (!isset($_SES5I0N['user_id'])) {
echo '<p class="login">Por favor <a href="login.php"> faça </a> login para acessar
esta página.</p>';
exit);
}
// Mostra o menu de navegação
require_once('navmenu.php'
)
;
// Conecta-se ao banco de dados
$dbc = mysqli_connect(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);
/ / S e este usuário jamais respondeu ao questionário, inserir respostas vazias no banco
$query = "SELECT * FROM mismatch_response WHERE user_id = . $_SESSION['user_id'] . ;
$data = mysqli_query($dbc, $query);
if (mysqli_num_rows($data) == 0) {
// Primeiramente, obtém a
. lista de IDs dos tópicos a partir da respectiva tabela
$query = "SELECT topic__id FROM mismatch_topic ORDER BY category_id, topic_id";
?data = mysqli_query($dbc, $query);
$topicIDs = arrayO;
while ($row = mysqli_fetch__array ($data) ) {
array_push($topicIDs, $row['topic_id']);
}
I
I Insere linhas de respostas na tabela respectiva,
foreach (ÇtopicIDs as $topic_id) {
$query = "INSERT INTO mismatch_response (user_id,
SESSION[1user_id'] .
"', 1$topic_id')";
mysqli_query($dbc, $query);
}
uma para cada tópico
topic_id) VALUES (1" . $
// Se o questionário tiver sido submetido, escreve as respostas do formulário no banco
if (isset($_POST['submit1])) {
// Escreve as linhas de respostas do questionário na tabela de respostas
foreach ($_P0ST as $response_id => Srespons.e) {
$query = "UPDATE mismatch_response SET response = '$response' " .
controle seus dados, controle seu mundo
"WHERE response_id = '$response_id'";
mysqli_query($dbc, $query);
}
echo '<p>As suas respostas foram registradas..</p>’;
}
O
( // Obtém os dados de resposta do banco, para gerar o formulário
$query = "SELECT response_id, topic_id, response FROM mismatch_response WHERE
user_id = ’" .
$_SESSION ['user_id1] .
$data = mysqli_query($dbc, $query);
Çresponses = array ();
while ($row = mysqli_fetch_array($data)) {
// Verifica o nome do tópico correspondente à resposta, na tabela dos tópicos
$query2 = "SELECT'namef category FROM mismatch_topic WHERE topic_id = ’" .
 $row[1topic_id’] .
$data2 = mysqli_query{$dbc, $query2);
if (mysqli_num_rows($data2) == 1) {
$row2 = mysqli_fetch_array($data2);
$row[’topic_name1] = $row2 [1name ’];
$row [rcategory__namer] = $row2[’category’
array_push($responses, $row);
}
mysqli close($dbc);
ôbiem a
categoria da Cada dategoria e
primeira resposta, tríada domo w*
para inidiar o dowjuivtode tampos,
prodesso ãnies de ^y-a ajudar a
entrar no loop. organizar os topidos.
// Insere a página
require_once{’footer.php’);
Cada w*a destas iftstsn*doesedKo
gera um botao de selelâo - w para
ftàaro’ e outro pâra ôdóo -
Lembre—
se,
—adoro e
2. —odeio-
rotulo seguido de botoes de
seleção "hdcK o e "O dãa •
X Ge
Q o c
I da
Ger#o fOFAufário HTML com
o questionário a partir dos
dados de resposta.
você está aqui ► 457
test drive questionaire.php
TtesT ORive
Teste o novo questionário do Mismatch.
Modifique o Mismatch para que ele use o novo script do questionário, (ou baixe a
aplicação no site da Alta Books, em wvw.altabooks.com.br). Para isso, você terá de criar um
novo script questionnaire.php, bem como adicionar um item de menu “Questionário”ao
script navmenu.php, para que os usuários possam acessá-lo.
Envie os scripts para o seu servidor web e depois abra a página principal do Mismatch
(index.php) em um navegador. Certifique-se de fazer login, e então clique no item de
menu "Questionário”para acessá-lo. Repare que nenhum dos tópicos tem repostas, uma
vez que esta é a sua primeira visita ao questionário. Responda aos itens e submeta o
formulário. Retorne à página principal, e depois volte ao questionário para confirmar que
as suas respostas foram corretamente carregadas a partir do banco de dadòs.
0 seríp-fc d©
questionário permite
°[^c os usuários
responda*. a i-fcchs
ddoro/odeio e
armâz«hem os
resultados ho bân£o
de dados.
Howdoyoufedabouteachtopic?
—Appearance
Tattoos:
GoW chains:
ULove 0Haß
0Love QHate
£Love 0Haie
^Love ©Haie
#Love ©Hate
Bodypiercings:
Cowboyboots:
Longhair;
—Fnterrainment-
RealityTV:
Professional
wrestling:
OLove IgHate
- se vofiê aditio^ar r.ovos
topidos, o -Çormulari© se
modiíitârá-
questões ho iormulario
são geradas d'inav*i£àw*.eft£e
a p a rtir do bahfio de dados
O código-fonte completo da aplicaçao Mismatch está
disponível para download no site da Alta Books:
www. a lta b o o k s.com .br
►
If
controle seus dados, controle seu mundo
nab existem
p e rg u n te is I d io fö s
P - Como o botão de seleção “Adoro" sabe que o
resultado do operador ternário é uma string?
0 operador ternário sempre resolve em uma das duas
instruções separadas pelos doís-pontos, com base no vaíor
(true ou false) da expressão de teste. Se essas instruções
forem strings, então o resultado do operador será uma string. É
isso que torna o operador tão útil - você pode inseri-lo no meio
de uma atribuição ou concatenação.
• O operador ternário faz o meu script rodar mais rápido?
Não, provavelmente não. O operador ternário serve para
adicionar eficiência estilística ao seu código, e não exatamente
para melhorar a eficiência do desempenho, o que significa
dizer que a sua vantagem é exigir menos linhas de código.
Em alguns casos, é mais conciso usar o operador ternário do
que uma declaração if-else completa, embora os dois sejam
logicamente equivalentes. Mesmo assim, não fique muito
entusiasmado com o operador ternário, porque ele pode tornar
o código mais difícil de entender, caso você esteja tentando
substituir uma declaração if-else complexa. A ideia é usar o
operador ternário em lugares onde a eliminação do if-else pode
realmente ajudar a simplificar o código, em vez de torná-lo mais
complicado. Isso geralmente envolve usar o operador para
controlar seletivamente um valor sendo atribuído a uma variável
ou inserido em uma expressão. No caso dos botões de seleção
do Mismatch, esta última abordagem foi usada para se controlar
seletivamente a inserção de um atributo HTML (checked).
- Como é possível gerar o questionário do Mismatch
a partir da tabela mismatch_response, quando o usuário
ainda não respondeu a nenhum tópico?
Excelente pergunta. O formulário do questionário tem de
lidar com dois cenários possíveis: o usuário está respondendo
ao questionário pela primeira vez, ou o usuário já o respondeu
e está revendo as respostas. No primeiro cenário, não há
nenhuma resposta ainda, portanto a tabela mismatch_response
ainda não tem dados para este usuário.
Mas nós ainda temos de gerar o formulário dinamicamente.
Poderíamos usar a tabela mismatch_topic para isso. Porém,
não funcionaria para o segundo cenário, porque desta vez
o formulário precisa ser gerado com base nas respostas
específicas do usuário; lembre-se, os botões de seleção
para "Adoro" e "Odeio” são gerados como parte do formulário.
Assim, nós temos um problema, no sentido que o código para
gerar o formulário é completamente diferente, dependendo
de se os usuários já responderam ou não o questionário. Não
apenas isso, e se o usuário tiver respondido apenas a algumas
questões? Pode ficar muito complicado bem rápido. A solução
adotada pelo Mismatch é preencher antecipadamente a tabela
mismatch^response com respostas em branco, na primeira vez
que o usuário acessa o questionário. Isso nos permite sempre
gerar o formulário a partir da tabela mismatch_response, e
não precisamos nos preocupar com a complicação de gerar
o formulário diferentemente dependendo de se o usuário já
respondeu ou não ou de quais tópicos ele tenha respondido.
É claro que o código para geração do formulário ainda não
é exatamente trivial, mas é mais simples do que se não
tivéssemos usado esta abordagem.
Para s»v*pli-Pi£ar o o Misma-fcdh »ao sc ajusta
F - i O autowatidam ehte 3 -novos tépidos, pelo meros »ao *0
r 3-9*1 ^ S tc l ^ que se re-fere a usuários que la tenH a* respondido o
, E x p e í f e n c i a ! <
V*«st |ot’
tfrio- Assim, vodê te ra de esvaziar a tabela
^ »>is»»*atdH_respoKse após adidionar um novo topido.
O Adicione um novo tópico à sua própria tabela mismatch_topic, com esta
instrução SQL:
INSERT IN TO m is m a tc h _ to p ic
(na m e , c a te g o r y ) VALUES
( ' V i r t u a l g u i t a r s ' , ' A c t i v i t i e s ' )
0 Esvazie todos os dados da tabela mismafch_response, com esta instrução
SQL:
DELETE FROM m is m a tc h _ re s p o n s e
o Visualize o questionário na aplicação Mismatch para ver o novo tópico.
Q Responda ao novo tópico, submeta o formulário e verifique a sua resposta
gravada.
você está aqui ► 459
lidar com dados ruins do banco de dados
Agora os dados estão comandando o formulário
Foi preciso algum trabalho, mas agora a aplicação Misraatch está
gerando dinamicamente o questionário a partir de respostas
armazenadas no banco de dados. Isso significa que quaisquer
modificações feitas ao banco serão automaticamente refletidas no
formulário —essa é a vantagem de se gerar a interface de usuário de
uma aplicação web a partir de ura banco de dados. Mas o que acontece
quando nós temos dados inválidos?
l Ä j l ß ä ü ö ä i l l l j j ä
E1p 1h 111í 1
re sp o n se jd
response
u s e rjd
to p ic jd
topicJd
category
How do yon lesäaboateachtapie?
Estes tmes donjuntos de
da>*pos deveria» sev- um so, de
»odo ^ue todos os topidos de
Entvetenim ento ii^uew* juntos.
0 -formulário e gerado de
-forma ta l <ue u»a mudança
de date^oría resulta e» um
novo óorvjunto de da»pos, ^ue
é o motivo pelo ojual »ais um
Conjunto desnede*saHo t Lriado
a<ui-
—Appearance-----------—
Tattoos: ©Lave 9 Hate
Gold chains: ©Love # H aie
Body piercings: ©L0V2 #H3K
Cowboy toots: igLove @Hafe
Long hair: 9 Love Q H ate
—Entertainment-------------
Reality TV : (SLove 0Hate
Professonal
wrestling: 0 Lovc # H aie
Horror movies.’ © Love 0 Haie
i-Eat&rtimDeni — -
' Easy &te5ng Omsk; 9 Lore ©Hate
—EnttftaiiBsent -............................ .... 
Hie opera: © Love QHste ’
—Food
Sushi: #Love OHare
l Spun: 0 Lovc @Hate
1 Spicy food: @ Lovc ©Hale
um erro de digitaçao nesta
W tegona, o ^ue resulta nela apareder
no seu próprio doiÿunio At dâmpos no
•formulário, o ^ue e bastânte don-fuso.
Os dados estão determinando o formulário como queríamos, mas algo ainda está errado.
Parece que uma das categorias foi escrita no banco de dados com um erro de digitação,
fazendo o código PHP gerar um conjunto de campos separado para ela. Isso é um
grande problema, porque arruina o efeito de se usar conjuntos para ajudar a organizar o
formulário e facilitar a resposta aos tópicos.
controle seus dados, controle seu mundo
mismatch topic
Ok, entao uma das
categorias foi escrita com um erro de
digitação no banco, o que está estragando
o nosso formulário. Como vocês acham que
devemos consertar isso?
Kos j i sabemos que e s t a ^ / i r
ta te jo ria dom ev-ro de
di^i-fcaçao esÜ dausand©
pvoblemâs
— e aqui temos mais
uma £3usâ*do o
mesmo pvobíemâ
«o í^rmv*iav*io-
Frank: É fácil. É só corrigir a grafia da categoria na tabela mismatch_topic.
Joe: Mas tem mais de uma categoria escrita errada. E agora que pensei nisso, não entendo
por que os nomes das categorias têm de ser armazenados mais de uma vez.
Jill: Concordo. Nós nos demos ao trabalho de eliminar dados duplicados ao projetarmos
o esquema do banco de dados, e aqui estamos nós com um monte de nomes de categorias
duplicados. E não apenas isso, mas temos até alguns nomes com erros de digitação.
Frank: Ok, e se nos livrássemos dos nomes das categorias, e talvez fizéssemos a referência a
elas por números? Assim não haveria o risco de termos erros de digitação.
Joe: Everdade, mas ainda precisamos dos nomes das categorias para usá-los como títulos
no questionário.
Jill: Talvez possamos nos referir às categorias por número, semjogar fora os nomes. E mais
ou menos o quejá estamos fazendo com os tópicos na tabela mismatch_topic, não é?
Joe: Certo! Nós não queríamos armazenar um monte de nomes de tópicos duplicados na
tabela mismatch_response, e portanto, colocamos esses nomes na tabela mismatch_topic, e
vinculamos os tópicos às repostas usando chaves numéricas.
Frank: Vocês estão dizendo que poderíamos resolver o problema dos nomes de categorias
duplicados criando uma nova tabela para as categorias?
Jill: E exatamente isso. Nós podemos criar uma nova tabela mismatch_category, onde cada
nome de categoria é armazenado exatamente uma vez. E depois, conectamos as categorias
aos tópicos usando chaves primárias e estrangeiras entre mismatch_topic e mismatch^
category. Brilhante!
você está aqui ► 461
normalizando seus dados
Nlorrrtal«'® slgruífca
Procure por um pouco de normalidade e laW üm
O processo de reelaborar o banco de dados do Mismatch de modo clckl0 5 d e Ul°cl0 cl
a eliminar dados duplicados, e a dividir e conectar tabelas de uma
forma lógicae consistente é conhecido como normalização. A JXíduZJl’ a d UPlíC3C3p
normalização é um assunto relativamente aprofundado no que i ‘
diz respeito ao projeto de bancos de dados, e pode ser um tanto d ad °S e a
intimidante. Mas não precisa ser. Existem váriastécnicas simples de
projeto de bancos de dados, das quais nós podemos nos aproveitar m e lllP ta í ctS íelaÇ ^eS
para tomar os nossos bancos MySQLmuito melhores do que
se simplesmente tentássemos adivinhar como é que os dados ellt^e PS dadPS-
deveriam ser dispostos.
Eis alguns passos gerais que você pode usar para iniciar o
processo de design do banco de dados, os quais levarão
naturalmente a um banco de dados mais "normal":
1. Escolha uma coisa, apertas uma coisa que t-
você queira que a tabela descreva.
2. Faça uma lista d as inform ações que você
precisa saber sobre e ssa coisa, ao usar ^
a tabela.
3. Usando a lista, divida a s inform ações
sobre e ssa coisa em pedaços que você
possa usar para organizar a tabela.
Um conceito fundamental na normalização é a ideia dos
dados atômicos, que são dados divididos até a sua menor
forma possível que faça sentido, considerando-se o uso
do banco de dados. Por exemplo, as colunas first_name e
last_name do banco de dados do Mismatch são atômicas
no sentido de que elas dividem o nome do usuário em mais
pedaços (primeiro nome e sobrenome) do que uma única
coluna para o nome inteiro o faria. Isso é necessário no
Mismatch porque queremos poder nos referir ao usuário
apenas pelo seu primeiro nome.
Talvez não seja sempre necessário que a aplicação divida
o nome em colunas separadas para primeiro nome e
sobrenome, porém, em cujo caso uma tabela "name"
sozinha seria atômica o suficiente. Assim, quando estiver
dividindo a "coisa" da tabela em partes, pense em como os
dados serão usados, e não apenas no que eles representam.
<$ual t a principal
iósa que vote quer
que seja o assunta
da sua tabela?
Corno
a tabela?
vode ira
$ual e o vnodo
mais %>Lis
Aoftsultar essa
tabela?
Dadps atPUlicos sã.P
dadps <]ue {gram
díVidídPS ate a nietiPt
fpvma necessária
para um determinado
bancp de dados.
controle seus dados, controle seu mundo
Ao normalizar, pense emtermos de átomos^
Para ajudar a transformar as suas ideias sobre o projeto do
banco em ações, é útil fazer perguntas específicas aos seus dados.
Isso ajudará a determinar como os dados se encaixam na tabela,
e permitirá saber se eles realmente foram divididos até a sua
representação atômica apropriada. Ninguém disse que dividir o
átomo seria fácil, mas esta lista de perguntas poderá lhe ajudar.
JÜft
w
‘'V1
U1
V°S se-us
dados atômicos
e 9 p rim e iro
pctSS9 se
criar umatabela
normalizada.
1.Qual é a principal coisa que a
sua tabela descreve? a** ta
b
e
lad
e
se
rv
ea
v
ista
m
^
-k
»d
«
0V^ de uma lista de emails,
pc^tuadoes máximas de um videogame,
«ornes de româívfcidos inóuvâvcis?
2. Como você U S a t a a tabela para
chegar até essa principal
coisa?
3. As suas colunas contêm
dados atômicos, para tornar
suas consultas curtas e diretas?
XÃ9 existem
---------------------------------------------------------- " p e rg u n ta s id io ta s —
Elabore sua -tâbeia
de modo «*e ela seja
íádi! de donsultar!
Certi-fi^ue-sc de
«ue os dados sejam
apenas -fcao pequenos
Quanto rsedessario.
^ • Eu devo tentar dividir os meus dados até os
menores pedaços possíveis?
Como os dados atômicos me ajudam?
K-.Não necessariamente. Tomar os seus dados
atômicos significa dividi-los até os menores pedaços de
que você precisa para criar uma tabela eficiente, e não
até os menores pedaços possíveis.
Não dividia os seus dados mais do que realmente
precisar. Se não precisar de colunas extras, não as
adicione à toa.
í ^ t Eles lhe ajudam a garantir que os dados da sua
tabela sejam precisos. Por exemplo, se você tiver uma
coluna para o endereço de um avistamento de ETs, poderá
querer dividiro endereço em duas colunas: uma para a rua
e uma para o número. Então, você poderá certificar-sede
registrar apenas números na coluna referente ao número.
Os dados atômicos também lhe permitemexecutar
consultas de modo mais eficiente, porque as consultas
ficam mais fáceis de escrever e rodam em menos tempo,
o que é eficiente quando você tem uma quantidade muito
grande de dados armazenados.
você está aqui ► 463
normalize a banco de dados do mismatch
0 banco de dados do Mismatch está precisando ser normalizado, para resolver
o problema de nomes de categorias duplicados. Dada a estrutura existente do
banco, esboce um projeto modificado que resolva esse problema, eliminando
o risco de erros na inserção dos dados. Escreva comentários no projeto,
explicando como ele funciona.
user id
username
password
join_date
first name
last name
gender
birthdate
city
state
picture
illlliiljjjd ;j*j|
r
i I^ Q
jjt
jJ
S
response id v w
" topic id ^ i
response name
MW i l ) ^ » category
tooic iri
controle seus dados, controle seu mundo
TWgutitíis idiotas
1 • Como eu faço para aplicar o terceiro passo de normalização ao Mismatch, para
consertar o problema hipotético com a cidade/estado/CEP?
A solução é colocar os dados de localização do usuário em uma tabela própria, e
então conectar a tabela mismatch_user à nova tabela por meio de uma chave estrangeira.
Assim, você poderia criar uma tabela chamada mismatchJocation, com uma chave
primária locationjd, junto com colunas para armazenar a cidade e o estado do usuário,
por exemplo. Então, as colunas city ("cidade") e state ("esíadò") são removidas de
mismatch_user e substituídas por uma chave estrangeira locationjd. Problema resolvido!
O que faz esse design funcionar é que a coluna locationjd na verdade usa o CEP como
chave primária, eliminando o problema de dependência de colunas que não sejam chaves.
? • Caramba, isso parece um monte de trabalho só para atender a um
requerimento de projeto exigente. Isso é realmente necessário?
Sim e não. Os dois primeiros passos da normalização são obrigatórios, porque
os dados atômicos e as chaves primárias são essenciais para qualquer bom projeto de
bancos de dados. É no terceiro passo que vocâ passa a ter que pesar a atratividade
de um projeto perfeito, por um iado; contra as realidades práticas do que a aplicação
realmente precisa, por outro. No caso do problema com cidade/estado/CEP do Mismatch,
provavelmente vale a pena aplicar esse requerimento, pela simplicidade que ele
proporciona. Essa não é uma decisão a ser tomada sem pensar bem, e muitos puristas
defendem que você deve aderir estritamente a todos três passos. A boa notícia é que a
coluna com o CEP é puramente hipotética, e não faz parte realmente da tabela mismatch_
user, portanto não precisamos realmente nos preocupar com ela.
• Mesmo sem uma coluna para o CEP, não seria necessário mover city ("cidade")
e state ("estado") para as suas próprias tabelas, para atender ao terceiro passo?
í ^ ’ Possivelmente. Sem dúvida você acabará tendo dados duplicados, referentes a
cidades e estados, na tabela mismatch_user. O problema em separar cidade e estado numa
tabela própria, sem uso do CEP, é que você teria de preencher essas tabelas com todas as
cidades e estados existentes. Caso contrário, os usuários sem dúvida escreveriam alguns
nomes de cidades com erros ortográficos, e ainda acabaria tendo dados problemáticos.
Este é um bom exemplo de caso em que você tem que pesar seriamente o benefício da
normalização estrita contra a realidade de uma aplicação real.Uma interessante solução
possível para todos os problemas é usar o CEP na tabela mismatch_user, em vez de cidade
e estado, e então procurar a cidade e o estado em uma tabela estática ou em algum serviço
web, conforme necessário. Isso é mais complexidade do que precisamos no momento,
portanto vamos ficar com as colunas city (cidade) e state (estado).
existem
você está aqui ► 467
a base de dados mismatch—agora normalizada!
SoLuÇSo
0 banco de dados do Mismatch está precisando ser normalizado, para resolver o
problema de nomes de categorias duplicados. Dada a estrutura existente do banco,
esboce umprojeto modificadoque resolva esse problema, eliminando o riscode erros
na inserção dos dados. Escreva comentários no projeto, explicando como ele funciona.
h nova tabela para as
userjd
username
password
join_date
first name
last name
gender
birthdate
city
state
picture
Lembre-se, mismatch_
response e wmô "tabela
de junjao <ue donedta
os usuários às respostas
cyuC derâm 3os topidos.
0 restan te do
Alismatdh não
t a íe ta d o pelas
modi-fidaçoes has■
d a t e r a s e nos
tópidos.
dateyw ias arm azena os
nomes das d a t e r a s
separados dos topidos,
eliminando os dados
redundantes.
dategory__id © — rf
name
Ihlçiftatcfrtopic
topicjd 0 “ "jr
name
^gategery:
•>. tifejaryjd
Em vez. de arm azenar o nome da
dategoria em dada linHa de tópido,
agora nós armazenamos apenas uma
reíerendia (ft>) à linha, na tabela
das dategorias.
;
Cada linha de dategoria na
nova tabela tem uma relaçao de
um—
para—
muitos dom os topidoS
da tabela mismatdK__topid-
nÊb eXÍStfGl
perguntas idiotas
I * Como exatamente a nova tabela mismatch,
category resolve o problema de dados duplicados?
A nova tabela separa os nomes das categorias
da tabela mismatchJopic, permitindo que eles sejam
armazenados isoladamente. Com as categorias
armazenadas em tabela própria, não é mais necessário
duplicar os seus nomes - você tem uma linha para
cada categoria, e essas linhas são então referenciadas
por linhas da tabela mismatchJopic. Isso significa que
as linhas de categorias da tabela mismatch_category
têm uma relação de um-para-muitos com as linhas de
tópicos da tabela mismatchjopic.
T * - Então isso significa que mismatch_category tem
apenas cinco linhas, uma para cada categoria?
Sim, isso mesmo: r o i s m a t c h _ c a t e g o r y
0 nome de dada
dategoria só
e armazenado
umâ vez/
üSklàiii
mm
J d y liiP P »
1 Appearance
2 --- >
- Entertainment
3 Food
4 People
5 Activities
controle seus dados, controle seu mundo
Alterando o banco de dados do Mismatch
Para tirar proveito do novo schema, o banco de dados do Mismatch requer algumas
modificações estruturais. Mais especificamente, nós precisamos criar uma tabela mismatch_
category, e depois conectá-la a uma nova chave estrangeira na tabela mismatch_topic.
E uma vez que a velha coluna category da tabela mismatch_topic, contendo os dados
duplicados, não é mais necessária, podemos apagá-la.
Crie a nova -tabela ^ue irá
ârm az^nar os nor»e$ dâs
dategorias isoladamente-
category_id INT NOT NULL AUTO_INCREMENT,
name VARCHAR(48) NOT NULL,
PRIMARY KEY (category id)
a an ti5a doluna
tategoryj u»a vez.
agora irewos re-(-erend»3r as
tategorias a p a rtir de
tabela prêpriâ-
rateaorvjd
name
ALTER TABLE mismatch topic
ALTER TABLE mismatch_topic
^ « l i S Ü H i i l i i INT n o t n u l l
Edition« u»a
dKave estrangeira
dategory_jd, para
donedtar dada topido
a u»a dategcria da
nova tabela-
mismatch topic
8 Horror movies 2
9 Easy listening
music
2
10 The opera 2
11 Sushi 3
12 Spam 3
13 Spicy food 3
14 peanut butter
& banana
sandwiches
3
15 Martinis
16 Howard Stern 4
17 Bill Gates 4
18 Barbara
Streisand
4
- 4 — -
A nova tabela mismatch_category precisa ser preenchida
com os dados referentes às categorias, o que é feito através
de algumas instruções INSERT.
INSERT INTO mismatch_category (name) VALUES
(’Appearance'}
INSERT INTO mismatch_category
('Entertainment1)
(name) VALUES
INSERT INTO mismatch_category (name)VALUES ('Food')
INSERT INTO mismatch_category (name)VALUES ('People')
INSERT INTO mismatch_category (name)VALUES
('Activities'
)
A nova coluna category_id precisa, então, ser preenchida
com dados para ligar corretamente cada tópico à sua
categoria apropriada da tabela mismatch_category.
UPDATE mismatch_topic SET category id = 3
WHERE name = 'Martinis' E sta (V deve ser a nscsmâ ID
âutoindrem entâdâ «ue a dategoria
te » na tabela »isr*atdh__dategory.
você está aqui ► 469
O R f V e
test drive as tabelas normalizadas mismatch
Crie e preencha a nova tabela m ism atch_category.
Usando alguma ferramenta MySQL, execute o comando SQL CREATE TABLE da página
anterior para adicionar uma nova tabela, chamada mismatch_category, ao banco de dados
do Mismatch. Em seguida, emita instruções INSERT para preencher a tabela com dados
referentes às categorias. Agora, execute as duas instruções ALTER para modificar a tabela
mismatch_topic para que ela tenha uma coluna category_id. Finalmente, use UPDATE em
cada linha da tabela mismatch_topic, para que as suas colunas category_id apontem para a
categoria correta na tabela mismatch_category.
Agora execute um SELECT em cadauma das tabelas, sópara certificar-se de que está tudo certo.
Então, o Mismatch realmente é normal?
Sim. Se você aplicar as três regras principais
da normalidade a cada uma das tabelas do
Mismatch, verá que ele passa no teste com louvor.
Mas mesmo se não passasse, nem tudo estaria
perdido. Assim como nas pessoas, existem graus
de normalidade no que se refere aos bancos de
dados. O importante é tentar elaborar bancos
que sejam completamente normais, só aceitando
menos que isso quando houver um motivo muito
bom para burlar as regras.
O
e
e
Em todo o ba*do de
dados, os homes são
n3 sua
_____£orma mais atomida, €
f sâo repetidos
«*ais de uma doluna.
| user_id 0 “
username
password
join.date
first_name
last name
gender iiiäiSimftlliSili«
birthdate fjü responsejd ö “ "8
^
city I O response
state
------¥ id
/ picture
topic id
Certifique-se de que as suas colunas
sejam atômicas.
Dê a cada tabela a sua própria chave
primária.
Certifique-se de as colunas que nâo
são chaves não sejam dependentes
umas das outras.
Todas as tabelas tem
dhave primária
wum£vi£a; para ^ara^tir
a uhiôidãde-
Sem a bipotétidâ depe*de*dia Áo CEP, as doUas <^*e se reíerem
a lofiaiizadâo do usuário »ao tem mais probiemas de dependerias.
controle seus dados, controle seu mundo
O novo projeto
das tabelas do Mismatch não
afeta as consultas que estão
sendo feitas no código do
script do questionário?
O
i i ü « MÜHR891
category id O""-)*
name
// Obtém os dados de resposta do banco para gerar o formulário
$query = "SELECT response_id, topic_id, response FROM mismatch_response
"WHERE user_íd = . $_SESSION['user_id'
] . " ;
$data = mysqlí_query($dbc, $query);
$responses = array 0;
while ($row = mysqli_fetch_array($data)) {
// Verifica o nome do tópico correspondente à resposta na tabela dos tópicos
$query2 = "SELECT name, category FROM mismatch_top:LC " •
"WHERE topic_id = . $row[[topic_id'] . ";
$data2 = mysqli_query($dbc, $query2);
if (mysqli_num_rows($data2) ==. 1) {
$row2 = mysqli_fetch_array($data2);
$row[1topic_name'
3 = $row2['name'];
$row['category^name1] = $row2[1category'];
array_push($responses, $rowj;
questionnaire.php
Sim. De fato, a maioria das modificações estruturais em
bancos de dados exige que nós ajustemos quaisquer
consultas que envolvam as tabelas afetadas.
Neste caso, modificar o projeto do banco para adicionar a tabela mismatch_
category afeta qualquer consulta envolvendo a tabela mismatch_topic. Isso
ocorre porque o projeto anterior tinha as categorias armazenadas diretamente
na tabela mismatch_topic. Após colocarmos as categorias na sua própria tabela,
o que nós agora sabemos que é uma ótima ideia graças à normalização, torna-
se necessário rever as consultas e programá-las para trabalhar com uma nova
tabela (mismatch_category).
você está aqui ► 471
usando rotação com pontos
Ligue com pontos
Uma vez que osjoins envolvem mais de uma tabela, é
importante ser claro sobre cada coluna referenciada
em umjoin. Mais especificamente, você deve identificar
a tabela de cada coluna, para não haver nenhuma
confusão - diferentes tabelas frequentemente têm
colunas com os mesmos nomes, principalmente no que
se refere às chaves. Basta prefixar o nome da coluna com
o nome da tabela e um ponto. Por exemplo, eis aqui a
consulta INNERJOIN anterior, que cria um conjunto de
resultados de IDs de tópicos e nomes de categorias:
E ste e o Mwe dà doiuna dentro da
Anptaçãp com
pont°S lfee peO Tite
te îe îe n cîa t 3. tabela.
à-juEÜ a coluna
pertence, detiti'O de
umjoin. •
£ ste é o nome
da tabela-
0 ponto/ tabela, separado do nome da tabela
por um ponto-
SELECT
FROM mismatch__topic
INNER JOIN mismatch_category
isijiiij««
1® à £ IS ©wfcra reierendia â
^ _ tabila/èoiw na usando a
ta ç a o to*» ponto-
not
£ a^wi <ue o uso do ponto realmente
dompensa - os nomes dâs doiunas são
identidos^resultando em ambiguidade total
se vote nao espediíidar os nomes das tabelas.
Sem a capacidade de especificar as tabelas
associadas com as colunas, nesta consulta, nós
teríamos uma ambiguidade problemática. Na
verdade, seria impossível entender a parte ON da
consulta, porque ela estaria verificando se a coluna
category_id é igual a ela mesma, presumivelmente
dentro da tabela mismatch_topic. Por esse motivo,
é sempre uma boa ideia ser bastante explícito
na hora de identificar as tabelas associadas com
colunas, ao criar consultasJOIN.
n u.sm atch_ topic. c a te g o ry id
Sozinho, o nome da
doiuna rôo nos d»2- nada
sobre a ^ual tabela ele
pertende-
Pentro de uma
Consulta OÖlK, o
nome desta doiuna
lid a a»bí<
nao se esqueça
do ponto/
mismatch topic
i_category
(dentiiidar
a tabela
resulta em uma
donsulta Jö lK
mais expifdíta.
l i s l l ^ f c i s i i í í
1 l;-=A pp^àflce'‘ ':
2 ÏKt-ect^irî^jtiV.
3 i ■fo&p ' .. 1
... ilr'i-'-;"--
474 Capítulo 8
controle seus dados, controle seu mundo
Certamente podemos fazer mais comos innerjoins
Os innerjoins não servem apenas para combinar dados de duas Um
tabelas. Uma vez que um innerjoin é, em última instância, apenas T Q jf^ COOlLullâ
uma consulta, você ainda pode usar construtos normais de
consultas para controlar ainda mais os resultados. Por exemplo, linhas de duas
caso queira obter uma linha específica do conjunto de resultados
unidos, você pode colocar uma instrução WHERE na consulta
INNERJOIN para isolar apenas essa linha.
SELECT m is m a tc h _ to p ic . t o p ic _ id , m is m a tc h _ c a te g o r y . name
FROM m is m a tc h _ _ to p ic
INNER JO IN m is m a tc h c a te g o r y
tabelas usando
opetadotes de
c o m p a ra ç ã o eIfl
uma condiçap.
ON ( m is m a tc h _ to p ic . c a te g o r y _ id = m is m a tc h _ c a te g o r y . c a te g o r y _ id )
IsIIlimillflíf«ÍI4ÍÍHr«ííH
fllifíHlííiíli
Então, o que é que esta consulta retorna, exatamente?
Lembre-se, primeiramente, que a cláusula WHERE serve
como um refinamento da consulta anterior. Em outras
palavras, ela restringe o número de linhas retornadas pela
consulta INNERJOIN original. Para recapitulação, eis aqui os
resultados do innerjoin sem a cláusula WHERE:
Esta fioluna reíina
os (resultados,
iowo parte de
ur*a instrudao
WH£R£. '
M IDs dos
tópidos sao
e*traídas da
tabela mis^atdK
topií-
1 Appearance
2 Appearance
3 Appearance
4 Appearance
5 Appearance
6 Entertainment
7 Entertainment
8 Entertainment
Estas duas
dolunas
dofttvola«* a
juní-âo entre as
duas tabelas.

O i homes das
datejorías sao
retirados da
tabela mismatch
category.
A cláusula WEHERE tem o efeito de diminuir este conjunto
de resultados a uma única linha, aquela cujo tópico tenha
o nome igual a 'Horror movies' ("Filmes de terror"). Nós
temos de olhar novamente na tabela mismatch_topic para
ver qual é essa linha.
mismatch_topic
Esta linha
bate tom
a dlausula
HMERE.
I
I
I ,
cateqorvJd ^
n am e
I l f t M f l i i l
ta R K iiiM
l í ií iillp » « ®
íjí rtí1
iililiíííif«Kif rfriJ
I H p
—.
7 Professional 2
wrestling
C 8 Horror movies
9 Easy listening music 2
0 donjunto de resultados da
IKKEK JOIN original e reduzido
a esta linha solitaria, devido a
dliusuia WHERE-
$ (lausula ítfttERE restringe ^
os resultados da junção a
apenas uma linha-
você está aqui ► 475
Os joins sã9
mais eîîcîentes
Joins, ao trabalho!
Assim, osjoins possibilitam envolver mais de uma tabela em uma
consulta, na prática retirando dados de mais de um lugar e colocando-
se em uma única tabela de resultados. A consulta do Mismatch que IQeTlPS C-Qcll^P
cria um array de respostas é um candidato perfeito parajoins, uma vez j j.
que ela contém nada menos do que três consultas aninhadas para lidar X ~
com várias tabelas. Vamos começar com o código original:
reescrevendo a consulta com osjoíns
// Obtém os dados de resposta do banco, para gerar o formulário
$query = "SELECT response_id, topic_id, response FROM mismatch__response "
"WHERE user_id = '" $_SESSION[1user_id'
] .
$data = mysqli__query ($dbc, $query);
$responses = array ();
while ($row = mysqli_fetch_array($data)) {
// Verifica o nome do tópico correspondente à resposta, na tabela dos
tópicos
....................l i l
$data2 = mysqli_query($dbc, $query2);
if (mysqli_num_rows($data2) == 1) {
$row2 = mysqli_fetch_array($data2);
$row['topic name'] = $row2[J
áuas ultimâs
donsultas do dódi^o são
responsáveis por obter
os now>€s do topido e
da date^oría das suas
respectivas tabelas —
uma dotówlta por tabela.
// Verifica o nome da categoria correspondente ao tópico,
tabela das categorias
ip IiSilSiL
$data3 = mysqli_query($dbc, $query3);
if (mysqli_num_rows($data3) = = 1 ) {
$row3 - mysqli_fetch_array($data3);
$row['category_name'] = $row3[
“
array_push($responses, $row);
} Com utwjoin, t possível obter
ta«to o notme d o topido ^wanto o
dâ dategorsa, em
»uma so donsi»lta-
E aqui vai a nova versão do código, usando umajunçao:
// Obtém os dados de resposta do banco, para gerar o formulário
$query = "SELECT response_id, topic_id, response FROM mismatch^response " .
"WHERE user_id = . $_SESSION['user_id'] . "
$data = mysqli_query($dbc, $query);
^responses = array ();
while ($row = mysqli_fetch_array($data)) {
// Verifica os nomes do tópico e da categoria correspondentes à resposta,
respectivas tabelas
Síl
l l l i ...
llfíf
$data2 = mysqli_query($dbc, $query2);
if (mysqli_num_rows($data2) = = 1 )
$row2 = mysqli fetch array($data2);
^ — “ í
f
,
p  í
%
?
,
Í
S
m
Srow [1topic_name '] = $row2 [u
i
$row[1category_name’] = $rowá
array p u s h ($responses, $row);
| £ao usados aliases
h pâra ajudar a
sW plm dar o
dodigo.
A ID do tápido t usado doTMo
base para s donsulta prindipal,
»as a |D da date^oría dontrola o
próprio join.
47R Canítulo 8
controle seus dados, controle seu mundo
Não entendo, ainda
temos uma consulta extra que
procura o nome da categoria. Se
os joins continuam tão bons, por
que ainda precisamos de duas
consultas?
Nós não precisamos de duas consultas, pelo menos
não se usarmos todo o potencial dos joins.
E possível unir mais de duas tabelas, que é o que realmente
precisamos fazer no código do array de respostas do Mismatch.
Precisamos de uma única consulta que realize três coisas: obter
todas as respostas para o usuário, obter o nome do tópico para
cada resposta, e finalmente obter o nome da categoria para cada
resposta. O novo e melhorado código da página anterior realiza
as duas últimas em uma só consulta, que envolve umjoin entre
as tabelas mismatch_topic e mismatch_category. O ideal é que
tivéssemos uma única consulta, com doisjoins, para acertar os três
coelhos com apenas uma cajadada em forma dejoin.
RCÍCIO
Segue algum código capaz de obter dados de resposta do banco com apenas uma
consulta, graças ao uso inteligente dos joins. Seja inteligente e escreva a consulta
SQL que fará a junção entre as tabelas mismatch_response, mismatchjopic e
mismatch_category.
// Obtém os dados de resposta do banco, para gerar o formulário
Squery -
Sdata ■= mysqli_query($dbc, $query);
$responses = array();
while ($row = mysqli_fetch_array($data)) {
array_push($responses, $row);
>
você está aqui > 479
hora de brincar mismatch
0 «uestiortfirio
de Sidney está
preendHido,
an»ãz£nâdo e
pronto pava
ser usado ao
AliSnrvòtdVí
O Mismatch agora se lembra das respostas dos usuários,
mas ainda não está fazendo o que gostaríamos com
elas... como por exemplo formar pares!
O conjunto dos dados dos usuários só nos leva até metade do caminho
para formarmos pares imperfeitos. A aplicação Mismatch ainda
precisa de um mecanismo para disparar a flecha de Cupido no banco
de dados para encontrar conexões amorosas. Para isso, precisamos
examinar de alguma forma as respostas de todos os usuários no banco,
para ver quais formam pares imperfeitos ideais.
48 2 CsDÍtuio 8
controle seus dados, controle seu mundo
Encontrar um par imperfeito ideal
parece bem complicado, com todas
aquelas categorias, tópicos e respostas.
Tem certeza que é possível fazer isso?
Certamente; nós só precisamos de uma forma
consistente de calcular quantos tópicos dois
usuários quaisquer têm com respostas opostas.
Se elaborarmos uma forma razoavelmente simples de calcular
quantos tópicos respondidos de forma oposta dois usuários
quaisquer têm, toma-se possível fazer um loop através do
banco de dados, comparando usuários. A pessoa com o maior
número de opiniões contrárias a um determinado usuário é o
par imperfeito ideal para esse usuário!
= Par imperfeito!
Escreva abaixo como você faria para calcular a ’'desencoutrabilidade"de
dois usuários, usando dados armazenados no banco do Mismatch:
a lógica do mismatch
0 amor é um jogo de números
Como você deverá se lembrar, as respostas do Mismatch são
armazenadas na tabela mismatch_ response na forma de números,
com 0, 1 e 2 tendo significados especiais em relação a uma
determinada resposta.
¥
Adoro=
0
Odeio = 2
response^
response
user_id
Esses são os dados usados para se calcular a
desencontrabilidade entre dois usuários, e o que estamos
procurando especificamente é uma combinação de adoro
com odeio ou de odeio com adoro. Em outras palavras,
estamos procurando por linhas de resposta em que
response é um 1em oposição a um 2 ou vice-versa.
topicJd
Asegunda Coluna destas
iinbas c â resfosía, ^ue pode
sev O (ndorespondido), /
(adoro) ou 2 (odeio).
28 r ? > ® i ' I ’ I
29 4
30 5
31
. T O * 1 J 5 I
Uma
com binação
► 278 r < ; ¥ i i 3
| 279 i * i n i, j __j.
I 280 1ff 1
1 I 5 J
_J-----—
2
8
1 11 5
Uma vesposta adoro 0 ) Combinada dom uma
odeio ( X ) para o mesmo tópit o freality shows)
'resulta e» uma dombinatao posrtiva-
Ainda nos falta uma forma de determinar, através de código PHP, os momentos
em que ocorre uma combinação entre duas respostas. Certamente poderíamos
escrever algumas declarações if-else para verificar se há um 1 e um 2 ou então
um 2 e um 1, mas a solução pode ser mais elegante do que isso. Em qualquer
um dos cenários, adicionar os valores das duas respostas resulta no valor
3. Assim, podemos usar uma simples equação para detectar a combinação
desejada entre duas respostas quaisquer.
S e ile s p P s ta A + íle s p P s ta B = 3 , te m p s u m a c o m b in a ç ã o !
Assim, achar uma conexão amorosa acaba sendo mesmo uma simples questão
de matemática. Isso basta no que se refere a comparar as combinações
individuais, mas não atende ao problema maior de como realmente criar o
script Meu Par Imperfeito.
controle seus dados, controle seu mundo
Cinco passos para um desencontro com sucesso
Encontrar o par imperfeito ideal para alguém não é apenas uma questão de
comparar linhas de respostas. O script Meu Par Imperfeito tem de seguir uma série
de passos cuidadosamente orquestrados para formarmos pares com sucesso. Estes
passos são a chaves para finalmente satisfazermos os usuários e usarmos de forma
significativa as respostas que eles deram ao questionário.
A Obter as respostas do usuário na tabela
T mismatch response, certificando-se de juntar
I os nomes dos tópicos aos resultados.
À Inicializar os resultados de busca do
Mismatch, incluindo as variáveis que
registram o “melhor par imperfeito".
0 Fazer um loop através da tabela dos usuários,
comparando as respostas dos demais às do usuário
em questão. Para isso, comparar as respostas
de cada pessoa no banco de dados às respostas
correspondentes do usuário em questão. Um "placar"
mantém registro de quantas respostas opostas o
usuário tem em relação a cada pessoa.
i | Após cada ciclo do loop, analisar se o par
y imperfeito atual é melhor do que o melhor par
encontrado até agora. Em caso afirmativo,
armazená-lo como o novo "melhor par imperfeito",
certificando-se de arm azenar também os tópicos
em oposição.
£ Certificar-se de que um "melhor par imperfeito"
foi encontrado, e então fazer consulta para obter
mais informações sobre o usuário considerado
como o melhor par, e m ostrar os resultados.
você está aqui ► 485
introduzindo o logo for
Tudo o que precisamos é um loop FOR
O PHP oferece outro tipo de loop que tem exatamente a funcionalidade
de que precisamos para as comparações de respostas no Mismatch. Chama-
se loop for, e é ótimo para repetir algo uma determinada quantidade de
vezes. Por exemplo, os loops for são ótimos para tarefas de contagem, como
contar regressivamente até zero ou contar progressivamente até algum valor.
Eis a estrutura de um loop for, que revela o modo como o loop pode ser
estruturado para atravessar um array usando uma variável para contar ($i).
//nidializa o
doirfcador do
loop C
omum
deteirmihddo
valor, àh-tís
de o prodesso
domedar.
Inicialização
Começa o loop
com o contador,
$i, em 0.
Condição de teste
Só realiza outro ciclo do loop se
o teste avaliar como true, ou seja,
se $ifor menor do que o número
de respostas dos usuários.
Atualização
Atualiza o contador,
adicionando 1a $i.
$uâ!<^uer dódijo dolodado
d en tro das dhaves e
e*edutado em dada
«teraçao do loop.
N
A-função dountO retorna Atualiza o dontador
uma dofttay» do numero de adidionando I a ele
elementos do 3rr3y> o <^ue - isto e o mesmo <^ue
serve domo parte da dondidao dizer fi =. /, + J.
de teste do loop.
0 Passo 3 do script Meu Par Imperfeito faz a comparação de dois usuários através
de um loop através de cada uma das suas respostas, calculando uma "pontuação"
com base em quantas respostas são opostas. Com os pedaços de dados a seguir,
termine de escrever o loop for que calculará essa pontuação.
$user__responses
É o array com as respostas
do usuário.
$mismatch_responses
E o array com as
respostas do usuário que
é o par potencial sendo
considerado.
f o r < $ i = 0 ; $ i < c o u n t ( $ u s e r _ r e s p o n s e s ) ; $ i+ + ) {
i f ( +
$score
A pontuação a ser
calculada dentro
do loop.
) í
a r r a y _ p u s h ( $ t o p ic s , $ u s e r_ _ re s p o n s e s [ $ i ] [ ' to p ic _ n a m e 1] } ;
}
}
AQQ ©
controle seus dados, controle seu mundo
não existem
perguntas idiotas
1 • Por que não simplesmente usamos um loop foreach para
calcular a pontuação, em vez do loop for?
Embora um loop foreach funcionasse perfeitamente para fazermos
o loop através de todas as respostas, ele não nos forneceria um índice
(i$) em qualquer iteração do loop. Esse índice é importante porque o
código está usando tanto para acessar o array das respostas do usuário
A quanto o das respostas do usuário B, Um loop foreach eliminaria a
necessidade de um índice para um dos dois arrays, mas não ambos.
Assim, precisamos de um loop for regular, com um índice que possa ser
usado para se acessar elementos semelhantes de cada array.
* Qual é o propósito de se armazenar as repostas do usuário B
em um array próprio?
0 array com as respostas do usuário B é importante para que
os usuários saibam exatamente como eles se comparam com os seus
pares ideais. Não é suficiente simplesmente dizermos a identidade da
pessoa que é o par imperfeito ideal - melhor do que isso é dizer em
que tópicos específicos o usuário tem respostas diferentes das dessa
pessoa. Isso ajuda a dar um pouco mais de contexto ao resultado, e
permite que os usuários saibam um pouco mais sobre por que esta
pessoa em particular seria um par imperfeito tão bom.
• No Passo 5 do script, como seria possível não haver um
melhor par para o usuário em questão?
Embora improvável, você tem de considerar o cenário em que
haja apenas um usuário no sistema inteiro, em cujo caso não haveria
ninguém com quem comparar esse usuário.
você está aqui ► 489
exercício solução
0 Passo 3 do script Meu Par Imperfeito faz a comparação de dois usuários através de
umloop através de cada uma das suas respostas, calculando uma "pontuação" com
base emquantas respostas são opostas. Com os pedaços de dados a seguir, termine
de escrever o loopfor que calculará essa pontuação.
SOLUÇÃO
$user responses
^mismatch sponses
1 1 Hate Tattoos
2 2 Hate Gold chains
3 3 Hate Body piercings
4 Love Cowboy boots
5 Love Long hair
6 Love Reality TV
7 Hate Professional
wrestling
8 8 Hate Horror movies
76 1 1 Love Tattoos
77 2 Love Gold chains
3 Love Body pierdnqs
4 Love Cowboy boots
5 Love Long hair
6 Hate Reality TV
7 Love Professional
wrestJ/nq
U - 8 j Love Horror movies
!
------- -
$ variável fstore adaba
rxã -faixa de O (nenKu»
par endontrado) ate o
numero to ta l de topidos
(desendontro períeito)-
$ pontuaca© e
mdrementada a dada
resposta oposta
endontrada*
Lembre-se, o numero de
a p o s ta s do usuário é o mesmo
lue o numero Uiãi de tópidos,
unȉ vez.nue as respostas
direto do questionário.
f o r ( $ i = 0 ; $ i < c o u n t ( $ u s e r _ r e s p o n s e s ) ; $ i+ + ) {
if (fuser_responsesCfi3Ctr^sponse>
3 +?mismatdh__responses£fi3rresponse,J
fsdore +—Jj
; ' to p ic _ n a m e 1] )
a r r a y p u s h ( $ t o p ic s
— /

0 dontador do loop e
usado para se passar
através de dada
resposta do usuário-
f u s e r r e s p o n s e s [ $ i]
;
Cada topido dom respostas opostas
e adidionado a um array, para que
possa ser exibido ao usuário quando
o sistema !Ke apresenta o par
im períeito endontrado-
Fazer um loop através <fa tabela dos
usuários, comparando as respostas
dos demais às do usuário em questão.
Uma dombi«3£ao positiva
donsiste de um adoro
(j) dombinado a um
odeio (Xi, de modo que
adidionar os dois sempre
resulta em um valor 3,
daso haja a dombinaçao
produrada-
controle seus dados, controle seu mundo
Finalizando o desencontro B-six Sdript Qntomhrd o par
im períçito para o usuário^
O loop que acabamos de criar para calcular a pontuação de
desencontro faz parte de um script maior (mymismatch.php),o qual
cuida de encontrar o par imperfeito ideal para o usuário, e depois
exibir as informações.
mymismatch.php
// Só procura pelo par se o usuário tiver respostas armazenadas
$query = "SELECT * FROM mismatch_response WHERE user__id = '" . $_SESSION['user_
id'] .
So é possível adKar um par para o usuarto
" tiver respondido o Questionário-
if (mysqli num rows($data) != 0) {
$data = mysqli_query($dbc, $query};
// Primeiro, obtém as respostas do usuário a partir da respectiva tabela (JOIN
para obter o nome do tópico)
$query = "SELECT rar.response_id, mr.topic_id, mr.response, mt.name AS topic_
name " .
"FROM mismatch_response AS mr "
■ .
"INNER JOIN mismatch_topic AS mt " .
"USING (topic_id) " .
"WHERE mr.user_id = '" . $_SESSION['user_id']
$data = mysqli__query ($dbc, $query);
$user_responses = array 0;
while ($row = mysqli_fetch_array{$data) ) {
array_push($user_responses, $row);
}
■familiar )0fH e usado
para se o b ter o home do
topito, so se seledionar as
respostas do usuário.
0 array fuser__responses armazena
todas as respostas do usuário-
Il Inicializa os resultados da busca
$mismatch_score = 0;
$mismatch__user_id = -1;
$mismatch_topics = array(
)
E stas variáveis mantem
registro da busda do
Mismatch, a medida Que o
prodesso odorre-
Aguente -firme> ainda
tem muito mâis — virc
a pagina/
você está aqui ► 491
____ T fe S T O r iv e
faça um par imperfeito!
Encontre o seu par imperfeito ideal!
Modifique o Mismatch para que ele use o novo script Meu Par Imperfeito (ou
baixe a aplicação no site da Alta Books, em www.altabooks.com.br). Será preciso
criar um novo script mymismatch.php, bem como adicionar um item de menu
’’Meu Par Imperfeito" ao script navmenu.php, para que os usuários possam
acessá-lo.
Envie os scripts ao seu servidor web e depois abra a página principal do
Mismatch (index.php) em um navegador web. Certifique-se de que está logado
e quejá respondeu o questionário, e então clique no item de menu "Meu Par
Imperfeito" para encontrar o seu par.
I Si
A p%*a
Meu Par
jw.períe'fbo
de JoHa*
revela *ue
SidUey e o
seu oposto
per-ferfco.
AQA f^ a n ítu ín S
controle seus dados, controle seu mundo
Imas de Geladeira do Scfcema d» Banco
de Dados
Lembra-se da aplicação Guitar Wars, de séculos atrás? A sua tarefa é estudar o banco
de dados do Guitar Wars, o qual poderia se aproveitar de um pouco de normalização,
e criar um schema melhor. Use todos os imas abaixo para completar os nomes das
tabelas e colunas, e identifique também as chaves primária e estrangeira.
0 bando de dados
d€'tí'rw,í^ a exibiçào
dai pontuadÕes «a
página prwdípal do
éjui-tar Wars.
Eis o bando de
dados original do
g u itar Wars, o
^al arma«na
pohtua^ocs
submcildàs pelos
usuários.
você está aqui ► 495
ímãs do schéma do banco de dados solução
Imas de Geladeira d° scfcemado Bancp de
Dados - Solução
Lembra-se da aplicação Guitar Wars, de séculos atrás? A sua tarefa é
estudar o banco de dados do Guitar Wars, o qual poderia se aproveitar
de um pouco de normalização, e criar um schema melhor. Use todos os
imas abaixo para completar os nomes das tabelas e colunas, e identifique
também as chaves primária e estrangeira.
0 bando de
dados determina
a exibidao das
pOnt^dOCS *a
pâgind prindipal
do g u itar Wars.
A tabela
predisa de
uma dhave
primaria, Que
e uma p arte
importante
de QuaÍQuer
bando de
dados
normâlizado-
Uma v er Que o mesmo usuário
fode postar diversas pontuadoes;
a doluna «ame resulta em dados
redundantes- nada bom^
A nova doiuna
sdore_id serve domo
uma dbave primaria
muito nedessaria para
a tabela sdore.
A tabela sdore
re-ferendia os jogadores
através de uma nova
dhave estrangeira-
“O “-
As tabelas
a^ora
tem novos
nomes, uma
vez. Que
servem a
propósitos
mais
espedífidos-
IXmarelaya© dc
um—
para-'***»'
en tre jogadores
e pontuâ^oesj
0 nome de dada
jogador agora
é dividido em
primeiro nome e
sobrenome, para
ser mais atomido,
e só e armazenado
uma vez., nao
portando
Quantas
pohtuadoes o
oftador envie--
— — >
T A redundândia nos dados
V dos nomes dos usuários e
resolvida driando-se uma
«ova tabela para arm azenar
os nomes dos jogadores, a
Qual se donedía a tabela
^ Certifique-se de que as suas colunas sejam atômicas
0 Dê a cada tabela a sua própria chave primária.
0 Certrfique-se de as colunas que não são chaves
não sejam dependentes umas das outras.
K .
sdore através de uma dHave-
0 bando de dados do
éjuitar Wars não tinHa
nenKum problema de
dependèndía nas dolunas.
Bis aQui as regras mais uma vez,
3fe*as^para assegurarmos Que
vode nao as esQuedeu^
A
r

r
> o
controle seus dados, controle seu mundo
r^aVras-CtuzacUis ?B P & M / Sq L
Está preocupado sobre se o seu par imperfeito ideal ainda
está por aí esperando para ser encontrado? Tire esse
pensamento da cabeça completando estas palavras cruzadas.
Horizontais
I. Uma representação de todas as estruturas, como
tabelas e colunas, do seu banco de dados, junto com o
modo como elas se conectam.
4. Isto acontece quando múltiplas linhas de uma tabela
relacionam-se com múltiplas linhas de outra.
5. Isto lhe permite converter entre diferentes tipos de
dados PHP.
7. Use isto para combinar resultados de uma tabela com
os resultados de outra, em uma consulta.
10.0 processo de se eliminar redundâncias e outros
problemas de design em um banco de dados.
II. Você pode abreviar algumas instruções if-else com
este útil operador.
12. Quando uma linha de uma tabela relaciona-se com
múltiplas linhas de outra
Verticais
1. Uma junção possibilita nos livrarmos de joins.
2. Uma coluna, em uma tabela, que referencia a chave
primária de outra (em inglês).
3. Quando um formulário é gerado a partir de um banco de
dados, ele é considerado...........
6. Não é nuclear, apenas dados no menor tamanho
apropriado para um determinado banco de dados.
8. Linhas de duas tabelas têm esta relação quando há
exatamente uma linha em uma tabela para cada linha
da outra.
9. Um destes pode ajudar enormemente a se entender o
projeto de uma tabela.
13. Um nome temporário usado para se referenciar uma
determinada informação, em uma consulta.
você está aqui ► 4 9 7
palavras-cruzadas php&mysql solugäo
TalaVras-Cruzaclas fH F & M ySQ L
O
ylOA ft
controle seus dados, controle seu mundo
Sua Caixa de Ferramentas do PHP £ MySftl
Um bom número de novas técnicas
para bancos de dados MySQL foi
apresentado neste capítulo, sem
mencionar alguns novos truques
com o PHP. Vamos fazer uma rapida
recapitulação».
. ,t:' ;.•!
U**çs«^a* e
CAFÍTOLO
8
Um bom trabalho arriscado édifícil de encontrar
O novo site Riskyjobs.biz tem como missão ajudar as empresas a
encontrar as pessoas certas para os trabalhos mais arriscados oferecidos
por elas. O modelo de negócios é simples: para cada candidato que
conseguirmos achar para um emprego arriscado recebemos uma
comissão. Quanto mais combinações de candidatos e empregos
conseguirmos, maior o nosso lucro.
O Riskyjobs precisa de ajuda para melhorar a sua funcionalidade de
busca por vagas. Dojeito como está agora, ha um banco de dados cheio
de empregos arriscados só esperando para serem descobertos pelas
pessoas certas. Vamos dar uma olhada no formulário de busca do Risky
Jobs e no banco de dados subjacente, que contém asvagas disponíveis.
0 íormulâHo de
busCa ddiOhâ um3
Cor»sulta na tabela
riskyjobs, a qual
produra fo r empregos
que batam dom o
driterío de busca-
riskyjobs precisa de uma ferramenta de busca em seu site
Éste -Pormulario
de busca simples
dhama umsdript
que -Paz. a busca na
"tabela riskyjobs.
A tabela riskyjobs
Contem títulos
e descrições de
emprejos, junto
Com m-formaÇoes
sobre a
localização e a
data do anundio-
[ iü i l i i i i i l l i I lililM * « ! .™.p,ny.
=•
'
■
■
■
■ -
1 Matador Bustling dairy farm... Rutland VT 05701 Mad About Milk
Dairies
2008-03-11 10:51:24
2 Paparazzo Top celebrity... Beverly Hills CA 90210 Diva Pursuit, LLC 2008-03-24 10:51:24
3 Shark Trainer Training sharks to
do...
Orlando FL 32801 SharkBait, Inc. 2008-04-28 03:12:45
4 Firefighter The City of
Datavilie...
Dataville OH 45490 City of Dataville 2008-05-22 12:34:17
5 Voltage Checker You'll be out in the... Durham NC 27701 Shock Systems, LLC 2008-06-28 11:16:30
6 Crocodile Dentist Do you love
animals...
Everglades
City
FL 34139 Ravenous Reptiles 2008-07-14 10:51:24
7 Custard Walker We need people... Albuquerque NM 87101 Pie Technologies 2008-07-24 10:54:05
8 Electric Bull
Repairer
Hank's HonkyTonk... Hoboken NJ 07030 Hank's HonkyTonk 2008-07-27 11:22:28
A
, Cada
> t identificado
mdividuaUente atrases
da cKave primaria job_id-
Mostra os resultados
■^da busca!
502 Capítulo 9
stings e funções personalizadas
Ernest», nosso âtét^ào Weivo,
esta ^ar-^ado pov-^ue â sua Wsta
«ao esta p ro d u zid o 'resultados.
ponte seu lápis
Quando o formulário do Risky Jobs é submetido, a string de busca
é armazenada na variável $user_search, que é colocada na consulta
SQL abaixo para ser feita a busca propriamente dita. Escreva aqui
quantas linhas do banco de dados riskyjobs da página anterior
serão encontradas como resultado da busca de Ernesto.
$ s e a r c h _ q u e r y = "SELECT j o b _ i d , ti t l e , Sta t e , d e s c r i p t i o n FROM r i s k y j o b s
M
"WHERE t i t l e = 1 $ u s e r _ s e a r c h '
$ r e s u l t = m y s q l i _ q u e r y ( $ d b c , $ s e a r c h _ q u e r y ) ;
Esdrevâ sua vesposta a«uif
você está aqui ► 503
riskyjobs code setup
Tempo! Tire um momento para se fam iliarizar com o banco de dados
do Risky Jobs... e experimente fazer algumas buscas.
Baixe o arquivo riskyjobs.sql, da aplicação Riskyjobs, no site da Alta Books em www.
altabooks.com.br. Esse arquivo contém as instruções SQSL para criar e preencher a
tabela riskyjobs com dados de exemplo.
Após ter executado as instruções de riskyjobs.sql em alguma ferramenta MySQL,
experimente fazer algumas consultas para simular as buscas dos usuários. Eis alguns
exemplos:
SELECT * FROM r i s k y j o b s ^
SELECT j o b _ id , t i t l e , d e s c r i p t i o n FI
^ S€òa
Bull pi^Kiev ft/lstiadar”.
SELECT j o b _ id , t i t l e , d e s c r i p t i o n FROM r i s k y j o b s
WHERE d e s c r i p t i o n L IK E '% a n im a ls % '
O código-fonte completo da aplicação Riskyjobs
está disponível para download no site daAlta Books:
w w w . a l t a b o o k s . c o m . b r
506 Caoitulo 9
stings e funções personalizadas
Imos de Geladeira da CláusulaLÍKp
Temos um monte de cláusulas LIKE bagunçadas pela mesa. Você é
capaz de ligar as cláusulas com os seus resultados? Quais imas não
serão encontrados por nenhuma destas cláusulas LIKE?
Algumas fôderao itr
mais de wmâ <r«sposta.
LIKE '%test %'
LIKE '%Tipper Cow%'
Team M a s c o t
(M a s c o te )
R od e o C lo w n
( P a lh a ç o d e R o d e io )
Human C a n n o n b a l
( B a la Hum ana)
C a t H e r d e r
(Pastor d e G a to s )
....... ••■
-r
( P e t F o o d T è s t e r )
E x p e r im e n ta d o r de R a çõ e s p a r a A n im a is
( T o u r e ir o ) P o l i t i c i a n 1
C l í f f D iv e r
(M e rg u lh a d o r d e J ? e n h a s c o s )
C ra s h T e s te Dummy
(B o n e c o d e T e s te s d e Im p a c to )
( E n c a n ta d o r de S e r p e n te s )
( V ir a d o r d e V a c a s )
(C a ç a d o r d e T u b a rõ e s )
você está aqui ► 507
É M
T f c S T O R f v e ___________________
stings e funções personalizadas
Leve o formulário de busca do Risky Jobs para dar uma volta.
Baixe a aplicação RiskyJobs no site da Alta Books, em www.altabooks.com.br. O
script search.php contém o código para a geração das consultas, no qual você
acabou de trabalhar, e é usado para processar os dados de busca digitados no
formulário da página search.html.
Envie o script e os outros arquivos do Riskyjobs para o seu servidor web, e
depois abra o formulário de busca (search.html) em um navegador. Faça
algumas busca para ver como o seu código gerador de consultas se comporta.
Não se esqueça de testar a busca “Buli Fighter Matador”de Ernesto, que é um
bom teste para o novo código com implode().
Danger! Your dream job is out there.
Do you have the guts to go find It?
Risky Jobs-SearchResults
Job Title
Ptücfighter
Toreador
Electric Bull
Repairer
&
Description
UpandcoifiiBgsuperflygoat wightboxeraa
opponenttokelpbuilshiswinningneeas'd.Sk
sloppyhands,andaglassjawsibpreferred.No
experiencerequited.TWsisnotafell»t!nsssois
position.Wellmeetyoumthealleybehindthe
toshape,thepons.LetRocKingmakeyoua
championshipfighter.oratieastMp youloseto
©net
Lovelybovineswaitingforyearsuperiorjsoe-
violefitc&
pewavingskills.Mustpassbasicbull
fightiBgaptitudetest.
Hick’sHoakyTaskneedsaftexperiencedelestac
btdiropakcrjFiccndcsRafteryoufixit)ssdhalfofif
hotwusgsaresonseofthebenefits.
Eirnes-f» hâo en£or>-èrou
«media^a^chie o seu iv-abalho
avmdado períei-U »as cie
de+i«iiivairr,«híc esiá -farchdo
pro^vesso, agora <
^
u
c o siHpt
de busfia pv-oéutra pov- èada
ia-me mdividuaUenie.
podemos melhorara busca?
SeUa, equilibrista de
tordas bawbas,
está ie*<Ao multa sor-te
dom o -formulário de
busias do Risky Jobs-
0 S " te r m o s d a r a m e n 'f c e m o s t r á m
uma busóa por va^as para
equilibristas de dordas bambas
de dirdo, mas os resui'tados não
sao e/aíameri-te apropriados.
D
anger!V
ou
rdream;obisout(her«.
D
oyouhavethegutstogofindIt?
RiskyJobs. SearchResults
JobTifie
M aster C at Juggler
Tightrope Tester
Description
Areyt® a practitioneroftheJostart ofcatjnggjing? AZ
Bsnaed in forty cotrntries, only theJim Ruiz Circus
bastefiaed catjuggling forthe sophisticated tastes of
the modemaudience. Ply yourtrade with premierscat
jugglersat ourcircus,tie only placean eãtí) to master
sywdinmized catjuggling.It's fnie,juggling than ii
even haulerteas herdiEgitem. Wea m aa equal
©ppafttt&ityemployer,and look ibrward to addiag you
to ourteam. Pleasebe preparedto ondsi^o a thorough
battery oftests toproveyourdeft haadlingof felirses.
Only ttsecrean oftbe crop will be accepted iato our
MasterCatJugglerprogram,
I f th e t h o u g h t o f d a n g lin g & w h o u r s o h e n d 6 o m g r e z t M T
h e ig b t s is y o u r i d e a o f a g o o d tim e , th e n th i s j o b ju s t
m a y b e f o r y o u . E y & iy o r * o f o u r r ig b b o p e s g o «
th r o u g h n g o w o s a 4 3 p o i e t t e a , c u ln a tt a tin g i s a z e a l
l iv e fc u jn a a h a n g in g f e f a p r o lo n g e d p e r io d o f tim e .
T hat could b e ya a i W e do provide safety nets but
y«u*U need to b an g y o u r ow e helm et and gloves. Hens
s t o a r m anufactoriag anã tearing facility in B ig T op,
M ontana* w e offer a c icciedibie em ploym ent package
w itk fceoefits ranging fiom B ring Y ourP et to W ork
W eek and Fw m al Fridays. W e w fll need fluee
references, including you r verified sax im u i» bang
tim e and num ber o f past fails. W ere the ciictti behind
t is e c u c a s !
Stale DatePosted
2008-11-14
21:13:35
2008-11-14
21:17:16
ierá que o
iroblema são
|os termos
le busca, ou
Irealm ente
não há
vagas para
[equilibristas?
stings e funções personalizadas
aponteseu lápfs-------------------------- -------------------
Escreva abaixo a consulta SQL gerada quando Selma digita
"tightrope, walker, circus" ("corda bamba", "caminhante", "circo")
como a sua busca, e depois escreva quaisquer problemas que você
acha que poderão ocorrer.
você está aqui ► 517
préprocessando a string de busca
ponte seu lápis
Solução Escreva abaixo a consulta SQL gerada quando Selma digita
"tightrope, walker, circus" como a sua busca, e depois escreva
quaisquer problemas que você acha que poderão ocorrer.
SELECT * FROM nskyjobs
IfVttÊREdescription LKfc^K-tvopc,%#OR description Lf^E '%ydlkeví%í OR
description L|£E 'Vofcirdus'Jo
A£unÇ3©
e*plodeO usa
espaços to»o
delimitadores,
mâs não pega as
vírgulas.
/s vírgulas sao Consideradas tomo
parte dos -termos de busta, e nao
Como serradores entre os -termos.
unido termo de busda
«^ue esta realmente
sendo usado e Cirdusw
,
porque ele não tem uma
virgula acidentalmente
libada a ele-
Naovejo qual é o problema. Basta chamar a
função explode() duas vezes - uma para se livrar
dos espaços e a outra para se livrar das vírgulas.
O
A função explode() lhe permite dividir uma string em
substrings, mas neste caso nós já temos substrings.
Aprimeira chamada à função explode() nos deixa com várias
strings armazenadas em um array, portanto não existe mais uma
única string a ser explodida. E tentar explodir cada uma das strings
do arrayprovavelmente só criaria mais problemas. Emvez de
tentar resolver o problema do delimitador com várias chamadas a
explode(), o que nós precisamos é pré-processar a string de busca,
para reduzi-la a um único delimitador antes de sequer fazermos a
chamada a explode(). Então, essafunção poderá fazer o que faz
melhor - dividir a string usando um delimitador.
stings e funções personalizadas
Pré-processe a string de busca
Nós queremos passar à função explode() uma string que
ela possa dividir sem problemas, de uma só vez. Como
fazemos isso? Certificando-nos de que explode() só precise
se preocupar com um delimitador, por exemplo um
caracter espaço. Isso significa que temos de pré-processar a
string de busca, de modo que cada termo seja separado por
um espaço, mesmo que o usuário tenha digitado vírgulas.
Predisamos trans-formar
isto-..
tightrope walker circus
£er* vir^uias/
...nisto-
0 p té -p rPoesscin} etifco
p e rm ite <£ue
n p s liV rem og
d e Oc|3:ctctetes
ín J e s e jtlJ o s e ^U e
iP tn e n iP s o s d a d p s
m a is íá e e is d e
p r p o e s s c jí -
■para cxplodeO
nos -í-orneça isto/
nãQ e x is te m
$search words
-p e r g u n ta s Id lo t a s -
Podemos usar mais de um caracter como
delimitador, ao explodirmos a string de busca?
J ^ Z Sim, você pode especificar qualquer número
de caracteres para servir como o seu delimitador,
mas isso não é o mesmo que especificar diferentes
delimitadores, e não resolverá o nosso problema aqui.
Se usássemos explode(',$user_search) para dividir
a nossa string, isso usaria uma vírgula e um espaço
combinados como o delimitador e funcionaria se o
usuário digitasse “tightrope, walker, circus". Mas
falharia se ele digitasse “tightrope walker circus”.
Nesse caso, acabaríamos tendo apenas uma longa
string - nada bom.
Q ? Podemos simplesmente apagar as vírgulas,
em vez de transformá-las em espaços?
A:Isso Sófuncionará se os usuários separarem os
seus termos de busca com uma vírgula e um espaço,
e não podemos confiar que será sempre assim. Se
apagássemos as vírgulas, correríamos o risco de
transformar "tightrope,walker" em "tightropewalker", o
que provavelmente não encontraria nada no banco de
dados do Risky Jobs.
você está aqui > 519
php função str_replaceQ
Substitua caracteres de busca mdesejados
Se você pensar bem, o pré-processamento da string de busca no RiskyJobs
funciona de modo bastante parecido com o recurso de localizar e substituir de
um processador de texto. No nosso caso, queremos encontrar vírgulas e substituí-
las por espaços. Afunção str_replace() do PHP lhe permite fazer exatamente
isso, usando três parâmetros: o texto que você quer encontrar, o texto que deseja
colocar no lugar do primeiro e a string na qual você quer realizar a operação de
localizar e substituir. Eis um exemplo de str_replace() em ação:
Esta t a substring «ue
vote deseja substrtuir
$clean search =
* ('
milhares
—
e esta e a string a s«r
£ofo£ada no lugar da
pVi**<íVâ-
r
1centenas'
,
’
Ganhe milhares de reais logo no primeiro mês.
Candidate-selagora!');
V 0iccteWo parâmetro t a string <y*e será
— modificada- A^ui, estamos adtàonando um
poudo de verdade ao anundto» substituindo
M
mÍÍKaresMpor ^entends*.
Mas, e quanto às vírgulas na string de busca? Afunção str_replace()
trabalha igualmente bem na substituição de caracteres individuais:
Lembre-se, esta é a substring
*V
*e vode esta substituindo...
•e esta é a string
substituta-
<
r
$clean_search = str_replace(
' ,', ' '
, 1tightrope,
walker, circus’);
Sempre <ue aparefier uma vírgula nesta __
string, ela sera substituída por um espado.
Depois que este código for executado, a variável $clean_stiing
conterá a string “tightrope walker circus”.
Você vê algo suspeito nos resultados da função
str_jeplace()? Você acha que a substituição das
vírgulas por espaços irá funcionar da maneira que
queremos?
stings e funções personalizadas
Dado o código PHP abaixo, mostre qual seria o output do array $search_words
para cada uma das seguintes strings de busca. Certifique-se de escrever dados
para os elementos apropriados do array e risque os elementos que sobrarem
caso o array $search_words acabe contendo menos elementos.
$clean_search = str_ re p la c e ( ', ', '', $user_search);
$search_words = explode(' ', $clean_search);
bull,matador cape
$search words
3 cspatos;—
buli matador cape
$search words
$search words
você está aqui ► 521
exercício solução
Dado o código PHP abaixo, mostre qual seria o output do array $search_words
para cada uma das seguintes strings de busca. Certifique-se de escrever
^ » dados para os elementos apropriados do array, e risque os elementos que
ftCIClO sobrarem caso o array $search_words acabe contendo menos elementos..
SoLuçao
$clean_search = str_replace (', ', 1 1, $user_search) ; Este array tem
$search_words = explode(
' $clean search) ; fc a tres elementos
bull,matador cape
3 espatosf —
buli matador cape
Estes dois elementos do array «a
verdade esta© vadios, por òausa
da<weles dois espaços entras entre
ftâtador e tâft na string de Ws£3
$search words
$search words
bull , matador cape
Nova»>ehte, dois elementos
vazios, porque a vírgula e
substituída por uimespado.
X espatos'
buli,
matador, cape
$search words
stings e funções personalizadas
Ahn, não. O pré-processamento nos livra de caracteres
indesejados, mas, infelizmente, não resulta em um array
contendo apenas termos de busca úteis.
Lembre-se, o nosso objetivo é ter uma string em que cada termo de
busca seja separado exatamente pelo mesmo delimitador, um espaço.
Dê outra olhada no que aconteceu nos três últimos exemplos da
página anterior. Alguns dos elementos do array $search_words estão
vazios. Se tentarmos criar a nossa cláusula WHERE com os elementos
vazios, poderíamos acabar com algo parecido com isto:
SELECT * FROM riskyjobs
WHERE description LIKE '%bull%' OR
description LIKE '%matador%1 OR
'% %' OR
Errado! Eles vão encon
Se houver um único espaço, <
descrição de um emprego (e
menos um), esta consulta o e
como resultado. Assim, todos
dados do Riskyjobs serão en<
por esta consulta. Precisamos
vazios no array antes de pode
SQL para tomar o script de t
description LIKE 1% % 1 OR
description LIKE '%cape%1
B-sfós espaços irdo
Cht0h"tV
"3V
*fiãdâ CSpâÇo
«steja jjvesen-fce em taâd
díSÍri^áo dc figs
sa© um problema t Îànbo.
você está aqui ► 523
tirando itens vazios da busca
A consulta precisa determos de busca legítimos
A boa notícia é que não é muito difícil consertar os nossos termos de busca antes de usá-
los em uma consulta. Teremos de criar um novo array que contenha apenas os termos de
busca reais. Para isso, copiarem os todos os elementos nâo vazios do nosso array original
para um segundo array, e então usaremos este último para construir a consulta SELECT.
Para construir o novo array, podemos usar um loop foreach para realizar ciclos através
de cada elemento do array original, e depois usar uma declaração ifpara encontrar os
elementos não vazios. Sempre que encontrarmos um elemento não vazio, basta adicioná-
lo ao novo array. O processo se dá mais ou menos desta forma:
Eis o array original
dontém os -termos dc busda e
os elementos vazios Asados
feios espaços extras.
Estes dois elementos
vazios predisâm ser
eliminados^
Nós precisamos adicionar
algum código ao nosso script
para criar um novo array,
contendo apenas os termos
de busca não vazios.
0 novo array c menor,
porque ele dontem apenas
termos de busòâ ^eais —
nada de elementos vazios.
$final search words
stings e funções personalizadas
Copie elementos não vazios para um novo array
Agora, vamos dar uma olhada no código que copia os elementos não vazios
do nosso array Ssearch words para o novo array $final_search_words.
$search_query = "SELECT * FROM r is k y jo b s " :
// Extrai as palavras-chaves de busca e as coloca em um array
$clean_search = str_replace(1,', T '
, ?user_search);
$search_words = explode(
' $clean_search); / espaços usdndo
strjreplateO.
Faz. «m loop através de fiada
elemento do array ?searfih_j«ord.
Se o elemento nao estiver vazio,
fiolofia-o no array fika»ado ?fina!_
searfih words.
J
Após verificar que há pelo menos um termo de busca no array $search_words, o loop
foreach percorre o array, procurando por elementos não vazios. Quando encontra um,
usa o operador [] para adicionar o elemento ao final do array $final_ search_words. E
assim que o novo array é criado.
E depois? Bem, nós geramos a consulta SELECT da mesma forma que antes, exceto
pelo fato de que agora usamos o array $final_search__words em vez de $search_words:
// Gera uma cláusula WHERE usando todas as palavras-chaves
de busca
$where_list = array{); ,
if (count (
^fina'L-_search_■ l i ) > °) { Este é o mesmo tódiy><ueja
foreach as-$word) {-=£r* ^ a f
i
r
i
a
r a f
i
l
á
u
s
u
l
a
$where_list [
] = "description LIKE '%$word%'"; vVttERE da fio n su lta de bustâ,
$where_clause = implode(
' OR '
, $where_list);
mas desta vez- ele usa o novo
array ^i'maljsearfiK.jMords, <ue
*ao tonte** nenhum elemento
// Adiciona a cláusula WHERE à consulta de busca,
if (!empty{$where_clause)) {
$search_query .= " WHERE $where_clause";
v
a
z
i
o
.
Esse código nos fornece uma consulta de busca que
não possui mais nenhum elemento vazio. Eis a nova
consulta para a busca “buli, matador, cape” ("touro,
toureiro, capa"):
SELECT * FROM riskyjobs
WHERE description LIKE 1%bull%' OR
description LIKE '%matador%' OR
description LIKE '%cape%'
você está aqui ► 525
teste search.php
T tE JS T O R f V e
Atualize o script Search para que ele pré-processe a string de
busca do usuário.
Atualize o script search.php de modo que ele use asfunções explode() e
implodeO para pré-processar a string de busca do usuário e gerar uma
consulta SELECT mais robusta. Depois, envie o script para o seu servidor web e
experimente fazer algumas buscas.
Danger!YourdreamJobisoutthere,
Doyou have the guts to gd find it?
RiskyJobs -SearchResults
JobTitle
Tightrope Walker
Tightrope Tester
Description State DatePosted
Master Cat Juggler
Fledgling big top looking fcrtkiee-riikg profess*anal TX2008*11-14
with 1-3 years of experieace to pesfcim tightropes 21:16:19
acrobatics,with pudgy elephant. Willingness to sweep
excrement a big piss. Exeslleat fceueSti iccluding
mcdical aad dental pirns* 4G1 (k),stack ownmhip
and discount purchase plan,prescription coverage,
merchandise discount,shczt acd long term disability
insurance,life and business travel insuraae®, vkkm
discount p5aa*attis> and home jDsinance discounts*
medical care and dependent care eeiHfeniseEaeiiti
educational a»htance, paid vacation aad holidays,
and adaption assistance. Flexible starting salaries
based ob skilU aod abilities,experience aud
geographic market. Proraorioa opportunities based on
pezfonnaace. The only thing stopping you from the
highest winein the big tent is your desire and work
ethic™aisdyoux balance1Otherduties mclude
planning 4k■organizing wiias,handling minorelephaat
admicistation,processing consnsexst cards from
children.Leading by example (dca't tall!), showing
mitialiva and a sease ofurgency and being results-
drivexs help acispfeaticprofessionals become successful.
Ifyon want to be challenged and your talent needs
meatoriag and opportunity. Bicgliag Brothers can
©fieryou a fasttrack to success?
Are yon a prartitinuercf ths lost art of cat juggling? AZ
Banned in Sbrtyconntries,only the Jim R1112 Circus
has refined cat juggling for the sophisticated tastes of
the modem auditnce.PIy yourtrade with premiere, cat
jugglere at our circus, the only place on earth to inaster
synchronised catjuggling. It’s true,juggling them is
even harder than herding them. We axe. an equal
opportunity employer, and look fonvaid to adding you
to our team. Haase he prepared to undergo a thorough
battery of tests to prove yourdeft handling of felines..
Only the cream of the crop will be accepted icto our
MasterCat Jugglerprogram.
Ifthe thought of dangling forboms on end from great MT
heights is your idea of a good time, thee thisjob just
may be for you. Every oee of ourtightropes goes
through rigorous a 4-3poiat test, culminating la a real
^ W i i t Stka
f«- "^Wlro,*, „aii^
a9«-â p jf t í í
Cstâr ttotombrïvdo
a^tóios »ais relevâtes
/
200S-U-H
2 1 : 1 3 :3 5
2008-1144
2 1 : 1 7 :1 6
stings e funções personalizadas
Estou obtendo anúncios de emprego, mas
estou recebendo descrições enormes para cada
anúncio. Nao preciso de todas essas informações.
Talvez seja melhor eu tentar em hazardpays.com,
onde eles mostram apenas parte da descrição, e eu
posso ver mais anúncios por página.
Embora o Risky Jobs esteja fazendo um trabalho
muito melhor para achar anúncios, as enormes
descrições deles são um exagero.
O que realmente estã irritando Selma é que para ver mais
anúncios, em seu navegador, ela tem de passar por várias telas.
Não é necessário mostrar a descrição inteira de cada emprego
nos resultados de busca. O ideal é mostrarmos apenas parte da
descrição de cada anúncio, talvez apenas as primeiras frases.
Escreva abaixo como nós poderíamos diminuir as descrições dos
anúncios, de modo que eles não fiquem tão grandes nos resultados
da busca:
a função php substQ
Às vezes você só precisa de parte de uma string
Uma vez que a extensão das descrições de empregos no banco A íimçãp FHP
de dados do Riskyjobs varia bastante, algumas delas sendo muito 1 ,v ,
longas, nós poderíamos melhorar os resultados de busca reduzindo Su d Su J ô
as descrições a um tamanho melhor. E para não confundirmos os P o
usuários, podemos colocar reticências (...) ao final de cada uma, para PmTh
deixar claro que eles estão vendo apenas parte de cada descrição
Você passa à função a string original e dois números inteiros. O
primeiro é o índice de onde você deseja começar a substring, e o
segundo é a sua extensão, em caracteres. A sintaxe é a seguinte:
e-xtran-m os
p c ttte d e u m a
strin g .
s u b s t r ( s t r i n g , i n í c i o , e x te n s ã o )
5 t *
„„3 su b str eeKefar 1
tavae-teres a sevem
rcíornâdos-
No que diz respeito à função substr(), você pode pensar na string
como sendo um array em que cada caracter é um elemento
diferente. Considere a seguinte string::
$job_desc = 'Are you a practioner of the lost art of cat juggling? 1;
De forma semelhante a elementos de um array, cada caracter desta
string possui um índice, começando e 0 e indo até o final da string.
>ractioner of the lost art of cat juggljjiçr^
3 4 5 6 7 8 9...
Podemos usar esses índices com a função substr() para obter
partes da string:
Cowete «o ,__
4*) re-tovifte 3
tairatteres
ComcCe m t, W
lna
vez.<uenao espediíiiamos
o S
e
W
U
f
i
d
o
siy»iítca <uea -íU^aodeve
seguirate o -Pinal da sfcring.
"
r
â
»
. substr ($job_desc, 4, 3)
jpr substr($job_desc, 49)
substr($job_desc, 0, 3)
substr($job_desc, 0, 9
)
50 51 52
you
ing?
Are
Are you a
Extraia substrings do início ou do fim
Afunção substr() não se limita a obter substrings a partir do início de
uma string. Você pode também extrair caracteres começando do final
da string. A extração ainda correrá da esquerda para a direita; você
apenas usa um índice negativo para identificar o início da substring.
stings e funções personalizadas
Aç^^ou^a^practitioner of the lost art of cat juggljjijj?
-53 -52 -51 -50 ... ... -3 -2 -1
Eis alguns exemplos:
Comete £
»
* ^ ^substr ($job_descf -53, 7
)
vc'bo'T'^c"7tâ'rôt'tc'rcs-
Co»*M £ su b str ($job_desc, - 9 )
h*do 3 paHir dit
ponte seu lápis
Segue abaixo algum código PHP para gerar uma tabela HTML
para os resultados de busca do Risky Jobs. Termine o código,
cuja tarefa é limitar a descrição dos anúncios a 100 caracteres, e
também reduza o texto referente à data do anúncio de modo que
ele mostre apenas o mês, o dia e o ano.
echo '<table border="0" cellpadding="2">';
echo '<td>Job Title</td><td>Description</tdXtd>State</td><td>Date
Posted</td>'
;
while ($row = mysqli_fetch_array($result)) {
echo '<tr class=,,r e s u l t s ;
echo '
<td valign="top"width=''20%"> 1
.
$row [1title ’] . '</td>';
echo '<td valign~"top"width="50%">'
.
............................... .
’...</td>1;
echo ’
<td valign="top"width="10%">'
.
$row[1state'
] . '</td>';
echo '<td valign="top"width="20%">1
.
..... ...........................
. f</td>1;
echo '</tr>';
}
echo '</table>';
você está aqui ► 529
aponte o seu lápis solução
— ^Aporte seu lápis —--------- — — — -----------— ------------
0 1 Segue abaixo algum código PHP para gerar uma tabela HTML
> 0 lU p c l0 para os resultados de busca do Risky Jobs. Termine o código,
cuja tarefa é limitar a descrição dos anúncios a 100 caracteres, e
também reduza o texto referente à data do anúncio de modo
que ele mostre apenas o mês, o dia e o ano.
echo '
ctable border="0" cellpadding="2">';
echo ,<td>Título</td><td>Descrição</td><td>Estado</td><td>Data do Anúncio</td>'
;
, .n „ Coloque veiido^tias do £
i
*
a
l
,
while $row = mysqli fetch array($result)) { . .l f
- pava mdidar <

u
e «
s
t
o c
echo '
<tr class=''results">'
; afends p
a
i
r
f
c
e dè d
e
s
i
-
^
i
ç
a
o
echo '<td valígn="top" width="20%">' . $row['title1] . '</td>1; 1
echo 1<td valign="top" width="50%"> T
’...</td> '
}
echo '<td valign="top" width="10%">' . $row['State’] . '</td>';
echo '
<td vaiign="top" width="2 0 % " 1 0 ) ....
. '
</td>'
;
echo '</tr>'; Todos os dados dt d ití_
fosted domeçam tom M M -
} DD-MAA, o ^ue odufa
e*âta»einie fõ t
a
v
-
a
t
f
c
e
v
e
s
.
echo '</table>';
jvjptíl Geek
É possível dispensar a função PHP substr() e
limitar os dados da descrição na própria consulta
SQL. Para isso, usa-se uma função MySQL muito
semelhante, chamada SUBSTRINGO, a qual aceita
os mesmos argumentos que substr{). A única
diferença é que o índice começa em 1, em vez de
0. Assim, para obter o 100 primeiros caracteres
da descrição, usamos isto:
SELECT SUBSTRING(
job_description, 1,
100)
FROM riskyjobs;
A vantagem de usarmos a função PHP é que
teremos tanto a descrição parcial quanto a
descrição inteira disponíveis para nosso uso. Se
usarmos o MySQL, só teremos a descrição parcial,
e teríamos de criar outra consulta para obter a
descrição completa.
nao existem
p e r g im ta s i d i o t a
* Substr{) trabalha com valores numéricos?
Não, ela funciona apenas com strings.
Porém, se você tiver um número armazenado
como CHAR, VARCHAR ou TEXT, ao obtê-lo
através de SQL, esse número é tratado pelo PHP
como uma string, e não um número, de modo que
você pode usar a função substr() nele.
" P • E se o valor referente à extensão for
maior do que a string? Será retomada uma
string com espaços depois dela, para atender
ao valor da extensão?
Será retornada a string inteira. Mas a
função não insere espaços depois da string para
mudar-lhe a extensão. Por exemplo, o seguinte
código retorna a string 'dog': substr('dog', 0,10).
stings e funções personalizadas
T e js t O R í v e
Ajuste o script Search de modo a lim itar o texto exibido para
descrições e datas dos anúncios.
Modifique o script search.php de modo que ele passe a usar a função PHP substr()
para reduzir os textos de descrição e a data dos anúncios retornados pela busca.
Depois, envie o script paira o seu servidor web e teste-o com algumas buscas.
Selma esia tonixnixi
por<ue cia yodc V€y os resul-fcados
da sua busta se* iev- de passar
pelas enojes desoiçSes dos
ahundtos.
Oangerl Youf job is out there
Do you have ths guts to go find It?
RiskyJobs-SearchResults
Description State
JobTitle Description
Tightrope Walker top lcokbgfbr P " “ “ 1 ^
® -uiaaTt nfffKoeneiscc- tQperform tsga.tr,..
AZ 20084144
w tb 1-3 years, ofexpetisRcs tQperform tigktr
MasterCat Juggler Are you a practitionerpf* el°!
B&owedin forty cauatnes.,oaly the Jim Ruiz...
Tightrope Tester Ifthe t h o ^ t dasrfiM forhems oa « ri * » » g*at fcTF
„jbs& tb*.
Eurealmentegostaria de
ver os resultados classificados pela
data dos anúncios ou talvez por estado.
Eurealmente gostaria de achar um
emprego de toureiro em Vermont.
A data do anundio ‘
iambem
Íí ê o u u» fouo r*ais íádil de lev,
agcra ^ue »ostva apenas a daia
e k3o a hora de pos-kagew».
Como nós poderíamos mudar o layout da página
e a consulta para podermos classificar os
resultados pr data, estado ou títuio?
você está aqui ► 531
adicionando classificação à busca dos resultados
Podemosclassificarnossos resuHados commúltiplasconsultas
Para permitirmos que os visitantes classifiquem os resultados das suas buscas, é
preciso que eles possam identificar como querem os resultados ordenados. Talvez um
formulário... ou um botão? Na verdade, é bem mais simples que isso. Podemos usar
HTML para transformar cada cabeçalho de coluna, na tabela de resultados, em links.
Os usuários poderão então clicar no link para indicar por qual coluna eles querem
classificar os resultados.
Danger!Yout dreamjob t*outthere.
Do you have the girts togofind It?
RiskyJobs-SearchResult^
Description
lobTitle
Prizefighter
Toreador
ElectricBull
Repairer
ÍOS *3is &di!mc»ic
terias audios dlassi-Pidando os
resultados através desks dabedalhos.
Podemos -b-ansfovmav os dabedalhos er*
links ^ue perm
i-fcam 3os usuirios dlidar
hfilcs para ordenar os anundtos.
sL DatePosted
State
an MO
Up and coming suj™. ~4 c------ ~ r
opponent to help fetald Som t..
Lovelyb o v m esw aitm g fcry o w su i^ r^ -Y irfm t ID
cape waving skills. Must pass basic bull fight*...
Haflk'i Honky T eat needs an experienced elactiic
bull repaker. Free rides isferyc* fi* it) «adhal.-.
NJ
2008-11-14
2008-11-14
2008-1144
Nós podemos usar esses links para recarregar o mesmo script Search, porém com
uma consulta que classifique os resultados de acordo com o link clicado.Já sabemos
como usar ORDER BYpara estruturar uma consulta com resultados classificados. Se
criarmos diferentes consultas SQL para classificar através de cada coluna individual,
permitiremos que o usuário ordene os resultados alfabeticamente por título, descrição
ou estado, ou cronologicamente por data do anúncio.
Eis a consulta SQL para classificar os resultados alfabeticamente, pela descrição:
SELECT * FROM riskyjobs
WHERE description LIKE '%Bull%' OR description LIKE '
%Fighter%' OR
description LIKE ’%Matador%'
domando dlassi-Pida os
resul-tados da donsul'fca pelas
desdrições dos empregos, cm
ordem alíabétida dresdenie-
stings e funções personalizadas
você está aqui ► 533
ORDER BY ordena o resultado da consulta
[
— %Aponte seu lápis
OaIiiaSa Escrevatrêsconsultasdiferentesqueclassifiquemosresultados
^ 8^ OUIUyttU doR
jskyJobsdeacordocomotítulodoanúncio,oestadoea
data.Assum
aqueousuáriotenhadigitadoastringdebusca
"window,washer,skyscraper"("janela,lavador,arranha-céus").
SELECT*
W
H
ER
Edescription L|^E'%window7e>O
Rdescription L|^E'^wasHe^1O
R
description L|£E'%skysCraper%>
^ —
-^RPERByj©b_title
0 padrão de
O
RPERBVt .
.SELECT.ff.FR
O
/ytxkltyjefc».......................................................
ASCcndcnte W
H
ER
EdescriptionLjKE'%
w
ii?d?;w
%
’O
R
.descriptionL[^E.'.^Yí®?h,ç)P
R
.
(fcresiente)^ desdriptiwi L|^E ^^Craper%'
OmCSm©*V
iC
ORPER jo b jàtl*... ORDER BY.state
ASC.
SELECT ff FROM risk^jobs
WHERE description L(^E '%
Y/ihdovi%
JOR description L|^E '%yiasher%i OR
description L|^E t%sk^scraper%i
Com
opoderíam
osreescreveressasconsultassevocêquisesseverostítuloseosestados
emordeminversa?Esequisesseterosanúnciosm
aisnovosaparecendoprim
eiro?
/SELECT FROM risk^jobs
WHERE desÇription Lj^E t%
window%>OR desCription L(^E t%
y/asKer%
>OR
Poderíãmos
^ r estes, caso
Jâ tínhamos
classilicad© por
uma dâs CoíuhâsT
c entao o
usuário clica
nela novamente
pâra inverter a
ordem.
description Ll^E '%
sleyscraper%
*
ORPER BV job^tle.PESC
ff FROM riskyjobs
description LlJ^E '^^Ssher^ OR
description L(íxE ^skysCrape^*
. * r i sto > k
WHERE description L|£E ^v/indov^ OR description LÍ^E '%
y/asKer%
) OR
description Lj^E ^skysCrape^*
^ ORPER BV date_posted PESC
5 3 4 Canítitin Q
stings e funções personalizadas
Parece que vamos
precisar de ummonte de
código redundante para gerar todas essas
consultas. Será que não podemos evitar essa
situação de ter o mesmo código repetido
três, ou até mesmo seis vezes?
Sim. Embora seja verdade que precisaremos
executar uma consulta diferente sempre que o
usuário clicar em um link diferente, é possível
construir uma única consulta baseada no link clicado,
Na primeiravezque os resultados são exibidos, nenhum link
foi clicado ainda, portanto não temos de nos preocupar com a
classificação. Podemos simplesmente pegar aspalavras-chaves
submetidas no nosso formulário e construiruma consulta sem
ORDER BYOs resultados são exibidos com cabeçalhos clicáveis,
cada um dos quais com um link de voltapara o script, mas com uma
ordem de classificação diferente. Assim, cada link consiste de uma
URL com as palavras-chaves originais e um parâmetro chamado sort,
que indica a ordem na qual os resultados devem aparecer.
O que realmente nos ajudaria aqui seria criar a nossa própria
função personalizada, a qual possa pegar informações sobre o
modo de classificar os dados e retomar uma string com a cláusula
WHERE e ORDER BYnos seus devidos lugares. A nossa nova
função personalizada consulta o parâmetro sort para descobrir
como classificar os resultados da busca. Eis aqui os passos que a
função tem de seguir:
Pré-processar as palavras-chaves da busca, e armazená-las em um array.
O Opcionalmente, usar um parâmetro sort que diz à funçao qual coluna
usar para a classificação.
Livrar-se de quaisquer palavras-chaves vazias.
Criar uma cláusula WHERE contendo todas as palavras-chaves de busca.
O Verificar se o parâmetro sort tem um valor. Se tiver, anexar uma cláusula
ORDER BY.
Retomar a consulta recém-formada.
Isso pode parecer muito trabalho, masjá temos a maior parte do código escrito.
Só precisamos transformá-lo em uma função. Mas antes de fazermos isso,
vamos dar uma olhada no modo de escrever funções personalizadas...
você está aqui ► 535
escrevendo funções php personalizadas
As fimpões lhepermitemreutilizarcódigo A s íu n çs& s
Uma função é um bloco de código separado do resto do seu
código, o qual você pode executar em qualquer ponto do seu
código que quiser. Até agora, tem usado funções internas que
o PHPjá criou para você. explode (), substr() e mysqli__query()
são funções pré-definidas pelo PHP, e podem ser usadas em
qualquer script.
Mas você pode também escrever as suas próprias funções
personalizadas, para implementar recursos não fornecidos
pela linguagem. Criando uma função personalizada, você
pode usar o seu próprio código várias vezes, sem ter de repeti-
lo no seu script. Em vez disso, basta chamar a função pelo
nome, quando quiser rodar o seu código.
Segue um exemplo de função personalizada chamada
replace_commas(), a qual substitui vírgulas por espaços, em
uma string:
o nome da sua
W a© e vode tem
liberdade para esdolher o
nome quiser —íada—
o
o »ais descritivo possfvel-
runtao
.A
Para driar uma &
personalizada, vode a inicia
dom a palavra "lunctien
/
p e rso n a liz a d a s ljie
p e r m i t e m o r g a n i z a r
um p eclaç^ c[e
c ó d ig o "PH P p p f
n o m e , d e m o d o <jUe
V °ce p o s s a lreu tlllzá-
l o f a c i l m e n t e .
Um domunto de parenteses vem
j / ' ^ » / .A
depois do nome da -rwnÇao- vode
pode enviar um ou mais valores
para a sua -fundão na íorma de
ar^umehtos, dada um separado
por vírgula - «este daso, só Ha um
ar^umento-
function replace_commas($str) {
$new_str = str_replace(',', 1 1, $str)
return $new_str;
} Uma íundão é capaz, de retomar
um valor âo dod^o <^ue a dlnâmou -
neste daso, «os retomamos a string
alterada.
Quando estiver pronto para usar uma função personalizada, basta chamá-
la pelo nome e digitar, entre parênteses, quaisquer valores que ela espere
receber. Se a função tiver sido elaborada para retomar um valor, você
pode atribuí-la a uma nova variável, desta forma:
As dhaves indicam
onde estará o Codigo
àã íuhÇao, da mesma
íormâ domo em um
ou uma mstrudao.
oop
/s/ós passamos uma string
"tigKtrope, Vialker, dirdus'.
$clean_search = replace_coimnas('tightrope, walker, circus');
A -fundão retoma uma
nova string dom as vírgulas
substituídas por espaços.
stings e funções personalizadas
Construa uma consulta com uma função personalizada
Nósjá escrevemos a maior parte do código de que precisamos para criar
a função personalizada que irá gerar as consultas de busca no RiskyJobs.
Só o que falta é colocar o código dentro de um esqueleto de função
PHP. Eis a função personalizada build_query(): tstamos passando pava a íunçao
o array fuser__seardh <
^
u
c driamos
a partir dos dados diytados no
•formulário.
// Extrai as palavras-chaves de busca e as coloca em um array
$clean_search = str_replace(',T, ' $user_search);
$search_words = explode(
' $clean_search);
$final_search_words = array();
if (count($search_words) > 0) {
foreach ($search_words as $word) {
if (!empty($word) ) {
$final_search_words[
] = $word;
}
}
}
// Gera uma cláusula WHERE usando todas as palavras-chaves
de busca
$where_list = arrayO;
if (count($final_search_words) > Û) {
foreach($final_search_words as $word) {
$where__list [
] = "description LIKE '%$word%'";
}
}
$where clause = implode{1 OR $where list);
Kada de
«ovo dentro
da luhção/
// Adiciona a cláusula WHERE à consulta de busca
if (
!empty ($where__clause) ) {
$search_query .= " WHERE $where_clause";
____ /
*
JJ Ka verdade, isto a^ui e novo- £ a«w
eye retornamos a nova donsulta,
para «ue o dodíjo ^ue dHamou a
fundão possa utiliza-la
Afunção build_query() retoma uma consulta SQL completa, baseada na string de busca
passada a ela através do argumento de $user_search. Para usar a função, nós simplesmente
repassamos a ela os dados de busca digitados pelo usuário, e então armazenamos o
resultado em uma nova string, que chamaremos de $search_query:
Çsearchjquery = build_query($user_search)
í Isto nos permite dapturar o valor
V e^
u
e â nossa -função retorna, neste
daso, a nossa nova donsultâ-
£ste e o valor submetido pelo
usuário através do -formulário.
você está aqui > 537
F u n d e s F erso n allzad as E x p o stas
Na entrevista desta semana:
Funções personalizadas: o quão personaliza­
das elas realmente são?
entrevista com a função função personalizada
Use a Cabeça: Olhe, nós estamos todos
curiosos sobre uma coisa: o que há de tão
errado com código redundante? Quer dizer,
ele é fácil de criar, basta copiar e colar e
pronto.
Função Personalizada: Ah, nem me fale
de código redundante. Ele é simplesmente
feio e torna o seu código mais difícil de ler.
Issojá é ruim o suficiente. Mas existe um
motivo ainda muito mais importante para
se evitar código redundante.
Use a Cabeça: Que é...?
Função Personalizada: Bem, e se algo se
modificar no seu código? Isso acontece com
bastante frequência.
Use a Cabeça: E daí? As coisas mudam
o tempo todo. Você simplesmente vai lá e
conserta.
Função Personalizada: Mas e se a coisa
que se modificou estava no seu código
redundante? E ela estava em cinco, ou
talvez dez, lugares diferentes espalhados
pela sua aplicação?
Use a Cabeça: Não vejo qual é o
problema. Basta achar todas as ocorrências,
consertá-las e pronto.
Função Personalizada: Ok, tudo bem.
Mas e se você se esquecer de consertar uma
das ocorrências? Vocês, programadores, são
humanos. Se cometer um erro, poderá ser
muito difícil achar a fonte do problema.
Use a Cabeça: Sim, é claro que isso pode
acontecer. Mas como é que você ajuda?
Função Personalizada: Ah, aí está a
beleza de ser eu. Se esse código estivesse em
uma função, você só precisaria modificá-lo
uma vez. Uma vez, e pronto.
Use a Cabeça: Eu tenho que admitir que
isso é bem interessante. Mas ainda não vejo
por que eu deveria me dar ao trabalho de
usar você. Quer dizer, você é bem limitado,
não é? Você só consegue usar strings.
Função Personalizada: Ei, espere um
minuto aí, amigo! Eu posso usar qualquer
tipo de dados que você me enviar. Desde
que o meu código lide com eles da forma
correta, eu posso usar quaisquer dados.
Caramba, eu usei até um array no úldmo
exemplo. Eu diria que isso é bem sofisticado.
Use a Cabeça: Mas você retornou uma
string.
Função Personalizada: Eu posso retornar
qualquer coisa que você quiser. A questão
é aproveitar ao máximo o que eu posso
realizar, e me utilizar corretamente.
Use a Cabeça: Essa é outra questão.
Você é muito exigente. Você sempre quer
receber dados.
Função Personalizada: De onde você está
tirando essas ideias malucas? Você pode me
chamar sem nenhuma variável, se quiser, e
se eu estiver configurada dessa maneira. Se
você não quiser me enviar dados, é só não
escrever nenhuma variável nos parênteses
juntos ao meu nome, quando me criar.
Embora eu não consiga pensar em muitos
motivos pelos quais você não queira me
enviar dados, nem recebê-los de volta com
uma instrução de retorno.
Use a Cabeça: Acabou o nosso tempo.
Muito obrigado pela entrevista.
Função Personalizada: Não há de quê.
Eu vivo para servir. Ou será que sirvo para
viver? Ou vivo e sirvo? Sei lã, alguma dessas
coisas.
stings e funções personalizadas
T t e S T D r i v e
Modifique o script Search para que ele use a função build_query().
Crie a nova função builcLqueryO no script search.php, certificando-se de substituir o
código original por uma chamada à nova função. Envie o script para o seu servidor
web e experimente fazer uma busca no navegador, para certificar-se de que está tudo
funcionando bem.
Essa novafunçao personalizada build_query()
é legal, mas eía ainda não esta classificando os
resultados da busca. Será que nós poderíamos
adicionar outro parâmetro para fazer isso?
Sem problemas. Nós podemos passar dois parâmetros à
função build_query()) em vez de um só.
Nósjá estamos passando â função o argumento $user_search, que
contém os termos de busca do usuário. Agora nós precisamos de
outro argumento, $sort, que indica como classificar os dados. O novo
argumento $sort precisa controlar a ordem dos dados retomados
pela consulta nas seis maneiras que estabelecemos anteriormente:
classificando pelas colunasjob_title, state e date_posted da tabela
riskyjobs, tanto em ordem crescente quanto em decrescente. 'V
Nós poderíamos armazenar as strings de ORDER BYem $sort para 
indicar a ordem de classificação. Ou poderíamos usar os números de 1a
fV
os esColhemos
arbitrariamente
Csses números c os
seus significados.
tão e*isU»> regras
especiais sobre issoj
fora usar as suâs
esdoihas de forȉ
donsistente-
6 para representar cada ordem, desta forma:
Çsort == 1 ORDER BY job_title
$sort == 2 m ORDER BY job_title DESC
$sort == 3 ORDER BY state
$sort ==4 rn ORDER BY state DESC
$sort == 5 ORDER BY date_posted
$sort == 6 ORDER BY date_posted DESC
*fâ2L VftUrto j
sentido classificar
feia descrito dos
empregos, u»a
vez. <^ue a orde»
alfabética não
significa »uita Coisa
na descrícão.
Mas os números não são ainda mais crípticos quando alguém está lendo
o seu código? Sem comentários para ajudar, sim, mas há um motivo mais
importante para usarmos números aqui. Se usássemos strings ORDER BY,
os nossos dados apareceriam na URL do script como parte do link de cada
cabeçalho. Isso inadvertidamente revelaria os nomes das nossas colunas, o
que é algo que você não quer tomar público por motivo de segurança.
você está aqui ► 539
Permitindo ao usuário escolher a ordenação
Ok, eu entendi como o novo
argumento $sort funciona, mas como saber qual
valor de $sort nós devemos passar para a nossafunção?
Não precisamos obter essa informação como
^usuário?
Sim, o usuário precisa especificar o modo de classificar os
resultados, da mesma forma como ele especifica os próprios
termos de busca.
Aboa notícia é quejá sabemos como queremos implementar essafuncionalidade:
nósvamos transformar os cabeçalhos das colunas na nossa página de resultados
em links. Quando o usuário clicaem um determinado cabeçalho, como por
exemplo, "Estado", nós repassaremos à função build_query() o número referente à
classificaçãopor estado.
Mas ainda precisamos fazer com que a ordem de classificação vá do link até
o script. Podemos fazer isso quando estivermos gerando os links para os
cabeçalhos, anexando um parâmetro sort à URL:
Queremos redarregar esta páginá «uando
0s resultados da busda são gerados os usuários ditarem no dabeçalho de uma
como parte de uma tabela ttTWL, e è . td w * ?*ra tlassifidar os resultados, ^
por isso t^ue temos uma tag <td> a^ui. f portanto, temos de driar este formulário
V
$ s o r t _ lin k s .= '< td X a h r e f = " ' . $_SERVER[' PHPjSELF' ] .
' ?u sersea rch = ’ . $ u ser_ se a rch . ' & so r t= 3 " > S ta te < /a X /td > , ;
A nossa funçao build_<^ueryO
predisa das palavv-as-dhavcs  Nós repassamos dados para indidar a
de busda do usuário para dlassifidação desejada para a busda- Uma
exibir resultados, portanto, v«z. *ue este é o tink para a dlassifidadão
fornedemos essas informâdoes por estado, w
sort” e igual a 3.
através da URL.
Quando a página dos resultados é gerada, cada link (exceto ’’Descrição") tem a sua
própria URL personalizada, incluindo um valor sort para definir como os resultados
devem ser classificados.
<a W f~ K
seardh-php?userseardh-bull fighter matador&sort^/H
>
Danger! Yourdream job Saout there.
Do you have it » guts to go find it?
Risky Job«-Search Results
L
Job Title Description
Classifidar pela desdríção
nao Síria muito informativo,
portanto, nao ha motivo para
transformar esse dabedalho
em um lihk-
Date Posted
<a href^seardh.phpfuserseardh—
bull f ighter
matador&sort—
3W
> 1
„
<a href—
'seardhphpfuserseardh—
bull fighter matador&sort—
1
5 >
stings e funções personalizadas
O
Hm. Entendi como esses
links funcionam nas três primeiras
consultas, mas e quanto às outras três
ORDERBYsque classificam por ordem
decrescente? Onde elas ficam?
Joe: Normalmente, o mesmo cabeçalho permitiria ao usuário classificar
em ordem crescente ou decrescente.
Jill: Correto. Cadavez que o usuário clicano cabeçalho, este apenas
inverte a ordem.
Frank: Isso não significa que nós agora precisamos de umjeito de
manter registro do estado dos cabeçalhos a cadavez que o usuário
clica neles, uma vezque o cabeçalho precisará apontar para um link
diferente do link para o qual ele aponta atualmente?
Joe: Não entendi o que você quis dizer.
Frank: Bem, os cabeçalhos não fazem sempre a mesma classificação.
Por exemplo, sevocê clicar em "Título'1e ele classificar o resultado
pelos títulos dos anúncios, em ordem crescente, então o link precisará
se modificarpaia classificarpelos títulos, mas em ordem decrescente,
na próximavez que for clicado.
Jill: Éisso mesmo. Mas tenha em mente que cada tipo de classificação
tem um número na URLdo link, para que o script saiba qual tipo de
ordenamento usar. Euma vez que nós estamos gerando esses links,
podemos controlar exatamente quais números de sort colocamos em
cada link.
Joe: Entendo. Então o nosso desafio é estruturar de alguma forma o
nosso código, de modo que ele possa gerar o link correto baseado no
estado atual da classificação, certo?
Frank: Ah,já sei! Não podemos resolver isso com algumas declarações
if? Quer dizer, é para esse tipo de tomada de decisão que essas
declarações servem, certo?
Joe: Sim, issofuncionaria, mas estamos falando de várias decisões
envolvendo exatamente os mesmos dados - o tipo de classificação. Seria
muito bom se conseguíssemos bolar uma forma melhor de tomar essas
decisões, que não seja com um monte de declarações if-else aninhadas.
Jill: Muito bem observado, e esta é uma oportunidade perfeita para
testarmos uma nova declaração que eu descobri. Adeclaração switch
nos permite tomar múltiplas decisões, muito mais do que duas, com
base em apenas um valor.
Frank: Parece bom. Vamos tentar.
Joe: Concordo. Qualquer coisapara evitar declarações if-else
complicadas. Elas me dão dor de cabeça!
Jill: Sim, a mim também. Acho que a declaração switch pode ser
exatamente o que precisamos...
a declaração php switch
SWITCH toma muito mais decisões do queIF
A declaração switch oferece uma forma eficiente de verificar TjU]3 cÍBclclJ*3cão
um valor e executar um dentre vários blocos de código, rÍTT^Tr /
dependendo desse valor. Isso é algo que iria exigir um O *VXI v j i CQtlteUl
pequeno exército de declarações if-else, principalm ente em Utllct SCtle d e
situações envolvendo mesmo um número pequeno de opções. ,
Em vez de escrever declarações if-else aninhadas para verificar C A . E
cada valor possível, em vez disso, você escreve uma declaração <Jue e x e c u ta m
switch com um rótulo case correspondente a cada valor
possível. No final de cada rótulo case, você coloca a declaração Q liereilteS
break;, que instrui o PHP a sair da declaração switch inteira e bloc-og d e COcIlP'O
não considerar quaisquer outros casos. Isso garante que o PHP , , , -
irá executar o código em um e somente um caso. clepetlcletlclQ clP
Vamos dar uma olhada em um exemplo que usa switch: Val<?v d e u m a
^ _____ Este € O v
a
l
o
v<^ue 3 declaração V %-iaVel•
switch ($benefit codeT^Í swk*» verificando - ele
controla toda a declaração.
case 1:
$benefits = ’
Plano de saúde, 10 dias de licença médica';
break; A dctlaruS. Wtak <te ^ --- * * * ' j  ‘**“kdo
ao PHP para sair da °^ " do e c
c a s e 2 : instrução switch. iguala i-
$benefits = 'Apenas em caso de morte e esquartejamento, um mês
de licença remunerada'
;
break; Se você precisar fazer 3 mesma Coisa
g __■
*
■
*
- ' para dois cu mais valores, basta omitsr 5
case 3: declaração break ate chegar ao ultimo valor-.
case 4:
$benefits = 'Boa sorte!';
^uaisyer v
a
l
o
r
e
sarmazenados em
; fbeneíit^Cade ^ue nãosejam /, Z,
default: ^ °u -rarao Com ^ue o código
& padrão seja executado.
$benefits = 'Nenhum. '
;
>
echo 'Nós oferecemos(guatro)pacotes de benefícios';
echo 'O plano que você^selecionou: ' . $benefits;
Hso exatamente- Só existem tres pacotes,
uma vez. ^ue ^ e 4“sao a mesma Coisa,
devido ao fato de 3 não ter um break
stings e funções personalizadas
0 Risky Jobs tem uma nova função chamada generate_sort_links() que permite aos
usuários classificar os resultados de busca clicando nos cabeçalhos dos resultados.
Infelizmente, estão faltando partes importantes do código. Complete o código da
função. E não se esqueça dos números para cada tipo de busca:
1 = por título, crescente; 2 = por título, decrescente; 3 = por estado, crescente; 4 =
por estado, decrescente; 5 = por data de postagem, crescente; e 6 = por data de
postagem, decrescente.
generate_sort_links($user_search, $sort) {
$sort_links = '';
........ ($sort) {
case 1:
$sort_links .= '<td><a href = . $_SERVER['PHP_SELF1] . '?usersearch=' . $user_search .
'&sort=.... ">Título</a></td><td>Description</td>';
$sort_links .= r
<tdXa href - . $_SERVER[
'PHP_J5ELF1] . ■
'?usersearch=' . $user__search .
1&sort=.... ">Estado</aX/td>',
*
$sort_links .='<td><a href = "1 . $__SERV£R[’PHP_SELF'
] . '?usersearch=' . $user_search .
'&sort=.... ">Data</aX/td>'
;
case 3:
$sort_links .= '<td><a href = ’
" . $_SERVER[1PHP_SELF'
] . 1?usersearch=' . $user_search .
'&sort= ....'^Job Title</a></td><td>Description</td>';
$sort_links .= ’
<tdXa href = . $_SERVER['PHP_SELF’] . '?usersearch=' . $user_search .
'&sort=.... ">State</ax/td>1;
$sort_links .= '<td><a href = ”' . $_SERVER[
'PHPjSELF'] . '?usersearch=' . $user__search .
’&sort= ">Date Posted</a></td>'
;
case 5:
$sort_links .= '<td><a href ="’ . $_SERVER['PHPJSELF'
] .
'?usersearch='
.
$user_search
'&sort=...... ">Job Title</aX/tdXtd>Description</td>1;
$sort_links .= '<td><a href = . $__SERVER[1PHP_SELF'
] .
’?usersearch=’
.
$user_search
'&sort=.... ">State</a></td>';
$sort_links .= '<td><a href = . $_SERVER[1PHP_SELF'
] .
1?usersearch='.
$user_search
'&sort=.... ">Date Posted</a></td>';
$sort_links .= '<td><a href = "' . $_SERVER['PHP__SELF’] . 1?usersearch='
'&sort= .... ">Job Title</aX/tdXtd>Description</td> ';
$user search
$sort
_
_
links
1&sort= .
$sort_links
'&sort=
return
<tdXa href = ’
" . $_SERVER['PHP_SELF’]
.’^ S t a t e C / a X / t d ^ ;
<tdXa href = "' . $__SERVER[ 'PHP__SELF’]
">Date Posted</aX/td>';
'
?usersearch=' . $user search
1
?usersearch= $user search
Este e o tonjuft-bo padra© de
devera apôreòer caso
o usuário ainda nâo tenHa esÊolVido
unv mcbodo de classiftca^âo-
você está aqui ► 543
a função completa generatejsortJínksQ
«cícío
SoLuÇão
0 Risky Jobs tem uma nova função chamada generate_sort_lihks() que permite aos
usuários classificar os resultados de busca clicando nos cabeçalhos dos resultados.
Infelizmente, estão faltando partes importantes do código. Complete o código da funçãc
E não se esqueça dos números para cada tipo de busca: 1 = por título, crescente; 2 =
por título, decrescente; 3 = por estado, crescente; 4 = por estado, decrescente; 5 = por
data de postagem, crescente; e 6 = por data de postagem, decrescente.
generate_sort_línks ($user_search, $sort) {
$sort_links ' '; ^ ^ d }; signifida <uejá
elassifiçamos feio título, porta«to> agora
predisamos redlassifidar em ordem dedresdente-
($sort)
switçK
case 1:
$sort_links .= ’
<td><a href = . $_SERVER[’
PHP_SELF'
] . '?usersearch=
1&sort= .7r.__">Titulo</a></td><td>.Description</td>1;
$sort_links .= ’
CtdXa href = . $_SERVER[’
PHP__SELF*]
'6sort= .3.
. ">Estado</ax/td> 1;
$sort_links .= '<tdXa href = . $_SERVER['PHP_S£LF’]
'&sort= ^ .
. ">Data</aX/td>'
;
break;......
case 3:
$sort_links .= '<tdXa href = . $_SERVER[
'PHP^SELF1]
_
_">Job Title</aX/tdXtd>Description</td
$user_search
'?usersearch=' . $user_search
'?usersearch=’ . $user search
= '<tdXa href =
4*
$_SERVER['PHP_SELF'
;
">State</a></td>’;
= ’
<tdXa href = *
'
1 . $_SERVER[’PHP__SELF'
;
">Date Posted</a></td>'
;
'
?usersearch=' . $user search
search
search
1?usersearch='
?usersearch='
ctdXa href - "' . $_SERVER[r
PHP_SELF'] . ’?usersearch='
">Job Title</aX/tdXtd>Description</td>1;
= ’
<td><a href = . $_SERVER[’PHP_SELF'
]
.
. ">State</aX/td>'
;
= '
<tdXa href = . $_SERVER[’PHPJ3ELF1]
.
. ">Date Posted</aX/td> ';
1
?usersearch='
$user
$user
$user
'&sort= _
$sort__links
'&sort= .
$sort_links
’&sort= .$
. break;........
case 5:
$sort_links .=
1&sort= .I
$sort_links
’&sort=,
$sort_links
’&sort=,$
. break;......
default;
$sort_links .= ’
CtdXa href = "’ . $_SERVER[’
PHP_SELF'
’&sort= .í
... ">Job Title</aX/tdXtd>Description</,
td>';
$sort_links .= '<td><a href = '
” . $_3ERVER['PHP_5ELF'
] . ’?usersearch=1
'&sort= .
. ">State</aX/td>1;
$sort_links .= '<td><a href = . $_SERVER['PHP_SELF'
] . '?usersearch='
'&sort= .5.
. ">Date Posted</aX/td>1;
^ Se /sort ainda não tiver sido definido
ou se for igual a Z, 4*ou ^ »»os temos de
exibir os links originais <ue dlâssifidâm os
dados em ordem dresdente-
search
search
'
?usersearch=' . $user search
'?usersearch=' . $user search
$user search
$user search
return /sort links
H a build.queryO a capacidade de classificar
Agora nós temos duas funções para lidar com as buscas no RiskyJobs. build_query()
constrói uma consulta SQL com base em termos de busca digitados pelo usuário, e
generate_sort_links() gera hyperlinks para os cabeçalhos do resultado da busca, os
quais permitem ao usuário classificar os resultados. Mas build_query() ainda não está
totalmente pronta, uma vez que a consulta gerada por essa função ainda não faz a
classificação. Afunção tem de adicionar uma cláusula ORDER BYà consulta. Mas precisa
ser a ORDERBYcorreta, conforme determinado por um novo argumento $sort:
Agora nós estados passa«do o
argumento fsort para a nossa
função, ale*» de fuser_search-
stings e funções personalizadas
function build_query($user_search, |1|111ÍÍ {
$search_query'= "SELECT * FROM riskyjobs";
// Adiciona a clausula WHERE a consulta de busca
if (!empty($where_clause)) {
$search_query .= ” WHERE $where_clause";
Eis a^ui as adições ao códig<
de build__^ueryO. Esta
dedaraçao switch verifica
o valor de fsort e adiciona
a instruto ORDER BŸ
Correspondente ao f inâl da
Consulta de busca-
iSSlw iR B w il
««»—
return $search_query; Kos retornados ?seârCh__^uery Como âhtes, más
desta vez. com u*a cláusula ORDER B / ao f inal
guando os usuários
carrega«* a pagina de
resultados se» clicar
Cm henKu» cabeçalho,
fsort estará vazio,
portanto, nós nào
classificamos os
resultados por padrão-
você está aqui ► 545
teste o scirpt revisado search.php
T fe s T O R tv e
Reelabore o script Search para que ele use as duas novas funções
personalizadas.
Crie a nova função generate_sort_links() no script search.php e depois adicione o
novo código à função bmld_query() ,para que ele gere uma consulta com resultados
classificados. Não se esqueça de fazer a chamada a generate_sort_links() no script, no
lugar do código que ecoa os cabeçalhos dos resultados.
Envie o script ao seu servidor web, abra a página search.html em um navegador e
experimente fazer uma busca. Agora clique nos cabeçalhos das colunas da página de
resultados para classificar os anúncios com base nos diferentes tipos de informações.
Não se esqueça de clicar no mesmo cabeçalho mais de uma vez, para alternar entre a
ordem crescente e a decrescente
A -Punção build_jueryO pega os -termos
de busca <
i»e o usuário digitou, e*p!ode a
Consulta e*» um array, remove «yuâis^uer
sfcrings vazias do ârray, e Cria uma
Consulta Com os termos e uma
ORPBR 2>i Correspondente ao valor de
Risky Jobs *S classificação; se Houver
Findyottrriskyjoj
iBuli n g h w Majador
AfunÇao
generate__sort_
linksO gera
os cabeçalhos
clicáveis, mcluindo
o empacotamento
das opções de
classi-Hcaçao na
URL- de cada link.
OangsrlYourdreamjol» oatthere.
DoyouHavemegirt»togofindit?
Risky Jobs - Search Results
Job Title Description State Date Posted
Matador Bustling dairy £mn lookisgforpart-tkaematadora/ VT 26084)3-11
entertain spirited bull withnald cajeofADO.
Firefighter The CityofDatavilleislurk";;iiiefjglitBivNo OH 2003^5-22
experienced required-you will be traised,Nor cmo
EleciricBull Hank'sHcmlryToni needsan experienced eketric XI 2008-11-14
Repairer bidJropaiiBr.Freendes(afteryou fix it’;.'irif ael..
Agora
eu consigover os anúncios
maisantigos, aqueles emque os
empregadores estao ficando realmente
desesperados para achar umtoureiro
em Vermont.
O
stings e funções personalizadas
Masàs vezes eu tento
fazer uma busca mais
ampla, e os resultados
são muitos.
O o
It®
Danger! Your frwm job Uoutthere,
Do you Dwe the 9® » to 8° Ow* *t?
RiskyJobs-SearchResults
JobTitle
Custard Walker
Description State
1st» t urn
bo&ddo de
anúncios
pairâ uma só
P«ssoa lev* dc
u»>«| S
O
Weneedpeople willingto testthe theorythatyou can MM
walkdo CBSffiid-WcVegoingto fill a sm..<
Training sharksto docate-tricksfortheaudjsece*atoat FL
newtvatartben®parit,You’il speadtils...
Ÿoolî beout in tisefieldcitEckiugax,aaddjc,foliages XC
io tbsjcasgeof3 to250 ormore volts. Y...
Yol'II heiartaOÎDg mtcnr.zsmá Q&eriuetaííic FL
broadcast içeeívíBgsquipaieat c
t
oth» loois. ofMiami—
Eicpkaji'.ProctoiogUr N&Kfcd:experienced proctologist-wiM'sagto-swsi with CA
lajgeaaiaiiik.Efepfeactsatourzoo (in San Fr.„
Setairplanesceeding engine«deseed.fa seed cícieac- TX
naaited individualswiHiegto baisdle rnsiaa...
Buntijagdaiiy fami ïookiag forjrart-tiajamatnderlo VT
entertainspirited,bull with mild c®æofADD. ...
Top celebrityphotographyfera looidag Sirseasoned CA
-------*- llrwcvrtrine
Sharis Trainer
WUagcC
h
e
c
k
e
r
Aclencifcitalícr
AkplansEngine
Clearer
Matador
Püpnraîszo
Tigbtroçc Waite-
C
ï
w
s
d
i
î
eD
e
n
t
i
l
* —o — - I---------
■w
ith i-3 jfeafsofexperience toperformtlghtr...
Do you kffteanimalsandhutsplaque?Well,thentfeii PL
might be thejob foryou! Ourcrocodik feno.,
.Mime WBueeds«»iBiiítEshnew£a£8s.Rjllhaa5íkÍE&ní&Ece NY
and shits padsprovided.Must tove kids....
PetFooc Tester Wapride ourselveso«sbow good ourp«tfoodtastes. MO
Newyoucan help mshxourproductseven better.
Toreador Lovelyisovines waiting foryour superioroon-viclect ID
cape ivaviug skills.Mustpas*basicballfigfeti...
ElectricBull Rjepaiter Hack'sHanky Took aeedi an experiencedelectric buli HJ
iw. fiee rides tafteryou fix it) andbal..
CityofDatavillekhiring firefigbtejvNo OB
«<«1«™
*r . tf0a<yiube rraÍBad.Nba^ano.
« R E S R Q
B k * juggling? A2
Como será que os outros sites Í
evitam ter muitos resultados em "
uma mesma página?
DatePosted
2008-07-24
2008-04-28
2008436-28
2008-09-04
200840729
2008-08-17
2008-03-1j
2008433-24
2008-11-14
2008-07-14
200S-1Î-02
2008-11439
2002.1144
2008-07.27
2008-05-22
2008-11-!á
200S-Î1-Ï4
2008*13-14
use paginação para mostrar os resultados
Podemos paginar os nossos resultados
Atualmente, nós estamos exibindo todos os nossos resultados
em uma só página, o que é um problema quando uma busca
encontra muitos anúncios. Em vez de forçar os usuários a irem
de cima a baixo em uma página enorme para ver todos os
resultados, podemos usar uma técnica chamada paginação para
exibi-los. Quando você pagina os resultados, divide o conjunto
de resultados em grupos, e então, exibe cada grupo em uma
página web separada, desta forma:
Cada tnosforâ iindo
resul-fcados»jwvio Ê
on» links para
se âôessar as ou-brd* pâginâs de
resul-fcados. Os usuários pode»
•Taiiin*e»vke dlidar para adessar
cada pagina, sem predisar íifiar
subindo e destcndo tom o mouse-
VoJiage Checker
Anlcarta Iisstalier
Tm
inLB
gsrta
our aewwnti Job Title
You'll be on A ndjK ta,™ «
intbenm
ga C
ta
m
e
r
Y oullbcis Matador
b
r
o
a
d
c
a
s
t
n
Etephmt Rroctologisl Needed:ex Papam ^
la
rg
ea
iiiß
is
<-12 34 ->
Risky Jobs-Search Results
£stes links
fermiicm <
^
uc
os usuários
naveguem
airaves de
varias paginas.
A pogii
TigbtnppcW
a&
jei
Crocodile Dentist
<-1234 ■>
T " "
A farina aiual
AÍ f
Y
Ú
O C urn
link - esta e a
se^unda pag'ma
de resul'tados.
m
pfc, JébTíüe
will Mime
Don
Pet fvscniTester
Dsscnpöon
Weneedsomefreshecw Fall beallfemsBcasoe
««IshinpaäspravltieiLMustlovekids—
W
eptidC
:rm
jT
W
jlvcias howgoodcarpet foo4tastes,
you.can kelp aafagoarproducts even better....
Toreador Loveiy bovines nom-v'iolca' ID
capeTüiiricg sldiJa-Mustpassbawibtill figitj...
Electric Bull Rcpiijct: ilaalc’ftffenky Tdnk needs ao expcrisoced eleetfiisboil NT
spssra,Free fitteryoufixit)andfcsL.
F
L
nsfiglsieT
<-12 34->
ofDstavülei
expetijecõedreqi
Isso é ótimo, mas como nós dividimos
os nossos resultados emgrupos? Anossa
consulta SQL retorna todos os resultados
encontrados pelastring de busca.
in a ç a p
d!V ide og
re s u lta d o s e m
g ru p o s, e e x ib e
c a d a g r u p o e m
uma págfna
Web prppria.
Nós precisamos de uma consufta que
retorne apenas um subconjunto dos
resultados, e não todos eles.
Afortunadamente, o SQLjá nos oferece uma
forma de fazer isso: a cláusula LIMIT. Vamos
rever LIMIT e aprender como podemos usá-la
para dividir os nossos resultados em grupos de
cinco...
stings e funções personalizadas
Obtenha apenas as linhas dequevocê precisa com UMIT
Achave para controlar quais linhas nós iremos exibir em uma dada página é adicionar
mais uma cláusula à nossaconsulta de busca, a cláusula LIMIT. Para obter um máximo
de cinco linhas, nós adicionamos LIMIT 5 ao final da nossa consulta, desta forma:
SELECT * FROM riskyjobs
ORDER BY job_title
Sc» Ufoâ dâttSulâ
C
sta donsulta retorní»
_os os anundios do
bando de dados, o ^ e e
equivaleu-te a produrar sen*
nenhum ‘
te'rvno dc bwsda-
£o retorna os dindo primeiros
resultados, nao importando
quantos tenham sido reaImente
endontrados.
Sevocê se lembrar, nós usamos a função personalizada build_query()
para criar a nossa consulta no Riskyjobs. Para forçá-la a exibir apenas
os cinco primeiros resultados, nós simplesmente adicionamos LIMIT
5 ao final da string da consulta, após esta ter sido criada:
$query = build_query($user_search, $sort);
/^didionar uma í-láusulâ i~|A1|T âo íinâl dc
umã donsulta limita Onumero de Imhas
retornadas por ela, neste taso a dindo.
Isso funciona bem para se obter as cinco primeiras linhas dos
resultados, mas e quanto às cinco linhas seguintes, e às cinco
linhas depois dessas? Para obter linhas posteriores no conjunto
de resultados, temos de modificar um pouco o nosso LIMIT. Mas
como? LIMIT 10 obteria as 10 primeiras linhas, portanto isso não
funcionaria. Nós precisamos obter as linhas 6 a 10, e para isso nós
usamos LIMIT com uma sintaxe diferente. Quando você fornece
dois argumentos a LIMIT, o primeiro controla o número de
linhas que quer pular, e o segundo controla o número de linhas
que você recebe. Por exemplo, eis o modo de obter as linhas de
11a 25, o que seria a terceira páginas dos resultados:
$query = build_que3ry ($user_search,
$query = $query
L J M rr
c o n s o la <juaís
e q u a n t a s
lín h a s s
re to rn a d a s
u m a c o n su lta
S Q L ,
0 primeiro argumento
di2. a L~/VT quantas
linhas pular - as dez.
primeiras.
Ô secundo argumento
dontroia quântas linhas
são retornadas —dindo,
o mesmo que antes.
você está aqui ► 549
use LIMIT para ajudar nos resultados de paginação
Controle os links das páginas com LIMIT
Uma tarefa importante da paginação é fornecer links que permitam ao
usuário navegar entre as diferentes páginas de resultados. Nós podemos usar
a cláusula LIMIT para definir os links de navegação na parte de baixo de
cada página. Por exemplo, os links "próximo" e "anterior" podem ter, cada
um, o seu LIMIT. O mesmo se aplica aos links numéricos que permitem ao
usuário pular diretamente para uma página específica dos resultados.
Eis as cláusulas LIMIT para as três primeiras páginas dos resultados,junto
com LIMITs para alguns dos links:
LIMIT 0, 5 / LIMIT 5, 5
LIMIT 5, 5 LIMIT 15, 5
LIMIT 10, 5
LIMIT 5, 5
Sem problemas. Nós só precisamos
escrever ummonte de consultas,
comumLIMIT diferente para cada
uma, certo?
Mais ou menos isso. Nós precisamos de um LIMIT
diferente dependendo da página e do link, mas
podemos gerá-lo em vez de escrever várias consultas.
Tudo o que precisamos fazer é modificar um pouco mais a nossa
função build_query(), para adicionar o LIMIT correto ao final da
consulta que ela constrói.
stíngs e funções personalizadas
Mantenha registro dos dados da paginapão
Para adicionar a nova funcionalidade de paginação a build_query(),
nós precisamos configurar e manter registro de algumas variáveis que
determinem quais resultados devemos consultar e mostrar em uma dada
página. Essas variáveis são importantes também para determinar como os
links de navegação na parte de baixo da página serão gerados.
$cur_page
Obtém a página atual, $cur_page, a partir da URL
do scriptvia $_GET. Se não houver nenhuma
página atual para ser passada através da URL, define
$cur_page como a primeira página (1),
$results_j>er_j?age
Este e o numero de resultados por página, que você
pode escolher para melhor se adequar à aparência
da página, colocando a quantidade de resultados que
caibam bem no layout da sua página. É daqui que vem o
segundo argumento para a cláusula LIMIT.
flflRRWiii
$skip
Calcula o número de linhas a serem puladas antes de começar
a exibir as linhas da página atual. Estavariável é o que controla
onde cada página começa, em termos de resultados, fornecendo o
primeiro argumento para a cláusula LIMIT.
$total
Executa uma consulta que obtém todas as linhas,
sem nenhum LIMIT, e depois conta os resultados e
armazena o resultado em $total. Em outras palavras,
este é o número total de resultados da busca.
$num__pages
Calcula o núm ero de páginas, $num_pages, usando $total dividido
por $results_per_page. Assim, para cada busca, existe uma
quantidade $total de linhas de resultados, mas estas são exibidas
uma página por vez, com cada página contendo um número
$results_per_page de combinações. Existem $num_pages páginas,
e a página atual é identificada por $cur_page.
definindo varáveis necessárias para paginação
Pefma as variáveis da paginapão
A maioria das variáveis de paginação pode ser definida puramente através
de informações fornecidas pela URL, que fica acessível por meio da
superglobal $__GET. Por exemplo, asvariáveis $sort, $user__search e $cur_
page surgem todas diretamente a partir de dados GET. Nós podemos então
usar essas variáveis para calcular quantas linhas devem ser puladas para
chegarmos à primeira linha de dados, $skip. Avariável $results_per_page
é um pouco diferente, no sentido de que nós simplesmente a definimos
com o número de resultados que queremos ter em cada página, o que é
mais uma questão de gosto pessoal, levando-se em consideração o layout da
página de resultados.
Obtém â ordem àt
elassiíidâçãoí «
um mime*-©inteiro
í>btem a S ' * à t! 3 *'
jagina atual, ^ Obtém a configuração de classificação e as palavras-
^ chaves de busca a partir da URL, usando GET
partir da URL f Obtem a dc
v
i
a SET. Se $sort = $_GET [
'sort ']; bu^a que o usuino
não houver uma §user search = $ get ['usersearch' ]; ^ digitou no -Pormuiario.
pagina atuai, - _ ^
.f
. ' Se o nu*»ero
de+me f£ur ^ . «
da pa<yna nao
pay t
o
rn
o I
. I J c -
// Calcula as informações de paginação s
- esti
v
e
r f
l
e
-
r
m
i
G
o
,
í o padrao é a
$cur_page = isset {$_GET [1
page']
) ? $_GET [
'page '] : 1; p
a
g
i
n
a
.
$results__per_page = 5; // número de resultados por página
$skip = (($cur_page - 1) * $results_per_page);
Pefine ° J
K
número de j ^ ^ Este ÚWo resulta em 0
resultados Caidula o número da primeira para a pagi*a I, 5 para a
linha da página, /skip. pagina 1 , 10 para a página
 eit
por pagina-
Ainda faltam duas importantes variáveis: $total e $num_pages. Essas
variáveis só podem ser definidas após realizarmos uma consulta iniciai
para descobrir quantos resultados foram encontrados no banco. Uma
vez que saibamos quantos resultados nós temos, é possível definir essas
variáveis e então usar LIMIT nos resultados...
stings e funções personalizadas
Revise a consulta para ter resultados paginados
Agora que nós temos nossasvariáveis definidas, precisamos revisar o script Search para que
ele, em vez de fazer consultas para todos os resultados, faça-as apenas para o subconjunto
de resultados de que precisamos para a página que o usuário está visualizando no momento.
Para isso, primeiramente fazemos uma consulta para que avariável $total possa ser definida,
e avariável $num_pages possa ser calculada. Em seguida, fazemos uma segunda consulta que
usa $skip e $i'esults_per_page para gerar uma cláusula LIMIT, que adicionamos ao final da
consulta. Eis a seção do scriptsearch.php revisada, com essas adições salientadas:
retorna um
a
dont3<jem de quantas linhas -foram
reiornadas peia donsulta.
Esta donsuita obtew
•todas as linhas, ser*
nenhum LiMÍT.
// Confeulta para obter o total de res
$query = build_query
$result = mysqlí_que ’
•($dbc, $query) ;
$sort);
A íun^ão
rowsO retorna o número
ados l
i
n
h
a
s
C
alfiw
la o número àt painas,
dividindo o numero total
de linhas pelo número de
resultados por pá^nâ,« depois
arredondando o resultado-
A -fundão dei10 arredonda
um numero ate o inteiro
»ais próximo —o w
tetow.
// Consulta novamente,.
para obter somente o subconjunto dos resultados
—
e retorna este
número de linhas-
$result = mysqli_query{$dbc, $query);
while ($row - mysqlijfetch_array($result)) {
echo ’
<tr class="reaults',
> 1;
echo 1<td valign="tpp" width="20%"> 1
Puía este
numero de
linhas—
echo '<td valign="t} op” width="50%">'
100) . '...</td>'
;
echo '<td valign="tpp" width="10%">
$row['title'
] . '</td>';
substr($row['description'], 0,
$row['state'
] . '</td>';
substr($row['date posted']/ 0,
echo 1<td valign="t®p" width="20%">'
10) . *</td> ';  _ ,
pmite uma sejunda Consulta, «as
echo 1</tr> '; desta v
e
z
.limitândo os resultados
para a pagina atual-
echo ’</table>';
você está aqui ► 553
criando os links de navegação
(rere os links de navegação da página
Então, nós definimos algumas variáveis e construímos uma nova consulta SQL que retorna
um subconjunto de resultados para a página. Só o que ainda precisamos fazer é gerar os
links de navegação da parte de baixo da página de resultados: o link "previous” ("página
anterior”), links numéricos para cada página de resultados, e o link "next" ("página
seguinte"). Nósjá temos todas as informações de que precisamos para criar os links. Vamos
revê-las para nos certificarmos de que está claro o modo como elas serão usadas.
$user search
Cada link ainda precisa saber o que o
usuário está realmente procurando,
portanto nós temos que passar os termos
de busca na URL de cada link.
$cur_page
Os links de navegação dependem
inteiramente da página atual, de forma que
é muito importante que essa informação seja
empacotada na URL de cada link.
$num_pages
Nós precisamos saber quantas páginas
existem, para podermos gerar links para
cada uma delas.
$sort
A ordem de classificação também influi
sobre os links de paginação, porque a
ordem precisa ser mantida ou então a
paginação inteira não faria muito sentido.
Ok, nós sabemos quais são as informações de que precisamos para gerar os links
de navegação, portanto, estamos prontos para escrever o código PHP necessário.
Esse código poderia simplesmente ser colocado no script search.php, mas que
tal se o colocássemos na suaprópria função personalizada? Dessaforma, o
código principal do scriptque gera osresultados da busca pode permanecer
muito mais simples, exigindo apenas uma linha de código para gerar os links
das páginas - uma chamada a estanovafunção, que chamaremos de generate_
page_links().
O único senão é que nós não queremos que esta função seja chamada se
houver apenas uma página de resultados. Assim, precisamos verificar o
número de páginas antes de chamar a nova função generate__page_links().
Eis o modo como podemos realizar a verificação e chamar a função,
sem nos esquecermos de enviar as informações necessárias na forma de
argumentos para a função:
if ($num__pages >1) {
FVimciramCft-U) veviíique se e*iste
mdis de Uimâ de V'CSul'fcâdoSj tdSO
don-h-avio, r£o 0crc os l'mks-
Ehvie a stHhj de busda; a orde* de
dlassilidada«, a pagina atua! e o numéro
■tatal de pajihas a sever* usadas »a
dvnadâo dos links.
stings e funções personalizadas
Imas de Geladeira dp F B F
A função generate_page_links() está quase pronta, mas estão faltando alguns pedaços
de código. Use os imas para preencher o código que está faltando e dar ao Risky Jobs a
capacidade de gerar links de navegação para as páginas.
function generate_page_links($user_search, $sortf $cur_page,
$num_pages) {
$page_links = '
' ;
// Se esta página não for a primeira, gera o link "previous"
if (...................... ) {
$page_links .= '<a href=”'..
. $_SERVER ['PHP_SELF •] .
' ?usersearch=1 . $user_search .
’&sort=' . $sort .
'&page=' . (
-
-
}
else {
$page_links .= '<-
}
.......... ) . '"><-</a>
N
link Previous òVèYttLt tomo urwâ
I M w
seta para 3 esquerda, < - •
// Faz um loop através das páginas, gerando os links com os
números das páginas
for($i = 1; $i <= $num_pages; $i++) {
if {
......................) {
$cur_page
$page_links . $i;
}
else {
$page__links .= ' <a href=" ' - $_SERVER['PHP_SELF'
] .
1?usersearch=' . $user_search .
'&sort=' . $sort .
'&page=' . $i . '"> ' . $i . '</a>';
}
//Se esta página não for a última, gera o link "next”
if (
.............................. ) {
$page_links .= ' <a href=r
" . $JSERVER[1PHP_SELF1] .
'?usersearch=' . $user_search .
1&sort=’ . $sort .
'&page=' . ($cur page + 1) . T">-x/a>';
$num_pages
}
else {
$page_lmks .= ’ -j>'; Q imk ’next" aparete tomo uma
V seta para a direita,
return $page links;
você está aqui ► 555
a função completa generate_pagejinks()
i
InictS d e G e la d e ítc t d 9 F H P & M / S Q L - S o l u ç ã o
A função generate_page_links() está quase pronta, mas estão faltando alguns pedaços
de código. Use os imas para preencher o código que está faltando e dar ao Risky Jobs a
capacidade de gerar links de navegação para as páginas.
function generate_page_links ($user__search, $sort, $cur_page, $num__pages)
$page_links = ’’;
// Se esta página não for a primeira, gera o link "previous"
if ( $cur_page
P T
m m m .
) {
$page_links .= '<a href="' . $_SERVER[’PHP_SELF'
'?usersearch=' . $user search .
$sort . ”
■
1&sort=1
’&page=1 $cur_page
1
Nós ainda pvedisamos
caviar os dados da busda
^ do usuário, bem domo a
ordem de dlassi-fidaeão,
else {
$page_links .= 'o T;
}
0 link ^previous aparede tomo
uma seta para a esquerda, <-
// Faz um loop através das páginas, gerando os links com os números das
páginas
for ($i = 1; $i <= $num_pages; $i++) {
if (
S
$cur_page I = I $ i i
i
) í
$page_links .= ' ' . $i;
Cerii-Pi^ue-se de <ue dada link
aponte de volta para o mesmo
sdript - hós estamos apenas
enviando um numero de pagina
diferente dom dada link.
$ SERVER['PHP SELF’] .
}
else {
$page_links .= 1 <a href="' _
’?usersearch=1 . $user_search .
'&sort=' . Çsort .
'&page=' . $i . . $i . '</a>'; 0 l
i
w
k para uma pagina
} espedí-fida é simplesmente
} o numero da pagina.
// Se esta página não for a última, gera o link "next"
i f ( j $cur_page j < | $num_pages {
$page__links .= ' <a href="' . $_SERVER['PHP_SELF’]
1?usersearch=1 . $user_search .
'&sort=' . $sort .
'&page=' . ($cur_page + 1) . '”>-></a>';
else {
$page links .:
return $page links;
/
0 link “next" aparede domo uma
seta para a direita,
Montando o script Search completo
stings e funções personalizadas
E finalmente nós chegamos ao script Search completo do Riskyjobs, que
exibe os resultados apropriados coin base nos termos de busca do usuário,
gera cabeçalhos clicáveis para a classificação dos resultados, faz a paginação
desses resultados e gera links de navegação na parte de baixo de cada página.
<?php
// Esta função cria uma consulta de busca a partir das palavras-chaves
de busca e da configuração de classificação
function build_query($user_search, $sort) {
// base na configuraçao de classificação
es
fu user_searchf $sort) {
}
// lavegação, com base na página atual e no
nú
fu user_search, $sort, $cur_page, $num_pages)
cação e as palavras-chaves de busca a
Mosjá criamos estas -funÇoes,
porianio «3o e pvediso retolodar
dada li»Ha do todíjo delas a«w-
return $page_links;
$user search = $ GET['usersearch'];
// Calcula as informações de paginação. Ü
n
S
t
ros i
t
*
$cur_page = isset($_GET['page']) ? $_GET['page'
] : 1;
$results_per_page =5; // número de resultados por página
$skip = {($cur_page - 1) * $results_per_page);
Chama a -Punção genera^&jsoH^
// Gera os cabeçalhos dos resultados depois os exibe-
echo 1<tr class="heading">'
;
echo generate_sort_links{$user_search, $sort);
echo '</tr>'; i
você está aqui ► 557
o final search.php
0 script Search completo, continua...
// Conecta-se ao banco de dados
require_once(1connectvars.php');
$dbc = mysqli connect(DB HOST, DB USER, DB PASSWORD, DB NAME);
Chama bv*ld_^uevyO pava dviav
„a donsulia SQL pava a busda.
// Consulta para obter o total de resultados
$query = build__query ($user_search, $sort) ;
$result - mysqli_query (
$dbc, $query) ; .
_
$total = mysqli_num_rows($result) ;
$num_pages = ceil($total / $results_perjpage);
// Consulta novamente, para obter somente o subconjunto dos resultados
Çquery = $query . " LIMIT $skip, $results per page’
'
; . k i .hait
* i +
- n a*ui a dlâusula L W T
çresult - mysqli_query($dbc, $query) ; l
while ($row = mysqli_fetch_array ($result) ) í busdâ apenas o
s
echo '<tr c l a s s = " r e s u l t s ;
echo '<td valign="top" width=;
"20%">'
echo ’<td valign="top" width="50%">1
100) . ' . . . </td>'
;
echo ’<td valign=
,
,
top" width="10%">1
echo '<td valign="top" width=',
20%">,
10) . *</td>’;
echo ’</tr>’;
}
echo '</table>’;
subdonjunios do vesuliado
. ?row['title1] . ,
</td>';
.^substr($row['description'], 0,
.l$row[Tstate'
] . '</td>';
.substr ($row ['
date_posted '], 0
,
£ a«ui vai o dodî^o <
^u
e esdvevemos pava
reduziv a desdviçao e a da-b de postagem
dos 3hindios; wsando a -fun^ao subyfcrO.
// Gera links de navegação, se tivermos mais de uma página
if($num_pages > 1) {
echo generate_page_links($user_séarch, $sort, $cur_page, $num_pages);
mysqli_close($dbc) ;
— Mantem a dasa awumada,
■redhando a donexão dom o
bando de dados.
Chama a -fundão genevate__page_
linksO para gev-av os links das
páginas, e depois os exibe-
nap exístem
P e r g u n ta s id io ta s
Nós realmente precisamos enviar as
informações de busca, classificação e paginação
para generate_page_links()?
I - Ok, e quanto a ecoar dados? Por que generate.
pageJinksO simplesmente não faz echo dos links?
H:
í l : o
Sim. Eo motivo para isso tem a ver com o fato
de as funções, quando bem elaboradas, não devem
manipular dados fora do seu próprio código. Assim,
uma função só deve acessar dados enviados a ela em
um argumento, e só fazer modificações em dados que
ela retornar.
mesmo problema. Ao ecoar dados para o
navegador, a função estaria, na prática, dando um passo
maior que as pernas, ao fazer uma modificação em
algum outro lugar. É muito mais difícil realizar debug e
manutenção quando não está claro quais dados a função
está modificando. A solução é fazer sempre a função
retornar os dados que está afetando, e aí então você
pode fazer o que quiser com eles, mas fora da função.
stings e funções personalizadas
T t e S T O R f v e
Finalize o script Search do Risky Jobs.
Adicione a nova função generate_page_lmks() ao script search.php, certificando-se de
adicionar também o código que chama essa função após verificar se existe mais de uma
página de resultados. Além disso, crie e inicialize as variáveis usadas como argumentos
para a função. E não se esqueça de atualizar o código da consulta para que ela use LIMIT
para obter o subconjunto correto de resultados para cada página.
Quando estiver tudo pronto, envie o novo script search.php para o seu servidor web, e
depois abra a página search.html em um navegador. Experimente fazer algumas buscas,
e não se esqueça de procurar por alguns termos que você saiba que vão gerar muitos
resultados, para ver as novas funcionalidades de paginação em ação. Para obter o máximo
de páginas, faça uma busca sem digitar nenhum termo no formulário.
Danger) Your dre*m job 1» out there
Do you have the gut* to go find It?
RiskyJobs-SearchResults
BusiUngdaily farmlooking forpartiisie matadorto VT
entertain spirited bull vitb mid castofADO. -
SharkTrainer
Firefighter
Voltage Checker
<-1234^>
Top celebrity photography firm looking ferseasoned
paparazzo U>stalk feniperaiitfiilal lip-syjïCÎEg ?I;P-.
CA
ft
2
Training shades to do cate tricksforthe audiencesat
ournew water theme park. YouT3spend tim...
EL ' 2ÛG8-G4-28
The City ofDatavilfe is hiring {kefiglîteis.No
experienced reqniiEd- yon wilSbe taiissd. Nog-stck>._
OH 20O8-OS.22
YouH be out ia the field checking ax;, and djc.voltages
in the rangeof3 to 250 or more vol's. Y.
NC 2008-06-25
Ernesto endohxrou um
emprego dom d ^»iidade
per+eiía de rîsdo/
Não se esqueça: o código-fonte completo da aplicação
Riskyjobs está disponível para download no site da
Alta Books:
www.altabooks.com.br
você está aqui ► 559
capítulo
9
caixa de ferramentas do php & mysql
L Sua Caixa de Ferramentas do PHP £- MySQL
r O script Search do Risky Jobs exigiu uma
boa quantidade de novas técnicas de PHP
e MySQL. Vamos recapitular algumas das
mais importantes.
10 Expr®ss°es Regulares
Régras Para Substituição
As funções string são adoráveis. Mas, ao mesmo tempo, são
limitadas. Certamente elas podem realizar tarefas como lhe dizer a extensão da sua string,
truncar a string, trocar certos caracteres por outros. Mas às vezes você precisa de liberdade para
lidar com manipulações de texto mais complexas. É aqui que as expressões regulares podem
ajudar. Elas podem modificar strings de forma precisa, com base em um conjunto de regras, em
vez de um só critério.
este é um novo capitulo ► 561
riskyjobs tem dados ruins
Risky Jobs permite que os usuários submetam currículos
O site riskyjobs.biz cresceu. A empresa agora permite que os usuários digitem os seus currículos
e informações de contato em um formulário web, para que os empregadores que usam o Risky
Jobs possam encontrá-los mais facilmente. O formulário separece com o seguinte:
0 novo íormulario de registro do
Risky Jobs permite ^ue os usuários
digite» m-forma^oes pessoais, de modo
Alé» das °SPcrk n^*s empregadores possa»
. r ~ i -**1 íe*do*tra-!os.
m+or^açoes de
£ontato normais, o
usuário deve digitar
o seu e»prego
desejado, be» torno
o seu durrídJo.
As informações dos nossos usuários que estão
procurando emprego ficam armazenadas
em uma tabela que pode ser consultada por
empregadores, recrutadores e headhunters
para identificarem potenciais novos contratados.
Mas há um problema... os dados digitados no
formulário aparentemente não sâo confiáveis!
Nome;FourFingers
5°brenom
e:M
cGraw
T p S :
f
o
l
í@9regs'
'
i
s
tnet
Telefone: 555-098
d
e
mfacT DeSejad° Ma,aba^ía
Nome: Jimmy
?mprengoDeseiado:Ninja
Primeiro eu queria contratar um ninja e não
consegui, porque o número de telefone dele estava
faltando. Agora, o meu email para este malabarista
voltou. Estou cheio desses dados inválidos do
b an c o de currículos do Risky Jobs.
O
0s empregadores pode» ía^ r busôâs no
baȣo de dados do Risky Jobs e ehtao
e*trar em dontato tor* as pessoâs para,
possivelmente, dontrata-ias... desde <
^
u
e
as ijvfWmaáoes su-fidichtes de dontato
su+idientes tenha» sido digitadas/
expressões regulares
Segue abaixo parte do código do script registration,php, que exibe e processa os
dados digitados pelo usuário no formulário para se cadastrar. Escreva o que você
acha que há de errado com o código, e como ele poderia ser modificado para
resolver o problema dos dados inválidos.
<?php
if (isset ($_POST ['submit']) ) {
$first_name = $_POST[Tfirstname1];
$last_name = $_POST['lastname'];
$email = $_POST['email'];
$phone = $_POST['phone'];
$job - $_POST['job']
;
$resume = $_POST['resume'];
$output_form = 'no';
if (empty($first_name)) {
//$first_name está em branco
echo T<p class="error">Você se esqueceu de digitar seu nome.</p>';
$output_form = 'yes';
}
if (empty($last_name)) { .
// $last_name está em branco
echo '
<p class=”error”>Você se esqueceu de digitar seu sobrenome.</
P>';
$output_form = 'yes';
}
if {empty($email)) {
// $email está em branco
echo '<p class="error">Você se esqueceu de digitar seu endereço de
email.</p>';
$output_form = 'yes *
;
}
if (empty($phone)) {
// $phone está em branco
echo '<p class="error">Você se esqueceu de digitar seu número de
telefone.</p>'
;
$output_form = 'yes';
}
Coh'tmU’
3 â validav os dâmpos nâo
vazios ire-Pev'Cn^
desejado e 3o t
$output_form = 'yes';
} V
2
-Z
ÍO
&ire-feircnies So Cíttfrej.
else { desejado e 3o 1«.
?>
}
if ($output_form == 'yes’) {
yz--------o i’ovmuiario-
você está aqui ► 563
exercício solução
ftcício
§ oluç£k>
Segue abaixo parte do código do script registration.php, que exibe e processa os
dados digitados pelo usuário no formulário para se cadastrar. Escreva o que você
acha que há de errado com o código e como ele poderia ser modificado para
resolver o problema dos dados inválidos.
<?php
if (isset($_POST['submit'])) {
$first_name = $_POST[1firstname'];
$last_name = $_POST[1lastname'];
$email = $_POST[Temail'];
Çphone = $_POST['phone'];
$job = $_POST[’job'J;
$resume - $_POST[1resume'];
$output form = 'no';
0 stript veri-fida se K
a dampos em
brando no formulário, o <ue e bom,
mas alguns dos dampos te** dados
mais espedializados <
^
u
e predisam
adcv-iv a um dctev-*y<inado íormato-
if {empty{$first_name)) {
// $first_name está em branco
echo '<p class="error">Você se esqueceu de digitar seu nome.</p>';
$output_form = 'yes'; r
} — N*0 ba muito M
âis cjue possamos veri-fidar
no <ue diz. respeito a nome e sobrenome,
if (empty ($last_jiame) ) { portanto este dódijo esta ok.
// $last_name está em branco
echo '<p class="error">Você se esqueceu de digitar seu sobrenome</p>';
} $outPut_f = 1yes'; Mmertàe^ c àt ewa-| ^ ^
bastante espedífido, «ue nós devemos
if (empty ($email)) { ^ veriíidar antes de adeitar os dados
// $email está em branco -fornedidos pelo usuário.
echo T<p class="error">Você se esqueceu de digitar seu endereço de
email.</p>'; „
$output_form ='yes '
; rour Finjer Md^raw se es^ueCeu de
} dolodar um ponto perto do íinaldo seu
endereço de email —o -formulário predisa
if (empty {$phone)) { dapturâr esse tipo de erro/
// $phone está em branco
echo '<p class="error">Você se esqueceu de digitar seu número de
telefone,</p>'
; f
c
*
. a * ■ *
■ j-
' mesma doisa dom o numero de
tele-fone —o -formulário nao deve
Continua a validar os campos não
vazios re-ferehtes ao emprego
} desejado e ao durrídulo.
$output_form = 'yes’;
} ser aterío a não ser <ue tenhamos
derteza de <ue o tele-fone esta ho
■formato dorreto-
else {
$output_form = 'yes';
}
if ($output form == 'yes') {
Jimmy Swi-ft nao
-fornedeu o DDP
?>
£*ibe o formulário
0 ^ue nós realmente predisamos c de
um
a -forma de veri-fidar endereços
____ _ de email e números telefonidos, os
-formulário deveria doxtempx do -formulário <ue tem
ter e^ido- ** fara os
demais dâm
posj basta veri-fidar se
eles nao estao vazios-
dom o seu numero
de tele-fone, o ^ue
o
expressões regulares
Por que nós não usamos algumas
funções string para consertar os
dados inválidos? Não poderíamos ter usado str_
replaceQ para adicionar os dados que estão
faltando?
Você pode consertar alguns dados com funções string,
mas elas não ajudam muito quando os dados precisam
atender a um padrão bastante específico.
As funções stxings são adequadas para operações de localizar-e-
substituir simples. Por exemplo, se os usuários estiverem submetendo
os seus números telefônicos usando pontos para separar os blocos de
dígitos, em vez de hífens, nós poderíamos facilmente escrever algum
código com str_replace() para substituir os pontos pelos hífens.
Porém, para qualquer coisa que não podemos prever, como por
exemplo, o DDD do número deJimmy Swift, precisamos pedir à
pessoa que está submetendo o formulário para ser mais clara. E
a única maneira que temos de saber que está faltando o DDD é
entendendo o padrão exato de um número telefônico. O que nós
realmente precisamos é de uma validação mais avançada, para
garantir que coisas como números telefônicos e endereços de email
sejam digitados da forma correta.
Ok, mas aindaassim, não
podemos usar funções string
para fazer essa validação?
As funções string não são realm ente úteis para validação
de dados, a não ser que a validação seja muito primitiva.
Pense na forma como tentaria validar um endereço de email usando
funções string. O PHP tem uma função chamada strlen(),a qual lhe diz
quantos caracteres existem em uma string. Mas não existe uma quantidade
de caracteres pré-definida para coisas como endereços de email. E claro
que essa função poderia ajudar no caso dos números telefônicos, porque
eles frequentemente contêm uma quantidade consistente de números, mas
você ainda poderá ter de lidar com pontos, hífens e parênteses.
Voltando aos endereços de email, o formato deles é simplesmente
complexo demais para que as funções strings sejam úteis. O que nós
estamos realmente procurando aqui é por padrões específicos de dados,
o que requer uma estratégia de validação que possa checar os dados
do usuário em relação a um padrão, para ver se os dados são válidos.
Modelar padrões para os seus dados é o cerne desse tipo de validação.
você está aqui ► 565
decida como deverá ser a aparência dos seus dados
Pecida conto deverá ser a aparência dos seus dados
O nosso desafio é especificar, clara e exatamente, qual deve ser a aparência
de uma determinada informação, nos mínimos detalhes. Considere o
número telefônico deJimmy. Ebem óbvio, para um observador humano,
que estáfaltando o DDD nesse número. Mas avalidação de formulários
não é feita por humanos; ela é executada por código PHP. Isso significa
que nós temos de ’’ensinar”o nosso código como procurar por uma string
de dados digitados pelo usuário, e determinar se os dados atendem ao
padrão estabelecido para os números telefônicos.
Elaborar um padrão desses pode ser um desafio, que exige pensar bem
sobre a gama de possibilidades para o tipo de informação. Os números
telefônicos são relativamente simples, uma vez que eles possuem, nos
Estados Unidos, 10 dígitos com delimitadores opcionais. Os endereços
de email são outra história, mas iremos nos ocupar deles mais adiante
neste capítulo.
Por que
ninguémestá
ligando?
P â r à um s e r h u m an o , c -fácil
vcr Jimwiy $c es<^tóeu de
folotèr o SC* m
<3s í»,3o
e ião simples âssifft -fazer essa
mesma observação ã pariir de
Cadimo P H P .
First Name: Jimmy
Last Name: Swift
Email: JS@sim-u-duck.com
Phone: 636 4652
Desired Job: Ninja
exMem
Ainda não sei se entendi por
que não posso simplesmente usar
isset() e emptyO para a validação
do nosso formulário.
Essas duas funções lhe
dizem se o usuário que submeteu
o formulário colocou ou não dados
em um campo de texto, mas eles
não lhe dizem nada sobre os dados
propriamente ditos. No que diz
respeito à função empty(), não
existe absolutamente nenhuma
diferença entre o usuário digitar
*{707) 827-700* ou *4FG8SXY12*
no campo de telefone do nosso
formulário. Isso seria um grande
problema para sites como o Risky
Jobs, que depende de dados
confiáveis para entrar em contato
com os candidatos a empregos.
Se isset() e empty() não
P e r g u n t a s id io t a s -
íuncioriam, nao poaernos
simplesmente ter alguém para
verificar os dados depois de eles
serem colocados no banco?
Você pode, mas a essa altura
frequentementejá é tarde demais
para consertar os dados inválidos. Se
estiver faltando o DDD em um número
telefônico, nós teremos de pedir ao
usuário que esclareça as coisas,
submetendo novamente os dados
desse campo.
Se esperar para verificar os dados só
depois que elesjá estiverem no banco,
talvez você não tenha como contatar
o usuário para lhe dizer que alguns
dos seus dados estavam inválidos. E
uma vez que o usuário provavelmente
não vai perceber que cometeu um
engano, é possível que elejamais
fique sabendo que há algo de errado.
Assim, o melhor plano de ação
é validar os dados dos usuários
imediatamente, quando eles
submeterem o formulário. Dessa
maneira, você poderá exibir uma
mensagem de erro e pedir que eles
preencham o formulário novamente.
Mas então como decidimos
se os dados digitados são válidos
ou não?
R : Isso depende do tipo
dos dados. Diferentes tipos de
informações têm diferentes regras
que precisam seguir: qual tipo de
caracteres elas contém, quantos
caracteres, em qual ordem esses
caracteres devem estar. Assim, você
precisa comunicar essas regras ao
seu código PHP. Vamos dar uma
olhada com mais detalhes nas
regras que governam os números
telefônicos...
- ^j^jottfeseu lápis------------------------------------------------
Escreva abaixo todas as formas de representar um número
telefônico que você conseguir se lembrar.
expressões regulares
Quais são algumas regras que é razoável esperar que os seus usuários sigam ao
preencher o formulário? Por exemplo, números telefônicos não devem conter
letras.
Eis uma re^ra,
tomo exemplo.
Mós poderíamos e*<$ir regras domo-' somente dígitos pode» ser
usados neste tampo.
você está aqui ► 567
i— f*Aponte seu lápis
Solupão
Escreva abaixo todas as formas de representar um número
telefônico que você conseguir se lembrar.
Espaços, brados,
parênteses, e as vez£s
pontos podem apareder t**
números te!eíonsdos
E possível ate mesmo indluir letras
em um número tele-Ponido, mas isso
ja estaria perto de ultrapassar
os limites do <
^
u
e nós devemos
donsiderar domo um numero valido-
95<5
Eis uma
regra, _
domo
exemplo.
(<595)^-4*52-
.....................
ÇÇ 4*6ÇZ
z
ÇÇÇfc^&^&ÇZ
ÇÇÇ— ^j"^Z
955 ME KIKJA
Quais são algumas regras que é razoável esperar que os seus usuários sigam ao
preencher o formulário? Por exemplo, números telefônicos não devem conter letras.
M
os poderíamos exigir regras domo- somente dígitos podem ser
usados neste dampo-
Nós.poderíamos dividir o número emtres dampos do formulário, um para o
.P
P
P
.
>
..W. pâr.^.?.s..i*!*? primeiros dígitos, e. um para os quatro últimos dígitos.-.
Ou nós poderíamos iníomar às pessoâs ^ue o número de teleíone dçlas
deve seguir o -formato . ( f N o s fazemos as regras.
568
Existem tantos padrões
possíveis. Como poderemos
criar regras para dar conta
de todos eles?
Existem algumas coisas que sabemos com
certeza sobre números telefônicos, e podemos
usar essas coisas para criar as regras.
Primeiramente, eles não podem começar com 1 (código de
interurbano) nem 0 (telefonista).Em segundo lugar, deve
haver 10 dígitos. E mesmo que algumas pessoas possam ter
maneiras inteligentes de representar os seus números com
letras, os números telefônicos são essencialmente números -
10 dígitos quando incluímos o DDD.
Canr
expressões regulares
Formule um padrão para números telefônicos
Para ir além da validação básica, como a de empty() e isset(), nós precisamos adotar um
padrão para os nossos dados. No caso do número telefônico, isso significa que temos de optar
por apenas um formato que esperamos receber do campo telefone de nosso formulário. Uma
vezque decidamos por um padrão/formato para o telefone, podemos validar esses dados.
Segue o que provavelmente é o formato de telefone mais comum em uso hoje em dia, pelo
menos para números dos EUA. Usar este formato significa que, se os dados que os usuários
digitarem não se conformarem a ele, o script PHP irá rejeitar o formulário e exibir uma
mensagem de erro.
Nós optados l àfytos,
1A
F
Khíícf»)
hííe* c e*tao os 4" dfyto*
-ÇmáiS'
636-46521 * .
JK n^UI estaO
v — ^«altando dígitos,
fcí&hs e o Hííe*
*
V
*e existe parede
estar -fora do
fcte bate
períe«ta»ehte Com o
nosso padrao.
r
e
# # # - # # # - # # # #
555-636-46521
. , 7
dígito 3 r»>a»sf| 5556364652
Este hão
íffm KtíehS.
nãp existem
Eu tenho que usar
exatamente esse padrão para os
números telefônicos?
Esse é o que estamos usando
para o Risky Jobs porque ele é
basicamente o padrão, mas ao
elaboraros seus próprios formulários
você deve escolher um que faça
sentido para você. Apenas tenha em
mente que, quanto mais comum o
padrãofor, maior a probabilidade de
os usuários o seguirem.
p e r g u n t a s i d i o t a s -
Você poderia fazer isso
e seria suficiente se esse fosse
o padrão esperado pelos seus
usuários. Infelizmente, na realidade
esse não é um padrão muito bom,
porque a maioria das pessoas
não escreve os seus números
telefônicos com os números todos
juntos desse jeito. É um pouco fora
do padrão, o que significa que os
usuários não estarão acostumados
com ele, e será menos provável que
irão segui-lo.
r
p Nós não poderíamos
simplesmente dizeraos usuários
para digitarum padrão como
e depois usar as funções
P:E daí? 0 padrão é meu, eu
posso fazer o que quiser; certo?
Ok, eu não poderia então
usar três campos de texto
para o número: um para o DDD,
depois três dígitos no segundo,
e finalmente os últimos quatro
dígitos no terceiro. Aí então eu
poderia usar as funções string
do PHP.
Sim, você poderia, e alguns
sites fazem isso. Mas usar os
padrões lhe dá mais flexibilidade.
E os padrões são úteis para muito
mais coisas do que apenas verificar
se o usuário digitou o número de
telefone corretamente, como você
verá mais adiante neste capítulo..
string do PHP para nos certificarmos
de que os dados contenham 10
caracteres numéricos?
Claro, mas ao mesmo tempo
você quer que os seus usuários
tenham uma boa experiência. Caso
contrário, eles não voltarão ao seu site.
você está aqui > 569
introduzindo expressões regulares
Confira padrões com relapão a expressões regulares
O PHP oferece uma maneira poderosa de criar e verificar padrões em um texto. Você
pode criai' regras que lhe permitem procurar por padrões em strings de texto. Essas regras
são conhecidas como expressões regulares ou simplesmente regex. Uma expressão regular
representa ura padrão de caracteres a encontrar. Com a ajuda das expressões regulares,
você pode descrever no seu código as regras que deseja impor as suas strings.
Como exemplo, eis uma expressão regular que procura por 10 dígitos seguidos. Este
padrão só irá coincidir com a uma string que consista de um número com 10 dígitos. Se
a string for maior ou menor do que isso, não irá checar. Se a string contiver qualquer
coisa que não seja um número, não irá coincidir. Vamos aos detalhes,
/Ad d d d d d d d d d $ /
Q tirí-unílexo
a íAtftar do infcio
da
d dígito- 0
frimeisre t&ràCÍcr da $trmg
ser umdfiÿto—
-
.„e tèÒA um destes siyú-Çida
a mesma eoísar pv-odurar for
OM
tsro —0 no total-
Existe também uma forma mais concisa de escrever esta
mesma expressão regular, utilizando chaves. As chaves são
usadas para indicar repetição:
usadas p a ra c o în c îd îr
padrões em uma <
?
u
570 fianítsiln ift
expressões regulares
Sim, as expressões
regulares são claríssimas.
Claras como lama.
É verdade, as expressões regulares são
enigmáticas e frequentem ente difíceis de ler... mas
são bastante poderosas.
O poder frequentemente tem um custo; no caso das expressões
regulares, esse custo é aprender a sintaxe enigmáticas que elas
usam. Você não vai se tomar um mestre das expressões regulares
da noite pro dia, mas a boa notícia é que você não precisa se
tomar um. E possível fazer algumas coisas impressionantemente
poderosas e úteis com as expressões regulares, principalmente
no que diz respeito à validação de campos de formulário, com
um conhecimento bastante básico dessas expressões. Além disso,
quanto mais você trabalhar com elas e quanto mais prática tiver
em analisá-las em detalhes, mais fáceis de entender elas serão.
você está aqui ► 571
metacaracteres regex comuns
Crie padrões usando metacaracteres
Poder checar dígitos em uma string de texto usando d é bem
legal, mas se isso fosse tudo o que as expressões regulares
possibilitassem, o seu uso seria tremendamente limitado. Apenas
checar dígitos não é suficiente nem para a validação de números
telefônicos no Riskyjobs, uma vez que precisaremos checar
caracteres como espaços, hífens e até mesmo letras.
Felizmente, afuncionalidade regex do PHP lhe permite usar
expressões mais especiais, comoVI,parachecaressascoisas. Essas
expressões são chamadas de metacaracteres. Vamosdar uma olhada
em alguns dos metacaracteres regexusados maisfrequentemente.
d
Como você viu na página anterior, este
metacaracter procura por um dígito.
Qualquer número de 0 à 9 - em outras
palavras, sevocê quisesse encontrar um
número com dois dígitos, teria de usar
W oud{2}.
s
Procura por espaço em branco. Isso não
significa apenas o caracter espaço que você
obtem na tela ao digitar a barra de espaço*
V tambem encontra caracteres tab, ou um'
newlme ou caniage return. Novamente,
lembre-se que s só encontra um desses ’
caracteres por vez. Se você quiser encontrar
exatamente dois caracteres espaços
seguidos, precisa usar^V ouV(2}.
O metacaracter ponto final encontra
qualquer outro caracter, exceto um
newline. Encontra letras ou dígitos,
assim comow, bem como espaços ou
tabs, comoV
Os metacaracteres
ii9s permitem
desci-eVet padrões
cíe i e X t ° d e n t r e
de uma expressãp
regular.
w
Procura por qualquer caracter alfanumérico
! em outras palavras, ou uma letra ou
um numero. Encontra um dos seguintes
caracteres: a - z e A- 2 (tanto maiúsculas
quanto minúsculas), bem como 0-9 (assim
comod) ..
Nós também vimos o metacaracter
circunflexo na página anterior. Ele procura
pelo começo da string, de modo que você
pode usá-lo para indicar que precisa haver
uma combinação no início de uma string
de texto, e não em qualquer lugar da string.
Por exemplo, a regex / A
d{3}/ encontrará a
string "300 cadastros", mas não a string "Nós
recebemos 300 cadastros".
Procura pelo final de uma string.
Você pode usar este metacaracter
com Apara marcar o início e o fim da
sua string, especificando exatamente
onde ela começa e onde termina.
Por exemplo / Aw{5Jsd{3}$/ irá
encontrar “Nanny 411”, mas não
“Nanny 411é ótima’ nem “Ligue para
Nanny 411”.
Esses metacaracteres são legais, mas e se você quisesse ter um caracter específico na
sua regex? Basta usar esse caracter na expressão. Por exemplo, se quisesse encontrar
o número de telefone “707-827-7000”exato, você usaria a regex /707-827-7000/.
rs /»
expressões regulares
* ’ +
WfUlfí.-fSkf # IMi»
Ligue cada expressão regular ao número telefônico a que ela
corresponde.
KegeX
//
v
d{ 3}sd{7}$/
/Ad{3}sd{3}sd{4}$/
/Ad{3}d{3}-d{4}$/
/Ad{3}-d{3}~d{4}$/
/Ad{3}swwsw{5}$/
Sttín^^ue elaencpiitta
5556364652
555 636 4652
555636-4652
555 ME NINJA
555 6364652
555-636-4652
você está aqui ► 573
quem faz o que solução
Ligue cada expressão regular ao número telefônico a que
ela corresponde.
/Ad{3}sd{7}$/
/~d{3}sd{3}sd{4}$/
/Ad{3}d{3}-d{4}$/
Este e o fâdrâo <
^
u
e o Risky Jobs usa
pava endontrar numéros de tele-fones
no formâto
/Ad{3}-d{3}-d{4}$/
/Ad{3}swwsw{5}$/
5
O
s meiatavatteves *
neste fadrão endontvarw
letras.
/Ad{10}$/
Este fadrao e doynpost©totalmente
for diÿtos, de modo *^
u
e ele só donsegue
endontrar um húmero tele-fônido <
^
u
e não
tenha esfados nem hífens.
5556364652
555 636 4652
555636-4652
555 ME NINJA
555 6364652
555-636-4652
*57A
expressões regulares
S i N T A - S E c o m o u m a
E x p r e s s ã o R e g u l a r
Suatareía é Interpretai- o papel da expressÈb regular,
e aceitar pu rejeitar númerosteleÍPiúcos
d°s usuáríos dp RïskyJol->s. Marque
ps números ^ue- Vpce considerar
Válidps, e deixe 9S demais em brancP. a expressão
EsoreVa ppr <jue ps núnieros mvalídps reguiar para o
sãp xnV^Jides* ___nwmero lele-fonito -
eja ela/
/ Ad {3 }-d {3 }-d {4 }$ /
□ (555) 935-2659 □ (555)672-0953
Surf pode sev V
tm
â
atividade be» arrisdada>
principalmente guando
vode trabalha de ista
profissional para tubarões/
□ 555-343-8263
555-441-9005 □ 555.903.6386 □ 555-612-8527-8724
você está aqui ► 575
§ ! n 1 T A - S E o o r n o u r n a E x p r e s s a 0
R e g u la i: “ S o lu ç ã ?
Sua-íareía é Interpretar o papel da expressa? regular,
e aceitar Q
Urejeitar númerostele-ÇpnicPs cIps usuários
d9 RiskyJobs. Marque os nÚmel-9S
<jne Voceconsiderar Válidos e deixe
çs demais em Wancp. EscreVapet <jue
95 números inválidos sãp inValídps.
seja expressão regular solução
Esta e a expressão
regular para o
número tele-fênico -
seja ela/
/ Ad {3 }-d {3 }-d {4 }$ /
Parênteses «ao
são permitidos e
espaços também
n3o->
□ (555) □ (555)672-0953
Sem parenteses, por
-Pavor.
555-343-8263
^s nossas expressões
regulares requerem
Kífens e nao pontos.
Bi, tem quatro
números a mais a«^ui.
Isso e uma extensão
Cmum esáritorio?
555-441-9005 □ 555.903.6386 □ 555-612-8527(-8724
5 7 fi ríanífn/rt <n
expressões regulares
As vezes as pessoas
colocam dígitos a mais nos seus números
telefônicos, como por exemplo, uma
extensão de quatro dígitos no final.
Existe alguma maneira de encontrarmos
esses padrões também?
Sim, mas a chave é especificar esse tipo de padrão
como opcional, na sua expressão regular.
Se modificássemos a nossa regex para / Ad{3fd{3}-d{4}-d{4}$/,
estaríamos exigindo que a nossastring tivesse uma extensão de quatro
dígitos no final, e não conseguiríamos mais encontrar números como
“555-636-4652”.Mas podemos usar expressões regulares para indicar
que partes da string são opcionais. As regexes têm suporte a um recurso
chamado quantificadores, que lhe permitem especificar quantas vezes
os caracteres ou metacaracteres devem aparecer em um padrão. Na
verdade, vocêjá viu os quantificadores em ação, em regexes como esta:
W» «V
*»* d'2
**- U
o dfyto deve
/  a i X U iO ve^es sendas"
Aqui, as chaves agem como quantificador, para dizer quantas vezes o dígito precedente deve
aparecer. Vamos dar uma olhada em alguns outros quantificadores frequentemente usados.
{min,max}
Quando há dois números
dentro das chaves, separados por
vírgula, issoindicauma faixade
possíveisvezesque o caracterou
metacaracter deveserrepetido.
Aqui, estamos dizendo que ele dc
aparecer 2,3 ou 4vezesseguidas.!
O caracter ou
metacaracter precedente
deve aparecer uma ou
mais vezes.
O caracter ou metacaracter
pode aparecer uma ou mais
veies... ou não aparecer
nenhuma vez.
O caracter ou
metacaracter precedente
ídeve aparecer uma vez
[ou então não aparecer
inenhuma vez.
0 Assim, se quiséssemos encontrar aqueles dígitos opcionais no final do
ôSpôC lílC a número telefônico, poderíamos usar o seguinte padrão:
<juíW
rfâsVezes / Ad {3}-d {3}-d {4} (-d {4})?$/
ummetacaracter
deVe a p re c e i'.
Coloque entire
parênteses a sedâo à
^«a! o ^uâftti-í-idado*- se
aplida.
0 ponto de mterregaçã© faz.
dor* ^*e o Sífen e os quatro
últimos dígitos seja» opdionâis-
você está aqui ► 577
usando classes de caracteres
Você se
esqueceu de uma coisa. Os
números telefônicos nos EUA não
podem começar com 0 nem 1.
Você tem toda razão. 0 é o número para chamar uma
telefonista e 1 é o código para interurbanos nos EUA.
Nós queremos simplesmente o código DDD e o número.
Precisamos nos certificar que o primeiro dígito não seja 1 nem 0.
E para isso, precisamos de uma classe de caracteres.
As classes de caracteres lhe permitem encontrar caracteres a partir
de um conjunto específico devalores. Com uma classe de caracteres,
você pode procurar por uma faixade dígitos, e pode também
procurar por um conjunto de valores. Evocê pode adicionar um
circunflexo para procurar por tudo que não esteja no conjunto.
Para indicar que alguns caracteres ou metacaracteres pertencem
a uma classe de caracteres, tudo o que você precisa fazer é
colocá-los entre colchetes, []. Vejamos alguns exemplos de
classes de caracteres em ação:
[0- 2 ]
Isto encontrará uma faixa de
números, especificamente 0, 1 ou 2.
[A-D]
Isto encontrará A, B, C ou D.
Uma classe de
c a ra c te re s e um
conjunto de regrais
para se encontrar
um c a ra c te r.
Em umâ itasse de
davâítevcs, o A signilidd
[Ab-f]
Este circunflexo tem um significado diferente
quando usado dentro de uma classe de
caracteres. Em vez de dizer "as strings devem
começar com...”, o circunflexo significa
“encontrar tudo exceto...”
Isto encontrará tudo exceto b, c, d, e ou f.
Escreva aqui uma expressão regular que encontre
números telefônicos internacionais:
expressões regulares
Ajuste os padrões com classes de caracteres
Com a ajuda das classes de caracteres, podemos refinar a nossa expressão
regular para números de telefone, de modo tal que ela não encontre
combinações inválidas de dígitos. Dessa forma, se alguém acidentalmente
digitar um DDD que comece com 0 ou 1, podemos exibir uma mensagem de
erro. Eis como seria a nossa nora e melhorada regex: A c f espedVfita» <ue â
nossa re^e* deve dobrir
/ toda a de -fc
e
^
fc
o
«^e es£a**os domparândo-
/ A[2-9]d {2 }-d {3 }-d {4 }$ /
t V V
^ dlasse de darafcteves ...ei^
osestam
os
diz- ° v
'oSSO j>rodurando por mais dois
tavattev- deve ser v & y * * díyt>s ^ue podem ser
díyfco á t 2 - i % c^aí^er valor entre 0
e *■ n ã ° e x i s t e m
-------------------Fel-gurttaslcllç>tíis
■
seguidos de
mais ires
dígitos....
Bw o^-b-as palavras, a
string pode donter
nenbum outro daradter *^
u
e
na©pertenda ao numero
tele-ronido-
....e um h$e* e »ais os
ultímOS dtyW
p Então as classes de caracteres permitem que você
especifique uma faixa de caracteres para comparar com
a string de texto?
í ^ ! Sim, a classe de caracteres lhe permite especificar, na
sua expressão regular, que qualquer membro de umconjunto
de caracteres especificado poderá ser usadopara se encontrar
a string de texto, em vez deapenas umcaracter.
Porexemplo, a classe [aeiou] encontrará uma instância de
qualquer vogal minúscula, e aclasse [m-zM-Z] encontrará uma
instânciade qualquer letrada segunda metade do alfabeto,
seja minúscula ou maiúscula.
Eaclasse [0-9] éequivalente ao metacaracterd, que na
verdade é apenas umaforma abreviada de dizer a mesma
coisa.
: Não é preciso colocar espaços ou vírgulas entre
os caracteres ou faixas que eu especificar nas classes
de caracteres?
Não. Se você fizer isso, esses caracteres extras
serão interpretados como parte do conjunto de caracteres a
serem comparados com a string de texto.
Por exemplo, a classe
[m-z, M-Z]
encontraria não apenas as letras minúsculas e maiúsculas
de maté z, mas também uma vírgula ou um espaço, o que
provavelmente não é o que você quer.
uma vez, com uma classe de caracteres? Por exemplo,
uma ou mais vogais consecutivas?.
Basteiadicionarumquantificadordepoisdaclassede
caracteres.Aexpressão/[aeiouAE10U]+/ encontraráumaoumais
vogaisseguidas.
^ - E u pensei que os quantificadores só se aplicassem
ao caracter imediatamente antes deles.
Geralmente é assim, mas se o quantificador vier logo
depois de uma classe de caracteres, ele se aplica à classe
inteira. E se você quiser fazer com que o quantificador se
aplique a toda uma série de caracteres que não estejam
em uma classe, poderá colocar esses caracteres entre
parênteses, para indicar que eles devem ficar agrupados.
Como exemplo, a expressão regular /(hello)+/ encontrará
uma ou mais ocorrências consecutivas da palavra "hello"
em uma string de texto.
E se eu quisesse encontrar uma palavra escrita de
duas formas diferentes, como "ketchup" ou "catsup"?
H: Você pode usar a barra vertical (|) nas suas
expressões regulares para indicar um conjunto de opções.
Assim, a expressão regular/(ketchup|catsup|catchup)/
encontrará qualquer uma das três grafias mais comuns para
essa palavra.
• P : a» niiicicco encontrar um caracter mais de
você está aqui ► 579
escapando caracteres reservados
Se quiser usar caracteres reservados na sua expressão
regular, você precisa fazer escape deles.
Na sintaxe das expressões regulares, há um pequeno conjunto de
caracteres que recebem significados especiais, porque são usados para
indicar coisas como metacaracteres, quantificadores e classes de caracteres.
Entre eles estão o ponto final {.), o ponto de interrogação (?), o sinal de
mais (+), o colchete de abertura ([), os parênteses, o acento circunflexo
(A), o cifrão ($), a barra vertical (]), a barra invertida (), a barra normal
(/) e o asterisco (*).
Se quiser usar esses caracteres na sua expressão regular, com o
significado deles, em vez dos metacaracteres ou quantificadores que eles
normalmente representam, você precisa "escapá-los", colocando uma
barra invertida antes deles.
Por exemplo, se quiser encontrar parênteses em um número telefônico,
você não poderia fazer só isto:
Em vez disso, os parênteses, tanto o de abertura quanto o de
fechamento, têm de ser precedidos por barras invertidas para indicar
que eles devem ser interpretados realmente como parênteses:
£stcs serão si»«^les»e»vte
tratadas tomo u» yufo.
(555)636-4652 / A<dí3}) dí3}-d{4}$/
Agora o PttP sabe <ue e*t«s sao
parênteses literais-
(555)636-4652
RAn A
r%
expressões reguläres
Crie uma string que bata com cada padrão mostrado abaixo.
/ A[3-6]{4}/ / A( [A-Z]d){2}$/
Suponha que queiramos aprimoraroesquema de validação do RiskyJobs para números
telefônicos, comoobjetivode permitirque os usuários submetam os seus números em mais
algunsformatos. Escreva uma única expressão regular que corresponda a TODASas strings
de texto abaixo, e que não permita um0ou 1como o primeirodígito. Oseu padrão só deve
permitirdígitos, parênteses, espaços e hífens.
555-636-4652 555 636-4652
(555)-636-4652 (555) 636-4652
você está aqui ► 581
exercício solução
Crie uma string que.bata com cada padrão mostrado abaixo.
ftcícío
SOLUÇÃO
A string deve
domedar tom. .
t repetir essa dlasse
de daradteres
A string
deve tornt^r ^ 3 j ^ â
dom...  mâiúsdujâ- t um
 l a
V £. ^ <uatrovezes.
/ a [3-6]{4}/
$ual<^uer string ^ue dome£e tom quatro dígitos na
íai*a de 3 d ^ irá dorresponder a esta expressão,
lòdds estas strings dorresponderao=
*&&> t um numero”.
duas
ve«s..
e entao
adaba--
dítóto...
I l C
/ A([A-Z]d){2}$/
<5ual«uer string «ue domede dom uma letra
maiúsdula e depois um dígito, seguido de
outra letra maiúsdula, um dígito e só;
"Bscr, •fttpz*
Suponha que queiramos aprimorar o esquema de validação do Risky Jobs para números telefônicos,
com o objetivo de permitir que os usuários submetam os seus números em mais alguns formatos.
Escreva uma única expressão regular que corresponda a TODAS as strings de texto abaixo, e que não
permita um 0 ou 1 como o primeiro dígito. 0 seu padrão só deve permitir dígitos, parênteses, espaços
e hífens.
555-636-4652 555 636-4652
(555)-636-4652 (555) 636-4652
A string
deve domedar duas . e uw
' digito,
dom... % a % veaes... uw w* espaço- <
iA
^ ro 'iez* s -
^  j ^ nríers
/ ' " i ( ? c i - u  d { i }  m -  « j  d { } ) -  d { + ) / /
T / T '~ r ^
a , e um ftaw
.iv.4-j»«* i e entao
o p X ti, * & * • — »
>
• v r â * acsU
O ou | vez...
expressões regulares
você está aqui > 583
a função the php pregjnatchQ
Verifique os padrões com preg^matchO
Nós não vimos desenvolvendo padrões só porque é divertido. Você pode usar
esses padrões com a função preg_match() do PHP. Esta função toma um padrão
regex, igual àqueles que vimos construindo, e uma string de texto. Retorna false
se não houver uma correspondência, e true se houver.
p re g _ m a tc h ($ re g e x , $ m y _ strin g )
Coloque d sua rey* a<ui. A íunçãoy ^
espera redeber uma string o «uc * string ^ue vode esta
signi-í-ida <uc a rege* deve -í-idar entre domparando -fida a<ui..
aspas simples-
Eis um exemplo da função preg_match() em ação, usando uma
regex que procura, em uma string de texto, por um padrão de
quatro caracteres de letras maiúsculas e dígitos alternando-se:
$wa*do rege*es são passadas para preg_
matdh0, elas dever« ser doiodadas entre aspas
preg_m atch(1/Ad{3}-d {2}-d { 4}$/
} , t
Retorna um numero inte*»ro;
I daso a string bata dom o
padrão e 0 daso dontrario.
V Vode pode dolodar o padrão
dentro da 4ndão desta Wr»a,
pas em geral, e melhor armazena
ío emuma variável.
Podemos tirar proveito da função preg_match() para habilitar
uma funcionalidade de validação mais sofisticada nos scripts PHP,
colocando uma declaração if em tomo do valor de retomo.
' 5 5 5 - 0 2 - 9 9 8 3 ' )
£sta string bate doma rege*,
e a íunção retomará 1.
A íunçao preg__matdK0
fida alinhada dentro
da dondi^ao, portanto
o seu resultado
determina «ual dódigo
será exedutado-
echo ’
Número de seguro social válido';
} else {
echo ’
Esse número de seguro social não é válido!’;
Se não odorrer dorrespondêndia,
pveg__màtdH0 retorna -false, o «ue
£32.a dondição avaliar tomo -false-
Portanto, este dodigo e e*edutado.
Se houver dorrespondendia, preg^matdhO
retoma true, o indida para o PffP
<ue a dondidao é verdadeira. Portanto,
este dódigo e exedutado.
expressões regulares
Reescreva a parte salientada do script PHP do RiskyJobs que verificaos
dados de registro abaixo para validarotextodigitado nocampo phone, usando
pregjnatch() emvez de emptyQ. Use a regex que você criou anteriormente na
função preg_match().
if (empty($phone)) {
// $phone está em branco
echo '
<p class="error">0 seu número de telefone não é
válido.</p>!;
$output_form = 'yes';
}
você está aqui ► 585
exercício solução
Reescreva a parte salientada do script PHPdo RiskyJobs que verifica os
9 dados de registro abaixo para validar otexto digitado no campo phone,
IIClO usando preg_match() em vez de empty(). Use a regexque você criou
§0LuÇã0 anteriormente na função pregjnatchQ.
if (empty($phone)) {
// $phone está em branco
echo '<p class=nerror">0 seu número de telefone não é
válido.
</p>1;
$output_form = 'yes’;
}
fcm vez. de emptyO, nos usamos uma
rej^maidh para validar Onumero de
tele-fone- Hos £olo£3mos âwtes dela o
operador HOT(ftporque queremos
exibir um et*o sempre *ue os dados
digrèados HhO baterem tom o padrão-
A expressão regular ja
vimos anteriormente.
.«f. sw
ffhwc «í».í. valido......................
o um poufio, um
a
vez. ^ue nao esiêmos apenas
verificando se dados
'<p £ lj!!= V w > « c wMWo tft UkÇ<**.é.mvál|<io</p> ';............... ^ s<
JvkxUx» r
.'
y
o
’
; *
•
“ b
^f"£
*">
*p
*
*
-
S
»
*ue estabeiedemos para os
Coloíâmos foutput
domo yestsim), í^uai
antes
nuw>eros tele-foniios.
expressões regulares
T te s T O R fv e £ *30 apegas se o usuário
di^rbou o nw
m
C
V
ol
Verifique se os números telefônicos são válidos no script de registro do
Risky Jobs.
Baixe o script registration.php no site da Alta Books, era www.altabooks.com.br,junto
com a folha de estilo do RiskyJobs (style.css) e as imagens (riskyjobs_titie.gife riskyjobs_
fireman.png). Em seguida, modifique o script registration.php para que ele use a função
preg_match() para validar os números telefônicos em relação à expressão regular.
Certifique-se de ajustar a mensagem de erro para que os usuários saibam que o número
telefônico não é válido, e não apenas que está em branco.
Envie o script modificado para o seu servidor web e então, abra-o em um navegador.
Experimente digitar alguns números telefônicos com diversos formatos, e observe como o
script captura os erros.
0 sdvtfl a^ora
exibe uma »e^sa^em
de erro guando
o *ú»ero de
'telefone e
m
d.©rre-ta»eirrbe>
nesttf tâso, tom
pontos e»* vez. de
hífens.
você está aqui ► 587
a função the php preg_replace()
Hmm. Se a nossa regex usa vários padrões
para o número telefônico, o texto não terá
vários formatos diferentes no nosso banco de
dados? Isso não é bom. Acho que precisamos
padronizar isso aí.
Só porque você está permitindo que os dados
sejam inseridos em vários formatos diferentes, não
significa necessariam ente que você queira esses
dados armazenados em todos esses formatos.
Afortunadamente, existe outra função regex que nos permiürá
pegar os números telefônicos válidos submeddos pelos usuários
do Riskyjobs e fazê-los todos se conformarem a apenas um
padrão consistente, em vez de quatro.
A função preg_replace() vai um degrau além de preg_match(),
ao fazer a comparação de padrões usando expressões regulares.
Além de determinar se um dado padrão bate com uma dada
string de texto, ela lhe permite especificar um padrão para ser
colocado na string, no lugar do texto encontrado. Funciona de
modo bastante semelhante com a função str_replace() quejá
usamos, exceto pelo fato de que ela faz a comparação usando
uma expressão regular, e não uma string.
preg__replace($padrão, $substituição, $minha_string)
* / f
A string ohde estaImos
Kós predisamos e^ontrar ' $uâhdo ehdontrâmos _
esses daradteres tãrêcitr indesejado, Queremos -fôzehd© a operação de
mdesejados- *
V
*e ele seja transformado «isto. ^^^^-c-substitui*^
Eis um exemplo da função preg_replace() em ação:
/
$ano novo = preg replaceC^OOtO-S]/’,
o nsdUio ds -fuBíS.
< a nossa string de
texto revisâdâ depois
de teita a operado de
+ica ar»nâicnac(0
fano novo.
em
Esta re y * diz- a p
repiate para produrar
uma dorrespondendia «ue
seja um numero entre
2 0 0 0 1 100%
2010'
t
guando uma
dorrespondendia t
endontrada, ela t
substituída por ZOlO.
Estamos em 2009.')
Cada vez. <
^
u
e um ano
de ZOOO-ZOO*}
■for endontrado na
nossa string, ele será
substituído por ZOiO.
KQQ íÁ..
expressões regulares
RCÍCÍO
Padronize os dados de números telefônicos digitados noformuláriodo Risky
Jobs, escrevendo cada umdos seguintes números na coluna phone da tabela
abaixo. Certifique-se de usar umformato que armazene o mínimode dados
possível para representar cada número de telefone.
(555) 935-2659
(555)672-0953
555-343-8263
555-441-9005
555.903.6386
555-612-8527-8724
Dangers You» job is there.
Bo you fiaye the guts »«■S*>,,n<1 lt?
Risky Jobs-Registration
Register wife Sisley Jobs*and pest yooiresume-.
você está aqui ► 589
exercício solução
Padronize os dados de números telefônicos digitados noformuláriodo Risky
Jobs, escrevendo cada umdos seguintes números na coluna phone da tabela
abaixo' Certifique-se de usar umformatoque armazene o mínimode dados
.RC|C|0 possível para representar cada número detelefone.
goLuçâo
(555) 935-2659
(555)672-0953
555-343-8263
555-441-9005
555.903.6386
555-612-8527-8724
A-fo*rr*»3wnàis
rápida de armaz**ar
■Wefônido
e retirar iudo,
exteio os dfyW
expressões regulares
Padronize os dados dos números detelefone
Da forma como está. agora, o RiskyJobs está usando a seguinte expressão regular para
validar os números telefônicos fornecidos pelos usuários no formulário de registro:
Embora esses formatos sejam facilmente interpretados pelas pessoas,
eles dificultam o trabalho das consultas SQL, de classificar os resultados
da forma como queremos. Os parênteses muito provavelmente irão
atrapalhar as nossas tentativas de agrupar os números por DDD, por
exemplo, o que poderia ser importante para o RiskyJobs caso nós
queiramos analisar quantos dos usuários do site são de uma determinada
localização geográfica.
Para tomar esses tipos de consultas possíveis, precisamos padronizar os ...para esta.
números em um só formato, usando preg 1 “ - -- - J~
INSERT para colocar os dados no banco,
livrarmos de todos os caracteres, exceto o
simplesmente armazenamos 10 dígitos x ií
outro caracter. Queremos que os nossos r
desta forma, na tabela:
/ A ( ? [ 2 - 9 ]  d { 2 }  ) ? [ -  s ]  d { 3 } -  d { 4 } $ /
Isto encontrará números que recaiam em um destes quatros padrões:
###-###-####
(###) ###-####
### ###.####
Nós queremos transformar
nossos dados desta forma...
##########
Isto nos deixa com quatro caracteres para localizar e substituir. Nós
queremos achar e removerparênteses, espaços e hífens. E queremos
encontrar esses caracteres independentemente de onde eles estejam
seus dados lie
dá melipves
resultados em
c o n su lta s Sç>L .
na string, portanto, não precisamos do circunflexo (A) e nem do cifrão
($). Nós sabemos que estamos procurando por qualquer caracter de
um tipo específico, logo, podemos usaruma classe de caracteres. A
ordem da busca não importa. Eisa regex que podemos usar:
você está aqui ► 591
removendo caracteres com preg_replace()
livre-se dos caracteres indesejados
Agora que temos o nosso padrão para encontrar esses caracteres indesejados, podemos
aplicá-lo aos números telefônicos para ajustá-los antes de os armazenarmos no banco.
Mas como? E aí que a função preg_replace() realmente vem em nosso auxílio. A
questão aqui é que não queremos substituir os caracteres indesejados, queremos
apenas nos livrar deles. Assim, nós simplesmente enviamos uma string vazia para
preg_replace() como o valor de substituição. Eis um exemplo que encontra caracteres
indesejados nos números telefônicos e os substitui por strings vazias, na prática
eliminando-os:
KÓS ârm3Z£ttâmCS OS resultados
da ttossà operaçao ioòalizá1
! e—
substituir nesta variável.
Realize esta substituição na
stHhg de te*fct> de fpkone.
1
$new_phone = preg_replace ('/[()-s]/', '', $phone) ;
tndontre estes
darafiteres.... —
-e os substitua por
uma string vazia...
###-###-####
### ###-####
(###)-###-####
(###)###-####
C.
preg replace(
)
Tódos os telefones sao padronizados
neste -formato, para ^ue todos
seja» armazenados «o bando «o
mesmo-formato-
expressões regulares
Não sei não, isso parece muito trabalho
apenas para termos strings de 10dígitos
no nosso banco de dados. Não poderíamos
simplesmenteexigir que os usuários digitassem
logo desse jeito, noformulário de registro?
C ertam ente, mas Isso acabaria causando
problem as depois, uma vez que as consultas
com números telefônicos não funcionariam
como esperado.
A maioria dos usuários está acostumada a digitar números
telefônicos com alguma combinação de hífens, parênteses e
espaços, de modo que tentar forçar o uso de apenas dígitos
nos telefones poderia não funcionar como esperado. E muito
melhor tentar alcançar algum equilíbrio, dando aos usuários
opções razoavelmente flexíveis para a inserção dos dados, ao
mesmo tempo nos certificando de que os dados armazenados
sejam o mais consistentes possível.
Além disso, só é preciso uma chamada a preg_replace()
para resolver o problema, o que não é grande coisa. Mas
se estivéssemos falando em escrever algum tipo de função
personalizada com um monte de código, seria outra história.
Mas melhorar a usabilidade e a integridade dos dados com uma
única linha de código não tem nenhuma dificuldade!
— T f e S T O R f v e
teste registration.php
Ajuste os números de telefone no script de registro.
Modifique o script registration.php para ajustar os números de telefone,
adicionando as seguintes linhas de código ao script, logo depois da linha que
agradece ao usuário por se registrar com o RiskyJobs:
$pattern = ’/ [{)-s]/';
$replacement = '';
$new_phone = preg_replace($pattern, $replacement, $phone);
echo 'Seu número telefônico foi registrado como 1 . $new_phone . '.</p>';
Envie o script para o seu servidor web e depois abra-o em um navegador.
Preencha o formulário, sem se esquecer de colocar um número telefônico com
caracteres extra, como por exemplo, (707) 827-7000. Submeta o formulário e
verifique os resultados.
Experimente colocar algumas outras variantes do número, como: 707- 827-7000,
(707)-827-7000, 707 827 7000. Repare em como a expressão regular e preg_
replace() se livram dos caracteres extras.
3 0 hun*cro
f ■
fcclc-íwiidoc
I reduzido â apenas
j dígitos -
Voubro târaô-Uy-l
expressões regulares
O email que mandei para este
equilibrista acabou de voltar. Não acredito que
esse formulário estúpido está deixando as pessoas
digitarem endereços de email que nem funcionam!
fir*‘ ”ame;F°ur Fingers
Last Name:McGraw
Email: four@gregs-|jstnet
Phone: 555-098 K
Desired Job: Knife JuggST
istí
faltando
ponto
no tn d trtto
dt email!
Da mesma forma que os números telefônicos, os endereços
de email têm um formato específico o suficiente para que
possamos validá-los, verificando mais do que simplesmente
se os usuários os digitaram.
Assim como na validação dos números telefônicos, primeiro nós temos
de determinar as regras que os endereços de email válidos têm de seguir.
Então poderemos formalizá-las como uma expressão regular, e implementá-
las no nosso script PHP. Assim, vamos primeiro dar uma olhada do que
exatamente se compõe um endereço email.
KSs sabemos <weos cnderedos
dt emãii devew tontev eskts
stf dois daraíteres
NomeLocal@Pref±xoDoDomín±o 7SufixoDoDomínio
^ poderá Kavev daradteres ^ jsto geraWnte
al+anu^erifios, onde Ko»eLodai te» no se eo^poe dt
»miMo .taradter e lWi*oP©!Wni© 3 daradteres
te» no mÍm** dois darafiteres. atfa*w**to**
Veja se você consegue bolar uma
expressão regular flexível o suficiente
para encontrar os endereços de email
à direita. Escreva-a abaixo:
você está aqui ► 595
Conferir endereços de email pode ser complicado
Parece que deveria ser bem simples encontrar endereços de email porque, à
primeira vista, não parece haver tantas restrições sobre os caracteres que você pode
usar quanto há para os números telefônicos.
Por exemplo, não parece ser grande dificuldade encontrar a parte NomeLocal
de um endereço de email (tudo que vem antes do sinal @).Uma vez que ela é
composta de caracteres alfanuméricos, deveremos poder usar o seguinte padrão:
uma regex para endereços de emall
/ Aw + /
„ ' M mais taratteres
Começa dom... alW É rií*-
Isso permitiria qualquer caracter alfanumérico no nome local,
mas, infelizmente, ele não incluiria caracteres que também são
permitidos em endereços de email.
Acredite se quiser, mas endereços de email válidos podem conter
qualquer um destes caracteres na parte NomeLocal, embora
alguns deles não possam ser usados como o primeiro caracter:
Todw «te* taraíW
poder« aparecer *
>
a
parte HomcL-otat de
»„ endweço de <•»»'■
Se quisermos permitir que os usuários registrem endereços de email com esses
caracteres, realmente precisamos de uma regex parecida com essa:
/ A[a-zA-ZO-9][a-zA-Z0-9. -& f?=#]*/
I K f
1 Os dedais daratteres , .
0 wsmÓYo pode» ser «suaisoiuer 2 podemos ter zjsvo ou
u ld e « * '* » '^ "’ais delts
Isso não encontrará absolutamente todo
NomeLocal válido, uma vez que ainda estamos
pulando alguns dos caracteres realmente obscuros,
mas é bastante prático de usar e, de qualquer
forma, ainda deverá encontrar os endereços de
email da maioria dos usuários do Riskyjobs.
expressões regulares
Esse negócio dos emails é fácil.
Basta usarmos omesmo padrão que
usamos para o nome local para validar o
nome do domínio... nada demais!
Isso funcionaria para uma parte do domínio, o prefixo,
mas não para o sufixo.
Enquanto o prefixo do domínio pode conter praticamente qualquer
combinação de alfanuméricos e alguns caracteres especiais, como o
NoméLocal, as restrições sobre os sufixos dos domínios são maiores.
A maioria dos endereços de email terminam em algum sufixo de
domínio comum: .com, .edu, .org, .gov e assim por diante. Nós
precisamos nos certificar de que os endereços de email terminem em
um sufixo de domínio válido também.
na? existem
TWgimtas Idiotas
P E se eu quiser permitir absolutamente todos os
endereços de email possíveis?
Você pode, e se for o ideal para o seu site,
certamente deve. Mas às vezes é melhor usar formatos
comumente aceitos, e não necessariamente aceitar
qualquer variação possível. Você precisa decidir qual
será o formato dos emails de 99.9% dos seus usuário,
e precisa estar disposto a não validar o .1% restante
simplesmente porque isso lhe permitirá escrever um
código melhor. Avalidação è, na realidade, um equilíbrio
entre o que é permitido e o que é prático aceitar.Se quiser
implementar uma validação de emails mais robusta
no seu site, você poderá encontrar alguns excelentes
códigos PHP open source (ou seja, gratuitos) aqui: http://
code.google.com/p/php-email-address-validation/.
* Mas as pessoas não vão ficar irritadas se
elas tiverem um endereço de email que eu me
recuse a validar?
É possível, mas a maioria das pessoas não terá
endereços de email malucos. A maioria dos serviços
de email online tem as suas próprias restrições que
impedem os usuários de criarem endereços de email
loucos, embora válidos, como:
"_eu sou louco”@gregs~list.net.
AV<ll1d^çã°Çte<Jiienternertte
e u m e<ju!lít>£iP e n tre 9
< j u e e p e t m i t í c t e e- 9 e
p rá tic o ciceltar.
você está aqui ► 597
coincidir sufixos de domínio
Sufixos de domínios estão por toda a parte
Além dos ultracomuns sufixosde domínios que vocêvêfrequentemente, como
.com e .org, existem muitos, muitos outros sufixosválidos para uso em endereços
de email. Outros sufixosreconhecidos como válidos pelo Sistemade Nomes
de Domínios (Domain Name System, ou DNS) que você podejá tervisto
incluem ,bize .info. Além desses há uma série de sufixos que correspondem aos
diferentes países, como .capara o Canadá e .tj para o Tadjiquistão.
Eis uma lista com apenas alguns dos sufixos de domínios existentes. Estes
não são todos os que existem.
jN
ÍPtcl Geek
Poderíamos fazer isso, e
funcionaria.
Mas há umjeito mais fácil. Em vez de
manter registro de todos os domínios
possíveis e ter de modificar nosso código
caso um novo domínio seja adicionado,
podemos verificar a parte do domínio
de um endereço de email usando a
função checkdnsrr() do PHP. Esta
função se conecta ao DNS e verifica a
0 Sistema de Nomes de
Domínios é um serviço
de dados distribuído que
fornece um diretório
mundíai de domínios
e os seus endereços IP.
Ele torna possível o uso
de nomes de domínio.
Sem o DNS, teríamos de
digitar 208.201.239.36
em vez de oreilly.com.
Use PHP para verificar o domínio
expressões regulares
O PHP fornece a função checkdnsrr() para verificarmos se um domínio é válido ou
não. Esse método é ainda melhor do que usar expressões regulares para encontrar o
padrão de um endereço email, porque em vez de apenas verificar se uma string de
texto poderia ser um domínio válido, essa função na verdade consulta os registros
do DNS e descobre se o domínio realmente está registrado. Assim, por exemplo,
enquanto que uma expressão regular poderia lhe dizer que gzsdjlkdfsalkjaf.com é
válido, checkdnsrr() pode dar um passo adiante e lhe dizer que, na verdade, esse
domínio não está registrado, e que nós provavelmente deveríamos rejeitá-lo caso ele
seja digitado no nosso formulário de registro.
A sintaxe de checkdnsrr() é bem simples:
eHetkdvvsrrO espera receber
ufeâ s-tr'm< dotvfcendo ur*
«orne de doimmio. Esse (nome
c h e c k d n s r r ( ' h e a d f i r s t l a b s .c o m ')
isto s©e ia» problema se
o seu servidor web us^y
Windows. Caso esteja
usando u*»idoiwputador
Se você estiver rodando o PHP em um
servidor Windows, esse comando não
funcionará para você.
u» servidor UN|;</Lmux,
eK-fcao nào seva pr©ble**a-
Em vez dele, você pode usar este código: te tocando cMt ^arwâ
^ p r ^ r â m a e*U irno, «ç*
voda no servider, para
function win_checkdnsrr($domain,$recType=1
1
if (iempty($domain)
) {
if ($recType— 1'
) $recType="MX";
exec("nslookup -type=$recType $doraain",$output);
foreach($output as $line) {
if (preg_match. ("/A$domain/”,
return true;
return false;
return false;
Server^.fll-M**!W<Wress<
autVjori'tsti'1
®aws'wer-
ov*e»lly-toww
íail e*cbawyr
2-0
oreilley-í-ow-
você está aqui ► 599
validação do email em 5 passos
Validapão de email: montando o quadro
Agora nós sabemos como validar tanto a parte NomeLocal de um
endereço de email, usando expressões regulares, quanto a parte
de domínio do endereço, usando checkdnsrr(). Vejamos o passo a
passo de como podemosjuntar essas duas partes para adicionar uma
validação completa de endereços de email ao formulário de registro
do RiskyJobs: Rc?âve
*ao ba nenbum
tiírao no ■
(■
m
a
l
desta re^e*, w»a
Use preg_match() para determinar se a parte NomeLocal do nosso vez. ^ue bavera
endereço de email contém um padrão de caracteres válido. caracteres apos
Podemos usar a seguinte regex para fazer isso:
/*■ [a-zA-ZO-9] [a-zA -Z0-9 t?- #] *@
/
i l í j n u i í°je'Slr í<
>
m“*>ísratier Desía <«, ía»>bé»>ím»«k
r°* e di«o pode Conter produrar por umsímbolo arroba
»
>
■^
3 1 i teres especiais. o endereòo de email fio«te»»
" i > - I . . 1 . J ___
esse símbolo ântes do dommio-
Se a validação do NomeLocalfalhar, ecoe uma mensagem de erro para
o usuário e recarregue o formulário.
Se a validação do NomeLocaltiver sucesso, envie a checkdnsrr() parte
da string de texto submetida pelo usuário referente ao domínio.
Se checkdnsrr () retornar 0, então o domínio não está registrado,
portanto, nós ecoamos uma mensagem de erro para o usuário e
recarregamos o formulário.
Se checkdnsrr () retomar 1, então o domínio está registrado, e
podemos ter razoável confiança de que teremos um endereço de
email válido. Podemos prosseguir com a validação do restante dos
campos do formulário.
6 0 0 Canítnin i
fl
expressões regulares
Segue abaixoo novo código PHP para validar os endereços de email dos
usuários, mas alguns pedaços desapareceram. Preencha os espaços em
branco para completar ocódigo.
if {!preg_match(
' .................................... $email)) {
// $emaíl é inválido porque NomeLocal é incorreto
echo 'Seu endereço de email não é válido.<br />';
$output_form = 'yes';
}
else {
// Retira tudo do email, exceto o .dominio
$domain = preg_replace(
'
..................... ............. ,..... )
;
// Agora verifica se $domain está registrado
if {.................. ) {
echo 'Seu endereço de email é inválido. <br />';
$output_form = 'yes';
}
1
você está aqui > 601
exercício soíução
Segue abaixo onovo código PHP para validar os endereços de email dos
^ # usuários, mas alguns pedaços desapareceram. Preencha os espaços em
ÍRCIClO branco para completar ocódigo.
S o L u Ç ã o Esta c a nossa re^e* fava entontv-ar a parte
KomcL-oda! do cndcvcço de email; terminando tom
y um sinal @
-
if (Ipreg match (
' C a - z ^ i '' $email)) {
// $email é inválido porque NomeLocal é incorreto
echo 'Seu endereço de email não é válido.<br />';
$output_form - •yes ■; ^ Q NoBeUial e o » W .
} #, 3 stnrq vazia í ^to»"«
stvi*3 de substituirão-
01S0 { *
// Retira tudo do email, exceto o dominio.
Çdomain = preg__replace {1/^a-z^-Z^-^Xa-zA-Z^-^ , , femail
u
) M
j! Agora verifica se ^domain está registrado s
..... Real« a*W rt»í*> no
N
. valor de fen»ai(
echo 'Seu endereçoSáe^email é inválido. <br />';
$output form = 'yes '; ^ estivev usando um servidor
H etk ã* ^ > « W * aW «ão « esn«£i
rejisbaao- íha»á-loMw.
PONTOS DE BALA
■ preg__match () localiza
correspondênciasparapadrõesemstrings.
■ preg_replace () modificastrings
encontradas..
■ Quantificadores (Quantifiers) lhepermitem
controlarquantasvezes umcaracterou
conjuntodecaracteres podeaparecer
seguidamente.
■ Vocêpodeespecificar umconjuntode
caracteresa serempermitidosnoseu
padrão, usandouma classe de caracteres.
■ Noseu padrão, d , w e  s significam
dígitos, caracteresalfanuméricoseespaço
embranco, respectivamente.
■ checkdnsrr () verificaavalidadede
nomes dedomínio.
fin?
expressões regulares
T b & T O R f V G
Adicione validação de emails ao script de registro do Risky Jobs.
Use o código da página anterior para adicionar a validação de emails ao script
registration.php. Depois envie o script para o seu servidor web, e abra-o em um
navegador. Tente submeter um endereço de email inválido, e perceba como o
código da nova expressão regular rejeita a submissão do formulário e exibe uma
mensagem de erro para explicar o que aconteceu.
^ T
Excelente! Eu
cumpri a minha cota de
contratações para empregos
arriscados. Nao preciso fazer
mais nada,alémde contar todo
*odinheiro queganhei
Danger!Yourdreamjob1*out»ere.
youSave*h«gutstogotindIt?
RiskyJobs-Registration
J.
Your«asiaíladdressJsimalid.
igsterwithRiskyJobs,and postyourresale.
DesiredJob:
Uma mensagem
Idc Oto in-forma
p*e o chdercÇo
ic Cm
âil do
av-io não t
|alido (ee tcm
espaço otide
rveria haver
»bole @).
Com a ajuda da validaçao no
-formulário de registro do Risky Jobs,
ew-fcrar e» fiontato tom dawfcdatos
promissores «ao e mais um problema,
e é possível -fazer as Coh-fcratações
em -tempo re£orde-
você está aqui ► 603
caixa de ferramentas do php & mysql
Soa Caixa de Ferramentas do PHP S-MySQL
C/til
11 ViSUclllzíUlcIo seus Dclclos... e]V[cl!s!
Desenhando Gráficos
Dinâmicos
É claro que todos nós conhecemos o poder de uma boa consulta
e O
SConsequentes resultados satisfatórios. Mas os resultados de consultas
nem sempre falam por si mesmos. As vezes é útil apresentar os dados de uma forma diferente,
uma forma mais visual. O PHP possibilita o fornecimento de uma representação gráfica dos
dados: gráficos pizza, gráficos em barra, diagramas de Venn, desenhos Rorschach, qualquer
coisa. Vale de tudo para ajudar os usuários a compreender os dados que fluem através da sua
aplicação. Mas nem todos os gráficos úteis, em aplicações PHP, se originam do seu banco de
dados. Por exemplo, você sabia que é possível evitar ataques de spam de preenchimento de
formulário robotizado com imagens geradas dinamicamente?
este é um novo capítulo ¥ 6 0 5
yíáque dos robôs
(ruitar Wars Reloaded: A
Vinganpa das Máquinas
O futurojá chegou. Os robôs foram soltos no mundo virtual e
não há muito que se possa fazer para impedi-los, exceto usar
alguma vigilância através de código PHP. Esses robôs são os
spam bots, os quais infestam a Web procurando por formulários
de input que os permitam publicar anúncios às centenas. Esses
robôs são incrivelmente eficientes e não estão nem aí para o que
deveria ser o uso legítimo dos formulários que atacam. O seu
único objetivo é substituir o seu conteúdo pelo deles, em uma
tentativa desenfreada de conseguir receitas publicitárias para os
seus mestres. Infelizmente, a aplicação de pontuações do Guitar
Wars acabou caindo vítima dos bots.
T o clo s
Çorniulárfos
Webtem o tíscp
de ctta^ues cie
spam lx>ts
Não c nada pessoal; os bots
apenas querem â ates^ao dos seus
usuários, para aumentar as refiíitas
publieífcirias dos seus iwestres.
Os bots de spam são excelentes para repetição
burra, neste caso preenchendo e submetendo
um formulário do Guitar Wars atrás do outro,
com dados que na verdade contêm anúncios,
em vez de pontuações.
visualizando seus dados... e mais!
Nenhum formulário de input está a salvo
Felizmente para o Guitar Wars, os ataques dos bots de spam ficam invisíveis
para o usuário final, graças ao recurso de moderação humana adicionado lá
no Capítulo 6. No entanto, o moderador agora está completamente soterrado
pelo enorme volume de posts dos bots de spam, o que lhe dificulta a tarefa
de "peneirar" e aprovar as pontuações legítimas. A moderação humana é um
excelente recurso, mas os humanos ficam em desvantagem ao se depararem
com um adversário automatizado que nunca se cansa.
GuitarWars-HighScoresAdministratfc
lis!ofaliGuiiarWarshígh.scorcs.Usete pagetoremove
Belowisa
needed-
Isto é ridículo.
Não consigo moderar
todos estes posts, a maioria
dos quais parecem ser falsos.
Eunemsequer sei o que é um
frowney!
Nauae
«rwvr^assbatesxom
wwv.ciasshates.coin
Date
2008-06-23
2008-06-23
2008-06-23
jtoiroeyceBtrtlxoin 2008-06-231
-trvmírowneyceofcraLwB»2008-06-23
vw ^vw iK rcnitnU «» 20084)6-23
wwJro-WBeyeeatraLcflm 2008-06-23
wwwJieaiilHitlatw^oin
K
yarwAewitefiateJ<H
P
wwJwadiastlfito^w
•yrvn»Jicadlastlabs-com
2008-06-23
2008-06*23:
2008-06-23
2008-06-23
2008-06-23
Score Aetkm
.:44:56 999999999E&gass >âtPSHÊ
45:15999999999Kemovel âggQSíê
45.;
:A
S
>
t
:46:<X999999999 f Appism
,:46:19 999999999 Ssm m tâ g p S ê
.:47:26 999999999 >&$$$£&
-.47:42999999999 SêffiSSg!
i;47:55 999999999 E m ® í
lMAZ999999999M&mt&m&&
si
1.52:20 999999999 Regove t AjffflKÊ
t‘
52:32 999999999 í AjaawS
0 nosso destemido
moderador do
éjuitar V
V
ârs se
enfioK-bra emumd
di-fic.il batalha
toYikri bots
*^
u
e Kutóa se
£a«sam de postar
poht**atões falsas,,
<
^
u
e v»a verdade
sao spam.
)
Está claro que a moderação humana dos posts não é o
suficiente. O que nós precisamos é de uma forma de evitar
que os robôs consigam submeter as pontuações - cortar o
acesso logo no início, por assim dizer. Mas para isso será
preciso distinguir, de alguma forma, entre um software
automatizado e um ser humano com um cérebro real...
um problema difícil, mas que pode ser solucionado.
Escreva abaixo três perguntas que você poderia fazer para distinguir
entre um ser humano real e o cérebro artificial de um robô:
você está aqui ► 607
Precisamos separar os humanos das máquinas
Para descobrir como detectar se há um ser humano real no outro lado da
página Adicionar Pontuação do Guitar Wars, você precisa primeiramente
avaliar o que exatamente o bot de spam está fazendo quando ele preenche
formulário com dados falsos.
Para um bot de spam, e a ddsâ
mâis ta£ij do mundo bombâtrdMtr
■ uc««:r*s, c âtC mesmo milhares
____ .
^ifítar wass: apenas para humanos
0 banto de dados,
do éjuitar W
ars esta
sendo inundado 6om
pontuações mvâlidàs
porque os bots estao
se aproveitando do
-formulário Adicionar
Pon^tuaçac
0 formulário Adidionar
rontuáiâo nao te*
nada para distinguir
entre um post de umsev*
Humano real e um post
teito automaticamente
por um robo.
0 formulário
AdiCl911at Y ^Iltuaçãí? O problemacom o formulário Adicionar Pontuação é que ele não
fríecisa de UUl I1Cm/o '^aznac^a Para impedir submissões automatizadas, significando que
1 ~ qualquer programador habilidoso poderá criar um bot que preencha
com anúncios e submeta o formulário repetidas vezes. É claro que
esse spam nunca chega à página principal do GuitarWars, graças ao
recurso de moderação, mas ele toma a moderação inútil em muitos
aspectos, porque o moderador acabaperdendo tempo removendo
manualmente centenas de posts falsosque contêm anúncios.
campp c[ueexíja
a confirmação de
c[üeo usuátfe é um
ser fcumaxio, antes
d e petm íííl: «Jue
uma ppntuaçao seja
subm etida.
O formulário precisa de um novo campo de verificação que
precise ser informado com sucesso para que a pontuação seja
submetida. E a verificação específica desse campo precisa ser algo
fácil para um ser humano real, mas difícil para uma máquina.
cno
visualizando seus dados... e mais!
RCÍCIO
Seguem abaixo algumas ideias de campos para oformulário que poderiam ser
usados para impedirque bots de spam submetam posts. Circuleos campos
que acharque poderiam, de forma simples e eficaz, permitirque apenas seres
humanos submetam posts, e não se esqueça de escrever porquê.
Você é um robô? Q ®im O Não
Qual era o prato favorito de Elvis?
Scaneamento de retina:
Digite as letras mostradas: jkdyqmc
Quanto é 7 + 5?
Que tipo de animal é este?
Digite as letras mostradas:
você está aqui ► 609
exercício solução
Seguemabaixoalgumas ideiasde campos para oformulárioque poderiamser
usados para impedirque.bots de spam submetam posts. Circuleos campos
que acharque poderiam, deformasimplese eficaz, permitirqueapenas seres
humanos submetamposts, e nãose esqueça deescrever porquê.
güLuçgo
/Vlutio fâdil de
adivinhar - »esmo
t<m Você é um robô? O O Não
sudesso à t ^ O k r A w w
base do dhuiomeiro,
vode ainda adabaria
tendo de apagar
toneladas de posts
falsos.
Qual era o prato favorito de Elvis??
Ceria^enie difídil para os robos,
mas poiendiaimenie difídil para
alguns seres humanes iambém. Nem
iodo mundo sabe <
^
u
e Elvis adorava
sanduídhes de pasta de amendoim dom
banana- Seria também prediso usar um
grande bando de dados doniendo as
diversas pergunias e respostas.
^__}
Scaneamento de retina: Olhe para a suaw *
Digite as letras mostradas:
Na© e ma ideia, assumindo-se
*V
*
e as ietras a serem digitadas
â£3redàm tomo uma imagem, e
rào tomo iext©, »as ainda t
possível de ser quebrada por bois
inteligentes o sufidienie para
usarem o redonhedimenio óptido
de daradteres (OCR)-
Quanto é 7 + 5?
Que tipo de animal é este?
Lembra-se d
>
Fang, o tèo
foi abduzido
por alienígenas
no domeço
deste livro?
Bastan-te efidienie - os bots tem ✓
difiduldade em inierpreiar o donieudo
de imagens. /Vias será prediso um bando
de dados doniendo as imagens e as
respediivas respostas
£xdelenie para
impedir os bois,
------ m
3s igtnidamenie
k d y q m c difídil e daro de
implementar.
Simples e efidienie, ^ois
a môioria dos bois nao e
speria o sufidienie para
onseguír inierpreiar «jue
esta sendo pedido o resultado
de uma expressão maiemátída
- só temos de iorder para
^ue a maioria dos seres
humanos o donsigamf
( S
Digite as letras mostradas:
tfêo iâo problemátido
quanto a verifida^ao
de reiina, mas ainda
exige hardware e
soÇbnâre espediais. ^ ^
Scaneamento de impressão digital:
W
minieressanie
aprimoramento do
idador dom leiras
aleatórias; a<
^
ui, as
leiras sâo obsduredidas
dom linhas e pontos,
para donfundir os bois
<ue ienham OCR.
visualizando seus dados,,. e mais!
Podemos vencer a automapão usando a automação
O teste usado para se verificar se a criatura do outro lado do
formulário é uma pessoa real é conhecido como CAPTCHA,
do termo inglês CompletelyAutomated Public Turing Test
to Tell Computers and Humans Apart ("Teste Turing Público
Completamente Automatizado para Diferenciar Computadores e
Humanos"). Isso é uma forma meio prolixa de se referir a qualquer
"teste", em um formulário, em que apenas seres humanos podem
passar.Já foram inventados diversos CAPTCHAs interessantes, mas
um dos mais populares envolve a geração de uma senha aleatória,
que o usuário precisa então digitar. Para ajudar a impedir que
bots com reconhecimento óptico de caracteres (OCR) consigam
vencer o sistema, as letras da senha são distorcidas ou parcialmente
obscurecidas com linhas e pontos aleatórios.
vez. <ue
Digite as letras exibidas:
Urna vet o|ue as irbras da senbâ sa©gradas
aleatoriamente, a senka c d iW ie a cada
o •W
n'utâ'rî© e exibido*
Um tampo de test©
normal é usado para
permitir *w
e o usuário
digite a senba CAPTCHA-
Um CAFTCHA
é um programa
<Jueprotege um
s!te cotxtra
autpm atS zadps,
u sa n d p alg u m
típP deteste.
LmKas e foh-èos aleatórios ajudam a
ob^urecer ©te*t© apcn3s 0
fara impedir ©redonheCimeni? óptido dc
caracteres, mas a©mesmo tempo permitinde
seres Hum
anos o possam ier.
Um campo CAPTCHA é igual a qualquer outro campo do formulário,
exceto pelo fato de que o seu propósito é impedir que o formulário
seja submetido se o teste não tiver sido completado com sucesso.
Assim, ao contrário de outros campos, que geralmente enviam
dados ao servidor no momento da submissão, o campo CAPTCHA é
verificado e usado para controlar todo o processo de submissão.
Uma vez. <
u
e o boi de spa««
nao t capaz, de identiíidar a Errado!
senHa, a unida doisa «ue ele 
pode íâz«r i tentar adivinhar- ______ _ ^
Digite as letras exibidas: |gwerty?
Para um ser Humano
real e -fâdil identi-fidar
a senha.
Digite as letras exibidas: owdysq
Correto!
É muito importante que a senha CAPTCHA seja exibida no
formulário como uma imagem, e não apenas como texto; caso
contrário, seria muito mais fácil para os bots identificar as letras.
você está aqui ► 611
não existem perguntas idiotas: edição captcha
nsb exSstem
p e r g u n ta s Íd!otclS
P - Aquele CAPTCHA gráfico com a imagem do cachorro é
bem legal. Eu poderia usá-lo em vez deste com senha?
J l - Perfeitamente.Apenas tenha em mente que você terá de
manter um banco de dados com imagens e descrições do que
elas são, porque uma das chaves para o sucesso de qualquer
CAPTCHAé a variedade. Um bom CAPTCHAprecisa ter um
repositório de conteúdo amplo o suficiente para que o formulário
raramente mostre o mesmo teste duas vezes. Esse é o beneficio
do CAPTCHAcom senha: uma vez que a senha é gerada a
partir de letras aleatórias, é muito improvável que o mesmo teste
apareça duas vezes para um mesmo usuário, mesmo com muitas
tentativas repetidas.
P■ Como o CAPTCHA funciona para os deficientes
visuais? E se eles não conseguirem passar no teste visual?
R : Os CAPTCHAs visuais obviamente não são a melhor solução
para os usuários com deficiência visual. Uma solução ideal
poderia induir uma alternativa sonora aos CAPTCHAs visuais.
Por exemplo, existe um CAPTCHAde áudio no qual uma série de
números é lida em voz alta, após o que o usuário precisa digitá-los
para passar no teste. Mas ainda há o problema de bots inteligentes
usarem reconhecimento de voz para fraudar o teste, que é o
motivo pelo qual algumas dessas soluções usam áudio altamente
distorcido, que faz a voz soar um pouco macabra. Os CAPTCHAs
de áudio são tecnicamente semelhantes aos visuais, no sentido
de requerem um banco de dados com cfipes de áudio e as suas
respectivas respostas. Existem serviços que oferecem CAPTCHAs
flexíveis, que utilizamtanto vídeo quanto áudio, como por exemplo
www.captcha.net. Tais serviços são excelentes para oferecer as
tecnologias mais atuais, mas em geral eles não se integram tão
bem à sua aplicação web quanto um CAPTCHApersonalizado
feito especificamente para ela
P'-Mas há também pessoas com pouca acuidade visual, e
pessoas com deficiência auditiva. E quanto a elas?
R : No fim das contas, você precisará pesara conveniência
de impedir os ataques dos bots contra o risco de alienar
alguns usuários. De forma semelhante ao que ocorre entre
vírus e softwares antivírus, os bots de spam e os CAPTCHAs
provavelmente continuarão nessejogo de gato e rato, em que bots
são criados para vencer um determinado CAPTCHA, o que fará
surgir um CAPTCHAmais sofisticado, e assim por diante. Pegos
no fogo cruzado estão os usuários que poderão acabar excluídos
por causa da acessibilidade limitada de alguns CAPTCHAs. Fica
a cargo de cada desenvolvedor web pesar os riscos de um ataque
de bots contra a potencial perda de usuários que poderão não
conseguir acessar partes do site. Se servir de consolo, tenha em
mente que os bots mais sofisticados geralmente miram nos alvos
mais graúdos, onde poderão obter um bom retomo em termos de
receita publicitária, o que significa que você poderá não encontrar
um bot realmente maléfico até que o seu site cresça ao ponto de
se tomar um alvo grande o suficiente para os bots mais poderosos.
OK, entoo a senha do
CAPTCHA precisa ser exibida como uma imagem,
com linhas e pontos aleatórios. Tudo bem, mas como
isso pode ser criado com o PHP? O PHP só é capaz de
v . _____ _ gerar código HTML, certo? _______
O
o O PHP possui capacidades gráficas que podem gerar
imagens dinamicamente, as quais você pode então exibir
usando código HTML.
Comaajudade umabibliotecadegráficoschamadaGD (GraphicsDraw), os
nossosscriptsPHPsãocapazesdegerarimagensdinamicamenteemformatos
populares, taiscomoGIF,JPEGePNG,e ouretomá-lasaumnavegadorpara
seremexibidasouescrevê-lasemumarquivono servidor.EsserecursodoPHP
éextremamente importante, porque não existeapossibilidadede se"desenhar"
emumapáginawebusandounicamenteHTML. OPHPlhepermite"desenhar"
emumaparte dapágina, realizandooperaçõesgráficasemumaimageme
depoisexibindoessaimagemnapáginacomafamiliartag<ámg>.
visualizando seus dados,., e mais!
(rere o texto da senha de CAPTCHA
Antes de sequer podermos pensar no aspecto gráfico de um CAPTCHA com
senha, precisamos descobrir como gerar a própria senha aleatória, que começa
como uma sequência de caracteres de texto. A senha pode ter qualquer número
de caracteres, mas algo entre seis e oito caracteres em geral é o suficiente,
Podemos usar uma constante para a extensão da senha, o que nos permite
modificar facilmente o número de caracteres posteriormente, se for preciso.
Umâ senhâ CAPTCHA
define (’CAPTCHAJJUMCHARS ', 6
) ; ^ s
c
i
s
provaveUenie é suíitieníe ^
para impedir os b<yb sc'n
*
atrapalhar os Wma*cs.
Então como exatamente nósvamos gerar uma string aleatória de texto
com seiscaracteres? É aqui que duas funções internas do PHP entram
em cena: rand() e chr(). Afunção rand() retoma um número aleatório
na faixa especificadapelos seus dois argumentos, enquanto que chr()
converte um código de caracterASCIInumérico em um caracter
propriamente dito. O ASCII (American Standard Code for Information
Interchange ou Código PadrãoAmericano para Intercâmbio de
Informações) é uma codificação de caracteres padrão, que representa os
caracteres através de números. Nós sóprecisamos dos códigosASCII na
faixa de 97-122, que representam asletras minúsculas a-z. Se gerarmos
um código nessafaixa seisvezes, iremos obter uma senha de seis
caracteres aleatórios, todos os quais sendo letras minúsculas.
// Gera a senha’aleatória
$pass_phrase =
for ($i = 0; $i < CAPTCHAJxíUMCHARS; $i++) {
$pass__phrase .= chr (rand (97, 122))
1 r ^ — -
Alais adiajvfce, este
dódijo sera Coletado em
um sdript reuiilizivel
próprio, fiâp&ha php.
$pass_phrase
Mmloop para cada taraticr
da sertHa.
Asenha e tonslrwda um
taratier aleâtort© de
tada vez.
rand(
)
Esta função interna retorna um número
inteiro aleatório ou dentro de uma faixa
especificada ou entre 0 e a constante
interna RAND_MAX (dependente do
servidor).Para obter um número aleatório
dentro de uma determinada faixa, basta
enviar os limites inferior e superior da faixa
como argumentos para rand().
chr (
)
Esta função interna converte um número
no seu caracterASCII equivalente. Como
exemplo, o número 97 é o código ASCII
para a letra 'a' minúscula. Assim, chamar
chr(97) retorna o caracter 'a'.
A íunç&>tqndOvetwiaum
númetp inteira dentre
de umadeterminadafaixa.
você está aqui ► 613
desenhando um captcha
Visualizando a imagem CAPTCHA
Pata se deseniaí
umaImagem
dinâmicaem
P H F , é ptcGlSO
usar Çunçpes da
Criada a senha aleatória, nós podemos passar para a tarefa de gerar uma
imagem consistindo do texto da senhajuntamente com linhas e pontos
aleatórios, para ajudar a obscurecer o texto. Mas por onde começar?
A primeira coisa a fazer é decidir qual será o tamanho da imagem
CAPTCHA. Sabendo que essa imagem será exibida em ura formulário,
ao lado de um campo de input, faz sentido mantê-la relativamente
pequena. Vamos tentar 100x25 e vamos colocar esses valores ein , 1
constantes, para que o tamanho da imagem seja definido em apenas um biblioteca<3D
lugar e, portanto, seja fácil de modificar depois, se necessário.
0 -fcam
anH
o da Wa$em CAPTCHA -fr^a
define (
•CAPTCHAJíIDTH 100) ; armax^ado em to»starrUs, para <

»
tseja
define ( 'CAPTCHft_HEIGHT ' , 25) ; ^ ^ a<rcis, a io r ywtiso
Para se desenhar a imagem CAPTCHA, é preciso chamar algumas funções
da biblioteca GD, todas as quais operam sobre uma imagem carregada na
memória. Em outras palavras, você cria uma imagem na memória e então
desenha em cima dela; depois, quando tiver terminado, você a envia para
o navegador para ser exibida.
// Cria a imagem
// Define um fundo branco com texto preto .
e gráficos cinza
$bg_color■= Ímagecolorallocate($img, 255, 255, 255); // branco'
$text_color = ímagecolorallocate($img, 0, 0, 0);
$graphic_color = Ímagecolorallocate($img, 64, 64, 64);
// preto
// cinza escuro
iodtop)
Cria dores para
serem usadas
por outras
TUhÇoes
// Preenche o fundo
i
// Faz output da imagem como PNG, usando um cabeçalho
heàçN
image
SI
m M S m s iá s'íihülílíJÁ
||íííífUlí/íí
CA A
visualizando seus dados... e mais!
Servidor web
As imajensvecém-driadas domeçam
domum-hmdopreto vasão.
PrediSâmos de um -Çundo
Wando onde desenhar os
CAPTCHA-
FVuneiramente,
desenhe algumas
linhas aleatórias.
Adidione alguns pontos
aleatórios pava uma
*textura” espedial
Desenhe o texto dom
uma Cor mais -foV-te,
írn dima das linhas e
dos pontos.
Uma vez. <ue o nave^sdor
redebe a ima^e», ele pode
exibi-b usando uma ta^
HTML- ^i**3> normal- ^
vt
-
Finalmente, retorne
â imâ^em, na
íor»a de PN4 3o
navegador
Navegador
web do cliente
você está aqui ► 615
funções gráficas GD
Por dentro das fuwpões gráficas GP
A mágica por trás da criação de imagens CAPTCHA é possibilitada pela biblioteca de
gráficos GD, que, como vocêjá aprendeu, oferece funções para se desenhar gráficos
dinamicamente usando-se código PHP. Vamos examinar algumas dessas funções com mais
detalhes e ver como elas se relacionam à geração da imagem CAPTCHA.^
imagecreatetruecolor(
)
Esta função cria uma imagem em branco na memória,
pronta para ser editada por outras funções GD. Os
dois argumentos de im agecreatetruecolor () são
a largura e a altura da imagem. A imagem no início
é apenas um fundo preto, de modo que geralmente
você vai querer preenchê-la com uma cor de fundo,
por exemplo, branco, antes de desenhar qualquer
coisa. Isso pode ser feito chamando-se a função
imagef ille d re c ta n g le (). O valor de retorno de
im agecreatetruecolor () é um identificador de
imagem, o qual a maioria das funções GD requerem
como primeiro argumento para a identificação da
imagem que está sendo desenhada.
«magens sao
driadas inidialmente
dom -funcíos pretos.
largura
altura
A largura da nova
imagem, em pixels.
A áliura da
imagem.
f
$img = imagecreatetruecolor (CAPTCHAJWIDTH, CAPTCHA_HEIGHT) ;
^ dodigo dr»a uma )ma$em tom tamanho
A -função retorna um » 100x25, de-Finido r>as nossas donstantes.
iden-titodor para a ma$cm, o
<ual e referido pelas^outras ^
íundõe* para «ue vode possa usa-
las para desenhar a)^0na i^ e -
imagecolorallocate{
)
l/erde dlaro-
(o, m , O).
Use esta função para alocar uma cor a ser usada em
Vermelho^ (1$%, 0 , O), outras funções de desenho. O primeiro argumento
é o identificador da imagem, seguido de três
argumentos representando os três componentes
numéricos do código RGB (do inglês Red-Green-
Blue, ou ’Vermelho-Verde-Azul”). Cada um desses
valores pode ir de 0 a 255. O valor de retomo é
um identificador da cor, o qual pode ser usado
para identificá-lo em outras funções de desenho,
frequentemente como o último argumento.
A**l: (0, O, V&>-
* i , . , $text color = imagecolorallocate($img
0 valor de retomo é » A
ideniiíidador da dor, o ^ualy 0 sdenti&dador y
voC
e pode usar cm outras
'kn^oes de desenho para
deierwiihar a dor a ser usada,
tomo por exemplo, a dor do
W o CAPTCHA-
da imagemna
e^
u
al a dor ira
ser usada-
Oi domponentes
vermelho, vevde e
aaul da dor, neste
daso preta-
visualizando seus dados... e mais!
imagesetpixel (
) q,
0
Lstafunção desenha um único pixel em uma
coordenada especificada, dentro da imagem.
As coordenadas começam em 0,0 para o
canto esquerdo superior da imagem, e vão
aumentando até chegar ao canto direito inferior.
Como na maioria das funções GD, o pixel é
desenhado usando-se a cor que foi passada como
o último argumento para a função.
£—>0 sistema de toordenadas
vara a w>aior‘»adas
j thamadas a íunções
X#y | 6jf) iorr.Çtâ nO tânto
j esquerdo swperior da
j imagem, e va*aumentando
j nas direções para a
direita e pa^a ba‘
«*o-
largura, altura
imagesetpixel ($img, rand() % CAPTCHA_WIDTH, rand() % CAPTCHAJHEIGHT, $graphic_color) ;
A imagem
fidenti-Pitador) onde
o pixel está sendo
desenhado.
xvVi
, . i L
- ^ to c íidenti-fitador)
A toordenada yH d« ?»*«>
>relativa ao ^ ?ixí(
danto esquerdo superior da imagem, *^ue
neste tas©ataba sendo uma localí&a^a«
aleatória dentro da »magem CAPTCHA-
imageline (
)
Chame esta função para desenhar uma linha entre
duas coordenadas (xl,yl e x2,y2). As coordenadas são
especificadas relativamente ao canto esquerdo superior
da imagem, e a linha é desenhada na cor que foi
r passada como o último argumento para a função.
2
As Coordenadas x / do inítio da linha, neste taso no
tanto esquerdo da imagem CAPTCHA-
image1ine{$irag, 0, rand(
) % CAPTCHAJHEIGHT,
CAPTCHA_WIDTH, rand() % CAPTCHAJHEIGHT, $graphic_color);
0 ponto íinal XY dâ linha, <ue neste taso, lotaliza-
se na borda direita da imâgem CAPTCHA-
imagerectangle <
)
Desenha um retângulo começando em um ponto (xl,yl) e
terminando em outro (x2,y2), com uma cor especificada.
Os dois pontos e a cor são fornecidos como argumentos,
do segundo até o sexto, para a função, vindo logo após o
*2>y2
argumento com o identificador da imagem.
A -(-unção x y ^
imaaerettanftleO
J I I : =ríí
wsa e*atamente os
mesmos argumentos «ue
i»*age£illedreitangleí)• *2>y
imagefilledrectangle(
)
Semelhante a im agerectangle (),
esta função desenha um retângulo
cujo interior é preenchido com a cor
especificada.
imagefilledrectangle($img, 0, 0, CAPTCHA_WTDTH, CAPTCHA_HEIGHT, $bg_color);
As toordenâdâs XY dos pontos
initiai e -finai - a«ui, a imagem
CAPTCHA inteira é preenthida.
você está aqui ► 617
use funções gráficas: parte dois
Continuando as funpões gráficas <rP
imageellipse(
)
Usada para se desenhar círculos e elipses,
esta função aceita um ponto central, uma
largura e uma altura. Um círculo perfeito
é apenas uma elipse com largura e altura
iguais. A cor da elipse ou círculo é passada
como o último argumento para a função.
largura
tlipSCS *30
usâdâs n3 Ím3gem
CAPTCMi»* w
âmdâ assim cias sa©
bastante wte'«!!
imagefilledellipse(
)
Precisa de uma elipse preenchida? Basta
chamar im ag efilled ellip se (),
que funciona da mesma forma que
im ageellipse () exceto pelo fato de
que a cor especificada é usada para se
preencher a elipse, em vez de contomã-la.
^ ^ imagefilledellipse($img, ^
0
^ 0 ^ 320, 240, $color) ;
Tant© imageellipseO
quanto imagefilledellipseO
aceita» os mesmos
argumentos.
imagepng(
)
A largura c a altura da elipse
—defina estes tem o mesmo
número para desenhar um
círculo perfeito-
J ACoordenada XV
do Centro da elipse-
Quando tiver terminado de desenhar
em uma imagem, você pode enviá-la
diretamente ao navegador do cliente,
ou então, para um arquivo no servidor
chamando esta função. De umjeito ou
de outro, o resultado final é uma imagem
que pode ser usada com a tag HTML
<img> para exibição em uma página
web. Se preferir gerar uma imagem PNG
diretamente na memória (ou seja, sem
um arquivo), então você precisará chamar
também a função header() para que
a imagem seja entregue ao navegador
através de um cabeçalho.
. imagepng ($img) ;
n -run^a© retorna true *
ou false dependendo de j
se a imanei» foi criada
M
Com suCesso ou não.
A imagem pode ser enviada
diretamente para o navegador,
©u entao para um arquivo no
servidor.
myimage.png
0 identificador de imagem
<
^
yc voCe vem usando nas
^ outras funções de desenho-
Vote pode passar um nome de arquivo Como um
jegundo argumento opcionâl - sem ele, a fundão
gera uma imagem na memória <
^
u
e pode ser
enviada de volta ao navegador, em ur* cabeçalho.
visualizando seus dados,., e mais!
as suas imagenS
«
^
n
3ndo elas nao sao mais
neiesssHas é u»a Wa ideia»
pav-a impede o desperdid»o de
redwrsos do servidor-
imagedestròy(
)
O trabalho com imagens usando-se a
biblioteca GD consome recursos do sistema,
e esta função se encarrega de liberá-
los depois que você tiver terminado de
trabalhar com a imagem. Basta chamá-la
depois de fazer o output com imagepngQ.
Semelhante a imagepngO,
esta fuh£â© retoma true se
a operaçao -tiver sudesso, e
false, das© dohtvirio.
L ib e re s e m p re as im a g e n s
da memérïa, depçïs de usa-
las, com îmagedesfrpyO
imagedestròy ($img)
A
Ten-te sempre esdrever uma
v dhamada a esta fu*çao para
dada imagem ^ue vode driar,
para <ue todas as imagens
sejam destruídas depois de
serem wsadas.
0 identifidador da imagem
^ue vode deseja destruir.
imagestring (
)
Esta função desenha uma string de
texto usando a fonte interna do
PHP, na cor especificada. Além do
identificador da imagem, você passa
à função o tamanho da fonte (na
forma de um número de 1a 5)Junto
com as coordenadas para o canto
esquerdo superior da string, a própria
string, e finalmente, a cor.
0 tamanho da fonte a ser
usado* na faixa de J a *5
-
0 número «a faixa de I a 5
define o tamanho da fonte
usada para se desenhar a
string de texto, dom 5 sendo o
maior tamanho.
x,y*.— -----— — .....
;Exemplo de texto j
f fonte interna e adequada
^ara o desenho de texto
basido, mâs e limitada em
termos de tamanho-
imagestring($img, 3, 75, 75, 'Exemplo de texto', $color);
A doordenada XY
do danto esquerdo
superior da string-
0 texto desenhado Com
imagestrmgupO t girado
em 10 grâus no sentido
anti-horário, para apareder
na vertida!-
A
Esta e a string de
texto a ser desenhada-
V A dor do
texto-
im ag estrin g u p ()
Semelhante a im agestring (), esta função
desenha uma string de texto usando a fonte
interna, mas o desenha verticalmente, como
se ele fosse girado 90 graus no sentido
anti-horário. A função é chamada com os
mesmos argumentos que im agestring ().
você está aqui ► 619
a função imagettftxtO
Pesenhando texto cow uma fonte
A função imagêstrin g () é fácil de usar para desenhos, mas é um tanto limitada
em termos do controle que você tem sobre a aparência do texto. Para conseguir uma
aparência específica, você precisa usar a sua própria fonte True Type. A imagem com
a senha GAPTCHA é um bom exemplo dessa necessidade, uma vez que os caracteres
precisam ser desenhados em tamanho razoavelmente grande, e de preferência em negrito.
Para conseguir esse look personalizado, você precisa da syuda de mais uma função.GD, que
desenha o texto usando uma fonte True Type que você fornece no servidor.
pava se desenha** um texto
al-UmCttie personalizado, c prediso
usav uma fonte True T(pe e a
função imagettftextO.
i
x,y #Exemplo de te x to
imagettftext(
)
Para desenhar um texto realmente personalizado,
coloque uma fonte True Type no seu servidorweb
e depois chame esta função. Você não apenas pode
usar qualquer fonte que quiser; como também obtém
mais flexibilidade quanto ao tamanho da fonte, e
mesmo quanto ao ângulo no qual o texto é desenhado.
Diferentemente de imagestring (), as coordenadas
passadas a esta função especificam o "ponto-base" do
primeiro caracter do texto, que é aproximadamente o
canto esquerdo inferior do primeiro caracter.
Estafunção requer que você coloque um arquivo contendo
uma fonte True Type no seu servidor, e depois especifique
esse arquivo como o último argumento. Os arquivos de
fontes True Type geralmente têm a extensão .ttf.
0 angulo da fonte, espedifidado
0 tawanbo da fonte, «
*
*
» 5raws no sentido antí-
geraUente espedifidado horav-io (õ c o texto normal)
em wpontosw- ^
imagettftext ($img, 18, 0, 5, CAPTCHA_HEIGHT - 5,1 $text_color,
’
Courier New Bold, ttf’, $pass_phrase) ; 0 ye ts& se*d0
deschKado.
f
' Difev-chtcmch-b: dc
'»»agestiringO, as doordenadas
usadas para se desenhar
texto dom imagettftextO
apontam para o danto
esquerdo inferior do texto.
As eoovdenâdas XV
do danto es«uevdo
infCrioT do texto-
í^ o ta G e e k
Se quiser tentar criar a sua própria fonte
TrueType, para personalizar ainda mais o
seu CAPTCHA, dê uma olhada em www.
fontstruct.com. Essa é uma comunidade
online de criadores de fontes, incluindo
uma ferramenta web para que você
possa criar fontes personalizadas.
Vode pvedisa dolodar a fonte True
Type no scu servidor **jeb, para <ue
a biblioteda de grafidos possa ^
endontrà~!a- CourierNewBold.ttf
Use a îunçâo
îmagettfextô para
d e s e n ta r urn t & x t v
altamente perspnaJizadp,
com a sua préprla fonte
True Typ<
>e.
A -^
C l flÉ M Ü F — -------------------------------------
imagedoloralloeaieífi^g, J2.8, /ZS, 12.0);
Ligue cada bloco de código PHP à imagem gráfica gerada por
ele. Assuma que a imagem ($img) e as cores ($black_color,
-$w hite_color e $gray_color) já tenham sido criadas.
. „ , ■
, ’wageeoiovaiSodâteffs*^
'"'âgcdolovalloíaícífiw^ O, O, O); U & } 2&?>,
visualizando seus dados... e mais!
image.filledrectangle{$img, .10, 10, 90, 90, $gray_color) ;
imagefilledellipse ($img, 50, 5
.
0
,
. 60, 60, $white_color) ;
imagefílledrectangle ($img, '
4
0
, 40, 60, 60, $black_color) ;
imageline($img,'15, 15, 50, 50,'$black_color) ;
imageline.
(
$img, 15, • 85,50, 5
.
0
,$black_color);
imageline ($img, 50, 50, 85, 50, $black_color) ;
imagefilledellipse($img, 15, 15, 20, 20, $gray_color) ;
imagefilledellipse($img, 15, 85, 20, 20, $gray_color);
imagefilledéllipse($img, 50, 50, 20, 20, $gray_color);
imagefilledellipse- ($img, 85, 50, 20, 20, $gray_color) ;
imagefillédrectangle($img, 10, 10, 90, 60, $gray_color);
iinagesetpixel ($img, 30, 25, $black_color)-;
imagesetpixel ($img,; 70, 25, $black_color);
imageline($img, 35, 45, 65, 45, $black_color);
imagefÍlledrectangle ($img, 45, 5
.
0
, 55, 90, $gray_color) ;
imageellipse($img, 45, 45, 70, 70, $black_color);
imagefilledellipse{$img, 75, 75, 30, 30, $gray_color);
imagesetpixel (
$img, -
1
0
, '10, $black_color)
imagesetpixel(
$img, 80, 15, $black_color)
imagesetpixel(
$img, 20, 15, $black__color)
imagesetpixel($img, 90, 60, $black_color)
imagesetpixel($img, 20, 80, $black_color)
imagesetpixel($img, 45, 90, $black_color)
imagefÍlledrectangle(
$img, 25, 35, 75, 90, $black_color)
imageline($img, 10, 50, 50, 10, $black_color);
imageline{$img, 50, 10, 90, 50, $black_color);
imagefilledrectangle($img, 45, 65, 55, 90, $white_color)
imageline($img, 0, 90, 100, 90, $black_color);
você está aqui ► 621
quem desenha o que solução
Ligue cada bloco de código PHP à imagem gráfica gerada por ele.
Assuma que a imagem ($img) e as cores ($black_color, $white_
color e $gray_color) já tenham sido criadas.
imagefilledrectangle($img, 10, 10, 90, 90, $gray_color);
imagefilledellipse($img, 50, 50, 60, 60, $white_color); ,
imagefilledrectangle($img, 40, 40, .
6
0
, 60, $black_color)
imageline($img, 15, 15, 50, 50, $black_color);
imageline{$img, 15, 85, 50, 50, $black_color);
imageline($img, 50, 50, 85, 50, $black_color);
imagefilledellipse ($img, 15, 15, 20, 20
.
,$gray_color) ;
imagefilledellipse($img, 15, 85, 20, 20, $gray_color);^
imagefilledellipse ($img, 50, 50, 20, 20, $gray_color.) ;
imagefilledellipse($img, 85, 50, 20, 20, $gray color);
imagefilledrectangle($img, 10, 10, 90, 60, $gray_color);
imagesetpixel($img, 30, 25, $black_color);
imagesetpixel($img, 70, 25, $black_color);
imageline($img, 35, 45, 65, 45, $black_color);
imagefilledrectangle($img, 45, 50, 55, 90, $gray color);
imageellipse{$img, 45, 45, 70, 70, $black_color);
imagefilledellipse ($img, 75, 75, 30, 30, $gray__color) ;
imagesetpixel($img, 10, 10, $black_color);
imagesetpixel($img, 80, 15, $black_color);
imagesetpixel($img, 20, 15, $black_color);
imagesetpixel($img, 90, 60, $black_color);
imagesetpixel($img, 20, 80, $black_color);
imagesetpixel($img, 45, 90, $black color);
imagefilledrectangle($img, 25, 35, 75, 90, $black_color)
imageline($img, 10, 50, 50, 10, $black_color);
imageline($img, 50, 10, 90, 50, $black_color);
imagefilledrectangle(
$img, 45, 65, 55, 90, $white_color);
imageline($img, 0, 90, 100, 90, $black_color);
visualizando seus dados... e mais!
dompletamente ât{èr>0m0
- vode pode abri-lo no seu
râvcgador c ver a imagem
<ue ele gera.
(rereuma imagem CAPTCHA aleatória
Agora, nósjuntamos todo o código CAPTCHAem um script
captcha.php, o qual se encarrega de gerar uma senha aleatória
e depois retomar uma imagem PNG para o navegador.
<?php
session start();
Crie Constantes para armazenar o numero de
daradteres no CAPTCHA e defina a altura e
largura da imagem.
// Define algumas constantes importantes
define('CAPTCHA_NUMCHARS'
, 6); // número de caracteres na senha
define(’CAPTCHA_WIDTH’, 100); // largura da imagem
define{’CAPTCHA_HEIGHT1, 25); //altura da imagem
// Gera a senha aleatória
$pass_phrase =
for ($i = 0; $i< CAPTCHA_NUMCHARS; $i++) {
$pass_phrase .= chr(rand(97, 122));
Embora vode possa armazenar a senha
dríptografada no bando de dados, é
mais simples dolodi-la apenas em uma
variável de sessão —nós predisamos
armô2£há~la em algum lugar para ^ue
o sdript Adidionar Pontuação possa
te r adesso a ela-
// Armazena a senha criptografada em uma variável de sessão
$_SESSI0N['pass_phrase'
] = shal($pass_phrase);
// Cria a imagem
$img = imagecreatetruecolor (CAPTCHA__WIDTH, CAPTCHA_HEIGHT);
// Define um fundo branco com texto preto e gráficos cinza
$bg_color= imagecolorallocate{$img, 255, 255, 255); //branco
$text_color= imagecolorallocate($img, 0, 0, 0)
; //preto
$graphic_color = imagecolorallocate.($img, 64, 64, 64); // cinza escuro
// Preenche o fundo
imagefilledrectangle($img, 0, 0, CAPTCHAJWIDTH, CAPTCHA_HE1GHT, $bg_color);
// Desenha algumas linhas aleatórias
for ($i = 0; $i < 5; $i++) {
imageline ($img, 0, rand() % CAPTCHA__HEIGHT, CAPTCHA_WIDTH, rand() % CAPTCHA__HEIGHT,
$graphic_color);
}
// Insere alguns pontos aleatórios
for ($i — 0; $i<50; $i++) {
imagesetpixel($img, rand() % CAPTCHAJrtIDTH, randO % CAPTCHA_HEIGHT, $graphic_
color);
// Desenha a string da senha
imagettftext($img, 18, 0, 5, CAPTCHA_HEIGHT - 5, $text_color,
$pass_phrase);
// Faz output da imagem como PNG, usando um cabeçalho
header("Content-type:image/png");
imagepng ($img)
//Apaga a imagem
imagedestroy($img)
?> 4:
éjere uma imagem PNéf
dontendo tudo o *^ue foi
desenhado
A imagem PKéj
é enviada ao
Courier New Bold.ttf"
,
^Algumas versSes da
btblioteda 6jZ> Querem
*uc useui-»,íarftinHo
relaiivo até o arquivo da
*oníe, temo "./Courier
rmàli^ando, apague a imagem da
memória feia ainda e enviada ao
navegador, através do dâbedalho).
navegador através Ntw Boid-ttf;J
.
de um dabedalho
captcha.php
você está aqui ► 623
teste captcha.php
^ i p p K P
TEJST O R fV e ------------------
Crie o script C A P T C H A e teste-o.
Crie um arquivo de texto chamado captcha.php, e digite nele o código para o
script CAPTCHA mostrado na página anterior (ou baixe o script no site da Alta
Books em www.altabooks.com.br).
Envie o script para o seu servidor web, e depois abra-o em um navegador. Você
verá imediatamente a imagem CAPTCHA com a senha aleatória no navegador.
Para gerar uma nova senha, recarregue o navegador.
Cada imagem CAPTCHA gerada
Consiste de seis caracteres
aleatórios, Com algumas jinhas e
pontos adicionados para criar
ruído de fundow
.
Recarregar o script
CAPTCHA resulta «a
gerado de uma nova
imagem, Contendo uma nova
senha aleatória-
visualizando seus dados... e mais!
Esses robos estão
me deixando louco!
Preciso de ajuda
para pará-los agora!
A sanidade retorna ao G-uitar Wars
Agora que nósjá trouxemos à tona o seu artista PHP interior,
com algumas funções GD e uma imagem CAPTCHA, é hora
de usarmos essa imagem para salvar o moderador do Guitar
Wars do ataque dos bots. Na verdade, será preciso seguir
alguns passos para resolver o problema. Aboa notícia e que
já realizamos dois deles: gerar a senha aleatória e desenhar a
imagem CAPTCHA. Vamos eliminar os passos restantes para
tornar o Guitar Wars oficialmente livre de bots!
0 »oderâdor do Quitar
W
ars está -tão estressado
i^uejá está dow>e$3ndo a
tentar bater em robos
imaginários ~ ele pretisa de
uma solução jaü
Feito!
Q Gora r uma senha aleatória
©
Desenho pronto^
Dese nha r uma im agem CAPTCHA.usando a sonha
0 Exibir a imagem CAPTCHA no formulário
Adicionar Pontuação do Guitar Wars e pedir ao
usuário que digite a senha.
0 Verificar a senha em relação ao input do usuário.
Complete o Passo 3do CAPTCHAdo GuitarWars, escrevendo ocódigo HTML
para umnovo campo de input de texto chamado Verificação, oqual pedirá
# ao usuário para digitara senha do CAPTCHA. Certifique-se de dara esse
RCIClO campo umrótulo, e ponha uma tag <img>depois dele para exibira imagem
CAPTCHAgerada peloscript captcha.php.
exercício soiução
Complete o Passo 3 do CAPTCHAdo Guitar Wars, escrevendo o código
HTML para um novo campo de input de texto chamado Verificação, o qual
»|C|0 pedirá ao usuário para digitar a senha do CAPTCHA. Certifique-se de dar
O M
g a esse campo um rótulo, e ponha uma tag <img> depois dele para exibir a
d O L u Ç 3 0 imagem CAPTCHA gerada pelo script captcha.php.
Uma tag <labei> t usada
para se rotular o novo
tampo texto Verificado-
£ste de te*to
e o»de o wuário ira
digitar a senha revelada
imagem CAPTCHA-
<label f<^^M
yçrifyM
>yeriftatgoi- </label> y
.
!^3»e^l'yerifywyalue^'Enter. the.pa^-phrase.” />
^••^g ?rc^w
captchaphpwalt^Veri-Pication .pâss—phrase” />
A >,fofttewda image» e o nome do
script PHP <^ue gera dinamicamente
à imagem CAPTCHA- Isso fu*Cio*a
forque o script captchaphp retorna
uma imagem diretamente para o
navegador, através de imagepngO e
um cabeçalho.
f wagem
CAPTCHA e
e^ibida no
formulário, ao lado
de um campo de
inpvt de te*k>-
aKas-sâP!
Guitar Wars -AddYourHighácore
fW »! Si rfis w. f**« f*-»
- ^ - Exibir a imagom CAPTC H A 4t»fermulário Adicionar
visualizando seus dados... e mais!
Adicione CAPTCH
Aao script Adicionar Pontuação
C°n:T ° nOVOCamP° de * Xto
porém, é a nova declaração ifno scodc/wi™ * °-o modlflcaçao mais importante,
verifica se a senha d i ^ D e ! ^ t ^ Pontu^ o (Passo 4), que
g1 pelo usuário bate com a de CAPTCHA
visuaiízanao seus dadt
<?php
sessionjstart (
);
?>
<html>
<head>
<title>Guitar Wars - Adicione o seu Recorde</title>
clink rel="stylesheet" type=r
’
tex.t/css" href=”style.css" />
</head>
<body>
<h2>Guitar Wars - Adicione o seu Recorde</h2>
<?php
require_once{’appvars.php');
require_once(’connectvars-php');
if (isset($_POST[1submit'])) {
// Conecta-se ao banco de dados
$dbc =mysqli_connect (DB_HOST, DB__USER, DB_PASSWORD, DBJNíAME)
~ Q - Vertfrear
'f«teçã©-ao
-input do-
-usuário.——
■
Tudo frontal
// Pega os dados em POST
Çname = mysqlí_real_escape_string($dbc, trim($_POST[1name']));
$5core = mysqli_real_escape_stri.ng ($dbcftrim ($__POST[
'score'1));
$screenshot = mysqli_real_escape_string($dbc, trim($_FILES['screenshot’][1name’]));
$screenshot_type = $_FILES [’screenshot’]['type1]; 6 ^ 3 senha
$s c r e e n s h o t _ s i z e - $_FILES t >s c r e e n s h o t ■] [ ' s i z e ' 1; í l«U *J*&
S í/ V e r i f i c a a senha CAPTCfiA ~ ~ vãviâvct ® ^
{ $user_passjphrase = shal($_POST['verify']);  vara ^ s
co u
suivto
if (
$ SESSION ['pass phrase'] == $user pass phrase) {  / verK < . .
•••“  3
else { --
- "
echo ’
<p class="error">Por favor, digite o código de verificação exatamente como
lostrado </p>';
}
?>
<hr />
<form enctype="multipart/form-data" method="post'' action="<?php echo $_SERVER [
'PHP_
SELF' ]; ?>">
<input type="hidden'' name="MAX_FILE_SIZE" value="<?php echo GW_MAXFILESIZE; ?>" />
<label for=,
'name'I
>Nome:</label>
<input type="text" id="namenname="name" value="<?php if (!
empty ($name) ) echo $name; ?>"
/><br />
<label for="score">Pontuapao:</label>
<input type="text" id="score" name="score" value="<?php if t!
empty ($score)) echo
$score; ?>" /><br />
<label for="screenshot">Captura de tela: </label>
<input type="file” id=''screenshot" name="screenshot" /><br />■
<label for=’
’
verify">Verificagao:</label>
<input tvpe*=”t
e
y
t
-
.
” ir
j
=
,
*
v
f
>
r
.
-
ifv" name="verify" value="Enter the pass-phrase." />
<imCT/€rc="captcha.php^>lt=,
f
Verification pass-phrasQ.” /> a
<hr /> ^ ______________________ £ a<w © s
£
*
r
i
p
tCrw IUfin
<input type="submit" value="Add" name=”submit" /> siviptA
d
i
ô
i
o
n
â
t
"
«Swltâ nâ i»*3yw« CA>*
sçr e*fotda nâ pâgjnâ-
</body>
</html>
M i m mm
addscore.php
teste drive addscore.php com a funcionaiidade captcha
T& s t O R tv e
Modifique o script Adicionar Pontuação para implementar o suporte a
CAPTCHA.
Modifique o script addscore .php de modo que ele passe a ter um campo Verificação,
bem como a usar o script captcha.php para exibir uma imagem CAPTCHA. Adicione
também o código para verificar se o usuário digitou a senha correta antes de adicionar a
pontuação.
Envie ambos os scripts ao seu servidorweb, e depois, abra addscore .php em um
navegador. Tente adicionar uma nova pontuação sem digitar a senha CAPTCHA. Depois
tente novamente, agora digitando a senha mostrada na imagem CAPTCHA.
0 «osso moderador humano
■
Çinataen-be-be» ?*** graça*
W^a «»ha CAPTCHA nuc se
■Kodiíida £o*sbnW n-fce diiiCui,
aos bcts a tav-e-Pa de -í-azer spam
no -rormulario do éjuitár W
fôrs.
visualizando seus dados... e mais!
nÜ9 existem
■perguntas idiotas
[ * Posso usar as funções GD para
criar imagens em outros formatos além
de PNG?
Sim. As funções imagegif ()
eimagejpegO funcionam de modo
bastante semelhante a imagepng (
)
,
mas criam imagens GIF e JPEG,
respectivamente.
y.
1 • As funções de criação de
imagens podem criar imagens com
transparência?
Sim! Existe uma função chamada
imagecolortransparent(
) que
define uma cor para ser a cor transparente
dentro de uma imagem. Essa precisa
ser uma cor que você já tenha criado
com a função imagecolorallocateQ. Após
defini-la como transparente, qualquer
coisa desenhada nessa cor será
considerada como transparente. Para
gerar a imagem com transparência, chame
imagegif() ou imagepng (); você
nãopodeusar imagejpegO porque
as imagens JPEG não têm suporte ao
recurso de transparência.
T * • Quando usamos im agepng ()
para enviar uma imagem PNG
diretamente ao navegador do cliente,
onde o arquivo .png da imagem é
armazenado, e qual é o seu nome?
Não há nenhum arquivo .png para
a imagem, pelo simples motivo que ela
não é armazenada em um arquivo. Em
vez disso, a função imagepng() gera uma
imagem PNG binária na memória, no
servidor, e então a envia diretamente ao
navegador através de um cabeçalho. Uma
vez que os dados da imagem são criados
e enviados diretamente para o navegador,
não é preciso armazená-la em um arquivo.
* É por isso que eu consigo colocar
o nome do script CAPTCHA diretamente
no atributo src de uma tag <img>?
Correto. Referenciar um script
PHP no atributo src de uma tag <img>,
como fizemos no script captcha.php para
o Guitar Wars, resulta na imagem ser
entregue diretamente pelo script. Isso
é diferente do modo normal como a tag
<img> funciona, onde o nome de um
arquivo gráfico é especificado no atributo
src. Uma vez que o script está enviando
a imagem diretamente para o navegador
através de um cabeçalho (por meio da
função imagepng ()), não se usa um
arquivo. E o navegador sabe que deve
conectar a imagem do cabeçalho à tag
<img> porque o script está especificado
no atributo src.
■ Todoformuláriowebcorreoriscodeser
atacado porbotsdespam, mastodobotde
spam está a mercê de ser combatido por
programadores PHPinteligentes, que usam
técnicas comoCAPTCHAparaderrotá-los.
■ GDé uma bibliotecadegráficos padrãodo
PHP, que lhepermitecriardinamicamente
imagensedesenhartodotipodegráficosou
textosnelas.
■ AfunçãOGDcreatetruecolorimage (
)
éusadaparasecriarumaimagemembranco.
■ Paraenviaruma imagemPNGaonavegador
ouaumarquivonoservidor, chameafunção
GDimagepng (
)
.
■ Aoterminardetrabalharcomuma imagem,
chame imagedestroyO para apagá~la
da memória.
visualizando dados do mismatch
Cinco graus de oposipão
Uma vez que o Mismatch é uma comunidade de usuários
(humanos!) registrados, bots de spam não têm sido problema.
Porém, os usuários querem um pouco mais do recurso de
encontrar pares im perfeitos do site, principalm ente o conceito
de "cinco graus de oposição" de que têm ouvido falar. Os
usuários do Mismatch querem mais do que apenas uma lista de
tópicos do seu par imperfeito ideal - eles querem algum tipo
de contextualização visual de como esses tópicos se relacionam
com cada categoria principal de "desencontrabilidade"
Euvejo ummonte de tópicos, mas
realmente naosei exatamente como nós nos
desencontramos nas diferentes categorias. Eu
gosto do conceito de "cinco graus de oposição",
mas não consigo ver como isso se relaciona ao
meu par imperfeito. Eagora?
0 c o n c e it^ d e
"c in c o g ra u s d e
o p o siç ã o ” d o
M ism a tc h enV plV e
a aVallaçã»
d p s tó p ic o s
d e se n c o n tra d o s p o r
categ p ria.
0 Beli-b c uma fessoâ
0 visual, t «uer ver
o mau do «ue acenas
uma lista de -toftèos
0 reíeren^s ao seu fâr
^ '»m
ç>eY
“£eVfcoideal
/>r>A
visualizando seus dados... e mais!
Fondo a desencontrabilidade m tabela
Como você deve se lembrar, o Mismatch inclui um questionário categorizado, onde
os usuários selecionam as opções Adoro ou Odeio para uma série de tópicos. São
essas respostas que determinam os tópicos que compõem um par imperfeito ideal. Ao
apresentar o par imperfeito ideal para o usuário, o script My Mismatch exibe uma lista
de tópicos desencontrados, que ele cria como um array a partir do banco de dados
do Mismatch. Mas os usuários agora querem mais do que uma lista de tópicos... eles
querem uma representação visual categorizada das suas "desencontrabilidades", talvez
em forma de gráfico.
Reality TV
Horror movies
Easy listening music
The opera
Sushi______
Spicy food
Peanut butter &
banana sandwiches
Martinis
Bill Gates
Yoga
Weightlifting
Cube puzzles
Karaoke
usando os dados do Mismatch, que
mostre visualmente os "cincograus
de oposição" para Belita e Jason.
Escreva oque as informações do
gráfico significam.
Desenhe umgráfico de barras,
FVedisamos ■
fcrâns-ítarmaVf
de alj^ummodo, esta lista
dc tópidos en. um gtriíido
você está aqui ► 631
gravando dados gráficos no array
Desenhe umgráficode barras, usandoosdados do Mismatch, que
mostrevisualmenteos "cincograusdeoposição" para Belitae
Jason. Escrevaoqueas informaçõesdográficosignificam.
e -j, Embora haja muitas W a s diferentes de representar
viswaUe^ oS dados do Mismatdb, ur* ojr&to debarras
• t . *ão é uma rná opdão, uma vC
zl ^ue as dateaorias tem, ta d a j ^ --------^
. â /alores um
a> nUero iftual de tépidos. < / 
de um 3raíido de . ç .--------------- ----------------------------------------- I Cada ba'
barras estabelece
os valores possíveis
para dada barra.
Faixa 3
Cada barra representa o
wmero de desendontros
cm uma dada daíey>ria de
tépidos.
barra do
cyrá-fido -tem
um-trtulo e um
valor - o valor
desta a<ui e 5.
altura de uma barra
reflete a magnitude
do valor para um
determinado título.
Armazenando dados do gráfico de barras
No fim das contas, os dados por trás de ura gráfico de barras são talvez
mais importantes do que os gráficos. Sabendo que esse tipo de gráfico
na verdade é apenas um conjunto de títulos e valores, podemos visualizar
os dados de um gráfico de barras com um array bidimensional, em
que o array principal armazena as barras, enquanto que cada sub-array
armazena o par título/valor para cada barra.
Cada sub-array armazena
o título e o valor pârâ um
dada barra do gra£»do.
/
$graph data = array(
array! "Heading-'.!”/
..$vaíue|||,
array("Heading 2", $value2),
array("Heading 3", $value3)
Cada i-tem do array prmdipal
dorresponde a uma barra-
m
i
r
visualizando seus dados... e mais!
nap existem
P e rg u n ta s Id io ta s
9 } 0 gráfico de barras precisa ser alimentado a
partir de um array bidimensional?
A: Não, não necessariamente. Mas tenha em mente
que cada barra do gráfico geralmente envolve duas
informações: um título e um valor. E cada gráfico contém
várias barras, de modo que um array bidimensional é
uma forma lógica e eficiente de se armazenar dados
usados para preencher um gráfico de barras. Como diz
o ditado, "se você só consegue ver uma solução, você
não entendeu realmente o problema". Neste caso, o
problema é achar a melhor forma de armazenar os
dados a serem injetados em um gráfico de barras, e
uma solução que funciona bem é o array bidimensional.
É claro que o desafio ainda é como exatamente criar
esse array bidimensional com dados das categorias do
Mismatch. 0 primeiro passo é isolar quais dados do
banco entram na solução.
RCÍClO
Oesquema do banco de dados da aplicação Mismatch é mostrado abaixo.
Circule todos os dados que precisam ser usados para a geração dinâmica do
gráficode barras "cinco graus de oposição”,e não se esqueça de escrever
como eles são usados para se criar ográfico
111
user id v —v
username
password
join_date
first name
last name
gender
birth date
city
state
picture
rateaory_id 0 ,
name
response id topic id 0 'ft
response name
1icpr i r i ^ H r _ category id
tnpic id ^
você está aqui ► 633
'exercício solução
RCÍCÍO
S oL u Ç ao
----
•_id o—
username
password
Uesquema do banco de dados da aplicaçao Mismatch e mostrado
abaixo. Circuletodos os dados que precisam ser usados para a
geração dinâmica do gráfico de barras "cinco graus de oposição", e
não se esqueça de escrevercomo eles são usados para se criaro
gráfico..
A doluna user_Jd é usada
para sc donsultar respostas
do Questionário, para Q
ue se A doluna response_id e usada para se
possa deíerminar o melhor par dombinar as respostas de dois usuários,
•mperteito para um usuário. para determinar se elas esta© definidas
dom valores opostos —um desendohtrof.
A doluna dategoryjid è usada
para se assobiar uma dategoria
tom um tépido, o Que leva a uma
resposta desendontrada- 0 nome
da dategoria e impoirtan-te porque
é ele Q
ue formede os -tftulos para
o jjráfido de barras.
join_date
first_name
iast_name
gender
birthdate
city
state
picture
T
ïïÿjïïri
' (^topic id
Adoluna topid_id serve
domo in-termediário para as
dategorias e as respostas, Que t
o Que permite a vode desdobrir
a dategoria de dada resposta
desendon-trada-
0 gráfido de barras reQuer,
em úl-tima instândia, uma
dontagem de Quantos
desendontros existem para
dada dâtegoría; a don-tagem
é o valor para dada barra,
enQuanto Q
^
Co nome da
dategoria t o seu -título.
C O A
Gtáflco de Battas Exp^stP
Na entrevista desta semana:
Lendo entre as linhas com o senhor
dos gráficos
visualizando seus dados... e mais!
Use a Cabeça: Então você é o cara que as
pessoas chamam quando elas precisam de uma
representação visual de alguns dados. E isso
mesmo?
Gráfico de Barras: Exato. Eu sou expert
em todos os tipos de visualização de dados,
principalmente no tipo retangular.
Use a Cabeça!: Então as suas capacidades de
desenho se limitam principalmente a retângulos
Gráfico de Barras: Acho que "se limitam" é
uma expressão forte neste caso. E uma daquelas
situações em que quanto mais simples, melhor
- as pessoas simplesmente parecem mais
acostumadas com as barras, talvez porque elas
estejam acostumadas a ver as coisas medidas dessa
forma. E como aquela barrinha nos celulares
que lhe diz o quão forte está o sinal. "Está
conseguindo me ouvir agora?" Eu adoro isso.
Use a Cabeça!: Certo. Mas eujá vi alguns
gráficos redondos bem eficientes. Me lembram
de coisas boas... como torta de maçã, entende o
que eu quero dizer?
Gráfico de Barras: Entendi o que você está
insinuando, e conheço o Gráfico Torta. Veja, são
duas maneiras diferentes de se pensar sobre a
mesma coisa. O Gráfico Torta vê o mundo em
curvas; eu vejo um pouco mais reto, só isso.
Use a Cabeça!: Ma as pessoas não se
relacionam inerentemente melhor com uma
torta do que com um monte de barras?
Gráfico de Barras: Não, a não ser que elas
estejam com fome. Veja, o Gráfico Torta é
realmente bom para mostrar as partes que
compõem o todo, onde os dados compõem
algo que realmente importa: 100%, 32 times, 50
estados. São 50 estados nos EUA, certo?
Use a Cabeça!: Sim. Bem, assumindo-se que
você conte Washington, D.C. como "distrito
federal" e lugares como Porto Rico e Guam
como "territórios''. Mas, de qualquer forma,
entendo o que você está dizendo sobre o Gráfico
Torta ser mais adequado para revelar partes de
um todo, mas você não faz a mesma coisa?
Gráfico de Barras: Sim, mas tenha em mente que
eu sou muito mais flexível do que o Gráfico Torta.
Você pode me adicionar quantas barras quiser, e eu
não terei problema nenhuma para exibi-las.
No caso do Gráfico Torta, quanto mais coisas
você adiciona, menores as fatias ficam. Chega
um ponto em que as partes ficam difíceis de
visualizar. No meu caso, tudo o que importa
é que as barras têm valores que podem ser
mostrados na mesma escala.
Use a Cabeça!: O que isso significa?
Gráfico de Barras: Bem, eu tenho dificuldades
em mostrar coisas que tenham valores altamente
diferentes - a não ser, é claro, que você não se
importe que as barras sejam altamente diferentes.
O meu ponto forte é mostrar a diferença entre
valores que estejam dentro da mesma faixa. Por
exemplo, talvez você queira que eu mostre o
preço da gasolina ao longo de um período de
um ano, em cujo caso, todos os valores estariam
dentro de uma faixa razoavelmente restrita, por
exemplo, com apenas alguns reais de diferença
uns para os outros.
Use a Cabeça!: Tem certeza disso?
Gráfico de Barras: Eu sei, o preço da gasolina
parece ser um valor que varia sem limites, mas
na verdade não é tão ilimitado assim, dentro do
tipo de situações com que eu lido.
Use a Cabeça!: Então você está acostumado a
ver coisas bem esquisitas, não?
Gráfico de Barras: Você não acreditaria.
Uma vez, um cara criou uma aplicação web
que mantinha registro de quantas milhas ele
arrastava o seu mouse por mês. Ele tinha até um
blog sobre isso, e me usava para representar as
suas "viagens" em forma de gráfico. Bem louco,
mas as pessoas adoram esse tipo de coisa.
Use a Cabeça!: Então esse é o seu campo de
atuação - fornecer representações visuais dos
dados das pessoas?
Gráfico de Barras: Sim, creio que sim. Sempre
que eu posso ser colocado em uma página para
fornecer um visual extra para dados que, sem
mim, ficariam um pouco chatos e difíceis de
entender, considero meu trabalho feito.
Use a Cabeça!: Fico feliz de ouvi-lo. Obrigado
por conversar conosco, espero que possamos
fazer isto novamente.
Gráfico de Barras: O prazer foi todo meu. E não
se preocupe, você continuará me vendo por aí.
você está aqui V 635
construindo um array para categorias
Pe uw array para outro
Um alias « wado
para sc eliminar
' A N
a do^TU
SâOao
referir â dolt*nâ
name da iabela
mismatdb_d*tegory.
Da última vezque vimos o Mismatch, tínhamos uma listade tópicos que
correspondiam a desencontros entre dois usuários. Mais especificamente, nós
tínhamos naverdade um array de tópicos. O problema é que o gráfico de barras
que estamos tentando desenhar não é exatamente sobre os tópicos- é sobre
as categorias associadas com os tópicos. Assim, estamos separados em um nível
dos dados que realmente precisamos. Parece que precisamos de maisalgumas
consultas SQL. Não apenas precisamos do array de tópicos desencontrados,
mas precisamos também de um arrayparalelo semelhante, de categorias
desencontradas.
Umjoin múl-tiplo
dohedta a "tabela das $<
:
íuery = "SELECT mr.response idf mr.topic id, mr .response,
dategorias à tabela mt.name as topic_name, f||§|p||f§
das respostas, de "FROM mísmatch_response AS mr " .
.
modo Q
ue o nome d a. T
," JOIN mismatch topic AS mt ^USING (topic id)
e ^ d c . ^ w
Ojoin adicional nessa consulta faz o nome da categoria
correspondente a cada tópico de resposta ser anexado aos
dados do resultado, acabando no array $user_responses.
Mas lembre-se, nós só precisamos das categorias
desencontradas, e não de todas as categorias. Precisamos
criar outro array, contendo apenas as categorias
desencontradas para as respostas.
topiename category^naire
Appearance
Appearance
Appearance
Appearance
Appearance
Entertainment
Entertainment
Entertainment
i~a no Capitule
o array
bidimensional
i lAserjresponses
-foi driado e
preendbido dom
dados de resultade
dorrespondenies
as respostas do
usuário atual-
Entertainment
Entertainment
Food
Food
Food
Nos ainda predisamos de
um novo array, dontendo
apenas as dategorias
desendon-tradas para este
par de usuários.
A »ova H
doluna” de
dados de resultado
armazena o nome da
dategoria de dada
resposta-
Nos predisamos y,
extrair apenas os f
nomes das dategorias
referen-tes a respostas
desendontradas, e
doloda-los em um array.
Food
Food
people
People
People
People
$user_responses
Mas ainda não estamos atingindo
o nosso objetivo de criar um array
de categorias desencontradas. Para
fazer isso, precisamos revisitar o
código que cria o array de tópicos
desencontrados...
visualizando seus dados... e mais!
T t e S T O R 1 V E
Teste a nova consulta para obter tópicos e categorias desencontrados.
Usando uma ferramenta MySQL, emita a seguinte consulta para selecionar tópicos e
categorias desencontrados para um determinado usuário. Certifique-se de especificar
a ID de um usuário que não só exista no banco de dados, mas que tenha também
preenchido o questionário do Mismatch:
SELECT mr.response_id, mr.topic_id, mr.response,
mt.
name AS topic_name, me.name AS category_name
FROM mísmatch_response AS mr
INNER JOIN mismatch_topic AS mt USING (topic_id)
INNER JOIN mismatch_category AS me USING (category_id)
WHERE mr.user_id = J3;
A (D deve str a de w*
usuário válido, Q
ue
respondido o Questiono do
q i> c.fc,LECT mr . r esp Q n se _ i'd .,. mr ■
.€ o p í c _ i d , s ir v r a s a q n s e ,
t .n a m e AS r.cp i c_n arn e, _mc.na.ms AS catéq.cA ry An'ain'e
ROM mi sm s r,c r.__re s c c a s e. .AS. mr .. . ' '
NAA.S o rr.isngi:ci'.._tôpr^c.. AS -.mt U SIN Q A ixQ pi'c id )
NNER JOIN :n is n a t:c h _ c a -e ç o .r y AS inc USING ' (C £ t e g o r y _ id )
HERE n r . user'A td.' = .•3-;A. A A ' . A -A.-- A • ■
i a } - r e s p o n s e ■:i ^ c p i c ;.cirri;
.. ! .1' 1 T a x t c c s
’ !.. 2 .' ' G o id c h a i:
' i l . 1 E ody- p i e r i
: i;' 2 A i i ' C o ^ ' û o v b e i
ï
L o n g h a ï r
... i. :
■ ; ; R e a ^ it y . T
! i P r q f e s s i o r
A A - :: AAi F .o r r c r no-,
! ■c a t e g o r y r.ami
.+ ----------------- ------
■
, A p p e a r a n c e
■
; A p p e a r a n c e
.^jc'ps tri"c <
3
.nc ^
•
! A p p e a r a n c e
 A p p e a r a n c e a
1..E n t c.r t a i r.me n t
i E n ter'iia in .T ien t
i E n t e r t a in m e n t
■
i E n t e r t a in m e n t
w r e s t i m c
s y l i s t e n i n q m u s ic '
Repava Que os resul-fcôdos desta tonsui'fca
bâte» to * o av-v-ay ?usev_jrespo*ses da
página airrbeviov, Que e o Que *os Queremos.
r
E sennpv-e u»»a bod ideia
testar as donsui-fcas em u»»a
-fe^rameh-ta My£$L antes de
doioia-las ko dódijo PUP.
você está aqui > 637
Construindo um arry por tópicos
Crie um array detópicos desencontrados
Agora nós temos uma consulta que realiza umjoin múltiplo para obter a categoria de cada
resposta, além do tópico, que é então colocada no array $user_responses. Lembre-se que
outra consulta, parecida com esta, também está obtendo dados para cada outro usuário do
banco, para que as comparações de desencontrabilidade possam ser feitas. Assim, $user_
responses armazena os dados de resposta para o usuário logado no Mismatch, enquanto que
$mismatch_responses armazena um dos outros usuários do sistema. Isso nos permite fazer
um loop através de todos os usuários, e atualizar $mismatch_responses em cada comparação.
Nósjá estamos usando esses dois arrays para encontrar pares imperfeitos e para criar um
array de tópicos desencontrados. Agora, podemos adicionar uma nova linha de código
para construir também um array de categorias desencontradas - este array conterá a
categoria de cada tópico desencontrado entre dois usuários.
Este i o mesmo dod'150 da versão anterior do Mismâtdh,
f e*deto feio +
<
3
rfcode Q
ue a$ora ele dria um array de
y, tate^orías desencontradas, alem do array de tépidos.
Çcategories = array{);
for ($i = 0; $i < count($user_responses); $i++) {
if ($user_responses[$i] [’response 1] + $mismatch_responses[$i] ['response'
]
== 3) {
?score -
+
= 1;
array push($topics, $user responses[$i] ['topic_name']);
' , t
Este código resulta em um
array toniendo apenas as
eatejorias desencontradas.
Ko íim das dontas, o array
/date^ories dontem uma dâtegoria
pôra dada desendontro.
na° existam
perguntas Idiotas
Um array de dategorias
desendontradas é driado
armazenando-se a dategoria
assodiada dom dada resposta
desendontradâ-
Estou um pouco confuso. Qual é adiferença entre
um conjunto de resultados do MySQL e um array do PHP?
K: Uma grande diferença é 0acesso. Um conjunto
de resultados só disponibiliza uma linha de dados de
cada vez, enquanto que um array pode armazenar
várias "linhas" de dados, graças às múltiplas dimensões.
Colocar um conjunto de resultados em um array
bidimensional permite que nos movamos através das
linhas de dados de forma eficiente, sem termos que
ficar voltando ao servidor do banco de dados para
obter linhas várias vezes. Isso não funciona com
conjuntos enormes de dados, uma vez que para isso
você precisaria criar arrays enormes; mas, no caso das
respostas do Mismatch, os arrays nunca são maiores do
que 0número total de tópicos no sistema.
I * Mas nós ainda precisamos contar quantas
vezes uma categoria foi desencontrada para
podermos gerar 0 gráfico dé barras, certo?
Certo. Um array de categorias desencontradas
não é suficiente. Lembre-se de que a ideia por trás
do gráfico de barras do Mismatch é que cada barra
representa uma categoria desencontrada, e que a
altura da barra representa quantas vezes a categoria
foi desencontrada. Assim, precisamos de uma forma de
contar quantas vezes cada categoria foi desencontrada.
Mas provavelmente vale a pena dar um passo atrás,
para formularmos um plano geral de ataque....
visualizando seus dados... e mais!
Formulando umplano para exeeupãodos gráficos debarras
Com um array de categorias desencontradas e um monte de ideias sobre como usá-las
para gerar um gráfico de barras para a página My Mismatch, só o que nos falta é um plano.
Como veremos logo abaixo, só são necessários três passos para se gerar dinamicamente o
gráfico de barras, ejá realizamos um deles.
Este passo nos íor»>eCe
a lista das categorias
desencontradas-
^ ConsnWdr o ba»co~c lrtfaKtoyilo Mismatch cm buocn dos
nomps das catogorias desencontradas
O Calcular os totais de desencontros para
cada categoria.
0 Desenhar o gráfico de barras usando-se os
totais das categorias.
Para completar o Passo 2 do nosso plano, precisamos de
alguma forma de pegar o array de categorias desencontradas e
transformá-lo em um conjunto de totais para as categorias, ou
seja, uma contagem de quantas vezes cada categoria aparece no
array. Como você deve se lembrar, esse é, precisamente, o tipo
de dados requeridos para se criar um gráfico de barras, onde as
categorias são os títulos e a contagem para cada categoria é o
valor de cada barra. Um array bidimensional pode ser usado para
se combinar categorias e totais em uma única estrutura de dados.
A lista de categorias
précisa ser Convertida
e» uma lista de totais.
Tendo os totais das categorias,
m
ós podemos passar para
ã parte divertida, <ue e
desejar o gráíico de barras
Com íun^oes
0lKar o »ovo array
Appearance
I S Entertainment 4
J B Food 4
J p people 2
Activities 5
das categorias por U
m
angulo diterente revela
C
or*©de g usado para
rn UY os «fedos a©
gra+íc© de barras.
Este array Contém o
nome de cada categoria,
uttto Com o total
i c *
de vezes <
^
u
e ela toi
desenCofttrada.
Os novos dados das
Categorias desencontrada
s3©cxdtdmente o «ue
precisados para o gra-fic©
de barras.
Uma vez criado esse array de totais, estaremos prontos para seguirmos
para o Passo 3, onde usaremos algumas funções GD para gerar o visual do
gráfico de barras.
você está aqui ► 639
um pouco de matemática de array
Amassando as categorias
O desafio agora é totalizar o array de categorias e colocá-lo em um array
bidimensional de títulos e valores. Nós temos um array de categorias
desencontradas armazenado em ^categories. Precisamos criar um novo
array cham ado $ category_totais, que irá conter um a entrada para cada
categoria,junto com o número de desencontros para cada uma.
Precisamos
partir disto..
0 número -bvhêl de
otorremttds de uma da£«govia
noasrây fdaiejotries apaveCe
Ê
O
rw
®u
m
ntoial hOSYYdy
f Câtegory^to-tals.
...e chegar a isto!
Appearance
—s.
s j j
4
I Entertainment
Food 4
People 2
Activities 5
$category_totais
$categories
W K R C T R «
Como você faria para totalizar as categorias
desencontradas no array Scategories, para criar o
array bidimensional $category_totals?
visualizando seus dados... e mais!
A matemática das categorias
Passar de um array unidimensional de categorias desencontradas para um array
bidimensional de totais das categorias pode ser um pouco mais complicado do que você
poderia pensar, à primeira vista. Por esse motivo, é útil trabalhar na solução através
de pseudocódigo antes de realmente escrever qualquer PHP. O pseudcódigo nos livra
dos detalhes sintáticos e nos permite focalizar nas ideias centrais envolvidas em uma
determinada solução de codificação.
Criar um novo array bidimensional para armazenar os totais das categorias,
certificando-se de inicializar o primeiro elemento com a primeira categoria
desencontrada e uma contagem 0.
Fazer loop através do array de categorias desencontradas. Para cada
categoria do array...
O último elemento do array contendo os totais é de uma categoria
diferente do desencontro atual?
^ S im ! Temos uma nova categoria, portanto vamos adicioná-
la ao array com os totais das categorias e inicializar a sua
contagem como 0.
^ Não. Esta é apenas uma nova instância da categoria atual,
portanto vamos incrementar a contagem do último elemento
do array com os totais das categorias.
O produto deste código é um array bidimensional de totais, no qual o
array principal armazena uma única categoria, enquanto que cada sub-
array contém o nome da categoria e o seu valor.
Traduza o pseudocódigo para completar ocódigo PHP real que cria oarray
bidimensional de dados de categorias do Mismatch, chamado $category_totals.
$category_totals = array{array{$mismatch_categories[0], 0));
foreach ($mismatch__categories as $category) {
}
você está aqui ► 641
exercício solução
Traduza o pseudocódigo para completar ocódigo PHP real que cria oarray
ibidimensional de dados de categorias do Mismatch, chamado $category_totals.
ttr ír ío arrays sao inde*ados a
partir do zero, portanto o
S o L u ç a o ultimo elemento de um ârray e
sempre Count^ «*enos um
.
$category_totals = array (array ($mismatch_categories [0], 0) );
foreach (Smismatch categories as Scateaorv) l
-
i-P (fcategory^totaUtcountífcategory^totaU) - 3C03 /—fcategory) {
,^!^.y(í£^kgory) ^ ta e uma nova categoria,
j ^ _______ ^ portanto vamos adiciona-la ao
..................................................................................................... array de totais, na -Por»,a de um
ejse { sub-array Consistindo do nome
.....-• ncn++;.... ' ie
....1.......................................................................................^Tmr.. 0 ofwâdov- de infiremen-t»
^ C++) é aplicado ao segundo
elemento do sub-array, <ue e
a dontage» das categorias.
$category__totals
/
A variável ?category_totais
agora armazena precisamente os
dados necessários para se gerar
um gra-fico de barras para as
categorias desencontradas.
Este e o resultado
-Pina) deste código-
Agora nos podemos
riscar este passo da
lista, o ^ue nos deixa
apenas com a tareia de
desenhar o grá£ic© de
barras.
0 Calc ular os totais de
dese
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf
Use a Cabeça - PHP.pdf

Use a Cabeça - PHP.pdf

  • 1.
    Primeiros Elogios aoUse a Cabeça! PHP & MySQL “PHP e MySQL são duas das tecnologias de desenvolvimento web mais populares de hoje em dia, e este livro mostra aos leitores o porquê. Criar um site sem elas, atualmente, é tão inimaginável quanto fazer web design sem CSS. Este livro é uma ótima introdução e é também uma boa fonte de risadas. E o livro que eu queria ter tido quando estava aprendendo.” — HarveyQuamen, ProfessorÁssociado de Inglês e Humanities Computing, Universidade deAlberta “Tudo o que nos acostumamos a aceitar como trabalho pesado no processo de aprendizado técnico foi abandonado, e em seu lugar foi criado um incomum método de aprendizado divertido. Eu tenho plena confiança de que a série Use a Cabeça! irá revolucionar a indústria de livros técnicos, e que estes métodos acabarão se tornando o padrão. Aposto que até a minha avó tecnofóbica poderia aprender técnicas de PHP e MySQL após uma única leitura. Ela provavelmente ainda se divertiria ao fazê-lo!” —Will Harris,Administrador de Bancos de Dados, Powered ByGeek “Ler Use a Cabeça! PHP 8c MySQL é como assistir a uma aula do professor ‘legal’.Faz você ficar com vontade de aprender.” ----Stephanie Liese, DesenvolvedoraWeb “Usando imagens e humor, o livro é fácil de digerir, e ainda por cima apresenta um sólido conhecimento técnico.” —JeremeAlien, DesenvolvedorWeb “Após uma desafiadora e ultrarrápida primeira leitura, e vários projetos práticos divertidos, como por exemplo “Meu cachorro foi abduzido por alienígenas”e a “Agência de Encontros Mismatch”,não vejo a hora de adicionar um pouco de PHP aos meus sites.” — David Briggs.Engenheiro de Software e Escritor de Livros Técnicos
  • 2.
    Elogios ao Usea Cabeça! HTML com CSS & XHTML “Eric e Elisabeth Freeman claramente entendem do assunto. À medida que a Internet vai se tornando mais complexa, fica cadavez mais importante criar páginas web atraentes. O design elegante é o cerne de todos os capítulos aqui, e cada conceito é apresentado com doses iguais de pragmatismo e inteligência.” — Ken Gold-Stein,Vice-Presidente Executivo &Diretor-Gerente, Disney Online “Aweb seria um lugar muito melhor se todo designer HTML começasse lendo este livro.” — L. David Baron, Diretor Técnico de Layout &CSS, Mozilla Corporation, http://dbaron.org/ “Eu escrevo HTML e CSS hã dez anos, e o que antes era um longo processo de aprendizado por tentativa e erro agora acaba de ser reduzido a um único e atraente livro. HTML costumava ser algo que você simplesmente ficava fuçando até que as coisas ficassem bem na tela, mas com o advento de padrões web e a exigência de melhor acessibilidade, práticas de programação preguiçosasjá não são mais aceitáveis... nem do ponto de vista empresarial, nem do ponto de vista da responsabilidade social. Use a Cabeça! HTML com CSS &XHTML lhe ensina como fazer as coisas corretamente desde o princípio, sem fazer com que o processo pareça impossível de aprender. A linguagem HTML, quando corretamente ensinada, não é mais complicada do que aprender inglês, e os Freemans íizerám um excelente trabalho em manter todos os conceitos compreensíveis.” — Mike Davidson, Presidente &CEO, Newsvine Inc. “Ah, ótimo. Vocês fizeram um livro de XHTML simples o suficiente para que um CEO consiga entendê-lo. O que farão a seguir? Um livro de contabilidade simples o suficiente para que o meu desenvolvedor consiga entender? Se continuar assim acabaremos tendo de fazer coisas como colaborar e trabalhar em equipe.” —Janice Fraser, CEO, Adaptive Path “Este livro tem humor, charme, mas o mais importante: tem coração. Eu sei que parece algo ridículo de se dizer sobre um livro técnico, mas eu realmente percebo que, no seu cerne, este livro (ou pelo menos os seus autores) realmente está preocupado em fazer os leitores aprenderem o material. Isso se faz notar no estilo, na linguagem e nas técnicas. O aprendizado - realmente entender e compreender - pelo leitor é claramente o objetivo número um na mente dos Freemans. E obrigado, obrigado, obrigado pela forte e sensível insistência que o livro prega pelo respeito aos padrões. É ótimo ver um livro para iniciantes, o qual acredito, que vai ser amplamente lido e estudado, fazer uma campanha tão eloquente e persuasiva pelo valor do respeito aos padrões na programação de páginas web. Encontrei aqui até mesmo alguns argumentos que ainda não tinham-me ocorrido - argumentos que eu posso me lembrar e usar quando as pessoas me perguntam, e elas perguntam, ‘qual a vantagem de respeitar os padrões, e por que eu devo fazê-lo?’Agora eu tenho mais munição! Também gostei do fato de o livro apresentar alguns fundamentos sobre a mecânica de como realmente colocar a página no ar - FTP, fundamentos do servidor web, estruturas de arquivos, etc.” —Robert Neer, Diretor de Desenvolvimento de Produto, Movies.com
  • 3.
    Elogios ao Usea Cabeça! JavaScript “Tão prático e útil, e tão bem-explicado. Este livro faz um excelente trabalho dt^apresentar um iniciante total aoJavaScript, e é mais uma prova da eficiência do método dè ensino Use a Cabeça! De todos os outros livros deJavaScript, Use a Cabeça!JavaScript é ótimo para aprender, comparado com outros livros de referência do tamanho de listas telefônicas.” —Alex Lee, Estudante, Universidade de Houston “Uma excelente opção para o desenvolvedorJavaScript iniciante.” — Fletcher Moore, Desenvolvedor e DesignerWeb, GeorgiaInstitue of Technology “Mais um ótimo livro no clássico estilo ‘Use a Cabeça!’” — TWScannell “OJavaScript vem sendo há bastante tempo o sistema por trás das páginas web, no lado do cliente, mas vem sendo também mal entendido e mal utilizado. Com Use a Cabeça! JavaScript, Michael Morrison apresenta uma introdução direta e fácil de entender sobre a linguagem, removendo quaisquer mal entendidos que possam ter existido e mostrando como usá-la da forma mais eficiente para melhorar suas páginas web.” — AnthonyT. Holdener UI, Desenvolvedor de aplicaçõesweb e autordeAjax: O GuiaDefinitivo “Uma página web tem três partes - conteúdo (HTML), aparência (CSS) e comportamento (JavaScript).Use a Cabeça! HTML apresentou os dois primeiros, e este livro usa a mesma abordagem divertida e prática para introduzir oJavaScript. A forma divertida com que o livro apresenta oJavaScript, e as muitas formas como ele reforça as informações para que você não as esqueça, fazem deste um livro perfeito para iniciantes usarem para começar a aprender a tomar suas páginas web interativas.” — Stephen Chapman,Dono daFelgallPtyLtd., editor deJavaScriptde about.com “Este é o livro que eu estive procurando para recomendar aos meus leitores. E simples o suficiente para totais iniciantes, mas inclui aprofundamentos suficientes para ser útil aos usuários mais avançados. E toma divertido o processo de aprendizado. Este pode acabar sendo o único livro deJavaScript de que você precisará.” —Julie L. Baumler, EditoradeJavaScriptde BellaOnline.com
  • 4.
    Outros livros dasérie Use a Cabeça! Use a Cabeça! Java Use a Cabeça! Análise & Projeto Orientado a Objetos (A&POO) Use a Cabeça! Ajax Iniciação Rápida Use a Cabeça! H TM L com C SS e X H TM L Use a Cabeça! Padrões de Projeto Use a Cabeça! Servlets e JSP Use a Cabeça! PM P Use a Cabeça! SQL Use a Cabeça! Desenvolvimento de Software Use a Cabeça! JavaScript Use a Cabeça! C # Use a Cabeça! PH P & M ySQL Use a Cabeça! Física Use a Cabeça! Álgebra Use a Cabeça! Ajax Profissional Use a Cabeça! Estatística Use a Cabeça! Ruby on Rails
  • 5.
    Use a Cabeça!PHP & MÿSQL v í - ALTABOOKS E D I T O R A Rio de Janeiro 2010
  • 6.
    Use aCabeçal PHP&MySQL Copyright © 2010 da Starlin Alta Con. Com. Ltda. ISBN: 978-85-7608-502-7 ProduçãoEditorial: Starlin Alta Con. Com. Ltda. Gerênciade Produçáo: Maristela Almeida CoordenaçãoAdministrativa: Anderson Câmara Supervisão deProdução: Angel Cabeza Tradução: Marcelo Santos Revisão Gramatical: Fátima Regina Félix RevisãoTécnica; Giuliana Cirelli Formada em Engenharia Elétrica com ênfase em eletrônica. Especializada em Programação em linguagem C++ enos ambientes de desenvolvimento Eclipsee VisualStudio. Diagramação: Haroldo Sodré Fechamento: Luis Rodrigues TranslatedFrom Original: Head First PHP & MySQL ISBN: 978-0- 596-00630-3 Use a Cabeça.!PHP & MySQL © 2010 Starlin Alta Con. Com. Ltda. AuthorizedtranslationoftheEnglishedition ofHeadFirstPHP &MySQL © 2009 Lynn Beighley andMichaelMorrison. This translation ispublished and sold bypermission ofO’Reilly Media, Inc., the owner ofall rights to publish and sellthe same. PORTUGUESE language editionpublished by EditoraStarlinAlta Con. Com. Ltda. Copyright©2010 byEditoraStarlin Alta Con. Com. Ltda. Todos osdireitos reservadoseprotegidos pelaLei ne9.610/98. Nenhuma parte deste livro, sem autorização prévia por escrito da editora, poderá ser reproduzida ou transmitida sejam quais forem os meios empregados: eletrônico, mecânico, fotográfico, gravaçáo ou quaisquer outros. Todo o esforço foi feito para fornecer a mais completa e adequada informação, contudo a editora e o(s) autor(es) náo assumem responsabilidade pelos resultados e usos da informação fornecida. Recomendamos aos leitorestestarainformação,bemcomotomartodososcuidados necessários (como o backup), antes da efetiva utilização. Este livro não contém CD-ROM, disquete ou qualquer outra mídia. Erratas e atualizações: Sempre nos esforçamos para entregar a você, leitor, um livro livre de erros técnicos ou de conteúdo; porém, nem sempre isso é conseguido, seja por motivo de mudança de software, interpretação ou mesmo quando alguns deslizes constam na versão original de alguns livros que traduzimos. Sendo assim, criamos em nosso site, www.altabooks.com. br, aseção Erratas, onde relataremos, com a devida correção, qualquer erro encontrado em nossos livros. Avisos e Renúncia de Direitos: Este livro é vendido como está, sem garantiade qualquer tipo, sejaexpressaou implícita. Marcas Registradas: Todos os termos mencionados e reconhecidos como Marca Registrada e/ou comercial são de responsabilidade de seus proprietários. A Editora informa não estar associada a nenhum produto e/oufornecedorapresentadonolivro.Nodecorrerdaobra,imagens,nomes de produtos efabricantes podem ter sido utilizados e, desde já, aEditora informa que o uso é apenas ilustrativo e/ou educativo, não visando ao lucro, favorecimento ou desmerecimento do produto/fabricante. Impressono Brasil O código de propriedade intelectual de Io de julho de 1992 proíbe expressamente o uso coletivo sem autorização dos detentores do direito autoraldaobra,bemcomoacópiailegaldooriginal.Estapráticageneralizada, nos estabelecimentos de ensino, provoca uma brutal baixa nas vendas dos livrosaponto de impossibilitarosautoresde criaremnovas obras. ALTABOOKS EDITORA Rua Viúva Cláudio, 291 - Bairro Industrial do Jacaré TFP- 9n07<vn31 -R in Ar Tan^irn-Tfl • 71 377R-SWÍ0/S41 0 Riy- 71 3777-17^3
  • 7.
    Para os meuspais, que frequentemente usam aplicações web e estão sempre me apoiando -Lynn Beighley Para Rasmus Lerdorf, que iniciou sozinho a linguagem que acabaria se tornando o PHP como nós o conhecemos. Prova duradoura de que realmente basta uma pessoa para liderar a todos nós em direção a um caminho novo e mais esclarecido. -Michael Morrison
  • 8.
    o(s) autor{es) Os Autoresde Use a Cabepa! PttPS- MySQL Lynn Beighley é uma escritora de ficção presa no corpo de uma escritora de livros técnicos. Após descobrir que escrever livros técnicos realmente dava dinheiro, ela aprendeu a aceitar e desfrutar a profissão. Depois de voltar à escola para obter um Mestrado em Ciência da Computação, trabalhou para os acrônimos NRL e LANL. Depois, descobriu o Flash e escreveu seu primeiro best-seller. Vítima de um timing infeliz, mudou-se para Silicon Valley pouco antes da grande crise. Passou alguns anos trabalhando para o Yahoo! e escrevendo outros livros e cursos de treinamento. Finalmente rendendo-se ã sua vocação de escritora, mudou-se para a área de Nova Iorque para obter um MFA em Escrita Criativa. Sua tese, escrita no estilo Use a Cabeça!, foi defendida diante de uma sala lotada de professores e colegas estudantes. Foi extremamente bem-recebida, e ela terminou seu curso, terminou Use a Cabeça! SQL, e acabou de terminar Use a Cabeça!PHP àf MySQL. Ufa! Lynn adora viajar, escrever e inventar histórias detalhadas sobre totais estranhos. Ela tem um pouco de medo de OVNIs. £,VtâC^ Mo'r'f'SOir' Michael Morrison tem sido um contribuinte entusiasmado ao mundo online desde quando mantinha um BBS no seu Commodore 64, na época em que ser nerd era bem menos maneiro do que hoje em dia. Alguns milhares de bauds depois, ele ainda fica fascinado com o progresso que fizemos, e com que rapidez. Michael não tem mais um BBS, mas ainda se mantém bastante envolvido com os equivalentes modernos e com as ferramentas que usamos para criá-los. Ele passa a maior parte do seu tempo “oficial” escrevendo sobre tecnologias relacionadas com a web, tendo escrito ou co-escrito mais de cinquenta livros, a respeito desde programação de jogos para celulares até XML. Entrou no universo Use a Cabeça! com Use a Cabeça! JavaScript e não parou mais. Michael é também o fundador da Stalefish Labs (www.stalefishlabs.com,uma empresa de entretenimento especializada emjogos, brinquedos e mídia interativa. Ejá foi visto passando tempo fora da Internet (o quê?!) andando de skate,jogando hóquei no gelo e cuidando do seu lago de carpas com sua esposa Masheed. Ele até mesmo dorme, de vez em quando.
  • 9.
    conteúdo Conteúdo (Sumário) Introdução xxvii 1Está Vivo: Adicionando Vida às Suas Páginas Estáticas 1 2 Como Tudo se Combina: Conectando-se ao MySQL 59 3 Criando os Seus Próprios Dados: Crie e Preencha um Banco de Dados 103 4 Sua Aplicação na Web: Aplicações Realistas e Práticas 159 5 Quando um Banco de Dados Não é o Suficiente: Trabalhando com Dados Armazenados em Arquivos 223 6 Presuma que Estão Todos Querendo Te Pegar: Tom ando a Sua Aplicação Segura 295 7 Lembra de Mim?: Criando Aç|icações Web Personalizadas 345 7V4 Compartilhar é Cuidar: Elimine Código Duplicado 417 8 Colhendo Dados: Controle Seus Dados, Controle Seu Mundo 427 9 Vivendo Melhor Através das Funções: Funções String e Personalizadas 501 10 Regras Para Substituição: Expressões Regulares 561 11 Desenhando Gráficos Dinâmicos: Visualizando seus Dados...e Mais! 605 12 Interfaces com o Mundo: Republicação e Serviços Web 657 i Os Dez Principais Tópicos (Que Não Abordamos): Sobras 713 ii Um Lugar para Brincar: Configure um Ambiente de Desenvolvimento 731 iii O btenha Ainda Mais Proveito: Amplie Seu PHP 749 índice Remissivo 755 Conteúdo (a coisa real) Introdução Seu cérebro ligado no PHP e MySQL. você está tentando aprender alguma coisa, enquanto o seu cérebro está lhe fazendo um favor ao certificar-se de que você não aprenda. Seu cérebro está pensando “é melhor guardar espaço para coisas mais importantes, como por exemplo, quais animais selvagens evitar e se fazer yoga em baixo d'água é uma boa ideia". Então, como enganar o seu cérebro, fazendo-o pensar que a sua vida depende de aprender PHP e MySQL? A quem se destina este livro? xxviü Sabemos o que você está pensando xxix Metacognição xxxi Faça seu cérebro lhe obedecer xxxiii Leia-me xxxiv Revisão técnica xxxvi Agradecimentos xxxvii ix
  • 10.
    conteúdo (sumário) Adicionando Vidaàs Suas Paginas Estáticas Está Vivo Você tem criado ótimas páginas web com HTML, com toques de CSS. Mas tem percebido que os visitantes do seu site não podem fazer muita coisa além de olhar passivamente o conteúdo das páginas. A comunicação está unidirecional, e você gostaria de mudar isso. Na verdade, o que você realmente gostaria é de saber o que o seu público está pensando. Mas para isso é preciso permitir que os usuários digitem informações em um formulário web, para que possa saber o que eles têm em mente. E também precisa ser capaz de processar essas informações, para que elas lhe sejam entregues. Está começando a parecer que vai precisar de mais do que HTML para levar seu site para o próximo nível. HTML é estático e chato 2 PHP dã vida às páginas web 3 Um formulário ajuda Owen a descobrir toda a história 5 Formulários são feitos de HTML 6 O formulário HTML apresenta problemas 8 HTML roda no cliente 10 PHP roda no servidor 11 Os scripts PHP rodam no servidor 12 Use PHP para acessar os dados do formulário 16 Os scripts PHP precisam ficar em um servidor! 18 O servidor transforma PHP em HTML 22 Algumas regras PHP para o seu código 25 Encontrando o nom e perfeito para a sua variável 26 Variáveis servem para armazenar dados de scripts 31 POST é um a variável especial que armazena dados do formulário 33 $_POST transporta os dados do formulário para o seu script 34 Criando o corpo da mensagem de email com PHP 44 Até mesmo texto simples pode ser formatado... um pouco 46 Newlines precisam de aspas duplas 47 Crie um a mensagem de email para Owen 48 As variáveis armazenam as partes do email 49 Enviando um a mensagem de email com PHP 50 Owen começa a receber emails 53 Owen começa a perder emails 54
  • 11.
    conteúdo (sumário) C on e c ta n d o -s e M / S o L Como Tudo se Combina Saber como as coisas se encaixam, antes de começar a construir, é uma boa ideia. Você criou seu primeiro script PHP, e ele está funcionando bem. Mas obter os seus resultados em um email já não é bom o suficiente. Agora precisa de uma forma de guardar os resultados do seu formulário, para que possa mantê-los pelo tempo que precisar, e ter acesso a eles quando quiser. Um banco de dados MySQL pode armazenar seus dados para você. Mas é preciso conectar seu script PHP ao banco de dados MySQL para fazer isso acontecer. O formulário de Owen funciona bem. Bem até demais... MySQL é excelente para armazenar dados Owen precisa de um banco de dados MySQL Crie um banco de dados e um a tabela MySQL A instrução INSERT em ação Use SELECT para obter dados da tabela Deixe o PHP lidar com as coisas tediosas do SQL O PHP permite usar os dados do formulário web de Owen Conecte-se ao seu banco de dados a partir do PHP Insira dados com um script PHP Use funções PHP para falar com o banco de dados Conecte-se com mysqli_connect() Construa a query INSERT no PHP Consulte o banco de dados MySQL com PHP Encerre sua conexão com mysqli-close{) $_POST fornece os dados do formulário Owen precisa de ajuda para peneirar seus dados 91 60 61 62 64 67 70 73 74 76 77 78 80 85 96 86 87 1 Owen sai em busca de Fang 98
  • 12.
    Crie e rteencjicium Betnco de Dcufos Criando os Seus Próprios Dados Nem sempre você tem os dados de que precisa. Às vezes você mesmo tem que criar os dados que pretende usar, às vezes precisa criar as tabelas que irão armazenar esses dados E às vezes precisa criar o banco que armazenará os dados que precisa criar. Confuso? Você não ficará. Prepare-se para aprender como criar seus próprios bancos de dados e tabelas. E se isso não for o suficiente, ainda criará, no processo, a sua primeira aplicação combinando PHP e MySQL. A loja Elvis está aberta 104 Elmer precisa de um a aplicação 105 Visualize o projeto da aplicação de Elmer 106 Tudo começa com um a tabela 109 Faça contato com o servidor MySQL 110 Crie um banco de dados para os emails de Elmer 111 Crie um a tabela dentro do banco de dados 112 JPrecisamos definir os nossos dados 113 I Conheça alguns tipos de dados MySQL 114 Crie sua tabela com um a consulta 117 SELECIONE o banco de dados antes de usá-lo 120 DESCRIBE revela a estrutura das tabelas 123 I Elmer está pronto para armazenar dados 125 Crie o script “Adicionar Email” 126 O outro lado da aplicação de Elmer 133 O funcionamento interno do script “Enviar Email” 134 Em primeiro lugar, obtenha os dados 135 mysqli_fetch_array() obtém os resultados da consulta 136 Loop para um WHILE 139 Loop através dos dados com while 140 Você tem email... de Elmer! 145 As vezes, as pessoas querem sair 146 Removendo dados com DELETE 147 Use WHERE e DELETE para apagar dados específicos 148 Minimize o risco de apagamentos acidentais 149 QueroSerElvis.com é um a aplicação web 154 conteúdo (sumário) custom erm afling(ítf;
  • 13.
    A p li c a r e s R e a lis ta s e p r á tic a s Sua Aplicação na Web Às vezes você precisa ser realista e repensar seus planos. Ou então planejar com mais cuidado logo no começo. Uma vez lançada a sua aplicação na Web, você poderá descobrir que não planejou suficientemente bem. Coisas que pensou que funcionariam podem não ser boas o suficiente no mundo real. Este capítulo dá uma olhada em alguns problemas do mundo real que podem ocorrer quando você transfere sua aplicação do ambiente de testes para um site real. E enquanto isso, lhe mostraremos exemplos de códigos PHP e SQL importantes. conteúdo (sumário) MateMe&vfccoM itocyçw rlIrW raíT *.Ja*rw > w ò M a f c * M aB v f e « w i f l n f l ' l & l E r*3 u -, C us»ni*r<*!retncw efl. nD & n n y d e r v i y Q J W f l h ^ g u n M d l s k Qh r o * W v f l f l l J w s f i g e l i e r r a a b d u e i M n « - « W 0 S & » / t K r « â J e « OD c nD í a o w a r a p e f ô s ^ i n g - í f i o p ô T . í ô m Elmer tem alguns clientes irritados 160 Protegendo Elmer de... Elmer 163 Exija bons dados do formulário 164 A lógica por trás da validação de Enviar Email 165 Seu código pode tomar decisões com IF 166 Testando em busca da verdade 167 IF verifica mais do que apenas igualdade 168 A lógica por trás da validação de Enviar Email 171 Funções PHP para verificar variáveis 172 Teste múlüplas condições com AND e OR 179 Os usuários do formulário precisam de feedback 183 Facilite a entrada e a saída do PHP 193 Use um flag para evitar código duplicado 194 Codifique o formulário HTML apenas um a vez 195 Um formulário que referencia a si raesmo 199 Aponte a ação do formulário para o script 200 Verifique se o formulário foi submetido 202 Alguns usuários ainda estão insatisfeitos 206 As linhas da tabela precisam ser identificáveis individualmente 208 As chaves primárias possibilitam a identificação individual 210 Das caixas de verificação até as IDs dos clientes 215 Faça loop através de um array com foreach 216 xiii
  • 14.
    conteúdo (sumário) T rab a lh a n d o c o m D a d o s A rm a z e n a d o s ©m A í^ u lV o s Quando um Banco de Dados Não é o Suficiente Não acredite no hype... peio menos não naquele sobre OSbanCOS de dados. Certamente os bancos são maravilhosos para se armazenar todo tipo de dados que envolvam texto, mas e quanto aos dados binários? Coisas como imagens JPEG e documentos PDF? Faz sentido armazenar todas essas figuras da sua coleção de palhetas raras de guitarra em uma tabela de banco de dados? Geralmente não. Esses tipos de dados normalmente são armazenados em arquivos, e nós os deixaremos nos arquivos. Mas é inteiramente possível ter o melhor de dois mundos - este capítulo revela que você pode usar arquivos e bancos de dados juntos para criar aplicações PHP cheias de dados binários. Guitarristas virtuais gostam de competir 224 A imagem é a prova 225 aplicação precisa armazenar imagens 226 Planejando os uploads de arquivos gráficos no Guitar Wars 231 O banco de dados das pontuações máximas precisa ser ALTERado 232 Como fazer para o usuário enviar a imagem? 236 Insira o (nome do) arquivo gráfico no banco de dados 238 Descubra o nome do arquivo enviado 239 Para onde foi o arquivo enviado? 244 Crie um lar para os arquivos gráficos enviados 248 Dados compartilhados precisam ser compartilhados 254 Serão necessários dados do script compartilhado 255 Pense em require_once como um “inserir” 256 O mais im portante para as pontuações máximas é a ordem 258 Homenageando o Guitar Warrior núm ero um 261 Formate a maior pontuação com HTML e CSS 262 São permitidas apenas imagens pequenas 267 A validação de arquivos torna a aplicação mais robusta 268 } - Planeje um a página Admin 272 Gere links para remoção de pontuações na página Admin 275 Os scripts são capazes de comunicarem-se uns com os outros 276 Sobre GETs e POSTs 278 GET, POST e a remoção d e pontuações 280 Isole a maior pontuação para ser removida 283 Controle o quanto você pode remover com LIMIT 284
  • 15.
    T o rna n d o ct -S ua A p lic a ç ã ? S e g u r a Presuma que Estão Todos Querendo Te Pegar Seus pais estavam certos: não fale com estranhos, ou peio menos não confie neles. Na pior das situações, não dê a eies as chaves para acessar os dados da sua aplicação, presumindo que não vão fazer nada de errado. Vivemos num mundo cruel, e você não pode partir do princípio que todos são confiáveis. Na verdade, como desenvolvedor de aplicações web você precisa ser metade incrédulo e metade adepto de teorias de conspiração. Sim, as pessoas em geral são más e elas definitivamente querem te pegar! OK, talvez isso seja um pouco de exagero, mas é muito importante levar a segurança a sério e elaborar as suas aplicações de forma que elas fiquem protegidas contra qualquer um que pretenda causar danos. conteúdo (sumário) O dia em que a música m orreu 296 Para onde foram as pontuações? 297 Segurança contra os bárbaros 299 Protegendo a página Guitar Wars Admin 300 i A autenticação HTTP exige cabeçalhos 302 ij Tudo Sobre o Cabeçalho 304 Controle os cabeçalhos com PHP 305 Autenticando com cabeçalhos 306 Crie um script Autorizar 314 Guitar Wars Episódio II: Ataque dos Clones de Pontuação 318 Subtração por adição 319 A segurança requer intervenção hum ana 320 Planeje moderação no Guitar Wars 321 Abra espaço para aprovações com ALTER 322 Pontuações não-aprovadas não são dignas 327 O hack de um milhão de pontos 330 Tudo em moderação...? 331 Como exatamente ela fez isso? 333 Enganando o MySQL com comentários 334 O formulário Add Score recebeu um a injeção de SQL 335 Proteja seus dados contra injeções de SQL 336 Um INSERT mais seguro (com parâmetros) 337 A validação de formulários nunca é inteligente demais 339 Cessar fogo! 341 XV
  • 16.
    C d ^n d p A p l i ^ ç ê ^ s W e b p e rS 9 n cú i^ld ctó 7 Lembra de Mim? Ninguém gosta de ser esquecido, especialmente usuários de aplicações Web. Se a aplicação tiver que trabalhar a noção de “comunidade”, ou seja, se for planejado que os usuários interajam com a aplicação de uma forma pessoal, então ela terá de se lembrar dos usuários. Você detestaria ter que se apresentar novamente à sua família a cada vez que entrasse em casa. Não precisa fazê-lo porque seus parentes possuem uma coisa maravilhosa chamada memória. Mas aplicações web não se lembram das pessoas automaticamente - é preciso que um desenvolvedor web esperto use as ferramentas disponíveis (PHP e MySQL, talvez?) para criar aplicações web personalizadas que realmente sejam capazes de se lembrar dos usuários. conteúdo (sumário) Tov*w pis», m nsedtolog Into ar« Místfiatch*o* w»w nrte-match^er : Y o t r p u i w e r d V t ftb t s e n t J f t . t h s d e a r ' • •■ < . :ijntftlÈ* ,Passtw rdiJ*«*««•M „AemftfTíbjythís passwwd in mykeythain ~êwesO Lastiume: Gendfr: frwfciMismatch*ViewProfíte Bm U iue:; City: >0^» Ushtímws jnesâes State: Ígü FÈPStnwne:Joijao Ffctnxe N ísiks Gfflda1 ; Mate BSrtbâate 1981-H-Q3 L o c a t í n u A t h e c s , G À Wouklyouliketo Dizem que os opostos se atraem O negócio do Mismatch são os dados pessoais O Mismatch precisa dos logins dos usuários Preparando o banco de dados para os logins | Construindo uma interface de usuário para o login Criptografe as senhas com SHA() Comparando senhas Autorizando usuários com HTTP Fazendo login dos usuários com autenticação HTTP Um formulário para novos usuários se cadastrarem Do que é feito o cookie? Use cookies com PHP Repensando o fluxo dos logins Um login baseado em cookies Fazer logout significa apagar cookies As sessões não dependem do cliente Mantendo-se atualizado com os dados das sessões Renove o Mismatch com as sessões Faça Logout com sessões Complete a sessão de transformações Os usuários não estão se sentindo bem-vindos As sessões tem vida curta... ...mas os cookies podem durar para sempre! Sessões + Cookies = Persistência de login superior 346 347 348 351 353 354 355 358 361 365 375 376 379 380 385 389 391 392 393 398 404 406 407 409
  • 17.
    conteúdo (sumário) Elimine CôdigpDuplicado Compartilhar é Cuidar Guarda-chuvas não são a única coisa que pode ser Compartilhada. Em qualquer aplicação web, você poderá encontrar situações em que um mesmo código encontra-se duplicado em mais de um lugar. Isso não só é um desperdício de recursos, como também pode levar a problemas de manutenção, uma vez que você inevitavelmente acabará fazendo modificações e estas terão de ser efetuadas em mais de um lugar. A solução é eliminar o código duplicado, compartilhando-o. Em outras palavras, você mantém o código duplicado em apenas um lugar, e depois, apenas referencia esse código sempre que precisar dele. A eliminação de código duplicado resulta em aplicativos mais eficientes, de manutenção mais fácil, e finalmente, mais robustos.. O Mismatch está em pedaços 421 Reconstruindo o Mismatch a partir de um template 422 Reconstrua o Mismatch com templates 424 O Mismatch está novamente em pé... e muito m elhor organizado 426 0 dâbefiâlho aparece «o ali» de cada pagina do Mismatch, e exibe © titulo da aplidaçSojuntamente tom un> trtulo específico pagina.. w» título espet$to Cada pagina do Mismatch <^ue■ forpevsowàtaadapavào usuário exigira um todig© de login, o <ual mantém registro do usuário- 0 vodape -fomeCe Conteúdo «a parte de baixo de todas as paginas do AWatch, « ^wâí inclui um aviso de í.opyv-:*Ll XVII
  • 18.
    conteúdo (sumário) C^nttole Seusüa<fcs, Seu Mundç> Colhendo Dados Nada como uma boa colheita de dados no outono, um sem-fim de informações prontas para serem examinadas, classificadas, comparadas, combinadas, enfim, qualquer coisa que a sua excelente aplicação web precisar que seja feito. Compensador? Sim. Mas assim como as colheitas na vida real, é preciso muito trabalho duro e uma boa dose de conhecimento para se obter controle sobre os dados em um banco MySQL. Os usuários da web exigem mais do que dados estáticos e enfadonhos. Eles querem dados enriquecedores... dados compensadores... dados relevantes. Então, o que você está esperando? Dê a partida no seu trator MySQL e mãos à obra! Fazendo o desencontro perfeito 428 Os desencontros se referem aos dados 429 Modele o banco de dados com um schema 431 Junte várias tabelas 436 Chaves estrangeiras em ação 437 As tabelas podem combinar linha por linha 438 eT Uma linha leva a muitas outras 439 Checando linhas de muitas-para-muitas 440 Crie um questionário Mismatch 445 Coloque as respostas no banco de dados 446 E possível com andar um formulário com dados 450 Gere o formulário do questionário Mismatch 456 Procure por um pouco de normalidade 462 Ao normalizar, pense em termos de átomos 463 Três passos para se criar um banco de dados normalizado 465 Alterando o banco de dados do Mismatch 469 Então, o Mismatch realmente é normal? 470 Uma consulta dentro de um a consulta dentro de um a consulta... 472 Vamos todos juntar as tabelas 473 Ligue os pontos 474 Certamente podemos fazer mais com os innerjoins 475 Apelidos para tabelas e colunas 477 Joins, ao trabalho! 478 Cinco passos para um desencontro com sucesso 485 Compare usuários pela “desencontrabilidade” 487 Tudo o que precisamos é um loop FOR 488
  • 19.
    conteúdo (sumário) Funçpes Stringe persç>ncillzíulas Vivendo Melhor Através das Funções As funções levam as suas aplicações para um nível superior. Você já vem usando as funções internas do PHP para realizar as coisas. Agora é hora de dar uma olhada em mais algumas funções internas realmente úteis. E depois você aprenderá a criar suas próprias funções personalizadas para levá-lo mais além do que sequer imaginava que fosse possível. Bem, talvez não tão longe que você comece a usar espadas laser, mas as funções personalizadas certamente simplificam o seu código e o tornam reutilizável. Strings e funções personalizadas 501 Um bom trabalho arriscado é difícil de encontrar 502 A busca não deixa margem para erros 504 ; As consultas SQL podem ser flexíveis com LIKE 505 ; Transforme um a string em palavras individuais 510 Implode() cria um a string a partir de substrings 513 Pré-processe a string de busca 519 Substitua caracteres de busca indesejados 520 í A consulta precisa de termos de busca legítimos 524 Copie elementos não-vazios para um novo array 525 As vezes você só precisa de parte de um a string 528 Extraia substrings do início ou do fim 529 Podemos classificar nossos resultados com múltiplas consultas 532 As funções lhe permitem reutilizar código 536 Construa um a consulta com um a função personalizada 537 Funções personalizadas: o quão personalizadas elas realmente são? 538 SWITCH toma muito mais decisões do que IF 542 Dê a build_query() a capacidade de classificar 545 Podemos paginar os nossos resultados 548 O btenha apenas as linhas de que você precisa com LIMIT 549 Controle os links das páginas com LIMIT 550 M antenha registro dos dados da paginação 551 Defina as variáveis da paginação 552 Revise a consulta para ter resultados paginados 553 Gere os links de navegação da página 554 M ontando o script Search completo 557 O script Search completo, continua... 558 xix
  • 20.
    conteúdo (sumário) E xp te s s P e s íle g u lc tfe s Regras Para Substituição As funções string são adoráveis. Mas, ao mesmo tempo, são limitadas. Certamente elas podem realizar tarefas como lhe dizer a extensão da sua string, truncar a string, trocar certos caracteres por outros. Mas às vezes você precisa de liberdade para lidar com manipulações de texto mais complexas. É aqui que as expressões regulares podem ajudar. Elas podem modificar strings de forma precisa, com base em um conjunto de regras, em vez de um só critério. A Riskyjobs permite que os usuários submetam currículos Decida como deverá ser a aparência dos seus dados Formule um padrão para números telefônicos Confira padrões com relação a expressões regulares Crie padrões usando metacaracteres Ajuste os padrões com classes de caracteres Verifique os padrões com preg_match() Padronize os dados dos números de telefone Livre-se dos caracteres indesejados Conferir endereços de email pode ser complicado Sufixos de domínios estão por toda a parte Use PHP para verificar o domínio Validação de email: m ontando o quadro 562 566 569 570 572 579 584 591 592 596 598 599 600
  • 21.
    ViSUcdizctndo seus Dados--.eMaís! Desenhando Gráficos Dinâmicos É claro que todos nós conhecemos o poder de uma boa consulta e os consequentes resultados satisfatórios. Mas os resultados de consultas nem sempre falam por si mesmos. Às vezes é útil apresentar os dados de uma forma diferente, uma forma mais visual. O PHP possibilita o fornecimento de uma representação gráfica dos dados: gráficos pizza, gráficos em barra, diagramas de Venn, desenhos Rorschach, qualquer coisa. Vale de tudo para ajudar os usuários a compreender os dados que fluem através da sua aplicação. Mas nem todos os gráficos úteis, em aplicações PHP, se originam do seu banco de dados. Por exemplo, você sabia que é possível evitar ataques de bots de spam com imagens geradas dinamicamente? conteúdo (sumário) Guitar Wars Reloaded: A Vingança das Máquinas 606 Nenhum formulário de input está a salvo 607 Precisamos separar os humanos das máquinas 608 Podemos vencer a automação usando a automação 611 Gere o texto da senha de CAPTCHA 613 Visualizando a imagem CAPTCHA 614 Por dentro das funções gráficas GD 616 Desenhando texto com um a fonte 620 Gere um a imagem CAPTCHA aleatória 623 A sanidade retorna ao Guitar Wars 625 Adicione CAPTCHA ao script Adicionar Pontuação 627 Cinco graus de oposição 630 Pondo a desencontrabilidade em tabela 631 Armazenando dados do gráfico com barras 632 Lendo entre as linhas com o senhor dos gráficos 635 De um array para outro 636 Crie um array de tópicos desencontrados 638 Formulando um plano para execução de gráficos de barras 639 Amassando as categorias 640 A matemática das categorias 641 Fundamentos dos gráficos de barras 644 Desenhe e mostre a imagem do gráfico de barras 647 Imagens individuais do gráfico de barras para todos 650 Os usuários do Mismatch estão gostando dos gráficos de barras 653 xxi
  • 22.
    ÍfepukliCcLçÍÍ9 e SetViçPSWeb U Interfacescom o Mundo Existe um grande mundo lá fora, mundo esse que a sua aplicação web não pode se dar ao luxo de ignorar ou o que talvez seja mais, você é que não gostaria que o mundo ignorasse a sua aplicação. Uma excelente maneira de fazer o mundo notá-la é tornar os seus dados disponíveis para republicação, o que significa que os usuários poderão assinar o conteúdo do seu site, em vez de ter de visitá-lo diretamente para encontrar novas informações. Não apenas isso, a sua aplicação pode fazer interfaces com outras aplicações, através dos serviços web, e pode tirar proveito dos dados de outras pessoas para fornecer uma experiência mais rica. conteúdo (sumário) Algutts clientes de email tèm suporte a conteúdo “pu sh”»permitindo que você receba atualizações do site da m esm a com o recebe m ensagens de email. Muitos navegadores web também lhe permitem exam inar conteúdo “push" que revela rapidamente a s noticias m ais recentes publicadas em um determinado site. Até m esm o dispositivos m óveis provém a c e sso a conteúdo ‘'push*, o qual é enviado autom aticam ente quando elgo se m odifica no Owen precisa avisarao mundo sobreFang 658 Envie dados sobre abduções alienígenas para aspessoas 659 O RSSenvia conteúdo web para aspessoas 660 ORSSé naverdade XML 651 Dobanco de dados para o news reader 666 Visualizando RSS 669 O que interessaaum comunicador 671 Gere um envio RSSdinamicamente 672 Crieum linkpara o envio RSS 676 Umvídeorale mais que milpalavras 678 Obtendo conteúdo webde terceiros 680 Republicando vídeos doYouTube 681 ;Fazendo uma requisição devídeo noYouTube 682 Owen estapronto para criaruma requisiçãoREST 686 OYouTubefalaXML 690 Deconstruindo uma respostaXMLdoYouTube 694 Visualize os dados de vídeoXML 695 Acesse os dadosXML com objetos 696 De elementos XMLpara objetosPHP 697 Penetre nos dadosXML com objetos 698 Não semum namespace! 699 Cadavez mais avistamentos de Fang 701 Disponibilizevídeos para visualização 702 Formate os dadosde vídeo para exibição 703
  • 23.
    $oL>ras Os Dez PrincipaisTópicos (Que Não Abordamos) Mesmo depois de tudo isso, ainda tem mais um pouco A in d a temos mais algumas coisas que você precisa conhecer. Não seria certo nós as ignorarmos, mesmo que só precisem de uma breve menção. Portanto, antes de guardar o livro, dê uma lida nestes pequenos, mas importantes parágrafos sobre PHP e MySQL. Além disso, uma vez concluído este aqui, só faltarão mais dois pequenos apêndices... e o índice... e talvez algumas propagandas... e aí o livro realmente acaba. Promessa! conteúdo (sumário) #1. Adapte este livro para funções PHP4 e mysql 714 #2. Permissões do usuário no MySQL 716 #3. Relato de erros para o MySQL 718 #4. Erros PHP com tratamento de exceções 719 #5. PHP orientado a objetos 721 #6. Tom ando segura a sua aplicação PHP 723 #7. Proteja sua aplicação de scripts cross-site 725 #8. Precedência de operadores 727 #9. Qual é a diferença entre PHP 5 e PHP 6 728 #10. Reutilizando o PHP de terceiros 730 xxiii
  • 24.
    C^nífgute um AmbientedeDesenVplVimentP 1 1 Um Lugar para Brincar I I Você precisa de um lugar para praticar suas recém- • • adquiridas habilidades em PHP e MySQL, porém sem tornar OSSeUS dados vulneráveis na web. É sempre uma boa ideia ter um local seguro para desenvolver sua aplicação PHP antes de lançá-la no mundo (ou seja, na web). Este apêndice contém instruções para a instalação de um servidor web, do MySQL e do PHP, para lhe fornecer um lugar seguro onde possa trabalhar e praticar. conteúdo (sumário) Servidor Crie um ambiente de desenvolvimento PHP 732 Descubra o que você tem 732 Você tem um servidor web? 733 Você tem o PHP? Qual versão? 733 Você tem o MySQL? Qual versão? 734 Comece pelo Servidor Web 735 Passos para a instalação do PHP 737 Instalando o MySQL 738 Passos para a instalação do MySQL no Windows 739 Habilitando o PHP no Mac OS X 742 Passos para a instalação do MySQL no Mac OS X 742 Passando do ambiente de produção para um site no ar 744 Dump seus dados (e as suas tabelas) 745 Prepare-se para usar seus dados 745 Mova os dados consolidados para o servidor ativo 746 Conecte-se ao servidor ativo 747
  • 25.
    conteúdo (sumário) 9Ê9 III Araplí lie Seu ObtenhaAinda Mais Proveito Sim, você pode programar com PHP e MySQL e criar Ótimas aplicações Web. Mas você sabe que ainda deve haver mais a se explorar. E há. Este pequeno apêndice irá lhe mostrar como instalar a extensão mysqli e a extensão biblioteca gráfica GD. Em seguida, mencionaremos mais algumas extensões do PHP que você poderá querer baixar. Porque às vezes não tem problema em querer sempre mais. Estendendo o seu PHP 750 E no Mac.. 753 XXV
  • 27.
    Como UsorEsteLíVrc> Introdução Nesta seção,respondemos à ‘ »»iporfcâ^ie per^wvfca-- u& ivfcdo> por < ^ w eíoi <^ue eles doSoÊdV ’âm isso e» um livro de PtfP e My£$U” xxvii
  • 28.
    como usar estefivro A quem se destina este livro? Se você puder responder “sim” a todas estas perguntas: Você é um web designer com experiência em HTML ou XHTML, e deseja melhorar as suas páginas? Você deseja ir além do simples HTML e aprender, entender e se lembrar como usar PHP e MySQL para criar aplicações web? Você prefere conversas informais e estimulantes, em vez de aulas enfadonhas e acadêmicas? então este livro é para você. Quem provavelmente deve fugir deste livro? Se você puder responder “sim” a qualquer uma destas perguntas: Você não tem conhecimento nenhum sobre conceitos básicos de programação, tais como variáveis e loops? (Mas mesmo que jamais tenha programado antes, você provavelmente será capaz de absorver os conceitos-chaves de que precisa, neste livro.) Você é um super desenvolvedor web PHP procurando por um livro de referência? Você tem medo de tentar algo diferente? Você prefere arrancar um dente do que misturar listras com xadrez? Você acha que um livro técnico não pode ser sério se um dos exemplos é um banco de dados sobre abduções alienígenas? então este livro não é para você. Nota Ao d.fjHa.e.fc d o d t f l d í „ â r k e t i de frredi-fxj.
  • 29.
    introdução Sabemos o quevocêestá pensando “Como isso aqui pode ser um livro de PHP e MySQL sério?” “Por que tantas figuras?” “E realmente possível aprender desta forma?” Sabemos o que o seu cérebro está pensando Seu cérebro pede novidade. Ele está sempre buscando, vasculhando, esperando por algo fora do comum. Ele foi construído dessa forma, e isso lhe ajuda a se m anter vivo.. Assim, o que o seu cérebro faz com todas as coisas rotineiras, comuns, normais, que você encontra? Faz todo o possível para evitar que elas interfiram no trabalho real do cérebro - registrar coisas que sejam importantes. Ele não se dá ao trabalho de armazenar as coisas chatas; elas nunca conseguem passar pelo filtro “isto aqui obviamente não é importante”. Como o seu cérebro sabe o que é ou não é importante? Suponha que você esteja fazendo um a caminhada na selva e um tigre pule na sua frente; o que acontece com a sua mente e o seu corpo? Os neurônios se acendem. As emoções fluem. A química dispara. E é assim que o seu cérebro sabe que... Isto deve ser importante! Não se esqueça! Mas imagine que você esteja em casa ou em um a biblioteca. É uma área segura, aconchegante, livre de tigres. Você está estudando. Se preparando para uma prova. Ou tentando aprender algum difícil assunto técnico que o seu chefe acha que só vai levar um a semana, dez dias no máximo. Só um problema. Seu cérebro está tentando lhe fazer um grande favor. Ele está tentando se certificar de que este conteúdo obviamente desimportante não ocupe recursos que são escassos. Recursos esses que são mais bem empregados armazenando-se as coisas realmente importantes. Como tigres. Como o perigo do fogo. Como esconder rapidamente ajanela do navegador com o vídeo de discos voadores no You Tube, antes que o seu ^ ÚrcU-c Isto ; ,mF'»rtâKit' chefe apareça. E não há um a forma simples de dizer ao seu cérebro “ei, cérebro, muito obrigado, mas não im porta o quanto este livro seja chato, e quão poucas emoções eu esteja sentindo neste exato momento, eu realmente quero que você se lembre destes assuntos.” Videos de ÍH/Ms no You Tube sa©obvia»wewte »«ais mievessa>vfces para o seu ievebv-o do ^ue um liw-o de TJ. xxix
  • 30.
    como usar estelivro tíntendeni9s c jue o JeítPr c[e um JiVtP cfa sène ^Jse a C^eça! Então, o que é preciso para se aprender algo? Primeiramente, você precisa entender o assunto, e depois se certificar de que não vai esquecê-lo. Não adianta tentar entulhar fatos dentro da sua cabeça. Com base nas pesquisas mais recentes em ciência cognitiva, neurobiologia e psicologia da educação, é necessário muito mais do que texto em uma página para um verdadeiro aprendizado. Nós sabemos como chamar a atenção do seu cérebro Alguns dos princípios de aprendizado Use a Cabeçal: Use o recurso visual. Imagens são muito mais memoráveis do que palavras sozinhas, e tomam o aprendizado muito mais eficiente (até 89% de melhoria em estudos sobre lembrança e transferência). Eias também tornam as coisas mais compreensíveis. Coloque as palavras dentro ou perto das imagens às quais elas se referem, em vez de na parte de baixo da página ou na página seguinte, e os estudantes terão duas vezes mais probabilidade de conseguir resolver problemas relacionados ao conteúdo. U se um estilo coiw ersacional e personalizado. Em estudos recentes, os estudantes tiveram um desempenho até 40% melhor, em testes pós-aprendizado, quando o conteúdo falava diretamente ao leitor, usando um estilo conversacional, em primeira pessoa, do que quando se usava um tom mais formal, Conte histórias, em vez de lecionar. Use 1 casual. Não se leve muito a sério. Hm que você prestaria mais c estimulante conversa informal ou uma aula? Faça o estudante pensar um pouco m ais profun Em outras palavras, a não ser que você ativamente exercite os neurônios, não vai acontecer muita coisa dentro da sua cabeç precisa estar motivado, engajado, curioso e inspirado para res problemas, chegar aconclusões e gerar conhecimento novo. f isso, você precisa de desafios, exercícios e perguntas que prov o raciocínio, bem como de atividades que envolvam ambos os hemisférios do cérebro e vários sentidos. Obtenha - e mantenha - a atenção do leitor. Tod< passamos por uma situação de "eu realmente quero aprender não consigo passar da página um acordado". O seu cérebro pr em coisas que sejam fora do comum, interessantes, estranhas, assunto técnico novo e difícil não precisa ser enfadonho. O se mais rapidamente se não for. Provoque as emoções. Nós sabemos que a sua capacid algo depende largamente do conteúdo emocional. Você se lei que se importa. Você se lembra de algo quando sente algo. N < de histórias de partir o coração sobre um garoto e seu cachori emoções como surpresa, curiosidade, diversão, "que ... é essa? fera!” que vem quando você resolve um quebra-cabeças, apre acha que é difícil ou percebe que você sabe algo que o Bob "e do departamento de engenharia, não sabe. U**a pequena domdào- Na verdade, nés íe**os Kistória de pariir o doraça© sobre um $ârci# e seu ÁSâherro - o dadhorro -Ç oi abduzido por alienígenas, e vode ajudará © * 3»kí/flB-f-Srá— ioJ.
  • 31.
    introdução Metacognipão: pensando sobrepensar Sevocê realmente quer aprender com mais rapidez e mais profu preste atenção ao modo como prestamos atenção. Pense sobre c pensa. Aprenda sobre como você aprende. raramente nos ensinaram a aprender. Masnós partimos do princípio de que, sevocê está com este livro é porque realmente quer aprender a criar sitesbaseados em bane dados, usando PHP e MySQL. Eprovavelmente não quer despenc tempo. Pará poder usar o que você irá ler neste livro, terá de se lei do que leu. E para isso,você precisa entender o assunto. Para tirai proveito possível deste livro ou de qualquerlivro ou experiência d assuma a responsabilidade sobre o seu cérebro. Focalize o seu cérebro neste conteúdo. O segredo é fazer o seu cérebro ver o novo material que você está aprendendo como sendo Realmente Importante. Crucial para o seu bem-estar. Tão importante quanto um tigre. Caso contrario, você se verá numa batalha constante, com o seu cérebro fazendo o possível para que o novo conteúdo não seja gravado.. Então, como é que você faz com que o seu cérebro trate o “PHP e MySQL” como se ele fosse um tigre faminto? Existe a forma lenta e tediosa, e existe a forma mais rápida e mais eficiente. Aforma lenta é pura repetição. Você obviamente sabe é possível aprender e se lembrar até dos assuntos mais chatos, se continuar empurrando repetidamente a mesma coisa para o seu cérebro. Com suficiente repetição, seu cérebro diz “ele não sent isto é realmente importante, mas continua olhando as mesmas c repetidas e repetidas vezes, então suponho que deve ser importa Aforma maisrápida éfazerqualquercoisaque aumente aatividade cerebral, ede preferência, diferentes tipos de atividade cerebral.As listadasna páginaanterior sãoumagrande parte dasolução, e sãoo que comprovadamente ajudam o seucérebro a trabalharem seufav exemplo, alguns estudosmostram que colocarpalavras dentro dasfí que elasdescrevem (emvezde colocá-lasem algum outro lugarna f como, porexemplo, em umalegenda ou no corpo do texto) obriga cérebro atentarentender arelação entre aspalavrase afigura, e ist< maisneurônios seativarem. Quando mais neurônios se ativam,há n chancesde oseucérebro entender que istoé algo aque'rale apena atenção, epossivelmenteregistrar. Um estilo conversacional ajuda porque as pessoas tendem a pres mais atenção quando percebem que estão envolvidas em uma cc uma vez que, nessa situação, espera-se que elas acompanhem o < está sendo dito para saber quando e como responder. O mais fai é que o seu cérebro não necessariamente liga se a “conversa”é e você e um livro! Por outro lado, se a escrita tiver um estilo form; seu cérebro o perceberá da mesma forma como a experiência d uma lição sentado em uma sala de aula cheia de estudantes pass Não é preciso ficar acordado. Mas as figuras e o estilo conversacional são apenas o início... Amaioria das pessoas não faz aulas de metacognição ou de teori aprendizado na escola. Sempre se esperou que nós aprendêsseir XXXI
  • 32.
    como usar estef/vro Um Desencontro! Ítilnoí ã • r n t i V ' A Ta PiUç de -tenror Aqui esta o que NOS fizemos: Nós usamos figuras, porque o seu cérebro está ajustado para prestar atenção em sinaisvisuais, e não em texto. Pelo menos no que concerne ao seu cérebro, uma imagem realmente vale por mil palavras. E quando texto e imagens precisam trabalharjuntos, nós colocamos o texto dentro das figuras, porque o seu cérebro funciona de forma mais eficiente quando o texto se encontra dentro da coisa a que ele se refere, em vez de em uma legenda ou escondido em algum lugar dentro do texto. Nós usamos redundância, dizendo a mesma coisa de formas diferentes e com diferentes tipos de mídia, e visando a múltiplos sentidos, para aumentar a chance de o conteúdo ser registrado em mais de uma área do seu cérebro. Nós usamos conceitos e figuras de formas inesperadas, porque o seu cérebro está ajustado para prestar atenção em novidades, e usamos figuras e ideias com pelo menos algum conteúdo emocional, porque o cérebro está ajustado para prestar atenção à bioquímica das emoções. Aquilo que nos faz sentir algo é mais provável de serlembrado, mesmo que esse sentimento não seja nada mais que um pouco de humor, surpresa ou interesse. Nós usamos um estilo personalizado, conversacional, porque o seu cérebro está ajustado para prestar mais atenção quando ele acredita que você está envolvido em uma conversação do que quando pensa que está passivamente ouvindo uma apresentação- Seu cérebro faz isso mesmo quando você está lendo. Nós incluímos mais de 80 atividades, porque o seu cérebro está ajustado para aprender e se lembrar mais quando você faz algo do que quando lê sobre algo. Efizemos os exercícios desafiadores, porém resolvíveis, porque isso é o que a maioria das pessoas prefere. Nósusamosváriosestilos de aprendizado, porque você poderá preferir procedimentos passo-a-passo, enquanto que outras pessoaspoderão querer entender o quadro geral primeiro, e outras ainda sóquerem verum exemplo. Masindepen dentemente do seu método preferido de aprendizado, todo mundo sebeneficia emver omesmo conteúdo representado de diversasfornias. Nós incluímos conteúdo para ambos os hemisférios do seu cérebro, porque quanto mais partes do seu cérebro você utiliza, maior a probabilidade de você aprender e se lembrar, e maior o tempo durante o qual conseguirá se manter focado. Uma vez que trabalhar um lado do cérebro frequentemente significa que o outro lado terá um M w L J U Ê L Ê / x Z tempo para descansar, você poderá ser mais produtivo nos estudos, por um período de tempo maior. Nós incluímos estórias e exercícios que apresentam mais de um ponto de vista, porque o seu cérebro está ajustado para aprender com mais profundidade quando é forçado a fazer avaliações ejulgamentos. Nós incluímos desafios, com exercícios e fazendo perguntas que nem sempre tem uma resposta direta, porque o seu cérebro está ajustado para aprender e se lembrar quando precisa trabalhar em algo. Pense no seguinte: não é possívelfazer seu corpo ficar em forma apenas olhando as pessoas malhando na academia. Mas nós fizemos nosso melhor para garantir que, quando estiver trabalhando duro, será sempre nas coisas certas, para que não tenha que gastar um neurônio sequer a mais do que o necessário processando um exemplo difícil de entender ou tentando decifrar um texto difícil, cheio de termos técnicos obscuros ou sisudo demais. Nós usamos pessoas. Nas estórias, exemplos, figuras, etc., porque, bem, porque você é uma pessoa. E o seu cérebro presta mais atenção nas pessoas do que nas coisas. lente isto' NAO CCNFÏE ;$B3p3 scaaSséi?
  • 33.
    introdução Veja o quefazer para que o seu cérebro se curve em sinal de submissão Ok, fizemos a nossa parte. O resto é com você. Estas dicas funcionam como um ponto de partida; ouça o seu cérebro e descubra o que funciona e o que não funciona para você. Experimente coisas diferentes. fcíeH* jsta pájina c cole na porta da sua geladeira. Vá devagar. Quanto mais você entende, menos você tem que memorizar. Não leia, simplesmente. Pare e pense. Quando o livro lhe apresentar uma pergunta, não pule direto para a resposta. Imagine que uma pessoa real está lhe fazendo a pergunta. Quanto mais aprofundadamente você forçar o seu cérebro a pensar, maior a sua chance de realmente aprender e se lembrar do que aprendeu. Faça os exercícios. Faça suas próprias | anotações. Nós elaboramos os exercícios, mas se os fizéssemos para você, isso seria como ir à academia e ter alguém para m alhar por você. E não basta só olhar os exercícios. Use um lápis. Há muita evidência de que a atividade física durante o processo de aprendizado pode m elhorar este último. Leia as seções “Não Existem i Perguntas Idiotas”. Todas elas. Elas não são com entários opcionais fazem parte do conteúdo central! Não as deixe de lado. Que isso seja a última coisa que você lê antes de dormir. Ou pelo menos a última coisa desafiante Parte do aprendizado (especialm ente a transferência para a m em ória de longo prazo) ocorre depois que você fecha o livro. Seu cérebro precisa de algum tem po para realizar todo o processam ento. Se você tentar absorver novas inform ações durante esse tem po, um a parte do que você acabou de apren d er será perdida. i Beba água. Em grande quantidade. Seu cérebro funciona m elhor quando envolvido em um bom banho. A desidratação (que pode acontecer antes mesmo de você sentir sede) prejudica as funções cognitivas. 0 PHP o MySQL. ÍKe £er«*>'rte»* éríar ^ vjebreais —naosc es^ueta y de envia-las e C*perimer>tí-!as em um servidor y»eb vevdadeiro.. Converse sobre o que está lendo. Em voz alta Falar ativa uma parte diferente do cérebro. Se você quer entender algo ou aumentar as suas chances de se lembrar do assunto depois, pronuncie-o em voz alta. Melhor ainda, tente explicá-lo, em voz alta, a outra pessoa. Você aprenderá mais rapidamente e poderá descobrir ideias que não tinha percebido ainda durante a leitura, lOuça o seu cérebro. Preste atenção para saber se o seu cérebro está ficando sobrecarregado. Se você perceber que está começando a ler superficialmente ou esquecer o que acabou de ler, é hora de fazer um a pausa. Uma vez que você passa de certo ponto, não é possível aprender mais rápido tentando absorver mais e mais conteúdo e poderá até prejudicar o processo. ^Sinta algo. Seu cérebro precisa saber que isto é importante. Envolva-se com as estórias. Crie as suas próprias legendas para as fotos. Resmungar sobre um a piada ruim ainda é m elhor do que não sentir nada. Escreva bastante código. Só existe um a forma de aprender a programar: escrevendo um monte de código. E é isso que você irá fazer ao longo deste livro. Programar é uma habilidade, e a única forma de se ficar bom nela é praticando. Nós iremos lhe oferecer muitas oportunidades de praticar: cada capítulo terá exercícios que apresentam problemas para você resolver. Não deixe de fazê-los - uma boa parte do aprendizado acontece quando você resolve os exercícios. Nós incluímos soluções - não tenha medo de dar uma olhada na solução caso não consiga resolver algum exercício! (é comum um pequeno detalhe atrapalhar toda a resolução) Mas tente resolver o problema antes de olhar as soluções. E, definitivamente, faça o exercício funcionar antes de passar para a parte seguinte do livro. XXXIII
  • 34.
    como usar estelivro Leia-me Isto é uma experiência de aprendizado, e não um livro de referência. Nós deliberadamente retiramos tudo que pudesse atrapalhar o aprendizado de qualquer que seja o assunto tratado em um determinado ponto do livro. E na primeira leitura, você precisa começar pelo começo, porque cada capítulo assume que você aprendeu o que viu no anterior. Nós começamos ensinando alguns conceitos simples de programação e fundamentos de conexão a banco de dados, em seguida apresentamos funções PHP e instruções MySQL mais complexas, e finalmente mostramos alguns conceitos mais complexos sobre aplicações. Embora seja importante permitir aos usuários adicionar dados e a retirar dados de uma aplicação web, antes disso, é preciso primeiramente, entender a sintaxe tanto do PHP quanto do MySQL. Assim, nós começamos apresentando instruções PHP e MySQL que você pode experimentar na prática. Assim, você poderá imediatamente fazer algo com PHP e MySQL, e começará a se sentir estimulado em usar essas tecnologias. Depois, mais adiante no livro, lhe mostraremos as boas práticas de projeto de aplicações e de bancos de dados. Nesse ponto,já terã um sólido domínio da sintaxe de que vai precisar e poderá se concentrar em aprender os conceitos. Nós não abordaremos todas as instruções, funções ou palavras-chaves do PHP ou MySQL Teria sido possível colocar cada instrução, função e palavra-chave do PHP e do MySQL neste livro, mas nós achamos que iria preferir um livro que não fosse do tamanho de um catálogo telefônico, e lhe ensinasse as instruções, funções e palavras-chaves mais importantes. Apresentaremos aquelas que você precisa conhecer, e que usará em 95% do tempo. E após terminar este livro, terá a confiança para procurar sozinho informações sobre aquela função de que precisa para terminar a aplicação que acabou de escrever. ^ ^ ^ ^ A Nós estamos abordando o PHP 5 e o MySQL 5.0. Devido ao fato de muita gente ainda usar o PHP 4 ou 5, nós evitamos usar códigos específicos para o PHP 4, 5ou 6 sempre que possível. Sugerimos que você use o PHP 5ou 6 e o MySQL 5 ou 6 ao estudar os conceitos deste livro. No desenvolvimento deste livro, nos concentramos no PHP 5 e no MySQL 5, ao mesmo tempo nos certificando de que o código fosse compatível com versões posteriores. Você precisa de um servidor web com suporte a PHP. O PHP precisa ser executado através de um servidorweb para funcionar corretamente. Você precisa do Apache ou de algum outro servidorweb instalado na sua máquina local, ou em alguma máquina à qual você tenha algum acesso, para que possa executar comandos MySQL sobre os dados. Consulte osApêndices ii e iii para instruções sobre como instalar e estender o PHP e o MySQL. Na verdade, voòe pode wsâv o tovn este SW voj -Çâz/ndo al$u»as modiíitadoes ao todifto. Consulte o
  • 35.
    introdução Nós usamos oMySQL. Embora exista uma linguagem SQL Padrão, neste livro nós usaremos a sintaxe particular do MySQL. Com apenas algumas poucas modificações na sintaxe, o código deste livro deverá funcionar no Oracle, MS SQL Server, PostgreSQL, DB2 e em mais alguns outros Sistemas de Gerenciamento de Bancos de Dados Relacionais (Relational Database Management Systems ou RDBMSs) existentes. Você terá de pesquisar asfunções e a sintaxe particulares do PHP, para se conectar a esses outros RDBMSs. Se fôssemos abordar todas asvariações de sintaxe para cada comando, este livro teria muito mais páginas do que tem. Nós gostamos das árvores, por isso nos limitamos ao MySQL. As atividades NÃO são opcionais. Os exercícios e atividades não são opcionais; fazem parte do conteúdo central do livro. Alguns deles servem para ajudar a memorização, outros para o entendimento e alguns irão lhe ajudar a pôr em prática o que acabou de aprender. Não deixe de fazê-los. As palavras cruzadas são a única coisa que não precisa fazer, mas são boas para dar ao seu cérebro uma chance de pensar de uma forma diferente nas palavras e termos que você está aprendendo. A redundância é intencional e importante. Uma diferença importante de ura livro Use a Cabeça! é que nós queremos que você realmente entenda o assunto, E queremos que termine este livro lembrando-se do que aprendeu. Amaioria dos livros de referência não tem a retenção e a recuperação como alvo, mas este é um livro de aprendizado, e portanto, verá alguns conceitos aparecendo mais de uma vez. Os exemplos são os mais simplificados possíveis. Nossos leitores nos dizem que é frustrante ter que navegar por 200 linhas de um exemplo, procurando pelas únicas duas linhas que eles precisam entender. Amaioria dos exemplos deste livro é mostrada dentro do menor contexto possível, para que a parte que você está tentando aprender fique clara e simples. Não espere que todos os exemplos sejam super robustos ou sempre completos - eles foram escritos especificamente para o propósito didático, e não são necessariamente 100%funcionais. Nós colocamos todos os códigos de exemplo e aplicações na Web, para que você possa copiar e colar partes deles no seu editor de texto ou Terminal MySQL ou então enviá-los como estão para o seu próprio servidorweb, para realizar testes. Você os encontrará em h t t p : / / w w w .altab o o k s. co m .b r Os endereços de websites de terceiros podem ser alterados ou desatualizados a qualquer momento pelos seus mantedores, sendo assim, aAlta Books não controla ou se responsabiliza por qualquer conteúdo de websites. Vários cios exemplos, pov-e*», são aplidadoes w«b £o*p|eiasf dapa«s de +azer Coisas bew » poderosas.. Os exercícios Poder do Cérebro não tem respostas. Para alguns deles, não existe uma única resposta; para outros, parte da experiência didática das atividades Poder do Cérebro é você decidir se e em que contexto as suas respostas estão corretas. Em alguns dos exercícios Poder do Cérebro, você encontrará dicas para lhe guiar na direção correta. XXXV
  • 36.
    equipe de revisão Revisãotécnica v W e AH» 1>âvid Bri99s Will Hav*-is Stephanie Liese Steve /VJilano Revisores Técnicos: JeremeAllené um desenvolvedor web sênior com experiência no uso das tecnologias mais avançadas para a criação de aplicações web. Ele tem mais de nove anos de experiência no uso de PHP, MySQL, bem como vários outros frameworks, sistemas operacionais, linguagens de programação e software de desenvolvimento. DavidBriggs é um autor de livros técnicos e engenheiro de localização de software que vive em Birmingham, Inglaterra. Q uando não está sendo detalhista sobre como guiar os usuários através de algum software particularm ente difícil, não tem nada que ele goste mais do que ir ao parque local com sua esposa, Paulette e Cleo, o cachorro da família. WillHarris é o responsável por um departam ento de TI que fornece serviços para 11 empresas em 4 continentes, e é o Vice-Presidente da filial em Las Vegas do PASS (Professional Association for SQL Server). A noite, ele entra num a cabine telefônica, coloca o seu uniform e web 2.0, e sai por aí ajudando os designers e desenvolvedores do Powered By Geek a garantir que as suas plataformas de dados permaneçam flexíveis, portáteis, de fácil manutenção e RÁPIDAS, usando MySQL e Rails. Ele também gosta de passar seu tempo com sua esposa, Heather, suas lindas filhas Mara e EUie, e seu cachorro Swiper Stephanieliese é um a instrutora técnica e desenvolvedora web em Sacramento, Califórnia. Quando ela não está pregando as virtudes do código que obedece aos padrões ou removendo bugs de algum layout CSS, você a encontrará suando em um a pesada aula de yoga. Hâv-vey ChHs Shi-Ple-tt Quando SteveMilano não está escrevendo código para o The DayJob™ ou tocando punk rock com sua banda, a Onion Flavored Rings, em algum porão mal ventilado, ele provavelmente está em casa com seu laptop, negligenciando a companhia felina de Ralph ou a companhia humana de Bianca. Harvey Quameii desistiu de um a carreira em programação de computadores para se juntar ao chique e glamouroso mundo universitário. Atualmente, é Professor Associado de Inglês e Humanities Computing na Universidade de Alberta, onde dá aulas sobre cybercultura, literatura do século XX e desenvolvimento web - incluindo PHP e MySQL. ChrisShifletté o Chefe de Tecnologia da OmniTI, onde lidera a prática de segurança de aplicações web e guia a iniciativa de desenvolvimento web. Chris é um reconhecido líder nas comunidades de segurança do PHP e de aplicações web - um blogueiro bastante lido em shiflett.org, um popular palestrante em conferências no mundo todo, e o fundador do PHP Security Consortium. Seus livros incluem Essential PHP Security (O’Reilly) e HTTP Developer’s Handbook (Sams).
  • 37.
    introdução Agradecimentos Nossos editores: Muito obrigadoa Brett McLaughlin pela incrível sessão de storyboarding que nos colocou no caminho certo, e pelo seu compromisso inquebrantável com o aprendizado cognitivo. Este livro não existiria se não fosse pelo esforço, paciência e persistência heróicos de Sanders Kleinfeld. Ele sempre conseguia apanhar os pinos com os quais estávamos fazendo malabarismo, toda vez que inevitavelmente deixávamos cair um (ou três!), e somos gratos por isso. Esperamos que ele tenha a chance de descansar por alguns dias antes de encarar um outro projeto tão difícil quanto este. A equipe O’Reilly: Obrigado a Lou Barr pelas suas fenomenais habilidades em design, que fizeram este livro ter uma aparência tão boa. Obrigado também a Brittany Smith por todo o seu trabalho em cima da hora e a Caitrin McCollough por colocar no ar os sites de exemplo. E a Laurie Petrycki por acreditar que nós poderíamos escrever mais um ótimo livro da série Use a Cabeça! Sanders tíeiníeid E também: Finalmente, muitíssimo obrigado a ElvisWilson por elaborar os vídeos de alienígenas no You Tube p ara o C apítulo 12. Ó tim o trabalho! E specialm ente considerando que ele é um simples diretor de arte do tempo das cavernas. xxxvii
  • 39.
    1 Adicionando Vidaàs Suas PáginasEstáticas * + Está Vivo Você tem criado ótimas páginas web com HTML, com recursos de CSS mas tem percebido que os visitantes do seu site não podem fazer muita coisa além de olhar passivamente o conteúdo das páginas. A comunicação apresenta-se de forma unidirecional e você gostaria de mudar isso. Na verdade, o que você realmente gostaria é de saber o que o se u p ú b lico está pen san d o . Mas para isso precisa permitir que os usuários digitem informações em um formulário web, para que possa saber o que eles têm em mente. E seu site precisa ser capaz de processar essas informações, para que elas lhe sejam entregues. Está começando a parecer que você irá precisar de mais do que HTML para levar seu site para o próximo nível. este é um novo capítulo ► 1
  • 40.
    as vezes somenteHTML não é suficiente HTML é estático echato O HTML é ótimo para se criar páginas web, até aí vocêjá sabe. Mas, e quando você precisa que as páginas realizem alguma ação? Suponha que seja necessário fazer uma busca em um banco de dados ou enviar um email... como fazer? O HTML deixa a desejar, porque é uma linguagem sem vida, elaborada para exibir informações que nunca se modificam. 0 HTML- c óWo ^«and© a ‘m-temçao e apenâ* mas towparblHar w»a do seu VidH o de estimâ^o-- »ao tawfco guando desejô ir>'tera^iv' to» cs visitantes do seu site- © Estas pessoas esta© em busda interação. O servidorweb representa uma grande parte do problema com o HTML estático, umavez que ele funciona como nada mais que um mecanismo de entrega sem graça. O navegador requisitauma página, o servidor responde com HTML, fim da história. Para transformar sitesem aplicaçõesweb interativas, o servidor precisa assumir um papel novo, mais dinâmico... um papel possibilitado pelo PHP. C»m páginas HTML pureis, 9 seiVidor sim p le sm e n te setV e HTML estático, <jue SP e de eXibít coijtôúdp.
  • 41.
    Co» uma pequena ajudado servido»-/ adicionando vida às suas páginas estáticas o — '»ctvioor' PttPdá vida às páginas web O PHP lhe permite manipular o conteúdo das páginas web no servidor, imediatamente antes de a página ser enviada ao navegador cliente. Funciona da seguinte maneira: um script PHP é executado no servidor, e pode alterar ou gerar código HTML à vontade. Uma página HTML então é entregue ao navegador, que não sabe e nem liga se há PHP envolvido na produção ou zyuste do HTML, no lado do servidor. - j 0 dodifto HTML destas *T 'rtoTM i P0'" PHP, e pode se ^ ’lr'âs — nriodiíiÊar dinawitameníe, no^ma»S|»as f defendendo do que a «ri*. fo, jarado v - dinamita^ente 1 aivavés de PHP, no servidcv Com ?H? na parada, 9 seíVxdot Web e cap eis d e £ e ra r páginas HTML de fotma dinâmica,em tempp real. PttP Sdo ain»ia2íhados «o ^ — wvidor web, o^de r 530 P^essados e depois os resultados entreves ao ^vegader £o»,o Painas HTML. Servidor web Navegador web cliente Páginas HTML dinâwõtas^^ SCrwodi-fÍÊ3w> e»» 'res^ostâ à iógita frogvamáiida presente nos sdripis PHP, -tornando— os intnveiwente íle*íveis. Banco de dados MySQL N A Os sòrip-b PHP ÒonW tádíp HTML e ftádiy> de sdnpt PHP, oi V *s deterwinaw o modo towo o tód',50 HTML t «.angulado- 0 PHP armazina e retira dados de um banto de dâdos e os incorpora ao úodigo HTML gerado. você esté ago/ ► 3
  • 42.
    Cães no espapo Esteé o O w en. Ele p erd e u seu cachorro, Fang. Mas en c o n trar seu cão não sc restringe a um a sim ples larefa dc p ro c u r a r p e lo bairro. A co n te ce q ue Fang foi abduzido p o r alienígenas, o que ex p an d e a busca de O w en p o r todo o universo. O w en sabe um pouco de HTML. e CSS e acha que um site personalizado p o d eria ajudá-lo a resolver seu p roblem a, ao p erm itir q u e outras pessoas com partilhem suas p róprias experiências de abdução alienígena. Mas, para o b ter inform ações das pessoas, O w en precisará de um fo rm u lário web capaz de receb er in p u t (en trad a de dados) dos usuários e notificá-lo sobre esse input. Sem pro b lem a - o H TM L possui várias tags para a criação de form ulários web. Os de-balv»es sao »as o sâWos t »yt avrebatado ««* < M a° 50 tcu _ Y&r umV3'© lwz»
  • 43.
    adicionando vida àssuas páginas estáticas Um formulário ajuda Owen a descobrir toda a história O novo site de Owen, AliensMeAbducteme.com, tem por objetivo conectá-lo com abduzidos que possam ajudar a esclarecer um pouco sobre o desaparecimento de Fang. Owen sabe que precisa de um formulário HTML para requisitar histórias de abdução dos visitantes e que precisa descobrir se por acaso, eles viram Fang durante as suasjornadas interestelares. Mas Owen precisa de ajuda para conseguir montar o site e colocã-lo no ar. Eis o que ele tem em mente para o formulário. Este é o tampo para 0 ewieveço de emaii do visitante- , 0V JÉK<^uer uma dcsâriçâo -Písifii aliehs. ísiââ dos Owtr, espera <ue al^wcm responda sim, «^ *e eles viram *a espaçwave alienígena- ^uais^uçv fiomentirios adiciowais Sâo àolotàda a^ctí. Òvjen deseja redeber uma mensagem de em a»! guando o usuirio submeter o -formulário- £ste -formulário c lOO%t pur© HTML./ O que você achou do formulário HTML de Owen? Você consegue pensar em quaisquer problemas com os quais Owen poderá se deparar quando tentar obter dados sobre abduções usando este formulário? Vá em frente, ponha suas ideias no papel. . .vrsí.. .r?:..!Aí.:...òX}......................*................................................ você está aqui ► 5
  • 44.
    Formulários são feitosde HTML O formulário “Relate uma Abdução de Owen” (baixe este código através do site da altabooks.com.br) se compõe, inteiramente, de tags e atributos HTML. Há campos de texto para a maioria das perguntas, botões de rádio para descobrir se o visitante viu Fang e uma área de texto para comentários adicionais. E o formulário está configurado para enviar os dados recebidos para o endereço de email de Owen. VailV' c um ^robotoío «ue permi-te t^uc dados à t -formulários seja» enviados por email- formulário html do Owen Se predisar de um re-Çresdo de memória sobre domo driar •formulários HTML, de uma olhada «o Capí-Wo l^vde Use a Cabeça! HTML tom CSS *rtTML <p>Share your story of alien abduction:</p> <form method="post" action="m ailto:owen@aliensabductedme.com"> fc-—. <label for="firstname >t'irst f i ' S I H S " !<. / label> ------- ---- ------ Own ira redeber o donieúdo deste -formulário enviado para ele «este endereço de r «^ail - fohha a< ^ u i o seu / endereço para testar ^ o +ormulár»o. £ste valor diz. ao servidor domo e*viar 05 dados. Será “post” ou w «çt - N ® 5 explidaremos a di-ferenÇa mais à írente- As tajs input dizem ao -formulário para esperar irvformadoes, a«ui. 0 atributo type diz. a ação do -formulário para esperar texto. cinput type=1 1 text" id="firstname" name="firstname" /><br /> <label for="lastname">Last name:</label>' Cinput type="text" id="lastname" name="lastname" /><br /> clabel for='’ email">What is your email address?</label> Cinpuf*~type="text" id="email" name="email" 7><br /> <label for="whenithappened">When did it happen?c/label> <input type="text" id=T T whenithappened" name="whenithappened" /xbr /> clabel for="howlong">How long were you gone?</label> <input type="textM id="howlong" name="howlong" /xbr /> <label for="howmany">How many did you see?</label> cinput ty^C="text" id="howmany" name="howmany' ’ /xbr /> <label £or=”aliendescription">Describe them:</label> <input type="text" id="aliendescription" name^'aliendescription" size="32" /xbr /> <label for="whattheydid">What did they do to you?</label> <input type="text" id="whattheydid" name="whattheydid" size="32" /xbr /> <label for="fangspotted">Have you seen my dog Fang?</label> Yes cinput id=”fangspotted" name="fangspotted" type="radio" value="yes" /> No cinput id="fangspotted" name="fangspotted" type="radio" value="no" />cbr /> cimg src="fang. jpg" width=,'100" height="175" alt="My abducted dog Fang." />cbr /> clabel for="other">Anything else you want to add?c/label> ctextarea id="other" name="other"x/textareaxbr /> cinput type="submit" value="Report Abduction" name="submit" /> c/form> 0 -formulário -fidS dont»do dentro de ta$s <£orm> de abertura e de -fedbamento- Nenhuma surpresa a^ui - o -formulário e 0Ô% puro totligo HTML/ 0 botao submeter" diz. a©-formulário para exedutar a ação exposta ali.
  • 45.
    adicionando vida àssuas páginas estáticas T f e s r O r í v c Teste o formulário “Relatar uma Abdução”. Baixe o código da página “Relatar uma Abdução”no site da Alta Bóoks, em www.altabooks.com. br. O código estará no cadastro deste Livro. O folder chi contém o formulário de Owen em report. html, bem como uma folha de estilo (style. css) e uma imagem de Fang (fang.jpg). Abra a página report.html em um editor de texto e troque o endereço de email de Owen pelo seu. Em seguida, abra a página em um navegador web, digite algumas informações no formulário e clique no botão “Relatar Abdução” (Report Abduction). t O â style.cssJ^(M8f report.WnM fan9-jpg AliensAbductedMe -ReportanAbduction Shareyourstoryofalienabduction; $u3háo v<*£ submete o Wulário, isso resulta nos dados a serem enviados... ou í$so. First name: Lost names What is jour emaflad/lress? When did tthappen? How hmg were you gpne? How many did you see? Descrfte them; What did they do to you? Have you seen my dog Fang? Aif N a d j a J f n f g i r i i e ’ ^a^reen.ccm 111hours Idozens !ilttifigreec* me?K ;asksdnttfaboutItfO Yes Q N 08 0 -formuiario HTML- nao sab«) reataentci iomo enviar uma mensagem dt email, entao ele delega a târeía para o progva^a de email do próprio usuário 0s dados do -formulário irvao sao enviados p ara ^y Owen, a nâo ser < ^ u e o usuário manualmente envie esta estranha mensagem de email- Então, o que você achou? Você recebeu os dados do formulário como uma mensagem de email na sua caixa de entrada? você está aqui ► 7
  • 46.
    mailto - máidéia 0 formulário HTML apresenta problemas O formulário “Relatar uma Abdução”está no ar, operante, mas ele não consegue obter muitas inforaiações dos usuários. Será que a abdução de Fang corresponde a um incidente isolado... ou tem algo de errado com o formulário. Vejamos o que os usuários têm a dizer. Eu observei algo parecido com o seguinte no campo Assunto: ?When=<&Where=. Estou confuso. O Não aconteceu nada, porque o meu navegador não tem um cliente de email padrao... seja la o que isso signifique. Quando clico no botão, ele abre o meu programa de email, o Outlook, e nada do que digitei, durante 15 minutos, ficou registrado no formulário! Apareceu um email em branco. Todas as respostas que eu tive o trabalho de digitar foram ignoradas. Deveriam abduzir este formulário idiota! T ' T mo’tivo> 0 de esta extraindo mais -kusW ão do «ue '»Wmaçao dos visitantes do seu site. O que está acontecendo aqui? Você tem ideias sobre como consertar o formulário?
  • 47.
    adicionando vida àssuas páginas estáticas Parece estar tudo OK com o formulário. Será que o problema tem algo a ver com aquela parte do "mailto"? O o Sim. O código HTML do formulário está correto, mas “mailto” não é uma boa maneira de enviar dados O formulário de Owen funciona bem até o usuário clicar no botão “Relatar Abdução”.Nesse ponto, você passaa depender do recurso de m ailto para empacotar os dados do formulário em uma mensagem de email. Mas este emaíl não é enviado automaticamente - ele é criado no programa de mail padrão do computador do usuário. E o pior: o usuário precisa enviarele mesmo o email, para que os dados sejam realmente enviados para você! Você não tem nenhum controle sobre a entrega do email, significando que ele poderá —ou não - fazer aviagem do seu formulário web, passando pelo navegador do usuário e pelo seu cliente de email, até chegar a você como uma mensagem de email. Nada bom. Você precisa de uma forma para ter o controle sobre a entrega do formulário web. Mais especificamente, você precisa que o PHP empacote os dados em uma mensagem de email, e depois se certifique de que essa mensagem será enviada. Isto envolve desviar a sua atenção do cliente (HTML, m ailto, etc.) para o servidor (PHP). 0 íormulârio esta ótimo, ate voee ttã no boWRelatav Abdução” - enta«? tudo dcsntoronâ! você esté aqui ► 9
  • 48.
    lado-cliente versus lado-servidor HTMLroda no cliente O formulário de Owen foi escrito em HTML puro, com uma ação m ailto que tenta enviar os ciadosvia email. Embora a página report html venha de um servidorweb, ela é preenchida e processada inteiramente no navegadorweb do usuário. O navegador requisita a páginaweb de Owen, a qualinclui o formulário 0 software navegador do seu domputador roda a«ui, tambem torMctido íorno C L lW T t . O servidorretorna o código HTMLpara a páginaweb. O usuário preenche o formulário e o submete. 0 saÊ-bwave servidor web de O^tTí voda a°ui> tambem donHedido domo SERVlPöR A tagde ação do formulário diz ao navegadorpara pedir ao programa de email do usuário que crie uma mensagem de email. O programa de email do usuário cria uma mensagem com os dados do formulário - mas é o usuário que precisa enviá-los, manualmente, a Owen. O papel do servidor, aqui, limita-se a apenas entregar a página web ao navegador. Quando o usuário submete o formulário, o navegador (cliente!) precisa resolver sozinho a questão de como fazer os dados serem enviados via email. O cliente não está.equipado para entregar dados do formulário - esse é um trabalho para o servidor. ô servidor jamais entra em dontato tom os dados digitados em -formulários < ^ u e usem mailto-
  • 49.
    adicionando vida àssuas páginas estáticas PHP roda m o servidor O PHP lhe permite controlar os dados que o usuário digita no formulário, enviando-os para você de forma transparente. O usuário digita o seu caso de abdução no formulário, clica no botão “Relatar Abdução”e pronto! O código PHP cria a mensagem de email, a envia para você e então gera uma página de confirmação para o usuário. ^ ---- --- Eu gostaria de ^ receber a página "Relatar 7 uma Abdução1 ', por favor. 0 O navegador requisita a páginaweb de Owen. O servidor responde com o código HTMLpara apágina web. O usuário preenche o formulário e o submete, enviando os dados a um scriptPHPpresente no servidor. O servidor envia umaconfirmação em HTML ao navegador. O**:* vetebe, to» u* ayadaveWen-te atado. Marque os lugares onde você acha que os scripts PHP devem residir: | | no cliente X no servidor j^j em ambos j^j em nenhum dos dois você está aqui ► 11
  • 50.
    php é umalinguagem do lado-servidor Os scrípts PHP rodam mo servidor O código PHP roda no servidor e é armazenado em sciipts PHP que geralmente tem a extensão .php. Os scripts PHP frequentemente se parecem bastante com páginas HTML normais, porque contêm tanto código HTML quanto CSS. De fato, quando o servidor executa um script PHP, o resultado final é sempre HTML e CSS puros. Assim, todo script PHP acaba se transformando em HTML e CSS, uma vez terminada a sua execução no servidor. Vamos dar uma olhada mais detalhada no modo como o script PHP modifica o fluxo do formulário web de Owen. O navegador do cliente requisitaumapáginaHTML- re p o rt htm l O O servidor retorna apágina HTML hc ttêr M botão "Relatar Abdução", 0 usuatrio submete os dados do •íww.ulirio para o sfivift PHP do servidor. O usuário preenche o formulário e o submete, fazendo o navegador repassar os dadospara um scriptPHP no servidor.
  • 51.
    adicionando vida àssuas páginas estáticas 0 PBP é uma linguagem de programação do lado do serVidPT(serVe-side) -pofs ele rpda em um serVidor Web. O servidorretoma umapágina de HTMLpuro, geradapelo scriptPHP. 0 sdript PttP v-oda no servidor! Embora Onome da pagina apareça tom uma extensão fhp no navegador, ela t furo HTML, neste ponto. O navegador exibe a página de confirmação. AliensAbductedMe-ReportanAbduction Youw ereabductedlastNororiberaodw eregoneforíI bows d e s c r i b e d i c t a WasFau£<h*rc?Do Y " o u r e m a i l 6 * h c a O servidor executa o scriptPHP, o qual envia um email e geraumapágina de confirmação em HTML. 0 usuário ve A uma págma de ^ toníirma^ao. O emailé enviado para a Caixa de Entradade Owen.
  • 52.
    o atributo actiondo formulário £ stc t o YiOTnt ào seu sflrip-l PHP- O atributo action dos elementos do formulário é o que conecta este último ao script PHP, fazendo o script ser executado quando o formulário é submetido. Os formulários são criados usando-se a tag HTML <form> e cada tag <form> possui um atributo action. O arquivo cujo nome você inclui com o atributo action é usado pelo servidor web para processar o formulário quando este é submetido. Assim, se o script PHP de Owen se chamar report.php, então a tag <form> para conectá-lo ao formulário se parecerá com o seguinte: <form a c tio n =s m ethod = "p o stM > r e p o r t h t m l Quando o usuário clica no botão “RelatarAbdução’ formulário faz o script report.php ser executado para processamento dos dados. <html> <head> </hLid t>e>Alie:1S Me - an Abduction</title> <body> ^ 2>^lie? ! . , AhdUCt6d Me " ReP°rt an Abduction</h2 > <link rel- stylesheet" type="text/css" = 1 </head> -ext/css href="style. css" /> <body> <h2>Aliens Abducted Me - Report an Abdoction</h2> <E>ghare your story of alien abduction:</n> /IfC' rm method- post1 1 action-repSTt.php-r^ ^ --- a ação do no servidor, 0 atvibwto âdtion da iao| <£<*■ *»> t o c faz. o strict PHP sec ey-edu-tado «o o -ÇovwuUrio c submetido- COI>xun=--report.J ^ mr-msttug'.hi'i.L Igbai» input type- t e X i _ id="£irstnameM na,-ns="firstname" /xbi reportphp
  • 53.
    adicionando vida àssuas páginas estáticas nty? existeni T e r g u n t a s i d í P t c t s T * * 0 que significa PHP? PHP é um acrônimo que originalmente significava Personal Home Pages (Páginas Pessoais). De alguma forma, o acrônimo teve o seu significado modificado para PHP: Hypertext Processor (Processador de Hipertexto PHP). Este último é considerado um acrônimo recursivo, porque ele referencia a si mesmo - um acrônimo (PHP) dentro do acrônimo. Inteligente? Confuso? Você decide! * Mesmo que o meu navegador esteja mostrando que o nome da página termina com .php, ela ainda é puro HTML? Como é possível? Isso é possível porque a página começa a sua vida como código PHP no servidor, mas é transformada em código HTML antes de ser enviada para o navegador. Assim, o servidor executa o código PHP e o converte em HTML antes de enviá-lo para ser visualizado no navegador. Isso significa que, mesmo que o arquivo .php contenha código PHP, o navegador nunca vê esse código - ele vê apenas o código HTML, resultado da execução do código PHP no servidor. * Mas não é verdade que toda página web se origina no servidor, inclusive as páginas HTML puras, em arquivos .html? Sim. Todos os arquivos que compõem um site ficam armazenados no servidor - . html, .c s s , . php, etc. Mas nem todos eles são processados peio servidor. Os arquivos HTML e CSS, bem como arquivos gráficos, sâo enviados diretamente para o navegador do cliente, sem preocupações sobre o conteúdo deles. Os arquivos PHP são diferentes porque contêm códigos que são processados e executados no servidor web. Não é o código PHP que é enviado ao navegador, e sim os resultados obtidos ao se executar o código PHP, - esses resultados são HTML e CSS puros. você está aqui ► 15
  • 54.
    Use PHP paraacessar os dados do formulário seu 1ascript php Então, Owen precisa de um script PHP capaz de fazer com que as informações do formulário cheguem a ele de forma mais confiável do que através do e-mail. Vamos criar esse script. Não se preocupe em entender tudo agora - nós chegaremos lá: O.*riftsPHP M ,éaVi nw as doisas -fica»» •frequentemente to *ttp *r*tc o & > - ■ mi o w a ^ es. j X * bastante £«. w»í ^ é a jájma HTML normal- do pWf5 propriamente dito. ort an Abduction</title> <html> <head> <title>Aliens Abducted Me </head> <body> <h2>Aliens Abdus? d Me - Report an Abduction</h2> É per-feitamente normal um script PHP íniluir ia^s c atributos HTML normais. J 0 blodo de dódijo inteiro é PHP—o restante do stript c HTML normal- j | fcsU pedaço dc I PHP obtem os dados do •formulário, para <*e eles possa» ser exibidos tomo parte de uma página de dottíirmadao. |||| usamos PHP para $erar dódi^o HTML a partir dos dados do -formulário- </body> jftssim domo uma pâ^ina v/cb normal, s^ipt PHP termina íeôhando ^uâis^uer tajs HTML abertas. </html>
  • 55.
    adicionando vida àssuas páginas estáticas T f e f iT O R f V E Modifique o formulário de Owen de forma que ele use um script PHP para processar os dados do formulário. Crie um novo arquivo de texto chamado re p o rt.php e digite nele todo o código da página anterior. Esse é o script que irá processar o formulário web de Owen. O script PHP ainda não está conectado ao formulário; abra a página report.html em um editor de textos e modifique a ação do formulário para report .php em vez de mailto. :form action = method = "post": report.html p^ty reportphp ‘ar>g.jpg Abra a página re p o rt.html em um navegador web, digite algumas informações do seu caso de abdução no formulário e clique no botão “RelatarAbdução”. AliensAbductedMe -ReportanAbduction Share yo o r sto iy o f aüfiB abduction; Dípersdeftd© do seu havendo*-, vo£e podara ve*- uma pá^ihâ 'web Com wwie*to esquisito ou Possivelmente apenas o toâi$o- •fotvfce PttP do séript reportphp. First name: Lastname: W hat is your email address? W ien did it happen? How Long-were you gone? How many did vou see? Dtsc-rEb« them: W hat did they do to you? Have you seen my **6 Fang? ■ 5 N adir > alfin® *e¥r*al|s“ ilasrH ov^'D er :ilh ß ü re AliensAbductedMe-Reportan Abduction ■ 3= ----------Y ouv,™ »M uc«d',SwbeaJLhappewd". echo and w ere gone fo r . 5 iio w _lon g ; echo ’ ^ , : <w.ywn*.. D e s c r i o e t e m : 1 . Sa^des^iior^M W as Fang *e re ? ‘ ■ YesON c»®Your«nailaadnsssK. -mm Ä “ '* <raeta _ 1want tûadd? ÎP teasivoisterm e. î AiiÂa*Abduc i < / h e a d v c- ô d “£ e p c r - f ca r , I <body> aC f < h 2 > J U i e c e â b d u c f c e d Report A ixiue tioQ< /h2> ^ M eS aq u e é assim mesmo que o scriptPHP deveria funcionar? Escreva aqui asua opinião, e o que acha que está acontecendo. .Ê f á / . .d .. ÇMM yU / ^ % . sà á^ r^ ê. ..0 .. ...................................... você está aqui ► 17
  • 56.
    colocando scripts phpno servidor Os scripts PHP precisam ficar em um servidor! A não ser que você, por acaso, tenha um servidorweb rodando no seu £ se v©tê tiver computador local, o script report .php não poderá ser executado ur*servidor web quando você submeter o form ulário “Relatar uma Abdução”.Lembre-se, o instalado lodalme«tc, PHP é uma linguagem de programação e precisa de um ambiente onde e ele tiver suporte a possa rodar. Esse ambiente é um servidorweb com suporte a PHP. Scripts P^P>enta© poderá PHP e páginas web que dependem deles precisam ser colocadas em um testar os stripts PHP servidorweb real, não basta apenas abrir um script diretamente a partir de diretamente no seu um sistema de arquivos local. tomputador. Os navegadoresweb não sabem nada sobre PHP e, portanto,não são capazes de rodar scripts PHP. $0 tontrário de paginas HTML-» podem ser abertas Totalmente em w* navegador web, os stripts PttP sempre ser w aberW’ através de umâ IXRLi a partir de um servidor web £$íe stript PHP representa apenas um monte de tódigo sem sentido para o navegador web. 0 servidor web entende este tódigo PHP e e*etuta o stript! Wma -forma ra>ida de saber se uma pagina web esta sendo entregue por um servidor web c olhar se a U R L tometa tom w Kttp:M . Páginas web abertas tomo arquivos letais sempre iomeÇam tom W -file'W Os servidoresweb com suporte aPHP são equipados para rodar scripts PHP e transformá- los em páginasHTML que os navegadorespossam entender. Os scripts PHP deVem ser eXecutadPS em um serVídPT W eb , o u e n tã o n a q íu n c fõ n ã tã o .
  • 57.
    adicionando vida àssuas páginas estáticas Coloque os seus scripts PHP no servidor E perfeitamente válido criar e editar scripts PHP no seu computador local. Porém, você precisa colocar os arquivos em um servidorweb antes de executá-los. Os arquivos PHP, frequentemente, são colocadosjunto com arquivos HTML em um servidor. Não hã nada fora do comum em colocar scripts PHP no servidorweb - basta colocá-los em um lugar onde as suas páginas web possam acessá-los. Para fazer o upload (envio) dos arquivos para o servidor, você precisará da ajuda de um utilitário, como por exemplo, um programa de FTP (File Transfer Protocol ou Protocolo de Transferência de Arquivos). A maioria dos sdripts PHP apareie junto dom outros arquivos, «a ■«esm a pasta, de*tro do servidor. são, 3* vez£s, armazet^adâs Cmurtvâ pâstá própria, parâ melhor or^ãnizaddo no servidor... mas fido _ «este daso. style.css fang.jpg éjeralmente, ha pasta «o servidor web onde a maioria, se não todos, os arquivos sao armazenados. Fazer o upload dos seus scripts PHP para um servidorweb não é o suficiente - esse servidor também precisa ter o PHP instalado nele. Alguns servidores incluem o PHP por padrão, alguns não. nãe existem perguntas idíptas T * • Como eu posso saberse o meu servidorweb tem o PHP instalado? Você pode perguntar ao seu administrador, ou à sua empresa de hospedagem de sites, ou então pode realizar um pequeno teste, você mesmo. Crie um arquivo de texto chamado t e s t e .p h p e coloque o seguinte código nele: <?php phpinfo( ) ?> £ste dódi$o pede para o^t in-formaÇoes sobre o PHP sejam mostradas no Agora, envie (upload) o teste.php para oS&tf&Widor, e então digite a sua URL em um navegador web. Se o PHP estiver instalado no seu servidor, aparecerão várias informações detalhadas sobre o PHP, incluindo a sua versão. Bingo! Se você não tiver o P H P instalado no seu servid or web, consulte o Apêndice ii. Nele, encontrará instruções para ter o PHP instalado e operante no seu servidor. Lembre-se de deietar o sdript phpmío guando estiver terminado, desta -forma, nin^uem mais tonse^ue ver isto você está aqui > 19
  • 58.
    _ — TJ e s t O r i v e test drive no seu script php Faça o upload dos arquivos da página "Relatar uma Abdução” e teste o formulário... novamente. Envie os arquivos report.html, report. php, style . css efang.j pg para um servidorweb que tenha o PHP instalado. Digite a URL da página report,html no seu navegador, preencha o formulário com informações do seu caso de abdução, e clique no botão “Relatar Abdução”. rep ort reportphp fan9-ipg First name: Last name: W hat fs your email address? When dfd it happen? How tang w ire you gone? How many did you see? Describe them: What did they do to you? Have you seen my dog Fang? Anythmg else vou wfint tn add?
  • 59.
    adicionando vida àssuas páginas estáticas Legal. Agora só é preciso adicionar um pouco de código PHP para enviar os dados do formulário por email. Isso mesmo. O script report.php ainda precisa de algum código para enviar os dados para Owen por em ail. Mas isso não é problema, porque o PHP oferece uma função, que é um pedaço de código pronto reutilizável, que você pode usar para enviar mensagens por email. Você só precisa determinar o que a mensagem deve informar, e então pode usar o PHP para criã-la e enviá-la. Um momentinho! Nós nem sabemos como o script report.php original funciona, e agora ainda temos de torná-lo capaz de enviar emails. Isso, é tipo, muito difícil... o que vocês estão pensando!? É verdade. Para fazer mais coisas com o PHP, é preciso saber mais sobre o PHP Assim, para adicionar a funcionalidade de email ao script report-php de Owen, você terá de se aprofundar um pouco mais no PHP e precisará ter um entendimento sólido de como o script funciona - pelo menos até aqui. você está aqui > 21
  • 60.
    como o códigophp muda para html 0 servidor transforma PHPew HTML Para que se entenda como um script PHP funciona, o principal é entender o que acontece com o script quando ele é executado no servidor. Amaioria dos scripts PHP contém tanto código PHP quanto HTML, e o PHP é executado e transformado em HTML antes de o servidor enviar tudo - na forma de HTML - para o navegador web do cliente. No script report.php de Owen, o código PHP gera a maior parte do conteúdo HTML no corpo da página de confirmação. O código HTML em torno do PHP é enviado sem modificações. Esie dódijo HTML é caiado sem modiíidaçÕes para c navegador. Este tódigo PHP e e*e£utado pelo servidor e gera o dódigo HTML òontendo os dados <^*e forâm digitados no formulário- Mais código HTML estate©, *lu€ e transmitido pelo servidor ao navegador sem modi£áaçoes. reportphp
  • 61.
    adicionando vida àssuas páginas estáticas Este tod130 HTML e chad© emicmp© veal pe!o sdripi PHP, o « ^w e perm'rte ao dodi^o issuer doisas iniereisar>-tes; demo for exemple, indluir dados < ^u e adabaram de ser digrfcados em um•formylario. Estítido - isto rto sc modi-Pida. £>mãmido - modi-pida— «dada vez.nue auu^ Orneie o iUr^WaVio/ Thanks for submitting the form.<br / > You were abducted last November and were gone for 11 hours<br /> Describe them: <br /> Was Fang there? no<br /> Your email 0 resul-fcado -filial do sdript PHP e uma patina web e w * HTML puro, < ^w e-foi gerada dihdMnidamewte «o servidor. você está aqui ► 23
  • 62.
    anatomia do scriptphp do owen Pescon$truindo oscript PHPde Owen O script report .php é acionado pelo formulário “Relatar uma Abdução”e o seu trabalho (no momento) é acessar os dados digitados e gerar uma página de confirmação. Vejamos como. O primeiro pedaço de código corresponde a HTML puro. Ele simplesmente configura a página que estamos criando, incluindo algumas tags HTML requeridas em toda a página web. report.php <html> <head> <title>Aliens Abducted Me - Report an Abduction</title> </head> <body> <h2>Aliens Abducted Me - Report an Abduction</h2> Aqui as coisas começam a ficar interessantes. Estamos prontos para sair do código HTML e entrar no PHP. A tag <?php abre uma seção de código PHP - tudo o que vier depois desta tag é puro PHP. <?php < r £im, este código HTML e mínimo — normalmente voÊe teria u mPOCTYPZ, tags <meta>j etc., mas estamos mantendo as Coisas simples, a^ui- Pa<ui em diante, estaremos lidando tom código PHP— pelo menos até chegarmos à tag de fechamento ?>• Este código reúne os dados do formulário e os armazena em variáveis individuais, para que possamos acessá-los posteriormente. Asvariáveis do PHP permitem que você armazene valores, sejam eles números, textos ou outros tipos de dados. $when_it_happened - $_POST['whenithappened* $how_long = $_POST['howlong']; $alien_description = $_POST['description']; $fang_spotted = $_POST[Tfangspotted'] $email = $ POST['email']; Cada linha do código PHP reune os dados do field do formulário para umã nova variável Agora sim! Aqui, asvariáveis que acabamos de criar são colocadas em ação, sendo inseridas no código HTML, gerado dinamicamente. O comando echo ocasiona o output (saída) de código HTML, que é retomado diretamente para o navegador web. echo echo echo echo echo echo 'Thanks for submitting the form.cbr />'; 'You were abducted ' 1 and were gone for 'Describe them: 1 . 'Was Fang there? ' , 'Your email address . $when_it_happened; ' . $how_long . '<br />'; $alien_description . '<br />’ $fang_spotted . '<br is ' . $email; FVoduz. a saída de código ht»l para o navegador A tag ?> correspondente a <? encerra a seção de código PHP. Daqui em diante, estamos de volta ao código HTML normal. M» fecha o ?> ^ _____________________________ ' PhP Isto finaliza o código PHP - depois desta tag, estamos de volta ao HTML normal. </body> </html> ^gora, termine a pagina fechando as tags HTML <ue havíamos aberto-
  • 63.
    o seu código Algumasregras PHPpara o ounvida O script re p o rt.php de Owen revela algumas regras fundamentais da linguagem PHP, que se aplicam a todo script PHP. Vamos dar uma olhada nelas. O código PHP sempre fica entre tags <?php e ?>. £eu tódiy>, <?PhP h maioria do* s ô rifb PHP são apenas paginas HTM L íita a*ui ^ tc*? toá<sp PHP inserido cm al^wmiu^ar - estas -fca^s ^ ^ __míorirwa»« ao Sírvidor ^uai paríe do código e PHP. l y f Toda instrução PHP precisa terminar com ponto e vírgula (;) echo 'Thanks for submitting the form. <br />';^ Sf^adasostu cód,y> íalKav, ’ vo-ií^« se ,0£Í „30 estiueCeu de i"ítr " S a° P f ^ íolotar o "foní» f vr«Ja*. 1«. •*> tarresy<m<k 3o ^ *o*teíe í» „iis d, ^ <** msb™**’ *ue se pode imaginar. Caso haja qualquer código PHP em uma página web, é uma boa ideia nomear o arquivo com .php, e não com .html, no servidor. adicionando vida às suas páginas estáticas Kã©t essential, »as e uw»aboa ideia «ornear s trifb PHP tom a extensão php- reportphp Os nomes de variáveis PHP precisam começar com um cifrão ($). ^ ----S»-$email = $ _ P O ST [ »email '] ; 0 ii-frao iden-èi-Pida dlàràmeftíe a variável PHP, responsável por armazenar Observando asvariáveisusadas no script report.php, você mo^a^oes dentro de u» consegue ver quaisquer outras regras do PHP referentes a sdript PHP. variáveis? Esçreva-asaqui! j .... você está aqui ► 25
  • 64.
    nomeando as variáveis AVcirîaVel Ewo^itrsncloonoii^pcfrértopstra^su^vskríávd correspondea Além de começarcom $, os nomes de variáveisPHP são também “case- ym C91ltíilllôt sensitive”.Masissonão é tudo - existem outras regras importantespara T A T osnomes que você pode dar àssuasvariáveis.Algumas delas se referem Pllclc- Y9 Ce pÇciO à sintaxe, significando que o seu códigofalharásevocê asignorar, enquanto outras outras obras correspondem a apenas boasideias transmitidasde uma geração de programadores PHP paraoutra. Vamos começarcom asregras oficiaisque irão definitivamente causar problemas sevocê ignorá-lasao nomear suasvariáveis. Sigaestas regras para criarnomes de variáveisválidas. J £ n W ido! l y f Oprimeiro caracter tem de ser um cifrão ($).< :—^ armazenar dados, e ca d a v ariáv el te m um npnie linico. 0 h':' t f * nome da variável precisa ter no mínimo um caracter. yÇO primeiro caracter depois do cifrão pode ser uma letra ou um "underscore" (_), e os caracteres seguintes podem ser uma letra, um underscore ou um número. fyÇEspaços e caracteres especiais, fora _ e $ , não são permitidos em nenhuma parte do nome de uma variável Sem dontar >e t requerido no nome de ioda variável. Inválido^ Nomes de variáveis PHP nao pode» donter Kí-fens nem espados. $emai l Val'do / $fang^spotted Y 1$when- r õ w h a t ^ 16^—d id _- - it happened ------------------- :_ 1 /álid« Invalido/ Hííens não sa© $how long I em nomes de = ---------- variáveis PHP. a lx e n jdescription Válido!- Sevocê não seguir estasregras, o seu código não funcionará. Existem ainda, outras regras que podem serseguidas- por uma questão de “convenções”de programação. Estassãoregras que ajudam a tomaro código PHP um pouco maisconsistente efacilde serlido. Use minúsculas nos nomes das variáveis. Inválido/ Nomes de variáveis PHP predisam domedar dom um di-frao (f). Os nomes das VoriaVeís FHT Em nomes de variáveis com mais de uma palavra, com eçar separe-as com "underscores". — t com um c if r a i) , e YtfjQ fcpdem Sevocê ignorarestas duasúltimas regras, não serão geradas falhas no seu código. Certamente, você encontrará códigosPHP que não seguem estas regras e, mesmo assim, funcionam perfeitamente. Isso ocorre porque estasregras- sobre asquaisestamos nos referindo- CÇU^eí eSpaç^S tratam-se de uma convenção estilística. Elas tomam-se úteis quando começam a criare nomearsuasprópriasvariáveis.
  • 65.
    adicionando vida àssuas páginas estáticas não existem p e r g u n ta s id io ta s paraos navegadores. 0 PHPnãom uda essefato. 0 queoPHPlheperm ite fazerémodificaroconteúdoHTMLem temporeal, inserindodadoscomoa datade hoje, informaçõesretiradasde umbancodedados, ouatém esm o valorescalculados, comoovalortotal do pedido, emumsitedecom pras. Assim, oPHPpermitequevocê manipuleo HTMLquecompõeaspáginasweb, em vezdetê-las criadasestaticamente, apenas um avez. Ébastantecomumter um apáginaHTMLcomcódigoPHPaqui eali parainserirdadosimportantes, ou alterar programaticam enteoHTM Lde algumaforma. Lembre-sedequetodapágina webcorrespondeao resultadode um a comunicaçãodeduas vias, envolvendo um a requisiçãofeita pelonavegador clienteeumarespostadoservidor web. AURLéabaseda requisição, enquantoconteúdoretornado pelo servidor éaresposta. Osscripts PHP são requisitados damesmaforma que páginas HTMLnormais, através de URLsdigitadas no navegadorou linkadasapartirdeoutras páginas, ou comoações deformulários. Isso explica porquea URLde uma“página” PHPmostrao nom edoscript. - Faz diferença escrever os comandos PHP em maiúsculas ou minúsculas? K : Simenão. Emgeral,oPHPnão é"case-sensitive",portanto,vocêpode m isturarm aiúsculasem inúsculasna m aioriadoscom andos. Issosignificaque vocêpodeusarecho, ECHOouE chO . E ntretanto, porum aquestãodeconvenção, éum aótim aideiaserconsistentenosseus scripts.Am aioriadosprogram adoresPH P prefereusarm inúsculasnam aiorparte dosseuscódigos,eéporissoqueveráa grafiaechosendousadanosexem plosde códigosdestelivro. T * - Então, mesmo sendo uma má prática de programação, posso misturar maiúsculas e minúsculas no meu código PHP? M ãocompletamente. Aexceção correspondeaos nomesdas variáveis, oquetambémseaplicaàs localidades dearmazenamentodedados que vocêcria. Vejamosavariável $email usada noscript "Relatar umaAbdução", comoexemplo. Onomedestavariável é"case-sensitive", portanto, você não podesereferiraela como$EMAILou SeM ail. Todososnomesdevariáveis, emPH P, são"case-sensitive", por isso, éimportantenomearas variáveis comcuidadoereferenciá-las de forma consistente, emtodoocódigo. Falaremos maissobrenomes de variáveis emoutromomento. • Realmente não tem problema colocar código PHP e HTML no mesmo arquivo? Nenhumproblema. Naverdade, emmuitoscasos, éabsolutamente necessáriofazer isso. - E por que colocar PHP e HTML no mesmo arquivo? Porqueoverdadeiropropósitoum servidorwebéservirpáginaswebHTM L • O código PHP inserido em um arquivo HTML precisa estar na sua própria linha ou posso colocá-lo em uma linha HTML, como parte do atributo de uma tag HTML, por exemplo? Foraanecessidadedecolocaroseu códigoPHPdentrodastags<?phpe?>, nãohárestriçõessobrecom oinseriresse códigonoHTM L. N averdade,énecessário colocar,frequentem ente,umblocode códigoPHPnom eiodocódigoH TM L, por exem plo,quandoestásendoconfiguradoo atributodeum atagHTM L. Esseéumuso perfeitam entelegítim odoP H P . TÍ^" Já vi códigos PHP iniciados por <? como tag de abertura, em vez de <?php. isso está certo? Naverdade, não. Tecnicamente issoépermitido, mas não recomendado. Éprecisoqueuma configuraçãodoservidor esteja habilitadaparaqueatag abreviada (<?) funcione. Atag <?php usual semprefunciona, entãoémelhor simplesmente usá-la, sabendoqueo seu códigovai funcionar. ? : Seo servidorweb sempre retoma HTML puro para o navegador do cliente, por que as URLs mostram o nome do script PHP, como, por exemplo, paginaweb.php? Aoutrametadedaequaçãoéaresposta doservidor, queéocódigoresultante geradopeloscript P H P . Umavezque am aioriadosscriptsPHPgeraHTM L, fazsentidoqueessecódigoseja HTM L enãoP H P .Assim, nãoéporacidente queaURLreferencie umarquivo .php noservidor, oquefazocódigoPHPser executadonoservidor, resultandoem umconteúdopuramenteHTM L, queé retomadoaonavegador. ^ • As variáveis PHP podem armazenar outros tipos de dados? Certamente. Vocêpodeusá-las paraarmazenardados Booleanos (verdadeiro/falso). Edados numéricos podemsertantonúmerosinteiros quantodepontoflutuante(decim ais). Hátambémos"arrays", osquais armazenamumconjuntodedados, bem com oobjetos, osquaisassociamum conjuntodedadosaocódigousado para manipulá-los. O s"arrays"serão abordadosumpoucomaisadianteainda nestecapítulo, enquantoos"objetos" sãoassuntodoCapítulo 12. Existe tambémumtipodedadoespecial chamadoNULL, querepresenta "nenhumvaior". Porexemplo, um a variável que nãotenha nenhumvalor atribuídoaelaéconsiderada NULL. você está aqui > 27
  • 66.
    adicionando dados perdidosno owen C lâv-âm entaíci unnâ desdVÍÇao (desóribe) dos aliens no ■í-ovrnulíirio... ••■»as a descrição «a© aparece na pagina de LorJtWmàtâo
  • 67.
    adicionando vida àssuas páginas estáticas Aponte seu lápis Há um problema com os dados referentes à descrição dos aliens, no script report.php de Owen. Circule as linhas do código que você acha que tem a ver com o problema e escreva o que elas estão causando. Alguma ideia do que há de errado? <html> <head> <title>Aliens Abducted Me - Report an Abduction</title> </head> <body> <h2>Aliens Abducted Me - Report an Abduction</h2> <?php $when__it_happened = $_POST ['whenithappened1]; $how_long = $_POST [ ■’howlong ']; $alien__description. = $_POST ['description1]; $fang_spotted = $_POST[1fangspotted'] $email * $_POST['e m a i l ; echo 'Thanks for submitting the form.cbr />N:j echo ’You were abducted ' . $when_it_happene^'; ■ * echo ' and were gone for ' . $how long . />>' '< echo 'Describe them: 1 . $alien description . ' <br />’ i . m i, c ik. / echo ’ Was Fang there? ’ . $fang_spotted . '<br />’; i i s i i o 'Your email address is ' . $email; ?> </body> </html> report,php você está aqui > 29
  • 68.
    apontando solução F 3|^pottteseulápis S O UCãO um Pr°klema com 05 dados referentes àdescrição dos aliens, no script report.php de Owen. Circule as linhas do código que você acha que tem a ver com o problema e escreva o que elas estão causando. Alguma ideiadoquehá deerrado? £sta ImKa do código ob-tem a destvitao dos aliens do respectivo ta^po no -formulário ttTMU e os dados ãVmdz-ena em um3 variável PHP Camada falien_jdesCription Report an Abduction</title> Este código Combina a descrição dos aliens Com alguns ot»-fcros -textos e códigos HTML e envia tudo isso para o navegador. <html> <head> <title>Aliens Abducted Me </head> <body> <h2>Aliens Abducted Me - Report an Abduction</h2> <?php $when_it_happened = $_POST['wnenithappened'] ; $how_long = $_POST['howlong'] ; $alien_de script-ion = $JPQST[-description']?) $fang_spotted = $_POST['fangspotted'] $email = $_POST[’email1]; echo ’Thanks for submitting the form.cbr />'; echo 1You were abducted ’ . $when_it happened; echo 1 and were gone for ' . $how_long . ’<br />'; echo 'Was Fang there? echo 'Your email address is ?> </body> </html> $alien_description $fang_spotted^ ' '<br /> $email; <br />' Por al^vtm motivo, a variave) falien_ description parece estar vazia- *ada bom. reportphp
  • 69.
    adicionando vida àssuas páginas estáticas Variáveis servem para armazenar dados descripts AsvariáveisPHPsão como containers que armazenam informações, damesmaforma que um copo armazena uma bebida. Umavezque avariável $alien_description estávazia, nós sabemos que os dados correspondentes do formulário não estão chegando até ela. Assim, avariável $a1ien_de scription permanece vazia, apesar da nossatentativa de atribuiralguns dados a ela. Este e e ftorvie da variável. «íelizmewte, dopo endoniva-se vâzio- $a1ien_description Nós pve£isa**os de um dopo •ètrâwsbordando desd<ri£©es dos aîienii igenas' Saliendescription Uma forma de consertaro scriptseriaatribuira stringexata que estamos esperando para avariável $a1ien_description, destaforma: $alien_description = 'Homenzinhos verdes1 . pnp J PWP, « 'pedaços” de 4 *xto, 0 13* .wt™IO dha-ad« dí striay, deve„ a atribuir < , val«r da d « .ta a s<mpre w u ]o ts ic i d ttilro d( variave! da « Verda. ^ rociclB S£(. si |ej ou ^ Este código armazena, definitivamente, o texto 'homenzinhos verdes ' navariável $alien_description. Masnós resolvemos um problema criando outro - este código faza descrição ser sempre a mesma, independentemente do que o usuário digitarno formulário. ( x f c É R É S R Q Por algum motivo, a atribuição dos dados do formulário referentes à descrição dos alienígenas à variável $aiien_description não está funcionando. $alien description - $_POST['description 1]; O que você acha que está errado com este código? você está aqui ► 31
  • 70.
    tudo sobre $_PO$T O Oproblema obviamente tem algo a ver com aquele negócio de $_POST. Mas nâo tenho ideia do que possa ser. O problema, de fato, tem algo a ver com $ _ p o s t, que é um mecanismo usado para que os dados do formulário sejam transferidos para um script. O cifrão no início de $ POST é uma dica... $ POST é um Container! Maisespecificamente, $_POST é um conjunto de locais de armazenamento usados para que osdados de um formulário web fiquem armazenados. No caso de Owen, todos os dados enviados para scriptreportphp sãoarmazenados quando alguém preenche o formulário e clica no botão de “RelatarAbdução”.Assim, para acessar osdados do foraiulário e fazerqualquer coisacom eles, nós temos que usar $_POST. Lembra-se deste código? $when_it_happened = $_POST['whenithappened1] ; $how_long = $_POST [ 'howlong']; ---• ------ - $alien_description = $_POST['description']; $fang_spotted = $_POST[1fangspotted'] ; $email = $_POST [’email1]; # »«esmo adonieCe a ^ u i , exee-fco feio £abo de <uc os , r is • ààáos. reíere*tes âo email « W t e a ***<*> « * va*i„ e|é cn il abdu^âo sao aonbuidcs a variável ?Kov#_jong. Assim, osdados de cadacampo do formulário “RelatarumaAbdução”são acessados usando-se $_P0ST . Mas o que exatamente é $_P0ST... uma,ariável?
  • 71.
    adicionando vida àssuas páginas estáticas t-POST é umavariável especial quearmazena dados doformulário $_POST é uma variável especial, conhecida também como superglobal, porque ela é interna ao PHP e fica disponível para o script inteiro. $_POST já existe quando o seu script é executado - você não a cria, como as outras variáveis no PHP. AliensAbductedMe-ReportanAbduction Shareyour story of alien atdoctíon: Asuperglobal POST armazena todos os dados d't3'iiados no iormularso- Firstname: Lastnamei Whatisyour esnafladdress? When did ithappen? How toug w«reyou gone? How man} did you sec? Describethem; Whatdid they do to yon? Haveyoa seen my dogFang? ; A ? f / 1 M a d i r f <html> a ^ r » ^ 1 i í « Y r e a l t í f e e p . e í > m ;J <head> & s th í o v e m f c e r <tifcle>Aliens ^ 1 1hoursTy </head> ^ d a r a u s <body> i l i t t l e s r c e i tihm <h2>Alíens A f c d ' : a s k e d a J s o i s t Ü F Or í g u t e t i O f > 5 Ÿ» © No & <?php $_POST[’howlong> ] _ - y POSTr ' when ith a p p e n e d '1; $how_long =(*$_P05T[1 howlong']; * ) $alien__de$crIptlon~^'"$'_Ff§Tt~*TSescription' ]; $fang_spotted = » $_POST[’f^gspotted11 $email = $_POST['email1J; : P l e a s e v o t * ? o r n t « . V R eportA bnhictiw T } echo ’ Thanks for submitting te form.cbr />', echo 'You were abducted ' . $wen_it_happened; echo ' and were gone for ’ . $h<Sw long . ‘ <br />'; echo ’ Describe them: ’ . $alien_«oscription . '<br />’ echo ’ Was Fang there? 1 . $fang_spVtted . 1 <br />’; ’ Your email address is 1 . echo ?> </body> </htmI> Asuperglobal $_POST évinculada diretamente ao método de submissãousado peloformulário HTML. Se o método tiversido definido como post, então todos os dados são empacotados dentro da superglobal $_POST, onde cadainformação pode serretiradae usadaconforme necessário. 0 r»eh>do de submissão do iorwwlav-io determina o modo Corno© Sdâdos são •fornecidos ao script PHP. reporthtml l "w r' 0 nome (“por Quanto tempo ) vem do atributo «a^e usado «a ta j <i»pu-è> Correspondente a este Ca»»po do Tormulario- 0 » E R > 0 __________________ JE /L'"/VV‘- Como você achaque a superglobal $_p o s t funciona? Como ela é capaz de armazenar múltiplos valores originários de todas aquelas caixas de texto do formulário de Owen? você está aqui ► 33
  • 72.
    $_POST é comoum array $-POSTtransporta osdadosdoformulário para oseuscript $_POST é um tipo especial de ContainerPHP, conhecido como array, que armazenaum conjunto de variáveissobum único nome. Quando o usuário submete oformulário de Owen, os dados que ele digitou nos campos são armazenados no array $_POST, cujo trabalho é repassaresses dados para o script. Cada elemento do array $_POST corresponde a uma determinada informação, digitada em um determinado campo do formulário. Paraacessarosdados referentes a um campo específico,vocêusa o nome desse campo com $_POST. Por exemplo, a duração da abdução é armazenada em $_ POST [' howlong' ]. O código HTMLdo formulário de Owen revela o modo como os nomes do formulário se relacionam com os dados armazenados em $ POST. <p>Share your story of alien abduction:</p> <form method="post" action="report.php"> Clabel for="firstname">First name:</label> <input type="text" id="firstr>ame" naree="firstname Clabel for="lastname”>Last name:</labei> <input type="text" id="lastname" name="lastname" / x b r £ <label for="email">What is your email address?</lab' <input type="tex.t" id="email" name="email" /xbr <label for='’ whenithappened">When did it h /label> <input type="text" id=nwhenithappened" na nithappened" <label for="howlong">Hciw long were you go bel> -------..........SWIfIffill r= bowmany">How many aid you <input type="text" id="howinany" name="howman.y" / x b r /> Clabel for=”aliendescription">Describe them:</label> clabel for="whattheydid">what <input type="text" id="whattheyd: <label for="fangspotted">Have youl Yes <input id="fangspotted" name= No <input id="fangspotted" nairie="f Cimg src="fang.jpg" width="100" he alt="My abducted dog Fang." /Xbr <label for="other">Anything else you w <textarea name="othern></textareaxbr cinput type="submit" value="Report Abducti </form> ey do to""you?</label">"' name="wh.attheydid"|S»ize="32" /X b r /> my dog Fang?</lljel> angspotted" type="raaS,o" value="yes" /> type="radiovalue="no" /xbr /> ="175" add?</label> name="submit" /> 0 a rra y $ _ p o sr& p re e n c tld p co m PS Vcjpres <jue O usuarfp dlgitpu n9 Çprmulárip* 0 nowC do tàrr^Q) H O Wmulávio, deicvmina o modo domo ele e adessado de«-bro do array fJ>0£T ‘firstname’ ‘iastname’ ‘whenithappened’ $ POST ‘aliendescription’ ‘howmany’ Todos os dados do ■ -formulário -fidam disponíveis através do arrav i PACT
  • 73.
    adicionando vida èssuas páginas estáticas r - ^Aponte seu lápis X " Examine o código de report.php que está fazendo a descrição dos aliens ficar em branco e depois escreva a solução para o problema. Dica: use o código HTML do formulário exposto na página anterior para ajudar a isolar o problema. Lembre-se1 anteriormente, «os isolamos o problemâ para essas duas ImKas de tódigo. <htrnl>' <head> <title>Aliens Abducted Me - Report an Abduction</title> </head> <body> <h2>Aliens Abducted Me - Report an Abduction</h2> <?php $when_it_happened = $_POST['whenithappened']; $how_long = $_POST['howlong']; (^$alien_description = $_POST[1description $fang_spotted = $_POST['fangspotted'] $email = $__POST [1email']; echo 'Thanks for submitting the form.<br />'; echo 1You were abducted ' . $when_it_happened; echo 1 and were gone for ' . $how_long . '<br />’; echo 'Describe them: ' , $alien_description . '<br / > ' ; y »■ *«________________________________— ------ —^ echo 'Was Fang there? 1 . $fang_spotted . '<br />'; echo 'Your email address is ' . $email; ?> c/body> </html> reportphp você está aqui ► 35
  • 74.
    apontando solução ponteseulápis Solupão Examineo código de report.php que está fazendo a descrição dos aliens ficar em branco e depois escreva a solução para o problema. Dica: use o código HTML do formulário exposto na página anterior para ajudar a isolar o problema. <input type-"text id- = " a l i e n d e scription" name=(aU6ndescriptiõn^ si 0 fiotwC do £3»*po C mrÜportM>l e "aliendcstvip-tioh”, diievwte do wwe "dcsCr'iyt»©« usado Com fJ>0£T. Kós pveCisamos modiiicar ij> o s r pâra tonrigiv o nome do Câmpo-' w a!icndestvip'tiohW . </head> <body> report.html Abducted Me - Report an Abduction</h2> <?php $when_it_happened = SN^pST[’ whenithappened1]; $how_long = $_FOST ['howlon^J, $alien_description = $ POST[ 'aliendescvip-bo«’ $fang_spotted = $_POST['fangspotted $email = $_POST[1email1]; echo ’Thanks for submitting the form.<br echo 1You were abducted ’ . $when_it_happened; echo ’ and were gone for ' . $how_long . '<br />'; echo 'Describe them: ' . $alien_description . '<br />'; echo 'Was Fang there? 1 . $fang_spotted . '<br />'; echo 'Your email address is 1 . $email; ?> </body> </html> reportphp
  • 75.
    . - ___ Tf e S T O R f V G ------------------------------------- adicionando vida às suas páginas estáticas Conserte e teste o script. Modifique a linha de código problemática em report .php e depois a envie para o seu servidor web. Abra a página report. html no seu navegador, preencha o formulário com as informações do seu caso de abdução e clique no botão “Relatar Abdução” para submeter o formulário agora corrigido script. você está aqui ► 37
  • 76.
    revisando o scriptphp do owen’s Aponte seu lápis Há alguns dados digitados no formulário “ Relatar uma Abdução” que ainda não estamos usando. Lembre-se, esses dados incluem informações vitais sobre um caso de abdução, as quais poderiam ajudar Owen a encontrar seu cão Fang. Portanto, precisamos acessar ou filtrar todos os dados do caso e armazená-los em variáveis PHP. fabièlmznht o sdrift vcfortfhf’esta i^snorSndo Cinto dam^os âo -Çormulârie v>3dreditávcí! <form method“"p o st” a ctio n ^ "re p o rt.php"> <Iab e l fo x= "firE tn a m e "> F irst name:</label> cinput typ e= "text” id = ”firstnam e” name="firstname" /: clab e l for="lastnam e">Last name:</Iabel> <input typ e="text" id^'lastnaitie” r-ame="lastname, T />< <label fo r= ”e:nail">What is your em ail address?</lsbe <input typ e="text" id ="em ail" name="email" / X b r /> : -clabel for="whenithappened">When did it happen?</lai: cinput ty p e ^ 'te x t” id = ”v .’henithappened" name=IT whenitl‘ ■clabel fo r= ’^ow idng3» 5How long were you gone?</label; <input typ e ^ IS iit^ ’ id="how long" naine="howlong" AfljUiMigrise you wanttnaH/i-1 <label f or^"howr.aiV£?>How many d id you see?</label> US?*?®?fltxiiiaSoin <input typeiHtfeex'C1 ' id="hbwmany" name="howmany" / x b <label fo r= "a lie n d e scrip tio n "> D e sc rib e them :</label> <input type5^-texfi'^id="aiiendescriptio_n" n ane = "alie n d e scrip tion " s iz e = "32"' ■clabel for=Xjhatjtheydid">,i3hat d id they do to you?</label> ■cinput type=" te xt" id="w hattheydid" nam e="w hattheyd id "size="32" / x b r /> «Clabel for="fangspotted">Have you seen my'dog Fang?</J©Hit^l' Yes Cinput id = ”fangspotted" name="f£.ngspotted" typ e="rad i No <input id ="fan gsp otte d" name="fangspotted" typ e="rad io" <irr,g src = "fa n g .]p g " w idth="100” height="175" 3lt= "M y abdu.c.t^d dog Fang." / x b r /> < label for=r^othei?'>Anything e lse you want to add?</label> -ctextarea i^js no$Jfer’' name=”othet,’></taxtarea><fcr /> <input type="subm it" v a lu e -" Rspo^t Abduction" name=T > submit </form> -c/body> </html> fl -ta^ <myut> de dada dawyo do -Çoviwulario t ja dkave para fadesso aos dados, a partir do PttP• reporihtml Escreva o código PHP afim de criar quatro novas variáveis que armazenem os dados do formulário que estão faltando: $naine, $how_many, $ w h a t_ th e y_ d id e $ o th e r. Dica: Crie a variável $name de forma que ela armazene o nomexompleto do usuáriçu--'" % ...rir..^_iPQ.r^.A..L.,W. !. ...................... %. .á* .í*.fa2.U/.. .................... 1o£.h£r..,rr..i—.í^ríXL .3^................
  • 77.
    adicionando vida àssuas páginas estáticas Seu trabalho ainda não terminou. A página de confirmação gerada peio script PHP precisa usar essas novas variáveis para exibir mais informações sobre a abdução. FVedisamos partir disto - AliensAbductedMe-ReportanAbduction Yon were abduciedfastNovemberand-weregone for 11Iruis Describethem*littlegreen Was Fangthere?do Youremailaddressisalfh@ihe}Tvsa%ree}Lcom •para isto/ Repare *ê quantidade de «ovas iníormaÇoes exibidas. f r f : ■ 0 nome do usuário nSo c esseindiai para a pagina de dwi-Çirmâçaoj ^ vode precisará dele p o sté rio rité , quando enviarmos o email dom os dados para Owen- Tfrai&sforsubmittingfee form. Yoa were abductedlastNovemberandwere gone for 11hours Humberofaliens:dozens Desoibet h e s s :M e g r e e a in^n The aliensdid this: asked meaboutUFO regulations Was Fang Sisre? £0 Otbefcomments’.Pleasevoteforna. YonrftrrmfladdressisaifnStheyrealigiwn.com Usando todas as variáveis que acabou de criar, exceto Sname, complete o código abaixo, o qual irá gerar uma página de confirmação mais infòrmativa. echo 'Thanks for submitting the form.cbr />'; echo 'You were abducted ' . $when_it_happened; echo ' and were gone for 1 . $how_long . '<br />'; echo 'Describe them: ' . $.alien_description . '<br />'; Í J ! /'>.'• f * ^ í . í y , J jj Ç .Ochxk. . . . W r 7 : 1 át : . . t kw.V . . . zf...z..àt.--X.á a y í« - r J.íd . . . . . . . . . . . S C .ít. /. echo 'Was Fang there? ' . $fang_spotted . '<br />'; 1 - A ^ * J * * 3 ^ , v Jv V " .......£&t. hM ?.......... A t ../.■<.............. echo 'Your email address is ' . $email; £ você está aqui ►
  • 78.
    o script phpdo owert revisado %^ponte seulápis Solução Há alguns dados digitados no formulário “Relatar uma Abdução” que ainda não estamos usando. Lembre-se: esses dados incluem informações vitais sobre um caso de abdução, as quais poderiam ajudar Owen a encontrar seu cão Fang. Portanto, precisamos acessar ou filtrar todos os dados do caso e armazená-los em variáveis PHP. ^•UaUen-be o sóript reportphp esta i<yorândo ivnto £a»pos do ío rm u ld rio . |inacreditável! <form method=,’p o st" action »1 1report ,php"> clab ei fo r= "firstn a m e "> F irst name:</label> cinput typ e="text" id = "firstn am e " name="firstname" / < label for="lastnam e">Last name:</labei> <input type=”te xt" id="lastnam e" name-',lastna^!e', />< < lab e l for="em ail">W hat is your em ail address?</lahe <input typ e="text" id = "e m ail" name="email" / x b r /> <label for="whenithaopened">When did i t happen?</iafc <input typ e="text" id^'whenithappened" ■name="wh.enii:i clab el for="howlDng">How long were yon gone?</label; . <input typ e="text" id “"howleng” name="howlong" /><b: .— Epfeyog want to add? < lab e i for="howmany">How many d id you see;</label> <input typ e="text" id="howmany" naree="howmany" /><b; <label fo r= "alie n d e sorip tion "> D e £ crib e them:</label <input typ e="text" id = "a lie n d e so rip tio n " name=T ,a lie n d e sc rip tio n " s iz e =”32 < lab e i for="whattheydid">W hat d id they do to ycu?</label> <input typ e="text" id="w hattheydid" name=T ,w h attheydid"_size="32" / x b r /> <label for="fangspotted">Have you seen my dog F a n g?< / JS e l> Yes <input id="fangspoti;ed" r.ame="fangspot ted" typ e = "ra d i No <input id ="fan gsp otte d" .iame="fangspotted" typ e="rad io" <img src = "fa n g .jp g " w idth="100" h e igh t= "175" alt="M y abducted dog Fang." / x b r /> <label fo r= "other">Anything e lse you want to aad?</label> <textarea id -"o t h e r ".name=”oth e r"> </ te xtare aX b r /> cinput type="subm it" va ltie= "Report Abduotion" narr.e^1'subm it1 1 </fcrm> </body> </j A ta$ <»put> de cada ca»po do ioriwulario e a th iv t para atesso aos dados, a partis do PttP Escreva o código PHPa fim de criar quatro novas variáveis que armazenem os dados do formulário que estão faltando: Sname, $how_many, $what_they_did e $other. Dica: Crie a variável $name de forma que ela armazene o nome completo do usuário. 0 poK-i»íihâl f ò f e x j . . j fW rW rfcejuhbr Í%amC ■ ••/•?JW$T.Ç varias strings de ■ textoem ur»a so - umpvodísso Conkedide tomo LoKtàteràÇac. este «paço separa o priineiro r>or»e áo sobrenome. fbow^»âlr»y —fJ?OSTC‘Kowrr.ahyjj f>wh^_tbçy_did 77 /_P.PSTtViaHttiKçyclid/pi fother = ■ /_Pp$X
  • 79.
    adicionando vida àssuas páginas estáticas Seu trabalho ainda não terminou. A página de confirmação gerada pelo script PHP precisa usar essas novas variáveis para exibir mais informações sobre a abdução. Predisamos partir disto 0 nome do usuaHo não c essential para a pagina de d©n-firmaça©> mas vote prensará dele posteriormente quando enviarmos o email tom os dados para Owe«- 0 Comando edho é usado para enviar as in-Pormacoes ao navejador, na íorma de donteúdo HT/VJL." Usando todas as variáveis que acabou de criar, exceto $name, complete o código abaixo, o qual irá gerar uma página de confirmação mais informativa. echo 'Thanks for submitting the form.cbr />'; echo 'You were abducted ' . $when_it_happened; 1 <br />'; As tajs <br /> ajudam a -formatar as iníormadoes - não se esqueça de que estamos usando PttP para driar ttTM L. echo 1 and were gone for ' . $how_long edbo 'Kumber of aliens; 1. fbow_mâny . '<br /> ] Movamente, pontos' f i n a i s são usados echo 'Describe them: ' . $alien_description . 1 <br />'; para dondatenar edho lTbe aliens did tbis: 1 f>«bat_tbey__did • '<br /> ', strings c varáveis.......................................'■/».......................................................................... echo 'Was— Eang - f e j l ^ re? ' . $fang_spotted . 1 <br />'; edbo 'Other domments: 1. fotber . (<br />', echo 'Your email address is ' . $email; você está aqui ► 41
  • 80.
    test drive noscript php do owen T f e S T D r i v e Ajuste o script de Owen e teste as modificações. Adicione o código das novasvariáveisa re p o rt.php, bem como o código que enviaasvariáveispara o navegador, com o HTMLformatado. Em seguida, envie o scriptpara o seu servidorweb, abra a página re p o rt.html no seu navegador e preenchao formulário com asinformações do seu caso de abdução. Finalmente, clique no botão “RelatarAbdução”para submetero formulário everos resultados. n£ÍP existem Perguntas idiotas 0 que realmente acontece quando eu faço a concatenação de várias stríngs, usando pontos finais? R: 0 que acontece com o código PHP no navegadòr? OK, então como, exatamente, o servidor transforma o código PHP em códigos HTML e CSS? Concatenar, neste caso, significa juntar diversas strings para formar outra, totalmente diferente. 0 resultado final é sempre uma única string, não importa quantas tenham existido originalmente. Assim, quando você concatena strings como parte de um comando echo, o PHP, primeiramente, as combina em uma só string e depois envia esta última para o navegador. T * * Quando eu concateno uma variável com uma string, a variável precisa conter texto? Não. Embora aconcatenação sempre resulteem / uma string, as variáveis não precisamconter strings j paraquevocê possausá-las emumprocesso de / concatenação. Por exemplo, digamos que umavariável contenha umnúmero; o PHPprimeiramente converte 0 número emuma string edepoisa inclui naconcatenação. ?: P . *■V- Nada. Eisso porque 0código PHP nunca é viste pelo navegador. Ocódigo PHPé executado no servidor ese transforma emcódigo HTML, este simsendo enviado para 0navegador. Assim, 0 navegador nem sequer fica sabendo da existência do PHP- as páginas web chegam como puros HTML e CSS. H Em primeiro lugar, lembre-se de que, por padrão, assume-se que 0código em umscript PHPé código HTML. Você pode identificar 0código PHPdentro de um script colocando-o entre tags <?php e ?>. 0 servidor vê essas tags e entende que deve rodar 0código dentro deias como PHPetodo 0código fora dessas tags é informado ao navegador como sendo umHMTL. - Certo. Mas isso ainda não explica como o códig^f^^jh^nsTõrmaíoíiivWTML/CSS. E então? Ah, é aí que 0comando echo entra erfccena. ' Você pode pensar no echo como umcomando para enviar as informações que estejamfora do domínio das tags <?php e ?>. Assim, 0comando echo representa a chave para a capacidade do PHPde gerar código HTML/CSS, dinamicamente. Concatenando strings de texto comvariáveis PHP, você pode construir código HTMLemtempo real e depois usar echo para enviá-lo ao navegador como parte da páginaweb resultante. Umbomexemplo disso, no scrip report .php, é quando atag <br /> éanexad ao final de umpedaço de texto para gerar uma quebç de linha no HTMLresultante.
  • 81.
    adicionando vida ássuas páginas estáticas A página de confirmação é útil para o usuário, mas não para mim. Ainda preciso que os dados do formulário sejam enviados para mim através de um email. O script PHP ainda precisa enviar os dados do formulário para Owen. Daforma como está, o script report.php estáusando osdados do formulário “RelatarumaAbdução”para geraruma páginade confirmação HTMLpara ousuário. Masisso ainda não está resolvendo o problema original, que baseia-se no envio de uma mensagem por email para Owen, umavezsubmetido o formulário. Ele quer apenas receber uma simples mensagem de email em modo texto, mais ou menos como a seguinte: r - De Wma scm elKan-fee à paji»>a web d t Con-fVmaçao, esta »ensaiem de email Consiste em texto estático, Combinado Com dâdos do -(•oV-mulário Estamensagem de email pode sergerada a partir de código PHP, criando-se umastring que combine textos estáticos como "Outros com entários: " com dados doformulário que estejam armazenados emvariáveis. Escrevaaquicomovocê criariaumamensagemde email apartirde texto estático evariáveisPHP. -Ê tf -s •'*................................................................................................................... AlfNaderfoi abduzido em novembro passado e esteve ausente por 11 horas. Número de aliens: dúzias Descrição dos aliens: homenzinhosverdes O que elesfizeram: me perguntaram sobre leispara asOVNIs Fangfoivisto: não Outros comentários: Porfavorvote em mim. você está aqui ► 43
  • 82.
    construindo o corpoda msg no php Criando ocorpo da mensagem de email com PHP Vocêjá viucomo um ponto final pode serusado em códigos PHP para concatenarváriasstrings de texto em uma só.Agoraprecisa usar novamente a concatenação para criaruma string que seráa mensagem de email, com variáveissendo usadasjuntamente com texto estático. V iáveis c tex to estático Sao ConCatenados em uma unica string (a mehsagem de email) usando— se pontos -Pinais. maioria dos editores de texto, automaticamente, quebra o tex to para a linha seguinte, mesmo <ue vote ndo inclua no código a sua própria quebra de Wha (return)- 5msg = ■ ' was abducted 'Number of aliens: ’Fang spotted: and was gone for ’ . 'Alien description: ’ . ' Other comment '■What they did: Um problema ao se criaruma stringdesse tamanho é que ela demanda uma grande linha de código PHP, difícilde ler e entender.Você pode dividiro código PHP em váriaslinhas, para deixá-lo maisfácilde ser estudado. Certifique-se, apenas, de separaro código em pontos onde o espaçamento não faça diferença, como por exemplo, entre duas strings concatenadas e não no meio de uma string. Em seguida, coloque um ponto evírgulano final da última linha de código, para finalizar a instrução PHP. [st© na verdade i apenas uma grande linha . de código dividida em varias linhas. Lembre-se^ cada variável armazena uma string de texto « tira d a do -formulário Relatar uma /'tbducao 5. v T ' $msg = . 1 was abducted 'Number of aliens: 'Alien description: 'What they did: 'Fang spotted: ' ' Other comments: Ó^uando uma linha de Codigo PHP e: deliberadamente, dividida em varias linhas, costuma-se indentar as linhas após a primeira, para ^ue se perceba, Com mais -facilidade, *uais linhas Compoem u».a mesma instrução no seu código- was gone for ^ de código e Cuidadosamente dividida, evitando-se separar uma string no meio. Mode ainda precisa f inalizar a instrução» Com um ponto e virgula. Um a longa linha de c6dígp p jjp pode set diVidlda era Vatlas llnfcas, desde <jue Você tenha cm dad° na fcpra de separar o eódígo.
  • 83.
    adicionando vida àssuas páginas estáticas Esse código PHP certamente ficou bonito. Mas sem formatação, a mensagem de emai! não vai ficar toda bagunçada? Sim. Só porque o código PHP está bem organizado, não quer dizer que o seu output (saída), autom aticam ente, também ficará bonito. Organizai’o código PHP para que vocêpossaentendê-lo melhor é completamente diferente de formatar o output que osusuários irãover. Você normalmente usará tags HTML para formatar o output do código PHP, umavezque, na maioriados casos, o PHP é usado para segerar, dinamicamente, uma páginaweb. Porém não neste caso. Aqui, estamos gerando uma mensagem de email, que é puro texto, e não HTML. Precisamos lidarcom o feto de que a mensagem, atualmente, se parece com o resultado seguinte: AlfNaderfoi abduzido em novembro passado e esteve ausente por 11horas.Número de aliens: dúzias Descrição dos aliens: homenzinhosverdes O que elesfizeram: me perguntaram sobre leispara as OVNIsFangfoivisto. nãoOutros comentários: Por favorvote em mim. I Hm... isto WftQ 't 0 <^e Owen metvte pava 3 sua de e-m ail existem Perguntas Idíçtas - Existe alguma maneira de se usar formatação HTML em emails que você envia a partir de um script PHP? Existe. Mas isso requer umpasso adicional, que envolve definir o cabeçalho do tipo de conteúdo para a mensagem. Cabeçalhos etipos de conteúdo vão um pouco alémdoescopo desta discussão, por isso, estamos nos limitando a mensagens de email emformato de texto simples. Você aprenderá mais sobre os cabeçalhos no Capítulo 6, portanto, não se preocupe - você verá como enviar emails em HTML mais adiante. W E R » 9 Como você reformataria a mensagem de email para torná-la mais fácil de ler? você está aqui ► 45
  • 84.
    formatando texto comphp Até mesmotexto simples podeser formatado... um pouco Umavezque Owen estáenviando mensagens de email como texto simples, sem nenhuma formatação especial HTML, ele não pode colocar tags<br /> para adicionarquebras de linha para separar o conteúdo. Masele pode usar caracteres newline (novalinha) , que são escapados naforma n.Assim, em qualquer lugardo email onde apareça n, seráinseridaumaquebra de linha, fazendo o conteúdo que viera seguirseiniciar na linhaseguinte. Eiso novo código para a mensagem de email, com os newlines adicionados: ^ t usado para ^uc seja»* inseridos darattergs newline na" ■ m ensagemde em ail- Coracteíes cie escape em P B P começam com uma t>arramVertlJa 00- $msg = $name was abducted $when_it_happened 'Number of aliens: $how ma and was gone for $how_long ' M ' ' n 1 'Alien description: ’ . $alien_defecription . ' | 'What they did: ’ . $what_they_did . ' | | | ; r . 'Fang spotted: ’ . $fang_spotted . ’ J j j | j , . 'Other comments: ' . SothGr; Alf Nader foi abduzido em novembro passado e esteve ausente por 11 h o ra ^ ^ ú m e ro de aliens: dúzias^n} Descrição dos aliens: homenzinhos verdes^rTp que eles fizeram: me perguntaram sobre leis para as 0 7 N I.<g^ang foi visto: n ãq g p u tro s comentários: Por favor v o te tS mim. O que é, exatamente, um caracter de escape? Umcaracter de escape é umcaracter que: ou é difícil de digitar ou que, por algum motivo, poderia causar confusão nocódigo PHP. Você pode estar familiarizado comos caracteres de escape do HTML, programados de uma forma umpouco diferente, como por exemplo, & # 1 69 ou &copy para o símbolo de Copyright. OPHPtemum conjunto bastante pequeno de caracteres de escape que são úteis para se escrever coisas que poderiamse confundir coma própria linguagem, como por exemplo, aspas simples (V), aspas duplas (V) e, é claro, newlines (n). 0 n esta aparedewdo -tomo te*t© Psormâl) zm vez. de um ta ra tte r newline nada bom-
  • 85.
    B j Ú adicionandovida às suas páginas estáticas y cisam de aspas duplas O problema com o código de Owen é que o PHP trata as strings de forma diferente, conforme elas se apresentem: dentro de aspas simples ou duplas. Mais especificamente, os caracteres newline (ji) só podem ser escapados dentro de aspas duplas. Assim, a mensagem de email com os dados do formulário precisa ser construída usando-se strings dentro de aspas duplas, para as newlines funcionarem, Masa históriadas aspas simplesx duplas não termina aí.Asstrings dentro de aspas simples são consideradas como texto puro, enquanto que o PHP processa asstrings dentro de aspasduplas em buscade variáveis. Quando umavariávelé encontrada dentro de uma stringem aspasduplas, o PHP insere o seuvalor dentro da string, como se tivesseocorrido uma “concatenação”.Assim, a stringdentro de aspas duplas não só é necessáriapara ofuncionamento dos newlines na mensagem de email, como também nos permite simplificaro código, colocando asvariáveis diretamente na string. tontaier>a^ao ttâo Cw »ôis netessavia, urnâ vex. *ue as variáveis pode» ser veíerendiadâs diretamente dentro da string entre aspas jdvfIas- $msg = "$name was abducted $when_it_happened and was gone for $how_long.n" "Number of aliens: $how manyn" . "Alien description: $alien_descriptionn" "What they did: $what_they_didn"t ] "Fang spotted: $fang spottedn" "Other comments: $other"; Kao e pretiso dc u*»a no va ) linha guando -for a VmKa ■ Pinal- Os daracieres newline agora sao interpretados dorretamente, graças à siring apresentada entre aspas duplas. Mas ainda predisamos dividir a mensagem em varias strings dondatenâdas para tornar o dodigo mais legível não existem ? Se as aspas duplas são tão legais, por que é que por que fizemos uso, praticamente, aspas simples, até agora? rJ^I^m lejlJ^em jTiente que agaspas simBJj^não| são processadas pelo PHPdëïienhuma manéír^ o que as tcrrna ideias~paraswitjsrqütí yaü"puiu luxlir/s&m nenhuma variável inserida. Assim, continuaremos a usar aspas simples ao longo do livro, a não ser que haja um bommotivo para usar as duplas. Acoisa mais importante nesta questão de usar aspas simples ou duplas para as strings, étentar manter-se o mais consistente possível. perguntas idiotas usar umapóstrofo em uma string dentro de aspas simples, basta fazer escape dele como V,desta forma: ’ H e V s lost! '.0 mesmo se aplica se você quiser usar uma só aspa dupla dentro de umastring delimitada por aspas duplas- use V. Nãoé preciso fazer escape das aspas quando não houver conflito, como por exemplo, ao usar umapóstrofo emuma string contida entre aspas duplas: "He's lost!" . 0 que acontece se eu tiver de usar um apóstrofo dentro de uma string que esteja dentro de aspas simples, como por exemplo, em 1He1s l o s t ! ’ (“ele está perdido!”)? Então, com as aspas simples, pode-se usar V mas não n. Como saber quais caracteres de escape eu posso usar dentro de aspas simples? As strings denlco^easpas simples só permitemos caracteres de escapéV eOodos osoutros caracteres de escape só podemsfèníSados emstrings dentro de aspas duplas. R * Éaí que os caracteres de escape são úteis. Para você está aqui ► 47
  • 86.
    envie email comPHP Enviando uma mensagem de emaii com PHP A Çunçã° Então, você estápronto para escrevero código PHP que enviaráa mensagem m a ílO , d » ? B T a Owen por email. Isto requer afunção interna mail () do PHP, a qual envia uma mensagem com base em informações que vocêfornece. envia uma mensagem de email a partir de um sctipt. 0 e*dcr£to~àc o^aíl w to • 't)"ãSSimto dâ mail ($to, $subject, $msg) ;j ^ iS 0 torpo da mensagem. Essastrês informações são requeridas pelafunção m ail (), portanto, você sempre tem de fomecê-las. O endereço de email “from”não é exigido, mas ainda é uma boa ideia incluí-lo. Para especificaro campo “from”ao chamarafunção m ail (), é preciso üsãrimioutro argumento dafunção,junto a algumaconcatenação de strings. mail($to, $subject, $msg, o ie *to 'FVom:' pretisa ser fi.oloi.ado antes do endereço, ao sc espetiíitar o enderedo de «»ail do remetewte- Cada parte do emajl t íometida à -função mailO por «ma variavel- $email|; 0 ponto -final t útil mais uma vez* para tontaíenar From; dom o endereço de email de Owen- nãp existem ?efguntas idiotas X * Há mais alguma coisa que possa ser especificada como parte de uma mensagem de email, além do endereço “from”? Sim. Vocêpodeespecificartambém recipientes“copy”(“cópia”) e“blindcopy” (“cópia oculta”)da mesmaformaqueo“from”- basta usar' Cc: ' ou ' Bcc: ' emvezde 1From: '.Sequiserespecificartantoum“from” quantoum“copy”,vocêterádesepará-loscom umacombinaçãodecaracteres returnenewline (rn), destaforma: £ isso mesmo, dois taratteres de esdape tolados um no outro^ $from . nrnCc:" . $cc i 'a n t f iif f l ■f Pretisamos usar aspas duplas a^ui, uma vez. < ^u e estamos usando os taratteres de estape V e n.
  • 87.
    adicionando vida àssuas páginas estáticas Mas então, como é que nós usamos, realmente, a função mail()? £nvic a umâ p%"mâ HT/WU em tempo real, pâva dôh-Çirmâr ^ue O-formulário toí submetido Com sudesso. Basta adicionar ao seu script o código para cham ar mail(). Alinha de código que chamaa função mai1 () é tudo o que vocêprecisa para enviara mensagem de email. Certifique-se de que este código apareça no script apóso códigoque criaasvariáveispara o email, e pronto. Eisaqui o código completo para o script report. php de Owen, incluindo a chamada para a função m ail (). <html> <head> <title>Aliens Abducted Me - Report an Abduction</title: </head> <body> <h2>Aliens Abducted Me - Report an Abduction</h2> <?php Çname = $_POST[1firstname1] . ' ' . S^POST['lastnaree' ] $when_it_happened = $_POST[1whenithappened']; $how_long = $_POST[1 howlong’]; $how_many = S_POST['howmany1]; $alien_deseription = $_POST['aliendescription']; $what_they_did = $_POST[1 whattheydid’]; $fang_spotted = $_POST[’fangspotted']; Çemail = $_POST[1 e m a i l ; Sother = $_POST[’other1]; Pegue todos os dados do -formulário no array fJP0ST e doio^ue-os em variaveis individuais- Certiíi^ue-se de tirodar este enderedo de email pelo seu próprio, para testar o sdript- $to = ’ovien5aliensabductedme.com ^subject = 'Aliens Abducted Me-- Abduction Report1, $msg = "Snarne was abducted $wh.en_it_happened and was gone for $how_long.n "Number of aliens: $how_manyn” . "Alien description: $alien_descriptionn" . "What they did: $what_they_didn" . "Fang spotted: $fang_spottedn" . - ' - ' X I U mu- —r n m i r i ^ n t g : Sn-t-hgr"- ■ . . . ^nail($to, $subject, $ r c . s g , ’From:' . Semail)7^> echo 'Thanks for submitting the form.<br />'; echo 'You were abducted 1 . $when_it_happened; echo 1 and were gone for 1 . $how_long . ’<br />'; echo 'Number of aliens: 1 . $how_jnany . '<br />’; echo 'Describe them: ' . $alien_description . '<br />’; echo ’The aliens did this: ' . $what_they_did . '<br /> echo 'Was Fang there? 1 . $fang_spotted . '<br />'; echo 'Other comments: ' . $other . '<br />'; echo 'Your email address is ' . $email; Junte os diierentes pedacos da mensagem a ser enviada para Owen. </body> </html> reportphp você está aqui ► 51
  • 88.
    email overload Owen comepaa perder emails A boa notícia é que Owen está recebendo emails. A má notícia é que ele está recebendo muitos, muitos emails. Tantos que está tendo dificuldade em acompanhá-los. A sua Caixa de Entrada está lotada, e elejá apagou alguns acidentalmente... Owen precisa de uma forma melhor de armazenar os dados sobre as abduções.
  • 89.
    adicionando vida àssuas páginas estáticas * m u F Os aliens mexeram com o seu cérebro? Coloque ascoisasno lugar ligando cadacomponente HTMLou PHP à descrição do que eles fazem. SilpeígfcW mailO Um software que serve para visualizar e interagir com páginas web. Age como o lado do cliente em ■ comunicações na web. Um comando PHP usado para fazero output de algum i f conteúdo, como, por exemplo, texto simples ou código HTML. f instastagssão usadas para delimitar o código PHP a fimde ! j que o servidorwebsaibaque deve processá-lo e executá-lo. ^ Um arrayintemo do PHP que armazena osdados submetidos usando o método “post”. Uma linguagem de programação usadapara a criação de scripts, que são executados em um servidorweb. Todastring precisaestar dentro de umavariável. Um softwarepara enviarpáginasweb, o qual age y ' como um servidorem comunicações na web. / l _ Uma linguagem marcação usada para descrever a estrutura / do conteúdo das páginas web, que são visualizadas em um navegador web. Um nome usado para descreverasvariáveisinternas do ^ PHP que ficam acessíveis a todos os scripts. Uma série de campos de input, em uma páginaweb, usados para seobter informações dos usuários. Umafunção intema do PHP que enviamensagens de email. Um local de armazenamento, em um scriptPHP, que tem o seu próprio nome e tipo único de dados. Um tipo de armazenamento de dados em PHP que permite que várias informações sejam armazenadas em um mesmo local. você está aqui > 55
  • 91.
    2 C on e c t a n d o - s e a « M y S o L * Como Tudo se Encaixa Saber como as coisas se encaixam, antes de começar a construir, é uma boa ideia. Você criou seu primeiro script PHP e ele está funcionando bem. Mas obter os resultados obtidos em um email já não é bom o suficiente. Agora você precisa de uma forma de guardar os resultados do seu formulário, para que possa mantê-los pelo tempo que precisar e ter acesso a eles quando quiser. Um banco de dados MySQL pode armazenar estes dados para você. Mas você precisa conectar seu script PHP ao banco de dados MySQL para fazer isso acontecer. este é um novo capítulo ► 59
  • 92.
    0 formulário deOwen funciona bem. Pem até demais. Sera prediso mais do *^u€ uma xídara dc da-P e para O'uzrt donseguir se »anter a par de todos os relatos de àbdudoes o ^u e estâo dHega*do r>asua Caixa de Enteada. O novo formulário para os relatos é ótimo, mas agora estou recebendo emails demais. Não consigo beber cafeína suficiente para ler todos eles assim que os recebo. O script de Owen estava funcionando bem enquanto ele estava recebendo apenas algumas respostas, mas agora ele está recebendo centenas de emails, muito mais do que consegue organizar. Elejá apagou alguns acidentalmente, sem osler. Ealguns estão indo parar na pasta de spam, a qual ele nunca olha. Na verdade, um email que lhe interessariamuito pode está escondido na pastade spam, neste exato momento...Owen precisade uma forma para armazenar todas asmensagens, de forma que ele possaconsultá-lasquando tivertempo e encontrar facilmente aquelas relativasao seu cão Fang. Este relatório perdido mendiona um dao (doo^)... trata-se de iníorrnaçoes de ^ue 0we» pvedisa, [desesperadamente. From: safiy@gmgs-4Jstnei: Subject: AliensAüductedMe-AbductionReport *<V4obef1,200612:1129PMCDT > andwasgene To; „ SatiyJoneswasabducted3daysago m<imfeefofaliens:four descfipfion:greenwithsixmala***«---- •w did:Wejusttaikedanqpiayedwith tor1day- Humbei Wienda Whatleyd i d - C o n t a c tm s . A Owen predisa «jue mensagens domo estâ sejâm armazenadas de -forma segura em algum lugar o*de ele possa donsuiti-las, em busda de possíveis avistamewtos de Fang. É aqui que um banco de dados MySQLviria a calhar.. Caso vode na©saiba, a <*aior'sa das pessoas J prohundia /Vjy£$L soletv-âhdo as ultimas — três letv-as, ou seja, ”my ésse < ^u êele*.
  • 93.
    conectando-se ao MySQL MySQL é excelente para armazenar dados Owen realmente precisa de uma forma de armazenar osdados dos relatos de abduções em um lugar seguro, que não a sua Caixade Entrada de email. O que ele precisa é de um bancode dados, que é uma espécie de gaveta de arquivos hi-tech, arrumada e super organizada. Umavezque asinformações localizadasem um banco de dadosficam totalmente organizadas,você pode consultar a informação exata que precisar, quando precisar. Os bancos de dados são gerenciados por um programa especial, chamado servidor do banco de dados - no nosso caso, um servidor de banco de dados MySQL. Você se comunica com esse servidor usando uma linguagem que ele é capaz de entender, que no nosso caso é o SQL. O servidor do banco de dados geralmente rodajunto a um servidorweb na mesma máquina, com os dois trabalhando em conjunto na leitura e escrita de dados e na entrega de páginas web. 0 servidor web prodessâ as requisições for fS^ihas y/eb, e*edufca s£rip-fcs PHP Computador Servidor e reiema tonieúdo HTML. Navegador do Cliente 0 "SOL-1» siÿni-Piia Sèrué-tuved $uery Language de Consulta Êsb-wtwrada"). 0 M/SoL qrnicfc&ena ciados deiïtrç de tabeleis do banco de d ad o s. Banco de dados MySQL 0 servidor de bastos de dados le e ---- esdreve dados de/para o banòo de dados Osbancosde dadosMySQLsãoorganizadosem tabelas, asquaisarmazenam informações emformade linhas e colunas de dadosrelacionados.Amaioria das aplicaçõeswebusauma ou maistabelasdentro de um mesmobanco de dados, deformamaisou menosparecidacomo usardiferentespastasdentro de uma mesma gavetado armário de arquivos. 0 servidor do batóo de esdreve dados no Um bâftdo de dados pode don-ter múl-bpias -tabelas 0 bário de dados propriawewfce d,-to dom £re<uê*ò"tâ, e ârmô^^ado na lermâ de ar^tvos em u» fosto ^ viÿdoj »âs t*3o ^etessariawe^te predisa ser assW- Com osdados sobreasabduções armazenadas deformaseguraem um bancode dados MySQL,Owenpoderá analisar, daformaque quiser, todos osrelatos de pessoasque responderam “sim”à questão de seavistaramou não Fang. Elesóprecisade um pouco de código SQL para secomunicarcom oservidordo banco de dados. S Q L e u m a linguagem de consulta usada pava <jue o co rra a comunicação com um banco de dadosAiySoL. v o c ê está aqui ► 61
  • 94.
    mysql pode ajudarOwen Owen precisa de um banco de dados MySQl Então, estádecidido: osbancos de dadosMySQLsãoúteise Owen precisade um para armazenardados sobre asabduções alienígenas. Elepoderá, então, modificaroscriptreportphp paraarmazenardados na tabelei, emvezde enviá- losparasimesmo, poremail.Atabelamanterá osdados recebidossãose salvos, dando tempo a Owenpara analisá-losefiltrarpotenciaisavistamentosdeFang. Masvamos “começarpelo começo”...um banco de dados! Parase criarum banco de dados My5QL, faz-senecessário um servidor MySOLcom um softwareespecial.Arazão disso é que, ao contrário de servidoresweb,um servidorde banco de dados precisareceber instruções usando comandos SQL. Acriação< J e bcUlCPg cie dadps e tabelas M /SQ L exige com un icação com . um serV lJor M ySq L . Eu sempre ouvi dizer que a ferramenta utilizada faz toda a diferença para se fazer um trabalho direito. Como eu vou saber qual ferramenta MySQL usar para criar meu banco de dados e minhas tabelas? 0 -brmihái é urna janela <^e íomede ôusso via lihHa de domândo, onde v© de pode digitar demandes £QL~ M ySftl terminal 0we* predisa de uma -ferramenta para dHdr seus »ovos bando de dados e tabelas. 0 pbpMyAdmm e uma 0 pbpM yA dm mpbpMyAdmiH ferramenta gráfica f 6 .... ... k, bandos de dados e €m ------------------------------rtpvMún E' tabelas atvaves de «m3 V j? mtev-íade v*fe. Duas ferramentas MySQLpopulares são o terminal MySQLe o phpMyAdmin. Ambas lhe permitem executar comandos SQL para criar bancos de dados e tabelas, inserir dados, selecionar dados, etc., mas o phpMyAdmin dá um passo além, por fornecer também uma interface gráfica acessívelviaweb. Algumas empresas de web hosting incluem o phpMyAdmin como parte do seu serviço MySQLpadrão,já o terminal MySQLpode ser usado para se acessar a maioria das instalações do MySQL.
  • 95.
    conectando~se ao MySQL Você precisa ter um servidor de banco de dados MySQL instalado antes de virar esta página. E impossível ajudar Owen sem um deste! Caso vocêjá tenha um servidor de banco de dados MySQL instalado e funcionando, continue lendo. Se não, consulte o Apêndice ii e siga as instruções de instalação. Caso esteja usando um serviço de web hosting que ofereça MySQL, peça ao administrador que instale o software. Várias informações são necessárias para se acessar um servidor MySQL. Você voltará a precisar delas posteriormente, portanto, agora é uma boa hora para entendermos quais são estas informações. Marque-as após ter escrito ^informação correspondente. Localização do meuservidorMySQL (endereço IP ounome do host): /,$■ _ / CâSo tenha medo Nome de usuárioparao meubanco de dados: X2&&& este livro eaia / maos erradas, [Tl Senhaparao meubanco de dados: — ^ ^ s i n t a - s e â vontade para hão Vote predisa veriíita r esdrever a senha, •todas estas daixas. Com essas informações em mãos, só o que você precisa fazer é confirmar se o servidor está funcionando. Marque uma das caixas de verificação abaixo para confirmar que você acessou com sucesso o seu servidor MySQL. / R7Í Consigo acessaro meuservidorMySQLcom sucesso, usando o terminal MySQL. | i/| Consigo acessaromeu servidorMySQLcom sucesso, usando o phpMyAdmin. | | Consigo acessaro meuservidorMySQLcom sucesso, usando........................................ prediso veriíidar Caso tenha endontrado alguma — uma destas tres. .utra ferramenta «ue ÍW ione, esdreva o nome dela a«ui você está aqui ► 63
  • 96.
    Crie um bancode dados e uma tabela MySQL criando banco de dados e tabelas no mysql Algumas instalações do MySQLjá incluem um banco de dados. Senão for o caso da sua, você terá de criarseu próprio banco, usando o comando SQL CREATE DATABASE no terminalMySQL. Mas, primeiro, abra o terminal em umajanela de linha de comando - em geral, basta digitar mysql. Você saberá se entrou com sucesso no terminal quando o prompt de comando mudar para mysql>. Para criar o novo banco de dados para asabduções alienígenas, digite CREATE DATABASE aliendatabase;destaforma: 0 servidor My£$L geralmente apresenta uma resposta, para vote saber que o tomado -teve sutesso Quando usar o -terminal, vote deve tolotar um ponto e vírgula apos Antes de criar a tabela dentro do banco de dados, certifique-se de que o to*râ*dc- nosso novo banco está selecionado. Digite o comando USE aliendatabase; 1 File Edit Window Help PhoneHome mysql> USE aliendatabase, Database changed O código SQL usado para se criar uma tabela é um pouco mais complexo, uma vez que ele precisa dizer, exatamente, qual tipo de dados está sendo armazenado. Vamos dar uma olhada no comando SQL antes de digitá-lo no terminal: Ésfce t um tom3ndo usado para que seja triada uma nova tabela- . iens_abduction first_name varchar(30), last_name varchar.(30) , when_it_happened varchar(30), how_long varchar(30), how_many varchar(30), alien_description varchar(100) what_they_did varchar(100), fang_spotted varchar (10) other varchar(100), email varchar(50) Todos os tomândos SQL deitados no terminai MySQL devem terminar tom um ponto e vír^ula- Todo o resto são míormaçoes detalhadas sobre quais tipos de dados podem ser armazenados na tabela.
  • 97.
    conectando-se ao MySQL Para que a nova tabela sejacriada, digite o comando CREATE TABLE no terminal MySQL (ou baixe o código do comando no site www. altabooks.com .br). Após executar o comando com sucesso, aparecerá uma tabela alien s abduction novinha em folha. / resposta tt$uery 0)CU do servidor /V]y£$L iKe permita saber <y*e a tabela ■foi driada sem problemas. Asua instalação do MySQLpoderá incluir a ferramenta phpMyAdmin, a qual lhe permite acessar seus bancos de dados e tabelas graficamente. E possível usar a interface do phpMyAdmin para criarbancos e tabelas apenas com cliques do mouse ou então digitar comandos SQL diretamente, da mesma forma como no terminal MySQL. Clicando na aba SQL do phpMyAdmin, você acessa uma caixa de texto que age como o terminal MySQL. l/ode pode digitar a^yi os mesmos domandos ^ue no terminal /Vjy£$L, basta dlidar em éo para £*edutá-ios. Apos digitar o dodig© SQL, dli^ue neste botao para ídriar a tabela. Assim, aguia SQL do aplicativo phpMyAdmin oferece uma maneira para que comandos SQL sejam emitidos da mesma forma como se o terminal MySQL estivesse sendo usando. você está aqui ► 65
  • 98.
    introduzindo a instruçãoINSERT Eu tenho um banco de dados MySQL e uma tabela; agora, como eu insiro dados neles? Você usa a instrução SQL i n s e r t para inserir dados em uma tabela. A linguagem SQL fornece todo o tipo de instruções interessantes para se interagir com os bancos de dados. Uma das mais usadas é INSERT, que realiza o trabalho de criar e armazenar dados em uma tabela. Dê uma olhada na instrução abaixo, para ver como INSERT funciona. Tenha em mente que esta não é uma instrução SQL verdadeira, e sim um modelo da instrução para lhe mostrar o formato geral de INSERT. palavras- c-Kavcs INSfcRT INTO inidiam & mstrvdâo- 0 sera I O f , . £ sta p arte é uma lista dos notées das dolunâs do seu bando de dados, separados por vírgulas- i Seguem «»ais »omes de dolunas, sendo <ue «ao Ha vírgula apos os ultúmos. t a b le name {co lu n a , n o m e l O c o lu n a nom e2, d a d o s2 © “ s ) /Vfais uma ^sta parte e uma lista palaw-as-ehave dos valores e dados a do SQL, esta serem inseridos/separados a«^ui indidando vírgulas- / «ue viva© a seguir os valores para as dolwnâs- As aspas simples estao dorretas. U se-as sempre «ue estiver inserindo texto, mgsi^o gue seja a p f ^ s urn ã d te r; Como */Vf Segue» mais valores, sendo ^ue não ha vírgula apos o ul-timo- Uma das coisas mais importantes a se estes predisam vir «a mesma ordeãT^ue os nomes das dolunas. içao é que os valores, no segundo conjunto de parênteses, precisam estar na mesma ordem que os nomes das colunas. É assim que o comando INSERT sabe qual dado vai para qual coluna, ao inserir os dados.
  • 99.
    conectando-se ao MySQL A instrupão INSERT em apão Veja a seguir como uma instrução INSERT pode ser usada para que os dados das abduções na recém-criada tabela aliens_abduction sejam armazenados. Os nomes das suas tolvmas estão noprimeiro tonjun-b àt parênteses, divididos por v W â s . A ordem é importante! Os valores a serem inseridos devem ser listados exatamente na m esm a ordem que os nomes d as colunas. Bsbe e o nome da tabela na qual os dádos sendo inseridos, t HhO o nome do bando de dados. — s i © aliens abduction (first_name, last_name, - 0 0 0 when_it happened, how_long, how many, alien_description, 0 © o © what they did, fang spotted, other, email) O O © O O (1Sally' , 1 Jones', '3 dias atrás ’, T1 dia', ' quatro', O Q 'verde com seis tentáculos', 'Nós só conversamos e brincamos com cachorro' , 0 0 ’sim’, 'acho que posso ter visto seu cão.entre em contato' f © / 'sally0gregs-list.net') Os dados para dada doluna esb o no segundo tonjunto de faventcses, tambem divididos por vírgulas. Ao donírário do <ue odorre no P^Psas^ • t^ r u ^ ^ L n a o -termina«* po5 ftt© c vírgula r ar,ilo wato dentro de dod»^0 » • Tõdos estes valores dontém tex to , e não números, portanto, nos os dolodâmos todos entre aspas simples- — ^Aponte scü lápis £stes sa© os nomes das tolunâs- 2 'v A tabela aliens__abductíon encontra-se abaixo, mas ela ainda não tem quaisquer dados. Escreva os dados da abdução de Sally na tabela. Você pode escrever alguns dos dados fora da tabela, se não houver espaço dentro das células, bastando ligar com uma seta a informação à célula respectiva. aliens abduction * B ü ií r««s»ls5t Ifuiwmwfnlríí W S XvA.. J - V^ ^ S > ‘ J 1 .1 .,, í— 's- - 1 s ■ ■ > r você está aqui > 1 67
  • 100.
    soluções e nãoexistem perguntas idiotas ponteseulápis Solupão verdes dom seis "fcentâdulos A tabela aliens_abduction encontra-se abaixo, mas ela ainda não tem quaisquer dados. Escreva os dados da abdução de Sally na tabela. Você pode escrever alguns dos dados fora da tabela, se não houver espaço dentro das células, bastando ligar com uma seta a informação à célula respectiva. Mós sc donversamos e brindamos dom ui» , , « H y à jx js -iis tx ít daihom,. kxer visto o seu dao. £n-fcre em don-títo- aliens iuction last name ÍÊÊÊÍfÊíÊIHaà' ÍÉ ^ I l l p Sally Jones 3 dias a^râs 1dia 1 *v*ít'ro sim Não sei se entendi bem a diferença entre banco de dados e tabela. Ambos não fazem a mesma coisa: armazenar dados? Sim. As tabelas servem como uma forma de dividir os dados de umbanco emgrupos relacionados, para que você não acabetendo umúnico conjunto enorme de dados. Émaisou menos como adiferença entre colocar um monte de sapatos em uma mesma grande caixa e colocar cada par dentro da sua própria caixa - a caixa grande é obanco de dados, as caixas menores sãoas tabelas. Assim, os dados são armazenados emtabelas, e astabelas são armazenadas em bancos de dados. ? : O que exatamente é o terminal MySQL? Como o encontro no meu computador: Oterminal MySQL é uma técnica para se acessar umbanco de dados MySQL através de uma interface de linha de comando. Emmuitos casos, o terminal não é um programa a parte, e sim uma conexão que você estabelece usando a linha de comando de um programa terminal “genérico”,como por exemplo o aplicativo terminal do Mac OS X. 0 modo como você acessa o terminal MySQLvaria bastante, dependendo de qual sistema operacional você está usando e se o servidor MySQLestá local ou remoto (localizado emalgum outro lugar que não o seu computador). O Apêndice II apresenta mais detalhes sobre como acessar oterminal MySQL. não existem ferguntas Idiotas ? E quanto ao phpMyAdmin? Onde posso encontrá-lo? K : Aocontráriodoterminal MySQL, ophpMyAdminéuma aplicaçãowebqueperm iteacessoaumbancodedados MySQL. Trata-se, naverdade, deumaaplicaçãoPH P, motivo peloquai vocêsempreaacessaapartirdeumservidor web, emvezdeinstalá-lanoseuprópriocomputador. Muitas empresasdewebhostingoferecemophpMyAdmincomo partedoseuserviçoMySQLpadrão, portantoelepoderájá estarinstaladoparavocê. Senãoestiver, baixeeinstaleo programa,vocêmesmo. Estádisponível, gratuitamente, em www.phpmyadmin.net.Lembre-seapenasdequeeleprecisa ser instaladoemumservidorwebeconfiguradoparater acessoaosseusbancosMySQL, damesmaformacomo qualqueroutraaplicaçãoPHPeMySQL. ? Eu tenho tanto o terminal MySQL quanto o phpMyAdmin disponíveis. Qual deles eu devo usar para acessar meu banco de dados? í^ * . Essaéumaquestãopessoal. Avantagemdo phpMyAdminéquevocêpodeexplorarseusbancos dedadosetabelasvisualmente, semterdedigitar comandosSQL Issopodeser bastanteútil, casovocê tenha sefamiliarizadocomoSQLenãoqueiradigitar comandosmanualmenteparacadacoisinhaqueprecisar fazer. Entretanto, por agora, éumaboaideiaquevocê seconcentreemrealmenteentender omodode interagir comosseusdados usandocomandos SQL, e nessecaso, qualquerumadasferramentasfuncionaacontento.
  • 101.
    conectando-se ao MySQL T fe S T O R fv e Armazene um caso de abdução alienígena no seu banco de dados com uma instrução SQL INSERT Usando uma ferramenta MySQL, como o terminal MySQL ou a guia SQL do phpMyAdmin, digite uma instrução INSERT para armazenar dados de uma abdução. Como exemplo, eis aqui a instrução INSERT para a abdução de SallyJones: INSERT INTO aliens_abduction (first_name, last_name, when_it_Jnappened, how_long, how_many, alien__description, what__they_did, fang_spotted, otherr email) VALUES ('Sally', 'Jones', '3 dias atrás', '1 dia', 'quatro', ’ verde com seis tentáculos', 'Nós só conversamos e brincamos com seu cachorro', 'sim', 'Acho que posso ter visto o seu cão. Entre em contato.', 'sally@gregs-list.net1} £*edu-fca»r a instrução l^í£BRT ho terminai /VJyS^L résulta c r» » uma «ova imha de dados a ser adiebnada â -tabela a!ie*_ desdírip-tioft. Ainstrução INSERTparece ter sido executada com sucesso. Como você acha que poderíamos confirmar se os dados foram inseridos? Escreva aqui. você está aqui ► 69
  • 102.
    introduzindo a instruçãoSELECT Use SELECT para obter dados da tabela Inserir dados em uma tabela é uma tarefa relativamente fácil, mas é compreensível sentir certa apreensão caso você não tenha confirmado se os dados realmente foram parar na tabela. E mais ou menos como depositar dinheiro na sua conta de poupança, mas nunca poder visualizar o saldo. A instrução SELECT é a forma de “ver o saldo”de uma tabela em um banco de dados. Ou, dizendo propriamente, SELECT permite que você solicite os dados das colunas contidos em uma tabela. /^ós SELECT, esdreva w«a lista das doiunds dujos dados «y*er redeber j c o lu n a s U p || nome_ _ A >arte FR0M da 'wsbruça© é o mdiea a SELECT de «w ai tabela <^uere**»os sclcdioftâv" dados* As colunas fornecidas a uma instrução SELECT precisam ser separadas por vírgulas. Independente de quantas colunas houver em uma tabela, somente os dados dos nomes das colunas especificadas em SELECT são retomados. Esta instrução SELECT extrai todos os nomes e sobrenomes dos abduzidos contidos na tabela aliens abduetion: sempre e -Peito im ç ^iadao a «ma tabela espedííida, e «ao L ao ba^do de dados, de -ror**a geral. da_teJbela , A instrução SE LE C T J o S q L o Lrtém coluneis de dados d e u m a ta b e la Son>e»vte os dados referentes a estas duas dotadas sao retornados ^>or esta instv^çao SELECT. h mstrudao SE LE C T so obíem dados da tabela aliens_abdudtioh. SELECT first name/ last name FROM aliens abduction Para verificar um INSERT, você precisa de uma forma para visualizar rapidamente, todos os dados da tabela e não apenas algumas colunas. A instrução SELECT oferece um atalho voltado exatamente para isso: 0 asterisdo, ou “estrela*! < *iz- è SE LE C T fa ra obtev todos os dados de todas as doW^as da tabela- N SELECT * FROM aliens abduetion Nao t nedessirio csfedi-fidâr uma lista de dolunas, porque ^ signifida “obtenha todas elas^’
  • 103.
    conectando-se ao MySQL T fe S T O R tv e Certifique-se de que a instrução INSERT funcionou, usando SELECT para obter dados da tabela. Execute uma consulta SELECT, usando uma ferramenta MySQL, para visualizar todo o conteúdo da tabela alien s abduction. Certifique-se de que a linha de dados que acabou de inserir está aparecendo nos resultados. SELECT * FROM aliens abduction sâoasdoiuhas. A fiowJta S B iS C T revela íhiea liftKa de dados srnxsz£inêdos nè -tabela- A Quantas linhas de dados há na sua tabela?....... . você está aqui ► 71
  • 104.
    automatizando comandos SQLcom PHP É verdade, cada inserção em um banco de dados MySQL requer uma instrução INSERT. E é neste ponto que a comunicação com um banco de dados MySQL realizada simplesmente através de comandos SQL fica tediosa. É claro que há muitos benefícios ao se armazenar os dados de Owen em um banco, em vez de em emails na sua Caixa de Entrada, mas gerenciar os dados manualmente, emitindo-se instruções SQL em uma ferramenta MySQL, não é uma solução razoável. Como você acha que o problema de inserção de dados de Owen pode ser resolvido?
  • 105.
    conectando-se ao MySQL Peixe oPHPlidar com as coisas tediosas do SQL Asolução para o problema de Owen não é evitar o comando SQL, mas sim automatizar o SQL com a ajuda do PHP. O PHP possibilita a emissão de instruções SQL em um código de script que será executado no servidor, de forma que você nem sequer precisa usar uma ferramenta MySQL. Isso significa que o formulário HTML de Owen pode chamar um script PHP para lidar com a inserção dos dados no banco, sempre que novos dados forem submetidos - nada de emails, nem ferramentas SQL, nem confusões! 0 -formulário HTML $era umemdil *UCOwCnrídcbe t ] ^redisa emíão âdidionâV) mânuaWen-te, as mí<w»aç3es ao bando de dados. Ove* dria uma insbrudao SQ L INSERT, a «ual' insere os dados do email «o bando. Sem PHP, é preciso executar uma instrução SQL INSERT manual para arm azenar cada relatório de abdução no banco de dados. Com PHP, um script PHP autom aticam ente executa INSERT quando o formulário é submetido. <rphp ---- 'aiíensrool', (flrst-naE6' ia- ••. üescript^ ' ”■ %it :r4" ',x^ ■ • ^ - s t s m x s r , r » ô -formulário HTML dKama- um sdripfc PHP e pede a ele <ue adidione os dados do ■formulário ao bando. Sresult = rnysqli^que2. y(?abc< squsry) cr d-ef2rror querying dstabase.’) 0 sdript PHP dria uma instruÇao INSERT <ue insere os dados do -formulário n© bando -- nao e yrediso nenhuma intervendao de OvcrJ reporLphp v o c ê está aqui ► 7 3
  • 106.
    como o aplicativodo Owen pode usar php e mysqi 0 PHPpermite usar os dados do formulário web de Owen O PHP melhora o form ulário web de Owen ao permitir que um script envie os dados diretamente para um banco, em vez de enviá-los para o endereço de email de Owen, que teria então de inseri-los manualmente. Vamos dar uma olhada com mais detalhes no modo exato como a aplicação funciona, agora que o PHP está em ação. O Sallypreenche o formulário e clica no botão “Relatar Abdução”,para submetê-lo. As informações são enviadas para o script report .php no servidor web. Sally, ainda 'TtUrien>enhc âbdbzjdd po<r olicns oVárias pessoas continuam a submeter o formulário. 0 íovmttlávi©dô s iv ift refcrt-fh? do scvvido'*" web, qwe t subwcttdo yo* < *musuâv-io.
  • 107.
    conectando-se ao MySQL e O script re p o rt.php de Owen conecta-se a um banco de dados MySQL e insere as informações de cada formulário submetido usando instruções SQL INSERT. 0 sdrtpt report-php domunida*-SC dom o servidor M ySQL para ihSíiriV' dados «a tabela ati«ns_abdudtion do bando de dados. report.php $ tabela al'»ens_abdudtion èrmèxjtnã os relatos na íorm a de ímhas íre^ stro s) de dâdos. Owen precisa não somente de um script para colocar os dados no banco, como também de outro script para procurar e visualizar os dados. Na verdade, isso poderia servir como a página principal do seu site. O script index.php conecta-se ao banco, obtém dados sobre as abduções e os mostra a Owen. Um servidor de bando de dados e afenas um proyâm â sendo exedutado em uma máquina servidora* geralmente junto ao servidor web- index.php 0 sdript indexpbp obtem dados da tabela à!iens_abdudtioní fa rá que eles possam ser -formatados e mostrados a Owen- ^ tabeia aliens_abdudtíon serve domo ío n te de dados para o sdript index.php. e Owen podem escolher acessar os dados de muitas novas formas, o que lhe permite focar-se em encontrar seu cão Fang. você está aqui ► 75
  • 108.
    fazendo uma conexãomysq! Conecte-se ao seu banco de dados a partir do PHP Antes que um script PHP possa inserir ou obter dados de um banco MySQL, ele precisa se conectar a esse banco. Conectar-se a um banco MySQL a partir do PHP é semelhante, de muitas maneiras, a acessar o banco através de uma ferramenta MySQL e as mesmas informações são requeridas. Lembra-se das três caixas de verificação que você preencheu anteriormente, neste capítulo? Aqui vão elas novamente,junto a mais uma, que indica nome do banco de dados —escreva todas as informações, mais uma vez. Seu provedor de hospedagem de sites, ou seu webmaster, pode lhe fornecer esta informação. Ov. entao, se o seu servidor web e o seu servidor de bando de dados estiverem rodando na mesma maquina, vode pode usar a palavra "lodalhost". ^ Localização do meu servidor MySQL (endereço IP ou nome do host): ^ O Nome de usuário para o meu banco de dados:..................... ^ Senha para o meu banco de dados: Nome do meu banco de dados:...... As informações de localização do host, nome do usuário, senha e nome do banco de dados são todas requeridas para se estabelecei; uma conexão ao banco MySQL a partir de um script PHP. Uma vez feita a conexão, o script pode executar comandos SQL da mesma forma como se você os estivesse digitando manualmente' em uma ferramenta MySQL. suas próprias informa^oes serao diferentes destas. 0 nome do bando de dados «y*e vode driou anteriorm ente e aliendatabase- Se, por al^um m<rtivo, vode -tiver atribuído alburn outro nome ao seu bando, ou iiver optado por usar um bando j 3 e*isten-te, use o nome apropriado- 0 nome do bando de dados, informação nedessária para ^ue o sdript se domuni^ue dom ele, é aliendatabase- report,php $ual<^uer sdrip-t P H P <^ue a rm a z e n e obtenha dados de um bando /WyS$L- predisa, primeiramente, estabeleder uma dofiC?^o dom o bando, usándo as Quatro informâ^oes mendionadás. iduction B stes sao o bando de dados e a tabela ^ue ddabamos de driar. 0 nome da tabela^e a!iens__ abdudtion, e ele nao en-trâ em dampo a té <ue vode domede a em itir domandos £$L~
  • 109.
    conectando-se ao MySQL Insira dados com um script PHP Executar uma consulta MySQL a partir de código PHP requer que você, primeiramente estabeleça uma conexão com o banco de dados. Em seguida, você constrói a instrução (query) na forma de uma string PHP. A instrução (query) não é executada até que repasse a string para o servidor do banco de dados. Finalmente, uma vez terminado o acesso ao banco de dados, você encerra a conexão. Todas essas tarefas são executadas através de código em um script PHP. Eis um exemplo que insere uma nova linha de dados de abduções: Coned-ta-se bando de dados MySQl— £siís deve» ser os SEUS valores, e hão os de Owen- <?php $dbc = niysqli_connsct or die(’Error connecting to MySQL server.' Vote talvez- fossa i*sar lodalhost para a ■ lodaiizadão do seu banio, em vex. de w* «owe de dowmio. $q’ aery = "INSERT INTO aliens_abductian t-first^nãme', -last_name, when_it_happened, how_lang, " "how many, alien description, what_they__did, fang_spotted, other, email) " . "VALUES (’Sally’, 'Jones', '3 dias atrás', '1 dia', 'quatro', 'verde com seis tentáculos', ” ’ "Mós só conversamos e brincamos com um cachorro', 'sim', 'Acho que posso ter visto seu cão. entre em contatoj ” ■ sally@gregs-list.net’) K - CohstruS 3 in i t io (<^ery) IMSBRT do**o uma strina em dodifto pfj’P. $result = mysqli_query($dbc, $query) / ; ____ 3 _ ^ TenHa ww-to dwdado or querying database.■ , , j ^ ^ ^ ^ ^ £ bando de dados AlySQL. mysqli_clcse ($dbc) ; duplas a^w» c tawbe» do» os espa$<* antes e depois das aspas. fcstas lunçoes venerem «ue o sevt servidor web tenba ô PH* versão * .l ou adimâ- Q > E R > 0 O que você acha que cada uma destas funções no script? j / PHP está fazendo iscript? * / mysqli_connect ( ) — ^ o o 17 & W ^ --_ _ mysqli_query( ) ■ ^ ' v s AAa X !2Ua mysqli_close () f j í ) ’• '* < ? v você esíá ago/ ► 77
  • 110.
    três funções phppara conexão mysql Ur* donjwfc©atvfcí^o àt -Ç w k Ç o c s Pi+P <y*e m-tera^m dom o My$$L dowc^rá UsefwipõesPHPparafaiarcowobawodedados (ttafrimorad<A t hoe e» dia ^re-Çeve— sc wsav as -Vw^ocs Existem três funções PHP principais, usadas para que se realize a comunicação com bancos de dados MySQL: m ysqli_connect (), m ysqli_query {) e m ysqli_close (). Caso tenha percebido um padrão aí, não é coincidência - todas as funções modernas do PHP que interagem com o MySQL começam com m ysqli_ mysqli_connect ( ) Conecta-se a um banco de dados MySQL usando as quatro informações que você já viu anteriormente. mysqli_query{ ) Emite uma instrução (query) a um banco de dados MySQL, o que, frequentemente, envolve armazenar ou obter dadosde uma mysqli__close ( ) Encerra uma conexão a um banco de dados MySQL. O uso destas três funções geralmente envolve uma sequência previsível de etapas. Conecte-se a um banco de dados com a função mysqli_connect (). Forneça a localização, o nome do usuário e a senha, para obter permissão para interagir com o servidor do banco de dados MySQL. Especifique também o nome do banco, uma vez que esta é uma conexão a um banco específico. O Connectado! Crie uma query SQL e a arm azene como uma string em uma variável PHP. Para se comunicar com o servidor do banco de dados, você tem de usar comandos SQL. Por exemplo, é necessário uma instrução INSERT para que dados sejam adicionados à tabela aliens_abduction. Não há nada de especial a ser citado sobre o nome da variável que escolhermos, e um nome simples como $query funciona perfeitamente bem. Eu tenho uma grande instrução INSERT para enviar e ela está armazenada em uma variável PHP.
  • 111.
    conectando-se ao MySQL Use a variável $query com a função m ysqli_query () para falar com o servidor do banco MySQL e adicionar dados à tabela aliens._abduction. Você tem que informar à m ysqli_query () tanto o nome da conexão que criou no Passo 1quanto o nome da variável que armazena a sua consulta, do Passo 2. Emita a instrução (query) com a função mysqli_query(). Ei, adicione estes dados com INSERT naquela tabela que você tem armazenada aí. e*edu£a a sua «uery, *ue e insiru^ôo IWSfcRT para ~ adidionar dados a -tabela- i mysqli_query( ) 0 Encerre a conexão ao banco com a função mysql±_close () . Finalmente, m ysqli_close {) diz ao servidor do banco MySQL que vocêjá terminou a sua comunicação com ele. mysqli_close ( ) Este é o von»e da suü variável da do«e*ao. J . <?php Sdbc - l l l l i i l l ü l l 'data.aliensabductedme.com or die ('Error connecting to MySQL server. 1) Conexão fechada. Sc aly> der errado, isto ^ 't u„ a ^ |^s e r t «vis u»â mçnssjcm < f» i ^ êo ^ ^ vode e para xudo. íensrooi' o = "INSERT INTO a!iens_abduction (first_name, last_name, when_it_happened, how_long, ”how_many, alien_description, what_they_did, fang_spotted, other, email) ” . "VALUES ('Sally1, ’Jones', '3 days ago', '1 day’, ’four’, ’green with six tentacles', " ” 'We just talked and played with a dog', 'yes', 'I may have seen your dog. Contact me.’, ” 'sally@gregs-list.net')"; © ^ -- Sresult =llilPllii¥S{$dbc' $query) or die('Error querying database.'); £ a^ui, hós ^edha adonexao- JU-l f -i- Jliuy V^ 1U ivs^li <ueryO é a -fundão usada pel© PttP para sc do«.unidar tom o serx/idor MyS6?L 0 dodi$o armazenado «a variável ?<uery é SQL, e «ao PHP- © ü i I I § Í ($dbc) ? Vamos dar uma olhada com mais atenção em cada uma dessas funções PHP para bancos de dados, começando por m ysqli connect ()... você está aqui ► 79
  • 112.
    usando mysq!i__connect() Conecte-secomwysqli cowiectí) Parao nosso script PHP poder criar uma conexão © Monte a string da query, com o banco de dados usando a função m ysqli_ © Execute a query com mysqli_queryO. connect {), você precisará de algumas informações, Q Feche a conexão com mysqli_closeO- com as quaisjá está começando a se familiarizar. Sim, são as mesmas informações que usou anteriormente, quando trabalhou com o terminal MySQL, mais o nome do banco de dados. Seu nome de usuário e senha Você precisará ter seu próprio nome de usuário e senha para o seu próprio CtUGWl? servidor do banco de dados. Essas informações ou serão definidas por você ou lhe serão entregues pela sua empresa de hospedagem de sites, quando o MySQL for instalado. Se você configurar seu próprio MySQL, siga as instruções para criar um nome e uma senha seguros. 0 quê? O nome do banco de dados No nosso exemplo, demos ao banco o nome aliendatabase. O seu terá qualquer nome que você decida lhe dar, ou então terá o nome dado pela sua empresa de hospedagem de sites, caso ela tenha criado o banco para você. A localização do banco (um nome de domínio, um endereço IP ou localhost) Onde? No nosso exemplo, estamos usando a localização do banco (fictício) de Owen. Você precisa usar a localização do seu próprio servidor MySQL. Frequentemente, você usará localhost, caso o servidor do banco esteja na mesma máquina que o seu servidorweb. A sua empresa de web hosting poderá informar-lhe a respeito disso. Alocalização poderá ser também um endereço IP ou um nome de domínio, como por exemplo, seu servi dor.seuisp.com. A localização, o nome do usuário, a senha e o nome do banco MySQL na função m ysqli_connect {) precisam estar, todos, entre aspas. variarei para realizar A íunçã? H l/ f ou-hras è&oes ho bando de dados. A T ^ connectOJida a $dbc = mysqli_connect( 'data .aliensabduetedme .c o m ' , IPcauzaçaP, P ’owen' ' ^odaiizada© Jp a S en ta e ’aliensrool ’, do bando de , j i 1aliendatabase1); dados. £ TlPIUc uP bailCP dô' ^ áo kâ*i0 dc dados' dados com o sftings, O resultado ao se chamar a função, é uma conexão ao pçtfcaníp, V pcetem banco de dados e uma variável PHP que você pode usar j i para interagir com o banco. Avariável recebeu o nome CQlQCat ^SSclS $dbc no exemplo, mas você pode atribuir qualquer nome i n £ ° r i l l ô T r f í C aSPaS- que quiser. í Kowe do usuário-
  • 113.
    conectando-se ao MySQL r %Apowtescü lápis---------------------------------------------- Eis alguns exemplos de strings PHP para conexão a bancos de dados. Observe cada uma delas e escreva se a string vai funcionar ou não, e como consertá-la, neste caso. Adicionalmente, circule qualquer parte de código que você considere problemática. $dbc = mysqli_connect ( 'data .aliensabductedme .com', 'owen 1, ' aliertsrool1, ’alíendatabase'); $dhí3^^vcYsqlj^s&i^nect. ('data.aliensabductedme.com’, 'owen', ' aliensrool' "aliendatabase'*^ 1 1 1 ■ M H-i,,..!, .. j ..Q :‘.. .v.Y.V1 .C./.h ................................................................................................ l^Çfangisgone^ mysqli_connect(1 data. aliensabductedme. com’, ' owen' , ' aliensrool' , 'alíendatabase1); $dbc = mysqli connect (^sagalhogte-^ ’owen', 'aliensrool', 'aliendatabase'); ....M ........................................................................................................ $dbc = mysqli_connect{'data.aliensabductedme.com1, 'owen ’aliendatabase'); 0 ..... ■.......... ™ ....................................................................................................................................... ' O $dbc.^jii^gjrr^eqMTiyLTt^a^a'.<^ieIIoabduefc^dme. com', 1 owen' , 1 aliensrool' ); (roysqli_select_db ($dbc, ' aliendatabase você está aqui ► 81
  • 114.
    solução do aponte ponteseulápis Solupão Eisalguns exemplos de strings PHP para conexão a bancos de dados. Observe cada uma delas e escreva se a string vai funcionar ou não, e como consertá-la neste caso. Adicionalmente, circule qualquer parte de código que você considere problemática. $dbc = mysqli_connect{'data. aliensabductedme.com', ' owen' , ' aliensrool' , 1aliendatabase1) ; Esta. string.de done*ao íundiona. sem,problemas-. f E pvédíso úm põnt© c ’vírcjulã'a«^üi...............jtfeste livrõj êstãmos úsándó' ãspás'simptes pàrà' sttfngs' para -terminar a instrudao PHP. ptfp e reservando as aspas duplas para donsultas SQL. $dbc = mysqli_conn,ect/' data.aliensabductedme.com', 'owen', 'aliensrool', "aliendatabasenj^ J |sto nã© íuntiona, .porque.está -falando um ponto e yírgula; /s aspas duplas íu^içmarn do mesmoje ito <ue as simples. Kao e um nome muito desdritivo para uma done*ao a bando de dados. ^fangisgone^ mysqli_connect('data. aliensabductedme. com' , ' owen' , ' aliensrool' , Aliendatabase' ); jsto £undiona, çmbora ^angisgone” (''íangestádesaparedido”) não seja um bom nome para uma done%ao a bando de dados. esta nítido assumindo <^ue o servidor do bando de dados se lodaliza no mesmo dompvitador <^ue o servidor web. $dbc = mysqli_connect ( ^ ^calhostT^^owen', 'aliensrool', 'aliendatabase'); Jstp. ^n d io n a.desde. «ue o. servidor web e. o sçryidor, do bando estejam na mesma máquina-.............. Uma senha vazia para o bando de dados nao e uma boa ideia-' $dbc = mysqli_connect{'data. aliensabductedme. com' , 1 owen' , ' aliendatabase' ) ; |st© so -fundionara se vode definir uma senha em brando para o bando de dados. Nâo e uma boa ideia, mas -fundiona/ Vode sempv-e deve t e r uma senha para dada bando de dados. D ei*ar de -fora o quarto argumento requer <^ue dhame mys^|i_seledt_dbO para seledionar o bando de dados. $dbc = mysqli_connect('data.aliensabductedme.com', 'owen', ’aliensrool' ) mysqli_select_db($dbc, 'aliendatabase'); Me desdulpe, mas isto ç uma Ipe^adinha”.. Em .m ys^li^d^nedtP/. o quarto item, o nome do, bando de dados, e opdional Vode pode dei*á— lo d e ío r a da -fundão e usar m^s^li^seledt^dbO para espedi-Pidar o nome do bando. Assim, este dádigo t o mesmo ^ue se vode tivesse passado todos os quatro argumentos párâ mys^li__donnedtO.
  • 115.
    conectando-se ao MySQL Parece que poderia ser fácil estragar uma das partes da informação usada para conectar-se ao banco de dados. Porém, como eu poderei ter certeza se a conexão funcionou? // É aqui que,ar£cfftcão PHP d ie () é útil. Afunção PHPdieQ^ífnaliza o script PHP e fornece conhecimento sobre algum còcíigo que tenha falhado. Embora não revele precisamente o que houve de errado, die () nos informa que algo aconteceu e precisa ser consertado. Se houver algo de errado com uma das quatro variáveis para conexão de mysqli__connect (), ou se o servidor do banco não puder ser localizado, a função die () impede que o restante do script PHP seja executado e mostra a mensagem de erro entre parênteses. A -função dieO t soiidítada, daso a Conexão nao tenHa sido estabeíedida- Se uittâ das nc&sds ^v^rbrc strings nâ íunÇ3© wys^ii_d©nnedt não esiiver dorreta, redeberewos ^ u m â resposta sobre isso- $dbc V mysqli_connect('data.aliensabductedme.com', 'owen1, . 1aliensrool1, ’aliendatabase') or die(’ Erro ao conectar o banco de dados.'); Esta mensage» t enviada para a pagina web, das© a done*a© -PalHe. Nâo t prediso dolodar ponto e vírgula a<ui, u*»a vez. <^*e “or dieí -)Mtorresponde a, tednida**ente, dontinuaçao de uma mesnta insfaruçao. você está aqui ► 83
  • 116.
    construindo consultas nophp Sim! Uma vez feita a conexão ao banco com mysqii_connect(), você pode em itir consultas SQL diretam ente do PHP. Praticamente, tudo que pode fazer em um terminal MySQL pode também ser feito em código PHP, com a conexão ao banco que acabou de ser estabelecido. E essa conexão que disponibiliza um canal de comunicação entre um script PHP e um banco de dados MySQL. Por exemplo, agora que Owen tem uma conexão ao seu banco, ele pode começar a inserir dados na tabela alien s abduction com a função m ysqli_query () e algum código de consulta SQL. L -C ftibve— scjnosso objetivo c automatizar esta ^uery (HSBRj u s ã n c l otcÁop P f f P . A «uery SQL é passada para swys^ii^ueryO domo u m a s tr m $ P H P • Afunção m ysqli_query () precisa ter uma 1 query SQL armazenada em uma string PHP ($query) para executar a inserção dos dados, abduções alienígenas. ^ _______
  • 117.
    conectando-se ao MySQL Construaa queryINSERT no PHP As query SQL, em PHP, são representadas como strings e costuma-se armazenar a query em uma string antes de passá-la para a função m ysqli_ query (). Uma vez que as consultas SQL podem ser razoavelmente grandes, frequentemente é necessário construí-las a partir de strings menores, que se estendem por várias linhas de código. A query INSERT de Owen é um bom exemplo disso: Correct««yg com wysqli_jconnaetQ. Monte a string da query. o o D Execute a consulta com mysqii_queryO. Feche a conexão com mysqlLcloseO- ^ —£sta e umd varilvel string do PHP,^ue agora armazjend a ^uevy INSERT. = "INSERT INTO aliens abduction (first name, last name, 0 ponto iihai diz. a© PHP para jw ta r esta siring do«* a >ue vier nâ linHa seguinte- ^ "when_it_happened, how__long, how_many, alien_description, " . "what_they_did, fang_spotted, other, email) " . "VALUES {'Sally1, 'Jones', '3 dias atrás' , ’1 dia', 'quatro', " . ’ "verde com seis tentáculos', 'Nós só conversamos e brincamos com um cachorro', " . "'sim1 , 'Acho que posso ter visto seu cão. Entre em contato.', "1sally@gregs-list. net' )" | | Uma vez. < Y *e tudo isto é dódigo PHP, e prediso -Tinâlizi— io tom ponto e vírgula. ^ string de donsulta se divide e» várias linhas, para to m a -la »«ais legível —os pontos íinâis instvu«»* oPHP 3 transíorw iar tu d o isto em u»a unida string- Com a query insert armazenada em uma string, a mesma estará pronta para ser transferida via função m ysqli query (). existem 1 * Por que um INSERT feito em um banco é chamado de query? 0 termo “query” não significa que nós estamos pedindo alguma coisa ao banco de dados? Sim, “query” significa que algo está sendo requisitando... você está pedindo ao banco que faça alguma coisa. Nas aplicações de bancos de dados MySQL, o termo “query” é genérico, referindo-se a qualquer comando SQL que seja executado, incluindo tanto o armazenamento quanío a obtenção de dados. Fer^untas idiotas 7 * Por que a instrução INSERT não é criada como uma única string gigante? Tenha em mente que a instrução INSERT é armazenada como uma única string gigante, mesmo que tenha sido criada a partir de várias strings menores,j ideal seria que a instrução INSEl fosse programada como uma únrç string. Mas, assim como várias instruções SQL, INSERT é bastar longa e não cabe em uma linha “normal” de código. Assim, ela é mais fácil de ler se programada como strings menores, conectadas por pontos finais. ^ * É realmente necessário listar os nomes das colunas ao se fazer um INSERT?^ pode omitir os nomes das colunas na instrução INSERT. Nesse caso, terá de fornecer valores para todas as colunas da tabela, na mesma ordeiji em que aparecem na estrutura da tabela. Tendo isso em mente em geral é mais seguro e mais conveniente especificar os nomes das colunas. você está aqui > 85
  • 118.
    a função mysqli_queryO ConsulteobancodedadosMySQL comPHP A função m ysqli_query () precisa de duas informações para executar uma query: uma conexão ao banco e uma string de query SQL. -Conecte«ve com mysqlr^connegtQ. -Monte Q-sjyÍRg-éa-^Bcry. — Execute a cõrvsulta"com mysqIi__query()T^ ^ Feche a conexão com mysqli_closeO. !>ííh 'S ' conexâo__ao_jDanco, consulta) Esiâ e uma do*exao <uejá íoi esèabeledida,^ aíraves da -fundão m ys*^!i_donnctfcí)• A conexão requerida pela função m ysqli_query () foi retomada para você por m y sq li_ co n n ect (). Caso isso tudo esteja um pouco difícil de visualizar, eis o código que estabeleceu a conexão: Esta i a <uery SQL será realizada- aquela arw>32XPiâm oS C m uma sirwty Lembre-se, estas variáveis serão di-fereivies «o seu propv-i© bando de dados. í j | j ^ G i j= mysqli_connect (1 data.aliensabductedme . con or die(r Erro ao conectar ao servidor mysql.T) ; A tont^èo dobô«êo dc dados ja íoi armazenada, na variável fdbd- Assim, você tem uma conexão ao banco ($dbc) e uma query SQL ($query). Só o que falta é repassã-los para a função m y sq li_ q u e ry (). ix '" ' A <Htery P ÍffiB S l|Í($ d b c f $query) ; 'owen', 'aliensrool', 'aliendatabase') or die('Error querying database.') j w tenf^èo 3o 0 resul-fcado da <^*ery batóo de dados. Uma ^lieiy SQL corresponde a unia re q u is iç ã o e s c rita e fll C PcR go SQL, <jue é enVIada a < ? setVidpr d9 banco d e d a d o s. Este código mostra que ou solicitar a função m ysqli_query {) não corresponde a, apenas, uma comunicação de uma só via. A função responde a você, retomando uma informação que é armazenada na variável $ re s u lt. Mas nenhum dado é realmente retornado a partir da consulta INSERT - a variável Sresult apenas registra a informação referente ao sucesso - ou não - da query emitida por mysqli. A íunçãp in>;sc [l?_c jiieryOrequerumacpnexãQ apbancode dadpse umasttlngde <juery para e x e c u t a r u m a c o n s u lta . S Q L .
  • 119.
    conectando-se ao MySQL e - -Mcnta q string da query. Encerre sua conexão com mysqlLcloseO Uma vez que só estamos interessados em executar a instrução INSERT simples, a interação com o banco está terminada, pelo menos no que concerne ao nosso script. E, ao terminar de usar uma conexão ao banco, feche-a. As conexões se fecham sozinhas quando o usuário fecha a página, porém, assim como fechar uma porta no mundo real, é um bom hábito tomar a iniciativa de fechar as conexões quando tiver terminado de usá-las. A função PHP m ysqli_ d o s e () realiza essa tarefa. conexâo_ao_banco) ; vode i« U a a friável às done%ão, utilizada para interagir tom obârtdo de d a d e s . No caso do script de Owen, precisamos executar a m y sq li_ clo se () e informar qual é a conexão a ser fechada, informação essa que se encontra armazenada na variável $dbc. Esta variável ârma«r,a uma wíev&dia ^ a -foi firiada por »ys«sli_ |f($dbc) ; totonttiO !â atrás, guando a donexão +oi aberta pela primeira vez. -gxeeute a consulta eetyi my^U_qwpyQ. Feche a conexão com mysqli_closeQ^ É u m U ?m t ó b r t9 Çeciat a C 0Tiexâ° a um banco de dadps M y S Q jL a p o s terminar de usa-lp. Mas se as conexões aos bancos se fecham automaticamente, por que se dar ao trabalho de fechá-las de forma manuaJ? Os servidores de bancos de dados só dispõem de um certo número de conexões disponíveis por vez, portanto, elas precisam ser preservadas tanto quanto for possível. E quando você fecha uma conexão, isso libera o recurso para que uma nova conexão possa ser criada. Se estiver em um banco de dados compartilhado, apenas cinco conexões poderão ser alocadas para você, por exemplo. E, à medida que você for criando novas aplicações que usem bancos de dados, tenha certeza que quererá manter o maior estoque possível de conexões disponíveis. você bstá aqui ► 87
  • 120.
    não existem perguntasidiotas e pontos de bala nãp existem P e r g u n t a s i d i o t a s 1 - Você não poderia, simplesmente, colocar todo o código SQL diretamente na função mysqli_ query (),em vez de na variável $query? P^_: Seria possível, mas ficaria muito bagunçado. É mais fácil gerenciar o seu código quando você armazena suas queries em variáveis, e depois usa essas variáveis na função mysqli_query ( ) . ? : 0 código que referencia a consulta INSERT deveria estar fazendo algo com o resultado? Talvez sim. Até aqui, estivemos usando die() para finalizar um script e enviar uma mensagem ao navegador caso algo de errado acontecesse. Chegará um momento em que você poderá querer fornecer mais informações ao usuário quando a query não tiver sucesso, nesse caso, você pode usar o resultado da query para determinar o sucesso desta. PONTOS DE BALA As conexões a bancos de dados precisam de uma localização, um nome de usuário, uma senha e um nome do banco. Afunção mysqli_connect () cria uma conexão entre o seu script PHP e o servidor do banco de dados MySQL. Afunção die () finaliza o script e retoma uma mensagem caso a sua conexão falhe. Para se executar uma query SQL a partir de código PHP, você constrói a query em uma string e depois a executa com uma chamada a mysqli_query { ) . Chame a função mysqli_close {) para fechar uma conexão ao banco MySQL, a partir do PHP, quando tiver terminado de usá-la. RQ
  • 121.
    conectando-se ao MySQL 0 P e jst O r iv e Modifique o código do script report.php de forma que, em vez de enviar os dados por email para Owen, eles sejam inseridos no banco de dados MySQL. Depois, teste as modificações que você fez. Remova a parte do código do script report .php que envia os dados para Owen. No lugar, coloque o código que inicia a conexão ao seu banco de dados MySQL, construa uma query SQL como uma string PHP, execute a query no banco de dados e depois encerre a conexão. _____ Eis o K O V Odódi^o PHP em ‘V*« vimos -b-abalhando. Mac tolo^uc as "tags <?pHp ?> cm veport-php, «*m a vez. < ^u e esta adidiona»d© este toáiop a um pcm-to no s£ri|H; ^ c já se endonira den-tvo das -ta^s- ? a - ,O M e n '' o£ die('EC-C-r connecting M y S 2 _ . * - ■ ■ t n = E R - IN -0alier.5abduction (first_nair.e, " ■ h o wior.i, .h o ._ m .w y , . "K h,t>ey>d, i-V Pa-te-3dfar;-^" 'I ^ ’< * « “ -«■. " • 1 1 1&aily@grsgs-liSt ,r.et ) / ^ r e s u l t .=m y s q l i . q u e r v t S d b C , i q u e r y )_ o rd i e1 ' E r r o rq u e r y i n gd s t a D & = e . J , f f l y s q i i _ c i o s el - S d b c ); Envie o novo report. php para o seu servidor web e depois abra a página report. html em um navegador para acessar o formulário “Relatar uma Abdução”. Preencha o formulário e clique no botão “Relatar Abdução” para armazenar os dados no banco. Agora, inicie a sua ferramenta MySQL e realize uma query SELECT para visualizar as modificações feitas no banco. Isto está correto? Escreva abaixo sevocê acha que é isto que o script deveria estar f^zeiído, e por quê. . í a J < . ' J J í í ^J j . a 7 .-. à . ’j v M X . .................................. você está aqui ► 89
  • 122.
    use $__POSTna queryINSERT Espere um minuto. Esse trabalho todo que estamos fazendo não é com o objetivo de pegar dados diretamente do formulário e armazená-los no banco? Parece que a consulta está inserindo os mesmos dados, não importa o que tenha sido digitado no formulário. Não estou vendo nenhuma automação com este script PHP. Isto é um grande problema. A consulta INSERT precisa inserir os dados do formulário, e não strings estáticas. A query que construímos consiste de strings definidas diretamente no código, e não de strings resultantes do texto que foi digitado no formulário. Para que o script funcione com o formulário, precisamos fazer com que os dados digitados sejam colocados dentro da string de query. mysqli_query() fcstes dados do íoTmulávio prctisan» iv pâra àtrfcco dS 0 -forwulavio e a -Ponte dos dados -e-Wenies aos «relatos de abduções Qual código PHP poderia nos ajudar a enviar os valores do formulário de Owen para dentro da query i n s e r t ?
  • 123.
    conectando-se ao MySQL *~POST fornece os dados do formulário A boa notícia é que o script re p o rt .php já tM n o 's c ia cíctsh form ulário armazenados em variáveis, graças a^rperglobal $_POST. Você lem bra deste código PHP? $name = $_POST['firstname' ] . ' ' . $_POST['lastnameT $when_it_happened = $_POST['whenithappened' $how__long = $_POST [1 howlong1]; $how_many = $_POST [' howxnany1]; $alien_description = $_POST['aliendescription' ] $what_they_did = $_POST['whattheydid' $fang_spotted = $_POST[’fangspotted1] $email = $_POST[1 email']; $other = $ POST [’ other '] ■ ; L1UI 1 A superglobal ?__P0£Tjá esèá sendo usada pava esvair os dados de dada dampo do -rormulari© de t para inseri— |©s em variáveis. Le»brs-sC) o nome <ue vode usar para fJPÜST predisa ser o mesmo do dampo dorrespondente, *o •formulário ttTMl— Assim, vocêjá tem os dados do formulário e só precisa incorporá-los na instrução INSERT . Mas é preciso fazer uma pequena modificação, primeiro. Agora que você não está mais enviando os dados por email, não precisa da variável $nam e. Você ainda precisa do nome e do sobrenome do usuário, para que o relato possa ser adicionado ao banco de dados - mas precisa tê-los em variáveis separadas. 0 nome e o sobrenome do wuario agora sao armazenados em variáveis $last name = $ POST ['lastname'] ; .separadas, |>arâ ^ue possam s e r inseridos em dolunas di-Perentes da tabela aliens__abdud£ion. $first name = $ POST['firstname' ] ; Escreva o código PHP para criar a string de query i n s e r t armazenada na variável $query, certificando-se de que ela esteja armazenando os dados do formulário na tabela a l i e n s a b d u c tio n , ao ser executada. ............ . a j.s .t .^ y > ? ; Lú.r í.^ r ^ r -.e .f. ..... é * y.V.ÉL.y..E.S. C. ..1 }Í Íà&.-t .* > . w ò>v5... f. você está aqui > 91
  • 124.
    aspas simples eduplas no php Escreva o código PHP para criar a string de query i n s e r t armazenada na variável $query, certificando-se de que ela esteja armazenando os dados do formulário na tabela aliens^abduction, ao ser executada. S o L u ção Os nomes das dolun3s aparedem «a instrução exatamente domo antes fquery —“INS&RTIKT0 aliehs^abdudtion (-firstjriame, last^name, wKen^it^bappened, Kowjon«^ w "Kow^many, alien^desdription, what^they^did, -Canc^spotted, other, email) w. w //lLUES (lf-first_nan*e,, Vlast_name t*v/hen_it_bappened,) 'fhov/_Joh^, 'fh^TSnãfP^" w?alien_desdription >'fv;Viat__they_jiid', l?-Pan^_spotted,) '/other, 'femailOw ; £m vez. de dados estitidos sobre a ^ ^ abdução de Sally Jones, ajora *cs_y A ordem das variáveis predisa ser a mesma dos inserimos os dados que o usuário nomes das dolunas, f ara que os dados seja» distou no -formulário- armazenados nas dolunas dorretas da tabela- na°e x i s t e m Eu tenho mesmo que criar todas essas variáveis para armazenar os dados de $_POST? Não posso, simplesmente, referenciar os dados de $_POST diretamentejao^çntro da string $query? ?car Pode. Não háflad£Tque lhe impeça de $__POST diretamente em uma query. Porém, é um bom hábito de programação isolar os dados do formulário antes de fazer qualquer coisa com eies. Iss acontece devido ao fato de ser relativamente comum a necessidade de processar os dados de alguma forma, antes de inseri-los no bansoJ&texemplo, existem técnicas inteligentes qufhackers^>odem usar para “sequestrar” suas query, dignando aados perigosos no formulário. Você verá como evitar tais ataques no Capítulo 6. Para manter a simplicidade, neste capítulo não fazemos nenhum processamento nos dados, mas isso não significa que não deva adquirir o hábito de ^armazenar os dados do formulário nas suas próprias • / varáveis antes de colocá-los em uma query. / T . 1 - Faz alguma-difgrença usar aspas-sfmples ou dupias? Posso usar aspas simples em torno de toda a consulta, e aspas duplas em torno de cada variável? tomo das variáveis. 0 motivo é que o PHP trata as strings de forma diferente, dependendo da fornia como elas aparecem: dentro de aspas simples ou duplas. Adiferença é que as aspas simples representam exatamente o texto contido nelas, enquanto, ao se fazer uso das aspas duplas, significa que há algum processamento adicional no texto quando se usam aspas duplas. Esse prõcessamento resulta nofato,de que os valores das variáveis colocadas dentro de aspas duplas são mostradas em strings, no lugar do nome da variável. Isso é bastante útil, e é por isso que as aspas duplas geralmente são preferidas para-se criar strings de query SQL. Não seria possível criar strings de query simplesmente concatenando-se as variáveis com o código SQ L? Í ^ I Sim, e se você decidir usar esse método, certamente poderá usar aspas simples em vez das duplas. Mas as strings de query já tendem a ser bagunçadas por natureza, de modo que tudo o que puder fazer para torná-las mais legíveis é bom - inserir variáveis diretamente em uma string dentro de aspas duplas, em vez de as concatená-las com aspas simples, definitivamente torna as strings mais fáceis de serem entendidas. Sim, faz diferença. E não, você não pode usar aspas simples em torno da query inteira, com aspas duplas em
  • 125.
    conectando-se ao t> . Vamosusar tudo o que já aprendemos para terminar o script PHP de Owen, para que ele possa armazenar com sucesso os dados sobre as abduções em um banco de dados. Escreva abaixo o código PHP necessário para completar Oscript report. php. <?php $when_it_happened = $_PQST [ 'whenithappened' ]; $how_long = $ POST ['howlor.ç']; $how^many ' = = $_POST['howmany1]; ■ $alien_description = $_POST[raliendescription’]; $whàt_they_did = $_POST[1 .whattheydid’1; $fang_spotted = $_POST['fançspotted'] $email = $_POST['email']; $other = $_PGST['other']; $query = "INSERT INTO aiíens_abduction (first_n-ame, last_name, 'when_i.t_happened, how__lcng, " . ”how_aany, alien_description, what_they_diã,.- fang__spotted, other, email) " - "VALUES ('$first_name1, '$last_nam.e 1 '$when_it_happene.d', '$how_iong', '$how__many' , " . ”'$alien_description 1, 1?.what_they_did' , '$rang_spotted1, ' ■'$other1, '$emaii')"; $result = echo .1Thanks for submitting the fom.cbr />'; echo You were abducted ' . ’ $when_it_happened; echo ’ and were gone, for ' . $how_long . '<br ■/>'; echo 'Number ' o f aliens: ' ■ . $how_m.any . '<br />’; echo 'Describe them: 1 $alien_description . '<br />'; echo 'The aliens did this: ' . $what_they_did . '<br />'; echo 'Was Fang'there? ' . Sfang_spotted . '<br />'; . echo 'Other comments: 1 . $othsr . 1<br ■/ > ' ; echo 'Your email. address is ' . $eii>ail; $dbc = ?> você está aqui ► 93
  • 126.
    C O o 4 cicio ~ Lx e R c ic io Vamos usar tudo o que já aprendemos para terminar o script PHP de Owen, O rti .c ã o Para c 'ue e'e P°ssa armazenar com sucesso os dados sobre as abduções em unr| [jarico çjg dados Escreva abaixo o código PHP necessário para completar Oscript report .php. As novas variáveis armazém* o nome c o sobrenome do usuário, do jei-fco ele digitou no formulário. <3: f-^rst^name — fmP0STrClfirstn3me> J; flast_na»e — f^P OSTClastramel', Vode predisa se donedtâr ao bando de dados e fomeder as informações nedessárias antes de realizar quaisquer donsultas £$L a partir do PHP. A query e donstruída domo uma string PHP- Certifique— se de usar os dados extraídos dos dampos do formulário- $when_it_happened = $_?OST['whenithappened']; $how_long = $_POST[’howlong' ] ; $how_many = 5_P0ST['howmany']; $alien_description = $_POST['aliendescription' ] $what_they_did = $_POST[1 whattheydid1 ]; $fang_spotted = $__POST [1fangspotted']; $email = $__POST ['email1]; $other = $_POST[1other 1]; $dbc = m ysq|i_donnedt^da^ Siensabdud^dme d o m V w e n , 'aiiewrool', 'alienda^UbaseO or dieC E rror donnedting to MySfiJL server/)^ Squery = "INSERT INTO a!iens_abdu.ction (first_name, last_name, when_it_happened, how long, "how_many, alien_descriptionr what_they_did, fang_spotted, other, email) ” . "VALUES (’$first_name' , '$last_name' , '$when_it_happened', '$how_long1, '$how many', " . $alien_description’, '$what_they_did', '5fang spotted', '$other', '$email')"; or dieC&rror querying database-0; ri»ys«íIit_it1 osçÇfdb^^i txedute a query ao bando de dados - isto e o que insere os dadosf ■i--—...... ■ 1 .....'•....... •-...... FedHe a dcmexao a© bando. echo ’Thanks for submitting the form.cbr />'; echo 'You were abducted ' . $when_it happened; echo ' and were gone for ' . $how long . ’<br />'; echo 'Number of aliens; ' . $how_many . ’<br />'; echo 'Describe them: 1 . $alien_description . '<br />'; echo 'The aliens did this: ' . $what they did . '<br />'; echo 'Was Fang there? ' . $fang_spotted . 1<br />'; echo 'Other comments: ' . $other . '<br />'; echo 'Your email address is ' . $email; Confirme se o formulário foi submetido dom sudesso, da mes*»a forma torno fazia no sdript antigo-
  • 127.
    conectando-se ao MySQL T fe S T O R fv e Modifique o script de Owen de forma a usar os dados do formulário para fazer um INSERT. Remova a variável $name do script r e p o rt .php, adicione as variáveis $first_name e $l a s t name e modifique $query para usar as variáveis do formulário, em vez de texto estático na instrução INSERT. Envie a nova versão dò script para o servidor e teste-o, submetendo o formulário da página r e p o r t .html algumas vezes, digitando dados diferentes a cada vez. U your ett« i gddltg? W taH d k litfeâp p eo? How long were you fln» yvany ywSBfc? Describe tbem: ; "V Ç liaílüdtheydotoyou? Bave you sten my dog ^Abducted M e . j hm v k * * * d l i k e te n te d I » 4 ' ^a -L s s t W i a i t : Yes « No 0 ïïsr.— «Wœüarday 0 B s e e , ““W tattan: First n&tre LAstaame: *8A b d t I C :W t u ui s y w i F C f t t S f i v f a l K S S ? Whendklithappen? H a w tag«rey « ig o n e ? H*nf»aBydMyous e e ? Describe them: W JkfltdMtfeeydotoyoa? Hftre jou x a my dog F«ng? N a d e r ;alftvÇSte»eyTíaU gr< ; J d c f e d m ta b o u t U f O r « $ < j S a e e r * Yes Q No 0 Anything<3s&yoo warnto add? feUpO^AMtfCPOTV^ Agora, use sua ferramenta MySQL para executar um SELECT e visualizar o conteúdo da tabela aliens abduetion. Os novos reUt»S de àbdudoes aparedem na tabela, exatamente domo vodê esperaí Hi uma linha extra de dados para Sally Jones, que lo i dolodada antes de «ode donsertar a donsuH ÍKSÊRT. Não se preodupe, vode aprendera domo remover dados indesejados no proximo dapitulo. você está aqui ► 95
  • 128.
    adicionando WHERE noseu SELECT Owen precisa de ajuda para peneirar seus dados O novo e aprimorado script r e p o rt .php está fazendo o seu trabalho, automatizando o processo de adicionar relatos de abduções ao banco de dados. Owen pode relaxar e esperar que os relatórios cheguem... exceto pelo fato de que há um novo problema. Receber mais dados não está, exatamente, tornando mais fácil selecionar os relatos que representem um potencial avistamento de Fang. Eu realmente estou feliz, agora que tenho um banco de dados sendo automaticamente preenchido com os relatos de abduções submetidos pelos usuários. Mas isso nao está ajudando a isolar os relatos que poderiam me ajudar a encontrar Fang. Owen precisa de uma forma para localizar dados específicos, como por exemplo, as abduções nas quais Fang foi avistado. Você sabe qual coluna do banco contém as informações em questão: f ang sp o tte d . Esta coluna contém yes (sim) ou no (não), dependendo do fato de o abduzido ter relatado se viu Fang - ou não. Assim, o que precisa é de uma forma de selecionar apenas os relatos da tabela a lie n s abd u ctio n que tenham um valor yes na coluna fan g _ sp o tted . Você sabe que a seguinte query SQL retorna todos os dados da tabela: SELECT * FROM aliens_abduction A instrução SQL SELECT lhe permite incluir uma cláusula para controlar os dados retornados pela query. Trata-se de WHERE, e com ela você diz exatamente como quer filtrar os resultados da consulta. No caso de Owen, isso significa selecionar apenas os relatos de abduções onde a coluna f an g _ sp o tte d seja igual a yes. L-e»bre-sc> se* a dausula WHERE* s—isto -Çârã do» <ue "todos os dados JL da -tabela seja» selediohados. SELECT * FROM aliens__abduction WHERE ---- ---------------- - . ------------------ 0 valor da dolwa fredisa ser deímido, f>ara «ue os dados fossam ser — -v seledtonados. fang_spotted = 1 yes1 0 home da doluna Esta farte da donsulla SELECT permanede a m es»>a a clausula WHERE duida dc ■Pil-trar os resuüâdos. Esta eiiusula reduz, o volume de dados rfbor»ados feia ^uevy, indlumdo afenas os dados e» <»e a dolu^a sfo^ttcd esteja de-fmida dow»o yes-
  • 129.
    conectando-se ao MySQL T fe S T O ro v e Teste a consulta s e le c t com uma cláusula w here para encontrar ciados específicos. Use ama consulta SELECT com uma cláusula WHERE na sua ferramenta MySQL para procurar por dados de abduções que envolvam, especificamente, avistamentos de Fang. Todos estes (rcejistv-os te»» â doluna fan^sfotted defmida to»© yes. ””” você está aqui ► 97
  • 130.
    banco de dadosmysql do owen está funcionando Owen sai em busca de Fang Graças ao PHP e às suas funções que fazem interface com o MySQL, o servidor de banco de dados MySQL de Owen está recebendo os dados das abduções a p artir de um formulário HTML e os está armazenando em uma tabela do banco. Os dados ficam guardados de forma segura na tabela, até que Owen tenha a oportunidade de peneirá-los. E, quando está pronto para fazê-lo, basta uma simples query SELECT para isolar os relatos de abduções que, potencialmente, envolvam Fang.
  • 131.
    conectando-se ao MySQL --------ÊÊÊEHk :v iu i w flyÉ V — Mesmo que você ainda não tenha organizado tudo, ligue cada componente HTML, PHP e MySQL ao que você acha que ele faz. alfendatabase tabela clliens__at*ííuctioTi se-WíclPt Veb serVicI°í de kmco de dad^S My-SQj kptão Sutnilt (sutmeter) i w ^ ___ mys^lLcpnnectO mys^lLcloseO Kiys^lijjueryO mys^l!_select_dt>() _ Este é o código SQL que o script PHP informa ao servidor MySQL. Isto executa os scripts PHP e retorna páginas HTML para os navegadores, / ' frequentemente se comunicando com um / banco de dados no processo. O nome do banco de dados que contém a tabela aliens_abduction. O formulário HTML usa este método de requisição para enviar os dados do formulário para um script PHP. E aqui que os dados do formulário report .html acabam sendo armazenados. E aqui que Owen coleta os dados do usuário. Esta função PHP encerra a conexão ao servidor MySQL. Este é o nome do script PHP de Owen que processa os dados que os usuários digitam no formulário report.html. Esta função PHP envia uma query para o "servidor MySQL. Este elemento HTML é usado pelos visitantes do site quando eles terminam de preencher o formulário. Este é outro nome para o software que roda o MySQL e todos os bancos de dados e tabelas que ele contém. Esta função PHP opcional diz ao servidor qual banco de dados usar. Isto abre uma conexão entre o script PHP e o servidor MySQL, para que eles possam se comunicar. você está aqui ► 99
  • 132.
    quem faz oque solução Mesmo que você ainda não tenha organizado tudo, ligue cada componente HTML, PHP e MySQL ao que você acha que ele faz. Este é o código SQL que o script PHP informa ao servidor MySQL. Isto executa os scripts PHP e retoma páginas HTML para os navegadores, frequentemente se comunicando com um banco de dados no processo. O nome do banco de dados que contém a tabela a lie n s_ a b d u c tio n . O formulário HTML usa este método de requisição para enviar os dados do formulário para um script PHP E aqui que os dados do formulário report.htm l acabam sendo armazenados. E aqui que Owen coleta os dados do usuário. Esta função PHP encerra a conexão ao servidor MySQL. Este é o nome do script PHP de Owen que processa os dados que os usuários digitam no formulário report.html. Esta função PHP envia uma query para o servidor MySQL. Este elemento HTML é usado pelos visitantes do site quando eles terminam de preencher o formulário. Este é outro nome para o software que roda o MySQL e todos os bancos de dados e tabelas que ele contém. Esta função PHP opcional diz ao servidor qual banco de dados usar. Isto abre uma conexão entre o script PHP e o servidor MySQL, para que eles possam se comunicar.
  • 135.
    crie e preenchaum banco de dados 3 Críe e Preencha umBhuicç»deDados Criando os Seus PrópriosDados Nem sempre você tem os dados de que precisa. Às vezes, você mesmo tem que criar o s dados que pretende usar. E, outras vezes, você precisa cria ra s tabelas que irão armazenar esses dados. E, ainda, você precisa criar o banco que armazenará os dados que você precisa criar. Confuso? Você não ficará. Prepare-se para aprender como criar seus próprios bancos de dados e tabelas. E se isso não for o suficiente, você ainda criará, no processo, a sua primeira aplicação combinando PHP e MySQL. você está aqui ► 103
  • 136.
    precisa-se do aplicativolista de email A loja Elvis está aberta Elmer Priestley abriu uma loja especializada em produtos Elvis, QueroSerElvis.com (makemeelvis. com). A demanda tem sido enorme. Elejá vendeu um monte de temos de poliéster, muitas costeletas falsas e centenas de pares de óculos. Cada vez que alguém compra algo, Elmer coleta um novo endereço de email. Ele os utiliza para enviar avisos sobre promoções na sua loja. Da forma como está agora, Elmer tem que copiar, manualmente, cada endereço da sua lista e depois colar um por um nos seus emails promocionais. Funciona, mas demanda muito tempo e esforço. £l»ev> o ih«yuestio*aveí Rei da © K iSm e de Elvis fVcsl«Y- EUev ja doletou VUè eísdere^os / " de emâil ate o wíowe^to) e 3 tada dia the^a*» **ais- ■Joffe ^evvsom e G arcia P'ZZa Com R yan M cK ïj Isto está demorando muito. Eu preferiria passar o meu tempo imitando Elvis, e não enviando emails manualmente. ^..G ^sim uduck-con-i Amanda aman21uv@breakneckpizza. Ed e d 9 9 @ b 0 tt0 m s u p .c o m Roundtree Jo-Ann joioroi Briggs Chris cbrig __ v”* Harte Lloyd hovei^<art@breakneckpiz2a.com Toth Anne AnneToth@ieapinlimos.com Wiley Andrew andrewwiley@objectvilie.net Palumbo T'"r~ palofinine@rnightygumball.net angrypirate@breakneckpizza.com ctay@siarbuzzcoffee.com annmeeker@chocohoiic-inc.com bp@fioney-doit.com am86@objeciviiie.net debmonster@breakneckpizza.com janistedesco@starbuzzcoffee.com vikt@starbuzzcoffee.com szwedjoe@objectvilie.net sheridi@mightygumball.net snowman@tikibeanlounge.com giennO O 9S@objectviile.net anneh@ bO ttO m sup.com nobigdea!@star‘- irpa”— ’' ' com com Elr«ev esdreve cste entail e fiofia e cola £ada endeve^o no Êâmpo “7© *. Tom Aianna nney Clay Meeker Ann Powers Brian Manson Anne Mandei Debra Tedesco Janis Taiwar Vikram Szwed Joe Sheridan Diana Snow Edward Otto Gienn Hardy Anne Deal Mary Jagel Ann Melfi James Oliver Lee Parker Anne Ricci Peter Grace Zelda Clifford Joyce Anne Lindy Fred Anne eckp iz2 :acom R eno A icss Day So/ger e< u rji e°l/ing G ares Jacobs l,ver@ M /e ;9 .r,suPco^ r>cZep@ Sta^ S o T a'C O m l !tr!a n m ikibe^eeco^ £ g £ t * * 2 ^ C W @ S ^ c o m l0yce@ cho^ck^.c o m anneb/uni@ fa r 'c‘'0ccom Te 9 9 @ ^SZ Z e-nef "; S t * f e c f c - ' ' fGrande promoção Caros Elvismaníacos, Grande promoção esta semana em Makemeelvis.com'. Costeletas de pêlo de cavalo genuíno com 20% de desconto! E não se esqueçam da promoção "compre um e leve outro de graça" para os ternos d e > poliéster - só dura irais três dias! fcsias fessoas estao *a lista d« e»ails de £Uev e ^ueirenr» a sua ajuda fava í tarr «** ^ouio mâis ^âiríiida^ fconx Êlvis- Elmer está passando tempo demais copiando e colando emails no campo “To” do seu programa de email. Ele deseja simplificar a tarefa de adicionar novos endereços e de enviar emails em massa.
  • 137.
    crie e preenchaum banco de dados Élwer precisa de uma aplicacão Uma aplicação é um software elaborado para atender a um determinado propósito dos seus usuários. Elmer precisa de uma aplicação que mantenha o registro da sua lista de endereços de email e que lhe permita enviar emails para a5 pessoas da lista clicando apenas em um botão. Eis a forma como ele quer que funcione: Uma aplicação Web é um site dinâmico elaborado pata atender a um determinado proposfto dog seus usuári9s. Ir até uma página web e digitar uma mensagem de email. E f Clicar em um botão Submit na página, e a mensagem ser automaticamente enviada para toda a lista de "QueroSerEIvis.com". Jyy Fazer com que a lista de emails cresça sozinha.^ permitindo que novos clientes se cadastrem através de um formulário web. Com essa lista de necessidades que a aplicação precisa atender, Elmer pode visualizá-la em detalhes... Esta fârte de ew »aiU sc ^arete bastante d o w » a apl'tdatao Abdução Alienígena de 0*>en» »as ' a di-ferença a<w é a lista de emails de El^ev ivi cresder sozjnVtâ) e^ as suas w»ensa^ews se>rao enviadas para a lista inteira 0 obetWo da ;lmcv t > Q A aplicação web QueroSerElvis.com {MakeMeElvis.com) consiste de dois componentes principais: um formulário para enviar mensagem de email para as pessoas na lista de Elmer e um formulário para permitir que novos clientes se inscrevam na lista. Com esses dois formulários em mente, faça um esboço de projeto para a aplicação de Elmer. você está aqui ► 105
  • 138.
    design do nossoaplicativo lista de email Visualize o projeto da aplicapão de Elmer Sempre é útil visualizar o projeto de uma aplicação antes de mergulhar nos detalhes do desenvolvimento. Isso implica descobrir quais páginas e scripts estarão envolvidos, com o eles se conectam e, talvez o mais importante, como você irá armazenar os dados no banco MySQL. Estas pessoas esta© «a lista de emails de Elmer e redebem o* e— »ails que ele envia ?ara a lista- Esta tow>bina^a° de iW Jario /sd ri^ «we os u s v i a r i ô sse insdrevam l. I _ J - V .) Àt> Este sdvipt pffp ChV,a a #«ensa^eft, de etnáil Este e o íormulirio web que Elmer preervdKe para driar e enviar um email para A lista de enderedos a lista- de email de Elmer -fida armazenada em uma tabela de um bando de dados que roda em um servidor de bandos My£$L. MËH1É3 l i f t É S l * » ......... Jon Matthews ionathan@wishiwaseivis.com Wendy Weriitz wwer@starbuzzcoffee.com Joe Bob Franklin 2ksdgi@gre9s-|istnet
  • 139.
    crie e preenchaum banco de dados Então, por onde começamos a criar uma aplicação com PHP e MySQL? Será que nós escrevemos o script PHP primeiro e depois criamos a tabela para armazenar os dados? Ou será que devemos criar a tabela primeiro e depois o script? Joe: Não entendo que diferença faz. Nós vamos precisar da tabela e do script para a aplicação funcionar. Frank: Isso é verdade, mas acho que nós devemos escrever o script primeiro, para podermos testar o código PHP antes de conectá-lo ao banco de dados. Jill: Mas o script PHP é completamente dependente do banco de dados. Será difícil testar o script se não tivermos um banco ao qual ele possa se conectar. Frank: Será que não poderíamos criar o script e omitir apenas a parte específica do código que faz a conexão com o banco? Poderíamos fazer tudo exceto interagir realmente com o banco de dados. Isso ainda seria útil, certo? Joe: Não necessariamente. Lembre-se, o único trabalho do script é selecionar os dados digitados em um formulário HTML e colocã-los em um banco. Ou, se a função for enviar emails para uma lista, o script lê os dados do banco e gera uma mensagem de email para cada usuário. De uma forma ou de outra, o banco é essencial para o script. Jill: E verdade, mas ainda nem começamos a pensar no formulário HTML. Onde ele se encaixa nisto tudo? Estou achando que precisamos criar o banco de dados antes de sequer pensarmos em escrever o script. Frank: E isso! Primeiro criamos o formulário HTML, depois analisamos que tipos de dados vão ser colocados no banco e, feito isso, nós finalizamos tudo com o script. Joe: Não sei se isso realmente faz sentido. Como podemos criar um formulário HTML se não temos 100% de certeza de que tipo de dados precisamos obter do usuário? Jill:Joe está certo. O formulário HTML ainda^aps leva de volta ao problema de precisarmos saber quais serão os tipos de dados usados fl^a aplicação. Os dados comandam tudo, A Cantão nós provavelm ente deveiyagjos criajfo banco de d ados e a tabela prim eiro, depois o form ulário HTML e, finalm engp, o script qüerearge a^uBmissão dò lormulãrlTYÍ1 Frank: Gostei. Vamos fazer isso! Joe: Eu ainda acho que nós, provavelmente, precisaríamos elaborar os passos específicos de como esta aplicação será montada... Escrevaabaixo ospassos específicos que você acha que serão necessários para ir do projeto até a implementação de QueroSerElvis.com.
  • 140.
    planejando a aplicação PLANEJEANTES Nós realmente precisamos de um plano para montar a aplicação de Elmer. Passo-a-passo, nós podemos nos concentrar em uma coisa de cada vez, sem que fiquemos sobrecarregados. Criar um banco de dados e uma tabela para a lista de emails. Esta tabela irá armazenar os nomes, sobrenomes e endereços de email de todos os inscritos na lista de Elmer. elvis store O Criar um formulário web e um script PHP Adicionar Email para inserir novos clientes à lista. Aqui, nós criaremos um formulário e um script que permitirão ao cliente digitar seu nome, sobrenome e endereço de email, e então adicioná-los à lista. addemail.html O Criar um formulário web e um script PHP Enviar Email para enviar emails para a lista. Finalmente, iremos criar um formulário web que permitirá a Elmer compor uma mensagem de email e, o que é mais importante, um script que enviará esta mensagem para todos os nomes inscritos na tabela da lista de emails. 'sendemail.php sendemail.html
  • 141.
    crie e preenchaum banco de dados Tudo comepa com uwa tabela Na verdade, tudo começa com um banco de dados, que é basicamente um Container para o armazenamento de dados.Jã vimos, no capítulo anterior, o modo como os bancos de dados são divididos internamente em mais containers, chamados tabelas. Assim como os dias e semanas em um calendário, a tabela se compõe de colunas e linhas de dados. As colunas consistem de um tipo específico de dados, como por exemplo “nome”, “sobrenome” e “email”.As linhassão conjuntos de colunas em que uma linha consiste de um elemento de cada uma das colunas. Um exemplo de linha seria “Wendy, Werlitz, wwer@ starbuzzcofee.com.” c a le n d á rio Um banco de dados 4 um container usado para armazenar dados, de íprma bastante estruturada. ■(A foS tolwW i 1 2 fllllilll 3 ilíílüliííílímm 6 M .. 7 3 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 20 2 1 -------------_l j Ambas estas -y estvuWas dados sa© tabelas. Em geral, todas as tabelas de um banco de dados tem alguma relação umas com as outras, mesmo que essa associação às vezes seja superficial. E comum uma aplicação web consistir de várias tabelas conectadas umas às outras por meio dos seus dados. Mas todas as tabelas ainda são feitas de colunas e linhas. Uw» bando de dados, «w e c iXm a li^a As tabelas armazenam dados segu!nd9 um padrão de cçlunas e linhas. ^> ov scvvidosr — uaiKts r n í Esias sao as AoJunas. J^nse no bando de dados domo um doniainer «ue armazena m-forw>a^oes. Ou-tv-a tabeia Ainda ou-tsra -tabela não existem Terguntas idiotas T * * Onde os dados do banco são realmente armazenados? É possível ver os arquivos? 1 ^ * Os dados de um banco geralmente são armazenados em um disco rígido. E, embora você certamente possa vê-los, eles não lhe diriam muita coisa. Os arquivos de bancos de dados são binários, e não podem simplesmente ser abertos e ter suas informações visualizadas. É por isso que temos SQL- para permitir que nós olhemos o conteúdo do banco e interajamos com os dados armazenados dentro dele. você está aqui ► 109
  • 142.
    CRIE seu bancode dados Faça contato com o servidor MySQL O projeto da aplicação de Elmer exige um banco de dados e uma tabela. A maior parte do trabalho cotidiano com um banco de dados envolve a interação com tabelas, mas você não pode simplesmente sair criando tabelas sem criar, primeiro, um banco onde elas fiquem armazenadas. CREATE DATABASE é o comando SQL usado para se criar um banco de dados. Uma vez feito isso, você pode então criar uma tabela com o comando CREATE TABLE. Mas antes de usar qualquer um desses comandos, você tem de se conectar ao seu servidor de bancos de dados MySQL. Você fez isso no capítulo anterior e precisou de algumas informações importantes. Uma íerramehia /HySßCJ1 Como o terminal permite qttC voie se fcmedte â um servidor A •ßornedehdo uma de usuário e uma senha válidos. Além de permitirem que um script PHP se conecte ao banco de dados e realize ações nele, a localização, o nome de usuário e a senha do banco são a chave para que o terminal MySQL ou o phpMyAdmin sejam utilizados. E essas ferramentas são bastante úteis para que realizemos os primeiros passos da aplicação: a criação do banco e da tabela. Já que a criação de um banco de dados e de uma tabela para a aplicação de Elmer é uma tabela que só só precisa ser realizada uma vez, faz sentido usar uma consulta SQL para criá-los manualmente. Portanto, inicie sua ferramenta MySQL preferida e prepare- se para realizar o primeiro passo na elaboração da aplicação de Elmer, criando um banco de dados e uma tabela para a lista de emails. VoC* esti aqui. Crie um banco de dados euma tabelo para a lista de emails, Crie um formulário web e um script PHP "Adicionar Email" para adicionar novos clientes à listà. Crie um formulário web e um script PHP "Enviar Email" para enviar um email para a Iista.
  • 143.
    crie e preenchaum banco de dados Crieuw banco dedados para os emails deElmer Para criar uma nova tabela e um novo banco para a lista de emails de Elmer, primeiro nós temos de criar o banco de dados elvis store, o qual irá armazenar a tabela email list. Nós usaremos comandos SQL para criar ambos. O comando SQL usado para criar um banco de dados é CREATE DATABASE, que você usou, rapidamente, no capítulo anterior. Vamos dar uma olhada mais detalhada no seu funcionamento. 0 nowe do ftovo nome do banco ba*to de dados à sev* eviado É preciso especificar o nome do novo banco de dados após o comando CREATE DATABASE. Eis a instrução SQL para criar o banco de dados de Elmer: CREATE DATABASE elvis store Quando você executar esta instrução em um servidor MySQL, o banco será criado. I File Edit Window Help Don’tBeCruel mysql> CREATE DATABASE elvis_store;^ Query OK, 1 row affected (0.01 sec) CheAtb d a t a b a s e é o oonjEuiJo S q L u s a J o p g ra se ctícií um íipVp kcUlco J e click's. Ao e*edu±ar C o a d o s SQ L *0 ■èev-minai, vote sempre adiòona W » po«*to-e-viVg^ia ao -Pinai... mas nêo tuâ»do -pi^cr donsui-bs SQL â tw é s da -função PHP »ys^íi^ucv-yO. elvis store Criar o banco de dados elvis store com o comando CREATE DATABASE resulta em um banco de dados novinho em folha, mas ainda não há uma tabela para armazenar os dados... N 0 banò© de dados £oi triado, mas ele «ao pode a r^ a ^ a r dados se hão Houver u»a -tabela. V e jÊ tW n ! As instruções SQL só terminam em ponto* e-vírgula quando você usa o term inal. No seu código PHP, as suas instruções SQL não precisam terminar em ponto-e-vírgula. O terminal MySQL é diferente, porém, e requer o ponto-e- vírgula ao final de cada instrução SQL. Isso ocorre porque o terminal é capaz de rodar múltiplas instruções SQL, enquanto que, no PHP, você só pode submeter uma instrução por vez. você está aqui ► 111
  • 144.
    agora CRIE suatabela Crie uma tabela dentro do banco de dados Você precisa saber qual tipo de ciados deseja armazenar na tabela, antes de criá-la. Elmer deseja usar o nome e o sobrenome das pessoas da sua lista de email, para tomar um pouco mais pessoais as mensagens que irá enviar. Adicionando a essas informações o endereço de email, a tabela e m a il_ lis t de Elmer terá de armazenar três informações para cada entrada. Cada informação de uma tabela fica em uma coluna, que precisa ter um nome que descreva os dados. Vamos usar f irst_ n am e (“primeiro nome”), last_nam e (“sobrenome”) e em ail como o nome das nossas colunas. Cada linha da tabela consiste de uma única informação para cada uma dessas colunas, e constitui uma única entrada na lista de emails de Elmer. 0 veiho arquivo de te*to de £imer> dontendo o senderedos ^ Cwâil, hão se doiwpara £,o mS estrutura e a segurança de w«a _____ bela de bando de dados Jon Mãtttews _________ Wendy _ ______ vjwer^starbyz^oW «^^_-*_ Joe ÇobJFraWklm_______ _ 2 J^^^r^"-Jist net__- eirna'»l_J'»st C“»â das »uitas tabelas < ^ue pode** ser armazenadas no bando de dados elvis store- store « rsfrü ú í» "! last name7! l i i i i i l l i i Ä l i l i i i i i i Jon Matthews ionathan@wishiwaselvis.com Wendy Werlitz wwer@starbuzzcoffee.com 1 — 1 Joe Bob Franklin 2ksdaiiaiflregs-list.net î tstas sao dolunds- ^ Kossa tabela tem très. fc&âs sao linKas. Cada < “*> iontô» „„ ^ sobrenome e un, enderedo de e»*aif de pessoa. mailinglist.txt As HnLas Ja tabela s ã 9 W iz ^ r tta S s e as colunas sã° V e rtic a is . Então, agora nós sabemos que o primeiro nome, o sobrenome e o endereço de email do cliente precisam ser criados como colunas na tabela e m a il_ lis t. O problema é que as tabelas do MySQL são altamente estruturadas e esperam que você forneça mais do que apenas o nome da coluna. Você precisa informar ao banco de dados um pouco mais sobre que tipo de dados você pretende armazenar na coluna. Colwrvâs de dados na nova tabela erraiMist de £Uer.
  • 145.
    crie e preenchaum banco de d» Precisamos definir os nossos dados Quando você cria uma tabela, precisa informar ao servidor MySQL qual o tipo de dados que cada coluna terá. A definição do üpo de dados é exigida para todas as colunas MySQL, e cada coluna de uma tabela armazena um tipo particular de dados. Isso significa que algumas colunas poderão conter texto, algumas poderão conter valores numéricos, algumas poderão conter horas ou datas, e assim por diante. O MySQL possui uma série de tipos de dados, e você precisa saber qual tipo corresponde aos seus dados específicos. Vamos supor que Elmer tenha uma tabela chamada p ro d u c ts (“produtos”), que registra os itens à venda na sua loja: ^ i'' ■M ) E sta doluna lon-téi» desíi-idScs textuais Ar ^ í mr»cro «da prcAM da loja de f dílada f*-odufc V .3«> « W '- p ro d u c ts ® Ü i .. product .• . ... in v e rt« ,- ■ H I I'.IfiTvMI 1 Blue Suede Shoes 24 59.00 2 Polvester Pants with Sequins 16 23.50 3 Stick-On Sideburns 93 1.99 -------------- 4 Elvis wig 7 48.00 Ntfaiero I n t e i r o ■ i Blue Suede Shoes Polyester Pants with Sequins Stick-On Sideburns Elvis wig A , • ÍTN ,A * A yvite CyreÇO J ft doluna IP tortßm valeves de iden-b+itaeao twbe» valors úm idos pava «da pvodup da loja. Texto Repare que p ro d u e té a única coluna de texto na tabela p ro d u cts. Há também números decimais para p ric e , e números inteiros para in v e n to ry e id. O MySQL tem os seus próprios nomes para cada um desses tipos de dados, bem como alguns outros, como por exemplo para datas e horas. E importante usar os tipos de dados apropriados ao se criar colunas, para que as suas tabelas sejam precisas e eficientes. Por exemplo, dados do tipo texto ocupam mais espaço do que números inteiros; assim, se uma coluna só precisa armazenar números inteiros, é uma prática inteligente usar o tipo de dados inteiro para ela. Além disso, se o servidor web souber qual tipo de dados uma determinada coluna armazena, ele não permitirá que você, acidentalmente, insira o tipo de dado errado. Assim, em uma coluna definida para armazenar datas, você receberá um erro se tentar inserir qualquer coisa que não seja uma data, nessa coluna. 24 16 93 Numero Inteiro Pata Vpoô pteoîsa sabeï IFh J set atmS c z & n ad< >>W-c£Ula*eoïui)a Jatabela. W E R Por que você acha que usar diferentes tipos de dados é melhor do que usar apenas texto, para armazenar tudo? você está aqui ► 113
  • 146.
    & < A s mysql frequentementeusados alguns tipos de dados MySQL Estes são alguns dos tipos de dados mais úteis do MySQL. Lembre-se, você pode usar qualquer um deles para descrever os dados armazenados dentro de uma determinada coluna da tabela. A função desses tipos é armazenar os seus dados sem criar,cpnfusões. f f Vcttm»CHARACTER. Ela €rí^da t preíére ^ue os seus dados íenbam w* íamanh© deíinido. Ela pode sev aliamen'te eíidienie se voíe ^ivet- al^um ix%bo < ^« e iehhâ sempre a mesma exèensao. p E C ,> e v 'a ^ °^ c lKe Wctcv-á W ôs tasas defr«*»* T e vote prediz» ?*‘0 jde ian-to for ID A TÍTM V3nto p.eu man'tem o registro da daía e da hora- / MRCHMj abreviação de ^R iô b le ^^fl^a tie r (Varadter variavel"). Efe^armâjyina dados em modo •texto- E -flexível e dapaz. de se adaftâv a extensa© dos seus dadosj arma^na^do apenas o *^*e vote predisâ; sem preendKer ladunas dom espaços em brando- JNT^ IKTSÇBR asK an u e olTnumeros devem sev hvteíros, mas na© "tem medo de números ne$a£iv©s. Eje e dapaz-, também, de âvmárenôr números mteivos , çe^enos^dwjo daso é dhamado de ‘TfX//(X/-T Dependendo da sua versão do My£$L, a extensa© pode ser de Z55 darad-teres anies da versão 5.0.3, e a-te darad-teres ná versa© 5 e adima. Ele se fib a m a ^i3 - Ele $osta * ^andes quantidades de dados binários- Uma boa am)0 < BLOB, esid^TB^Kl cia é exdelen-te í " armazienar grandes <wa«-tidades de "texto —murt© mais do <^e O iM ou VMOMR- (PATEVan-tém registro dâTsías datas. Ela não se interessa pilas boras, porem- ESa itjt . ? A nrma jemea, 3o dontrario tíe(á> «3o se importa dom as datas
  • 147.
    crie e preenchaum banco de dados nq.9 existem perguntas Idiptas 1 - Por que eu usaria CHAR, se V A R C H A R faz a mesma coisa, com mais flexibilidade? A resposta está na precisão e na eficiência. Do ponto de vista do projeto, você deve sempre projetar suas tabelas de forma a modelar os seus dados o mais rigidamente possível. Se você souber, sem sombra de dúvida, que uma coluna para armazenar a sigla dos estados irá sempre armazenar exatamente uma abreviatura composta de duas letras, então faz sentido permitir apenas dois caracteres de espaço para ela, com CHAR { 2). Entretartto, se por exemplo uma coluna para senhas puder conter até 10 caracteres, então VARCHAR (10) faz mais sentido. Esse é o ponto de vista do projeto. Assim, CHAR é um pouco mais eficiente do que VARCHAR, porque ele não precisa se preocupar com a variação de tamanho dos dados. Assim, é mais desejável usar quando você sabe, com certeza, que uma coluna de texto terá uma extensão fixa. 1 - Por que eu preciso desses tipos numéricos, como IN T e D E C ? Trata-se do armazenamento e eficiência do banco de dados. Escolher o melhor tipo de dados para cada coluna da sua tabela reduz o tamanho desta, e torna mais rápidas as operações feitas nos seus dados. Armazenar um número como número propriamente (INT, DEC, etc.), em vez de caracteres de texto, em geral é mais eficiente. f É só isso? Esses são todos os tipos? Não, mas estes são os mais comumente usados. Nós praticaremos com estes por agora, em vez de complicar as coisas incluindo tipos de dados que, talvez, você nunca vá precisar. VARCHAR(60) CHAR(2 ) DATETIME DEC (10,2) U P R 9 P Q 5 ÍT Q Ligue cada tipo de dados MySQL à descrição dos dados que você poderia armazenar em uma tabela. Desctiçãp ,,-Seu nome completo. ma abreviatura de estado, com duas letras, reço de uma peruca do Elvis: 48.99 J^uanto dinheiro rendeu o disco mais vendido de Elvis. ata da abdução alienígena: 2/12/2004 Número de costeletas do Elvis em estoque: 93 Você viu o cachorro de Owen? S ou N Seu en d ereço d e em ail que horas você janta Quantos aliens você viu quando foi abduzido uando foi que Elvis nasceu você está aqui ► 115
  • 148.
    qual o meupropósito? solução U PR9 P9 SfTQ Ligue cada tipo de dados MySQL à descrição dos dados que você poderia armazenar em uma tabela. Kao é nedessário. Embora íundione para a abreviatura de estado, CHAR(2J t uma opçao melhor, porque geralmente é um poudo mais eíidiente. de Dados DATE TIME ■ VÃReHAfi-{- DEC (4,2 VARCHAR(60 CHAR(2) DATETIME DEC (10,2) DEC 3eralmente é usado para armazenar preços, além de outros valoves dedimãis. guando o tamanho de um valer de texto puder variar, l/ARCHAR c uma boa opção. Faça-o iom ^o o suíidiente para armazenar *ual<uer valor < ^ u ealguém predise armazenar. Descrição ó^uándo v©de souber exatamente quantos daradteres esperar em uma doluna, use CHAR- Seu nome completo. Uma abreviatura de estado, com duas letras. Preço de uma peruca do Elvis: 48.99 Quanto dinheiro rendeu o disco mais vendido de Elvis. Data da abdução alienígena: 2/12/2004 Número de costeletas do Elvis em estoque: 93 Você viu o cachorro de Owen? S ou N — Seu endereço de email A que horas vocêjanta Quantos aliens você viu quando foi abduzido Quando foi que Elvis nasceu /K / Estes dois numeroS mostvam ^uântos dúytos o ba*£o dc dados deve esperar nd frente do deí-i*^ t quantos depois. V o tepode -ter respondido DATE a*ui, mas os Elvismaníádos verdadeiros sabem a data e a hora exatas. Podem Haver outras (t Potendialmente melhores) 4-ormas de se representar um valor sim/«ao n o/VlySáJL do < ^ u e usando CHARO), mas esta -forma é simples e, razoavelmente, eíidiente
  • 149.
    crie e preenchaum banco de dados Crie sua tabela com uma consulta Já temos todos os pedaços de que precisamos para criar nossa tabela, inclusive um bom nome (email_list). Também temos nomes para as colunas de dados: first_name, last_name e email. Só o que falta são os tipos de dados para cada coluna, bem como uma instrução SQL parajuntar tudo isso e criar a tabela. O comando SQL para criar sua tabela é CREATE TABLE. Ele começa com CREATE TABLE seguido do nome da sua tabela. Os nomes de todas as colunas vem entre parênteses, separados por vírgula e seguidos, cada um, de um tipo de dados. Eis como seria o comando: Si», a'mda estamos a^ui.» »as estamos «uase prontos fa^a vLf seguir adiante- Q Crie um banco de dados e uma V tabela para a lista de emails. Q Crie uni formulário web e um script PHP "Adicionar Email" para adicionar novos clientes à lista. 0 Crie um;formulário web e um script PHP "Enviar Email" para, enviar umemail para a lista. kT 0 nomt da tabela m J È Ê Ê A nome_da_tat,ela 0 nome da dolu^a ) nome_da_colunal t±po_da_colunal, nome_da_coluna2 t±po_da_coluna2, K y 0 tipo de dados da Coluna /o à wao predisa nomear suas tabelas e doluwas do» um undersdore separando as palavras, mas c uma boa ideia se rna«ter dohsistente em relaçao a «ual«uer donver^âo de nomearão <ue dedidir usar- Mais doiunâs, se «edessario 0 c o m a n d o S Q L C R E A T E T A B L E é u s a d p p a ta <jue seja cilada uma nWatabela era um banco de dados. Aponte seu lápis Escreva uma query SQL para criar a tabela email_ list de Elmer com as três colunas de dados requeridas: first n a i t i e ,last name e email. CÍ€flu.e.. .....V A R c M ft f e íâ h . s : L ^ à ... V ô A Q m £ © p 1 . &r.sãi. — -J- ■ ■ ■ /...... você está aqui ► 117
  • 150.
    test-drive suas queriesCREATE - t^ponte seu lápis-------------------------------------- Q n l l i p õ n Escreva uma query SQL para criar a tabela e m a il_ ^ l i s t de Elmer com as três colunas de dados requeridas: f ir s t _ n a m e , la s t _ n a m e e e m a il. £ste c o to*nèndo SdJL. pav-a criar a tabela - repare nãs letras »aiusduias. r ) ___o *ome da sua tabela deve t o r em L eaiita ba‘»*a e deve te r um wvderscore CREAT6 TABLE «.ail list » lu3a'r a' ts?a^ s' 0 parentese ............................................... ............................................... de abertura *--------- ( abre a lista de ................................................................................................ dolunas a serem -Pirst_na«*e /ARCttAR(2^))> ér~ ~ ^ vírgula separa as tolunas tríadas- ”/ serâo tria das- last_wame VARCHAR(2£ ), éz: email V b K C m ttO ) ‘...............V ’” " ................................ isto diz. ao /V|y£^L nuCa toU a /) a i ^ ^ ' V c . o iifo de dados t e t ................... = » : < u * u a ............... œ l o « * * « 1« » a lista das ‘V* 05 ürattww. ° ^ ^ 40 toiunas. endereços de email O R f V e Crie o banco de dados e a tabela de Elmer. Execute as queries CREATE DATABASE e CREATE TABLE usando uma ferramenta MySQL para criar o banco de dados e lv is _ s to r e e a tabela e m a il_ lis t dentro dele. CREATE DATABASE elvis_3tore CREATE TABLE email_list (first_name VARCHAR(20 ), last_name VARCHAR(20) , email VARCHAR(60) ) Ambas as queries foram executadas sem problemas? Caso contrário, escreva aqui o que-você acha que podje ter dado errado. . .......í . p^fr' ^ •
  • 151.
    crie e preenchaum banco de dados Espere aí, tem algo de errado aqui. Eu digitei o código para criar a tabela exatamente da forma como estava escrito... e agora estou recebendo uma mensagem de erro esquisita. File Edit Window Help Oops A ívvs-bruçâo CREATE TABLE e s t a OK m as o -fccvWiha} M y £ $ L «âo sabe em bando de dados a iabcla csta sendo triada-. isso nSc c bom v Elmer csta fvcodupado por^uc a sua inytvuiao CREATE TABLE M fcr-fcita e, W C S nnOassim, ©ievmina! My£$L &íã vclaíahdo um trro- mysql> CREATE TABLE email_list ^ = 5^ ( fxrst_name VARCHAR(20), last_name VARCHAR(20), email VARCHAR(60) ) ; ERROR 1046 (3D000): No database selected ^ al^um motivo, a insfaru^ao CREATE TABLE íalbou w> terminal MyS$L. a tabela do *,aMC0 de dados Colocando o oarro na frente do9 bois Elmer tem um problema que tem a ver com o fato de que o terminal mySOL não sabe, automaticamente, a qual banco você está se referindo ao emitir comandos. É claro que ele sabe que você acabou de criar o banco de dados e lv is s to re , mas poderia haver diversos outros bancos de dados armazenados no mesmo servidor - ele não pode simplesmente assumir que você está se referindo àquele que acabou de criar. Felizmente, existe uma solução simples, que envolve informar ao terminal MySQL qual banco de dados você quer que seja o alvo de todas as instruções subsequentes... na° existem p e r g u n ta s Id io t a s Qual é a desse promptesquisito ->que eu às vezes vejo no terminal MySQL? 0 prompt -> indica que você está digitando uma mesma instrução ao longo de várias linhas - o MySQL está basicamente lhe dizendo que sabe que você ainda está digitando a mesma instrução, mesmo que você tenha pressionado Enter para separá-la em mais de uma linha. Uma vez que você termine a instrução e coloque o ponto-e-vírgula no final, o MySQL irá executá-la. você está aqui ► 119
  • 152.
    não esq ueça do com ando U S E ! SELECIONE o banco dedados antes deusá-lo Para que a instrução CREATE TABLE funcione, Elmer precisa selecionar o banco de dados no terminal MySQL, para que este saiba a qual banco de dados pertence a nova tabela. O comando U S E escolhe um banco de dados como sendo o padrão no terminal, o que significa que todos os comandos subsequentes irão se aplicar a esse banco de dados. Funciona desta maneira: 0 tomando USE m-forma ao MyS$L <i*a! bane© de dados vote pretende usar. r . ■ I nome do banco 0 comando USE selecfona um banco d e d a d p s c o m o o p a d r ã o p a t a insítuçoes SQL s u ts e c p e ti te s . Elmer deve especificar o nome do seu banco de dados (elvis_store) em uma instrução USE para selecioná-lo e acessar a sua nova tabela. USE elvis store Home do bando d e dados vott ***€r setedicnar do» USE- e1vis _ j sightings 0 doma*d© USE esdolhe o baháo d edados do«, o «^ai vodc d e se jatrabalhar. elvis_lyrics elvis_fans Wma vez. vode tenha esdolhido un> bando de dados para usar, os demais bandos dc dados do servidor sao ignorados - â it ^ue vodê esdolha seiedionar um outro bândo de dados.
  • 153.
    T fe ST O R fV G ------------------------------ crie e preencha um banco de dados ; .v Execute USE primeiro para depois criar a tabela. Execute a consulta USE em uma ferramenta MySQL, para selecionar o banco de dados elvis_store de Elmer e depois execute a query CREATE TABLE para criar a tabela email_ l i s t dentro do banco. USE elvis_store CREATE TABLE email list (first name VARCHAR(20) , last_name VARCHAR (20) ,email VARCHAR(60) ) A instrvção USE *ao « «efiessaria daso vod£ esteja usando uma -ferramenta S ^L 9 ™ -«da, fcomo o fbfMyAdm'm - nesse daso, vote ira selecionar o bando ^raiitamehte, antes de emitir os tomáwiw ■ I File Edit W indovj/^elp LisaMarie mysql> USE elvis_store; Database changed mysql> CREATE TABLE email list ( first__name VARCHAR(20) , last_name VARCHAR(20), email VARCHAR(60) Your SQL query has been executed successfully (Query took 0.4481 sec) A 0 código para a triaça© da tabela e o mesmo de antes —só era prefiiso seletionâr o bando para que -fuhdionasse. Com o bando de dados seledionado atrâves do dom3ndo USE, a triaiac da tabela, a^ora, edorre sew. problemas- você está aqui ► 121
  • 154.
    o comando DESCRIBE Opa!A minha instrução CREATE TABLE tinha um erro de digitação, mas foi executada mesmo assim. O SQL tem uma opção "desfazer"? Não há exatam ente uma opção desfazer no SQL, mas certam ente é possível consertar erros. Entretanto, você precisa, primeiramente, descobrir exatamente que tipo de erro foi cometido, para consertá-lo. Suponha que a tabela ema i 1 1 is te se pareça com o seguinte: e m a il l i s t fcrst_name last name Circule o que você acha que há de errado com esta tabela. Algumaideia sobre como consertá-la? ''V
  • 155.
    ( J ? 0O ' c / } I cr/e e preencha um banco de dados PESCRI0E revela a estrutura das tabelas Para consertar um erro em uma tabela, é preciso, primeiro, achar o erro. Mesmo que você não suspeite que haja um, nunca é uma má ideia verificar o seu trabalhp^0~ contagio SQL DESCRIBE analisa a estrutura de uma tabela, exibjuídSuma lista^a.nomes de colunas, tipos de dados e outras informações. ome_da_tabela na tabela de Elmer, teremos a seguinte instrução SQL: Usando DESCRIBE email list Est« e o »on*« dô tábefa Cuja desdriçao Queremos ver. Em «field" (‘‘Campo'*) voôe Cfttonira OS nomes de dada tolunâ- 1 File Edil Window Help Graceland mysql> DESCRIBE email_list; +--- -------------I - --------:---------+--------+------+------------ +--------- + | Field I Type i Null I Key | Default t Extra | + ___________+----------------- +--------+ ------ +------------+ --------- + | first_naem | varchar(30) j YES I I NULL 1 I t last_name | varchar{30) |YES ! INULL I I | email i varchar^60) iYES | jNULL 1 I 3 rows in set^O.02 sec^Sv vote Pm Jype ("T ifo ” ) v, ve os iipos de dados ^ue defihimos f ara tadâ Coluna. • 0 que são aquelas outras colunas: Null (Nulo), Key (Chave), Default (Padrão) e Extra? 0 MySQL lhe permite definir uma série de opções para cada coluna da sua tabela. Essas opções controlam opções como, por exemplo, se uma coluna pode ser deixada em branco ou se ela terá umvalor padrão. Nós vamos explorar isso um pouco mais adiante, quando essasopções se tomarem maisvitais para a aplicação. 0 nao -faz. distinção entre maiusdulas e mihusdulas no < ^u e se venere às palavras reservadas, tomo os tipos de dados; por isso, vode poderá, às ve«s, ve-!os esdriios em minÚsdulas. n09 existem p e r g u n ta s Id io t a s r ■ Se eu já tivesse dados armazenados na minha tabela, eles teriam aparecido aqui? í ^ : Não. DESCRIBE só lhe mostra a estrutura da tabela, e não os dados armazenados nela. Mas não se preocupe, você logo verá os dados da sua tabela... mas primeiro temos de aprender como inserir esses dados nela. P Eu posso visualizar a mesma estrutura usando o phpMyAdmin? Sim. Ferramentas gráficas como o phpMyAdmin lhe permitem visualizar a estrutura das tabelas através de uma instrução DESCRIBE ou clicando em uma representação visual da tabela. Você é livre para escolher que tipo de ferramenta deseja usar para analisar suas tabelas. você está aqui ► 123
  • 156.
    APAGUE sua tabela Euconsertei o erro de digitação e tentei rodar a consulta CREATE TABLE novamente. Não funcionou. E claro que eu não preciso apagar primeiro a tabela que contém o erro... ou preciso? o «we da cota* dWtado f°""> - °?s- rTií^EdíM/Tindow Heíp Typo? mysql> DESCRIBE email_list; +------------ I------- “ ----- Field I Null 1 Key | Default | Extra | f ^first naem))l varchar{30) | YES | | NULL | [ last__riam? | varchar(30) | YES | j NULL | I email | varchar(60) j YES | | NULL | 3 rows in set (0.02 sec) Na verdade, precisa sim. Não é possível recriar uma tabela com CREATE TABLE uma vez que ela já tenha sido criada. U m a vez q u e você te n h a criado u m a tabela, ela n ão p o d e ser sobrescrita através de u m a nova co n su lta CREATE TABLE. Se q u iser rec ria r a ta b ela do zero, você te rá d e ap ag ar p rim e iro a existente, e co m eçar tu d o de novo. N o SQL, o c o m an d o DROP TABLE é u sad o p a ra q u e se possa ap a g ar u m a ta b ela d e u m b an c o d e dados. E le ap a g a a ta b e la e tu d o q u e você tiver a rm a ze n ad o n ela. U m a vez q u e n ão ex istem d ad o s em u m a tab ela recém -criad a, n ão irem o s p e rd e r n a d a ao apagá-la e criar u m a nova, com f i r s t nam e escrito co rre ta m e n te . e m a il l i s t h W da -tabela e gostaria de apagar ba*do de dados- 0 d o m a n d o PRO? T A B U E âfaga a 'tabela c bodos os dados doivfcicics nela.
  • 157.
    crie e preenchaum banco de dados Hwerestáprontoparaarmazenardados Os comandos SQL CREATE DATABASE, USE e CREATE TABLE foram usados com sucesso para criar o banco de dados e a tabela de Elmer. Ele não poderia estar mais satisfeito, a não ser que a tabelajá viesse preenchida com os dados dos clientes. Esse é um trabalho para o PHP... e lv is 0 ka*to âe dados c)vÍs_storc ion-tem «ma úníta iabels, !ss£. Legal. Com o banco de dados e a tabela criados, estou pronto para começar a armazenar alguns dados da minha lista de emails. s to re O o firstnam e M i m e liÜlltfIfIIIjfíijlí? fjlllfj fíiitflllllliililfílitlifflffíj? A A Uela o rtiljs t £o«tetí de tó - to j» * d » » ^ «ad* <*e « dad« da Wa de « j** *r»»»ad«- __ Ei, eu tenho uma cópia de Use a Cabeça! SQL (ótimo livro, a propósito). Naquele livro, toda vez que você mostrava o código de uma instrução SQL, colocava um ponto-e-vírgula ao final dela. Por que aqui é diferente? Ficamos felizes de você ter gostado de Use a Cabeça! SQL. A diferença é que, quando você fala diretamente ao MySQL, é preciso colocar o ponto-e- vírgula para que ele saiba onde a instrução termina. Isso porque é possível emitir múltiplas instruções ao MySQL, diretamente. No PHP, quando é usada função mysqli_query(), você só executa um comando SQL por vez, de modo que não é preciso usar o ponto-e-vírgula. Mas não se esqueça de que você ainda precisa colocar o ponto-e-vírgula ao final de cada instrução PHP! existem p e r g u n t a s i d i o t a s ? Se a minha tabela tiver dados e eu a apagar, todos os dados serão apagados, também? Sim, é verdade. Portanto, cuidado ao apagar tabelas! ■ Então, semmecisar modificar uma tabela que já teriba^ládos, estou ferrado? /x Yi Ei, ninguém é perfeito. Todo mundo comete erros, o SQL oferece a instrução ALTER para nos ajudar a ) Ddíficar tabelas existentes. Falaremos desse comando / maíSsâdiante, neste livro. / y
  • 158.
    o script addemail.php Crieo script "Adicionar Email" VbdC 3$<ara está a«ui. Elmer precisa de um formulário HTML para coletar nomes e endereços de email dos clientes. Uma vez que ele tenha essas informações, precisa filtrá-las com um script PHP e armazená-las na tabela e m a il_ lis t. O formulário web (ad d em ail.htm l) requer três campos de input (entrada) e um botão. A ação é a parte mais importante do código do formulário, uma vez que o seu trabalho é repassar os dados para o script addem ail .php, que estamos prestes a criar. © - •■ Crie um banca rfe-Juüuj» t. uniu ; •tribale poro a lista de emuils. SC V ^ad Crie üm formulário web e um script ^HP "Adicionar Email'1para adicionar novos clientes à lista» Q Crie um formufário web e um script PHP “Enviar Email" para enviar um email para a lista. A a $ ê oé o elemen-to H ífc & M & E ltfS .C O M C o n e C - X ÃO -rormuiino E r í t e r y o u r f l r s t f l a m eta«-™ „ H T/V1 L ao sdvipt PttP íadde^l.pHp) prodessara os dados, "''Xe * * » ;:' s c t i o n = " a d d e r n a i l , p h p " > <£ormmethod^ post action_ Cinput type- text íu , i> ‘í e s l. « — ■ / * * » <input type- text m ^ <label f°r="email''>Email:</^ /><br /> </form> </body> /> r addemail.html Os novos diienies podem se dadasivav *a lista de email de £lw*ev (ou s«Ja, serem adidionados ao bando de dados) simplesmente usando o -rovwwlav-io web. sdvipt addemâil pKp é e^eduiado |«|uando o -Çorwvulano |c submetido, e o seu ItvabalKo e prodessar ! os dados e adidíonav- Odlien-te à lista de emails ína tabela do bando de dados). elvis store email list
  • 159.
    crie e preenchaum banco de dados 0 script addemail. php processa os dados do formulário Add Email ("Adicionar Email"). 0 script precisa filtrar os dados do formulário, conectar-se ao banco de dados elvis_store e inserir (insert) os dados na tabela email_l'ist. Ajude Elmer a escrever um exemplo de query SQL para inserir um novo cliente, e depois use essa query para finalizar o código do script PHP. EsúfCVâ â«ui um exemplo de Consulta para ihserir dados *a tabela de EUer. .... Q ................................................ <?php $dbc = a $first name = S_POST['firstname’ ^ tir s t_ n a iu tí - l * 1 ...j ...... i..^..«v t r ~? h 7 . * ........... $query - '' i j/lfc A T u V .T .Q .... mysqii_< i_query ( C / echo ’clients adicionado. f ?> í addemail.php você está aqui ► 127
  • 160.
    solução do exercício CICIO §OLuÇck> 0script addremaii.php processa os dados do formulário "Adicionar Email". 0 script precisa filtrar os dados do formulário, conectar-se ao banco de dados elvis_store e inserir (insert) os dados na tabela email_list. Ajude Elmer a escrever um exemplo de query SQL para inserir um novo cliente, e depois use essa query para finalizar o código do script PHP. INSERT. INTO emailJ is t JrtâmC, last^name, email) l/Aí-WÈS ('Julian, 'Oates', julian^breaknedkpizia.tom') A ^ i esta© os valores do avray fJP O S T ^ue t<mktr* âs in+ormaçoes submetidas. A ^uevy INSERT de e*«mplo e reesdrita tomo uma string PHP < ^u e depende dos dados do -formulário para a inserção- <?php $dbc - ""Vs or ^li_donnedt('data.makemeelvis.dom,( 'elmer*, ‘tbekinj, ‘elvis_jstoreJ ) tonetiar tom o servidor AflyS^L server.'); diei'&rro ao $firstjrt a m e = $_POST [’firstname ’]; flâ st^m e — f^POSTC‘lastname'3] f email..= ■ . ................. 5query = = “fKSERT IfrTFO emaiMist £-first__name, last__nâme> email) 1 1 'V A ír^í? ílf^irst_l>ameJ J'/la^^hàmÇj )fernâtl> )U j|.......................... mysqli^query( fdbdj f^wery ) die(*£rr© do adessar o bando de dados*)j or echo 1clicrite ■ adicionado - wys^li_diose(fdbt); addemail.php Se ^uisessemos nos exibir a^ui, poderíamos dolodâr um !mk de volta para o nosso -formulário, dom uma ta$ HTML <a>.
  • 161.
    cr/e e preenchaum banco de dados T te S T O R tv e Teste o formulário de “Adicionar Email”. Baixe o código da página web “Adicionar Email” no site da Alta Books, em w w w .altabooks.com .br. O código está na pasta c a p itu lo 0 3 . Ele consiste do formulário web addem ail .htm l, uma folha de estilo ( s t y l e . css) e duas imagens (e lv is lo g o .g i f e b la n k fa c e . jp g ). Em seguida, crie um arquivo de texto chamado ad d e m a il.php e digite nele todo o código da página anterior. Este é o script que irá processar os dados do formulário web de Elmer e adicionar novos clientes à tabela email_list. Envie todos esses arquivos ao seu servidor web e abra a página addemail. html em um navegador. Digite os dados de um novo cliente no formulário e clique em Submit (Submeter). Nao se esc^ue<p de {rodar as variáveis de donexão ao ba*do de dados pelas suas próprias. $ iyisevÇâo do novo elièivte a lista de emdil c to»víirmada pelo stvipi addemail-php- Verifique se o cliente foi adicionado ao banco de dados emitindo uma consulta SELECT em alguma ferramenta MySQL. você está aqui ► 129
  • 162.
    lápis solução p^sgjxmte seulápis O f|||A 4 A Com a lista de Elmer começando a ser preenchida, ajude-o VVIU yC All a escrever algumas consultas SQL que ele possa usar para encontrar dados específicos dos clientes. Selecionar todos os dados de clientes que tenham o primeiro nome Martin: SêLECT FR0M e»aiM ist 1 VHBRE -first_name — 'Alartm A estrela seleciona W a s as Ç stâ ‘ j f 3“1 * W ® * 6 colunas da tabela- “ «« Clientes dujo primeiro nome sea Martin. Selecionar apenas o sobrenome de clientes qúe tenham o primeiro nome Bubba: SELECT last_name FR0M emaiMist IíVHERE í írst__name —'Bubba; ................t _ ..................................................................................................... Somente a doluna last_«ame e retornddâ nos resultados dâ donsulta- Selecionar o nome e o sobrenome do cliente que tenha o endereço de email ls@objectville.net: S£L£CT íirs t name, last »ame FR0M email list WttERE email — IséSobjedtvillenet' ........ “..v " .......... ................ ...*........ Para espedi-fidar múltiplas dolunas de resultadosj vote separa os nomes das colunas dom vtrgulâs- ■ s Selecionar todas as colunas dos clientes que tenham a primeiro nome Amber e o sobrenome McCarthy: » / / 1 S£LECT # FR0M emaiMist WttERE first^name — 'A*»»ber AND Is s h jn d m e 'AldCarthy A dlawula IVHERE pode ser realizada, mas depende de varias ihíormâ^oes, neste daso a odorrendia tanto de u» primeiro nome quanto de um sobrenome- /N Ls
  • 163.
    crie e preenchaum banco de dados 0 outro lado da aplicapão de Elmer Enviar mensagens de email para as pessoas na lista de Elmer é uma tarefa semelhante à de adicionar as pessoas à lista, porque ambas envolvem um formulário HTML e um script PHP. A grande diferença é que, para enviar uma mensagem de email para a lista, é preciso lidar com o conteúdo inteiro da tabela eraail list, enquanto que o script ad d em ail. php lida apenas com uma linha de dados. ^ Crie um bnnes de dados c uwo tabela paro o lista do cmoHs-, : Crie um foiiwuluiiu web e um seript PHP "AdiUimui'/Snoi!”1 para adicionar novos1elientea à liste. ^ Crie um formulário web e um script PHP "Enviar Email" para enviar um email à lista 0 -formulário Yíeb Enviar Email permite a Elmer deitar o assunto e o dorpo de uma mensagem de email, e depois envia-los para toda a lista- ^ U-fa, -finalmente checamos ao último Passo- itKTLiK method="post” ac^on="sendemaí 1,php"> <label fox=”subject">Subject of email :</labelXbr /> <input type="text" id=”subject" nam.e="subject" si2s="60" /Xbr /> <label for=”elvismail''>3ody of email:</labelxbr /> . Ctextarea id="elvismail" nanie="elvismail" rows="8" cols="6Dn></textarea><br /> <input type="submit" name="submit" value="Submit" /> </form> </body> </html> / / ^ p a r a tada w 0 sdript sendcmaílphp lc as »*forma£oes dos dliewtes nS tabela, e e«v«a o e»»ail de £1»er Jf ação -form dispara o sdript se«de»ail*pbp. elvis store T i i t p r i i l l i l l l l i l i l l l l i l l i S i i Julian Oates julian@breackneckpizza.com Kevin Jones jones@simuduck.com Amanda Sanchez sunshine@breakneckpizza.com você está aqui ► 133
  • 164.
    o script sendemail.php 0funcionamento interno do script "Enviar Entail" O script sendemail. php precisa combinar dados de duas fontes diferentes para gerar e enviar mensagens de email. Por um lado, o script precisa retirar os nomes e endereços de email da tabela s e n d e m a il_ lis t do banco de dados e lv is _ s to r e . Porém, ele precisa, também, obter o assunto e o corpo da mensagem digitados por Elmer no formulário web “Enviar Email” (sendemail. html).Vamos detalhar os passos da operação. A Use o array $_po st para obter o assunto e o corpo da mensagem de email do formulário. Nada de novo aqui. Clicar no botão Submit do formulário sendemail.html para enviar os dados para sendemail .php, onde nós os capturamos em variáveis com uma pequena ajuda do array $_POST. Execute uma consulta selec t na tabela email_list. A função PHP mysqli__query () roda uma consulta SELECT para obter os dados da lista de emails. Uma vez que queremos todos os dados da tabela, podemos usar SELECT * . O Acesse os dados do email no resultado da consulta. Apenas executar uma consulta não fornece acesso aos dados. Nós precisamos acessar cada linha de dados do resultado da consulta, para termos acesso ao nome, sobrenome e endereço de email de cada cliente. Recorra à função maii() para enviar um email a cada cliente. Para enviar os emails, é preciso fazer um loop através de cada cliente na lista de emails, o que corresponde a cada linha de dados nos resultados da consulta. O loop que criamos aqui começa na primeira linha de dados, depois passa para a segunda linha, e assim por diante através de todas as linhas de dados obüdos pela consulta SELECT. Nós paramos ao atingirmos o final dos dados. 0 sdsrip-fc ptredisa de dados da tabela e»aií iisfc.
  • 165.
    cr/e e preenchaum banco de o< Em primeiro lugar, obtenha os dados 0 enderedo de email de EUer e arma^nado Nósjá estamos bem experientes em extrair dados de formulários no PHP, portanto, o primeiro passo não traz nada de novo; basta usar a superglobal $_POST para armazenar o assunto e o corpo da mensagem " "7*? do email em variáveis. E vamos aproveitar também para armazenar o em un,a ^lâvei, endereço de email de Elmer em uma variável, uma vez que iremos precisar dele posteriormente, quando enviarmos os emails. $from = 1 elmer@makemeelvis.com1 $subject = $_POST['subject1]; $text = $ POST[1elvismail']; pa*ra saibamos exaiamen-te onde ele esta, easo predisemos odiíidá-lo. Os dados do íormuiário pava^a ensaiem de email tawbem sao armazenados em variável- Os demais dados requeridos pelo script se n d e m a il.php são extraídos do banco de dados MySQL de Elmer. Para obter dados dos clientes a partir da tabela e m a il_ lis t e colocá-los no script, precisamos de uma consulta SELECT. Ao contrário do que fizemos anteriormente, quando usamos o terminal MySQL para emitir um SELECT e olhar os dados da tabela, desta vez iremos fazê-lo no script se n d em a il.php, e iremos emitir a consulta com m y sq li_ q u ery (). A variável f^uery armâzenâ a r donsul-ta S$L na íormâ de uma strift^ de ieitfeo- $query = "SELECT * FROM email Eis a nossa donsul-fca, «^e seiedioha -todas as dolunas da -tabela email list- list"; $result = mysqli_query ($dbc, $query); enetoia a donsulia usando uma vanave! de donexao (fdbd) e uma sírina de donsulta (?«iuery). ___ _______ Entao, tudo o que temos de fazer é usar os resultados da consulta, presentes na variável $result( certo? £ predíso Kaver uma done*ao domo o bando de dados para <ue a donsulta possa ser sutaeüda - OS de-talhes da donexao sao armazenados na variável fdbd- Não, a variável $result, na verdade, não contém quaisquer dados. Se você tentar ecoar a variável $ r e s u lt diretamente, verá algo como: Resource id #3 A variável $ r e s u lt armazena um número de identificação de um recurso MySQL, e não os dados, propriamente ditos, que são retornados pela consulta. O que acontece é que o servidor MySQL armazena, temporariamente, os resultados da sua consulta e fornece a eles um número de recurso para identificação. Você então usa essa ID do recurso com a função PHP m y sq li_ f e tc h a rra y () para obter os dados, uma linha de cada vez. você está aqui ► 135
  • 166.
    g- C O d) lchjarrayO paraobter os resultados da consulta etch_array() obtém os resultados da consulta Uma vez executada a nossa consulta, podemos obter os resultados com a variável $ re s u lt. Essa variável é usada com a função m ysqli f e tc h a rra y () para se obter os dados da tabela, uma linha por vez. Cada linha de dados é retornada como um array, que podemos armazenar em uma nova variável chamada $row. ^ — -------------- Ésèa função obtém uma ImKa dt dadosâ partir dos resultados da $row = mysqli_fetch__array ($result) A variavel fvow é um array ^ue, inicialmente, armazcna a primeira linha de dados dos nossos resultados. Consuita, e a armazena em um array. Cada consulta £<$L tem o seu próprio numero de IP, ^ue é usado para se tenha acesso aos dados, associados aos seus resultados. Cada vez que este código é executado pelo servidor web, uma linha de dados dos resultados da consulta é armazenada no array $row. Repetidamente, você solicita que a função m y sq li_ f e tc h a rra y {) seja transmitida através de cada linha dos resultados. Assim, as três primeiras chamadas à função m y sq li_ fe tc h _ a rra y {) obtém as três primeiras linhas de dados da tabela, armazenando cada coluna da linha como um item no array Srow. Aíunçãpm/s^lL íetcfc_arrayO E tr m a z e n a u m a l ï n t a d e - d a d e s e m U H ] n iT i'K . em ail_JLí-s t $ ro w = mysqli_fetch_array($result); $row — mysqli_fetch_array( $result); $row = mysqli_fetch_array($result) ; Cada Coluna de dados t armazenada Como um item no ârray frovi. A variavel fvow t deíinida Como um array Contendo tre s elementos, um para cada uma das tres colunas de dados.
  • 167.
    crie e preenchaum banco de c — ^Aponte seu iápis Como um teste para nos certificarmos de que realmente conseguimos obter os dados dos clientes, termine este código PHP para exibir o primeiro nome, sobrenome e endereço de email de cada cliente presente na tabela email list, uma linha de cada vez. $query = "SELECT * FROM email_list"; $result = mysqli_query($dbc, $query); $row = mysqli fetch array($result); £c i _ r 1 "í v ' ...... você está aqui ► 137
  • 168.
    ± solução 0 ) & to nteseu lápis Soluçãoconseguimos obter os dados dos clientes, termine o K* Como um teste para nos certificarmos de que realmente Solupão código PHP para exibir o primeiro nome, sobrenome e endereço de email de cada cliente presente na tabela e m a il l i s t , uma linha de cada vez. $query = "SELECT * FROM email_list"; $result = mysqli_query($dbc, $query); $row = mysqli_fetch_array( $result) ; J v o w C f . 1*. ' :*. fvov/C'cimairj . '<bv />'; l fr. fv-csui^j tto jVovjt'-Pirst^ttâme'3 •1' ■ fv-oY/Clart^pâiwc J •' : - fv-ovíCemailJ ■ <bv- /> ', frow —mys^li^íc-tí-h^âvrayífresul-ü; cdKo■firrt^name'J . 11 . frowClast^nâme^ . ' : 1 . fy-oyíC'cwail 3 • '<br />'; fro>/ — mys^l etdb_^array(? v-esulO ; efibo fyowr-Pirst^naiwe1 ^ . ' ' . y Você deve estar brincando. i » y * Repetir as mesmas duas linhas de código sem •?.???. rr. parar é, provavelmente, a coisa mais estúpida que eòho /ro w fíiw t nân»e‘3 'L _ eu v‘- £ claro que tem de haver uma maneira ............................. .............melhor de fazer isso. frov/ — edbo f flrov; — m^BMp^^BtnrâyCfreShl^j cdho . fvowClast . 1 : * . frotiCcw^il^ • '<bv- />*; .............. ................................................."""* .......................................................... froY/ =• ' - frowriasi nâim e'3 . frowFemaiH - l<br />'j Existe uma maneira melhor - nós precisamos de um loop. Um loop é um mecanismo da linguagem PHP que repete um pedaço de código até que uma certa condição seja atendida, por exemplo, até se esgotarem os dados. Dessa forma, o loop é capaz de analisar, ciclicamente, cada linha de dados de um resultado de consulta, executando qualquer ação que quisermos, em qualquer linha.
  • 169.
    crie e preenchaum banco de dados Loop com um WHILE loop usando o w hile é umlofip^éspecificamente voltado à tarpfaHy-^ep^rir o ródigrrpfííyíamo uma, determinada condição esteja sendo atendida. Por exemplo, você pode ter uma variável em uma aplicação de serviço ao cliente chamada $got_ cus tome rs ($ te m _ c lie n te _ e sp e ra n d o ), que serve para registrar a informação sobre o tempo de espera para a realização dos serviços, por pate do cliente. Se $ te m _ c lie n te _ esperando estiver definida como tr u e (“verdadeiro”), você sabe que ainda há clientes para atender, então você poderia, consequentemente, chamar a função n ex t custum er () (próximo c l i e n t e ) para ajudar o próximo cliente da fila. Eis como poderíamos programar isso usando um loop w hile: Uni loop wfcíle f e p e t e o c o j i g o enquantp uma condição estíVet s e n d p a t e n d id a . Enquanto tivermos Clientes» -n C ontinue o loop- ^ while ($got custom ers) { next customer () ; Este e o Codijo í^ue e e*eCutado a cada iteraçl© do loop. * Colocar o cód'150do U p dentro de chaves IKe permite executar quantas linhas de Cod*5° *luiser' Quando verificamos “se há mais clientes a atender”, estamos testando uma condição. A condição é o código entre parênteses, e ela sempre apresenta uma questão que resulta em uma resposta sim/não. Se sim, ou true (“verdadeiro”), então a ação é realizada. Se não, ou false (“falso”), então terminamos o loop. Quando chamamos next_custom er () e passamos a atendê-lo, estamos realizando uma ação. A ação é o código dentro das chaves, e é repetida enquanto a condição permanecer tru e . Se a condição se tornar f a ls e , o loop termina e a ação não é mais repetida. Eis o formato geral de um loop usando o w hile: Um loop while nos permite fazer loop atraves dos clientes ate <y*e náo sobre nenhum para atender. A Condição de teste sempre resulta em verdadeiro ou falso— continuar olhando (verdadeiro) ou parar o loop (falso)- while (condição d e_ teste) { ação A açao do loop ©Corre uma vez. a cada passada do loop. CÉRÉSRO Como você acha que um loop while poderia ser usado na tabela em ail_ l i s t de Elmer? você está aqui ► 139
  • 170.
    como whileQ funciona Loopatravés dos dados com while Aplicando um loop com w hile para os dados do email de Elmer, acessarmos os dados, uma linha de cada vez, sem duplicar nenhum código. Nós sabemos que m y sq li_ f e tc h _ a rra y {) é capaz de tomar uma linha da tabela e colocar os valores das respectivas colunas no array $row, mas a função, sozinha, não passa através de todos os nossos dados — ela armazena a primeira linha e então para. Um loop w hile pode chamar m y sq li_ f e tc h _ a rra y {) para atravessar todas as linhas dados do resultado, uma de cada vez, até chegar ao final. while ( p A to*diçao do loof to» víVile e o valor ^ retornado pela -funça© » v > y s« ^ !i_-fettb_arrayO; «ue t interpretado domo trv»e, se houver dados disponíveis, ou -faUe, se os dados tiverem acabado- A ad ão do loop C executada w n êvez. a cada Geração. A aça© do loopj^onsiste de uma instrutao etbo ey*ejunta os dados da linha, doUanáo uma quebra de tmba ao Vmal primeira passada do loop, o array fro*/ armazenara a primeira linka da tabela em ailjist $row eioail—• list /o°Ps. Na .'seaunda passada do loop, o array frow armazenara a segunda linhâ da tabela emaiMist- esta vendo o padrao?
  • 171.
    cr/e e preenchaum banco de dados A instrução edbo dentro âo loop while e*trai os dados do array frow e cx.*b« o dontcwdo formatado tomo HTML. + ' 1 + v Q ■ 4 ^ < ® r "y Uma <ueWa ÜTML- dolota tada Whs de dados em urr> a Vm Ka prepria pá^ftâ results™*- '<br $row[1first_name' ] $row[ 'last__name1] $rowt' email[] t A dhave usada para aícssar o elemento do array deve te r o mesmo home <ue uma dolunâ- 0 loop wfcile p e rp a s s a 9 s d a d o s datakela, lfnta por linta. Quandp nap iíPuVeí mais llnfcas de dadps, ele Çlnallza a c o n s u lta . Julian Oates ; julian@breakneckpizza.com Kevin Jones : jones@sirauduck.com Amanda Sanchez : sunshine@breakneckpiz2a.cam Bo Wallace : bo@bOttOmsup.com Amber McCarthy : amber@breakneckpizza.com Comae Hurst : churst@boards-r-us.com Joyce Harper : jcyceharper@breakneckpizza.com Stephen Meyer : meyers@leapinlimos.com Martin Wilson : roartybaby@objectville.net Walt Perala : walt@mightyguraball.net Shannon Munyon : craftsmanSbreakneekpiaza.com Joe Milano : joe_m@starbuzzcoffee.eom Ka secunda passada do loop, as instrudoes edho e*ibem uma outra se«uendia de te*te, mas dcsta vez. sac usados os dados da secunda línKa da tabeia $row[’first_name' ] $row['last_name1] $row[’ email' 3 Na verdade, nao se usa o smal de mais para juntar duas strings —usa— se o operador ponto- A dada passada do loop, os valores armazenados no array frow se modi-fidam para refletir a linHa atual. Os nomes das doiu*as sao usãdos para se adessar os valores do array- você está aqui ► 141
  • 172.
    não existem perguntasidiotas sobre whiíeQ nqo existem f e r g u n t a s i d i o t a s £ I Comoexatamenteo loopwhilesabequedeve continuar olhando? Quer dizer, o loopwhileé controlado por uma condiçãoverdadeiro/falso,e mysqli_fetch_array () retoma algumtipo de IDdo recurso, que é armazenado em $ r o w . . .Isso certamente não se parece com uma condição de teste verdadeiro/falso. K : Bemobservado. Ocorre que o PHPé bemliberal no que diz respeito ao modo comoele interpreta a condição “verdadeira”. Resumindo, qualquer valor que não seja zero (O )o u fa ls o é considerado como verdadeiro, em uma condição de teste. Assim, quando a função m y s q li_ f e t c h _ a r r a y () retoma uma linha de dados, o array $ ro w é interpretado como verdadeiro, umavez que não está definido como 0 nem f a ls o . E, uma vez que a condição é verdadeira, o loop segue emfrente. O interessante é o que acontece quando não há mais dados disponíveis- a funçãom y s q li_ fe tc h _ _ a r r a y () retoma f a ls o , o que encerra o loop. Então eu posso controlar um loop while com qualquer tipo de dados, e não apenas valores verdadeiro ou falso? K : Correto. Mas tenha em mente que, nofim das contas, o loopwhile está interpretando os dados como verdadeiro ou falso.Assim, a coisa mais importante a se entender é o que constitui verdadeiro ou fa1so no que diz respeito àinterpretação de outros tiposde dados. Ea resposta simplesé quequalquer coisa diferente de Ooufalsoé sempre interpretada como verdadeiro. " P i Oque acontece com o loop while se nenhumdadofor retomado pela funçãomysqli_fetch_array() ? Se a consulta não resultar em quaisquer dados, então a função mysqli_fetch_array () retoma falso.E issofazoloop while nunca chegar ao código da ação, nem mesmo uma vez. ? Então é possível ter um loop que nunca faz repetições? H : É, sim. Tambémé possível ter umloop que nunca termina. Considere este loop while: while (true) { Istoé conhecido como loop infinito, porque a condição de teste nuncafaz o loop terminar. Loops infinitos representam algo muito ruim. PONTOS DE BALA Um banco de dados é um Container para armazenar dados de uma forma altamente estruturada. As tabelas armazenam dados em um padrão de colunas e linhas dentro de um banco de dados. O comando SQL create DATABASE é usado para que seja criado um novo banco de dados. O comando SQL c r e a t e t a b l e cria uma tabela dentro de um banco de dados e requisita informações detalhadas sobre as colunas de dados dentro da tabela. Você pode apagar uma tabela de um banco de dados com o comando SQL DROP TABLE. AfunçãO mysqli_fetch_array ( ) obtém uma linha de dados a partir dos resultados de uma consulta ao banco de dados. Um loop while repete um pedaço de código PHP enquanto uma condição de teste continua sendo atendida. Q Crie uro b<meo de dodos e uma tabela papa a Ifata de emails. Q Cwc um formularia web e um -script PIIP "Adfdwim..Dnuil" para adicionor-novos clientes fl ^ Crie um formulário web e um script PHP “Enviar Email" para enviar um email para a lista. ? Não sc esqueça? ainda temes este úittmo Passo para terrnínâv.
  • 173.
    crie e preenchaum banco de dados ímãsdeGeladeiraFHF&MySoL Use os ímãs abaixo para completar o código do script "Enviar Email" de modo que Elmer possa começar a enviar emails para a sua lista de clientes. Para refrescar sua memória, eis aqui o modo como m a il () funciona: m a i l (to, su b ject, msg, 'F r o m :' . fro m ) ; <?php $from = 'elmer@makemeelvis.com'; Â * $subject = * A sxcw.to $text =(/**■ _ J . _ $dbc = mysqli connect('data.makemeelvis.com', 'elmer', ’theking', 'elvis_store' or die('Erro ao se conectar com o servidor MySQL.'); $query = ''SELECT * FROM email_list" ; $result = mysqli_query ($di>c, $query) or die('Erro ao consultar o banco de dados.’); while($row = mysqli_fetch_arrayf$result)) { $first_name = $row['first_name’] ; $last_name = $row['last_name']; $msg = "Dear $first_name $last_name, n j[ $to = 4 í í f P 1 . .a ..w.*............... mail{ ^ r t: ' -íi $c$ echo 'Email sent to: ' . j f . 1<br />'; } mysqli_close($dbc); 'From: ?> sendemail.php
  • 174.
    script sendemaiLphp finalizado ímãscie- GaKJeira FBF & M /SQL - Solução Use os ímãs abaixo para completar o código do script "Enviar Email" de modo que Elmer possa começar a enviar emails para a sua lista de clientes. Para refrescar sua memória, eis aqui o modo como mail () funciona: à Certifi^ue-se de trodâr isto a*ui pelo seu proprio enderedo de email- mail(to, su b je c t, msg, 'From:! . from ); <?php w Çfrom = 'elmergmakemeelvis.com'; 0 dampo referente ao assunto dhama~se ttsubjedtw , <ue t o mesmo nome usado para adessá-lo no arrav ÍJC Z T $dbc = mysqli_connect('data.makemeelvis.comr, 'elmer1, ’theking', 'elvis__store' ) or die ('Erro ao se conectar ao servidor MySQL.')í Q de email t Squery - "SELECT * FROM ewil.list"; M f"?0 Í ° (< * r" " > l á r ' K’ $result = mysqli_query($dbc, $query) denominado e l v i s m a i l • or die('Erro ao consultar o banco de dados.’); ^ , 6 d» «.ait 0 ^ t # while ($row = mysqli fetch array (Sresult) ) { s J ° " ' ' C t t S â a e » * S l ?n . $first name = $row[ ’ firstname'] ; f d fundão mâilO, iun-fvi / ° ^ $last name = $row['last name’]; 'Y Kfrom de °* * ° $msg = "Dear $first_name $last_namern ^$to = echo 'Email sent to mysqli_close($dbc); 1From:1 il'cbr ?> 0 email desti*tario, assunto da mensagem e dorpo da mensagem, s^° passado nâ fund3o mailOj dom o endereço ”à t tim er.”” A doluna email do bando de armazena os enderedos dos dlientes, aos ^uais a mensagem deve ser enviada. i n jla d o s sendemail.php Uma mettle™ de donfirmajão é enviada para a pagma, dom o endereço de dada dliente â c^uemfoi enviada a mensagem- £m gerab não e uma boa ideia, em termos de segurança, informar o < ^ue o usuário digitou diretamente para a função mailO sem faz<r, antes uma verifidaçao primeiro- 0 Capelo y mostrará algumas tédnidas para resolver este problema-
  • 175.
    crie e preenchaum banco de dados TfeST ORfve Envie um email para a lista usando o formulário “Enviar Email” Baixe o código para a página “Enviar Emairno site da Alta Books, www. altabooks . com.br. Está na pasta capitulo03. Da mesma forma que a página “Adicionar Email” que você viu anteriormente, este código consiste de um formulário web em sendmail.html, uma folha de estilo (style.css) e algumas imagens (elvislogo. gif e blankface.jpg). Crie um arquivo de texto chamado sendmail .php e digite nele todo o código da página anterior. Envie todos os arquivos para o seu servidor web e abra a página sendm ail .htm l em um navegador. Digite uma mensagem de, email no formulário e clique em Submit. Tenba em mente <Y *e o scw enderedo de email preíisara estar «a lista, para < < *e voóe reteba 3 mensagem. Você tem email... de Elmer! Finalmente, Elmer pode enviar os seus emails anunciando promoções de QueroSerElvis. com (MakeMeElvis.com)para todos os inscritos na sua lista de email, usando o seu novo formulário e script PHP de “Enviar Email”. Ele pode, também, usar o output do script para confirmar que cada mensagem foi enviada com sucesso. Cada vez que o código no loop w hile do script é executada, ele vê “Email enviado para alguem@algumlugar.com”, com os endereços das pessoas no seu banco de dados. O resultado final é mais exposição para os seus produtos e, para o bem ou para o mal, mais sósias de Elvis Presley por aí! 0 sdript J£end U a il Vendi todo o meu estoque de sapatos de camurça azuis... estou rico! realmente envia mensagens para os endereços presentes no banto de dados, portanto duidado ao ía z ^ r alterações *ele! ImaSingtistrosífàefs. Subjectofemai1' ;BisS a*«? Email sent to:julian@breakneckpizza.com Email sent to:jones@simuduck.com Email sent to: sunshine@breakneckpizza.com Email sent to: bo@bOttOmsup.com Email sent to: amber@brealweckpizza.com ; . . . . . . . . . . . ----- ------ -v -- findyofsmall: _____— —---- - — tmajl sent to: amber@brealwerkpizza.r. "Bílíe this week« Genuine.hors Email sent to: chum@boards-r-us.com Email sent to:joyceharper@breakneckpj —oriSy -days Email sent to: rnevers@leaninTinn^ir t ” ? I jv;^**aiyti^uitraK necK pizza.coi Emaü sent to: meyers@leapinlimos.com Email sent to: martybaby@olgectville.net Email sent to: walt@mightygumball.net Email sent to: craftsman@breakneckpizza.com Email sent to:joe_m@starbuzzcoffee.com Email sent to: bnjce@chocoholic-inc.com Email sent to: pr@honev-doit.cam Email sent to: bertieh@objectville.net Email sent to: gregeck@breakneckpizza.com Email sent to: wilmawu@starbuzzcoffee.com Email sent to: samjaffe@starbuzzcoffee.com Email sent to: ls@objectville.net EmaUsent to:J>sliakes®mightygumball.net você está aqui ► 145
  • 176.
    nosso aplicativo precisada funcionalidade delete Às vezes, as pessoas querem sair Como acontece com qualquer nova empresa, existem obstáculos no caminho. Parece que alguns fãs de Elvis pularam do navio do Rei e querem sair da lista de Elmer. Ele quer atender a esses pedidos, mas para isso é necessário remover os clientes do seu banco de dados. Caro Coiegg Ra ^nbora eu a' brador' Passos c/e dan da aprec'e os estou 7?n?a cfo e/w_ s_ habHidades3n !ncr>veis f me^ n a e Z ^ n°-A^ v a i Caro Elmer, Eu não desejo receber mais emails sobre promoçoes da sua loja. Ainda sou fã de Elvis mas não tenho mais tempo para im itá -lo . Por favor, me retire da lista. Meu email e cbriggs® boards-r-us.com. Obrigado, Um Ex-lmitador Prezado Senhor, Após várias reações alérqicas as costeletas de genuínoS de cavalo, decidi que tentar me ‘S ”eE^ad E'VÍSnà0éamin^ prara .Eu adoro capas bonitas, mas as costeletas são um pouco de exagero. Por favor, me retíe da sua lista de emails. Um Abraço, Brian Powers bp@honey-doit.com £W er»âo está ™ » V íe liz . e*» pevder dlie*ies, mas atender aos pedtdos de vewoçao da sua nsta de emails. E um fato na vida do MySQL - às vezes você precisa remover dados do seu banco. Elmer precisa atualizar a sua aplicação para poder apagar usuários da tabela e m a il_ lis t. Escreva aqui os novos componentes da aplicação que você acha que Elmerirá precisarpara implementar o recurso de “Remover Email”: É, parece que nem todo mundo tem o talento para imitar o Rei. Preciso retirar estas pessoas da minha lista, para que possa me concentrar nos verdadeiros fãs. , ......... ......'S. r. 2*.
  • 177.
    crie e preenchaum banco de dados Removendo dados com PEIETE Para apagar dados de uma tabela, precisamos de um novo comando SQL, DELETE. Usaremos DELETE em um novo script “Remover Email”, o qual apagará dados dos usuários da lista de emails de Elmer. Na verdade, precisamos de um novo script e de um novo formulário web para ativá-lo... mas antes de tudo precisamos da função DELETE. O comando SQL DELETE remove linhas de dados de uma tabela. Isto o toma um comando que você deve usar com muito cuidado, uma vez que ele é capaz de eliminar uma tabela inteira, e todos os seus dados, num piscar de olhos. Sabendo disso, eis aqui a forma mais perigosa de DELETE, que apaga todas as linhas de uma tabela. -grtc tim-bonco de dodói e uma tabela para a lista de emails. eitviop om-ewõil-parq-qHtstq. Crie umformulário web e um script PHP "Remover Email," parc remover clientes da lista. o no*»»e dê nome da tabela tsbclâ da < ^ u a l v < ? d < r — “ deseja apagar linhas. Se«» nenKum outro ^ualifidador, _ _ S o domâindo esvazia i — ~ ^ to » p le w te a tabela, Entoo nao podemos nunca vCn,ov»do S 5SS à ie ! ( apagar algo de uma tabela ^ sem apagar tudo? Não, de jeito nenhum. DELETE pode ser usado especificando-se uma determinada linha, ou linhas, para serem apagadas. Para especificar precisamente a linha - ou as linhas - que se deseja apagar com DELETE, você precisa adicionar uma cláusula WHERE. Se você se lembra de como a usamos com o comando SELECT, WHERE tem a mesma função aqui: permitir que você isole linhas específicas em uma consulta. Parede «ue predisai*o$ de um wovo Passo... às vezes os projetos prédisant se mod»f*dar/ [~ ^Aponte seu lápis Suponha que Elmer tenha 23 clientes cujo primeiro nome seja Anne, 11 clientes cujo sobrenome seja Parker, e uma cliente com o nome Anne Parker. Escreva abaixo quantas linhas de dados seriam apagadas por cada uma destas consultas. 1 1 DELETE'FROM email list WHERE first name - ’ Anne’; ..... DELETE FROM email_list WHERE first_name = 'Anne' OR last_name = 'Parker'; DELETE FROM email list WHERE last namS = Parker; j /S /— i i — ■ P você está aqui ► 147
  • 178.
    DELETE com WHERE ponteseu lápis Solução 5uP °nha que Elmer tenha 23 clientes cujo primeiro nome seja Anne, 11 clientes cujo sobrenome seja Parker, e uma cliente com o nome Anne Parker. Escreva abaixo quantas linhas de dados seriam apagadas por cada uma destas consultas. DELETE FROM' email_list WHERE first_name = 'Anne1; DELETE FROM email_list WHERE first_name = 'Anne' OR last_name = 'Parker1; ^ DELETE FROM email list WHERE last name = Parker; o 'ft 0 soWe*or*e *ao esta entre aspas, portanto, nenbuwa taba e apagada - todos © s valores de tento preèisam estar entre aspas- Use WHERE e PEIETE para apagar dados específicos Usando uma cláusula WHERE com o comando DELETE, nós especificamos algumas linhas para serem apagadas, em vez de tudo que houver na tabela inteira. A cláusula WHERE permite que nos concentremos apenas nas linhas que desejamos remover, neste caso um dos clientes de Elmer que pediu para ser retirado da lista. DELETE FROM email_list WHERE |bifi = >pr@hon 0 honte de w *»a íoluna (fô tabela Ö valor à ser proíurado. A cláusula Esta parte da dliwsula WHERE W H E R E lilf llt c t realiza um teste e» todas as lihKas, para ver «uais atende» ao ct CPTlSUít£ t7 cl& « I« - « tá * « )» p ro d u to . ç £ o c o O teste propriamente dito, dentro da cláusula WHERE, realiza uma , * lo 1 comparação que é executada em cada linha da tabela. Neste exemplo, ctS IÍÍIp h S o sinal de igual (=) testa cada valor da coluna em ail para ver quais e c í£ l Cc^S dei linhas são iguais a ”p r@ honey-doit. com". Se o valor da coluna * em ail bater com o que está sendo procurado, então a linha em ^ p o lc U questão é apagada. Escreva aqui por que você acha que a coluna email é usada na cláusula WHERE, e não first name oulast name: .j.O... :> . v . ..J L A . . . ....... ri.. . 4. . . . ês/y^tS.. .
  • 179.
    crie e preenchaum banco de dados Minimize o risco de apagamentos acidentais E importante entender que, embora qualquer coluna possa ser usada em uma cláusula WHERE para selecionar linhas, há um motivo muito especial para termos escolhido a coluna email para a consulta DELETE de Elmer. Considere que, se mais de uma linha atender àcláusula WHERE, todas as linhas que também atenderem, serão apagadas. Assim, é importante que a cláusula WHERE de Elmer indique exatamente, a linha que deve ser apagada. Estamos nos referindo, aqui à unicidade. É razoavelmente seguro assumir que, entre os endereços de email da tabela email list, não haverá dois emails idênticos, enquanto nomes e sobrenomes não forem detectados como únicos. Você não vai querer criar uma cláusula WHERE que procure por “Pat” na coluna first__name para apagar um único cliente - você acabará apagando todos os clientes chamados Pat! E por isso que a cláusula WHERE de Elmer tem de ser cuidadosamente elaborada, de forma a procurar algo bastante específico, na coluna email. DELETE FROM email list WHERE Uma clausula WHEflE em uma insfrução DELETE lfce petm ite-in d icar a línha c jue V^ce cju e r v e m 9 V er. A eoMvlta Í)S u E T £ re»*>ov€ esta |mH â do bândo de dàdos... p jrj nunda mais ser vista^ email = ’ pr@honey-doit.com' email Usar d doluna email nâ eláusula WHERE ajuda a estabeleder a unididade e 3 reduzir o risdo de se apagar uma linba adidentalmente- Se -tivéssemos usado firs t nôme na dláusuia WHERE, em vez. de email, este usuário teria sido, adidentaimente, deíetado. V . mysql> DELETE FROM email_list WHERE email = ’ pr@honey-doit.com ; 1 row deleted (0.005 sec)
  • 180.
    O R tv e _______________________ Teste o comando DELETE no banco de dados de Elmer. Inicie uma ferramenta MySQL e emita alguns comandos DELETE para apagar linhas individuais da tabela e m a il_ lis t, com base nos endereços de email dos clientes. Certifique-se de incluir uma cláusula WHERE em todas as instruções DELETE, para não acabar, acidentalmente, deletando a tabela inteira! test-dríve o comando DELETE O comando d e l e TE é bem útil, mas o ideal seria apagarmos linhas de dados usando um formulário web e umscript PHP, certo? Correto. Apagar usuários manualmente, com consultas individuais, não é a forma ideal de se gerenciar uma lista de emails. Já que Elmer, inevitavelmente, irá se deparar com usuários que desejarão ser removidos da sua lista, faz todo o sentido futuramente, desenvolver uma interface web para a remoção de usuários da lista. Um formulário web HTML e um script PHP resolvem o problema,juntamente com uma consulta DELETE FROM auxiliada por uma cláusula WHERE...
  • 181.
    crie e preenchaum banco de dados Elmer criou um formulário web (removeemail.htmi) para apagar clientes da sua lista. Só o que o formulário está aceitando apenas um endereço de email, o qual é digitado em um campo chamado email. Complete o código do script removeemail .php que é chamado pelo formulário para executar cada remoção de usuário. tfhamâ-se ‘ email" Enterãnem ailaddress» rem ove. V Email address: Cliôôr no boiao Cftvia o -formularioj r> 5 - N +cr»a de uw > a vc<ws'tdao POST, ao s t ú f i PttP. removeemail.html <?php $dbc = mysqli_connect(1data.makemeelvis.c o m ', 'elmer', 'theking', 'elvis_store' ) or die(’Erro ao se conectar com o servidor MySQL.’} í & * A . ~ % £ $ $ L L â r . s . 2 l ............ ........................................................ $. .....W .E !?.É £................ I ■ ■ ^ I...../ * I i f • r~ C-C .TiQ. .è k 1 ........ f__ . - r ? è . i.!......... : .............o .5 _j ’ / ' T ‘ mysqli_close($dbc) ?> removeemail.php você está aqui ► 151
  • 182.
    o script removeemaii.phpfinalizado Elmer criou umformulário web (removeemail.htmi) para apagar clientes da sua lista. Só o que o formulário está aceitando apenas um endereço de e email, o qual é digitado em um campo chamado email. Complete o código do ç)OLuÇãO script removeemail .php que é chamado pelo formulário para executar cada remoção de usuário. dhama-se email". Clidar n©botao M Removew envia o formulário, «a forma de uma requisição POST, 3o sdript PHP- Os dados do formulário presentes em f__P0ST s3o armazenados em uma variavel, e depois usados na donsulta p e l b t e . , , t j Cuidado tom esta* aspas ?email — f POSTremail 3, y [ ^ simples e dujlas a®|w! aspas duplas fitam cm , .................. ’7'*v f torno "dif tôda ‘3r donsulta f^e ry - ^ i l - lfe r^il'w ; / ç as simples fidâm mys«|i queryí/dbd, fuery) ew k *""0^ ...........t...............................................................................................d i’é^ail arma«y^do- e** or dief'Erro ao donsultar o bando de dados'); few?jl ................................................................. demais ,do»ifi»:tt»ar-o-.................................. edho ‘Client? removido: 1. [email; ^ **"& ****> prindipaimente ................................. ................................. ^ ^ ^ tra tâ -d á V e m 0 dão'- de dados do bando. * Kão se esqueça de fedhar a done*ão dom o bando de dâdos te ; ............0 removeemail.php
  • 183.
    crie e preenchaum banco de dados U-(WPmâWntc tcrminâmosl Crie um bonco de dados e uwo---- tobcln piara a lista de emails. 0 Oie um formutáriu web e um æript PMP "Adiciurórt»uíl" [xuxi adisipnarn cvgs-cliGrrtes o lista. ^ Grie um formularia wcb-e um - aeript FHP ”&w»ai*Email" para onviar um email à ligta.----- -Q — CpÍo um-formuiório web e um ■ ■ ■ scmpt PMP”Romovan Emcit“ p«po pomoven cliontas do lista. TfeST ÛRIVE Remova um cliente da lista de emails usando o formulário “Remover Email”. Isto está começando a lhe parecer familiar, não? Baixe o código para a página “Remover Email” no site da Alta Books, www. altabooks.com.br. Está na pasta capitulo03. O código consiste de um formulário web em removeemail. html, uma folha de estilo (style.css) e algumas imagens (elvislogo. gif e blankface.jpg). Crie um arquivo de texto chamado removeemail. php e digite nele todo o código da página anterior. Envie todos estes arquivos para o seu servidor web e abra a página removeemail. html em um navegador. Digite o endereço de email de um cliente no formulário e clique em “Remove” para apagá-lo do banco de dados. você está aqui ► 153
  • 184.
    o aplicativo listade email esta cómpieto! "QueroSerElvis.cout" é uma aplicapão web É oficial. Com a £yuda do PHP e do MySQL, o site QueroSerElvis.com de Elmer agora é digno de ser chamado de aplicação web. Elmer agora é capaz de armazenar dados, permanentemente, em um banco de dados MySQL e também de interagir com esses dados através de formulários web. Uma combinação de páginas HTML scripts PHP e consultas SQL inseridas permite a Elmer adicionar e remover clientes da sua lista de email (os clientes também podem se inscrever sozinhos), bem como enviar mensagens de email para a lista inteira. A página “Adicionar Email” adiciona novos clientes à lista de email de Elmer. A página “Remover Email” exclui um usuário da lista de emails.
  • 185.
    crie 0 preenchaum banco de dados C r u z a d a s p H P & M y S o L Depois que você tiver treinado, os passos de dança de Elmer, veja se consegue cantar junto e completar estas palavras cruzadas. Horizontais 3. Um banco de dados MySQL divide-se nelas. 5. Uma estrutura de dados persistente, altamente organizada, que geralmente é armazenada em um arquivo, no disco rígido. 6. Esta cláusula condicional pode ser adicionada a instruções SQL para controlar quais linhas são especificadas. 8. Este comando SQL remove uma tabela inteira do banco de dados. 9. Use este comando SQL para selecionar linhas de uma tabela. 10. Use este tipo de dados do MySQL para armazenar uma quantidade variável de texto. 12. Dentro de uma tabela MySQL, isto armazena um tipo específico de dados. 13. Continua fazendo algo, enquanto uma determinada condição de teste permanecer verdadeira. Verticais 1. Um tipo de dados do MySQL que armazena números sem casas decimais. 2. Use este comando SQL para olhar a estrutura de uma tabela. 4. Quando funcionalidades dinâmicas são adicionadas a um web site usando-se PHP e MySQL, o site torna-se uma......... 5. Use este comando SQL para destruir linhas de uma tabela. 7. Após ter criado um novo banco de dados em um terminal MySQL, você deve exexutar este comando antes de fazer qualquer coisa com o banco. 11.Termo em inglês que representa um conjunto singular de dados de uma tabela, consistindo de um elemento de cada coluna. você está aqui ► 155
  • 186.
    palavras cruzadas php& mysql - solução Cruzadas T H ? & M / SQ L - Solução
  • 187.
    crie e preenchaum banco de dados Sua caixa deferramentas PHP £ MySQL Você não só ajudou Elmer a montar sua aplicação web, como também desenvolveu valiosas habilidades com PHP e MySQL neste capítulo. Por exemplo... 157 c a p ítu lo 3
  • 189.
    4 Aplfcaç^es Realistase prátícas Sua Aplicação * na Web Às vezes você precisa ser realista e repensar seus planos. Ou então planejar com mais cuidado logo no começo. Uma vez lançada a sua aplicação na Web, você poderá descobrir que não planejou suficientemente bem. Coisas que você pensou que funcionariam podem não ser boas o suficiente no mundo real. Este capítulo dá uma olhada em alguns problemas do mundo real que podem ocorrer quando você transfere sua aplicação do ambiente de testes para um site reai. E enquanto isso, nós mostraremos exemplos de códigos PHP e SQL importantes. este é um novo capítulo ► 159
  • 190.
    elmer precisa deum aplicativo de lista de email melhor Elmer tem alguns clientes irritados A lista com os emails dos clientes de Elmer cresceu exponencialmente, mas os seus emails têm gerado algumas reclamações. Elas são variadas, mas todas parecem ter algo a ver com os usuários recebendo mensagens em branco, ou múltiplas mensagens, o que não é bom em nenhum dos casos. Elmer precisa descobrir o que deu errado e consertá-lo. O seu negócio depende disso. sabe *ue te» u** problema, «âs ele pireti* de ajuda para âesttbn* e*ata»ervte o <ue W a - í«: ' '■ :? } 1 : ■ ; V if.; B: ."v ‘ W n l ' r'"'
  • 191.
    aplicações realistas epráticas SINTAXE comoEkner, e administrador da lista de etnails 3uaiaíeía é Interpretai' p papel de Elmer e desoot-rijr C 9H }9 egses einails em bt^ncç esta.9 sendo enviados. Ele suspeita <jue tem algo a Ver com o formulário sendemail.kml- Êstrcvâ a<wi o <ue £Uev atha «uc pode sev- o ^roble^a
  • 192.
    sinta-se como elmersoiução Si^TArSE como Elmer, o administrada da lista de e m a i l s - S e l u ç ã o Suatarefe. é-fnt&íptetcir 9 pape-l de Elmer e descobrir como esses erri^ls em Wanco estão sendo enViad^s. Ele suspeita, ^ue tem algo a Vet cem p ÍQrmularfè sendemqjl.kmL Esireva a«ui o <ue EUer adha «jue pode ser o problema. £e o bota© Submit íc r pressionado no formulário sem haver nada no £ampo Body (iorpo da mensagem); é enviado um email em brando £ a^ora ^ue estamos pensando no assunto, um tampo Subject íâssuni») vazio também é problemático.
  • 193.
    aplicações realistas epráticas Protegendo Elwer de... Elmer Portanto, o problema aqui está naquela peça que fica entre o teclado e a cadeira - Elmer está clicando acidentalmente em Submit (Submeter) sem digitar uma mensagem, e com isso emails em branco são enviados para a lista inteira. Nunca é seguro presumir que um formulário web será usado exatamente da forma que foi planejada. E por isso que você, um programador PHP atento, tem a responsabilidade de tentar evitar esses tipos de problemas, antevendo que alguns usuários irão usar os seus formulários de forma errada. Vamos dar uma olhada no código do nosso script sendem ail ,-php atual, para ver como as mensagens vazias de Elmer estão sendo criadas. Kosso Bhviâm Email usa o •fceitfco do -rormuíâHo S £<ri3ir um email, mesmo c^u e o usuário n3o íenha dijííado nada. 0 -te*t» do íovmulavio e obiido d t fJ>Ô STf* b jr t« e f POSlTelvismaiD, e e salvo cm fib je fit e fte*fei resfefrtivameK-te- $dbc = mysqli_connect(’data.makemeelvis.com’, ’elmer' or die('Erro ao se conectar ao banco de dados.'); ’theking1, 'elvis store' $query■= "SELECT * FROM email_list"; $result = mysqli_query($dbc, $query) or die('Erro ao consultar o banco de dados.') while ($row = mysqli_fetch_array($result)){ $to = $row['email']; $first_name = $row['first_name']; $last_name = $row['last_name']; $msg = "Dear $first_name $last_name mail{$to, $subject, $msg, 'From:' . echo 'Email $to 1 <br />' } mysqli_close($dbc); 0 problemâ c < ^u e m os usamos f'tex’ i *a nossa mensagem, ^dçpehdcM-temcnie de a variável toYí{,<X algum ou »ao— ...e inos -também usados fsubjeòi i*de?e*de*W *t« de bavev kjcÀfi *ela nâ°' ?> Escreva aqui o que você acha que deveria ser modificado no código do script sendem ail .php para consertar o problema dos emajls em branco: , / *. .* ■ * '' . .. _V. .*.. .-is. c. " T ‘.. .. ^ você esíá aqui ► 163
  • 194.
    sendemail.php precisa devalidação Exija bons dados do formulário O formulário de Enviar Email de Elmer precisa de alguma validação, que é o processo de se verificar se os dados do formulário estão OK antes de fazer qualquer coisa com eles. Elmerjá está usando validação, embora não a esteja chamando por esse nome. Sempre que ele recebe um pedido através do site, ele não envia o produto imediatamente... ele valida o pedido antes. No caso de um pedido, Elmer primeiramente verifica se o cartão de crédito do cliente é válido. Caso afirmativo, ele prepara o produto para envio. Mas para isso, ele precisa verificar se o endereço do cliente está completo. Se estiver tudo certo, então Elmer faz o envio. Para que um pedido seja processado com sucesso na loja de Elmer, é necessário validar vários dados referentes a esse pedido. EWev te» que validav -s. odarfcao de A drédito de dada dliente, antes de atender ao pedido. Para resolver o problema dos emails em branco, precisamos validar os dados do formulário entregues ao script sendemail -php. Isso significa que os dados devem ser submetidos da página do cliente (sendemail. html) para o servidor e o servidor (sendemail. php) deve checar se todos os dados estão presentes. Podemos adicionar algum código a sendemail. php para examinar os valores das caixas de texto, e verificar se elas não foram deixadas em branco. Se tudo estiver OK, o script envia os emails. 0 endereço pav-a—■ —^ envio predisa estar do^pleto- H Elmer preenche e submete o formulário Enviar Email. O Os dados do formulário são enviados para o script de Enviar Email, no servidor. Validar slgnííica certíÇiCcfr-se d e <jue 9S dadPS cj[ueVoce está reeekendp s§9 9s espetadas. 0 pedído só é enviado se o dartao de dredito e o endereço de envio íore» válidos. O script PHP valida os dados. Se estiverem OK, ele envia os emails - caso contrário, ele retorna um erro para o cliente. H O servidor envia uma resposta HTML para o navegai v dizendo ou que o email foi enviado ou que os dados do formulário eram inválidos.
  • 195.
    aplicações realistas epráticas A lógica por irás da validação de Enviar Email Elmer precisa validar os dados que obtém do formulário s e n d e m a il. htm l, para poder enviar os emails. Na verdade, a situação ideal é que o envio dos emails dependa totalmente da validação dos dados. O que realmente precisamos que o PHP faça é tomar uma decisão com base na validade dos dados recebidos pelo script s e n d e m a il.php. Precisamos de algum código que diga “se os dados forem válidos, vá em frente e envie os emails”. Estas duas eoftdiÇoes predisa» ser verdadeiras parâ o dado ser donsíderâdo valido i SE Subject contiver texto E Body contiver texto ENTÃO enviar email Se a»bas as tonditoez -Pore» atendidas, e sinsl de <ue esis tudo derto e <ue pode»os enviar os e»ails. Estavamos »andando e»ail se» h© $ preodupar»os se aUo losse digitado nestes da»pos do -rormulario. Co» a ajuda da validado, pode»os nos dertiíií-ar de <*e os e»aiis só seja» enviados se a»bo* os ta»pos dontwere» dados. íia < ?eX istem Perguntas idiotas sendemail.html Eu já ouvi falar em validar os dados no cliente, em vez de no servidor. Como isso funciona? 0 navegador web é considerado como o cliente, de modo que a validação no lado do cliente seria qualquer verificação que ocorra antes de os dados serem enviados para o script PHP. Linguagens como JavaScript são capazes de fazer validação no iado do cliente. Se estiver interessado em aprender mais, dê uma olhada em Use a Cabeça! JavaScript, o qual aborda em detalhes a validação no lado do cliente. Então por que usar a validação no lado do servidor, em vez de no lado do cliente? Se validarmos no cliente, apenas parte do problema é resolvida. Elmer poderia navegar diretamente até sendemail.php e enviar um email em branco. Porém, se validarmos no servidor, isso resolve ambos os problemas. Dados em branco no formulário serão detectados, bem como dados em branco sendo carregados diretamente no script PHP. Isso não equivale a dizer que é errado validar no cliente. Na verdade, é uma ideia muito boa. Mas o servidor é a última linha de defesa para se capturar dados ruins, portanto a validação no lado do servidor não pode ser ignorada. você está aqui ► 165
  • 196.
    tirar a declaração Seucódigo podetomar decisões com IF A declaração PHP if permite ao seu código tomar decisões com base em se algo é verdadeiro ou não. Considere novamente os pedidos da loja de Elmer. Antes de atender um pedido, Elmer precisa receber o pagamento, o que significa cobrar no cartão de crédito do cliente. Se o cliente fornecer a Elmer um número errado de cartão de crédito, ele não pode atender ao pedido. Assim, Elmer realiza uma espécie de validação-no-mundo-real em cada pedido, que acontece mais ou menos assim: Se o cartão de crédito do cliente for válido, vá em frente e atenda ao pedido Nós podemos traduzir este cenário para código PHP usando a declaração if, que serve para lidar exatamente com este tipo de tomada de decisões. A Instrução i f básica tem três partes: Apalavra-chave i f Ela inicia a declaração O A condição de teste A condição de teste ou expressão condicional, localiza-se entre parênteses logo após a palavra-chave i f . E aqui que você coloca a declaração cuja validade ou veracidade, você deseja determinar. A ação A ação deuma declaração i f vem logo após a condição de teste, e fica dentro de chaves. E aqui que vocêcoloca o código PHP que deseja executar quando a condição for verdadeira. Esta e 3 t<nâtâo Ela esta dedlaradao ^"'Snd© uma íw^ao para veH-Pidar eomcça dom i f -v f ® está a r^ n a d o e* ^ tKav<; ) fíw art_£ard I » ( «alido. ^ . . . sP s ' -------- — _ I > ----------------------> ^ i w f c .a a r * r t e © i f ( i s V a l i d ( $ c r e d i t _ c a r d _ n u m ) ) { a açao O f i l l O r d e r 0 ; s r ] Mo í ir tliu a iã o « ' fcta ‘ a * 9 ° ' ° ?^ ' r Í 3 i t t laraíão if..' t t í b J t » taso a ío n to » ^ »«-dadwa. V oá ?oa< ImKas de tóá^o aqui quanto quiser- ^ ( íalso ^dependendo da validade do dartâo de dredito. Jk.n n
  • 197.
    aplicações realistas epi. Testando em busca da verdade O cerne da declaração if é a sua condição de teste, que é sempre interpretada como verdadeira ou falsa. A condição de teste pode ser uma variável, uma chamada a função ou uma comparação de uma coisa com outra, por exemplo. A validação de cartão de crédito feita por Elmer usa uma chamada a função como a condição de teste, o que significa que o valor retornado pela função será ou true (“verdadeiro”) ou false (“falso”).. A dondição de / — -teste e.verdadeira V' ou £alsa- SE(ojcartão for váNdoJ “ 'I lf f ENTÃO atender ao pedido f illOrder () ; ^ 5 dondiÇâo de teste ----- to r verdadeira, a aça© ê e*edutada. 3 É bastante comum usar uma comparação como condição de teste, o que normalmente significa comparar uma variável com algum outro valor. Por exemplo, talvez Elmer queira oferecer um desconto para clientes que morem em Nevada. Ele poderia criar uma declaração if para executar uma comparação em parte do endereço de envio, desta forma: isto e verdadeiro se a variável fsí>iffi«5__state do«tiver o texto levada" SE o cliente mora em Nevada ENTÃO aplicar desconto } if ($shipping state == 'Nevada') { $total = Esta condição de teste realiza uma comparação de igualdade, a qual envolve dois sinais de igual (==). As comparações de igualdade não são apenas para variáveis e strings. Você pode comparar variáveis com números, variáveis com variáveis e até mesmo realizar cálculos. Um desdohto de 10% e aplidado *a ação, daso a dondiçao de teste seja verdadeira- Vode pode veriíidar se o <ue esiS armazenado em uma variável é ijual ao ^ue está armazenado em outra. ($num items == 10) Mão dolo^ue valores fcumeridos entre aspas. ($shipping addr.ess = = = $billing address) (2 + 2 =— 4: Vode pode e*edutar operações matemátídâs em umâ dondiÇ3o de teste- você está aqui ► 167
  • 198.
    i/ores no php amais do que apenas igualdade Uma declaração if pode verificar mais do que apenas igualdade. A condição de teste da sua declaração if pode também verificar se um valor é maior do que outro, por exemplo. Se for, o resultado da condição é true e o código da ação é executado. Eis aqui alguns outros testes que você pode usar para controlar a decisão de uma declaração if. ComeCe ton> estas duas variáveis. Kao te» problema escrever wma declaraçao l'Ç£m W *3 S Olinbâj desde que a açao seja relativamente simples. $small number = 2; Existem duas formas de se verificar se as coisas não são iguais: <> e !=, Isto lhe dá o resultados oposto de um teste de igualdade com = . $big_number - 98065; ^ a s estas CohdiÇoes são verdadeiras. if ($small_number <> $big_number) { echo 'True'; } if ($small_number != $big_number) { echo 'True'; } O sinal maior que (>) verifica se o valor da esquerda é maior do que o valor da direita. Se for, a condição é true; caso contrário, é false. Esta c©*diça© e íaUa- if ($small_nuinber > $big number) { echo 'True'; } O sinal menor que (<) compara o valor da esquerda com o valor da direita. Se o da esquerda for menor do que o da direita, a condição é true. ^£$ta Co^diça© e verdadeira. if ($small number < $big number) { echo 'True'; } Maior ou igual a (>=) funciona como maior que (>), exceto pelo fato de que ele também resulta em true se os dois valores forem iguais. 'Ç Esta condição e falsa- if ($small number >= $big_number) { echo 'True'; Menor ou igual a (<=) é semelhante a menor que, exceto pelo fato de que também resulta em true se os valores forem iguais. E*ta Condição e verdadeira. if ($small__nuniber <= $big_number) { echo 'True'; } E quanto as strings? Será que ("cachorro" >"gato") funcionaria? Sim, você pode comparar strings em condições de teste A comparação funciona com base no alfabeto, com a letra a sendo considerada como menor do que a letra z. Usar os sinais de maior que ou menor que pode lhe ajudar quando você tem que apresentar informações em ordem alfabética ar> e
  • 199.
    aplicações realistas epráticas m T A S V c o m o uma condição deteste- da declctt-aç-sb li 3uatarefe 4 Interpretar o papel da condfçap deteste- 5? e decidir s&Voce é Verdadeiro 9u Çals9, dadas as seguintes VatiáVels. $my_name = ' Buster' ; $a_number = 3; $a_decimal = 4.6; $favorite_song = 'Trouble'; $another_number =0; $your__name = $my_name; ($favorite_song == "Trouble") ( $my_name = 1$your_name' ) ( $my_name == "$your_name") > ($your_name == $my_name) ($favorite_song == 'Trouble') ($a_number > 9) r <$favorite_food = amburger’) verdadeiro ou(Talso> verdadeiro ou falso
  • 200.
    sinta-se como umacondição de teste solução SÍJsÍT A -SE coniP um a condição de teste da declcU- açã° IÇ - Soluçã? Sua tareia é Interpretar Opapel da condição de te-Ste- ïî e decídlr se Vçce é verdadeiro ou {qjso, dadas as seguintes VarîaVeïs. $my__name = 'Buster’; $a_number = 3; $a_decimal -4.6; $favorite_song = 'Trouble'; $another_number = 0; $your_name = $my_name; ($ a _ n u m b e r = 3) ($ a n o th e r_ n u m b e r = " " ) ^ —T . .—s , . ^ c umd strihfl < % d a d e ir^ou falso & C or> úd^ (yerdadeir^ou falso 0 e uma strmg vazia os domo iguais. Pcvidio às aspas simples, ($ fa v o r i te _ s o n g == " T r o u b le " ) $ e rd a d e iro )o u fa ls o ^a dondiçao na verdade está perguntando se a ($m y_naine « = ' $ y o u r_ n a m e ') v e rd a d e iro ou (fa ls o ) string Buster é igual à . string ufyour_nâme I e ( N>my_name = "$ y o u r_ n a m e ") v e rd a d e iro o u fa ls o «ão ao v^jor dontido na , a . -----— v. variável fyour name- ($your__nam e = = $m y_nam e) (^ e rd a d e ir ^ o u fa ls o l ( $ fa v o r ite _ s o n g = = 'T r o u b le ') (y e rtla d e irj^ o u fa ls o e maior q^e e f. ^ ($ a _ n u m b e r > 9) v e rd a d e iro o u ( p s ^ ) ( $ f a v o r ite _ fo o d (= ^), h a m b u rg e r ’ ) ($ fe rd a d e ira )o u fa ls o Deveria te r 0£, esta aqui e di-fíeil Uma vez. sido , se a N. que esta sendo usado apenas intentao aqui ^ um sinal de igual aqui, isto e na era -fazer uma níi? verdade uma atribuidao (— ), e tompavaçao F c V /crU t ll3.S Id lO fa s nao uma domparadão í—=^- £ «la ? £-, - lAix» ataba sendo verdadeira, porque - Então a condição de teste é a mesma coisa que usamos para controlar qualquer doisa que nao seja O, os loops while no Capítulo 3?? NULL- ou -false t interpretada domo true pelo PttP• v J . É exatamente a mesma coisa. No capítulo 3, a usamos para saber se ainda tínhamos linhas de dados resultantes da consulta, mas podemos pensar em condições de teste mais interessantes para loops while, usando diferentes tipos de comparações. Você verá isso mais adiante no livro..
  • 201.
    aplicações realistas eprática A lógica por irás da validapão de Énviar Ewail Elmer precisa validar os dados que obtem do formulário sendemail.html, para poder enviar os emails. Na verdade, a situação ideal é que o envio dos emails dependa totalmente da validação dos dados. O que realmente precisamos que o PHP faça é tomar uma decisão com base na validade dos dados recebidos pelo script sendemail.php. Precisamos de algum código que diga “se os dados forem válidos, vá em frente e envie os emails”." Mas primeiro nós precisamos obter os dados do formulário e os armazenar em algumas variáveis: $subject = $_POST[1subject1]; $text = $_POST[1 elvísmail']; Isto é tudo de que precisamos para verificar se existem dados em cada um dos campos do formulário. A lógica é su algo como o seguinte: SE S u b ject contiver texto E Body contiver texto ENTÃO enviar email Ou então poderíamos adotar a abordagem oposta e verificar se os campos do formulário estão ambos vazios, em cujo caso poderíamos exibir um aviso para o usuário: SE Subject estiver vazio E Body estiver vazio ENTÃO exibir mensagem de erro Ambos os exemplos têm um problema, porque a lógica deles requer que nós façamos duas comparações em uma mesma declaração if. Uma solução possível é usar duas declarações if.. sendemail.html Aponte seu lápis Escreva duas declarações if para verificar se tanto o assunto quanto o corpo da mensagem do formulário Enviar Email estão vazios. Emita um aviso caso estejam. ..Á ..? .9 :d y .... .t f c r ...M u JL .Lr?..).........k você está aqui ► 171
  • 202.
    íssetQ e empty() Mteseulápis Solupão Escreva duas declaração i f para verificar se tanto o assunto quanto o corpo da mensagem do formulário Enviar Email estão vazios. Emita um aviso caso estejam.. fcí" ’ |sto âqui sao duâs dSpãS Simples, O if (/lubjeet — ” ) 1« rtfra e n i» •»* *b™>5 'atà *~ = = "H ............................................ Colocando a i^stvutâo ií dcnbro ;ÇÍ£kovodese esw*eieu de àtyksr o asswbo fi o tewbo de e vm ail <br />'; da pvinxeirâ, o dodi$o esta dizendo que ambas prcdisâm ser verdadeiras pâra que a instrução ttsQ seja exedutada- A indentaça© ajuda a mostrar onde a dedlarada© i+ interna termina e onde domeça a dedlaradã© ií externa. Fimpões PHP para verificar variáveis Usar == para checar se uma string está razia funciona, mas existe uma forma melhor de fazer isso, através de funções internas do PHP. A função isset() verifica se uma determinada variável existe, o que significa dizer que ela tem um valor atribuído a si. A função empty() dá um passo além e determina se a variável contém um valor vazio, que o PHP define^eeuq^o um 0, uma string vazia (' ' ou "") ou os valores false ou NULL. Assin^sset()§byte‘torna true se um valor tiver sido atribuído à variável, enquanto qite.^mpty{/ só retoma true se a variável tiver sida definida como (j^umjstring vazia, feilsejju Vejamos como essas funções trabalham: fvl dontem um valor*. $vl = 'aloha fvZ c uma $v2 = " - string vazia.. -} Tanto fvl quanto fv2- sao donsideradas domo tendo sido definidas, mesmo que somente fvl tenha um valor- fvZ esta definida? mesmo que dontenha umâ string vazia if (isset($vl)) { if (empty($vl)) { echo ' $vl está vazia<br />'; } if (isset($v2)) { if (empty($v2)) { if (isset ($v3) ) { echo '$v3 está definida<br />'; } I V 5 nac existe- if (empty($v3)) { Somente o dódi^o sombreado e exedutadof! fvl nâo está vazia, ela dontem texto. Assim, esta dondidao if é falsa.. jvZ está vazia porque a string ^ o^ue ela dontem e v32ia ?v3 e donsiderada vazia, mesmo que nem exista..
  • 203.
    aplicações realistas eprátic^ Entendi. Nós podemos usar isset() e emptyO para validar os dados de $subject e $text. Quase isso. Na verdade, nós só estamos verificando se os dados não estão vazios, por isso empty() é o que precisamos. As variáveis de texto $sub j e c t e $ te x t recebem valores das superglobais $_POST [ ' sub j e c t ' ] e $_POST [ 1e lv is m a il ’ ]. Se você testar essas variáveis com i s s e t (), o teste sempre retomará true, independentemente de elas realmente conterem ou não algum texto. Em outras palavras, i s s e t () não lhe mostra a diferença entre um campo em branco e um preenchido. A função empty () verifica se a variável está realmente vazia, que é o que precisamos para a validação do formulário. iSSetO VeífÇfoctse a VatfaVel existe e se está deíltuda. e U l p t / 0 V e tííf c a s e a VorfaVe1tem algum c o n te ú d o . na° existem idíptas * Então qual o propósito de usar issetQ? A função isset 0 é extremamente útil quando você precisa saber se um determinado dado existe. Por exemplo, você pode verificar se um formulário foi submetido através de uma requisição POST repassando $_post à função isset (). Isso acaba sendo uma técnica bastante útil, como você descobrirá um pouco mais adiante neste capítulo. Apowte seu lápis — ------------------- — ----------------- Reescreva as duas instruções if que criamos para verificar se tanto o assunto quanto o corpo da mensagem do formulário Enviar Email estão vazios, porém, desta vez, use a função empty () em vez de == nas condições de teste.
  • 204.
    4) C 0 nte seu lápis SolupãoReescreva as duas declarações if que criamos para verificar se tanto o assunto quanto o corpo da mensagem do formulário Enviar Email estão vazios, porém, desta vez, use a função emptyO vez de - - nas condições de teste.. ' U*»a tha»ada a fwr^ão ewvpiyO substrU» o operador ■''U lZ J / de igualdade í- ~ ) em tada .jk h o jy & e sc.cs.V ™ '^ :íl.l. 3i. ‘^.'r .°. ass^ 1> J,c.° k*fco;do uma das do^diçoes dc teste- 0 «sbnte do códi9o_£ . í ^ £ j ? 5 v f W ' o mesmo que antes- J jX ^ . .J T Í? Á . .L È AW ^ »y" ' ' " ' ^ ’ / ' / E se nós precisarmos executar uma determinada açSo apenas se o campo do formulário nao estiver vazio? Existe uma função notemptyO? Não, mas há uma maneira fácil de inverter a lógica de qualquer condição de teste... o operador de negação. Nós sabemos que a condição de teste que controla uma declaração if sempre resulta em um valor true ou false. Mas e se a nossa lógica determinar que precisamos verificar o inverso do que uma condição nos apresenta? Por exemplo, seria útil saber se os campos do formulário de Elmer não estão vazios, antes de enviar um monte de emails. O problema é que não existe uma função notempty(). A solução é o operador de negação (!), que transforma true em false ou false em true. Assim,!empty () literalmente chama a função empty() e inverte o seu resultado, desta forma: 0 operadov UOT (/) tvans-íWmâ true ei» N faíse ou -false e» tvue- if ( 1 3m.pty ($subject) ) { £sta íondiçâo esta ' perO)u»ta*do u0 daw «po do Assunto esta nao— vâzjo ; ou seja, ele dontem dados?
  • 205.
    aplicações realistas epráticas Preencha as lacunas no código sendemail.php de Elmer, de modo que o email só seja enviado quando tanto $subject e $text não estiverem vazias. Use declaração if e a função emptyQ. <?php $from = 'elmer@makemeelvis.com'; $subject = $__POST [ 'subject']; $text = $ POST['elvismail']; O o Private: For Bm efs use ONLY Write and send an email to rnaffinâ Ftstnnem sendemail.html i í .i í .e .w í i Y .L í í M .4 j à í f i j ) .e ® ^ 0 = : Jy n , /* i . i . . C i •lux-.~J ÍXÍí>.e>3:® - "f-i ’ j f f s' K ’ y® ~ ^ J ^^ $dbc”= mysqli_connect('data.makemeelvis.com', 'elmer', ' theking', 'elvis_store1) or die{'Erro ao se conectar com o servidor MySQL.'); $query = "SELECT * FROM email_list"; $result = mysqli_query($dbc, $query) or die('Erro ao consultar o banco de dados.'); while ($row = mysqli_fetch_array($result)) { $to = $row['email']; $first_name = $row ['first_name ']; $last_name = $row['last_name']; $msg = "Caro(a) $first_name $last_name, n$text", mail{$to, $subject, $msg, 'From:' . $from); echo 'Email enviado para ' . $to . '<br />'; } mysqli close ($clbc); ?> você está aqui ► 175
  • 206.
    sendemail.php—agora com validação! Preenchaas lacunas no código sendemail.php de Elmer, de modo que o email só seja enviado quando tanto $subj ect e$text não estiverem vazias. RCÍCIO Use declaração if e a função empty { ) , 0 ponto de exdlamação inverte a lógida da •função emptyO. <?php $from = ' elmer@makemeelvis .com' $subject = $_POST[1subject' $text = $_POST['elvismail j_f " (Jemptyifsubjedt)) { A (x-imeM íondiçao _ sendemail.html veri<ida se fsttbjctt »3^. esta vazia... ...se nâo estivev> ótimo/ Agora vevi-ficâmos se fte%t não esta vazia- Mós tivemos de dolodar uma dedlaraçao ií dentro da outra, para que o dódigo -Çundionâsse. |sso se dha**>a aninhar. $dbc = mysqli connect(1data.makemeelvis.com1, ’elmer’, 'theking', ’ elvis__store' ) or die('Erro ao se conectar com o servidor MySQL.'); Çquery = "SELECT * FROM email_list"; Çresult = mysqli_query($dbc, $query) or die('Erro ao consultar o banco de dados') while (?row = mysqli_fetch_array($result)) $to = $row['email']; $first_name - $row [ 'first_name ']; $last_name = $row['last_name1] ; $msg = "Caro(a) $first_name $last_name, n$text' mail($to, $subject, $msg, 'From:' . $from); echo 'Email enviado para: ' . $to . '<br />'; } mysqli_close($dbc) Se qualquer uma das variáveis estiver vazia, uma das dedlara^ões ií será íalsa, e nada deste dódigo será e*edutado, o que signlfida que nenKum email em brando será enviado —exatamente o que queríamos ?> N Ó S temos de -finalizar a parte relativa à ação de ambas as dedlarações ií^A primeira dhave -finaliza a dedlaradao ií interna, enquanto que a segunda -finaliza a dedlaração i-f c*terna-
  • 207.
    aplicações realistas epráticas O R t v e Verifique se a validação dos campos do formulário funciona. Modifique o código de sendemail.php para usar declarações if que verifique os dados do formulário antes de enviar as mensagens de email. Envie a nova versão do script para o seu servidor web e abra a página sendemail.html em um navegador. Certifique-se de deixar pelo menos um dos campos do formulário em branco, e clique em Submit. 0 dorpo da n»en$39evn esta vazio, o «uc -(■ a z- os dados do •formulário ■ ( ‘âlVlârem na validaçao. M a te M e E L v ts .e o M Prfrato: F o rSn»rts useONLY WHte and send m ema» to maiiing ijstmembers Suüjeetofemail: BlueSiaede Cíe^rance! Bodyofemail: A ausendia dc doníirmaçoes dc cmâiU revela <ue nada ■ P o i enviado, < ^u e é o ^«e nós ___ queríamos. Mas algum iipo de aviso a<ui seria mais u-fcii do < ^u e uma pâ^ina em brando. você está aqui ► 177
  • 208.
    conversa a três Ese nós tivéssemos um monte de campos no formulário? Teríamos de aninhar um monte de instruções if para validar tudo?? Aliens AbductedMe - Report an Abduction Share your storyof alienabductsoo: rotnwulivio de 0weh, visto an-fccricmrKCnie nesie livy©, e m cxemplo de to*no o -fsip de •fcev-m os mSis tdmfos ! r > 0fov-nnuldvio results C n >i&rmos tdtoben* un* cuonte de detUratozs i-P a*i*Hadas. if (!empty($first_name)) { if (!empty( $last_name)) { if (!empty{$when_it_ ^ " happened)) { if ( !empty ($how__long) ) { LatfBsme WbaisJT M Tejnalsd4re»7 W hendidithappen? How lo«swtrtyooeooe? Howm i dW> * o osee? Detofbe®«ai! What< JS dtheydotoyou? HaveyonstmmyiK«Fane' Anytfetog«fcíj™'*««toadi? Tãnto anm haiw eivfc© -fcov-na di-ffal maivtev o èotttvolc áe quantas òhaves pvetisa»* sev usâdâs e» que leaves. F W J M if ( !empty ($how__many) ) { Joe: Acho que você tem razão. Se quisermos nos certificar de que todos os campos estejam preenchidos, precisaremos colocar uma declaração if para cada campo. Frank: Mas desde que façamos a indentação da linha de cada declaração, estará tudo bem, certo? Jill: Tecnicamente, sim. Quer dizer, o código certamente vai funcionar, não importa quantos if’s nós colocarmos. Mas eu me preocupo se ele não vai ficar difícil de entender, com tanto aninhamento. Colocar as chaves corretamente poderia se tomar um problema. Frank: Isso é verdade. E eu acho que também seria trabalhoso ter de indentar o código de ação que temos até aqui... vejamos, são dez campos no formulário, o que nos dá dez ifs aninhados, com dez níveis de indentação. Mesmo se cada iffor indentado com apenas dois espaços, isso dá 20 espaços antes de cada linha do código. Nada bom. Joe: Mas se indentarmos com tabs, isso diminui pela metade - 10 tabs em vez de 20 espaços não é tão ruim assim Jill: Pessoal, a questão não é o modo como nós indentamos os ifs aninhados. E que simplesmente não é uma boa prática de programação colocar tantos ifs uns dentro dos outros. Pensem desta forma - o que estamos realmente falando é de uma condição de teste lógica, “todos os campos do nosso formulário estão não-vazios?” O problema é que essa condição de teste envolve dez dados diferentes, fazendo com que nós tenhamos de dividi-la em dez declarações if separadas. Frank: Ah, entendi. Então o que precisamos é de uma forma de verificar todos os dez dados em uma só condição de teste, certo? Jill: Isso. Joe: Então nós poderíamos escrever uma só condição de teste gigante, para verificar todos os campos do formulário de uma só vez. Seria ótimo Jill: Sim, mas ainda não temos o pedaço do quebra-cabeça que nos permitirá combinar diversas comparações em uma mesma condição de teste...
  • 209.
    aplicações realistas epráticas teste múltiplas condipões com ANP e OR É possível construir uma condição de teste para uma declaração if com diversas verificações conectando-as através de um operador lógico. Vamos ver como isso funciona com duas condições familiares, !empty($subject) e !empty($text). Este primeiro exemplo envolve duas expressões conectadas através do operador lógico AND (“e”), que é codificado usando-se && . Os fa tie s « e*tras ajudai a dei*ar dlaro « ^u e o cfcrsâc* de ne^adão só se 0 operador apísda a -funçãoemptyO.. ISjito AND- % ^ if {(lempty ($subject) )|!||| (lempty ($text) )) { dondidao de iesie só e verdadeira se tanto fsubjedt «v>a*to fte * t «ao estwere** vazias. O operador AND toma dois valores true/false e lhe retorna true somente se ambos forem verdadeiros; caso contrário, o resultado é false. Assim, neste caso, ambos os campos precisam estar não-vazios para que a condição de teste seja verdadeira e o código de ação da declaração if possa rodar. O operador lógico OR (“ou”), codificado como ] |, é semelhante a AND, exceto pelo fato de que ele resulta em true se pelo menos um dos dois valores true/false for verdadeiro. Eis um exemplo: A 16gicíi do TH? to m pogsíVel elaborat d e c la ra ç õ e s ! Í ma!s elegantes- o A r ^ ló g ic o e c p d i í i c a d o c o m o enc juant9 c(ue 9 O R lêgfco é codificado c o m o ||. if ((!empty($subject)} Es-fca dondida© à t teste é verdadeira se fsvbjedt OU fte x t estiver nâo-vazia. ! | ( !empty ($text) )) â^UÍ hâO £ OyiU lV i^O € duás bâirfâs —íida na parte de dima da Assim, o código de ação para esta declaração if é executado se ^ ^ b â rra mvertida (), no um dos campos do formulário estiver não-vazio. As coisas ficam ainda mais interessantes se você quiser isolar um campo como estando vazio, mas com o outro tendo dados, desta forma: if (empty($subject) (!empty($text) )) fswbjedt^vtdisa estar vazia e fte * t predisa estar nac-vâzja para esta dondidão de teste ser verdadeira- Uma vez que esta condição de teste usa AND, ambas as expressões dentro dela precisam ser true para que o código da ação possa se executar. Isso significa que o campo Subject (“assunto”) do formulário precisa estar vazio, mas o campo Body (“corpo da mensagem”) precisa ter dados nele. Você pode inverter essa verificação passando o operador de negação (!) para a outra função emptyO: M* sé í if ((! empty ($subject))jfjiilí empty ($text)) { h^o estiver vazio e /te *to ^ ^ estiver. Os operadores lógicos AND (ScSc) e OR (||)tornam possível elaborar condições de teste muito mais poderosas que, de outra forma, necessitariam de muitas, e frequentemente bagunçadas declarações if. você está aqui ► 179
  • 210.
    eliminando o aninhamentoda declaração if Reescreva as seções salientadas do scripí sendemail.php para que ele use operadores lógicos em uma única condição de teste, em vez de declarações if aninhadas. <?php $from = 'elmer@makemeelvis.com'; $subject = $_POST['subject']; $text = $ POST['elvismail']; aa ■ „ - cstao nossas dediavações i ía n i n h a d a s . Re-esdveva usando uma u n i d a dedlaradao i íe tom ».»„.m,™™...^ o&eradores l ó g i d o. v e $dbc = mysqli_connect('data.makemeelvis.com', ' elmer' , 'theking', 'elvis_store' ) or die('Erro ao se conectar com o servidor MySQL.'); $query = "SELECT * FROM email_list"; $result = mysqli_query($dbc, $query) or die('Erro ao consultar o banco de dados.'); while ($row = mysqli__fetch_array ($result) ) { $to = $row['email']; $first_name = $row['first_name']; $last__name = $row ['last_name']; $msg = "Caro(a) $first_name $last_name, n$text"; mail($to, $subject, $msg, ’From:' . $from); echo 'Email enviado para: ' . $to . '<br />'; mysqli_close($dbc); P l f fetas thave fetha- P i «------- " as duas d r t lM ^ e . * ?>
  • 211.
    TfeST ORtve_ _ _ _ __ _ _ _ _ _ _ _ _ _ _ aplicações realistase práticas Certifique-se de que os operadores lógicos no script " "Enviar Email” estejam fazendo o mesmo trabalho que as declarações if aninhadas. Modifique o código de se n d em a il -php para usar uma única declaração if que tire proveito dos operadores lógicos para verificar os dados do formulário, antes de enviar as mensagens de email. Consulte a solução do exercício na próxima página, caso não tenha certeza sobre como fazer as modificações. Envie a nova versão do script para o seu servidor web e abra a página sendemail.html em um navegador. Certifique-se de deixar pelo menos um dos campos em branco e clique em Submit. O script ainda impede as mensagens de serem enviadas quando um campo é deixado em branco? m ° existem perguntas id!°tas I - Faz diferença a ordem em que você coloca as duas conexões ligadas por && ou [j em uma declaração if? Sim. 0 motivo é que o funcionamento desses dois operadores pegam atalhos sempre que possível. 0 que isso significa é que, se o primeiro operando for suficiente para determinar o resultado da expressão, o segundo é ignorado. Por exemplo, se o primeiro operando de uma expressão AND for false, isto é suficiente para fazer a expressão inteira ser false, independentemente do segundo operando, de modo que este é ignorado. A mesma regra se apfica quando o primeiro operando de uma expressão OR é true. * vi códigos PHP que usam and e or em vez de && e | | . Como isso funciona? Eles são praticamente a mesma coisa que && e 1 |. Há uma ligeira diferença no modo como eles são avaliados em relação a outros operadores, mas, se você tiver o cuidado de usar parênteses para tornar as suas condições de teste claras, então não haverá nenhuma diferença essencial. você está aqui ► 181
  • 212.
    sendemail.php—agora sem declaraçõesif aninhadas SoLuçâo Reescreva as seções salientadas do script sendemail.php para que ele use CÍO operadores lógicos em uma única condição de teste, em vez de declarações if aninhadas. <?php $from = 'elmer@makemeelvis.com'; $subject = $_POST[’subject’] $text = $ POST['elvismail']; h «. « opevad« MOT 0), í <*»*» ?»> thttzc se Ka dam?os nâo-vazios no Wmulano. ( 1om pty ($oubjoo- t )) { Nós Podemos usar AHT> m m — ii-" ' (!ompty ($tcxt) ) — i . . „ r.. ' ---- ^ r f '? " âmbas as fiondiÇocs, Cmuma .,'í.((!e.^pty(??ubjedt)) s®dediaraçao A ^ Lembre-se, ff é o modo domo vode ........................................................................ espedi&da o ofevador lógido AND- $dbc - mysqli_connect('data.makemeelvis.com', 'elmer', 'theking', 1elvis_store' ) or die('Erro ao se conectar com o servidor MySQL.'); $query = "SELECT * FROM emailJList"; $result = mysqli_query($dbc, $query) or die('Erro ao consultar o banco de dados.'); while ($row = mysqli_fetch array ($result) ) { -rj r. $to = $row [-email']; ^ T l ° dtnhro H O y J - O w L S I Î Î 3 .1 - L j / j j w ' f f * $first_name = $row[ ' first_name ' ] ; edârâÇâo t+ deve ser ^ 1 u ^ ___ ____ (*<_____ r T 1^ i_ ________ I 1 iiMu h f iM I J . $last_name = $row['last_name '3; reduado em umnível de $msg = "Caro (a) $first_name $last_name, Xnítexí^d^taÇao, uma vez. que mail ($to, $subject, $msg, 'From:' . $from) ; agora ele reside dentro echo 'Email enviado para: ' . $to . ' <br />'; uma unida dedlâraÇao ií mysqli_close($dbc); Tendo apenas uma dediaraçao ií, nós só rdisámos de uma dKave de fedKamen-fco. ?>
  • 213.
    aplicações realistas epráticas Os usuários do formulário precisam de uma resposta O código do nosso script sendem ail .php faz um bom trabalho ao validar os dados do formulário, com o objetivo de impedir que emails sejam enviados caso o campo Subject (Assunto) ou o Body (Texto) sejam deixados em branco. Mas quando a validação falha, e não são enviados emails, o script não informa a Elmer o que aconteceu. E U apenas uma página web em branco. £!»er ve esta pa$iwa «luâftdo submete o +o»rmu!ivio... e n3o te» a fn fh o rid e iado porque! que aconteceu? Eu tentei usar o novo formulário e tudo o que recebi foi uma página em branco. O problema é que o nosso código só reage a uma validação com sucesso, em cujo caso ele envia as mensagens de email. Mas se a declaração if acabar sendo false (dados do formulário inválidos), o código não faz nada, deixando Elmer sem saber se foram enviados emails ou não, ou então o que deu errado. Eis aqui o código abreviado, que revela o problema da página em branco: <?php $from = 'elmer@makemeelvis.com'; $subject = $_POST['subject'] ; $text = $ POST['elvismail']; 1 elmer1, 1 theking' mysqli_close($dbc); ^ if ((!empty($subject)} && (!empty( $text)) ) { $dbc = mysqli_connect { 'data.makeimeelvis. com', 'elvis_store1) Nao aóontede *ada se a dedaraça© vf -falhar ao e*e£utar o òód'»y> de atío, eef&r isso < u ee ?> • — ___________— « —"" gerada uma ^a^ma e» bvatóo <<*a«do al^u» tamfo do -Çormulâvio teriKa -fitado e» b^a^áo. Precisamos avisar a Elmer que houve um problema, de preferência dizendo a ele quais campos do formulário ficaram em branco, para que ele possa tentar digitar novamente a mensagem. você está aqui ► 183
  • 214.
    a cláusula else ÉíW " 1 rlfl I Sem problemas. Basta colocar uma declaração echo depois da chave que fecha a declaração if. Isso não vai funcionar, porque o código depois da declaração if sempre será executado. Colocar a declaração echo depois da declaração if só significa que a primeira vai rodar depois da segunda, mas ela sempre roda - independentemente do resultado de if. Não é disso que precisamos. Precisamos que a declaração echo mostre uma mensagem de erro apenas se a condição de teste da declaraçã if for false. Você pode expressar esta lógica da seguinte forma: SE Subject contiver texto E Body contiver texto ENTÃO enviar email X CASO CONTRÁRIO exibir mensagem de erro A declaração if oferece uma cláusula opcional, else, que executa algum código no caso de a condição de teste ser false. Assim, a nossa mensagem de erro é colocado dentro de uma cláusula else, e portanto, só é executado quando um dos campos do formulário for deixado em branco. Basta colocar a palavra else depois da declaração if, e depois colocar o respectivo código de ação dentro de chaves ?subj ect) ) && (!empty($text)) ) { esqueceu do a ssu n to e/o u do corpo da insere o Coá'^0 envia as mensa^e«* de e w â i i -
  • 215.
    aplicações realistas epráticas Segue abaixo o novo código para o script sendemail.php de Elmer, usando declarações if e cláusulas else para fornecer feedback, mas partes do código se perderam. Coloque os ímãs corretamente no lugar do código que está faltando. // Nós sabemos que tanto $subject e $text estão •'faltando <?php ■$from = 'elmer@makemeelvis.com'; $subject = $_POST [ . 'subjectT]; $text = $ POST['elvismail']; // $subject está vazia está certo, enviar emails // $text está vazia ...í±r.. .ÇQ. .e í.3.v.k)^£í. . & } else { ....... // Nós sabemos que um dos dois, $subject ou $ text, está faltando - vamos descobrir qual deles / e-" ■ < 2 r - echo 'Você esqueceu do assunto.<br />'; else ( ■£ echo 'Você esqueceu do corpo da mensagem.<br />'; } else { m . . while ($row = mysqli_fetch_array($result)) { "$to = $row['email1]; $first_name = $row['first_name']; $last_name = $row['last_name']; $msg = "Caro{a) $first_name $last_name, n$text"; __________ mail($to, $subject, $msg, 'From:' . $from); I empty($text) §| echo 'Email enviado para: ' . $to . 1<br />’ — > mysqli close($dbc); ?> você está aqui ► 185
  • 216.
    soiuçâo exercício Segue abaixoo novo código para o script sendmail.php de Elmer, usando declarações if e cláusulas else para fornecer feedback, mas partes do código se £RCÍCÍ0 perderam. Coloque os ímãs corretamente no lugar do código que está faltando. S o L u Ç ã o O i í externo thetà se o assu*-k> c 0 <?php texfco esfcSo vtóos. £e nao Há apenas $from = 'elmer@makemeelvis.com'; ^ 3 opÇoes a»*bas estío preewthidos o $subj ect = $_POST [-subj ect']; / ***»tc esU íalta»do, ou o texto do $text - $_POS.T [ 'elvismail ’ • ]; f £«rpo do e r * > a i lestá íalkndo if jèmpty{$subj ect) empty($text) m ii Nós sabemos que tanto $sub:ject e $text estão faltando else { if |( pempty ($subj ect) I li " ] empty($text) // Nós sabemos que um dos dois, $subject ou $ text, está faltando - vamos descobrir qual deles F m if [( empty ( $subject) J ) // $subject está vazia * rnimèmwlfm m n* ' , /. echo 'Voce esqueceu ao assunto,.<br />'; } else { // $text está vazia echo ’ Você esqueceu do corpo da mensagem..<br />'; } else { // Tudo está certo, enviar emails ~ W íW tw W ? ? W T '' Heste yor>to passages pov while {$row = mysqli__fetch__array {$result)) { ^_ iodos 3s p o s s i b i l i d a d e s , $to — $row [’ email ’]; ^tao, sabemos *we a«*bos $first_name = $row ['first_name 1]; d . 3»pos do Tormwlavio $last_name = $row ['last_name ']; towt«»* v a l o r e s - $msg = "Caro(a) $first_name $last_name, n$text"; mail($to, $subject, $msg, 'From:' . $from); echo 'Email enviado para: ' . $to . ' <br />'; } mysqli close($dbc); ?> A O i? ___ . f - &
  • 217.
    aplicações realistas epráticas Todos esses ifs e elses aninhados estão tornando o script difícil de ler. Eu detestaria ter que trabalhar nesse script! Ele precisa ser simplificado, antes que alguém se machuque.. É sempre uma boa ideia simplificar código sempre que possível, especialm ente, código com muitos níveis de aninhamento. Uma quantidade muito grande de cláusulas e ls e com declarações i f aninhadas pode tomar o seu código difícil de ler. Talvez isso não fizesse diferença caso nós nunca mais tivéssemos que olhar esse código, mas isso é bem improvável. Se algum dia precisarmos modificar o formulário para adicionar um novo campo, validá-lo seria mais difícil do que precisa ser, porque seria muito difícil ler o código e entender onde as modificações precisam ser colocadas. você está aqui ► 187
  • 218.
    o código tflim po Ç íç d n e fo 0 ^ $ ÍH T A -~ S E c o m ò ^ c o j i g p i p S p ] u lç a 9 Sua tareia 4 interpretar o papel do código ip e limpar o código dos lF ’s e EL'SE’s aninhados. ReescreVa o oçdígç de modo a se livrar do anin^ament^, mas ceiti6c]ue-se- de <jue-ela ainda Çunciynará corretamente. if (empty($subject) && empty($text)) { echo 'Você esqueceu do assunto e do corpo da mensagem.<br /> ’; } else { if (empty($subject) | | empty($text)) { if (empty($subject) { echo 'Você esqueceu do assunto.<br />'; } else { echo 'Você esqueceu do corpo da mensagem.<br />'; Aquij estamos } ■testando $ e } else { tanto 3 variável //Tudo está certo, enviar emails fsob'vett <uaKÍ» 1 a f f c - ■ “ vazias a fte * t estso * ■ f (emptyf/subjedO && em pty(fte*t)) { edbo Vode esquedeu do assunto e do dorpo da mewagem..<br />*; Aqui, estamos ........................................................................dodígo verifida se fsubjedt st j- (IfifbjfÍM )'» { ^ ^ ‘ * « tí «âo- ejsubjtói estó . «>!?. V oíí es>ewu do ass»„to. <W / > ) .............. & ^ estivíssemos « a * * „ AND hao-vazia. } ------“ 7 7 !------—------(ff) para isolar o texto «ao-vazio de edKo Vode se esquedeu do dorpo da mensagem .cbr desnedessaria- 0 mesmo 3do*tede para j ------ "**— ---------- ^ fsubjedt e fte * t «âo— vazias. ií ^/e»pty(fsubjedt)) && 9 °perâdor Né)T (0 verí-fida se ^ ^ it; v jh..jr.v/:/...Tyfcvív... ....Tv.ry j . f /1 — t* »t» n 1^0 E y i , « U « „ Tudo fsii ^ ,„yjJr ^ a,|s .................fs“b j “ * ‘ íie%i ts & »*>-«»**• -testando se nem fsubjedt } ............................................................................................................................... nem fte * t estão vazias.
  • 219.
    aplicações realistas epráticas Estou chocado. Quando me esqueci ^ de digitar o assunto no formulário, recebi esta página. Mas quando cliquei no botão Back (voltar), tive de redigitar a mensagem inteira. A validação no script Enviar Email de Elmer está funcionando, mas ela poderia ser um pouco mais útil. Quando o script se n d e m a il.php detecta que estão faltando dados no formulário, ele exibe uma mensagem dizendo que alguma informação está faltando, mas só isso. Não há um link para voltar ao formulário original, por exemplo. E, pior ainda, quando Elmer navega de volta para o formulário original, as informações que digitou não estão mais lá. Ele tem de redigitar o assunto e o corpo da sua mensagem. CXfcÉRESRO O que você faria para melhorar o tratamento de erros do script Enviar Email, de modo a torná-lo mais útil? você está aqui > 191
  • 220.
    regenerando o códigoHTML do formulário Seria legal exibir o formulário junto ( com a mensagem de erro. Será que não j V poderíamos simplesmente exibir o formulário J J ( com echo, no caso de o assunto e o corpo do y ^ ---- - texto estarem vazios? Exibir o formulário definitivamente seria útil, uma vez que assim Elmer não precisaria navegar de volta à página original. Assim, além de apresentar uma mensagem de erro quando um dos campos do formulário é deixado em branco, nós precisamos também “ressuscitar” o código HTML a partir do PHP, usando echo para enviá- lo ao navegador. Este código mostra que o PHP é capaz de gerar código HTML razoavelmente complexo: echo ' <label for="subject">Subject of email:</label><br />'; echo ' cinput id-"subject" name="subject" type-"text" ' . 'size="30 " /xbr />T; echo ' <label for="elvismaii">Body of email:</iabelxbr />'; 1cols="40"></textarea><br />'; :ype="submit" name="submit" value="Submit" />'; Se você estiver achando este código um pouco caótico, é porque ele é mesmo. Só porque você pode fazer algo em PHP, não quer dizer que você deva fazê-lo. Neste caso, a complexidade adicional de se enviar todo esse código HTML através de echo é um problema. O código é tão grande que gerá-lo através do PHP, com a declaração echo, realmente não é uma boa opção... echo ' <textarea id="elvismail" name^'elvismail" rows="8" ajvtdd a visualiza*- a cstvuWa do par-te, e mais -fádil usar aspas simples para esdrever strings de dód.50HTML cm pf}p. tódigo HTML.
  • 221.
    aplicações realistas epráticas Facilite a entrada ea saída do PHP As vezes é fácil esquecer que um script PHP é na verdade apenas uma página HTML capaz de armazenar código PHP. Qualquer código, em um script PHP, que não esteja dentro das tags <?php e ?>é presumido como sendo HTML. Isso significa que você pode fechar um bloco de código PHP e reverter ao HTML conforme necessário, e depois começar de novo com um novo bloco de código PHP. Esta é uma técnica extremamente útil para se transmitir um pedaço de código HTML que seja grande demais para ser gerado através de declarações echo do PHP... como por exemplo, o código do nosso formulário Enviar Email.. <?php Esta ta$ $from = 'elmer@makemeelvis.com'; ?> -Iredha o blodo PHP, nos levando $subject = $_POST['subject' ] $text = $ POST[1elvismaíl’] ; if (empty($subject) && empty($text)) { de volta 30/j sakem0s que tanto $subject e $text estão faltando HTML- ^ echo 'Você esqueceu do assunto e do corpo da mensagem Vbcepode ÇecfecU' e abtíftjocpg de c ó d ig o p j j p p q j^ enV icD :pedctÇ^Sde código HTML de denfto do script?HF- 0 -formulário é dodi-fidado Como HTML noTmàl, vez. < ^u e este código +iCd íora das tags PHP. í <?php- } A tag inidia um novo blodo de dódigo „ vez- *V*e ainda estamos dentro da adao de ií, temos de íedhar a dedlaradão antes de dontinuarmos- if (empty(Çsubject) && (!empty($text))) { echo ' Você esqueceu do assunto.<br />'; . f ((!empty( $subject) ) && empty{$text)) { echo 'Você esqueceu do corpo da mensagem.<br />'; Uma vez. < ^» e ainda estâmos dentro da ação de « •£ , o dódigo HTML só é exibido se ambos os dâmpos do -formulário estiverem vazios. if ((!empty($subj ect)) && (!empty{$text))) { // Código para enviar o email ?> Escreva abaixo qualquer coisa que você considere que esteja limitando este código. Como você o consertaria? .v. ' k :v :.. você está aqui ► 193
  • 222.
    evitando code duplicadocom uma flag Use um flag para evitar código dDplkstíío duplicado O problema com o código anterior é que ele precisa sair do PHP e repetir o código do formulário em três lugares diferentes (um para cada validação). Nós podemos usar uma variável true/false, conhecida como flag, para nos mantermos a par sobre a necessidade ou não de enviar o formulário. Vamos chamá-la de $output_form. Então, poderemos verificar a variável mais adiante no código, e exibir o formulário caso ela seja true. Assim, nós começamos o script com $output_form definida como false, e só a modificamos para true se algum campo estiver vazio e precisarmos exibir o formulário: £*frf*niv ?«^tput_jform inicialmente inicialize $output form como false ^ ° ^ue ° -f<**mulario nao sgrâ exibido a não ser que haja um problema de validado que -faça o valor se modi-fitar. S E Subject está vazio E Body está vazio Estas meKsagefts E N T Ã O exibir mensagem de erro, definir $output_form como true de erro são ^ * 7 K ^ p --------------- . Se um tampo -ror deixado em brando, S E Subject estiver vazio E Body N Ã O estiver vazio a variave! ?output_ •form e de-fmida li^eiramehtí di-ferentes, para mdifiar oU) tampo(s) espedrfidofs) que esteja(m) vasào(s). y EN TÃ O exibir mensagem de erro, definir $output__form tomo tru«, mas o ^ c o m o t r u e j^ -formulário nao e / exibido-- ainda! E N T Ã O exibir mensagem de erro, definir $output_form como true Se ambos S E Subject NÃ O estiver vazio E Body N Ã O estiver vazio os tampos . contiverem y E N T Ã O enviar emails dados, vá em_________ írente e envie os emails. S E $output form for true E N T Ã O exibir formulário Finalmente, veri-fidâmos a variável ?output_-form para ver se o -formulário predisa ser exibido. De uma -forma ou de outra, s© pretisamos que o dodi^o HT/VjL. apareça uma vez. .
  • 223.
    aplicações realistas epráticas Codifique o formulário HTML apenas uma vez Transformar o novo código de validação em código PHP envolve a criação e a inicialização da variável $output_form, e depois garantir que ela vá ser definida ao longo de todo o código de validação. Mais importante é a nova declaração if ao final do código, a qual só exibe o formulário se $output_form for definida como true. <?php $from = 'elmer@raakemeelvis.coin' $subj ect = $_POST [ . ’subject ']; $text = $_POST['elvismaíl']; ■ $.output f o r r r .^ ■ ■ i faI&e; " í , ■ . ^ Mos. driamos nossa hova variavei a«^i, e a AptPVnat 9 c6dígo H7KÎL dependente de uma declaração ÍF, nés eVItamos duplicação de codígo n 9 n p s s p script. de-fi*imos temo -false-. if (empty{$subject) && empty($text)) { // Nós sabemos que tanto $subject e $text estão faltando echo 'Você esqueceu do assunto e do corpo da mensagem.<br />'; } Soutput_±orr c = true; ' if (empty($subject) && (!empty($text))) { echo 'Você esqueceu do assunto.<br />'; íiS ilillB iS ílllc u e ;.■^ _ } Peíme a variável tom otrue se tanto fsubjedt «yd**5 0? te * t estiverem Yãrè *ue o íormuiário seja exibido- Tãmbem deíine a variável £0mo true se fsubjedt estiver vazia- if ((!empty($subject)) && empty($text)) { echo 'Você esqueceu do corpo da mensagem.<br />'; l l l l l l I l l l l B i l É l l ----- t deíme a variável domo true } se fte xt estiver vazia- (!empty($text)) ) if ((!empty($subject)) && // Código para enviar o email í Esta dedaraçao ií vertida a variavel fw tp v t.ío r* * ' e exibe o •formulário daso elâ seja true- A<m í, ja saímos do dódi^o PHP, mas tudo < ^u e estiver antes da } de íedharwe^to ainda é do«siderado domo parte da ação de i-P - neste daso, è o ^ dódigo HTML do íormulario. Kao se esqueça de voltar ao dód'150 PHP e -fedbar a dedlaraçao ií. ^ 0 íódigo ttT/VjL so afârede uma vez. desde <ue resolvemos dolodar toda a io^ida da sua exibidao em uma S Ovaviavei; ?outfut_fcrm. você está aqui ► 195
  • 224.
    os dados doformulário continuam desaparecidos O novo formulário é melhor, mas eu ainda tenho de refazer o que eu já havia digitado corretamente, o que é muito irritante. O HTML sozinho não é capaz de preservar dados de formulários. Quando Elmer submete o formulário Enviar Email com um campo vazio, o script se n d e m a il.php captura o erro e gera um novo formulário. Mas o novo formulário é puro código HTML, o qual não tem como saber nada sobre quaisquer dados que Elmer possa ter digitado anteriormente. Assim, estamos gerando um formulário totalmente novo, como parte da validação, o que apaga quaisquer dados que Elmer possa ter digitado Pados «ue Elmer diyfcou «o íomulâTto- Eli«er adidentalmente dci*ou este dampo em brando- Esta mehsa^e*« de erro sivfovma á Elmer *|ue ele dei*ou um dampo em brando. sendemail.html Iodos OS dâmpos a$©ra estã< vazios, porque este e um íorrrulav-io fcO V O em íolWa sendemail.php 0 -formulário t submeti ao sdript sendemail.pbp ^uândo Elmer dlida no botao Submit Submete Péssimo. Não conseguimos contornar o fato de que um novo formulário terá de ser gerado no script PHP. Nos precisamos de uma forma de preservar quaisquer dados que Elmerjá tiver digitando, colocando-os no novo formulário para que ele possa se concentrar em preencher apenas o campo que acidentalmente deixou vazio...
  • 225.
    aplicações realistas epráticas Aponte seu lápis------------------------------------------ Esboce aqui como você gostaria que fosse o comportamento do formulário de Elmer depois que ele o submete com apenas o primeiro campo preenchido. Em seguida, escreva como você acha que cada um dos arquivos (HTML e PHP) deve ser alterado para executar esta nova funcionalidade. mm sendemail.php ' j) ............. / ..... .............. ..’ jyí-ry.r^r?... você está aqui ► 197
  • 226.
    faça o formulário“permanente"’ - scolápis---------------------------------— — —----- Esboce aqui como você gostaria que fosse o comportamento do formulário de Elmer depois que ele o submete com apenas o primeiro campo preenchido. Em seguida, escreva como você acha que cada um dos arquivos (HTML e PHP) deve ser alterado para executar esta nova funcionalidade. A dc erro â i f t d ât - • > CíCibidâ--- E ste dampo permânede vazi© porque Elmer rtáo digitou hâds nele nâ primeira vez-. •mas o Sdript amdâ se lembra dos dados < ^u e Êl»er digitou e os insere m hevo formulário. B sendemail.php .Cf.sdript PHP assum e, a.ta.rç-fa,dç..... .c.^lbtr o í^mulario,.antes.e depois da submissão. E uma vez. < ^u e o sdript tem adesso a.^uais^uer.dados «ue tçhbam sido dijitados^ ele p<^e ihseriv- esses dados no novo íoy-mulário, íuahdo este fo r gerado, jsto resolve o problema de. Elmer te r f^ue rçdi^itar dados ^ue já tenha..... preendhid©- sendemail.html £e exibirmos p.f^mulario.............. .V^iíi^âfíÇ^te .através do sdript. PHP, podemos eliminar a pagina HTML-, uma.,yez,^ue,o .sdript. PHP.ira. coibir. e prodessar o formulário. Ao fazer isso, o sdript PHP,pode,adessar e..... usar ^uais^uer dados digitados no formulário,. o,^ue.e. impossível,dom..... dodigo .HTML .puro..........................
  • 227.
    aplicações realistas epráticas Um formulário que referencia a si mesmo Como é possível ter o formulário Enviar Email sem o arquivo sendem aí 1. html? A resposta é que nós não estamos na verdade eliminando o código HTML, estamos apenas transferindo-o para o script PHP. Isso é possível devido ao fato de que um script PHP pode conter código HTML, como uma página web normal. Assim, nós podemos estruturar nosso script de modo que ele não somente processe o formulário após a submissão, mas também o apresente desde o início, que é o que se n d e m a il.htm l estava fazendo. A chave para o script sendemail.php ser capaz de desempenhar o papel de se n d e m a il. htm l é a ação do formulário. Uma vez que o próprio script agora contém o formulário HTML, a ação nos leva de volta ao script... um formulário que referencia a si mesmo. fsfâo «'âV s de sendem3sl-WW ~ os usuários *âve$3v5o direiamentí 3^* ° sdript PHP f>ars usar o -formulário. Um formulário HTML c[iie íaça parte de um sctlpt YHF <jue o ptPCesse e contecido como a u tP - r e íe r e n te . Os dados do -formulário são $ubme-£idos do mesmo sdrip*t, o <uâl prodessa e exibe ftovame>vte o -formulário, mãs desta vez. cie preserva os dados já digiiados. Subftie^v-/ Swbmater 0 sdript midialyrente »«ostra c -formulário e depois o prodessa, guando ele t submetido- 0 prodcssament© resulta ou «o envio de emaiis ou na re-exibição do -formulário dom uma mensagem de erro- sendemail.php Para entender o que está acontecendo aqui, pense na primeira vez que Elmer visita a página (script). Um formulário vazio é gerado como código HTML, e é exibido. Elmer preenche um campo do formulário e clica em Submit. O script processa o seu próprio formulário e exibe uma mensagem de erro se quaisquer dados estiverem faltando. Mais importante, o script exibe o formulário novamente, mas desta vez inclui quaisquer dados que Elmerjá tenha digitado. Quando um formulário é inteligente o suficiente para se lembrar de dados inseridos em submissões anteriores, ele é conhecido como permanente... os dados permanecem nele! Os {pOTulátlPS permanentes se lembram <k>s dadps c [ue o usuárfp ja tlVer d ig ita d p c o r r e t a m e n t e . CÉfcEWO Como você acha que podemos modificar a aplicação de Elmer para tornar os campos do formulário permanentes? você está aqui ► 199
  • 228.
    faça a açãodo formulário auto-referente Aponte a apão do formulário para o script Como já vimos algumas vezes, o atributo action da tag <form> é o que conecta um formulário a um script PHP que o processa. Para permitir que o form ulário de Elm er processe a si mesmo, o que é o prim eiro passo para tomá-lo permanente, você direciona a ação do formulário para sendemail.php. Na verdade, o formuláriojá tem o seu atributo action direcionado para o script: 0 atributo adtion da tag <•&*•«*> toneeta 0-formulário a° o prodessa - neste tssc o mesmo sdript sendemail.php que armâz£na o -formulário <form action = nÍHlftlHSÍil|iÍ®" method="post"> L-y_J f f i l Í l I i l Í l l f f l ! l Í Í (_______ _ J A fcsta e umâ tag <-form> padrão, que As V ^ usa P0ST para submeter os dados _ _ / do -formulário ao sdript- Este código funciona, presumindo-se que você nunca renomeie o script e se esqueça de atualizar o código. Mas há uma forma melhor, que funciona em qualquer caso, porque ela não depende de um script específico. Trata-se da variável superglobal interna do PHP $_SERVER[’PHP_SELF’], que armazena o nome do script atual. Você pode substituir a URL do script, na ação do formulário, por $_S£RVER['PHP_SELF'], e então jamais terá de se preocupar em atualizar nada, se algum dia tiver de mudar o nome do script. O único senão é que $_SERVER[’PHP_SELF'] é código PHP, o que significa que você tem de enviar o seu valor através do comando echo, para que ele seja exibido como parte do código HTML, desta forma:: vez- d< estrever o nome do sdript permanentemente no £Ódi$o, podemos instruí— lo a re-ferentiar a st mesmo, usando superglobal 1- <form methott="post"> É claro que usar $_SERVER['PHP_SELF'} em vez do m m e do script não é um aprimoramento espetacular, mas é uma T 3 e h v b ^ i t h t _ das pequenas coisas que você pode fazer para facilitar a __ manutenção posterior dos seus script. vt/L /T J f â fÚ c lZ & flc t 9 riP U le J p s c r i p t a tu a l.
  • 229.
    aplicações realistas epráticas TfeST O rive Teste o novo script autorreferente, com a lógica de validação aprim orada. 0 Modifique o código de sendemail.php de modo que ele use a variável $output_ form para exibir o formulário seletivamente, como mostrado algumas páginas atrás. Modifique também o atributo^ct io n da tag <form> de modo a tornar o formulário autorreferente. Você não precisa mais da página se n d e m a il.htm l no seu servidor web, portanto, esteja à vontade para apagá-lo. Em seguida, envie a nova versão do script sendmail.php para o seu servidor e abra-o em um navegador. Está tudo funcionando? Por âlgum motivo, O script esta mostrando uma me*sa4em de erro, embora o formulário fiáo tinha nem sido submetido... nada bom. Mak^MisELVfs.eoM Private: For Hlinefsuse ONLY WHtearri sand an email tomailing Sistmembers, (^You forgotthe email subject and body S&xt) SSU jtw ltrfew iaii. ... . ■ . t r . fc: *3o t so isso* fo rm u lário amda «ao esta preservando os dados distados. P (vd&temos trabalb© a fa « r! iffPlW ??? W ff? Mas vamos domedãr pelo domeÇo- Logo passaremos para a parte da preservado dos dados. ) Escreva aqui o motivo pelo qual você acha que o script está mostrando uma mensagem de erro na primeira vez que o formulário é mostrado. .. . Ç ju d p . í À * .... ..p.->.. ...-ç/k.. .. ....................................... ............... ' ' / ? * você está aqui ► 201
  • 230.
    verifique o $_POST[‘submit’] Verifiquese o formulário foi submetido O problema é que o script não é capaz de distinguir entre o formulário estar sendo exibido pela primeira vez e estar sendo submetido com dados incompletos. Assim, o script relata o problema de dados faltando na primeira vez que o formulário é exibido, o que é confuso. A questão é: como podemos verificar se o formulário estã sendo submetido? Se tivermos essa informação, podemos nos certificar de só validar os dados quando houver uma submissão. Você se lembra de como os dados são armazenados no array $_POST, quando um formulário é submetido usando-se o método POST? Se o formulário ainda não tiver sido submetido, então o array $_POST ainda não terá sido preenchido com quaisquer dados. Ou, colocando de outra forma, o array $_POST ainda não terá sido definido. Alguma sugestão de qual função poderíamos chamar para ver se o array $_POST está definido? )o issrtO verí-fidâ se uma -Ç unÇ ac variável íoi de-£mtdâ- 2 i f ( l i l l l i l l i i l l i l l i i i l Bstfi deve ser o mesmo nome da ■ bâg <i»puè> usada dom o seu boiao Submit ) { $ualrçuer dodi^o 3<ui so sera e^edu'tado formulário tiver sido submetido- se o Uma vez que todo formulário tem um botão Submit, uma forma fácil de se verificar se o formulário foi submetido é ver se existem dados em $_POST para o botão Submit. Os dados são apenas o rótulo do botão, o que não é importante. O importante é simplesmente a existência de $_POST [ 'submit' ], o que nos diz que o formuláriojá foi submetido. Apenas certifique-se de que o texto 'submit' seja o mesmo do atributo id do botão Submit, no código do formulário. A supejrglokal $_POSTnes permite Veriílccií se um formulário foi submetíclo. Hclo existem ? petgimtas idfotas Como o conhecimento de se o formulário foi submetido ou não nos impede de exibir mensagens de erro de validação acidentais? K : 0 motivo pelo qual as mensagens de erro estão sendo mostradas incorretamente é que o script não consegue distinguir entre o formulário ser submetido e ser exibido pela primeira vez. Assim, precisamos de uma maneira de saber se esta é a primeira vez que o formulário está sendo mostrado, em cujo caso é perfeitamente OK ter campos vazios - não se trata de um erro. Nós só devemos validar os campos se o formulário tiver sido submetido; portanto, a capacidade de detectar a submissão do formulário é muito importante. r:Então por que não verificamos se existem dados diretamente nos campos do formulário, em vez de no botão Submit Seria perfeitamente aceitável verificar $_POST[ ' s u b j e c t ' ] ou $_ p o s t [ ' e l v is m á il' ], mas apenas para este formulário em particular. Uma vez que todo formulário tem um botão Submit que pode ser consistentemente chamado de submit, verificar $_ p o s t [ 1s u b m it' ] lhe fornece um modo confiável de checar a submissão do formulário em todos os seus scripts.
  • 231.
    aplicações realistas epráticas .0scriptEnVicir Emailemdetalhes Attc $text = $_P0ST [ . 'elvismail']; $output__form = false;. ■ if (empty($subject) && empty<$text)) { // Nós sabemos que tanto $subject e $text estão faltando' echo 'Você esqueceu do-assunto e do corpo da mensagem.<br />'.; $output_form - true; if (empty($subject) && (!empty($text))) { echo 'Você esqueceu do assunto.<br />'; $output_form = true; } if ((!empty( $subject)) && empty($text)) { echo 'Você esqueceu do corpo da mensagem.<br />'; $output_form = true; } if ((!empty ($subject)) && (!empty($text)) ) { // Código para enviar o email <form method="post" action="<?php echo $_SERVER['PHP_SELF1]; ?>"> <label for="sub]ect">Assunto do email:</label><br /> <input id="subject" name="subject" type="text" size="30" /xbr /> <label for="el vismail">Corpo da mensagem:</labelxbr /> <textarea id="elvismail" name="elvismail" rows="8" cols="40"x/ textareaxbr /> <input type="submit" name="submít" value="Submit" /> i-have -PetHa a primeira é lsè y . $oucput_fci-ín mosbrâ-leJ pv-edisamos if ($output_form) { ?> </form> <?php ?> você está aqui ► 203
  • 232.
    faça os camposdos formulários “permanentes” Legal. Então agora nós podemos detectar a submissão do formulário e mostrar as mensagens de erro corretamente. Mas ainda não tornamos os campos do formulário permanentes, certo? É verdade. Detectar a submissão do formulário é importante, mas ainda precisamos de uma forma para , m anter os dados permanentes. I Saber se o formulário foi submetido é uma parte importante de torná- I lo permanente, mas não é a única. A parte que está faltando é a que ' toma quaisquer dados que tenham sido submetidos e os coloca de volta no formulário, quando este é re-exibido. Você pode definir um campo de input do formulário usando o atributo value da tag HTML < input> . Por exemplo, o seguinte código pré-define o valor de um campo de input usando o atributo value: V âlo V " tstd CSiríto í»0 • — ele f. scmpve o mesmo, a tèéè vez. < ^ue o -Formulário z mostrado.. ^ Mas não queremos escrever um valor específico de forma permanente no código. O que queremos é inserir a informação retirada de uma variável PHP. Como fazer isso? Lembre-se de que usamos echo para gerar código HTML dinamicamente a partir de PHP, em outras situações. Neste caso, podemos usar echo para gerar um valor para o atributo value a partir de uma variável PHP, desta forma:: A ./-,/• cinput type^subnnit" name^'submit" value="Submit" /> </form> l> n vãriãve! z enviaaa usando-se < in p u t n a m e - s u b je c t” ty p e = " te x t" L < i * t p i n v »vá MfiUW permâWfttes < ^*e Então, o formulário de Elmer pode ser modificado de forma semelhante, se ewioh-èram para tirar proveito dos dados permanentes:
  • 233.
    aplicações realistas epráticas T te S T O R fv e Verifique se os dados de Elmer realm ente estão permanecendo. M odifique o código de sen d em ail.p h p de m o d o q u e ele verifique em $_POST se o form ulário foi subm etido, e adicione tam bém o código ech o p ara to rn a r os cam pos p erm an en tes. Envie a nova versão script p ara o seu servidor web e abra-o em um navegador. E x p erim en te d iferen tes valores p ara os cam pos do form ulário, d eixando um ou am bos em bran co , e subm eta-o algum as vezes. 0 sdv"ipt dc tnviôv* agora mosfarâ umâ menSâge»* de erro ^ando ííWer dei^i um tan»po do forwulario ew > brando, »âs ele mantem os dados digitados anteriormente- você está aqui ► 205
  • 234.
    quando bons DELETESviram maus Alguns usuários ainda estão insatisfeitos A validação do fo rm u lário nos ajudou b astante a lid ar com os clientes insatisfeitos de Elm er, p articu larm en te aqueles q u e estavam receb en d o em ails em branco. Mas n em todos estão felizes. P arece q u e algum as pessoas estão rec eb en d o em ails duplicados... lem bra-se deste cara, do início do capítulo? From: SbertKresíee<et0ert@Krssleesptocket5.biz> Subject: Spam? Dais: October24k£008 12:20:33 PMCOT To; EimerPnesüey<e3m&f@fralæmee3vis.€om> Elmer, r PorfavorwMecomospam Eugosto de ruceteroseimailatfeofertes, mas j: mandoumsó. Nàopreciscrôcefeertrésmensagenstotevözquetsmursaoferta. , Sauteats incomodadocitent«, Ebert Bsie filie«te esta fvustvado por^ue est refiebendo miîltiplas Copias dos emails de £îmer. E lm er sabe que n ão digitou a m esm a m ensagem m ais de u m a vez, o q u e o leva a suspeitar que talvez alguns usuários acid en talm en te ten h am se inscrito n a sua lista m ais de u m a vez. Sem problem as, basta usar a p á g in a /sc rip t de R em over Em ail do capítulo an terio r p ara rem over o usuário, cefto? Infelizm ente, n ão é tão sim ples assim. R em over E lb ert u san d o o en d ereço d e em ail dele fará com que ele seja co m p letam en te apagado d a tabela em ail_list, e com isso ele n u n c a m ais receb erá n e n h u m em ail de Elm er. Precisam os de u m a m an eira de ap ag ar apenas as linhas duplicadas de E lbert n a tabela, d eix an d o um a. Usar a p%mâ de Remover £mail do tafítui® anterior removeria inteiramente o dlienic do bando de dados de £Uer, e fcão e isso o < ^ u e Queremos. _ ® W E R ' > 0 __________________________ D C C É R E S R Q Como Elmer poderia apagar todas as linhas da sua tabela que tiverem endereços de email idênticos, exceto uma?
  • 235.
    aplicações realistas epráticas Hmm. O problema é que há linhas repetidas na tabela, mas não temos nenhuma forma de distingui-las umas das outras. Sem uma forma de isolá-las, qualquer DEIETE que tentarmos usar irá apagá-las todas. Joe: Talvez o nosso formulário Adicionar Email devesse verificar os endereços de email antes de adicionar novos usuários. Isso consertaria o problema, certo? Frank: Excelente ideia. Jill: Sim, isso resolveria o problem a para o futuro, mas nao nos ajuda a lidar com endereços de email duplicados que já estejam no banco de dados. Frank: Certo. E se tentássemos usar um a coluna diferente da tabela para apagar as linhas extras, como por exemplo, Iast_name? .Jill: Também pensei nisso, mas usar um sobrenom e pode acabar sendo pior do que um endereço de email. E se quiséssemos apagar alguém chamado John Smith da nossa lista, usando o seguinte código SQL: DELETE FROM e m a i l _ l i s t ' WHERE la s t_ n a m e = 'S m i t h 1 Joe: Isso não apagaria apenasJohn Smith da tabela; estaríamos apagando também Will Smith, Maggie Smith, Emmitt Smith... Frank: E, isso não seria bom. A probabilidade de sobrenomes se repetirem em várias linhas é maior do que a dos endereços de email, e primeiros nomes seriam ainda piores. Poderíamos perder dezenas de linhas com um a simples consulta. Jill: Exatamente. Não podem os nos arriscar a usar um a cláusula WHERE que apague linhas que querem os manter. Precisamos ter certeza de que podem os especificar apenas aquelas que querem os remover. Joe: Então o que fazer? Não podemos usar e m a il, l.ast_ n am e nem f ir s t _ n a m e em nossa cláusula WHERE. Frank: E não temos outras colunas para usar, na nossa tabela. Parece que estamos sem sorte. Jill: Não necessariamente. O que realm ente precisamos é de algo para tom ar cada linha da tabela identificável individualmente - assim poderíamos especificar linhas sem nenhum problema. E só porque não temos atualmente um a coluna com um valor único para cada linha, não significa que não podem os adicionar uma. Joe: Uma nova coluna? M asjá temos um a estrutura para a nossa tabela. Frank: Sim, mas o que temos não está atendendo às nossas necessidades. Você tem razão, teria sido m elhor se tivéssemos previsto esta situação antes, para que pudéssemos ter elaborado nossa tabela de m odo a evitar este tipo de problemas, mas não é tarde demais para consertar o que temos. Joe: OK, mas que nom e daremos à nossa nova coluna? E que dados colocaremos nela? Jill: Bem, um a vez que o propósito seria identificai" individualmente cada linha da tabela, poderíamos chamá-la de i d e n t i f i c a d o r , ou apenas id, para abreviar. Frank: Ótimo, e podem os preencher a coluna id com um núm ero de identificação para cada linha, de m odo que quando executarmos nosso DELETE, poderemos remover linhas com base em um núm ero individual, em vez de em um endereço de email ou sobrenome. Joe: Exatamente. E um a ótima ideia, não? Fico feliz de ter pensado nela. você está aqui ► 207
  • 236.
    adicionando uma coíunacom chave primária para uma tabela As linhas databela precisamser identificáveis individualmente P arte de to d o o processo de se arm azenar algo em u m banco de dados é que, posteriorm ente, você irá q u erer p ro cu rar esses dados e fazer algo com eles. S abendo disso, é incrivelm ente im p o rtan te q u e cada lin h a de u m a tabela seja identificável individualm ente, o que significa q u e você p o d e acessar cada lin h a especificam ente (e som ente a lin h a em q uestão!). A tabela em ail_list de E lm er faz u m a perigosa assunção de que os endereços de em ail serão únicos. Isso funciona, desde que nin g u ém acidentalm ente se inscreva n a lista duas vezes, m as qu an d o alguém o fizer (e alguém o fará, p o d e ter certeza!), o seu endereço de em ail será arm azenado n a tabela duas vezes... e acabou-se a unicidade! 0 que a tabela de Elmer contém agora: Mais de u»a pessoa pode ter o mesmo primeiro nome, portanto, esta não e uma boa opção para doluna identiíidadora. 0 mesmo a^ui, «ao podemos dontar tom sobrenomes para ídentifidação. Nada na estrutura desta -tabela garante identidade para as linhas- ttst name : lastMiné - Denny Bubbleton denny@mightygumball.net Irma Werlitz iwer@aliensabductedme.com Elbert Kreslee elbert@kresleesprockets.biz Irma Kreslee elbert@kresleesprockets.biz £ embora os endereços de email sejam <y*ase sempre unidos, nâo podemos doníiar sera sempre o daso. Se você n ão tem u m a co lu n a de valores realm en te únicos em u m a tabela, en tão deve criar um a. O MySQL lh e oferece u m a fo rm a de ad icio n ar u m a co lu n a de n ú m ero s inteiros individuais, o q u e tam b ém se ch am a de chave prim ária, p ara cada lin h a da sua tabela. 0 que a tabela de Elmer deveria conter: ---------nretisamos At una neva Coluna <ue dontínha V val°r unido para dada linha da tabela. H » A first.name lastjianiè email 1 y Denny Bubbleton denny@mightygumbaîl.net 2 Irma Weriitz iwer@aliensabductedme.com 3 j Elbert Kreslee elbert@kresieesprockets.biz 4 / irma Kreslee elbert@kresleesprockets.biz Agora «ue esta doluna dontém um valor unido, podemos ter t,f Y de c^ue dada linha da nossa tabela sera realmente unida- 0&dados duplidados nas outras dolunas não a-fetam mais a unididade das linhas, porque a nova doluna id duida disso-
  • 237.
    aplicações realistas epráticas Ei, gênio, você sabe que, se quisermos fazer uma modificação na estrutura de uma tabela, temos de usar um DROP TABL6 e recriá-la do zero. Os dados de Elmer serão perdidos! É verdade que DROP TABLE destruiria os dados de Elmer. Mas o SQL tem outro comando que lhe perm ite fazer modificações em uma tabela existente, sem perda de dados. Trata-se de ALTER TABLE, e p o d em o s usá-lo p ara criar u m a nova co lu n a sem te r d e excluir a tab ela e d estru ir os seus dados. Eis o fo rm ato geral de um a instrução ALTER TABLE p ara se ad icio n ar u m a nova co lu n a à tabela: r 0 nome da tabela 3 ser alterada- 0 nome da doluna a ser adidionada. da coluna [nome_da_tabela ADD nome_da_coluna tipo_ 0 -tipo de dados da nova doluna- Nós podem os usar o com ando ALTER TABLE para adicionar u m a nova coluna à lista e m a il l i s t , a qual cham arem os de id . Nós darem os à coluna id o tipo INT, u m a vez que núm eros inteiros são ideais para estabelecer a unicidade. Algumas outras inform ações são tam bém necessárias, com o revela este código: Queremos adidionar M» diz- ao servidor A1y£#L para h0"‘c da tabela «ue (£pp) uma nova doluna, adidionar I ao valor armazenado nesta geremos alterar. ^ tramaremos de id- para dada nova linha inserida. ALTER TABLE em ail_list ADD id INT NOT NULL AUTO_INCREMENT FIRST, ADD PRIMARY KEY (id) £ste pequeno pedalo de dodigo diz. ao <ue a nova doluna sd é a dhave primária da tabela. Falaremos mais sobre isso mais adiante! / “ e r 0 tipo de dados FíRST instrui o MySQL a +azetr dom «ue a da doluna, INT. nova doluna sea a primeira da tabela. Isto é opdionali mas e uma boa pratida dolodar a sua doluna de identifidâdão em primeiro lugar . Esta instrução ALTER TABLE tem u m m o n te d e coisas aco n tecen d o , e isso é p o rq u e as chaves prim árias precisam ser criadas com características b astante específicas. P or exem plo, N O T N U LL diz ao MySQL q u e é preciso haver u m valor n a co lu n a id —n ão se p o d e n u n c a deixá-la em branco. A U TO _IN CR EM EN T descreve ain d a m ais as características da coluna id, fazendo com q u e ela receb a au to m aticam en te u m valor n u m érico único a cada vez q u e u m a nova lin h a é inserida. C om o o n o m e sugere, A U TO _IN CR EM EN T au to m aticam en te ad icio n a 1 ao ú ltim o valor id usado em u m a linha, e coloca o resu ltad o n a co lu n a id d a sua nova linha. F inalm ente, PRIMARY KEY diz ao MySQL q u e cada valor d a colu n a id é único, m as existem m ais coisas aí d o q u e apenas a unicidade.... você está aqui ► 209
  • 238.
    tudo sobre chavesprimárias As chaves primárias possibilitam a identificapão individual U m a chave prim ária é um a coluna que distingue, em um a tabela, cada linha com o sendo única. Ao contrário das colunas norm ais, que tam bém podem ser elaboradas de form a a serem únicas, apenas um a coluna pode ser designada com o a chave prim ária. Isto cria a possibilidade de se fazerem consultas que precisem apontar um a ou mais linhas específicas. Para g aran tir a u n icid ad e das chaves prim árias, o MySQL im põe u m a série de restrições sobre a co lu n a d eclarad a com o PRIMARY KEY. Você p o d e p en sar nessas restrições com o regras a serem seguidas, no seu trab alh o com as chaves prim árias: Uma ctaVe p r im á r ia é u m a oeluna da sua t a b e l a < jue t e r n a cada linha única. As cinco regras das chaves primárias: Os dados de uma chave primária não podem ser repetidos. lÊBÈÈkA' N u n ca duas linhas p o d em te r os m esm os dados nas suas chaves prim árias. Sem exceções ~ u m a chave p rim ária deve sem p re te r valores únicos d en tro V de u m a d ad a tabela. Uma chave primária deve sempre ter uma valor. Se u m a chave p rim ária fosse deix ad a vazia (N U L L ), ela p o d eria não ser única, p o rq u e outras linhas p o d eriam tam bém sér N U LL. S em pre d efina as ^ suas chaves prim árias com valores únicos! ^ A chave primária deve ser definida sempre que uma nova dffigfcjp linha for inserida. _ jjfW Kr Se ho u v er a possibilidade de você in serir u m a lin h a sem u m a chave XJ prim ária, você co rreria o risco d e te r chaves N U LL e linhas duplicadas n a sua tabela, o q u e acabaria com to d o o propósito. A chave primária deve ser o mais eficiente possível. U m a chave prim ária deve conter apenas as inform ações de que precisa para ser única, e n ad a mais. E p o r isso que núm eros inteiros rendem boas chaves prim árias - eles ^ perm item a unicidade sem exigir m uito espaço de arm azenam ento. jfdQPjp O valor de uma chave primária não pode ser modificado. JSKREm Se ho u v er a possibilidade de você m odificar o valor d a sua chave, você C T co rreria o risco d e acid en talm en te defini-la com o u m valor já usado. L em bre-se, a chave precisa se m an ter única, a q u alq u er custo. A doluna id na tabela de £lmer não tem dados repetidos, tem um valor diíoresvte para cada linha, t automaticamente definida guando uma hova linH â c inserida, e dompadta e não se modiíióâ- Períeita^ s i i n i « l I S I ü l l ü i B i l l i i i i l l i i htliiilí l i l i l j ; i j f J ^ 1 Denny Bubbleton denny@mightygumball.net 2 Irma Werlitz iwer@aliensabductedme.com
  • 239.
    J h mm m , .^ * *m Ê 3 ^ ^ È m Ê È m è ~— T fe s T O R tv e aplicações realistas e práticas Altere a tabela de Elmer e tente inserir uma nova linha de dados com uma chave primária. U sando u m a ferra m en ta MySQL, com o o term in al M ySQL o u a guia SQL de phpM yA dm in, digite a instrução ALTER TABLE p ara ad icio n ar um a coluna de chave p rim ária ch am ad a id : ALTER TABLE email_list ADD id INT NOT NULL AUTO_lNCREMENT FIRST, ADD PRIMARY KEY (id) A gora insira u m novo cliente no ban co de dados, p ara ver se a co lu n a i d é au to m aticam en te d efinida n a nova linha. Eis u m exem plo de instrução INSERT p ara ser usada (rep are q u e a chave p rim ária n ão é m en cio n ad a): INSERT IN TO e m a i l _ l i s t ( f ir s t _ n a m e , la s t_ _ n a m e , e m a il) VALUES ('Don', ’Draper', 'draper0sterling-cooper.com') F inalm ente, em ita u m a instrução SELECT p ara visualizar o co n teú d o da tabela e ver a nova chave p rim ária em to d a a sua glória! Caso te n h a se esquecido, eis aqui a instrução SELECT: SELECT * FROM email_list A nova iolwnâ id c au-fco- ihdircmch-fcada, de modo a femanedev mttã tom a adição da nova Jinha de dados- I File Edit W indow Help Email nysqi> SELECT' * FROII email list;; , • . ; i +----- — — ---- --- 4 . . , -------- --- ; id I iirstjname i last name ; | ema x1 / .1 ; i + + | I ; Denny' I : Bubbleton i dennySrrightygumball.net [ : ! ; 2 IIrma i Werlitz |'iwer@aliensabductedir.e .com 1 ! 3 I Elbert :i Rreslee j elbert@kresleesprockets.biz j | 4 i Irma I Kreslee ! elbert@kreslee3prockets.biz ' ■ J 'jNvS ! . Don | Draper ! drapergsterling-cooper.com ! « 5 rows in set (0.00 C5 sec) você está aqui ► 211
  • 240.
    conversa à três OK,agora cada linha da tabela tem uma chave primária única. Como isso ajuda? Elmer ainda está deletando os usuários com base nos endereço de email. Joe: O problem a é que o usuário precisa especificar as linhas usando a chave prim ária, em vez do endereço de email. Frank: E isso! Então só precisam os m odificar o form ulário para que o usuário digite a ID do cliente, em vez do endereço de em ail. Sem problem as! Jill: N a verdade, h á um problem a sim. O usuário não tem com o saber qual é a ID do cliente sem ter algum a form a de procurar essa inform ação no banco. Na verdade, o usuário não sabe nada sobre a estrutura do banco. Talvez o que precisam os aqui é de m odificar o form ulário, de form a que ele m ostre todos os nom es e endereços de em ail em um a lista, com caixas de verificação ao lado de cada nom e. Seria mais ou m enos assim: Frank: Bonito desenho, mas com o isso ajuda Elm er a isolar um cliente para rem oção, usando a ID? Joe: H m m . E se arm azenássem os a ID do cliente no valor da caixa de verificação? A ID não ficaria visível ao usuário, m as o script teria acesso a ela. Jili: ó tim a ideia. Poderíam os então gerar o form ulário autom aticam ente, em um loop, fazendo um SELECT para obter os dados e depois criando cada caixa de verificação a partir de um a linha dos dados da consulta. Joe: ó tim o . Mas o que acontece quando o botão Subm it é pressionado? Q ual será o conteúdo de $_POST? Frank: U m m inuto Joe, chegarem os lá em um instante. Mas vamos com eçar criando esta p arte do script, a parte que exibe todos os dados da tabela e gera as caixas de verificação...
  • 241.
    aplicações realistas epráticas imãs de Geladeira PH? &My-SoL <img src=”blankface.jpg" width="16l" height="350" alt=’ "’ style="float:right" /> <img name="elvislogo" src=''elv-islogo.gif" width="229" height="32" border="0" alt=”Make Me Elvis" /> <p> Por favor selecione os endereços de email a serem apagados e clique em Remove. </p> <form method="post" action=" echo $_SERVER['PHP__SELF']; > <?php $dbc = mysqli connect('data.makemeelvis.com'r 1elmer', 'theking’, 'elvis__store' ) or die('Erro ao conectar servidor MySQLr.’); // Exibe as linhas com os clientes e as caixas de verificação para apagá-los $query = "SELECT * FROM email_list"; $result = mysqli_query($dbc, Squery); while ( = mysqli_fetch_array($result)) { echo ’ <input’ type="checkbox" value="1 . • name="todelete[]” />’; .............................. echo ' echo ’ ’ . echo ’ ' . echo '<br />'; mysqli_close($dbc) ; ?> </form> <input type="1 submit" name=" im " value="Remove" />
  • 242.
    ímãs php &mysql - solução imãs de GeladeiraTH? &M/SQL - $ojuçã° Use os ímãs abaixo para completar o código do script Remover Email, o qual deverá apresentar uma caixa de verificação para cada cliente presente no banco de dados de Elmer. Repare que este código apenas cria o formulário; por enquanto, não se preocupe com o código que realiza o DELETE. <img src="blankface.jpg" width="161" height="350” alt=’ "' style="float:right" /> <img name="elvislogo" src="elvíslogo.gif" width="22 9n height="32" border="0" ^ alt="Make Me Elvis" /> dodí^c <p>Por favor, selecione os endereços de email a serem apagados e clique em de èmds U irtá Remove.</p> <form rnethod="post" action=" <?php ícho $_SERVER ['PHPJ3ELF ']; Bste dódigo c autorre-Pevente/ ?> ik ser dol< dentro dJ % <??4 <?php e ^ $dbc = mysqli_connect(1data.makemeelvis.com' , 'elmer', 'theking', ’ elvis_store’) or die('Erro ao conectar ao serviço MySQL.'); // Exibe as linhas com os clientes e as caixas de verificação para apagá los $query = "SELECT * FROM emailJList"; $result = m y s q l i_query($dbc, $query); while ( íd echo '<input type='’ checkbox" value=" ' . name="todelete[]" />’; fir s t name £ a < wo u t â í-Kave primavial e usada nas daixas de veriíida^ac —podemos «sar ísto a^ui mais adiante, para remover «^uais^uer usuários seledionados Cada dai*a de veri-Pidadao t donstvvfda a pârtir de uma iinK a de dados dos diientes. } mysqli_close($dbc); ?> <input type="submit" name=r </form> submit. value="Remove" /> 0 sdript a'mda nâo esta apagando nada- Por enquanto, ete apenas apresenta uma lista de daíxas de veri-hdâdao. l/ode pode dar ^uaí^uer nome nuisc'r 3o seu botã© Submit —m < 3s predisará lembrar-se do nome posteriormente, daso dedida usar f_PO£T para verilidar se o lormulirio íoi submetido. removeemail.php
  • 243.
    aplicações realistas epráticas Pas caixas de verificação até as IPs dos clientes O código p ara as caixas de verificação geradas pelo script R em over Em ail é sim ples HTM L, com a nossa chave prim ária (id) colocada n o atributo valor d a tag <input>. N o entanto, hã um a p eq u en a, porém , m uito im p o rtan te m odificação em relação ao código H TM L com um . Você pod e te r rep arad o que h á colchetes ([ ]) no final do n o m e da caixa de verificação - eles servem a um propósito vital. echo 'cinput type="checkbox" value="' . $row['id!] name="§tílÍ®S|i#|i|si, l >'; Os colchetes resultam n a criação de u m array d en tro de S_POST que ^ toltHetes ao arm azena o conteú d o do atributo (valor) de cada caixa de verificação m arcada n o form ulário. U m a vez que o atributo value de cada caixa contém u m a chave prim ária, cadavalorno array todelete é a ID de uma Unhadanossa tabela que precisa ser apagada. Isso nos possibilita fazer um loop através do array todelete e em itir um a consulta SQL p ara apagar cada cliente m arcado no form ulário. -Ç inâl do da d t veri&daÇâ© aiA-fcomaiií-ametvte eolodsm os valores da e** w ôv-vay a demos o «ome "Wele-beCÍ3 - c « x M a te tfe E L v fs x o M Cada tai*a de te» a ID do dien-te armazenada, tfs. ,ue Íiía aíessfvel atvav» da suferjlobal f J W . d r a p e w g stsilin a n a e a p e ,..O T ( T . Entendi. Podemos simplesmente usar um loop com while para fazer um ciclo através do array todelete e apagar cada um dos clientes usando as suas lbs. Nós poderíamos usar um loop while, mas há uma solução mais elegante que usa um tipo diferente de loop. O lo o p fo reach é um tipo especial de loop elab o rad o especificam ente p a ra se fazer u m ciclo através de valores arm azenados em u m array. Tudo o q u e você precisa fazer é especificar o array através do qual q u er fazer o loop, além de u m a variável o n d e arm azen ar os valores, e o PH P cu id ará d e fazer as iterações neles, u m p o r um ... n ão é necessária n e n h u m a condição de teste! Escreva aqui como você acha que um loop foreach poderia fazer iterações através de um array contendo as IDs dos clientes de Elmer: você está aqui ► 215
  • 244.
    anatomia de umloop foreach Fapa loop através de um array com foreach O loop fo reach to m a u m array e faz loop através de cada elem en to do array sem a necessidade d e u m a condição d e teste n em u m co n tad o r de loops. A m ed id a que passa através d e cada elem en to do array, ele arm azena o valor desse elem en to em u m a variável tem p o rariam en te. A ssum indo-se que o array está arm azen ad o em u m a variável ch am ad a $custom ers, este código faz o loop: 0 array através do <uai vede deseja £ med.da o loop passa através de ía « r o loop aparede primeiro elemento do array, ele os armazena temporariamente em uma variável dom este lUtÜill ( ^ c u s t o m e r s a s C u s t o m e r ) { nome. a c h o $ c u s t o m e r ; Dentro do loop, vode pode adessar dada elemento, usando o nome da variavel- Assim, se quiséssem os fazer u m loop através das IDs dos clientes arm azenadas n o array $_PO ST do script R em over Em ail, po d eríam o s usar o seguinte código com foreach: o array t armazenado dentro da superglobal f^POST, e t identi-fidado por "todelete”.” Cada elemento do array íida adessfvel através da variavel fdeiete id- f o r e a c h a s 11«« 1 » < k í*silílflffllim liiiil / / A p a g a um a l i n h a d a t a b e l a }; Podemos usar ?delete_jd para remover dada um dos dlientes do bando de dados. A variável $ d e l e t e _ i d arm azena o valor de cada elem en to d o array à m ed id a q u e o loop passa p o r eles, u m de cada vez. $delete_id ^ Podemos usar es-i variavel para ade a ID de dada dlit « entao apa«á-l© tabelay Pleaseselectmeemail addressestodeleteiromthe emaS listsna dick Remove, jg Denny Bubliletcn d e n n y @ m ig h ty g u m tiaii net ^ Ima Wurfitt iwer©a ItensEtKJjctsiime oom □ BberttíreáeeelbertetoBsleesprictetsJíli - " g Irma Kre&iae elbert@«resieesproârate.biz |g Don Draper arapergsfeflwg-oo^er com Com o loop f o r e a c h agora passando através da cada caixa m arcad a no fo rm u lário R em over Em ail, só precisam os adicionar algum código d en tro do loop p ara em itir u m a consulta DELETE, a qual fará a rem oção p ro p ria m e n te dita de cada lin h a m arcada. J'/os donstruímos o ârrây de íorma tal <ue ele so armazene os dlientes < ^ »e tiverem sido mardados no íormulario Remover Email.
  • 245.
    aplicações realistas epráticas Complete o código do novo e melhorado script r e m o v e e m a i l . p h p de Elmer, para fazê-lo excluir os clientes que tiverem sido marcados no formulário, quando este for submetido. $dbc = mysqli_connect(1data.makemeelvis.com', 'elmer', 'theking', ' elvis_store' ) or die{'Erro ao conectar no servidor MySQL.'); // Exclui as linhas dos clientes (somente se o formulário tiver sido submetido) i f { ) í foreach ($_PÒST['todelete'j as $delete_id) { } echo 'Cliente(s) removido(s).<br />'; } // Exibe as linhas dos clientes com caixas de verificação $query = "SELECT * FROM email_list"; $result = mysqli_query($dbc, $query); while ($row = mysqli_fetch_array($result)) { echo 'cinput type="checkbox" value="' . $row['id’] . '" name=”todelete[]" />'; echo $row[’first_name']; echo 1 ' . $row[’last_name']; echo ’ ' . $row['email']; echo 1<br />'; } mysqli_close($dbc); ?> cinput type="submit" name="submit" value="Remove" /> </form> removeemail.php você está aqui > 217
  • 246.
    the revised removeemaii.phpscript Complete o código do novo e melhorado script r e m o v e e m a il . p h p de Elmer, para fazê-lo excluir os clientes que tiverem sido marcados no formulário, quando este for submetido. Çdbc = mysqli connect(1 data.makemeelvis.com', 'elmer', 'theking1, ' elvis store') ~ ~ or die('Erro ao conectar no servidor MySQL.'); So exdluir os dlientes se o ientes (somente se o formulário tiver sido submetido) echo 'Cliente (s) removido(s) .<br />'; } // Exibe as linhas dos clientes com caixas de verificação $query = "SELECT * FROM email_list"; $result = mysqli_query($dbc, $query); while ($row = mysqli_fetch_array(Çresult)) { echo 'Cinput type="checkbox" value="' . $row['id'] . ' " name=Mtodelete[]" -Pormulario tiver sido submetido^ flV íÇ T Y -— PRO/yj. e»aiMist INHERE id ^ fdelete^d”; foreach ($ POST['todelete'] as $delete_id) { esdolHer o dlientc a ser e% dluído- or d'»e(lforro Consultando o bândo de dãdos/)j />'; echo ' 1 . $row['last name']; echo ’ 1 . $row[1email1]; echo '<br />'; 0 dodi$o fâra ^erar as daixas de dada dlientc e o mesmo de antes. ?> mysqli_close($dbc); <input type="submit" name="submit" value="Remove" /> removeemsil.php </form> O HQ a
  • 247.
    ----- T feS T D r î v ë _______ _________ aplicações realistas e práticas Teste o novo e aprimorado script de Remover Email de Elmer. M odifique o código do script r e m o v e e m a il .p h p de m o d o q u e ele gere caixas de verificação p ara os clientes, em vez de u sar o velho cam po de texto com os em ails. Em seguida, adicione o código p ara excluir os clientes sem pre q u e o fo rm u lário for subm etido. A lém disso, m odifique o atrib u to acd o n d a tag <form > p ara to rn a r o fo rm u lário au to rreferen te. A gora q u e r e m o v e e m a il. p h p usa um fo rm u lário au to rreferen te, você n ão precisa m ais d a p ág in a r e m o v e e m a il. h tm l n o seu servidor web, p o rtan to , esteja ã vontade p ara apagá-la. Em seguida, envie a nova versão de r e m o v e e m a il .p h p p ara o seu servidor e abra-o em u m navegador. M arque as caixas de alguns clientes e clique em Subm it. O fo rm ulário au to m aticam en te se m odifica p ara in fo rm ar a rem oção dos clientes.. P leas©selecttheem ailaddressestodeletefro m »10em ail listandclickR em ove 0 D ennyB u b b tetonctennyentightygufflballnat 0 lim aW u rlilziw ergaitensabductedrne.coffl 0 E lb ertK resleeeJbengkresteesprockets.'D iz g tm al^esle« Q Don Draperdrapef@sterl)ng-coop«r.oom ^ R em ove3 Quando vote u» dieh-fce e dlida em Subwrb «le e ve»*ovido do bando de dados- H ^ M e E L v ? s . c o f S S S S 1 “ “ ® * “ " « '™ ''* « .! r emoved^ --- ,W er@ 8J,er^M ucted^ « Qaben ^ eéeJbsrt@ ft^ MMêi8t&iz O^l^perdraps^tefing-coQper.cDm 0 sdvift dowiiVrtiS 5 rcm nodao do dlîttvU e tânnb«» atualiz-a a lista - o dliewte e*twido não apavede »ais. â você está aqui ► 219
  • 249.
    aplicações realistas epráticas Suacaixa de ferramentas PHP £ M ySQ l Você embolsou uma boa quantidade de tiovas habilidades em PHP e MySQL ao trabalhar para fazer a aplicação de Elmer subir de nível. você está aqui ► CAFiTÜLO 4
  • 251.
    aplicações realistas epráticas 5 T m t a U i a n d o c o m D a d o s A í n i c t z e n a d o s em Ar^ufVog > Quando umBanco de , Dados Não é o Suficiente* Não acredite no hype... pelo menos não naquele sobre os bancos de dados. Certamente os bancos de dados são maravilhosos para se armazenar todo tipo de dados que envolvam texto, mas e quanto aos dados binários? Coisas como imagens JPEG e documentos PDF? Faz sentido armazenar todas essas figuras da sua coleção de palhetas raras de guitarra em uma tabela de banco de dados? Geralmente não. Esses tipos de dados normalmente são armazenados em arquivos, e nós os deixaremos nos arquivos. Mas é inteiramente possível ter o melhor de dois mundos - este capítulo revela que você pode usar arquivos e bancos de dados juntos para criar aplicações PHP cheias de dados binários. este é um novo capítulo ► 223
  • 252.
    guitar wars precisade captura de tela Guitarristas virtuais gostam de competir A p aren tem en te, o conceito de arte p ela arte n ão é m ais o suficiente, p o rq u e os jo g ad o res do novo G uitar W ars estão fascinados com a possibilidade d e to car g u itarra virtual com petitivaxnente. T anto que eles reg u larm en te publicam as suas m aiores p o n tu açõ es n o site do G uitar W ars, cuja m a n u ten ção você agora está en carreg ad o d e fazer. O p ro b lem a é que, atu alm en te, n ão h á u m b om sistem a p ara se verificar as pontuações. A aplidaçao guitar W ars permite os usuários ddidionem ás suas pontuações à lisia. Sem àljuma -forma de veri-Pitaçao, não temos domo saber c^uais pontuações sao legítimas e <w ais *a© são. Não dá para confiar no texto D o je ito com o fu n cio n a agora, os jo g ad o re s estão p u b lican d o as suas po n tu açõ es sim plesm ente com o texto, e tem havido m uitas discussões sobre quais po n tu açõ es são reais e quais n ão são. Só existe u m a fo rm a d e p ô r u m fim a todo esse bate-boca e co ro ar o verd ad eiro cam peão do G uitar W ars...
  • 253.
    trabalhando com dadosarmazenados em arquivos 0 roek À imagem é a prova O que precisam os p ara d eterm in ar q u em está falando a verdade o u n ão é de algum tipo de verificação visual. Assim, a aplicação G uitar W ars terá de p erm itir q u e os usuários subm etam u m a cap tu ra de tela co n ten d o a sua p o n tu ação , q u an d o forem in clu ir esta últim a. Isso significa q u e a lista dos reco rd es não co n terá apenas pontuações, nom es e dadas, m as será tam b ém u m a lista de im agens (telas cap tu rad as). a vev>í'ítâ^Ío C ^ u cUdxc í ^ awd€- A d t Belftâ t vcvdadeiv-a, tomo ^roVâ â eiâ enviow. S 9 t s t ' í td tx , ^scudortro^uciro e •taUiíidâdor do éjwiav V V avs. você está aqui ► 225
  • 254.
    o design daaplicação guitar wars A aplicapão precisa armazenar imagem D o je ito com o está, a aplicação d e recordes do G uitar W ars registra três tipos d e inform ações: a d ata e h o ra de u m a nova p o n tu ação , o n o m e d a pessoa q u e a está su b m eten d o e a p o n tu ação p ro p riam en te dita. Essas inform ações são digitadas através de um fo rm u lário q u e faz p arte d a in terface d e usuário d a aplicação, e depois disso, são arm azenadas em u m a tabela ch am ad a g u i t a r w a r s , em u m b anco de dados MySQL.. Guitar Wars - High Scores y r i y m y .Otiimr w aTPOT An yop k»™*w het it tala» ciadc ihe high score list? Tf so ■ just add vom own score. ^ tak adidione a s«a pontuada©" na pagsna prmdipal^de djuitar tYars, £ vô * P|9ihá Adidionar PontuadJío. 127650 N am e: Paco Jaflctii» 2008-W-2Z 14:37:34 98430 Vatng;N cV fiJofraD isO U D ate: 200S'0+-22 21:27:M 345900 jia aie: Eddie V aaiffi D ltts 200804-23 0 9 * 6 Í55 i 282470 ! N anK i Bciüii Chevy i D »tK 2008-04-23 09:12:53 j 368420 ! N ym e: Asfeaon Simp«** ! D ite 200S-04-23 09:13:34 A página Adídioftâr PontwâdâO Z apresenta um ■Pormulario para se distar o nome e a pontuada© (3 data e a bora sao awtomâiidament« obtidas a partir da data e bora do »omento da inserÇâo)- 0 novo registro e doft-fivmâdo; para <^uey o usuário saiba < ^ u e cie ío i adidionado dom Sud€SS© . GuitarWars-AddYourHighScore Thacksforaddicgyournsw high scare!
  • 255.
    IZ Z 4 mbe e iso §ooa oçócm Ez-to-sooz zjjab ^ :3 bi9 0€6t9 ; K O T 60K -W W C K:w » aI TO $xfaq$acU^Y53CW X ! ozmz I íot'605 z *K r8 o o r;«*a X a «Ò J * = * X! O L fZ S ZI SS30-60 £C-tÜ^00£ :a » Q í H P T C À^ P P 3- * 3 * Nf 006£f£j « F C Z -U W tO U O G ïi:a w af u o s s n r u o f : « r e oetsó çnoO B B faxâ:ann»N I QÇ9LZI j ’ ‘ o ç j i i i ^ a ï o o s q  q w p ^ o c a î ^ ï B î ï ï  i i A v a A f i i i i i O A o p ' i c i p j B ^ j i e i t n ^ ' s c i o a p j f tj I «M oagq3ga-sxsfajei|nf>| ^ * r* > ’ ? guiWá e« ayo-ejeip*“'- ' ' ope«°WPe — iut^-A OJCpfo* 0 -epeu^ua epe? e -A Ç < i e 3 3«*O M o çwyzçwjie vu»c|«*e^ •sopep ap o^ue^ op sJierM Ç^w^ ep<^ e opeuo^ipe 3 aVjqstÇa* »A O « o ^e^o^lpV wí A Ç ?H ? 3 o ek ^ w °i Ç sM *í fjíttc« «ífl « ty •s^e^ oe^ç?ij<Je e epi^-Svui^ns iO £ opjert^M O tl ç opue*> ap e ^ s (e-«>s e 3) q-çp e ? *e ^ « « j epe? çjiçi 3^«3*ue?i^e«*oc).»»e epe-fisS » » sopep sp O^UÇC| op ÇMÇmíwA 3a6^? e » <jj ewp? soainbje tua sopeuazeuue sopep tuoo opueqieqej)
  • 256.
    comente o código Rcício Aaplicação dos recordes do Guitar Wars terá de ser modificada para acomodar a nova necessidade de se enviar arquivos gráficos. Circule e escreva comentários nas partes da aplicação que terão de se modificar para atender ao novo requisito. <html xmlns=”http://www.w3 . org/1999/xhtml" xntl:iang="en" lang="en’ ’ > <head> <title>Guitar Wars - Maiores Pontuações</title> clink rel="stylesheet" type="text/css" href="style. css" /> </head> <body> <h2>Guitar Wars - Maiores Pontuações</h2> <p>Bem-Vindo, intrépido guitarrista! Você é bom o suficiente para entrar na lista de recordes do Guitar Wars? Se for, clique aqui para adicionar a sua pontuação. </a>.</p> <hr /> <?php // Conecta-se ao banco de dados $dbc = mysqli__connect (’ www.guitarwars.net’, 'admin', 'rockit’, 'gwdb'); // Obtém os dados das pontuações a partir do MySQL Çquery * "SELECT * FROM guitarwars"; $data = mysqli__query($d’ a c , $<iuery) ; / / Faz um loop através do array contendo os dados das pontuações, formatando-os como HTML 1 <table>'; while ($row = mysqli_fetch_array($data)] { // Exibe os dados das pontuações echo '<tr><td class=’ 'scoreinfo">' ; echo '<span class="score">' . $row['score1] . '</spanXbr />'; echo ' <strong>Name: </strong> ' . $row['name' ] . '<br />'; echo 1<strong>Date:</strong> 1 . $iow[’date'] . ' </td></tr>' ; . ) echo ’ </table>'; mysqli_close($dbc) ; </body> </html> 7T ____ ( style, css Hsfce â*r^ u iv< > pm edisa se »»odi-Pida*-, P<*"bivfco v© de *2° fredisa sc p'reodupav dor* ele- index.php O código-fonte com pleto d a aplicação G uitar W ars está disponível p a ra dow nload n o site da Alta Books: www. altabooks.com. br ÇTuitarw ars
  • 257.
    trabalhando com dadosarmazenados em arquivos " - - - , 1 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" iang=”en"> <head> <title>Guitar Wars - Adicione o seu Recorde</title> <link rel="stylesheeT:" type="text/css" href="style.css" /> </head> <body> <h2>Guitar Wars - Add Your High Score</h2> <?php if (isset($_POST[1 submit'])) { // Pega os dados em POST $name = $_POST[r name’] ; $score = $_POST['score' ]; if (!empty($name) && ! empty($score)) { // Conecta-se ao banco de dados Sdbc = mysqli_connectCwww.guitarwars.net', ’admin1, ’rockit', 'gwdb'); // Escreve os dados no banco $query = "INSERT INTO guitarwars VALUES {0, NOW(), ’$name’, '$score')"; mysqli_query{$dbc, $query); // Confirma êxito com o usuário echo ' <p>Obrigado por adicionar o seu recorde! </p>’; echo 1 <p><strong>Nome:</strong> 1 , $name . '<br />'; echo ’ <strong>Pontuaçâo:</strong> ' . Çscore . '</p>r; echo '<p><a href=”index. php">S11;S11; Voltar para a lista dos recordes.</a></p>'; // Limpa os dados da pontuação para limpar o formulário SNome = ”" ; $Pontuação = mysqli_close($dbc); } else { echo '<p class="error">Por favor, insira todas as informações para adicionar seu recorde.</p>’ 1 ) ?> <hr /> <form method="post” action="<?php echo $__SERVER['PHP_SELF']; ?>"> <label for="name">Name:</labelxinput type="text" id="name" name="narae" value="<?php if (!empty (Çname) ) echo $name; ?>" /Xbr /> <label for- score"i>Score;</labelXinput type=”text" id—"score” name=,rscore" value="<?php if (!empty($score)) echo $score; ?>" /> <hr /> <input type="submit" value="Add" name="submit” /> </form> addscore.php você está aqui ► 229
  • 258.
    código guitar warscomentado A aplicação dos recordes do Guitar Wars terá de ser modificada para acomodar a nova necessidade de se enviar arquivos gráficos. Circule e escreva comentários nas IC IC lO partes da aplicação que terão de se modificar para atender ao novo requisito. S o L u Ç ã o ______________________________ C n tm l x iril,n 5s=,Th t t p : //w w w .v r 3 . o r g / 1 3 9 9 / x í - t m l ” x r n l : i a n g - Me n M l a n g = ,Te n ,T> <head> < title> G u ita r Wars - Maiores Fontuações</i.ítIe> < i i n k r e l ^ ’ s t y l e s h e ^ t " t v p é = Mt @ x t / c s s ” h r e f = Ms t y l e . c s s " / > < /b e « d > <bodv> < h 2 > G u i t a r W a rs - M a io r e s P o r . t t a ç õ e s < / h 2 ?' < p > W e lc a r e , B e m - V in d o , i n t r é p i d o g u i t a r r i s t a . ! V o c ê é bo m o s u i i c i e n t ê p a r a e n t r a r n a l i s t a d e r e c o r d e s d o G u it a r W a rs ? Se f o x , c l i q u e ã q u i p a r a a d i c i o n a r a sx ia p o n t u a ç ã o . < / & > • < / p > < h r /> - a r s . n e t 1 , < ? p h p ,/,/ C o n e c t a - s e a o b a n c o d e d a d o s $ d b c « iT iy s q li c o r .r .e c t [ *www , g u i t a r v 1 çvrdcT ); / / O b térr. o s d a d o s d a s p o n t u a ç õ e s a p a r t i r FROM ç u i t a r w a r s " ; ■í$dbc, 5cfiiery); S q u a r y = "S E L E C T Çdata = mysqli_query( // Faz um loop através do array HTML T<ta.ble>' c c n t e n d o o f o r m a t a n d o - o s ^o m o m m - m ^ í w /• w hile <$row - n y sq li_ fetch _ arrav (S d ata)) / / Exibe os dados das pontuações i Hii I m -1 -!laRA=M sco reinfoT ,> '; echo ’cspan cl5SS»T rscoreM >' , ?x.6nTf echo '<strong>Narre;</strong> ’ . $ro echo ’<strong>D ate:</$trong> 1 :ho T </table>'; 0 arquivoda im age,* p«£isa ser obtido a Vce* deve “ *■* validação partir d« dados de ierti-fiiar-se dc POST. *lue ° Mmfo do nome da imagem não esteja vazJa ■w3.olg/aS99/xhtml" xml:Iang= irvsqli_ciose ($ábc) ; ?> / imagem tomprovando </body> â pow-UaçSo ^retisâ ser </hrira> cabida ** imagem precisa ser para o usuário, para se totuíirmar o exrto. <htmi xnüns="htqp:// <heaS> <title>Guitar Wars - Add YcVr High Score</tiile> <link rel="stylesheet" typeAr-ext/css" href="style </head> <body> v < h 2 > G u i t a r W a rs - A d i c io n e o s e i^ R e c o r d e < / h 2 > <?php j f i s ^ p n S T f s i M i f ; n i // Pega os dados emP O S T íname = $_PO ST['nam e1 i; Sscore = $__POST. [ 'scora*] (rfl^Têmpty l í l l í U l I t í ) K ' i empty iísroisrK1 Conecta-se ac banco de dados J / tonsulta £$L-.agora preòisa inserir *a -tabela guitar^« o nome do ar^uWo <ue tontém a imagem- S d õ c - ir i y s q li _ c o n n e c t ( ' gwab+ ); ■g u i t a r w a r s . . i e t ' , 'a d m in ' index.ph mysçli^close ($dbc) / -tabelapretisade uma^ „ova tolu«a para arma«*âr 0 -formulário precisa o arquivo ojríkto de tada um a -tag <input> p av-j^i pon-tua^ao-______________a seleção da imagem. "INSERT INTO guitarwars VALQES (0, NOK(), 'Sname',^ Sscore ’) --- roVBgii query ($dbc, j q u e r v ) ____ _ // Confirma êxito com o -jsuáriü eebo '<p>Obtigado por adicionar o s e ' J . recorde ! < / p > 1 echo T<p><strong>Nom.e:</s“rona> 1 . Snaue . '<br /J/í echo '<p><;a href="index.php">6clt;&it; Voltar para a lista dos recordes.</a></p>' ; ; s dados da pontuaçSo para limpar o formulário „) « r Havendo sutesso, ierti-fi^ue-se de <m »e o dampo d a imagem no -formulário, . ( <yue é permanerrte, seja limpo. e c h e ‘ < p c l a s s = r e r r í > r T '> P o r f a v o r , i n s i r a , t o d a s a s i n f o r m a ç õ e s a d i c i o n a r s e u r e c o r d e . < / p > '; r Çsta C onsulta i*s aw »a espetit de ataiKo, ao não esp etiíitar OS hOWCS d â s t c l u h 3 s- < l a b e l f o r - ^ n a n v e '^ N o i u e K / i a b e l x i n p - a t ^ y p e ^ t e x t ” id = " n a m e ,, n a n je = ,rn a m e " value=r T <?php if {!empty(Sname)) echo $nam e; ?>T f /><br /- xiabel for=,,sccret,>Pontuação;</Isbel><input type*"text"' n a r o Ê = ^ * ^ j^ e ” v a 1 u e = " < V p n p : r ( ] e m p t y ( ç s c o r e ) ) e c n o S s c o r e ; ? > " ebr /> <input type=”submit" Tíalue="Add" namg="Eubmit" /> </fonr> L j </òody> * * < / h t m l > a t i r t g f t n r p p h p
  • 259.
    trabalhando com dadosarmazenados em arquivos Planejando os uploads dearquivos gráficos no Guitar Wars E m bora possa p arecer que não é n ad a m uito com plicado adicionar suporte ao upload (envio) de arquivos gráficos ao G uitar Wars, a aplicação precisa ser m odificada d e várias m aneiras. Por isso, é um a b o a ideia te r um plano antes de m erg u lh ar no código. Vamos esquem atizar os passos necessários p ara atualizar o G uitar W ars e adicionar a funcionalidade que querem os. o Use a lte r para adicionar à tabela a coluna screenshot. Em primeiro lugar vem o banco de dados, que precisa de uma nova coluna para armazenarmos o nome de cada arquivo gráfico contendo a pontuação do usuário. Umavez que estamosplanejando colocar todos os arquivos gráficos na mesma pasta, tudo o que precisamos armazenar no banco éo nome do arquivo (não épreciso incluir o caminho). 0 Escreva uma consulta insert para inserir o nome do arquivo gráfico na coluna screenshot da tabela. O scriptAdicionar Pontuação que processa o formulário para aadição dos recordes também deve levar em consideração o novo campo de input de arquivos, e deve lidarcom a inserção do nome do arquivo gráfico na coluna screenshot, quando inseriruma novalinha de dados de pontuação à tabela guitarwars. Modifique o form ulário de Adicionar Pontuação de modo que ele passe a usar um cam po de input de arquivos para perm itir o upload das im agens. A páginaAdicionar Pontuaçãojá tem um formulário para se adicionarem aspontuações, de modo que precisamosmodificaresse Formulário, incluindo nele um campo de input de arquivos. Essecampo funcionará conjuntamente com o navegador para apresentarao usuário uma interface onde ele selecionaráum arquivo a ser enviado. Screen shot: ( Choose fite]) *RphizsscQre-gif Modifique a página principal de Guitar Wars de modo que ela passe a mostrar as imagens comprovantes dos recordes. O último item da nossalistade modificações envolvea página principal do GuitarWars, index.php, que precisaser modificada para exibir aimagemjunto a cadapontuação exibida. você está aqui ► 231
  • 260.
    ALTERE sua tabela 0banco de dados das powtuapões máximas precisa ser AlTERado Além de um a série de ajustes no script PHP, a nova aplicação G uitar Wars precisa de um a nova coluna, n a tabela g u i t a r w a rs, para arm azenar os nom es dos arquivos gráficos. E aí que entra o SQL, que oferece um a instrução cham ada ALTER, capaz de m odificar tabelas de tudo quanto é jeito, inclusive adicionando novas colunas de dados. Você usou a instrução ALTER, no capítulo anterior, para ajustar a tabela e m a i l _ l i s t de Elmer, mas vamos recapitular aqui com o esse com ando funciona. guitarw ars score A instrução DRO PCOLUm dimirt uma doiuna mte»ra da tabela. OK, talvez esse seja u m exem plo perigoso, u m a vez q u e ele revela com o elim in ar u m a co lu n a in teira d a tabela, com os dados e tudo. Mas é q u e certam en te p o d erá haver u m a situação em que você precise rem over u m a co lu n a inteira. E m ais provável, p o rém , que você precise ad icio n ar u m a coluna, com o é o caso aq u i com o G uitar W ars. Isso é possibilitado p o r ADD COLUMN, q u e é u m a das diversas alterações q u e você p o d e ex ecu tar n a tabela com ALTER. A instrução A l t e r e u s a d a paiam udara estrutura b a n c o d e d a d p s A instrução A L T E R •frequentemente t seguida yor T A B L & yara mdidar < ^ *e vote estara modi-Pidando uma tabela, E possível tambew alterar a estruWa de todo o bando de dados, dom ALTER DATABASE, mas isso é outra Vistoria* ADD COLUMN A diciona u m a coluna â tabela - basta especificar o n o m e da co lu n a e o seu tipo, após ADD COLUMN. g g g g g ^uitaryars ^ DROP COLUMN Exclui um a coluna (e quaisquer dados arm azenados nela) de um a tabela - basta especificar o nom e da coluna apos DROf COLUMN. ALTER TABLE guitarwars CHANGE COLUMN M uda o nom e e o tipo de dados de um a coluna - basta especificar o nom e atual da coluna, o novo nom e e o novo tipo de dados, após CHANGE COLUMN. MODIFY COLUMN Modifica o tipo de dados ou a posição de um a coluna dentro da tabela - basta especificar o nom e da coluna o seu novo tipo de dados após MODIFY COLUMN. Para m udar a posição de um a coluna, especifique o nom e dela e a sua posição exata (FIRST é a única opção aqui) ou um a posição relativa (AFTER para colocá-la após um a determ inada coluna, sendo esta especificada pelo nom e). ALTER TABLE g u ita r w a rs
  • 261.
    trabalhando com dadosarmazenados em arquivos Aponte seu lápis_____________ ___________________ Escreva uma instrução SQL para adicionar uma coluna chamada s c r e e n s h o t à tabela g u it a r w a r s . Certifique-se de fornecer à nova coluna um tipo de dados adequado. Depois, escreva outra consulta SQL, desta vez para verificar a estrutura da tabela e certificar-se de que a coluna foi adicionada com sucesso. Esdreva a^ui a instrução para driar a doluna. Esdreva a outra instrução você está aqui ► 233
  • 262.
    - f^ ApoHteseulápis--------------------------------------------- Solupão Escrevauma instrução SQL para adicionar uma cotuna chamada screenshotàtabelaguitarwars.Certifique-sedefornecerà nova coluna um tipo de dados adequado. Depois, escreva outra consulta SQL, desta vez para verificar a estrutura da tabela e A • jl ~ certificar-sedequeacolunafoiadicionadacomsucesso. ^instruça©AiTBR â d itio n a a Coluna screenshot a tabela guitarwars. Uma vez. c^ u e a Coluna c «ova, ela Começa sua existência vazia (NULL) de «uais<^uer dados nas linhas. aponte seu lápis solução A instrução AiTBR nao afeta ^uais^uer outros dados da tabela- 0 nome da tabela a ser alterada vem depois de AtXER TABL-E- ALTER TABLE guitarwars A W COLUMN screenshot varchar^^O r * ADD COLUMNindica <ue queremos alterar a tabela, adicionando a ela uma nova coluna- r DESCRIBE guitarwars 0 nome e o tipo de dados da nova Coluna são especificados por ultimo na Consulta SQL —b^ç caracteres sao o suficiente para stot^odair a maioria dos nomes de arquivos, mas voCe pode Criar a Coluna ainda maior do <ue isso se quiser- Esta instrução exibe a estrutura da tabela, incluindo os nomes das Colunâs e os seus tipos de dados. “Terminamos o ____ primeiro passoj A í Use AL" tabela a coluna s c r e e n s t
  • 263.
    trabalhando com dadosarmazenados em arquivos T te S T O R iv e Adicione a coluna screenshot à tabela guitarwars. U sando u m a ferram en ta MySQL, execute a instrução ALTER p ara ad icio n ar a coluna screen sh o t à tabela guitarw ars. Em seguida, em ita a instrução DESCRIBE p a ra d ar u m a o lh ad a n a estru tu ra d a tabela e certificar-se de q u e a co lu n a foi adicionada. l/ode pode donstruiv- & iabela juitarvrârs midial bai*ando o dódí^o de e*emplo pava éjui-Uv iVa« e depois exedu-fcando a doífssulta S$L < ^ u e se endOftiira r»o av^uívo 5uiiarwavs.s«|i. A 'mstrvi^ao PíSCRlBE mostva a nova dolunâ sdreensbot- existem ^ • As colunas criadas com ALTER precisam ser adicionadas ao final da tabela? Não, elas podem ser adicionadas em qualquer lugar. Mas tenha em mente que a ordem das colunas dentro de uma tabela não tem tanta importância assim. Em outras palavras, você pode estruturar os resultados das suas consultas, de modo a organizar os dados de qualquer forma que quiser. Mas talvez goste da sensação de ordem estrutural criada pelo ordenamento específico das coiunas, em cujo caso você poderá querer adicionar a coluna em um local exato. É possível fazer isso incluindo- se a palavra-chave FIRST a esta consulta ALTER. Ou então use AFTER coluna para posicionar a nova coluna relativamente a uma já existente: TWgiintas Idiotas ALTER TABLE guitarwars ADD COLUMN age TINYINT AFTER name Se você não especificar um lugar para a nova coluna ser adicionada, o padrão é no final da tabela. ? • O que acontece com as linhas de dados existentes no banco de dados após a adição da nova coluna screenshot? R : Uma vezque a instruçãoALTERsó afeta a estrutura do banco, a nova coluna é criada vazia de dados nas linhas pre­ existentes. Embora seja possível preencher a coluna screenshot defuturas linhas, as linhas pré-existentestodas terão uma coluna screenshotvazia. Os nomes dos arquivos gráficos ainda poderão ser adicionados às linhas pré-existentes? í{:Sim, sem dúvida, e você usa a instrução u p d a t e do SQL para fazê-lo. Não há nada que lhe impeça de enviar arquivos de imagens manualmente para o servidor, e depois usar u p d a t e para vincular os nomes dos arquivos às pontuações existentes. Mas lembre-se de que a ideia aqui é permitir que o próprio usuário envie o arquivo gráfico, e portanto, faz sentido implementar a funcionalidade de upload das imagens. E os usuários poderão fazê-lo usando o script Adicionar Pontuação aprimorado que você está prestes a criar... você está aqui ► 235
  • 264.
    adicione imagens como formulário adicione pontuação Como fazer para o usuário enviar a imagem? Com a nova coluna adicionada ao ban co de dados, estam os p ro n to s p ara nos co n cen trarm o s n a fu n cio n alid ad e q u e p erm itirá ao usuário enviar u m arquivo gráfico. Mas com o ex atam en te isso é possível? FTP? Telepatia? Isto n a verdade nos leva de volta ao form ulário A dicionar P ontuação, n o qual p o d erem o s u sar u m cam po p ara p erm itir q u e o usuário selecione u m arquivo gráfico a ser enviado. N 0 torwuiâri© AdiCionar Pontuaçao t O permitirá 3os usuários ^ ----- adicionarum novo registro â lista G ultar W ars - Add Your High Score B dt«terdes de$w ta*-«>«■ j Nane: — — 1 Score: I86S80 ’ : Screen siioc Choosf: ^ * - . cí f j® > f / Apos submeter-se o 0s detalbes sob« o 1 -formulário, o arquivo funcionamento deste botão sâo I SráfiCo binário é enviado Controlados pelo navegador e J do servidor, pelo sistema operacional nativo- ) £m geral, ele aciona uma cai*a de dialogo do navegador, na fr ffiiiffi ç^è o usuário pode navegar pâra encontrar o arquivo desejado no ^ S 0 f seu própr^ rígido- phizsscore.gif Assim, um cam po de in p u t ajuda o usuário a en c o n trar o arquivo a ser enviado. E depois? O cam po tam bém cu id a da o p eração de fazer a im agem selecionada chegar até u m a pasta do servidor, a p artir d e o n d e p o d e en tão ser exibida com o p arte d a lista de reco rd es do G uitar W ars. Esse cam po d e u p lo ad d e arquivos do fo rm ulário é algum tipo de extensão esquisita do HTM L? D e fo rm a algum a. A tag <input> do H TM L tem su p o rte aos cam pos referen tes a arquivos, e trab alh a em co n ju n to com o PH P p ara p erm itir o u p lo ad dos arquivos. Mas antes de en trarm o s nos d etalhes do fu n cio n a m en to do PHP, vam os d ar u m a o lh ad a com m ais atenção n o p ró p rio cam po do form ulário... Uma pasta no servidor recebe o arquivo i f iCo e o armazena- Servidor web r
  • 265.
    trabalhando com dadosarmazenados em arquivos 0 Feram látfo Adicionai: pontuação em D é fa ite s Estabelece um tamanho máximo para os arquivos enviados, «este caso 3ZKB Í3Z.7&0 bytes). Este formulário e autorreferente- Imethod="post'' action="<?phb echo $ SERVER ['PHP £$te atributo instrui o formulário d usar um tipo especial de codificaeao, requerido para o upload de arquivos —ele afeta o modo como os dad^s POST sao tombinados e enviados apos a submissão do formulário. <form SELF’]; ?>”> aMawBBwafWUNiriininHiniai iiiï._s.. . . mmam m m <label for="name">Nome:</label> <input type="text" id="name" name="name" value="<?php if (!empty($name)) echo $name; ?>" /> <br /> clabel for="score">Pontuação:</label> <input type="text" id=”score" name="score'' value="<?php if (!empty($score)) echo $score; ?>" /> <br /> <label for="screenshot">Captura da Tela:</label>' • <hr /> <input type="submit" value="Add" name="submit" /> </form> Este e o campo de input propriamente dito, <ue em ultima instância, utiliza— se de uma caixa de diálogo do sistema operacional nativo para o usuário navegar ate o arquivo e seleCiona-lo. ulário Adicionar Pontuação de modo que ele passe a usar um campo de input de arquivos para permitir o upload das imagens. você está aqui ► 237
  • 266.
    Insira o (nomedo) arquivo gráfico no banco de dados Sim plesm ente enviar ura arquivo gráfico para o servidor através de um form ulário não é suficiente. Temos de arm azenar o nom e do arquivo na nova coluna screenshot do banco de dados, para que a im agem possa ser acessada e exibida. Do jeito que está o script A dicionar Pontuação, já está inserindo novas pontuações na tabela guitarwars, usando a instrução SQL INSERT, mas esta não está levando em consideração a nova coluna s c r e e n s h o t : armazenar arquivos de imagem no banco de dados Os nomes <fcs ssíp a t m o z e t ic i d p s n° t>ctnco de dctdPS cotio pqrte de uma Insfruçífe ÍHSEílTT * r A -função M ov/O do MyS#L é usada pava se ínseviv a data e Kora atuais. INSERT INTO guitarwars VALUES (0 , NOW() , ^narne', '$score') A doiuna id e deíinida automatidamente através de AMT0__IMCR£MêKT — O C ^ e v o )t i^ n o v a d o je m b o raa donsulta realmente regueira um vaior a«ui. Um a vez que esta instrução SQL está inserindo valores sem identificar colunas para eles, ela precisa incluir um valor para cada coluna. Mas nós acabam os de adicionar um a nova, o que significa que a consulta não funciona mais - está faltando um valor para a nova coluna s c r e e n s h o t . Assim, para adicionar um nom e de arquivo gráfico ao banco com o parte de um a nova linha de dados, precisam os adicionar um novo valor à instrução INSERT: INSERT INTO guitarwars VALUES ( 0 , NOW() , T$name’ M linhas de dados inseridas antes^ da triaçao dô doiuna sdreensHot *ao^ possuem um nome de arquivo ya-fido- fassav o nome do arquivo ojviíito na instrução StL-fcCT -faz- tom <ue ele seja ad^ionado ao bando de dados. ’$score', A ordem destes valores íaz. di-ferenda, uma vez. c «ue a instrução IKSERT esta assumindo «ue eles se endontrâm na mesma ordem «ue as dolunas da tabela- A nova instrução ÍK^ERT resulta no nome do arquivo da imagem a sev inserida na do!una sdreenshot- E3cii>'u ------- IN S E R T para Inserir o nom e do arquivo gráfico na coluna scre e n sh o t da tabela.
  • 267.
    trabalhando com dadosarmazenados em arquivos Pescubra o nome do arquivo enviado Parece estar tudo certo com a consulta, mas nós ainda não sabemos qual é o nom e do arquivo gráfico. E lógico assumir que o cam po de input de arquivos do form ulário oferece, de algum a form a, acesso ao nom e do arquivo, mas como? A resposta reside em um a variável superglobal interna do PHP cham ada $_FILES, que é sem elhante à superglobal $_JPOST que já usam os para acessar dados do form ulário. Com o $_POST, $_FILES é um array, e dentro dele encontra-se não apenas o nom e do arquivo enviado, mas tam bém outras inform ações que poderão ser úteis. <input type="file" name="screenshot" / > 0 Wmulávio envia alg^as utess sobre o av^uWo para o scrip-b PftP, através dia variarei superglobal f_jF|L££- c phizsscore.gif Éste e o àv^uivo gváfiCo sendo enviado através do ca»»po de input de arquivos do formulário. A SUpelrglokal interna 4LFÍLE S íptnece acessp a í n f e n i a ç p e s s p b t e a r ^ u íV p s e n V la d p s . ILES['screenshot1]['name'] Nome do arquivo enviado- $_FILES['screenshot' ] [ 1type' ] M M H Ü ^ __ 0tipo MIMÊ do arquivo enviado, neste caso éjlJ'*. $ FILES['screenshot1] [ 1size' ] 1 1 1 ! *--oWh.< * *byte) do âv^uivo enviado. $_FILES [ 1screenshot1] [ 1tmp__name'] , * l l l i B l l i P ^ localização de te»*poravia do ar^uivo no servidor. $ FILES['screenshot'] E'error' ] ~ mm 0 código de erro para i ^ 0 up}oad do av<uivoj 0 indica suCesso, ovtros valores indiCâm fracasso- As outras inform ações disponibilizadas n a variável $_FILES certam ente são úteis, m as neste m o m en to só precisam os d o nom e da im agem , q u e p o d e ser arm azenado em u m a variável local ($screenshot) e usado n a instrução SQL INSERT. você está aqui ► 239
  • 268.
    manter os dadosde arquivo externo em arquivos externos Dados armazenados em arquivos externos geralmente são deixados nesses arquivos externos, mesmo em aplicações de bancos de dados. Neste caso, os dados são um conjunto de pixels que com põem um a imagem, a qual é arm azenada em um arquivo externo - um arquivo GIF, JPEG ou PNG. Os bancos de dados são excelentes para arm azenar dados de texto, e não dados binários puros com o são as imagens, e por isso, é m elhor arm azenar no banco apenas um a referênciaà imagem. Essa referência é o nom e do arquivo. O utro motivo pelo qual as imagens não são annazenadas em bancos de dados, nas aplicações web, é que seria m uito mais difícil exibí-las usando* se código HTML. Lembre-se de que o código HTML referencia imagens a partir de arquivos externos usando os nomes dos arquivos. Assim, para gerar um a tag de imagem em HTML usa-se o nom e do arquivo, e não os dados puros da imagem. Telia se colpocií u rna im a g e m em uma página Wet>7 SP é precísp uma r e f e r e n c i a a ^ ~ ar^ u íV p . < im g s r c = ' 0 nome do arquivo $ ráfy 0. a l t = " S c o r e im a g e " / > A -ta $ H T M L - < im $> usa o nome para referenciar o arquivo ^ráfito armazenado no servidor web. Phizsscore.gif
  • 269.
    trabalhando com dadosarmazenados em arquivos Aponte seu lápis A página principal do Guitar Wars (index.php) ainda não está exibindo as imagens de captura de tela que comprovam as pontuações. Complete o código para que ele passe a exibi-las. <?php // Conecta-se ao banco de dados $dbc= mysqli_connect{'www.guitarwars.net' , 'admin', 1rockit' , 'gwdb'); // Obtém os dados das pontuações a partir do MySQL $query= ; $data= mysqli_query($dbc, $query); // Faz um loop através do array contendo os dados das pontuações, formatando-os como HTML echo '<table>' ; while ($row = mysqli_fetch_array($data)) { // Exibe os dados das pontuações echo 1ctrxtd class=" scoreinfo"> '; echo 1<span class="score">' * $ row ['score'] .'c/spanXbr />' ; echo '<strong>Name:</strong> 1 . $row['name'] . '<br/>'; echo '<strong>Date :</strong> ' . $row ['date'] .. '</td>'; if {is_file(................. ) &&filesize{..................) >0) { echo 'Ctdximg src=" ' . ............... alt="Score image" /></tdX/tr>'; } else { echo 'ctdximg src="unverified.gif" alt="Unverified score" / x / t d x / t r > '; echo 'c/table>'; mysqli__close ($dbc) ; ?> você está aqui ► 241
  • 270.
    aponte seu lápissolução ponte seu lápis----------------------------------------------- Solupão Apágina principal do GuitarWars (index.php) ainda não está exibindo as imagens de captura de tela que comprovam as pontuações. Complete o código para que ele passe a exibi-las. N uma tentativa de ajudar a simplvfidar o tód^o, «ao iremos usar "or d'seO“ para produzir mensagens de erro e interromper o sdript guando uma íunÇâo mys^ii -falhar- <?php tyodê poderá dontinuar utilizando esse redurso «as suas próprias apiidadoesj «és pararemos de usa-lo da^ui em // Conecta-se ao banco de dados v , ‘ _ „ „ ^ diante, apenas para manter o dodtjo o mais breve possível- $dbc= mysqli_connect(1www.guitarwars.net', 'admin1, 'rockit' , 'gwdb'); // Obtém os dados das pontuações a partir do MySQL $query = S t U ã C T * F R O M guitarwars" ^ ^ instrução S Q L < u e pede as pcm-tuadoes nao se modvfida em çdata = mysqli__query ($dbc, $query) ; 1 j 1 // Faz um loop através do array contendo os dados das pontuações, formatando-os como HTML echo '<table>'; while ($row= mysqli_fetch_array<$data)) { // Exibe os dados das pontuações echo '<trxtd class="scoreinfo">'; M * £sta íundao vereda echo 1<span cl-ass=" score"> ' . $row [’score 1] . '</span><br />' ; ^ q arquivo g r á - f i í - o e c h o ’ < s tro n g > N a m e : < / s t r o n g > ' . $ ro w [ ‘ n a m e ’ ] . ' < b r / ^ l - ^ ^ ^ r>ão esta vazio- echo '<strong>Date:</strong> ' . $row['dat^>f^T'</td>'; ___ if (is_file( && filesize ( > 0) { í echo '<t d x i m g src=" ' . frovíCsdreenshot 3 . '" alt=" Score image" /></tdx/tr> ^ Esta -Punça© veriíida se o ar«uivo doíuna sdreensbot do bando de dados ^ e ile { YcaUtíit cxisíe' a rm a ^ uma imagem para dada pontuadao- echo 1<t d x i m g src="unverif ied.gif" alt="Unverified score" /></td></tr>1; } A Modifi echo 1</table>'; mysqli_close($dbc) ?> m odo que ela p a sse a m ostrar a s im age n s com provan tes d os I recordes.
  • 271.
    trabalhando com dadosarmazenados em arquivos T f e S T O R f v e Adicione um novo recorde ao Guitar Wars, incluindo a captura de tela. Books, www.altabook5.com .br. Está n a pasta capitulo 05 (ch ap ter 05). O código consiste da p ág in a principal (index.php), do script A dicionar P ontuação (addscore.php) e de u m a folha de estilo (style.css). P rim eiro, você precisa m odificar o script a d d s c o r e . p h p de m o d o q u e o seu form ulário A dicionar P o n tu ação passe a te r su p o rte ao u p lo a d de arquivos. Isso inclui ad icio n ar novos cam pos ao form ulário, ajustar a tag <form > e verificar se a variável S screenshot n ão está vazia. D epois, in co rp o re ao script a nova consulta INSERT que insere pontuações. A gora, vá ao script in d ex .p h p e insira n ele o código d a página anterior, p ara q u e ele possa exibir a cap tu ra de tela referen te a cada pontu ação . Envie todos esses arquivos p ara o seu se n ad o r web e ab ra a p ág in a a d d s c o r e . p h p em um navegador. D igite u m a nova p o n tu ação n o fo rm u lário e clique em Subm it. Em seguida, navegue até a p ág in a i n d e x . p h p e d ê u m a o lh ad a n a nova pontu ação . Caso ain d a n ão o te n h a feito, baixe o código de exem plo do G uitar W ars no site d a Alta AI50«aoesta devtc if*agem não está ap . junto do» a «ova pontuaça©. Por que você acha que a imagem com a captura da teia não está aparecendo junto com a nova pontuação? E quanto às pontuações que já estavam no banco de dados? você está aqui ► 243
  • 272.
    arquivos enviados sãoarmazenados em uma pasta temporária Para onde foi o arquivo enviado? O p ro b lem a com a im agem enviada não ap arecer é q u e nós assum im os q u e o arquivo seria enviado p ara a m esm a pasta, no servidor, q u e a dos nossos scripts PHP. O co rre q u e isso está sim p lesm en te in c o rre to . O fo rm u lá rio d e A d icio n a r P o n tu a çã o p e rm ite q u e o u su ário selecione u m arquivo do seu p ró p rio com putador, m as o arquivo é enviado p ara u m a pasta tem p o rária do servidor, n a verdade. Essa pasta tem p o rária é criada au to m aticam en te no servidor, e em geral possui algum n o m e estran h o , cheio d e letras e n ú m ero s aleatórios. Isso ap resen ta u m p ro b lem a p ara o nosso código < im g> em i n d e x . plrp, p o rq u e ele assum e q u e a im agem está localizada n a pasta p rin cip al do site: c im g s r c = " |lli|& á Í £ S © Í r ^ l|! iÍ | |^ '' a l t = " S c o r e im a g e " / > Este tódi5©assume ejue â im âSjÇ .w armâzenâda n3 mesmâ pasta ft os scripts PHf*..’ mas ela nao esta! Navegador eb do cliente 0 ar^uivo Corn a ima^em da captura de teia se localiza origiyvâlmente aljMma pasta do Computador do M S U â V -io . Servidor web 0 nome e 3 jotaiiz^Çao deste pasta temporária vaviam conforme a instalaçao do PHP- í«*aááâÍcorG.php index.php CSS phizsscore.gif Este formulário se or’ tÿna de addsCorephp- û script de Adicionar Pontuação cuida de enviar o arquivo grafico para uma pasta temporária no servidor.
  • 273.
    trabalhando com dadosarmazenados em arquivos Armazenar imagens em uma críptica pasta tem porária parece ser uma complicação desnecessária. Não é possível definirm os onde os arquivos enviados devem ser armazenados? Sim! O PHP lhe permite controlar onde os arquivos enviados serão armazenados. Porém, não é possível controlar, através do PHP, o local de armazenamento inicial dos arquivos enviados, motivo pelo qual essa localização é considerada como temporária. Mas você pode mover o arquivo para outro lugar, depois de ele ter sido enviado. A função PHP move_jiploaded_file() aceita como parâmetros a localização-fonte e de destino do arquivo, e então realiza a transferência: move_uploaded_file (;||t|f c a iotâljiiâçao-WU do arquivo grafito, indluindo OtâmmKo COnome do dr<i*W o temporário. fscore.php index.php Esta pode ser ^uatauer pasta do servidor < ^ u e vode quiser usar, apenas dertifi^ue— se de ter permissão para esdrever arquivos nela. Servidor Web ^ t a r g e t ) ; Esta é a lodalizaçao de destino do arquivo grafido, indluindo o daminho e o nome do arquivo permanente. 0 arquivo é movido de uma pasta temporaria para uma permanente- move uploaded__fü e 0 phizsscore.gif phizsscore.gif você está aqui > 245
  • 274.
    não existem perguntasidiotas mQ existem p e r g u n t a s i d i o t a s I • Nãoé possível modificar o lugar de armazenamento inicial dos arquivos enviados editando-se o arquivo php.ini? Sim. 0 arquivo de inicialização do PHP (php.ini) pode ser usado para se modificar o lugar de armazenamento inicial dos arquivos enviados, através da opção uploadJmp_dir. Porém, se a sua aplicação estiver hospedada em um servidor virtual, você poderá não ter acesso a esse arquivo de inicialização, o que significa que, se quiser mover o arquivo enviado para uma outra pasta, terá de fazê-lo através de código PHP. 7 * Por que a pasta de armazenamento inicial é chamada de “temporária” ? Ela desaparece depois que o arquivo é retirado dela? K : Não. A pasta é “temporária” no sentido de que não foi criada para servir como o lugar de armazenamento definitivo para os arquivos enviados. Você pode pensar nela como uma espécie de antessala, onde os arquivos enviados são armazenados até serem movidos para os seus lugares de armazenamento finais. * Por que eu não posso simplesmente deixar um arquivo na pasta temporária? J^_t Você pode, em cujo caso terá de adicionar $_ FILES['screenshot'] ['tmp_name'] ao caminho da imagem, para se certificar de que ela possa ser encontrada na pasta temporária. Mas tenha em mente que você não pode controlar o nome ou a localização da pasta, em geral. Mais importante ainda, as pastas temporárias podem ser automaticamente esvaziadas, periodicamente, em alguns sistemas. Outro potencial problema é que a pasta temporária poderá não estar acessível ao público, e com isso, você não poderá referenciar os arquivos enviados a partir do seu código HTML, o que atrapalharia o funcionamento do Guitar Wars e da maioria das aplicações PHP. Movendo os arquivos enviados para outra pasta que não a de armazenamento temporário, você pode controlar cuidadosamente onde os arquivos ficarão, e como serão acessados.
  • 275.
    trabalhando com dadosarmazenados em arquivos OK, então agora eu sei como mover os arquivos enviados de um lugar para outro. Isso é realmente útil. Mas ainda não tenho a menor ideia de para onde eles devem ser enviados. Toda aplicação precisa de uma pasta im ages (im agens). OK, talvez dizer q u e “precisa”, possa ser u m exagero, m as é im p o rtan te q u e os pedaços das aplicações PH P fiquem o m ais organizados possível, e u m a m an eira d e fazê-lo é crian d o pastas p ara os diferentes com ponentes. U m a vez q u e as im agens são enviadas pelos usuários, elas n ão são algo sobre o q u e você n o rm alm en te terá co n tro le direto, pelo m enos em term os de nom es de arquivos e quantidades. Assim, é u m a b o a ideia arm azená-las sep arad am en te dos outros arquivos da aplicação. D ito isto, precisam os de u m a pasta im ages, o n d e os arquivos gráficos enviados p ara a aplicação G uitar W ars possam ser arm azenados. Esta pasta p o d e servir tam b ém com o lu g ar d e arm azen am en to p ara quaisq u er outras im agens que a aplicação use, caso surja a necessidade. A pasta '»majes «a verdade *ao t muito »ais importante *u C oyuàl«uer outrâ pâstâj mâs ela ajuda a organizar os arquivos gráf(tos em um so lu^âr. você está aqui ► 247
  • 276.
    Crie um larpara os arquivos gráficos enviados faça uma pasta para imagens enviadas A pasta im ages é id ên tica a q u alq u er o u tra do servidor, exceto pelo fato de q u e ela tem de ser colocada em algum lu g ar abaixo da pasta p rin cip al d a aplicação. N a m aioria dos casos, basta colocá-la d iretam en te com o u m a subpasta da p rincipal, m as você p o d e criar u m a h ierarq u ia de pastas m ais com plexa, se quiser. C riada a pasta im a g e s d iretam en te d en tro d a pasta p rin cip al do servidor, torna-se possível referen ciar arquivos de im agens d e d en tro de scripts PHP, assim: 0 no**e do âr^uivo e Starget = Condatenado âo dámmfoo (jlmage zsscõre. O cam in h o $ targ et é criado a p artir de u m a nova constante q u e irem os ad icio n ar ao script, ch am ad a GW_UPLOADPATH, q u e arm azena o cam in h o até a nossa pasta im ages. Assim com o as variáveis, u m a co n stan te serve p ara arm azen ar algum dado. Mas o valor d a con stan te n ão p o d e ser m odificado, u m a vez definido. O n o m e do arquivo gráfico, conform e digitado no fo rm u lário A dicionar P ontuação é en tão co n caten ad o ao cam inho até im a g e s . Çsta c a fasta web da aflitaçao, onde os sevifb PHP, induindo inde*- fiy, íidaw arma^nados. Servidor web V e j a W n ! Use um program a de F T P para acessar o sistema de arquivos do seu site, e crie a pasta im ages diretamente dentro da pasta web da aplicação. 0S âr^uVvos grafitos enviados sâo movidos fara a fasta images, cmde fodem ser exibidos através de tags HT/V1L <i»g>. Se a sua aplicação PHP estiver hospedada em qualquer outro lugar que não o seu computador local, você precisará usar FTP para criar a pasta images. phizsscore.gif
  • 277.
    trabalhando com dadosarmazenados em arquivos S Í n I T A - S E c o m o u m a w u ï V o g r â î ï c o e n v i a d o Suaíatefa e inteípi-et^t o papel de UH1ai^UlVo gráffco envlad«?,traçando o seu camínjip atraVés do apllcatíVo Guitar Wars. Desenhe seu caminto atraVés de cada parte da aplicação, sem se esquecer do banco de dados, pense como um stFjvfa/Q enViade! Navegador web do cliente Servidor web Comtu a«v*ií phizsscore.gif phizsscore.gif phizsscore.gif guitarw ars você está aqui ► 2 4 9
  • 278.
    sinta-se como umarquivo gráfico enviado-soiução S i r í r A - S E c o m o u m qj^ u W q g r á S i c o e n v i a d o - S o l u ç a » Esta pasta -(■ id a no 7t Computador do usuário A » —vote «ao tem dontrole nenhum sobre o nome dela, ne» onde ela e armazenada, mas também nada disso lhe importa- Sua tareia é Interpretar 9 papel de um arquivo graíicç enViade,traçando 9 geu camínlio atraVás d» aplioatíVp Guitar Wars. Desenlie seu camfnlio atraVé-s de cada parte da aplicação,, sem se esquecei do banco de dados. ¥ense come um arquive enVíado! Navegador web do cliente V ot i deve ser ti/tdidoso tom o riomt c a lotaSitatâo desta ya^ia, porque ela 6 visãás Cmtoda a apitéa^ã« áw-tav tva« para ar«*az£w ar e j reíerendiar os ar^utoos^^/^ ^rá-fitos e^ados- Pviwcir 0 arquivo e ewtàd© (Asando-^ w ífi Servidor web AâmPode mPut do phizsscore.gir, ' , +or(*vwiârÍ0- Sscreenshot = $ _ F IL E S [’screenshot’][1 nam e’]; Caramba! »© vopasso « ^ u e w âo havíam os fianejado - o seu proje-èo precisa ser -P ie% ível/ phizsscore.gif £m se%hdo lu^at-, © ar<^»iv© £movido Áè pasta temporária para a p a s-fca imanes permânen-te- Apos o arquivo ser ewviado ao servidor e ser rrovide para O seu ta^ar de amazena^e^t» -final» seu *© "»« s adicionado ao ban& ode dados- the Mova o ai gráfico da pasta temporária para uma pasta permanente criada para as imagens. addscore.php guitarw ars
  • 279.
    TfeSTO R fve __________________ trabalhando com dados armazenados em arquivos Dê aos arquivos gráficos enviados um lar permanente, com uma pasta própria para eles. M odifique o script a d d s c o r e . p h p p ara q u e ele use a constante G W JJP LO A D P A T H e arm azene os arquivos gráficos no cam inho p ara o n d e ela está ap o ntando. Eis o p edaço do código q u e precisa ser m odificado: as ccin.qtpir.tss dc caminho e do define(1GW UPLOADFATE' , 'images/ <?php -amanho máximo dos arquivos if (isset(S_POST[1submit']) ) { // Pega os dados em POST Sname - §_?OST['nane']? Sscore = $_POST[1score']; $screenshct - $ FILES[’screenshot’][1name']; : ('empty($name) 5S !empty($score) £& !empty(Sscreenshot)) { // Move o aranivQ.. para a pasta-alvc Starget = (S_UPLOADPATH .jfscreenshot; if (jnove_upKkJfca_i.ilbi (i_Tfll.ES [ 'screenshot1][ 'tmp_name’], $target) ) { // Ccnecta-se ao banco de dados $dbc = mysqli connect{1h w w .guitarwars *net1, ‘admin’, 1rockit' , 1g^'db1); // Escreve os dados no banco $query = "INSERT IHTO guitarwars VALUES (0, NOW(). mysqli_query(5dbc, $query); // Confirma êxito com o usuário echo '<p>0brigado por adicionar o seu recordei</p>'; echo '<p><stronç>Nome:</strong> ' . Sname . '<br echo 1 | , g|trr '",, > 1 $sccre . 1<br. />'; echo '<img src="’ ./gw_UPLOADPATH 7screenshot . alt="Score image" /></p>'; echo 1<oXa h.ref="in3è8";{Sll!i{i"^iiL;STtVoltar para a lista dos recordes. </a></p> '; addscore.php O script i n d e x .p h p tam bém é afetado p ela co n stan te G W _UPLO ADPATH. N ão se esqueça de m odificá-lo tam bém . A pós fazer essas m odificações, envie os scripts p ara o seu servidor e te n te ad icio n ar um a nova p o n tu açã o novam ente. a . « . r r n tr^age* unvevi-hed exibida f3râ fon-twaçocs an-tigas, <uc nâo íem w^a dap^twra de beis domfvobatóría. A tap-tava dc tela enviada agora -Pita visível na pagina printipa!. você está aqui ► 251
  • 280.
    n a ?eXJStem perguntas idiotas P ' Seoarquivophp.in i pode serusadoparasecontrolarolugarde armazenamentodosarquivosenviados, porque énecessáriomoverosarquivos? K : Porque nem sempre é possível modificar php.ini. Por exemplo, se você estiver criando a aplicação PHPem um servidor web virtual, é bastante provável que você não terá acesso para modificar as configurações de php.ini. Emesmo que possa modificar esse arquivo, você corre o risco de danificar sua aplicação caso precise movê-la para outro servidor. Emoutras palavras, a aplicação ficaria dependente de umcaminho controlado por php.ini, em vez de umcaminho controlado pelo seu próprio código PHP. 7 • Por que os usuários não podem digitar uma data, na aplicação Guitar Wars? Adata é uma parte importante do registro da pontuação, no sentidode queelaestabelece quandoo recordefoi oficialmente publicadono site. Comoocorre comqualquer registro, a primeirapessoa a conseguir umadeterminada pontuação recebe toda aglória. Emvez deconfiar que o usuário nosdirá realmente quando foi que ele conseguiu a pontuação, podemos simplesmente usaradata ea horadopost comoo registrooficial da pontuação. Isso eliminafalsificações e empresta maior credibilidadeà lista dos recordes. Os Os bancos de da<fcs sãp usuários de umaaplicação tãocompetitiva estarão sempre procurando por umjeito de fraudá-la, portanto, vocêdeveeliminar todas as possibilidadesdefraudeque puderencontrar! Vale a pena ressaltar que a função now () usa a hora do servidor, que poderá não ser a mesma que a hora local do cliente. Isso não deverá ser um problema, porém, uma vez que todos os usuários estarão obrigados à mesma hora do servidor. T * * Não é possível que as pessoas escrevam em cima das imagens umas das outras, enviando arquivos gráficos com os mesmos nomes? Sim. O problema tem a ver com o fato de que as imagens armazenadas no servidor usamexatamente o nome de arquivo fornecido pelo usuário no campo de upload do formulário. Assim, se dois usuários enviarem arquivos com o mesmo nome, a imagem do segundo usuário será escrita em cima da imagem do primeiro. Isso não é bom. Uma solução é adicionar alguma unicidade aos nomes dos arquivos no servidor. Uma forma simples de fazê-lo é adicionar a hora atual do servidor, em segundos, ao nome do arquivo, desta forma: $target = GW UPLOADPATH . time( ) $screenshot; O resultado desse código é um nome 1221634560phizsscore.gif para o arquivo, em vez de phizsscore.gif, onde 1221634560 é a hora atual do servidor, expressa em segundos. P ' Nós poderíamos ter armazenado, no banco de dados do Guitar Wars, os dados propriamente ditos da imagem enviada? H : Sim. Os bancosdedados são bastanteflexíveis, e lhepermitem armazenardados binários dentrodeles. Porém, ogrande problema nestecasoé queoGuitarWars usaas imagens enviadas nooódigoHTML, paraqueelas possam ser exibidas napágina principal index. php.Atag HTML<img> foi criada para referenciarumarquivográficoarmazenado noservidor, e não umconjuntode dados binários armazenados emumbanco. Assim, mesmoque vocêalterasse atabela guitarwars paraarmazenar dados binários, aindasedeparariacomumdesafioabsurdo, aotentarcolocaros dadosde voltaemum formatoque pudesseser exibidousando-se código HTML Kao hi nada de <^üa! sob« a Wa v-eW*ada pela-funçaotimeO, e+ux# pelo-fato de y t ela ^era «Uer*s íhiòos... eonimcro retocado esta sempre âww»e«tawdo| PONTOS DE BALA 9tunps para se armazenar dadPS detexfcp, Pias em geral e melhor cjue eles referenciem dadbs blnáliPS de affiufVps externps. A instrução ALTER é usada para se modificar a estrutura de uma tabela de banco de dadoa MySQL, por exemplo para se adicionar uma nova coluna de dados. Com uma pequena ajuda do PHP e do MySQL, uma tag HTML < in p u t> pode ser usada para se enviarem arquivos gráficos. A variável superglobal $ _f i l e s é onde o PHP armazena informações sobre um arquivo enviado. Afunção padrão do PHPmove_uploaded_ file () lhe permite mover arquivos de um lugar para outro no servidor, e é essencial para o processamento dos arquivos enviados. A maioria das aplicações web beneficia-se deter uma pasta images para armazenar as imagens usadas pela aplicação, especialmente aqueias enviadas pelos usuários.
  • 281.
    trabalhando com dadosarmazenados em arquivos Legal que o caminho seja armazenado em uma constante, mas por que ele é criado em dois lugares, index.php e addscore.php? O que acontece se o caminho se modificar? A £©nstante #v_UPU>AZ>PATft armaz-ena ° tami*ho *fcc o arquivo yráÇito enviado. define('GW_UPLOADPATH’ aeímeO é«sado J o da *e en*w » tonstantes- 'images/ ' ) ; 0 valo*" da tonstante, o <*à nuntd fode sev modi&tado- ele é uma Aonstante! S e o cam inho se modificar, você terá de m odificar o código em dois lugares... código duplicado não é um a boa coisa! Assim, dentro de cada um dos scripts, in d e x .php e a d d s c o re .p h p , a constante GW_UPLOADPATH funciona sem problemas. Mas ela é criada duas vezes, o que significa que qualquer modificação no caminho terã de ser feita em cada um dos scripts. Esse tipo de duplicação de código é consequência de um mau projeto, e deve ser eliminado sempre que possível. The donstant is stored tv/ide, meaning it has to be maintained in two di-ffevent fldtes. W É R > 9 C É R E B R O Para resolver o problema do código duplicado, precisamos armazenar a constante g w _ u p lo a d p a t h em apenas um lugar. Você a armazenaria em index.php ou em addscore. php? Por quê? você está aqui ► 253
  • 282.
    dados em scriptscompartilhados com arquivos include Pados compartilhados precisam ser compartilhados Q u an d o têm dados q u e devam ser com partilhados p o r diferentes scripts em um a aplicação, você precisa d e u m a fo rm a de arm azená-los em um só lugar, de o n d e cada script possa obtê-los p ara uso. Mas isso ain d a n ão resp o n d e a questão de o n d e e x a ta m en te os dados devem ser postos,..? Você poderia arm azenar os dados apenas em index.php... // Defina a . constante do carrinho da upload define{1G WU P L O A .D P A T H ' , 'images/'); Os dad°s a serem c p r a p a t t i l t a d p s p p t scripts precisam íicat acessíVels at°da a aplicaçãp, sem d u p lic a ç õ e s tiP c ó d ig o , index.php ...mas desse jeito os outros scripts não teriam acesso a eles. Assim, arm azen ar os dados a serem co m partilhados em um script n ão fu n cio n a, p o rq u e os dados n a verdade n ão estarão m ais sendo com partilhados. A resposta está em conseguir, de algum m odo, to rn a r os dados acessíveis a vários scripts, m as sem arm azená-los d iretam en te em n e n h u m deles. - @ addscore.php index.php addscore.php Como tornar os dados acessíveis a ambos os scripts sem os arm azenar em nenhum deles? A solução p ara o p ro b lem a são os arquivos include, arquivos de código-fonte PH P q u e são inseridos em outros arquivos PH P co nform e necessário.
  • 283.
    trabalhando com dadosarmazenados em arquivos Serão necessários dados do script compartilhado Os arquivos in clu d e são b astante poderosos, p o rq u e, após criá- los, você p o d e usá-los sem pre que necessário em outros scripts, n a prática co m p artilh an d o o código co n tid o neles. A con stan te GWJJPLOADPATH p o d e ser colocada em u m arquivo include p ara estabelecer u m co n ju n to de “variáveis da aplicação”. <?php // Define constantes da aplicação define('G W JJPL C ãDPATH', Timages/T); ?> O s a r ^ u íV ^ s in c lu d e lfce p e r m i t e m c o m p a r t l ll ic ü : c(> cl!go e n tr e d iV e r S 9 S scripts. addscore.php A »hsfcrudâo re^nHre_j»w*e tuida de indluiv um sdv-ipt denhro de outro sdHpt- jnfcluir apfvars.fHf C» outvos ~ , stvipis periwite estes nqo e X isM os dados doados I e t^ U X ltc lS l d l 9 f à S na^eíe.a^va«.f^. ~P • Ei, essas “variáveis” da aplicação não são na verdade constantes? Em alguns casos, sim. Mas não há nenhum problema nisso. A ideia aqui não é se preocupar em diferençar variáveis de constantes. Em vez disso, estamos apenas tentando estabelecer um lugar comum para o armazenamento de dados a serem compartilhados, dentro de uma aplicação. E esse lugar é um arquivo de script chamado appvars.php. compartilhados, como frequentemente fazer isso é uma ótima ideia, em termos de organização do código. • 0 código nos arquivos de script compartilhados limita-se a dados? Não, de forma alguma. Qualquer código PHP pode ser colocado no seu próprio script e compartilhado usando-se a instrução require_once. Na verdade, é bastante comum que aplicativos compartilhem uma grande quantidade de códigos funcionais residentes em vários scripts. Não só é comum usar arquivos de scripts Por que a instrução PHP para se incluir códigos se chama require_once (“ requisitar uma vez” )? K : O nome arquivo indude (“de indusão”) vemde uma instrução PHP chamada include, a qual é bastante semelhante a require_once. Adiferença é que require_once resultaem umerro caso o arquivo include não possa ser encontrado - include, poroutro lado, não acusa umerro caso o arquivo include esteja faltando. Além disso, o “once” (“uma vez”) de require_ once significaque o arquivo não poderá ser acidentalmente incluído mais de uma vez. Você poderá, às vezes, ver include sendo usado em vezde require_once para se induiralgum código que não sejatão importante, como por exemplo, código HTMLpuro que não esteja realizando algum propósito essendal. 0 PHPtambém tem as instruções include_once e require, que são variações de require_once e include. você está aqui ► 255
  • 284.
    a instrução require_once Pensecm require once cowo uw "inserir"1 As inclusões n ão se lim itam a u m só arquivo PH P com partilhado, e p o d em ap arecer em q u alq u er lu g ar do script q u e você q u eira usá-las. Você p o d e p en sar em r e q u i r e o n c e com u m a instru ção in sert (“in serir”) q u e é substituída pelo co n teú d o do script q u e ela referencia. N o caso do G uitar W ars, as variáveis d a conexão ao banco de dados p o d eriam tam bém se beneficiar de serem m ovidas p ara u m arquivo inelude. Assim, os conteú d o s dos dois scripts com p artilh ad o s são inseridos d iretam en te em outros scripts, nos p o n to s o n d e fo rem requisitados. Esfcâ VâHâVc! global êhrrftdziftd J dados importantes para a_ y apíidadao, dos «^uais tanto inde*.pHp quanto addsdorephp predisa». tw ve*. d« duplidav as variáveis da toYc%ão ao bando «m dada sdriptj nós podemos »ove- las para um arquivo indlude» ■tornando— as dompartílhadas- connectvars.php A îîistiruçâpR EqU ÍR E^O N C E insere c p j í g p s J e s c r i p t s c o n i p q r t í l l i a c l o s e m P U t t P s s c r i p t s .
  • 285.
    trabalhando com dadosarmazenados em arquivos <?php r — — — — — — — — — — — — ' I // Define as constantes da aplicação define('GW UPLOADPATH’, 'images/'); // Define as constantes da conexão ao banco de dados 'define(’DB_HOST1, ' www. guitarwars. net'); Idefine(’DB_USER', 'admin'); |define(’DB_PASSWORD'r ’rockit1) ; define('DB NAME', ' gwdb1); // Conecta-se ao banco de dados $dbc = mysqli_Connect(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME) // Obtém os dados das pontuações a partir do MySQL Squery = "SELECT * FROM guitarwars"; Sdata = mysqli_query($dbc, $query); I I Faz um loop através do array contendo os dados das pontuações, formatando-os como HTML echo 1 <table>1; while ($row = mysqli_fetch_array( $data)) { // Exibe os dados das pontuações echo ' <tr><td class="scoreinfo">' ; echo '<span class="score">1 . $row [ 'score '] . echo 1 <strong>Wame:</strong> ' . $row['name' ] echo ' <strong>Date:</strong> ' . $rowí'date'] if (is_file(GW_UPLOADPATH . $row[1screenshot1] ) s& filesize(GW_UPLOADPATH . $row['screenshot']) > 0 ) { echo '<tdximg src=" 1 . GW_UPLOADPATH . $row['screenshot'] alt="Score image" /></td></tr>'; </spanXbr />' 1 <br />'; '</td>'; else { echo ' <td><img src=”1 . GW_UPLOADPATH . 'unverified.gif' alt="Unverified score" /x/tdx/tr>'; } } echo '</table>'; mysqli_close($dbc) ; índex.php T fe S T O r iv e Sensacional! Agora eu também tenho acesso aos dados compartilhados! addscore.php ■ [ i l B U i i W O do arquivo enviado para uma constante, que será então com partilhada através de um arquivo include. ouíro passo novo[ doisâs são J di+iííis dc planejar de ânhcmâo, portanto vode terá de estar pronto para ajustar o seu projeto sempre <ue necessário- Crie dois arquivos Include para o Guitar Wars, e depois compartilhe-os entre os outros scripts. C rie dois novos arquivos de texto, a p p v a r s .p h p e c o n n e c t v a r s .p h p , e digite neles o código m o strad o n a p ág in a anterior. Em seguida, ad icione instruções r e q u i r e _ o n c e a i n d e x .p h p e a d d s c o r e .p h p p ara q u e am bos os scripts com p artilh ad o s sejam incluídos. Envie todos os scripts p a ra o seu servidor e teste o fo rm u lário A dicionar P o n tu ação e a página principal, p ara se certificar de q u e eles estejam fu n cio n an d o com a nova e ap rim o rad a estru tu ra organizacional com arquivos include. você está aqui ► 257
  • 286.
    A instrução ORDERBY 0 mais importante para as pontuações máximas é «-timing- a ordem O G uitar W ars fin alm en te tem o su p o rte a im agens, p erm itin d o q u e os usuários enviem capturas d e telas p ara validar os seus recordes. E m bora isso seja um g ran d e ap rim o ram en to n a aplicação, ain d a n ão resolveu o p ro b lem a de q u e os usuários têm reclam ado h á algum tem p o - a o rd em das po n tu açõ es n a p ágina principal. /{Üd>onar noVâ agora envolve o envio de Wage»— — *ue parei« oiimo, cxtcbo pelo râio das pontua^oes snão esiare» e» orde»J E verdade, as pontuações n ão estão em ordem . Elas estão sendo exibidas n a ord em em q u e se en contram no banco de dados, que é totalm ente arbitrária. Você n u n ca deve perm itir que a o rd em de exibição seja a m esm a o rd em em que os dados se en co n trem arm azenados n o banco, a não ser que ord em realm ente n ão faça diferença. N este caso, precisam os im p o r algum a ord em sobre os resultados da consulta. A instrução SQL O RD ER BY to rn a isso possível.
  • 287.
    trabalhando com dadosarmazenados em arquivos luws < Iü Geladeira <1° VHF & M/-5QL §1 Veja se você consegue descobrir como ORDER BY funciona, usando os imas abaixo | | para criar instruções SELECT ordenadas que resultem na saída abaixo. Circule também I| qual consulta você acha que representa a melhor solução para o Guitar Wars. Dica: ASC significa ASCendente e DESC significa DESCendente. 1File Edit Window Help YYZ I 5 I 2 0 0 8 - 0 4 - 2 3 09 : 1 3 : 3 4 Ash Lor: S i m p so n 4 : 2 0 0 8 - C4 - 2 3 0 9 : 1 2 : 5 3 | E e l i t a Cnevy ! I 2 0 0 3 - 0 4 - 2 3 0 3 : 0 6 : 3 5 : E d d i e v s n i l l - I 6 i 2 0 0 8 - 0 4 - 2 3 2 4 : 0 9 : 30 ! Kenn y L a v i t z ! 2 I 2 0 0 3 - 0 4 - 2 2 21 : 2 7 : 5 4 j N e v i l J o h a n s s o n j 1 i 2 0 0 8 - 0 4 - 2 2 - 14 : 37 : 34 I Paco J a s L o r i u s I 7 I 2 0 0 3 - 0 4 - 2 4 0 8 : 1 3 : 5 2 | P h i z L s i r s t o n I screensho; I 36642 0 I I 345-900 I I 12 7 65 0 i ! 18 6580 I p h i z s s c c r e . g i f 7 r c w s i n s e c (Q.CGÜ5 s e c } A^ui, os resuliâdos da donsulta são retornados em order« desdendesvte> for fcmtuadao, e defois em ordem asdendente, for data- A^ui, os resultados da eo^ulta são »retornados s** ordem alíabétida asdendente, for nome.
  • 288.
    ímãs dophp &mysqlsolução : Im a s d e G e la d e ir a dç> P B P & M / S Q L - S p I u ç I lp Veja se você consegue descobrir como ORDER BY funciona, usando os imas abaixo para criar instruções SELECT ordenadas que resultem na saída abaixo. Circule também quai consulta você acha que representa a melhor solução para o Guitar Wars. Dica: ASC significa ASCendente e DESC significa DESCendente. A^ui, os resultados da consulta sao retornados em ordem numérica descendente, for pontuaçao, e depois em ordem ascendente, por data I File Edit _Aw, os resultados da Consulta sao retornados em ordem al-Pabetica ascendente, por nome- tsta t a Consulta de «ue precisamos para o Quitar Wàrsj FROM guitarwars j ORDER BY DESC í SC 5 ! 2008-04-23 09:13:34 ; Ãshton — 1 -/ - 3 2008-04-23 09:06:35 ! Eacie vanali; ! 34 ! 2006-04-2 3 09:12:53 ; Belita C'svy ! . ?8 i 2008-04-24 08:33:52 1 Phiz T , azrs.cn p 1 ■ £006-04—22 14 :37:34 i i : anc • i2 2 ! 2008-04-22 ■ í1:i - :o4 Nev_ : Johansson i 5■ 6 - -4Á----- U:09:iC | Kenny lavitz 0 ordenamento por data t seCundário, e so se aplica caso haja duas pontuações idênticas, o e^ue nao oCorre a^ui mas te» uma boâ probabilidade de acontecer guando se te» um Conjunto bastante grande de dados. A vfrjula e necessiv-ia para se separar os dois níveis de ordenamento.
  • 289.
    trabalhando com dadosarmazenados em arquivos Homenageando o (toitar Warrior número um C om a o rd em das p o n tu açõ es consertada, agora é possível fazer u m a m elh o ria in esp erad a n a lista dos recordes: colocar a m aio r p o n tu a ção de todas n o tipo d a lista. O G uitar W arrior com a m aior p o n tu ação m erece u m cabeçalho dizendo claram en te q u e ele é o n ú m e ro um , p ara que n ão h aja dúvida... e p ara q u e os adversários saibam qual p o n tu ação eles tem de superar. Um tabeçalKo sdlientâ dlavâmeirvfce a poníuaçao m£*i»*a, estabeledendo um alvo para os demais éjuiiav- W a(rlriors.. u a9 ex iste m perguntai Idiotas "i • Muitas pontuações ainda estão sem verificação? Isso nãoé um problema? É sim. Mas não nos impede de seguir adiante e incluir a funcionalidade de chamar a atenção para a pontuação máxima. A falta de verificação, na verdade, só significa que em algum momento nós teremos de limpar a lista, excluindo os registros sem comprovação. De fato, assim que terminarmos com esta funcionalidade de salientar a pontuação máxima, já passaremos para a questão das pontuações sem verificação. você está aqui ► 261
  • 290.
    adicionando um poucode css Formate a pontuapão máxima com HTML e CSS A coisa m ais im p o rtan te sobre o cabeçalho q u e estam os in clu in d o é que ele será visto claram en te acim a d e todas as dem ais p o n tu açõ es d a lista. Para isso, precisarem os de ajuda tan to do H TM L q u an to do CSS, p ara a p arte visual. O ca b e ça lh o será g erado com o u m a lin h a n a tabela H TM L, com u m CSS especial aplicado a ela. Este estilo, t o p s c o r e h e a d e r , deve ser acrescen tad o à folha de estilo s t y l e . c s s do G uitar Wars. Centraliza a pontuadão máxima no dabeçalho. Usa um -fundo de dor esdurd dom te*to brand©> para íâz.cr a pon-Uadao má/ima realmente saltar aos olhos- £*ta dlasse de estilojá está sendo usada para salientar os erros de inserdao de dados ho sdript Adidionar Pontuaçao- .e rro r { font-w eight: b o ld ;-^7 c o lo r: ÍFFOOOO; .topseoreheader { text-align: center; font-size: 200%;^ background-color: #364Q7F color: #FFFFFF; .score { font-size:150%; color : #36407F; .scoreinfo { v e r tic a l-a lig n : top p a d d in g -rig h t:15px; } Estas duas dlasses de estilo ja estâo -formatando as pontuadoes, na pagina " prindipal- style.css garante <ue o tamanho da -fonte seja aumentado em relaçao às demais pontuações- O script i n d e x .p h p já está g eran d o u m a tabela H T M L co n ten d o a lista das pontuações. G erar u m cabeçalho ap en as p ara a p o n tu ação m áxim a req u e r q u e isolem os o p rim eiro registro, o qual g ara n tid am en te será a m aior p o n tu ação , u m a vez q u e a lista ag o ra está o rd en ad a. U m loop w h ile é posto em ação, e nós precisam os de algum a fo rm a d e co n tar as p o n tu açõ es e g erar o cabeçalho apen as p ara a prim eira..;
  • 291.
    trabalhando com dadosarmazenados em arquivos Complete ocódigo do script index .php do Guitar Wars de modo que ele adicione um cabeçalho formatado para a pontuação máxima, usando o estilo GSS tops coreheader. Dica: Não se esqueça de que esse cabeçalho fará parte da tabela HTML contendo os recordes, a qual possui duas colunas. // Faz um loop através do array contendo os dados das pontuações, formatando- os como' HTML echo 1<table>'; $i = 0; while ($row = mysqli_fetch_array{$data)) { // Exibe os dados das pontuações if (..................) { } echo 1ctrxtd class="scoreinfo">'; echo 1<span'class="score">' . $row[1score' ] . '</span><br />'; echo 1<strong>Name:</strong> ' . $row[,namel] . '<br />'; echo '<strong>Date:</strong> ' . Srowf'date'] . 1</td>'; if (is_file(GW_UPLOADPATH . $row[1screenshot[]) && filesize(GW_UPLOADPATH . $row[1screenshot1]) >0) { echo ’<td><img src="' . GW_UPLOADPATH . $row[1screenshot1] . ,n alt-"Score image" / x / t d x / t r > '; } else { echo 'ctdximg src="' . Gw_uPLOADPATH . 'unverified.gif1 . alt="Unverified score" /></td></tr>' ; } } echo ,</table>1; I index.php f a . E x k t á c o você esté aqui ► 2 6 3
  • 292.
    exercício solução Complete ocódigo do script index.php do Guitar Wars de modo que ele adicione um # cabeçalho formatado para a pontuação máxima, usando o estilo CSS topscoreheader. Rcicio Dica: Não se esqueça de que esse cabeçalho fará parte da tabeia HTML contendo os recordes, a qual possui duas colunas. SoL oção fi c 3 vâviivcl « U C-foz. d Conta das pontuações - nós podemos usa-ía para isolar a primeira pontuaçao- // Faz um loop atravé^ do array contendo os dados das pontuações, formatando-os como HTML / Se f I -for igual a O, nós sabemos t^ue esta é a .x " primeira^ou seja, a maior) while {$row = mysqli_fetch_array($data)) { pontuaçao, e portanto, devemos gerar o código ttTML para o cabeçalho. echo '<t // Exibe _ os.dados . das, pontuações if ( 7 i,=~ OJ í echo '< tr> < td Colspan=tt2-Mclass—w topsCoreheaderw >Tõp Score: * frov^rsCore^ •4</td x /b r^ i } echo '<tr><td class="scoreinfo">'; echo '<span class="score">' . $row[1score' ] . '</span><br />'; echo ' <strong>Name: </strong> 1 . $row['name'] . ’ <br />'; echo 1 <strong>Date: </strong> ' . $row['date’] . ’ </td>'; if (is_file(GW_UPLOADPATH . $row['screenshot1] ) && filesize(GW UPLOADPATH . $row['screenshot' ] ) > 0 ) { echo '<td><img src="' . GW_UPLOADPATH . $row['screenshot' ] . ' " alt="Score image" /></td></tr>' ; } else { echo 'ctdximg src="' . GW_UPLOADPATH . 'unverified.gif’ . alt="Unverified score" / x / t d x / t r > ' ; fi classe de estilo topscoreheader enContra-se armazenada em style-Css- echo '</table>'; Incrementa o Contâdor Bo -final do loop pelas pontuações —este Codigo e o mesmo «iue fi — fi + /;• index.php
  • 293.
    Tejst O ri v g --------------------------- trabalhando com dados armazenados em arquivos Ordene as pontuações e dê destaque à maior delas. Modifique o scrípt index .php de modo que ele passe a usar a nova consulta SELECT ordenada, e depois, adicione o código que irá gerar o cabeçalho para a pontuação máxima. Envie o novo script para o seu servidor e abra-o no seu navegador, para ver a maior pontuação sendo exibida proeminentemente. , ™ r . Nsme: AshtoE Simpsou Donxuâtdo ' Date2GOS-04-2309:13;34 a^ova e mostrada destatada^cntc W 5 da lisfca de r t t ordes. É verdade, ainda precisamos tratar das pontuações n ã o -v e rific a d a s. Mas uma coisa de cada vez. Parece que surgiu outro problema, que está impedindo as pessoas de enviarem os seus arquivos gráficos. você está aqui ► 265
  • 294.
    adicionando restrição detamanho para imagens fakt av^uivo «ao somente e ggawfccs6o íiWrb? w>ai0*‘do l>V(C^h *»& ta^bew *ao c ne» se^t*ev“u»a àmage»! ethelshugescore,pdf O arquivo não só é gigantesco, ele nem é uma imagem! Temos um problema: nosso formulário estã rejeitando alguns arquivos sem dizer aos usuários por quê. Na verdade, é bom que ele esteja rejeitando arquivos, neste caso porque são grandes demais - lembre-se de que limitamos o tamanho dos arquivos a 32 KB, no código do formulário. Mas precisamos avisar ao usuário por que isso está acontecendo. E não apenas isso, nós também não queremos que os usuários enviem arquivos que não sejam imagens. Adicionar alguma validação ao formulário de Adicionar Pontuação permitirá que nós tenhamos maior controle sobre o modo como os arquivos são enviados. Assim, a validação no formulário addscore .php servirá a dois propósitos essenciais. Primeiramente, ela poderá aprimorar a prevenção contra uploads de arquivos grandes demais, fornecendo aos usuários uma notificação de que o arquivo não pode ter mais que 32 KB. E, em segundo lugar, ela poderá impedir que as pessoas enviem arquivos que não sejam imagens. O formulário precisará ter validação tanto para o tamanho quanto para o tipo do arquivo. Gitítar Wars - Add Yonr High Score f Sorrv,tfaerewas, prcbkm nploadtagyourserasssfcot^ Narae: :ahíuSidreí ~ Sccae: ’swJõõã ~ ~ ~™ Screen shnt: fchoo«.fh,-"» 1 Qfli{
  • 295.
    trabalhando com dadosarmazenados em arquivos São permitidas apenas imagens pequenas Então, como exatamente nós verificamos o formulário Adicionar Pontuação e nos certificamos de que as imagens enviadas estarão obedecendo às limitações de tamanho e tipo? A resposta se encontra na variável superglobal $_FILES, da qual, se você se lembrar, nós obtivemos a localização de armazenamento temporário do arquivo enviado, para que pudéssemos movê-lo para a pasta images. Agora, iremos usá-la para obter o tamanho e o tipo MIME do arquivo. 0 do arquivo C*£ede IMBi muito maiov do «ue o ytosso limite de iv f a (ttQ 0 .Y 1 l ^tes i-2-2-AlB) ou $ FILES[ 1screenshot’] ['size1] $_FILES['screenshotT]['type' ] Não queremos apenas que os arquivos gráficos sejam menores do que 32KB, mas também precisamos que eles sejam de um tipo que possa ser exibido como imagem web. Os seguintes tipos MIME são tipicamente usados para se representarem imagens web: $_FILES[ 1screenshot']['type' ] GIF 0 tifo do € PDF,y t não t u» tipo aceitável de ar^ivo pava web, tomo qfF 0P3 ov> PvcopãVOS ya-fitos tonteado a taptuva de tela do»pvòbatfâria da pcmtua^ao... Escreva uma declaração if para verificar se um determinado arquivo é uma imagem, checando também se ele é maior do que 0 bytes e menor do que o determinado na constante GW_MAXFILESIZE. Assuma que o tamanho e o tipo do arquivo já tenham sido armazenados em variáveis chamadas $screenshot_size e $screenshot_type. if ( ) { você está aqui ► 2 6 7
  • 296.
    incorporando arquivo devaiidação no aplicativo tpowteseu lápis Solupão S o lu ç ã o Escreva uma declaração if para verificar se um determinado ^ arquivo é uma imagem, checando também se ele é maior do que 0 bytes e menor do que o determinado na constante GW_m a x f i l e s IZE. Assuma que o tamanho e o tipo do arquivo já tenham sido armazenados em variáveis chamadas $screenshot_size e $screenshot_type. para íf(((fscreenshot t ype ==•=• .1! “ 77.''»agç/jpçgOi) '-eConheCer i t . í imagens jp<$.... pjro?. J).íf.^r«r'.shoL.^ypc.r r . !)***&/&*!}). M Alguns «avegadoires este tipo Mf/VíE (fscreens)i©tmsizc > && (fsôreensh<rtjsize <—^VV^AI/t^FfLÍSl^-E)) Uma vez. <^ueo tacanho máximo para o arquivo agora aparece cm mais de um lugar no sdript Adicionar Pontuado, -Paz. sentido armazína-lo na -forma de uma constante- appvars.php A validação de arquivos torna a aplicapão mais robusta Um nouf.o de validarão ainHa muito a tornar mialmipr anlirarão Uma »ensaiem d e Um pouco de validação ajuda muito a tornar qualquer aplicação PHP mais intuitiva e fácil de usar, além de mais segura. Agora, uma mensagem de erro ajuda o usuário saber exatamente quais são as limitações impostas sobre os arquivos gráficos a serem enviados. Uma »»ehsagem de erro ajuda a explicar exatamente < ^ u e tipos de arquivos podem ser enviados. ethelshugescore.pdf jeanpau1sscore.jpg phizsscore.gif jacobsscore.png
  • 297.
    trabalhando com dadosarmazenados em arquivos Uma vez. ^ue estamos bomando O sdnpt mais robusto, também e uma boa ideia veri-fidar a £*»be uma mensagem de erro desdrVtiva, daso o arquivo seja do tipo errado, ou grande demais. if ('empty($name) &5 ! empty($score) && ! empty($screènshot)) { if {((5screenshot_type == ’image/gif’) I I (Sscreeishot_type == ’image/jpeg') | j ($screenshot_size > 0 ) && ($screensh©t_size <^/üW_MAXFILESIZE)} { if ($_FILES [’screenshot' ]['error'3 == // Move o arquivo para a pasta-alvo $target = GW_UPLOADPATH . $screenshot; if (move uploaded file($_FTLES[1screenshot1]['tmp_name'], $target)) Í // Conecta-se ao banco de dados $dbc = mysqli_c0nnect(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME); // Escreve os dados no banco $query = "INSERT INTO guitarwars VALUES ( 0 , NOW(), '$name’, '$score', // Confirma êxito com o usuário echo '<p>= Obrigado por adicionar o seu recorde! </p>' ; ^ echo 1<p><strong>Name: </strong> ‘ . $name . '<br />'; echo ' <strong>Score:</strong> ’ . $score . '<br />'; echo ' <img src="’ . GW_UPLOADPATH . $screenshot . alt="Score image" />< echo '<p><a href="index.php">£lt;&lt; Back. to high scores</a></p>' ; // Limpa os dados da pontuação para limpar o formulário $name = Çscore = $screenshot = mysqli_close($dbc); . } else { echo '<p class=’ ’ error">Sorry, there... = Desculpe, houve um problema com o arquivo que você tentou enviar.</p>*; } ) } else { echo '<p class=”error”>0 arquivo precisa ser um gráfico GIF, JPEG ou PNG com ’ menos de ’ . ’ KB1 . (GVJ_MAXFILESIZE / 1024) . ' KB de tamanho. </p>'; } // Tenta excluir o arquivo gráfico temporário unlink($_FILES['screenshot' ] f'tmp_name']); else { echo ’ <p ciass="error">Por favor, digite todas as informações para adicionar sua pontuação. </p>1; mysqli_query($dbc, $query); você está aqui ► 2 6 9
  • 298.
    test drive addscore.php Tf e S T O R f v e Adicione a validação dos arquivos gráficos ao script Adicionar Pontuação. Modifique o script addscore .php de modo que ele passe a usar o novo código de validação dos arquivos gráficos. Envie o script para o seu servidor e teste o formulário Adicionar Pontuação com imagens válidas e inválidas (imagens grandes demais ou arquivos de outro tipo). não existem Perguntas idiotas í * Por que existem dois tipos MIME diferentes para imagens JPEG? Essa é uma pergunta que pode ser mais bem respondida pelosfabricantes de navegadores, os quais, por algum motivo, decidiram usar tipos MIMEdiferentes para imagens JPEG. Para nos certificarmos de que avalidação de arquivos JPEGfuncionará na maior quantidade de navegadores possível, é necessário verificar ambos os tipos. * Por que é necessário verificar se os arquivos têm mais de 0 byte? Os arquivos gráficos não têm sempre mais do que 0 byte? Nateoria, sim . Masétecnicamentepossível criar um arquivode0 bytenoservidor, casoousuárioespecifique umarquivoquenãoexista noseu própriocomputador. Apenasparase resguardarcasoissoaconteça, addscore. php tomaaatitudemaissegura, qual sejaa deverificar seoarquivonãoestávazio. " F * Por que GW_MAXFILESIZE é colocado em appvars.php, uma vez que só é usado em addscore.php? Embora seja verdade que appvars.php foi elaborado paraarmazenar dados que sejam compartilhados entre diversos scripts, eletambémé um bomlugar para se armazenar quaisquer constantes. Neste caso, colocar GW_MAXFILESIZEem appvars.php facilita que a encontremos, caso você queira aumentar o limite de tamanho paraos arquivos enviados. F -C o m o funciona a linha de código que contém @unlink()? Afunção internado PHP unlink () apaga um arquivo do servidor, no nosso caso o arquivo temporário quefoi enviado. Uma vez que é possível que o upload tenha falhado, eque não haja arquivo temporário, nós suprimimos quaisquer potenciais erros gerados por unlink () colocando umsímbolo (@ ) antes dele. Você pode colocar @ nafrente de qualquer função PHP para suprimir o recurso de relatar erros dessa função.
  • 299.
    trabalhando com dadosarmazenados em arquivos E quanto às pontuações não verificadas? Elas nSo desapareceram, se é que você não reparou. A lista das pontuações precisa ser limpa. Com o upload dos arquivos gráficos aperfeiçoados graças à validação, não podemos continuar ignorando o problema das pontuações não verificadas. As novas pontuações, com imagens comprobatórias, não podem ficar atrás das pontuações antigas sem comprovação, as quais podem ou não ser legítimas. O Guitar Wars precisa de uma forma de remover pontuações antigas! esta tomprovada, o ^ e *ao desperta muitâ towÇian£3 nos outros usuários.. g u i t a r w a r s ; 345900 ^ N ane: Etkiis Vanaii : B ate2 0 0 5 -0 4 -2 3 0 9 :0 6 :3 5 id i - — .fa,. ■ ■ =i; war« .. 7 2008-04-22 14:37:34 Paco Jastorius 127650 2 2008-04-22 21:27:54 Nevil Johansson 98430 3 2008-04-23 09:06:35 Eddie Vanilli 345900 4 2008-04-23 09:12:53 Belita Chevy 282470 5 2008-04-23 09:13:34 A shton Sim pson 368420 V 2008-04-23 14:09:50 KennyLavitz 64930 7 2008-04-24 08:13:52 Phiz Lairston 186580 phizsscore.gif M pointuâ^oes sem imagens £omprobatórias precisam sev removidas do banco de dados, Escreva aqui como você faria para limpar as pontuações não verificadas da lista: você esté aqui ► 271
  • 300.
    adicionando uma páginaadmin Planeje uma página Admin Uma vez que só precisamos remover algumas pontuações não verificadas do banco de dados, é perfeitamente razoável simplesmente acionar uma ferramenta SQL e remover linhas manualmente, com algumas consultas DELETE. Mas esta poderá não ser a última vez que tenha de remover uma pontuação, e não é divertido ter de usar consultas SQL manuais para fazer a manutenção de uma aplicação web. A ideia aqui é elaborar uma aplicação que possa ser mantida com o mínimo de trabalho possível. O que precisamos é de uma página à qual somente o administrador do site tenha acesso, e que ele possa usar para remover pontuações... uma página Admin! Mas precisamos tomar muito cuidado na hora de distinguir quais partes do Guitar Wars são para o administrador e quais partes são para os usuários. Estas páginas são para os usuários: As a p lic a ç õ e s W eb Çte<Juetitemente in c lu e m páginas pataacessp púUíco, bem como páginas admín apenas para ps administradores Çazerem^ manutençãp do site- A fiÿn d M»dio*air Pontuaçao e < 3pâÿnâ principal do éjwtar lAfôrs sSo elaboradas para os usuir»os -Ç'm aîs submeterem e visualizarei suas pontuações. Esta página é apenas para o administrador: pa^inâ hd**"me elaborada apenas para uso do administrador do £«te —vote nao «uer os *suârios -finais possa» sair por aí removendo pontuações. GuitarWars-HighScoresAdmiiriaratíon ____ ■ 08:13:343BHa>ag«w ; » fa U irrtM 2008-04-2408:13^2 1863H 2O0S«-2«OS-,2 li , MOSíM-i, M.OTJ0W?» R m i> Oidar em urn link “Remove’ apa^a a respectiva pontuaçao.
  • 301.
    trabalhando com dadosarmazenados em arquivos fccícío Escreva aqui o que os scripts Admin e de Remover Pontuação precisam fazer para implementarmos um recurso de remoção de pontuações no Guitar Wars. Em seguida, faça um esboço de como a remoção afetaria uma linha da tabela g u i t a r w a r s e a sua respectiva imagem. admin.php Servidor web removescore.php guitarwars ■ f ! ! » I Í ! I f c l ■ H M M i score Mxeensfcot 1 2008-04-22 14:37:34 Paco Jastorius 127650 2 2008-04-22 21:27:54 Nevil Johansson 98430 3 2008-04-23 09:06:35 Eddie Vani/Ii 345900 4 2008-04-23 09:12:53 Belita Chevy 282470 5 2008-04-23 09:13:34 Ashton Simpson 358420 6 2008-04-23 14:09:50 Kenny Lavitz 64930 7 2008-04-24 08:13:52 Phiz Lairston 186580 phrzsscore.gif
  • 302.
    exercício soiução Escreva aquio que os scripts Admin e Remover Pontuação precisam fazer para implementarmos um recurso de remoção de pontuações no Guitar Wars. Em seguida, faça um esboço de como a remoção afetaria uma linha da tabela SoLuÇâo guitarwars e a sua respectiva imagem. Guitas' Wars - High Scorn Administration I Bekwisalia.ofallG oíB xW a reliighs c o re s .Ussfiiiip a g etore m o vesconsa sn e e d e d .J AshtonStapsoa 2Ö08-0+-2309:13:513(58420Ramftw ’ EddieVaitQB 2Q0MM-23 09«635 345900 toliW S Be&aCbery 2003^)4-2408;02:11282470 PKiLaftstoa 2008-04-2408:13.52 1S6580BsSBEä PacoJaaurius 2008-04-240S«2:11 1276SGg&s£2& NenUohaasson2008-04-2403.(0:11 98430 Reirovc Kaonj-Lavttz 200804-23 14:09’5064930 Emwe Servidor web 1 0 strip t admin.phf lista, todas as linhas da tabela, wda uma dom um link w Rcmovew ao lado, o <ual repassa iníorma^oes para o sóript Removçr Pontuaçao- admin.php 0 .s^lft-VcmoycstorçrfKp. remove...... propriamente,o registro do.bando de e^lui o arquivo jyraíido do.servidor, e*ibe uma mensajem de,fiowíirmação- dados, D a t^ e depoiss^jl Guitar Wars -RemoveaHigh Score T ltèh ig hs c o n ?of3 6 S 4 2 0fcrA U ito nS in q p o o sw a ss a c c e *s fu ltyre o s > v c d . « B a c k ,isadminpage removescore.php g u i t a r w a r s m ilBlÜftM» « 0 « screenshot 1 2008-04-22 14:37:34 Paco Jastorius 127650 2 2008-04-22 21:27:54 Nevil Johansson 98430 3 2008-04-23 09:06:35 Eddie Vanilli 345900 4 2008-04-23 09:12:53 Belita Chevy 282470 6 2008-04-23 14:09:50 Kenny Lavitz 64930 7 2008-04-24 08:13:52 Phiz Lairston 186580 phizsscore.gif pmbora esta Imha em par-utuia» now tenHa um arquivo ^ráíido assodiado, o sdript Remover Pontuação terá de estâr pronto para exdluir do servidor os arquivos de pontuações ^ue os tenham dssodiados.
  • 303.
    trabalhando com dadosarmazenados em arquivos Gerelinks para remoção depontuapões na página Admin Embora o script Remover Pontuação seja responsável pela remoção propriamente dita, nós precisamos de um script Admin que nos permita selecionar uma pontuação a ser eliminada. O script admin.php gera uma lista de pontuações, com links “Remove” para cada uma. Esses links repassam os dados referentes à respectiva pontuação para o script removescore.php. <?php require_once ( ' 'appvars .php' ) ; require_once ('.connectvars.php' ) ; m /! Conecta-se ao banco de dados admin.php $dbc = mysqli_COnnect(DB_HOST, DBjJSER, DB_PASSWORD, DB_NAME); // Obtém os dados das pontuações a partir do MySQL $query = "SELECT * FROM guitarwars ORDER BY score DESC, date ASC"; $data = mysqli_query($dbc, $query); // Faz um loop através do array contendo os dados das pontuações, formatando-os como HTML while ($row = mysqli_fetch_array{$data)} ■ { echo '<table>'; A URL fèrâ o i f i R«wowr Pon-tuâáJo «stá íazjCndo mais do ‘V*« a^cnâs dviav um link ^av3 o s tric t ■ * mysqli_close($dbc) ; você está aqui ► 275
  • 304.
    introduzindo a requisiçãoGET Osscriptssãocapazesdecomunicarem-seunscomosoutros A URL de um scriptp^de ser usa<Japata enviar dadps na í°rma de uma r e ^ u ls iç ã ^ G E T T Para o script Remover Pontuação poder excluir um registro, ele precisa saber qual. Mas isso é decidido no script Admin. Isso leva à pergunta “com o o script Admin informa a Remover Pontuação qual registro deve ser excluído?”Essa comunicação entre os scripts é realizada empacotando-se os dados como parte de uma URL “Remove”para cada pontuação mostrada na página Admin. Se você analisar os detalhes da URL de uma determinada pontuação, perceberá que todos os dados referentes a ela se encontram lá. Cada m-Çormaçao tem w rv >nomC t um valor, e e separada de outros pares de nome/valov ^or um símbolo ? ■ A URL de K RemoveM Cria links para o script removesCore.php, ^às tambem inclui dados reíerentes à linha a ser excluída- Guitar Wars - High Scores Administration i imm-X 09:13:3435g42(f K ^ n .......... 2«MM3«MMas3«SOtSíVJ 200MM*(»:l3aBigíS »aB(HB Wahâns™ JOOWHMoMttn98430 Haw» aa»OM31*OM[»««» SaaaB Clicar neste link nao só abre o sír] Remover PontuaWo, Como tambem envia dados, na íorma de uma requisição éj£T- OK, então os dados são enviados através de uma URL, mas como exatamente o script Remover Pontuação põe as mãos nesses dados? Os dados enviados a um script através de uma URL ficam disponíveis na superglobal $_GET, que é um array bastante semelhante a $_POST. Empacotar dados em uma URL linkada é o mesmo que usar uma requisição GET em um formulário web. Em uma requisição GET tradicional do HTML, os dados do formulário são automaticamente enviados para o script que os processará, como parte da URL desse script. Estamos fazendo o mesmo aqui, ao criarmos manualmente a nossa própria requisição GET como parte de uma URL personalizada. Assim como $_POST, para usar o array $_GET para acessar os dados das pontuações você precisa do nome de cada informação desejada. URU que leva 3 / umscript serve C o m o ^ £orma de envia*/ Ml o nome da ih&rmacao e usado para acessa- array umâ dados mportânteS)
  • 305.
    trabalhando com dadosarmazenados em arquivos Não entendo por que tanto entusiasmo com GET. Por que não podemos passar os dados para o script usando P05T? E assim que vimos fazendo até agora. As requisições POST só podem ser iniciadas por um formulário, enquanto que as requisições GET podem ser empacotadas como URLs. Até o momento, nós sempre enviamos dados aos scripts a partir de um formulário, no qual o script encontrava-se listado como a ação para o botão Submit. Quando o usuário preenche o formulário e clica no botão Submit, os dados são empacotados e enviados para o formulário como uma requisição POST. O problema é que a página Admin não usa um formulário para iniciar o script Remover Pontuação. Ela apenas estabelece links para o script, via uma URL. Assim, nós precisamos de uma forma de enviar dadosa um scriptusando nada mais do que uma URL. E aqui que GET é particularmente útil, uma vez que fornece acesso a dados que estão empacotados em uma URL como parâmetros. De forma semelhante a POST, os dados que são enviados ao script através de uma requisição GET ficam disponíveis através de uma superglobal, mas esta é chamada de $_GET em vez de $_POST. Oi -formulários web -íVe<uentemen-fce usam re^uisidoes POST para submeter dados, os <uas -Pica» armazenados no array ? POST. 0 envio dc dados através de uma URL e -feito dom éj£T, e os dados sao armazenados no array ?_é}£T. $ POST v o c ê está aqui ► 2 7 7
  • 306.
    GET versus POST SobreG-ETse POSTs A diferença entre GET e POST não é apenas de formulário versus URL, uma vez que as requisições GET podem ser (e frequentemente são) usadas para se submeter dados de formulário, também. A distinção real entre GET e POST tem a ver com a intenção da requisição. GET é usada principalmente para se obter dados do servidor sem afetar nada nele. POST, por outro lado, geralmente envolve o envio de dados para o servidor, após o que o estado do servidor normalmente se modifica, de alguma forma, em resposta aos dados enviados. Os doísi^pPS de te ^ u ís lç õ e s W eb , GET~e rOSTT controlam o mojo c o n ]o VQC-e e ílV x c l dctdP S d e e pQtcl scripts. GET — '—~ ~ posT ; banco. Os dados de GET, as >em uma.resP“ ^ . só odem ser feitas mediante ,requisições ,^ nWeb Também ao . --------„„ltc . aaçãodeu m t o " ^ osemiadosemuma I ao m ■ uma URL Ao contrário contráriode GET,os ndid0s. I TOST' GETse™ pnncpalmente para ;requisiçãoPOSTBc^ enviarpequenas quantidades de dados. nã° ermtÊamaaaÊÊmmmmt'' — Geralmente usada para obtenção de dados que nao modifiquem nada no servidor. Para quantidades pequenas de dados, GET também é útil para enviá-los diretamente ao servidor, em uma URL. Ao contrário de POST (TFT________• T * - Já vi formulários web que usavam GET. Como isso funciona? Tanto GET quanto POSTtêmo seu lugar, no que se refere aformulários web. Ao se criar um, o atributo method da tag <form> controla o modo como os dados são enviados, enquanto que o atributo action identifica o script que deverá receber e processar os dados: <form method="post’ ' action="addscore.php"> Quando o botão submit é clicado para submeter este formulário, o script addscore.php é executado, eosdados são enviados a ele através do array $_POST. Mas você poderia muito bemter escrito atag <form> desta maneira, emcujo caso os dados seriamenviados através do array $J3ET: <form method="get" action="addscore,php"> "P - Ah, então não faz diferença se eu uso o método GET ou POST? Errado. Faz bastante diferença. GETgeralmente é usado para se obter dados de umservidor, sem modificar nada nele. Assim, GETé perfeito para formulários que p e r g u n ta s id io ta s requisitem inTormações do servidor semalterar o seu estado, como por exemplo, ao selecionar linhas de um banco de dados. POST, por outro lado, é mais adequado para requisições que afetemo estado do servidor, como por exemplo, emitir consultas INSERTou DELETEque modifiquem o banco de dados. Outra distinção entre GET e POSTé que os dados enviados através de GETficam visíveis em uma URL, enquanto que os dados de POST ficamescondidos e, portanto, umpouquinho mais seguros. "P * Como essa distinção entre GET e POST se reflete no envio de dados a um script através de uma URL? i l : Bem , antesdetudo, vocêsópodeenviardadosaum scriptatravésdeumaURLseestiver usandoumarequisição G ET, portantoPOSTéeliminadoimediatamente.Alémdisso, umavezqueGETéusadounicamentecomrequisiçõesque nãoalteremoestadodoservidor, issosignificaquevocênão devefazer INSERTs, DELETEFROMsouqualqueroutracoisa quemodifiqueobancodedadosemumscriptqueesteja recebendodadosatravésdasuaURL.
  • 307.
    trabalhando com dadosarmazenados em arquivos Conversa Informal Esta noite falando: GETe POST GET: Mas então, fiquei sabendo que você anda dizendo que eu só presto para responder perguntas, mas não consigo fazer nada com as respostas. E verdade? OK; é verdade que eu não fui elaborado para causar modificações no servidor, como apagar arquivos ou adicionar linhas ao banco de dados, mas isso não quer dizer que não sou importante. Éverdade, mas você fica permanentemente grudado com o seu amiguinho, o Formulário, enquanto que ele e eu somos apenas conhecidos. Eu tenho outras amizades, como por exemplo, URL. Bem, então eu tenho uma pergunta para você. Como exatamente você age quando o seu ajudante, o Formulário, não está disponível. Você sabe que àsvezes a Página não acha necessário se dar ao trabalho de requisitar osserviços do Formulário Calma aí. Só estou ressaltando que, embora a minha função seja obter dados do servidor, eu sou razoavelmente flexível no modo como posso ser usado para isso. POST: Claro que é. Vamos encarar, você não tem nenhuma capacidade além da de pedir algo ao servidor. Sevocê está dizendo. Tudo o que eu sei é que seria difícil fazer algo acontecer sem pessoas como eu, que realmente trabalham. Se o servidor ficasse sempre no mesmo estado, seria tudo bem chato na aplicação. Então vócê acha que o seu “círculo de amizades”de alguma forma compensa a sua incapacidade de agir? Não sei, não. Olha, o Formulário é meu amigo, e há muito tempo eu me comprometi a não fazer nenhuma requisição sem ele. Pode julgar a minha lealdade se quiser, mas eu não vou trair meu amigo! Ok, admito que você tem razão nisso. Fico feliz de ouvi-lo. Foi um prazer conversar com você... você está aqui > 2 7 9
  • 308.
    como removescore.php vaifuncionar (rET, POST e a rewopão de pontuapões Nósjá sabemos que a remoção de pontuações no GuitarWars começa com um link “Remove” na páginaAdmin, o qual aponta para o scriptRemoverPontuação. Nós sabemos também que os dados podem ser enviados através da URL do link para o script. Mas temos um problema: uma requisição GET não deve fazermodificações no servidor, como apagaruma pontuação. Uma possível solução é não mudar nada no servidor... ainda. E se o script RemoverPontuação, inicialmente, exibisse uma página de confirmação antes de realmente excluir a pontuação do banco de dados? W ma pagina de donfiv-mação da ao usuaVi© uma dt <Wnrmar a rem otào, t mvez. de simplesmente exeduia-la instantaneamente A página de confirmação mostra o registro a ser removido, junto com um simples formulário de Yes/No. SelecionarYes e clicar no botão Submit resulta em a pontuação ser removida, enquanto que escolher No cancela a operação. Pensando em termos de GETs e POSTs, o script Remover Pontuação pode exibir a página de confirmação como uma resposta à requisição GET do script Admin. E uma vez que a própria confirmação é um formulário, ela pode emitir a sua própria requisição POST quando submetida. Se o formulário for autorreferente, o mesmo script (removescore.php) poderá processar o POST e executar a remoção. Eis os passos desse processo: É to ta lm e n te pPssíVel, e ate utíl em alguns OctS9S, <JUeO m e sm o sc rip t re s p o n d a ta n to te ^ u ls fç o e s G E ' rOSTT A O scrip t Rem over Pon tuação é iniciado, atravé s de um a req uisição GET, ” pelo usuário ao c licar no link “Rem ove” da págin a Adm in. © O scrip t Rem over Pon tuação u sa o s d a d o s arm azen ad os no array $_GET para ge rar um form ulário de co n firm ação da exclusão. A O scrip t Rem over Pon tuação é iniciado novam ente, d esta vez através de ” um a req uisição P O ST do usuário que e stá subm eten do o form ulário de confirm ação. O O scrip t Rem over Pon tuação a p a g a o registro se le cio n ad o do ban co de dados, e tam bém a p a g a do servidor o arquivo gráfico contendo a im agem com probatória.
  • 309.
    trabalhando com dadosarmazenados em arquivos Vejamos agora como o processo de exclusão de pontuações se desenvolve, através de uma série de passos... Uma requisidao éjET c usada fara se inidiar o sdript Remover Pon{>aça©z enviar os dados da fontuadao atvavés de uma URL. Uma requisição POST e usada para se in'did'r ° sdri^t^ Remover Pontuadão (novamente!^ « enviar a ele o re<ystvo 3 se'r deletado $_GE1 ^ o W á dados de ^ ^ imagem dom^robator‘» a çava esta pont^adao- Este e o mesmo sdript, só que reaÿndo di-feventemente don-forme redeba uma requisição óiè-T ovr POST. Guitar Wars - Remove a High Score TbsMghscoreof368420torAstainSin^soawa>successfullyremoved. « Back toadcâa page removescore.php 0 strict Remover Pontuado apa$a Oreysbro do bando de dados, e a sua re s ^ v a ima^em do servidor. você esté aqui > 2 8 1
  • 310.
    mais sobre GETe POST nã? existem ferguntas Idiotas ? • Como é possível o mesmo script processar tanto requisições GET quanto POST? Aresposta tema ver como modo como o script é chamado. Nocaso do script Remover Pontuação, ele é chamado de duas formas diferentes. A primeira é quando o usuário clica emum link “Remove" da páginaAdmin, emcujo caso uma URL o leva até oscript. Uma vez que os dados são empacotados dentro da URL, essa éconsiderada uma requisição GET. Ela faz oscript gerar umformulário web, cuja ação aponta de volta para o mesmo script Remover Pontuação. Assim, quando o usuário submete oformulário, o script é chamado pela segunda vez. Mas, ao contrário da primeira, não há nenhuma URL contendo dados, e, portanto, nenhuma requisição GET. Emvez disso, os dados da pontuação a ser removida são enviados através de uma requisição POSTeficam, portanto, disponíveis no array $_POST. T * - Então a forma como o script é chamado é o que realmente determina o que ele faz? Sim! Quando oscript vê que alguns dados foram enviados através de uma URL, na forma de uma requisição GET, ele sabe que deve exibir um formulário de confirmação, emvez de apagar qualquer coisa do banco de dados. Assim, os dados enviados no array $_GETsão usados apenas dentro da página de confirmação, e nãotêm nenhum efeito duradouro noservidor. Quando o script vê que há dados sendo enviados através de uma requisição POST, ele sabe que pode apagar os dados do banco, Assim, ele usao array $_POST para acessar os dados e criar uma consulta DELETE FROM que apaga a pontuação. Euma vez que a maioria das pontuações tem um respectivo arquivo gráfico armazenado no servidor, o script também apaga esse arquivo.
  • 311.
    trabalhando com dadosarmazenados em arquivos Isole a maior pontuapão para ser removida Com o processo de remoção explicado, podemos agora concentrar nossa atenção no lado do banco de dados. O script Remover Pontuação é responsável por excluir um registro de pontuação, o que implica excluir uma linha do banco. Como você deve se lembrar, a instrução SQL DELETE FROM nos permite apagar linhas. Mas, para fazê-lo, precisamos primeiramente achar a linha. Isso é feito colocando-se uma cláusula WHERE na consulta que usa DELETE FROM. Por exemplo, esta consulta SQL apaga a linha cuja coluna name está definida como 'Ashton Simpson': DELETE FROM guitarwars WHERE name = 'Ashton Simpson' g u i t a r w a r s iHOWí n n w 1 2008-04-22 14:37:34 Paco Jastorius 127650 2 2008-04-2221:27:54 Nevil Johansson 98430 3 2008-04-23 09:06:35 Eddie Vanilli 345900 4 2008-04-23 09:12:53 Belita Chevy /282470 5 2008-04-23 09:13:34 C-Ashton Simpson ^ 4^— 'm . 368420 6 2008-04-23 14:09:50 Kenny Lavitz 64930 7 2008-04-2408:13:52 PhizLairston 186580 phizsscore.gif Esta Consulta apaga ImHas cuja coluna name ContenHa o texto ’Ashton Simpson. 0 nome da tabela é obvi^atário tom DéLéTB FROM, ^ para que a instruça« saiba de que tabela vote esta apagando dados. 0 home do usuário e o drrfcerio usado para se apajar a pontuação. Há, porém, um problema com esta consulta. Em um mundo de milhões de Guitar Warriors, existe a possibilidade de haver mais de um Ashton Simpson. Esta consulta não apaga somente uma linha, ela exclui todas as linhas que tenham o nome 'Ashton Simpson'. A consulta precisa de mais informações para apagar a linha certa: DELETE FROM guitarwars MIERE name = 1 Ashton Simpson ' Ao se esjcúiíidar a powtuaçaoJunto Com — o nome, a operação f íica muito mais predisa. g u i t a r w a r s iliül! ^ípmííitîîlíii^ll^^illlïil|iîíl|ïíí S l l l l i i i i i l l l screenshot 1 2008-04-22 14:37:34 Paco Jastorius 127650 2 2008-04-2221:27:54 Nevil Johansson 98430 3 2008-04-23 09:06:35 Eddie Vanilli 345900 4 2008-04-2309:12:53 Belita Chevy 282470 — 5 2008-04-23 09:13:34 ^Ashton Simpson 368420"““c 6 2008-04-23 14:09:50 Kenny Lavitz 7 2008-04-2408:13:52 Phiz Lairston 186580 phizsscore.gif 0 operador AND modiíica a ConsuIta, de modo que tanto o nome quânto â pontuação predisâm corresponder ao que sendo pedido. Agora que tanto o nome quanto a consulta precisam corresponder ao que está sendo pedido, a cbânce de se apagar acidentalmente » » » a is de uma iir.Ha diminui Consideravelmente- você está aqui ► 2 8 3
  • 312.
    colocando um LIMITno seu DELETE Controle oquanto você pode remover com UMIT Usar as colunas de nome e de pontuação como base para se excluir uma linha é bom... mas não o suficiente. O desenvolvimento de aplicações tem que se pautar pela m inim ização dos riscos a qualquer custo, e ainda há um pequeno riso de se apagar mais de uma linha que tenham o mesmo nome e a mesma pontuação. A solução é forçar a consulta a só apagar uma linha, não importa o que aconteça. A cláusula LIMIT faz isso acontecer: DELETE S f f i i ® í arwars name = 'Ashton Simpson' AND score = '■ 368420 'ÍSl*ÜSÉ (V, W • »W . a* Coloque um limite sobre o *W ro de linhas que podem sev- apagadas. O número após LIMIT diz ao MySQL o número máximo de linhas que podem ser apagadas - neste caso, uma. Assim, fica garantido que nunca apagaremos mais de uma linha com esta consulta. Mas e se houver dois Ashton Simpsons com a mesma pontuação? É claro que este é um cenário improvável, mas àsvezes vale a pena considerar cenários extremos ao se pensar no melhor projeto possível para uma aplicação. g u i t a r w a r s .d ilb líÉ IfllillJ É M ilillil name score @ S P P ÍI:| 1 2008-04-22 14:37:34 Paco Jastorius 127650 2 2008-04-22 21:27:54 Nevil Johansson 98430 3 2008-04-23 09:06:35 Eddie Vanilli 345900 4 2008-04-23 09:12:53 Belita Chevy 282470 ( 5 2008-04-23 09:13:34^ Ashton Simpson 368420 * v - l -2008-U4-23 14:09:50" Kenny Lavitz 64930 7 2008-04-24 08:13:52 Phiz Lairston 186580 phizsscore.gif 2008-11-04 10:03:21" "Ashton iimpson 368420 ashtonsscore.^ jpg _ Puas linhas Com e*atâmente o mesmo nome e a mesma fontuaçao apresentam um problema para a nossa Consulta DELETE. Escreva abaixo o que acontece com esta tabela quando a instrução DELETE acima é executada. Como você poderia certificar-se de que a pontuação correta seja apagada?
  • 313.
    trabalhando com dadosarmazenados em arquivos Faria alguma diferença usar a ID da pontuação na cláusula WHERE da consulta DELETE FROM? Isso poderia ajudar a garantir que estaremos apagando a pontuação certa, não? Sim, poderia! A ID da pontuação é a maneira perfeita de se isolar o registro para ser apagado. A unicidade é uma das principais vantagens de se criar chaves primárias para as suas tabelas. A coluna id da tabela guitarwars é a chave primária e, portanto, é única para cada pontuação. Usando essa coluna na cláusula WHERE da consulta DELETE FROM, nós eliminamos toda a dúvida sobre qual registro será excluído. Eis uma nova consulta, desta vez usando a coluna id para nos ajudar: DELETE FROM guitarwars WHERE Havendo a confiança de que a coluna id é de fato a chave primária, este código apagará de forma segura apenas uma linha. Mas e se não tiver sido você quem criou o banco de dados, e talvez a unicidade não tenha sido devidamente implementada. Nesse caso, uma cláusula LIMIT poderia ainda ser útil. O raciocínio é este: sempre que você quiser afetar apenas uma linha, deixe isso claro na consulta. DELETE FROM guitarwars WHERE id = Nunca é má ideia ser bastante explícito com o que você quer que seja feito em uma consulta, e neste caso, LIMIT adiciona uma medida adicional de segurança à consulta DELETE. O Apagar dados tom base cr* uma dhave prmatria ajuda a garantir precisão ao se isolar a linha dev-ta para ser e*dlwda- A dláusuh LIM IT diz. e^plid-itâmente ‘V** a donsulta nao pode apagar »ais de w^a linha• você está aqui ► 2 8 5
  • 314.
    o script removescore.phpquase pronto Im as de Geladeira PHP & M /S o L O script removescore.php está quase pronto, mas ainda faltam algumas partes importantes do código. Use os imas para preencher as lacunas no código e implementar no Guitar Wars a capacidade de eliminar pontuações indesejadas. <html xmlns="http://www.w3.org/1999/xhtml" xml:lang-’ 'en’ ' lang-"en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title>Guitar Wars - Remover uma Pontuag.ao</title> clink rel="stylesheet" type="text/css" href="style.css" /> </head> <body> <h2>Guitar Wars - Remove a High Score</h2> <?php ('appvars.php'); (’connectvars. php’); if (isset($_GET['id'3) && isset($_GET['date']) && isset($_GET[’name']) && isset{$ GET['score']) && isset($_G£T[ ............. 1)) i // Pega os dados em GET $id = $_GET['id’]; $date = $_GET['date']; $name = $_GET [' name1]; $score = $_GET['score']; = $ GET [ .....]; else if (isset($_POST['id']) &£ isset($_POST[’name']) isset($_POST[1score // Pega os dados em POST = $ POST[ ]; $name = $ POST[1name']; $score = $_POST['score']; $ sceenshot = $_POST ['screenshot']; } else { echo ' <p class="error">= Desculpe, nenhuma pontuaçao foi especij-icada para removida.</p>1; } if (isset($_POST['submit'])) { if ($_POST['confirm'] == ) { // Exclui o arquivo gráfico do servidor @unlink(GW_UPLOADPATH . $screenshot); // Conecte no banco de dados $dbc = mysqli_connect(DB_HOST, DB_USER, DB_PASSWORD,.DBJJAME);
  • 315.
    trabalhando com dadosarmazenados em arquivos // Exclui os dados da pontuação do banco $query = " guitarwars WHERE LIMIT mysqlí_query($dbc, Squery); mysqli_close($dbc) ; // Confirma êxito com o usuário echo '<p>'A pontuação de ' . ' para 1 . ' foi removida com sucesso.'; else echo '<p class="error">A pontuação nào foi removida.</p>'; else if (isset( ) && isset( ) && isset( ) & & isset($score) &5 isset($screenshot)) { echo 1cp>Temcerteza de que deseja apagar a pontuação abaixo?</p>' ; echo 1 <pXstrong>Nome: </strong>' . $name. '<br /><strong>Date: </strong>' . $date . ’<br /><strong>Pontuação: </strong>' . $score . [ c/p>'; echo 'cform method="post” action=,'removescore.php">'; echo 'cinput type="radio" name="confirm" value="Yes" /> Yes echo '<input type="radio" naine="confirm" value="No" checked="checksd"/> No <br/>' echo ’<input type="submit" value="Submit" name="submit" />'; echo ’ <input type="hidden" name= value="’ echo 'cinput type="hidden" name="name" value="1 . $name . /tr­ echo 'cinput type="hidden" name="score" value="' . $score . echo 'cinput type="hidden" naxae="name="screeshot"value="1.$ screeshot.'”/>; echo 'cp>ca href= ?> c/body> c/html> >Slt;6lt; Voltar para a página admin</aX/p> ' removescore.php v o c e e s tá aqui 2 8 7
  • 316.
    o script removescore.phpfinalizado Imas de Geladeira YHY e MySQL - Solução O script removescore.php está quase pronto, mas ainda faltam algumas partes importantes do código. Use os imas para preencher as lacunas no código e implementar no GuitarWars a capacidade de eliminar pontuações indesejadas. chtml xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title>Guitar Wars - Remover uma Pontuagao</title> dink rel="stylesheet" type="text/css" href="style.css" /> </head> <body> <h2>Guitar Wars - Remove a High Score</h2> <?php require_once fndlua os arquivos de script dompav-tilHados, mas use required_ende, uma vez. que elcs sao essendiais para a remodao das pontuadoes. iE‘ ’ Tis’ setT$"GErTt,rd’]) £& isset ($_GET [’date ’]) && isset($_GET['name11 ) && isset ($_GET [’score ’]) && isset($_GET[ ’screenshot’Hi)} { require__once : {'appvars-php'); h 'connectvars-php[); // Pega os dados em GET $id = $_GET['id']; $date = $_GET[’date']; $name = $_GET['name 1]; $score = $_GET['score’]; $screenshot |j|i= $_get I 0 sdript reaje diferentemente dowíorme a requîsidâo redebida seja fcjET ou POST- ^ // Pbcjb os dados 6 i f t POST else if Usse, ^ P O S n . ^ » « Í...US « isset <^POST r score „ < A diretiva PttP de supressão de erros, 0, impede que erros sejâm relatados, faz. sentido usar essa opÇdo dom unlinkO, uma vez. que poderemos estar tentando exdluir um arquivo que nao existe- Messe daso, nao queremos que o usuirio redeba uma mensagem de erro. $name = $_POST ['name 'D $score = $_POST[1score 1 $screenshot=$_POST[1screenslyít1] else { L“ ‘ .< c l^ r r o ^ 4 ^ — £OÍ eSPeClflCada P“ a echo '<P class- eriuj. y rem ovito</p> J « « f o it } usado para se remover quaisquer pontuações, ^ de modo que o arquivo i l | (S_POST [ ' c o n f ir m ' ] - e M l3 Ío ser excluído tombent. if (i/set($_POST[’submit'1) 7/ Exclui o arquivo gráfico do servidor^ @uniink(GW_UPLOADPATH . $screenshot>; " COT * = a= b^°sqli! d=onL=t,DB__HOST, DENSER, ;
  • 317.
    trabalhando com dadosarmazenados em arquivos // Exclui os dados da pontuação do banco $query = " gguitarwars WHERE jLIMIT mysqli_query($dbc, $query); mysqli_close($dbc); // Confirma êxito com o usuário echo '<p>T'A pontuação de ’ . ' para ’ foi removida com sucesso.1' else echo '<p class="error">A pontuação não foi removida.</p>' ; else if (isset isset ( ) && isset { ') & £ isset($score) && isset($screenshot)) { echo ' <p>Tem certeza de que deseja apagar a pontuação abaixo?</p>' ; echo '<p><strong>Nome: </strong>' . Çname . '<br /><strong>Date: </strong>' ’<br /><strong>Pontuação: </strong>' . $score . ' < / p > ' ; echo '<form method="post" action="removescore.php">' ; echo '<input type="radio" namè="confirm" value="Yes" /> Yes echo '<input type="radio" name=’ , confirm" vElue="No" checked="checked"/>No <br />’ echo ’<input type="submit" value="Submit" nc®e=r ' submit" />'; echo '<input type="hidden" name= |vaiípe=" " />’; echo '<input type="hidden" name="name’ ' value="'V $name . echo 'cinput type—"hidden" name="score" value="' Çscore . />’; echo ’cinput type="hidden" name="screenshot" value%^' . $screenshot . />1 echo '</form>'; echo '<p><a href= ;&lt; Voltar para a página admin</ax, p>' ; </body> </html> rert.ovescore.php pagma Mrn*} para mclKor ft tówfos esCo*did<* SBLF3 0 Wmulári, »avegacao. ,^7 ~ J F<*>e «só incluiria . r- ■ ^ «a* usaA* quaisquer dados que tenha» de Con-hrmâÇao alguns ímãs- do -formulário são usados para se armazenarem os dados da pontuaçao, para que eles sejam enviados Como parte da requisiçãoPOST. sido enviados através da URL, que****« ^ ti+ ic a r de que nenW, dado seja enviadoju^tocom este TGTwiujári©“ aPenAfi D/u t apehâs dados P (O T você está aqui ► so e exibido se todas estas variáveis estiverem definidas. 2 8 9
  • 318.
    o test drivefinal do aplicativo guitar wars T fe S T O r iv ë Adicione os scripts de Remover Pontuação e Admin ao Guitar Wars, para que seja possível excluir pontuações. Crie dois novos arquivos de texto, removes core .php e admin.php, e insira neles o código que acabamos de completar. Envie os novos scripts para o seu servidor, e depois abra o script Admin no seu navegador. Clique no link "Remove" de uma pontuação que você queira excluir, e depois confirme a remoção na página Remover Pontuação. Volte à página Admin para se certificar de que o registro foi apagado, e depois vá para a página principal do Guitar Wars (Index.php), para ver lá o efeito da modificação. A nova página Remover Pontuaçao fiuida de d-on-firmâr e -fazer a remoção das pontuações mdesejadas. Tt pájma pv-intipal do éjuitar Wars a^ora só mostra pontuações tomprovadas. st A nova pá^na Ad -fornede links para se removerem pontuações nao vevi-fitadas- £ste e o pequeno Jatob, Quitar VVarrior prodfyo Os ^uitav- Warriors legítimos esta© -felizes, ajora <^ueso Há pontuaçSes domprovadas. As pontuações hao vcriíi&adasj ou seja* aquelas sem imagens £.omprobató*r'sas, -foram removidas do sistema-
  • 319.
    trabalhando com dadosarmazenados em arquivos Palavras Cruzadas PHP & M /S Q L Cansado de enviar arquivos gráficos? Que tal então enviar um pouco de conhecimento para um monte de quadrinhos? Horizontais I. 0 atributo type da tag <input> deve ser definido como isto, para que um campo do formulário aceite upload de arquivos. 4. Geralmente éuma boaideia armazenar as imagens enviadas àaplicação emuma pasta.... 8. Esta instrução SQLé usadaparase modificara estrutura de umatabela. 10. Esta instrução SQLé usadapara secolocaros resultados de umaconsulta emumadeterminada ordem. II. Informações sobreos arquivos enviadossão armazenadas navariável superglobal $.... 12. Estainstrução PHPé usada parase inserir código de outro script. 13. Éum aboaideiafazeristocomumarquivorecém -enviado. Verticais 2. Para impedir que uma instruçãoDELETEFROM apague maisde uma linha, useesta instrução. 3. Quando umarquivoéenviado através de umformulário, eleécolocadoem umapasta... no servidor. 5. Aoalterar umatabela, este comando SQLcuida de adicionar uma novacoluna. 6. Estainstrução PHPé usadapara se criar uma constante. 7. Os arquivos includesão bastante úteis parase... dados entre váriosscripts. 9. Esta instrução SQLé usada como parte de outra instrução para ordenar resultados de consultas em ordem descendente. você está aqui > 2 9 1
  • 320.
    palavras cruzadas phpe mysql - solução TalaVras Cruzadas PíTP & MySQL Solução
  • 321.
    trabalhando com dadosarmazenados em arquivos Sua Caixa de Ferramentas PHP£- MySQl Fique à vontade para fazer uma m K F reverência virtual. Você não só ó adorado pelos guitarristas virtuais do mundo todo, como também adquiriu novas habilidades em PHP e MySQL: alterar a estrutura de tabelas, lidar com uploads de arquivos, controlar a ordem de dados e remover dados. você está aqui > 293 CAFITOIO 5
  • 323.
    7«tn an c[oa Sua Aplfcaçã° Segura * Presuma que Estão Todos Querendo TePegar ^ f r Seus pais estavam certos: não fale com estranhos. Ou pelo menos não confie neles. Na pior das situações, não dê a eles as chaves para acessar os dados da sua aplicação, presumindo que eles não vão fazer nada de errado. Vivemos num mundo cruel, e você não pode partir do princípio que todos são confiáveis. Na verdade, como desenvolvedor de aplicações web você precisa ser metade incrédulo e metade adepto de teorias de conspiração. Sim, as pessoas em geral são más e elas definitivamente querem te pegar! OK, talvez isso seja um pouco de exagero, mas é muito importante levar a segurança a sério e elaborar as suas aplicações de forma que elas fiquem protegidas contra qualquer um que pretenda causar danos. este é um novo capítulo ► 295
  • 324.
    guitar wars estásendo hackeado 0 dia em quea música morreu Parece que os quinze minutos de fama do nosso roqueiro-virtual-prodígio se acabaram: a pontuação deJacob no Guitar Wars sumiu,junto com todas as outras. Pareee que há alguma força do mal em ação, bagunçando o aplicaüvo e impedindo os Guitar Warriors de terem os seus placares publicados. Guitamstas virtuais insatisfeitos são usuários insatisfeitos, e a consequência última disso é um desenvolvedor de aplicações insatisfeito... você! 0 re tw d is h do Quitar Wars, Jaíob, está ■furioso por a suâ pontuâdao "ter sumido da lista. 0 armamento musita! pre-ferido de Jafcob, uma Eradicasíer saíra 2-005
  • 325.
    segurança para asua aplicação Para ondeforam as pontuapões? Nós sabemos que a página principal do Guitar Wars está vazia, mas será que isso significa que o banco de dados também está vazio? Uma consulta. SELECT pode responder essa questão: A tonsuita SÊU&CT revela < ^u e a -tabela ^ui-tavwa« esta tompíe-tamen-te vazia— todas as pcm-tuatoes se Çerèd 4- ^ De algum modo, todas as linhas de dados foram apagadas do banco Guitar Wars. Seria possível que alguém talvez esteja usando o nosso script Remover Pontuação para o mal? Nós temos de proteger as pontuações! i- %Aponte seu lápis Faça um círculo em torno das técnicas, dentre as apresentadas a seguir, que você poderia usar para proteger as pontuações do Guitar Wars contra hackers, e escreva em baixo o porquê. Proteger com senha a página Admin, de modo que somente quem souber a senha (você!) possa remover pontuações. Criar um sistema de registro dos usuários, e só conceder a alguns (de preferência só a você!) os privilégios administrativos. Verificar o endereço IP do computador que está tentando acessar a página Admin, e só permitir alguns endereços (de preferência apenas o seu próprio!). Eliminar totalmente o recurso de remover pontuações. você está aqui ► 297
  • 326.
    protegendo as pontuaçõesdo guitar wars’ ponte seu lápis Solupão Faça um círculo em torno das técnicas, dentre as apresentadas a seguir, que você poderia usar para proteger as pontuações do Guitar Wars contra hackers, e escreva em baixo o porquê. Proteger com senha a página Admin, de modo que somente quem souber a senha (você!) possa remover pontuações. .Proteger Çcm.senha.a.página,Admin;e uma . bod .e.yâpjdâi porque na© ç muit©... complicada e -for^ete ao site umaseguy-an^a |razjoáyel ^apiçtemente- Todas as tefcnicas foram circuladas, porque W as elas são Capa**s de resolver o problema, embora al^uwâs seja» «ais viáves <ue ouíras. Criar um sistema de registro dos usuários/^ e só conceder a alguns (de preferência só a você!) os privilégios administrativos. Um sistema de registro dos usuários, Com privilégios administrativos limitados, e uma otima solu^ao, mas envolve bastante planejamento e programarão... o Quitar tVars.precisa.de segurança, a^ora/(............. Verificar o endereço IP do computador que está tentando acessar a página Admin, e só permitir alguns endereços (de preferência apenas o seu próprio!). Veri-fitar © {P funCiona, mas.torna, o site dependente do endereço |P do seu Êoi^putador, o <ual poderá se modificar. Remover o recurso cevtamente resolve este problema específico, mas lembre-se: o reCurs© foi adicionado originalmente, no Capítulo anterior, pdv~a tornâr a manutenção do site mais fácil.
  • 327.
    segurança para asua aplicação Seguranpa contra os bárbaros Uma maneira simples e direta de se garantir rapidamente a segurança do Guitar Wars é usar autenticação HTTP para proteger com senha a página Admin. Na prática, será pedido um nome e uma senha, mas a ideia teórica é exigir do administrador uma determinada informação secreta antes de permitir que ele tenha acesso a recursos restritos da aplicação, como por exemplo, os links para remoção de pontuações. Quando uma página é protegida usando-se autenticação HTTP, aparece umajanela pop-up pedindo o nome do usuário e a senha, para que seja concedido o acesso à página protegida. No caso do Guitar Wars, você pode limitar o acesso à página Admin a qualquer número de pessoas que quiser, possivelmente até a apenas você! A autenticação HTTP oíetece uma forma slniples de se fazer a segurança de uma página tju & useri ir. Aja*e!a de autentiíadão ^TTP agorâ se ihterpoe entre os usuários « 3 página Admi». m As fwituaçSes do hante de dados agora estao protegidas, u*a vez. ^ue o âtesso à págihj Adrift restringido. guitarw ars um iffllilillfSffi IPffü ilü ü iwwmm® 14 2008-05-01 20:35:07 ßelita Chevy 232470 beüta&scûre.gïf 15 2008-05-01 20:36:45 Jacob Storihersöft 339740 jasiobsscort.gtf 1& 2008-05-01 20:37:02 Nevil Johansson 93430 nevilsscore çîf 17 2003-05*01 20:37:23 PacoJartorius 127650 pâiossCûre.gif Iß 2008-05*01 20l 37;40 Phiz Lairston 166380 phizsscore.gif 19 2008-05*01 20:38:00 Kenny Lavitt 64930 kennysscore.gtf 20 2003-05-01 20;îS:23 Jean Paul Jon« 2-4336Û jeanpôu?55cor«.gÍí Os links M Rewove da página Admin agora só estao disponíveis para o administrador do Quitar liVars. você está aqui ► 2 9 9
  • 328.
    usando autenticaçao HTTP Protegendoa página (ruitar W ars Admin A autenticação HTTP funciona assim: quando um usuário tenta acessar uma página protegida, como a nossa página Admin, eles recebem uma janela que lhes pede um nome de usuário e uma senha. 0 *ave$ador web us< 3um3jánelâ tomo esta para re<^uisi£ar um nome e senha, antes de permitir o âéesso a umô Paaina Toviewthispage,you.needtoSogmtoarea . > J "GuitarWars"onwwfw.giisarwars.ret pvotegîda. Your password wil! fcc sent in Oie t'W - Name: ; Password; Para manter as doisas simples, a senKa nao e iriptogra-Pada. r? Rem em berthispasswordinm yH eycbain (■ Carccet £sta variável superjlobal do PHP armazena o nome do usuário digitado na janela de autenticarão. I $ SERVER['PH P AUTH USER’ ] $ SERVER['PHP AUTH PW'] r £sfca variável armazena a senha diÿtada «a janela de autentitaçao- O PHP entra em cena através do seu acesso ao nome e à senha digitados pelo usuário. Eles ficam armazenados na superglobal $_SERVER, que é semelhante a outras superglobais que vocêjá usou ($_POST, $_FILES, etc.). Um script PHP pode analisar o nome e a senha digitados pelo usuário e decidir se ele deve receber acesso à página protegida. Digamos que só vamos permitir acesso se o nome do usuário for “rock”e a senha for “roll”. Eis aqui o modo como o acesso à página Admin é concedido: A páçynâ Admin so í aiessível st tiverem sido diÿtados o nome t a senha dorreW /y s 5_SERVER[.pHp_Â0TH $ SERVER[ ' PHP__AUTH_USER' ] l_PW <]
  • 329.
    segurança para asua aplicação nã9 existem Ferguntas idíptas "P -A autenticação HTTP é realmente segura? Sime não. Depende do que você está tentando conseguir coma segurança. Nada é 100%seguro, portanto nós estamos sempre falando de níveis de segurança. Para se protegerem pontuações no Guitar Wars, aautenticação HTTP fornece umnível razoável de segurança. Você poderia adicionar criptografia à senha para ter umnível ainda maior. Porém, mesmo isso provavelmente não seria suficiente em uma aplicação que envolvesse dados mais sensíveis, como por exemplo, dados financeiros. • O que acontece se o nome e a senha forem digitados incorretamente? K * Onavegador emite umpequeno choque elétrico através do mouse. Brincadeira, nãoacontece nada tão dramático assim. Emgeral, é exibida uma mensagem para avisar o usuário de que ele está tentando acessar uma página segura, a qual aparentemente não é da conta deie. Emúltima instância, évocê quemescolhe oque essa mensagem deverá dizer. "P • A autenticação HTTP requer tanto o nome do usuário quanto a senha? E se eu só quiser usar a senha? Nãoé obrigatório usar ambos. Se você quiser usar apenas uma senha, basta verificar só avariável global $_SERVER['PHP_AUTH_PW’]. Falaremos mais sobre como essa variável é verificada, em instantes..,. T * • Como exatamente você protege uma página com autenticação HTTP? Chamando-se uma função PHP? Exato. Aautenticação HTTPenvolve o estabelecimento de uma linha de comunicação entre o navegador e o servidor, através de cabeçalhos HTTP. Você pode pensar no cabeçalho como sendo uma pequena conversa entre o navegador e o servidor. Ambos usamos cabeçalhosfrequentemente para se comunicarem fora do contexto do PHP, mas o PHP lhe permite enviar umcabeçalho, que é o modo como a autenticação HTTPfunciona. Estamos prestes aaprender muito mais sobre os cabeçalhos eo seu papei na autenticação HTTP com PHP. Quando é que a autenticação da página deve realmente ocorrer? você está aqui ► 3 0 1
  • 330.
    autenticação a cabeçalhos Aautenticação HTTP exige cabeçalhos A ideia por trás da autenticação HTTP é que o servidor esconda uma página protegida, e instrua o navegador a pedir um nome e senha ao usuário. Se o usuário os digitar corretamente, o navegador vai em frente e fornece a página. O diálogo entre navegador e servidor se realiza através dos cabeçalhos, que são pequenas mensagens de texto com instruções específicas sobre o que está sendo pedido ou entregue. Os cabeçalhos na verdade são usados sempre que você visita uma página web, e não apenas quando a autenticação é requerida. Eis o modo como uma página normal, não protegida, é enviada pelo servidor para o navegador com a ajuda dos cabeçalhos: Teclei p á g in a Veb é entvegue co m a a ju d a <fes cakeçalfcps. Servidor web O navegador requisita uma página do servidor, enviando alguns cabeçalhos para identificar o arquivo sendo pedido e nome de host do servidor. Este Cohjuhte de tabeçalHos a U»a jrg^uisj£Ao de fdgina vieb- O servidor responde com um conjunto de cabeçalhos, seguidos da página requisitada. Este ÿrupo de cabeçalhos forma w*â v-esposfa de fâgma web índex.php O navegador recebe os cabeçalhos e a página, e gera o código HTML da página. Jv/ô f im das dojvbas, os eabeçalhos ajuda» a eniv-egar to» sutesso ao «avegador a fâg'ma fedida-
  • 331.
    segurança para asua apficação A n e m ia de um Cakeçqlfeo --------- ------------------------------------------------------------------- Oscabeçalhos controlam precisamente como e que tipo de informação é enviada do navegador para o servidorweb, evice-versa. O cabeçalho frequentemente consiste de um par de nomes/valor que identificauma determinada informação, como por exemplo, o tipo de conteúdo da página (HTML).Um determinado grupo de cabeçalhos é enviado ao servidor como parte de uma requisição web, e depois outro grupo é retornado ao navegador como parte da resposta. Vamosdar uma olhadacom mais detalhes nestes grupos de cabeçalhos, para descobrir exatamente oque é enviado, àmedida que o cliente e o servidor comunicam-se um com o outro. A maioria dos dabeòalhos donsiste — de Um par át tiOtnts/ valor separado por dois pontos. £ste dabeçalbo espeii-fída o navegador <ue esti -fazendo a re®uisidâo- ■i£- _GET / in d e x , p h p H T T P /1 , H o s t : www. gui : ;a r w a r s . ne). . i ^.t.lQD^ciose - U -ser- A g e n t -M c z illa /5 7 Ò T ? > v " ^ c c ê p c - L n a r s e t : ISD =S SS«7 » Í...' C a c h e - C Q n tr o l: n o ■ ■ : A c c e p t- L a n g u a g e : d e , e r.; q=Q . 7. 0 primeiro £abetalho nao t um par de nomes/valor - e a requisição 6 ß T da pagina. 0 primeiro dabeçalbo a resposta ttTTP do servidor- „» „■ 1 1 : 2 2 :0 9 GMT Server; Apache/2 .0.54 X-Powered-By: PHP/5 .2 . ■.n^far^Enroiii Content-Type: text/html 0 tonteudo HTML- àd pagina e enviado logo após os tabeçalKos •ndex.php Este dabefalh© diz. ao navegador que o donteudo e dódigo HTML, em vez. de, por e*emp!o, te*to simples. Os cabeçalhos nos são importantes, no que diz respeito ao Guitar Wars, porque eles fornecem o mecanismo que interrompe a entrega de uma página do servidor, requerendo que o usuário digite um nome e uma senha para liberar a página. Em outras palavras, ê preciso trabalhar nos cabeçalhos retornados pelo servidor para proteger uma página com autenticação HTTP. você está aqui ► 303
  • 332.
    entrevista com ocabeçalho TudoSobreoCabeçalho Na entrevista desta semana: por que tanto falatório? Use a Cabeça!: Você parece estar recebendo bastante atenção no que diz respeito a autenticar páginas web. Isso sejustifica ou você está apenas tendo os seus quinze minutos de fama virtual? Cabeçalho: Não, isso sejustifica sim. Você está se esquecendo de que eu tenho um papel vital na entrega de qualquer página web existente. Assim, acho que posso dizer que a web nem sequer funcionaria se eu não estivesse em cena. Eu vou durar muito mais do que quinze minutos, mesmo que as pessoas não apreciem o meu trabalho. Use a Cabeça!: Então qual é exatamente esse papel que você desempenha? Cabeçalho: Você tem que entender que navegadores e servidores web não são pessoas, portanto eles não podem simplesmente ligar um para o outro ou enviar uma mensagem de texto. Use a Cabeça!: SÉRIO?! Cabeçalho: Sim, eu sei que é um choque, mas as máquinas simplesmente não se comunicam do mesmo jeito que as pessoas. Mas os navegadores e os servidores ainda precisam falar uns com os outros, e eles o fazem através de mim. Use a Cabeça!: E como isso acontece? Cabeçalho: Quando alguém digita uma URL ou clica em um link de uma página, o navegador cria uma requisição GET e a envia ao servidor. Essa requisição é empacotada em uma série de cabeçalhos, cada um dos quais contendo informações sobre a requisição. Eles contêm informações como o nome e o host da página sendo pedida; o tipo de navegador que está fazendo o pedido, etc. Use a Cabeça!: Não consigo ver o que há de tão importante nisso. Cabeçalho: Bem, quando você vai a um café, você acha importante dizer ao atendente que quer um cappuccino grande sem creme? Use a Cabeça!: Claro que sim, o atendente precisa saber o que é que eu quero. Cabeçalho: É a mesma coisa, aqui. O navegador diz ao servidor o que ele quer, empacotando a requisição e enviando-a em cabeçalhos. Use a Cabeça!: Interessante. Mas ouvi dizer que os servidores também são capazes de enviar cabeçalhos. Eu pensava que os servidores só enviassem páginas web. Cabeçalho: Ah, boa pergunta. A minha importância no outro lado da comunicação é a mesma, porque o servidor precisa fazer mais do que apenas jogar um monte de conteúdo em cima do navegador. O navegador poderia não ter a menor ideia do que fazer com esse conteúdo, se não lhe fosse passadas mais algumas informações. Use a Cabeça!: Como por exemplo...? Cabeçalho: O tipo do conteúdo seria um exemplo. Essa é provavelmente a informação mais importante, mas o servidor envia também outras coisas, como o tamanho do conteúdo, a data e a hora da entrega, e assim por diante. Use a Cabeça!: Quando é que a página propriamente dita é enviada? Cabeçalho: O conteúdo, seja ele código HTML, dados PDF ou dados de imagens como um GIF ou JPEG, segue logo depois que o servidor me envia ao navegador. Use a Cabeça!: OK; estou começando a entender como você funciona em relação às páginas normais. Mas e quanto a esse negócio de autenticação? Cabeçalho: Eu desempenho o mesmo papel em uma página autenticada que nas páginas normais, exceto pelo fato de que eu também cuido de informar ao navegador que página precisa ser autenticada. Dessa forma, o navegador poderá pedir ao usuário as informações de autenticação. Use a Cabeça!: Ou seja, um nome de usuário e uma senha? Cabeçalho: Exatamente. E depois, fica a cargo do código PHP no servidor decidir se o nome e a senha são válidos, em cujo caso o servidor pode enviar o restante da página. Use a Cabeça!: Fascinante. Obrigado pelos esclarecimentos. Cabeçalho: Sem problemas. Isso faz parte do meu trabalho.
  • 333.
    segurança para asua aplicação Controle os cabeçalhos com PHP Com o PHP, você pode controlar cuidadosamente os cabeçalhos enviados pelo servidor ao navegador, abrindo a possibilidade de realizar tarefas como a autenticação HTTP. A função interna header() é usada para se enviar um cabeçalho, do servidor para o navegador, de dentro de um script PHP. |{1Content-Type: text/html'); A função header() envia imediatamente o cabeçalho, e deve ser chamada antes de qualquer conteúdo propriamente dito ser enviado ao navegador. Esse é um requerimento bastante estrito - se mesmo um único caracter ou espaço for enviado antes do cabeçalho, o navegador o rejeitará com um erro. Por esse motivo, as chamadas à função header() devem preceder qualquer código HTML dentro de um script PHP; Mesmo um espaÇo «*e viesse antes da tag "v. <?php tausaria um V erro «este sdript de <?php e*<»y*plo- A íunçãp h e a d e rO llie petmfte Gtlat e enViar um cctkeçalfeç» a partír <le um script?HP- 0 servidor envia este fiôbeçaiho ao «avegador para ser frodessado, antes de tentar enviar «^uai^uer parte do Conteúdo ffTM L da página- 0 s espaços dentro das tags <?php ?> não e problema, porque eles não são repassados para o navegador. ?> Chtml xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" > </html> você está aqui ►
  • 334.
    como a autenticaçãode cabeçaiho funciona? Autenticando com cabeçalhos Para se autenticar a página Admin do Guitar Wars mediante cabeçalhos, é preciso criar um conjunto bastante específico deles - dois, na verdade — , que façam o navegador saber que deve pedir um nome e uma senha ao usuário antes de entregar a página. Esses dois cabeçalhos são gerados através de código PHP no script Admin, e controlam a entrega da página para o navegador. Servidor web O s. dabeçalHos de autentüação HTTP são enviados do servidor para o have^ador. Navegador web do cliente Sãç>necess&iPs ck>is cabeçaljiog e s p e c í f ic o ^ p a r a se Ve^jUeVeVa autenticação de uma página Web, . í’ 5 5 1' U n a ú t h Ô - r i â i ê â ' ^ ^ Á ü f c f t é n t i G â f c Q : -;Wi/ ; Êa^ic rpalm^Guitar;;»: 0 «ave^ador, eniao, pede <ue o usuário digrte um home t umd senha- Antes de enviar o ton-teído da p%*» admm-pbp para o navegador» o servidor protessa <uais<uer eabetalKos da pa<ynâ To view tn«s page, you n e td to log in to area “G uitar Wars" on www.9 uitajwars.net Your password will be sent in the cfcar. .ftfettae; . ,.;rock ; Password: j « ••• 0 'tentsmber this password in rt«y ioychain Os dois cabeçalhos necessários para se iniciar a autenticação fazem duas coisas bastante específicas: £ste dabeçalho in-Porma ao navejador ^ue pagina. lo a ver a Este tabeçalHo pede ao navegador para tentar âutentitar o usuário, pedindo~lKe um nome e uma senKâ- WWW-Authenticate : Basic realms"Guitar Wars 0 basid realm” (domínio basidos) e apegas uma expressão usada para ►dentsíidar individualmente esta autentidaçao em partidular - ela aparede «ajanela de autentidadão.
  • 335.
    segurança para asua aplicação Após processar os cabeçalhos, o navegador espera a resposta do usuário, através dajanela de autenticação. O navegador responde com ações completamente diferentes, dependendo do que o usuário fizer... Gaitar Wars -HighScoresAdministration Below isalisto£allGuitarWarshighscores.Usethispagetoremovescoresasneeded. JacobScorchmon2008-05-0120:36:45 389740Remove BdltaChevy Jean Paul Jones PbizLajrstoo Paco Jasiorius NevilJohansson KenayLavitz 0 to M id o HTML- da pag>»a Admin t CntreguC depois «U€ SC digitâ um nomC Cum3 se*Ha Corretos. 2GG8-OS-OÍ 2056:07 282470 Rgmrrw 2008-05-01 20:38:23 243260 Remava 20)8-05-01 20:37:40 1865SOReraove 2008-05-01 20:37:23 127650 Remove 2008-05-01.20:37:02 98430 Remove 2008-05-0120:3S:00 64930 admin,php Se o nome ea senHa do usuario -fore» subtmctidos e -fWem inCometos, aja^ela de autewticac^o ape»>3s aporeCe para usuário Toviewthispa*, your*môtotegin» area “Guitar Wars“on *M*.guitarwars.,net ; Your passwordwlft 6 »*« * m.thedeir. Name:' :: . . ................ Password: n Remember This password in my keychair? £C a n c e l^ A aplicacao tem a oportunidade de -finalizar o script e e*bir ur*>a message»* de erro personalizada? caso o usuário tainCele o proCesso de auterttiCâÇâo- Se o usuário digitar um nome e senha corretos, e clicar em Log In, o servidor envia o conteúdo HTML da página admin.php para o navegador. Este exibe a página Admin, e o usuário poderá então remover pontuações, da mesma forma como na versão não protegida anterior. Se o usuário digitou um nome e senha incorretos, e clicar em Login In, o servidor diz para o navegador pedir ao usuário de novo o login. O navegador continuará este processo enquanto o usuário tentar combinações incorretas de nome e senha. Em outras palavras, se eles não souberem o nome e a senha, o único jeito de sair é clicar em CANCELAR. Se o usuário clicar em CANCELAR para sair da autenticação, o servidor envia para o, navegador uma página com uma mensagem de acesso negado e nada mais — a página admin.php não foi enviada. A mensagem de acesso negado é controlada pelo código PHP no script admin.php que está associado com os cabeçalhos. Este código chama a função PHP exit() para mostrar a mensagem e imediatamente sair do script: exit('<h2>Guitar Wars</h2>Sorry, you must enter a valid ' 'user name and password to access this page.'); você está aqui > 3 0 7
  • 336.
    imas de GeladeiraPHF No script Admin do Guitar Wars, estão faltando diversos pedaços importantes do código PHP que fornece a autenticação HTTP. Use os imas para completar o código abaixo, e use cabeçalhos para tornar a página segura. Dica: alguns imas poderão ser usados mais de uma vez. finalizando o código de autenticação <?php / Nome do usuário e senha para autenticação = 'rock'; .............. = 'roll'; if ( !isset { ....................................... ) I1 !isset ( .................................... ) iI ($_SERVER[' PHP_AUTH__USER'] !=....... ) I I ($J3EKVER [’ PHP_AUTH_PW'] !=......... ) ) { // Nome do usuário/senha incorretos, então enviar os cabeçalhos de autenticação ........ ('HTTP/l.1 401 Unauthorized'); ........ ('WWW-Authenticate: Basic realm= .............. ' ) ; ....... ( '<h2>Guitar Wars</h2>Desculpe, v o c ê deve digitar um’. 'válida para acessar esta página.' ) ; } ?> <html xmlns="http://www.w3 .org/1999/xhtml" xml:lang="en" lang="en"> </html>
  • 337.
    segurança para asua aplicação Será que é possível enviar outros tipos de cabeçalhos usando-se PHP? Sim , é possível... o s c a b e ç a lh o s n ão se rve m a p e n a s p ara se g u ra n ç a . Embora a autenticação seja o principal caso em que os cabeçalhos se fazem necessários, eles são bastante flexíveis e são capazes de fazer outras coisas interessantes. Basta chamar a função header() com o par de nome/valor apropriado, desta forma: 0 navegador é <?php ^ redirecionado à abouipKp, h e a d e r(ItttaitWSHIláillílHlS após receber ?> este Cabeçalho- Neste caso, temos um cabeçalho de localização, o qual redireciona da página atual para outra, chamada aboutphp, no mesmo site do Guitar Wars. Aqui, nós usamos um cabeçalho semelhante para redirecionar para a página aboutphp depois de cinco segundos: 0 navegador è redirecionado para a pagina About depois de 5 segundos. ?> Ve^laem! O s c a b e ça lh o s p recisam se r a prim eira c o isa enviada ao navegador, em um arquivo PHP. echo T Em 5 segundos, você será levado para a página About.’; E neste caso, nós temos um cabeçalho de recarregamento, uma vez que ele recarrega a página após ter-se passado um determinado período de tempo. Você frequentemente vê a URL nesse tipo de cabeçalho referenciar a página atual, para que ela se recarregue periodicamente. Um último caso é o chamado cabeçalho de tipo de conteúdo, porque ele controla o tipo do conteúdo sendo entregue pelo servidor. Como exemplo,você pode forçar uma página a ser exibidacomo texto puro, em vezde HTML, usando o seguinte cabeçalho ao chamar a função header(): Devido ao fato de os cabeçalhos serem enviados antes de qualquer conteúdo, é extremamente importante não permitir que um espaço sequer apareça fora do código PHP, antes de ser chamada a função headerQ no script PHP. <1php header{ * 0 Conteúdo é entregue ( „PI 3o navegador Como 11] ; texto simples. echo 'Este <strong>texto</strong> na verdade não aparecerá em negrito.'; ?> Neste exemplo, o texto enviado ao navegador é exibido exatamente como mostrado, sem nenhuma formatação especial. Em outras palavras, o servidor está dizendo ao navegador para não exibir o conteúdo como HTML, e portanto, as tags HTML são exibidas literalmente, como texto. você está aqui ► 309
  • 338.
    o código deautenticação completo íütas de Geladeira PHP - Solupão No script Admin do Guitar Wars, estão faltando diversos pedaços importantes do código PHPque fornece aautenticação HTTP. Use os imas para completar o código abaixo, e use 0 para tornar a página Admin segura. Dica: alguns imas poderão ser usados mais de uma vez. <?php // Nome do usuário e senha para autenticaçao j (.—— ^ O^nome do usuário c d senha ião • â 3 dos e*nVâriâveis, 5= 1roll '; h° m'&l° do seript- $ M^global f^ B R V B K d á êtesso do fcon*e t à senha digitados pelo uswivio nà janela de âutentida^ao. !isset (I £ |_SERVER 1'ERVER[’PHP_AUTH_PW ’] $password Éf ^ ll rio/senha incorretos, então enviar os cabeçalhos de autenticaçao | (’HTTP/1.1 401 Unauthorized'); í'WWW-Authenticate: Basic realm= I "Guitar Wars Wars</h2>Desculpe, você deve digitar um" . dos para acesar esta página.' ); $ duas thârsâdas 3 íunçao A -função exítO exibe uma mensagem headerO resulta** e» estes de erro e devtiíida— se de nada mais tabeçalhos sevem enviados ao se*- enviado ao navegador, no evento navegador- de uma £alha de awtentídaçao. <html xmlns="http://www.w3 .org/1999/xhtml" xml:lang="en" lang- en > 'usuário e senha } ?> 0 nome e â senha digitados pelo usuário sa©veri-fidados aqui. entregue ao navegador até que os cabeçalhos tenham sido enviados t prodessados. admin.php ™ ::.; 401 Authorised WWii-Autnentieats: Basic. realm="Guitar Wars'
  • 339.
    segurança para asua aplicação T fe S T O R fv e Adicione autorização HTTP ao script Admin. Modifique o script admin.php de modo que ele passe a usar autenticação HTTP, para que só você tenha acesso a ele. Envie o script para o seu servidor, e depois abra-o no seu navegador. Experimente digitar um nome e senha errados primeiro, para ver como o acesso é restringido. r Bt9aCHt*V ------ - tofeLi**» axiwJwiMíJftiowwssfl*» H**9l * a M WGfcS ta jU v to SDO M W H30;3Sá»^3C E áS S tfS Uiw nome de usuário e wm â sertKâ a$orâ impedem o atesso ^ I j ' ’ ™ nao autorizado á fá^md Admi*. . . * ) Pohtuaçoes nâo podem scr removidas semauWisaçao Score: 3897« u i ta Q u ita r $ Os furtar Wàrriors es-bao íeli2 Les por a ãfiitação a^ora estar se^uraf nap existem Perguntas Idiotas Quando exatamente a função exit() échamada no script Admin do Guitar Wars? K:I Embora afunção exit() apareça no código PHP logo abaixo das duas chamadas a headerQ, ela só é chamada se o usuário sair dajanela de autenticação, clicando no botão Cancel. Se a autenticação falhar, o servidor não continua a execução para alémdas duas chamadas a header(}. Emvez disso, ele re-envia os cabeçalhos etenta novamente. Somente se o usuário clicar emCancel éque o servidor chega àfunção exit(), emcujo caso ele envia o conteúdo da chamada àfunção, e nada mais. Se a autenticação tiver sucesso, exit{) nãoé chamada, porque o script nunca chega à parte de dentro da declaração if- ocódigo dentro de if só é executado se nãoexistirem umnome e senha definidos, ou se eles tiverem sido digitados incorretamente. O de uma autenticação HTTP tem algum propósito real? 1^1 Sim, ele define umazona de segurança que é protegida por umdeterminado nome de usuário e senha. Uma vez que o nome e senha tenham sido digitados corretamente, em umdeterminado realm, o navegador irá se lembrar deles, e não continuará a exibir ajanela de autenticação para cabeçalhos subsequentes no mesmo realm. Emouíras palavras, os realms permitem que o navegador se lembre que vocêjá atendeu aos requerimentos desegurança para umdeterminado conjunto de páginas - basta especificar o mesmo realm paraos cabeçalhos de autenticação dessas páginas. você está aqui ¥ 3 1 1
  • 340.
    outro problema desegurança Boa tentativa, espertinho! Felizmente, eu salvei o link para a página de remoção de pontuações, e depois falsifiquei um pouco a data. O link é este aqui no quadro que estou segurando. «ri«-,doyouhavewhatittakest0r-nvt > . http://www.guitarwars.net/ removescore. hp?id=10&name=Jacob%20 Scorcherson& date=2008-05-01 %20 20:36:45&score=389740& screenshot=jacobsscore,gif: M> nâof As pohtua^oes desapareceram da apiiòôçao guitar Wars dcnovo^. Parete <ue a nossa vila do éjwtar Wars destobriu umd -forma de dontornar a nossa tewtatwa de tornar o guitar Wars mais sc^uro- V Isto tudo tertamente é firíptito, mas â URL fârà a fa^ma removes£orephp de íato «ao passa feia pa$ina admin- php secura- QK, então talvez o Quitar Wars N&O esteja seguro Isso é que é um sucesso de pouca duração. Não demorou para os vilões atacarem novamente, apagando as pontuações do Guitar Wars e mais uma vez frustrando osjogadores. Parece que só tomar a página Admin segura não foi suficiente, uma vez que o script Remover Pontuação ainda pode ser acessado diretamente... se você souber o que está fazendo. Escreva abaixo como você acha que poderíamos resolver este novo problema, evitando que as pontuações sejam apagadas:
  • 341.
    segurança para asua aplicação Nós precisamos tornar seguro o script Remover Pontuação, e tenho quase certeza que podemos simplesmente O ^-------- usar a autenticação HTTP novamente. Fvahk 0% toç Joe: Faz sentido,já que funcionou bem para a página Admin. Frank: É verdade. Então tudo o que temos de fazer é colocar o mesmo código de cabeçalho de autorização no script Remover Pontuação, e pronto. Certo? Jill: Sim, isso certamente vai funcionar. Mas eu me preocupo em replicar todo aquele código de autorização em dois lugares. O que acontecerá se, no futuro, nós tivermos de adicionar outra página que precise ser protegida? Nós replicamos o código mais uma vez? Joe: É; código duplicado é definitivamente um problema. Principalmente porque há um nome de usuário e uma senha que todos os scripts precisam compartilhar. Se algum dia quisermos mudá-los, teremos de fazer a modificação em cada um dos scripts protegidos Frank: Já sei! Que tal colocar asvariáveis fusername e Spassword em um arquivo include próprio, e depois compartilhá-lo entre os scripts protegidos? Nós poderíamos até mesmo colocá-las no arquivo include appvars.php dasvariáveis da aplicação Joe: Eu gostei do raciocínio, mas essa solução só lida com uma pequena parte do problema de duplicação de código. Lembre-se, nós estamos falando de um pedaço de código relativamente grande. <?php // Nome do usuário e ssnha para. autenticação Çusername = 'rock'; $password = ’roll' ; if (!isset($_SERVER[’PHP_AUTH_USER1]) | | !isset($_SERVER['PHP AUTH P W ]) U ($_SERVER[1PHP_AUTH_USER' ] != $username) || ($_SERVER['PHP_AUTH_Pw” ] ' = $password)) { // Nome do usuário/senha incorretos, então enviar os cabeçalhos de autenticação header('HTTP/l.1401 Unauthorized'); header ('WWW-Authenticate:Basic realm-"Guitar Wars" ’); exit ( •<h2>Guitar Wars</h2>Desculpe, você precisa digitar uma senha válida para acessar esta pagina. ' ) ; } ?> <html> admin.pnp Jill: Vocês dois têm razão, e é por isso que eu acho que precisamos de um novo arquivo incluae para armazenar todo o código de autorização, e não apenas asvariáveis fusemame e Spassword. Frank: Ah, e nós podemos simplesmente incluir esse script em qualquer página que quisermos proteger com autorização HTTP. Joe: Isso mesmo! Só precisamos nos certificar de sempre incluí-lo em primeiro lugar, uma vez que ele depende dos cabeçalhos para todo o trabalho de autorização HTTP. você está aqui ► 313
  • 342.
    criando authoríze.php Crie umscript Autorizar Nósjá temos todo o código de que precisamos para um novo seript, Autorizar; é só uma questão de passar o código de admin.php para um novo arquivo (authoríze.php), e substituir o código original por uma instrução require_once. re-tirav»do este de advwmphp para o dolotavwos ko seu próprio arqwWo de siripi, auihori«.pVip. admin.php
  • 343.
    segurança para asua aplicação <?php // Nome do usuário e senha para autenticaçao $username = 1rock1; $password = 'roll1; ^ 0 "« “O«sl- dt JuWidatâo, a je ita elas d cra rtilh a v*, o »CSm o « M * «sA-io e a « *«a «„ha. i, < ,i „ . t ($ SERVER[ 'PHP.AUTH USER' ,, II ’ ^ . . w o r « » , < • cvBVFR I'PHP AUTH USER'] !=$username) i l (§_SEKVtKi ^ - )rNo rdoLuàr-io/se-nha i„corretos, entto envrar os cabeçalhos^--------- autenticação ( 'HTTP/l .1401 Unauthorized l ’ ÂST você precisa digitar ur,a s e n h a vâlida para acessar esta página.1); authorize,php 0 sdript Autorizar Compartilhado C incluído logo «o mítio deste sdript» u»3 vez. < ^u e ele thama a •(•w^ao headerO. <?php require_once('authorise.php1); ?> <html> <?php require_once('authorize.php’); ?> 0 dódi^o de auter»tida^ão no script Admin e substituído por «má uni£a linha de âódi^o PHP. admin.php removescore.php PONTOS DE BALA Os scripts PHP podem usar cabeçalhos para controlar o modo como o servidor entrega conteúdo web ao navegador. A função PHP headerQ é usada para se enviarem cabeçalhos ao navegador, os quais podem ser usados para se redirecionar uma página, controlar o tipo de conteúdo da página ou requisitar a autenticação da página. Quando os cabeçalhos são enviados ao navegador usando-se a função header(), as chamadas a header() devem ser feitas antes de qualquer conteúdo ser enviado. Quando uma página é protegida com autenticação HTTP, o nome e a senha digitados peio usuário ficam armazenados na superglobal $_SERVER. O “basic realm" de uma autenticação HTTP é uma zona de segurança que se associa a um determinado nome de usuário e senha, permitindo que várias páginas tenham a sua segurança feita conjuntamente. A função exit() do PHP finaliza um script PHP, impedindo que qualquer código após ela seja executado ou enviado de qualquer maneira ao navegador. você está aqui ► 3 1 5
  • 344.
    segurança não existemperguntas idiotas nüp existam p e r g u n ta s id io t a s I * Ainda não entendo totalmente como a Ethel conseguiu contornar a segurança do Guitar Wars. O que foi que ela fez? Eíaseaproveitoudafraqueza inerenteaseproteger apenas uma página(Admin), quandoo recursode remoçãode pontuaçõesnaverdade usaduas páginas (AdmineRemover Pontuação). ApáginaAdmin apresentaumasériede links Remove, vinculadosà página Remover Pontuação, Osdetalhes sobrequal pontuaçãodeveser removidasão passados na URL, permitindoqueoscript Remover Pontuaçãoosacesse atravésdasuperglobal $_GET. Sevocêconseguisseconstruir umaURL legítimaparaa página Remover Pontuação, poderiaremover pontuações semjamaispassar pelapáginaAdmin. Foi issoqueEthel fez. * Mas como ela sabia a estrutura da URL para a página Remover Pontuação? H: Elaé bastanteengenhosa, mas nãoé preciso ser gênio para fazer isso. Lembre-se de queelamencionouque salvouo link para a página Remover Pontuação, quando osite inteiroestava desprotegido. Bem, umlink salvo nosfavoritos éapenas uma URL, eela pôde usá*la para construir uma URLparaacessar diretamente apágina Remover Pontuaçãosemter de passar pela páginaAdmin. ^ * OK, mas as pontuações foram reinseridas depois do último ataque. Isso não significa que as URLs antigas não deveriam funcionar mais, uma vez que as datas estariam diferentes? H : Sim, éumaobservaçãomuitoboa. Maslembre-se, Ethel ébastante esperta. Elapodefacilmenteolharnapáginaprincipal doGuitarW ars, anotarasnovasdatas, eentãocoíocá-lasnaURLantigapararemoveras novaspontuaçõessemqualquer problema. Éimportantenuncasubestimar ahabilidadequepessoasdeterminadastêmdefazerengenhariareversa nosseusscriptsPH P, paraexplorarfraquezasdosistema. Tudo bem, então a proteção das duas páginas, Admin e Remover Pontuação, consegue parar a Ethel. Mas isso não torna muito difícil remover pontuações legitimamente? Não, de forma alguma. Semaajuda dos realms, certamente seria complicado remover as pontuações legitimamente, porque você teria de digitar o nome do usuário e a senha separadamente para as páginasAdmin e Remover Pontuação. Mas lembre-se de quefoi estabelecido umrealm (domínio) que éo mesmo emambas as páginas significando que elas estarão dentro da mesma zona de segurança. E uma vez que você tenha passado pelajanela de autenticação para uma página de umdado realm, o nome e asenha são lembrados para S lS t^Ü lcU todo o realm. Oresultado final é que digitar comsucesso o nome e a senha apenas uma vezjá é suficiente para liberar ambas as páginas. HutiCct sukestlme a fcab ilid ad e <Jue p e sso a s determinadastem de feizer engenkatia feVetsa H9Sseus scriptsTH?, para explprat- íra^ue^as d°
  • 345.
    segurança para asua aplicação T fe S T O R tv e Crie o script Autorizar e o inclua nos scripts Admin e Remover Pontuação, para torná-los seguros. Crie um arquivo de texto chamado authorize.php, e digite nele o código para o script Autorizar. Depois, modifique o script admin.php para que ele inclua o script Autorizar em vez do código de autenticação HTTP propriamente dito. Adicione a mesma instrução require_once ao início do script removescore.php, para que ele também fique protegido pela autenticação HTTP. Envie todos os scripts para o seu servidor e depois experimente abrir o script Remover Pontuação diretamente no seu navegador. Talvezvocê precise limpar algumas sessões de autenticação HTTP prévias, no seu navegador, para que ele lhe peça novamente o nome e a senha - a maioria dos navegadores memorizam os domínios de autenticação, para que você não tenha de ficar redigitando o nome e a senha. ^ uw de usuário t uma sc»h3 "tâwio para a pa^na Admin ^ua«"b> fara a Reroov«r Pcwfcuaçao- http://www. guitarwars. net/removescore. php? id=10s name=Jacob%20Scorcherson& date=2008-05-01%2020:36:45& score=389740s screenshot=jacobsscore. gif ^ £sia URL evrta a ^a$'ma Admm e aeessa a ?a<y*a Remover Porcbuaça© dire-Umemie^ A pa^ittâ Remover Poh-Uatao e pro-tegida, ihdependev>íeme«ie de £©m©'‘" o usuirio dKega a ela- Y, Tovíewrtfiis fxage, you neícf to log in to area Yí&ur wtf be inthe ctear. K aiue: ) Passywcwd: ; 3Remember this passwpnd to; ksychaln Q > E R > Q C É R E B R O Você consegue pensar em outras maneiras pelas quais a aplicação Guitar Wars esteja em risco? Guitar Wars - Remove a High Score : m higà saae Of314340 forBiff f c * was ssccessfuUy < < Back to admin p apf v o c ê está aqui ► 3 1 7
  • 346.
    (toitar Wars EpisódioII: Ataque dos Clones de Pontuapão Lamentavelmente, a felicidade no universo do Guitar Wars não durou muito, porque pontuações fantasmas estão aparecendo por toda a parte, no lugar das pontuações legítimas... o que incita o ódio em todo o universo Guitar Wars. Parece que é perfeitamente possível danificar a lista de pontuações do Guitar Wars sem remover pontuações. Mas como? um fracasso de pontuação falsa GuitarWars-HighScores W elcom e, G uitar W arrior, do you h a ve w h a i it takes to crack: the M g li score list? I f so, 500000 N am e: E tíiel Heckel Date2008-05-0214:0234 Top Score; 50000Q Gui tar 389740 Name: Jacob Scorctoson Date:2008•054U20:36:45 L.?ïK'Orl Scoreï 5 “/Í;§§ sm ß6 $ïs' 0 redorde de Ethel € dlarâmente suspeito, devido a tapW a de tela mal -faUiiieada, e a© -Pato de que ela d ii f&r ataso fcohse^uiu uma pontwaçao de g*ataweftte $00.000. 2008-05-01 20:36:45 Jacob Scorcherson 170 389740 belitasscore.gif jacobsscore.gif 23 2008-05-01 20:37:02 Nevil Johansson 98430 nevilsscore.gif 24 2008-05-01 20:37:23 Paco Jastorius 127650 pacosscore.gif 25 26 2008-05-01 20:37:40 Phiz Lairston 186580 2008-05-01 20:38:00 phizsscore.gif Kenny Lavitz 64930 kennysscore.gif 27 2008-05-01 20:38:23 Jean Paul Jones 243260 jeanpaulsscore.gif 28 2008-05-01 21:14:56 Leddy Gee 308710 leddysscore.gif 29 2008-05-01 21:15:17 T-Bone Taylor 354190 30 2008-05-02 14:02:54 tbonesscore.gif Ethel Heckel 500000 ethelsscore.gif >
  • 347.
    segurança para asua aplicação Subtrapão por adipão Até agora, vimos assumindo que qualquer pontuação submetida com uma captura de tela era considerada legítima. Agora, é razoavelmente seguro dizer que nem sempre é o caso! E está bem claro quem é o culpado... Ah, sim, sou eu... culpada! Tudo o que tive de fazer foi enviar as minhas fantasticamente falsas pontuações, com capturas de telas retocadas. Ah, é muito bom ser a melhor Quitar Warrior. ' N fctheí perdebeu cb poderia bagunçar basta^^te o éjuiW Vtòrs sím^lcs»ehÍ€ submemendo jpo?íts/3^oes das» (om dafUv-as dí •belas íaUi&tadas- Escreva abaixo como você resolveria o problema de as pessoas conseguirem inserir pontuações falsificadas na aplicação Guitar Wars: você está aqui ► 319
  • 348.
    guitar wars precisade moderação humana A segurança requer intervenção humana Mesmo neste mundo modemo em que vivemos, àsvezes, um ser humano real, capaz de pensar, é imbatível. No caso em questão, é difícil ter uma solução melhor, para analisar uma determinada informação e avaliar se ela é válida ou não, do que uma pessoa real. Estamos falando da moderação, na qual um ser humano é encarregado de aprovar o conteúdo enviado a uma aplicação web, antes de esse conteúdo ser liberado para o público em geral. Com a moderação, cada nova pontuaçao é adicionada a© banto de dados, mas nao aparefce ^ara o public* en^uâ*to o moderador s tâo a aprovar. A moderação fcumanae uma forma excelente de se melhorar a Integridade d 9 cç>nteád9 s u b m e tid p u su âtio g . A modi-fitaçao ern Admm adiciona v*mU*k Aprova a cada nova pontuação, para <*e ela possa ser aprovada- Sw k AcHoa SQQQQQRemove /Approve 389740 Remvft Simplesmente adicionar uma nova pontuação nâo mais a adiciona automaticamente à lista ^ue pode ser vista pelo publico. O Guitar Wars realmente poderia se beneficiar de alguma moderação. E claro que ainda é possível alguém fraudar cuidadosamente uma captura de tela, e talvez fazer passar uma pontuação falsa pelo moderador humano. Mas não serã fácil, e isso não muda o fato de que a moderação é um ótimo método de desencorajar os fraudadores. Tenha em mente que fazer a segurança de uma aplicação PHP depende ^ basicamente de uma boa prevenção. s Nosso destemido moderador do Quitar Wars... de nunca se deparou Com uma pontuaçao ha <ual Coníiâsse totalmente-
  • 349.
    segurança para asua aplicação Planeje woderapão no Guitar Wars Adicionar um recurso de moderação humana ao Guitar Wars é significativo porque isso afeta diversas partes da aplicação. O banco de dados precisa ser modificado, precisa ser criado um novo script para executar a aprovação, a página Admin precisa adicionar um link 'Aprovar" a cada pontuação e, finalmente, a página principal precisa ser modificada de modo a exibir só as pontuações aprovadas. Com todas as modificações assim envolvidas, é importante ter um plano e executar uma modificação de cada vez. Use ALTER para adicionar uma coluna approved à tabela. Vamos começar pelo banco de dados, o qual precisa de uma nova coluna para guardar a informação de se uma pontuação foi ou não aprovada. Modifique a página Admin para incluir um link "Aprovar” para as pontuações que ainda tenham de ser aprovadas. O scriptAprovar Pontuação fica no back-end e não deverá normalmente ser acessado diretamente. Em vez disso, ele é acessado através de links "Aprovar" gerados e exibidos na páginaAdmin - somente as pontuações não aprovadas terão o link "Aprovar”ao lado delas. S e t t e r W e « < H * * S w e » A A u f a i e t r a t i * » i Crie um script Aprovar Q Pontuação para realizar a tarefa de aprovar uma nova pontuação (definir a coluna approved como 1). Com o banco de dados pronto para acomodar a aprovação das pontuações, você precisa de um script para realizar essa tarefa. Este script Aprovar Pontuação é responsável por procurar uma determinada pontuação no banco e modificar a coluna approved dela. Modifique a consulta da página principal para só exibir pontuações aprovadas. O último passo é se certificar de que tudo o que estamos modificando seja refletido na exibição da página principal da aplicação. Assim, a página principal é modificada para só exibir as pontuações que tenham sido aprovadas - sem essa modificação, todas as outras seriam inúteis. você está aqui ► 3 2 1
  • 350.
    adicionando uma colunaAPPROVED para a tabela guitarwars Abra espaço para aprovações com A ltER Para adicionar a nova coluna approved à tabela guitarwars, é preciso usar uma vez a instrução ALTER TABLE, que é um comando SQL que já vimos anteriormente. 0 tipo de dados &QOL do M/SQL « ALTER TABLE guitarwars U m «Vo ya r aTIKVINT, yortwt» ADD COLUMN a p p r o v e d T IN Y IN T «otê foAc usar »>» dos dois- A nova coluna approved é do tipo TINYINT, e usa 0 para indicar uma pontuação não aprovada ou 1 para indicar uma pontuação aprovada. Assim, todos os novos registros devem começar tendo o valor 0, para indicar que são inicialmente não aprovados. r- m Espere um minuto. NSo sei se você pode simplesmente ir adicionando uma coluna ao banco de dados sem modificar o script Adicionar Pontuaçao - ele não terá de inserir dados à nova coluna, com INSERT? adicionar uma coluna approved à tabela. É verdade, uma nova coluna implica um novo valor na consulta INSERT do script Adicionar Pontuação. E importante não perder de vista o fato de que uma aplicação PHP é um cuidadoso arranjo de diversas partes e pedaços: um banco de dados que consiste de tabelas com linhas e colunas, código PHP, código HTML, e geralmente código CSS. Nem sempre fica imediatamente claro que, para modificar uma parte, é preciso modificar outra. Adicionar a nova coluna approved na tabela guitarwars também exige a modificação da consulta INSERT no script Adicionar Pontuação: Todas as linhas das novas INSERT INTO guitarwars VALUES (0, NOW( ) , 1$name pon-luaçoes -tem approved ~ deímida t<mo 0 — nao aprovadas. ^ Uürtili f i l ! * * ' S í i i i i S B l i f e l i i S i i l f f i i l i l l i l i i i M I I I 1 Jíitoi' of 30 2008-05-02 14:02:54 Ethel Hecke! 500000 ethelsscore.gif 0 31 2008-05-02 20:32:54 Biff Jeck 314340 biffsscore.gif 0 ‘ 32 -ÉU08-05-02 20:36:38 Pez Law 322710 pezsscore.gif ’$score1,'$screenshot', | j p guando uma nova linha é adicionada, a sua coluna approved t deíinida Como O, para <ue ela, de início, seja nao aprovada-
  • 351.
    segurança para asua aplicação Aponte seu lápis <?php O script Aprovar Pontuação tem estrutura semelhante ao Remover Pontuação, exceto pelo fato de que a sua tarefa é aprovar pontuações. Complete o código do script Aprovar Pontuação abaixo, certificando-se de fazer a página segura, e de só aprovar a pontuação apropriada, com base em dados enviados através de uma URL. ?> <?php require_once{'appvars.php') ; . require_once{'connectvars.php'); if (isset{$ POST [ 'submit ’] . ) ■ ) { if { .) { // Conecta-se ao banco de dados $dbc = mysqli_connect(DB_HOST, DBJJSER, DB_PASSWORD, DB_NAME); // Aprova a pontuação, definindo a coluna approved do banco de dados $query - "UPDATE guitarwars SET "; mysqli__query ( $dbc, $query) ; mysqli_close($dbc); // Confirma o êxito com o usuário echo else { echo echo 1 <p><a href: ">&lt;&lt; Voltar à página Admin</a></ ?> v o c ê está aqui ► 3 2 3
  • 352.
    o script paraaprovar pontuação completo r~ %Aponteseulápis Solupão <?php ?> O script Aprovar Pontuação tem estrutura semelhante ao Remover Pontuação, exceto pelo fato de que a sua tarefa é aprovar pontuações. Complete o código do script Aprovar Pontuação abaixo, certificando- se de fazer a página segura, e de só aprovar a pontuação apropriada, com base em dados enviados através de uma URL n ,, . . Tudo Ottue vod€ predisa -kzor para garantir a reT * , ^ !í!.k ‘ k," a . f : [ ).............. da A f" * * í « e u - » sdrip-t Á^toriz^o mas isso deve ser a primeira toisa no sdrip-fc, uma vez. *ue o prodesso defende dos dabedalhos <?php require_once('appvars.php'); require_once('connectvars. php' ) X Crie um script Aprovar Pontuação para realizar a tarefa de aprovar uma nova pontuação (definir a coluna ai como! ) { A IP predisa ser veri-Pidada, para <ue a aprovadao seja -feiia- i f ( i s s e t ($_POST['s u b m i t'] )) { i f ( / / C on ecta-se ao banco de dados $dbc = mysqli_connect(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME); / / Aprova a pontu ação , d e fin in d o a coluna approved do banco de d a d /s $query = "UPDATE guitarw ars SET .77. .*í4 m y sq lí_query($dbc, Çquery) ,• af?m<£a . m y sq li_ c lo se ($dbc) ; domo I aprova a pontuarão. usuirio, mosfcrândo a / / Confirm a o ê x ito com o u su á rio pontuadao aprovada e ( V o echo l<pi*A pontuação de *• fsdore ■' para * • fname . ‘ íoi aprovada dom sudesso/j } e ls e { echo *<p dlass-"erv-or”>Pesdulpe, houve um problema para aprovar a pon-fcuadão.«c/p>; } 'tT £ i^porbahie iníormar ao usuário guando umã } pott-tuaeao não puder ser aprovada, de Wma semeibaW a tomo os ouiros sdripts do guitar Wars relatam os erros. echo '< p x a h ref= " âdmin.php "> & lt;& lt; V o lta r à p ág in a Admin</a></ p> 1; ............. V"............ Forneda um link de volta à ?> pagina Admih, para -fadilitar a navegação.
  • 353.
    itfb existem Yergimtas idiotas 1• Por que não é necessário informar o nome do I • Parece pouco informativo usar 0 e 1 na coluna arquivo gráfico para se aprovar uma pontuação? approved. Não há outras maneiras de se representar essa informação? J ’ Porque o processo de se aprovar uma pontuação só exige as informações necessárias para se achar i y - Sim. Otipodedados ENUMdoMySQL, quesignifica uma determinada linha na tabela, e então aprová- "enumerado", lhepermitecriarumacolunacomumalista la. Isso significa que você só precisa informar o restritadepossíveisvalores.Assim, emvezdeadicionara estritamente necessário para achar a linha em questão, colunaapprovedcomoumTINYINTquedeveráterovalor 0 Adata, o nome e a pontuação são suficientes para ou 1, vocêpoderiaadicioná-lacomoumENUMquepudesse se especificar uma determinada linha e definir a sua terapenasosvalores'yes' e'no', destaforma: coluna approved como 1. ALTER TABLE guitarwars ADD COLUMN approved ENUM( 1y e s ' , 1n o ' ) .Aponte seu lápis----------------------------------------------------- Os dados das pontuações usados para aprová-las, no script Aprovar Pontuação, são passados através de links "Aprovar" que são gerados no script Admin. Complete o código do script Admin para que ele gere esses links. // Faz um loop através do array contendo os dados das pontuações, formatando-os como HTML echo 1 <table>'; echo ' <tr><th>Name</th><th>Date</thXth>Score</th><th>Action</thx/tr> '; while (Srow = mysqli_fetch_array($data)) { // Exibe os dados das pontuações echo '<tr class="scorerow"xtdxstrong>' . $row ['name'] . ' </strongx/td>1; echo '<td>' . $row['date'] . '</td>'; echo '<td>' . $row[1score1] . 1 </td>'; echo ' <td><a href="removescore.php?id=' . $row['id'] . '&amp;date=1 . $row[’date' ] . '&amp;name-' . $row[’ name'] . 1&amp;score=I . $row['score'] . '&amp;screenshot=1 . $row['screenshot1] . 1">Remove</a>1; if (............................. ) { echo segurança para a sua aplicação } echo ' </td></tr> ' ; ^ as r*o } apv-ovadas t deve» íc r w* echo '</table>'; Af'roV3r - você está aqui ► 325
  • 354.
    gerando links deaprovação %^ponte seu lápis Solupão Os dados das pontuações usados para aprová-las, no script Aprovar Pontuação, são passados através de links "Aprovar" que são gerados no script Admin. Complete o código do script Admin para que ele gere esses links. // Faz um loop através do array contendo os dados das pontuações, formatando-os como HTML; echo 1<table>'; echo '<trxth>Name</thxth>Date</thXth>Score</thxth>Action</thx/tr>' ; while ($row = mysqli_fetch_array($data)) { // Exibe os dados das pontuações echo '<tr class="scorerow"XtdXstrong>' . $row ['name'] . '</strongx/td>' ; echo '<td>' . $row['date'] . ' </td>'; echo '< td > ' . $row [ Ts c o re ’ ] . '< /td > '; l/eriíída se echo '<td><a href="removescore.php?id=' .$row['id'] . â pojvtuadao imp;date=' . $row ['date'] . Csiâ^apvovadé t , » ’ * r i ■ n » r- . í- r T , n 0W n &amp; name= ' . $row['name'] . *&amp; score= ' . $row ['score ’] . . dc jerar o '&amp; screenshot=' . $row ['screenshot1 ]. '">Remove</a> ' ; link aprovar if { fro>«rappy;9ycd, J ^ " “ " " echo 1/ <a hreí— "appv-ovesdore.php?id— J.frowfidO *l &a»pjd^te— -fVovjC'date’ 3 . echo ,</table>'; echo '</td></tr>' ; Çcra o link de modo -tal y c a d > j d a U o nomC) a powt^a^a® * 0 w nowe do arquivo y & t o sao passados «a URI— Admin para incluir um link "Aprovar"1 para as pontuações que ainda tenham de ser aprovadas.
  • 355.
    segurança para asua aplicação Pontuações não aprovadas não são dignas Agora,jã temos toda a infraestrutura necessária para o recurso de moderação na aplicação Guitar Wars. Só falta o último passo, que é alterar a página principal de modo que ela mostre apenas as pontuações aprovadas. Para isso, teremos de ajustar a consulta SQL SELECT de modo tal que ela só obtenha os registros cuja coluna approved esteja definida como 1 (aprovada). Isso é feito por meio de uma instrução WHERE. SELECT * FROM guitaryars ORDER BY score DESC, date ASC A adição da instrução WHERE a esta consulta elimina quaisquer pontuações que não tenham sido aprovadas, o que inclui todas as novas inserções. Isso dá ao moderador a chance de analisá-las e decidir se elas devem ser removidas ou liberadas (aprovadas) para visualização pública. Use WHERE pcflTct s e le c io n a i- llntas com base n9 V aioxJe um a determinada c o lu n a . £< 3 toluna amoved estwcv dfrÇwwfô to» diíevente de I» a ■'i ^ ** í não setra e*ibidâ- ..................’....... 1 28 2008-05-01 21:14:56 Leddy Gee 308710 leddysscore.gif 29 2008-05-01 21:15:17 T-Bone Taylor 354190 tbonesscore.gif 1 J 30 2008-05-02 14:02:54 Etheí Heckel 500000 etheisscore.gif m o m 31 2008-05-02 20:32:54 Biff Jeck 314340 biffsscore.gif 1 32 2008-05-02 20:36:38 Pez Law 322710 pezsscore.gif Agora, somente as pontuações aprovadas apatetem na pagína principal (inde*.php)- Modifique a consulta da página principal para só exibir pontuações aprova« você está aqui ► 327
  • 356.
    - — .TejstDrive, test drive approvescore.php Crie o script Aprovar e ajuste o restante da aplicação Guitar Wars para usá-lo. Usando alguma ferramenta MySQJL, emita a consulta ALTER para adicionar a nova coluna approved à tabela guitarwars. Em seguida, modifique a consulta INSERT do script addscore.php para inserir um 0, na coluna approved, para novas linhas de dados. Agora, crie um arquivo de texto chamado aprovescore.php e digite nele o código para o script Aprovar Pontuação. Em seguida, modifique o script admin.php de modo que ele inclua um link "Aprovar" para pontuações que ainda precisem ser aprovadas. Finalmente, modifique a consulta SELECT de index.php para que ela mostre apenas as pontuações aprovadas. Envie todos os scripts para o seu servidor, e abra a página principal do Guitar Wars no seu navegador. Tome nota de quais pontuações estão visíveis, e depois abra a página Admin. Clique em um dos links "Aprovar" e realize a operação de aprovar o registro. Depois, volte à página principal para ver se esse registro agora está aparecendo. GuitarWars-HighScoresAdministration Bdow is a Ksio f all GniiaiWar» hS^i seoses. Use asís|»ge ta scores s Ethel Hecfcel Jacob Scoreherson T-Booe Tajtor P e g L a w BUTJeck I . e d d yG e e BeBaCbery J e a nP a n ]J o n e s I_af7Sinn Paco Jastorras N V r i l J o h a n s s o n Kenny L»vte D jrtt Son __ _ 2008-05-02 14:0234 500000 20084)5-01 20:36:45 389740 R e tire 2008-05-01 21:15:1-? 354190 2008-05-02 20:3638 322710,.,.,,,-:.-, 200S-05-02 2032:54 314340 Êfam vS 20084)5-01 21:1436 308710 R em vg 2008-05*0! 20-36507 282470 20034)5-01 20:3853 243260 f e r o t 2008-05-01 20:37:40186530 gum™» 20084)5-01 20:3723 127(650 20OS-O54)i 20:3?#2 98430 30084)5-01 2038:00 64930 V 0s «ovos i'mks ”Aprovar" da p%‘*a Adwin £ome£ew> atcsso a patina Aprovar Pon-bua^ao, ohdt os reystros pode» ser aprovados indi dual»eR"te■
  • 357.
    segurança para asua aplicação Apos a operaçac -fcev sido Conduídâ dorr SUÍCSSO, urr> a de £o«íiVn>3Çao e exibida. Um simples íovmirflário requer coníiymaçao a^ies de 'reaUewíe aprovar o re^istvo. h ^edewi— apvovada , pohiuacao aaova apareie pagina principal do quiiav IV ô v -s. v o c ê está aqui ► 329
  • 358.
    ethel marca denovo 0 hack de um milhão de pontos A versão moderada do Guitar Wars representa uma melhoria significativa na segurança, mas está longe de ser completamente à prova de balas. Parece que a nossa infiltradora conseguiu achar outra fraqueza no sistema, e de alguma forma está conseguindo fazer as suas pontuações passarem pelo moderador. Ethel precisa ser detida, permanentemente, para que possamos restaurar a confiança no universo do Guitar Wars. Bsie t C*atarwOrte o -tipo de foh-tuaçao < ^u e o nnoderâdor deve impedir... e no enia>vto, 3*ui esta ela/
  • 359.
    segurança para asua aplicação Tudo em moderação...? Embora o moderador saiba, sem sombra de dúvida, que ele nao aprovou a pontuação submetida por Ethel, esta claro que essa pontuação chegou ao banco, com a coluna approved de^n'd como 1. Nós sabemos que o script Adicionar Pontuaçao defm a coluna approved como 0 para novas pontuaçoes, porque acabamos de modificar a consulta INSERT desse scnpt. Algo simplesmente não está certo! Como é possível? Eu sei que não aprovei essa pontuação. Um milhão de pontos!? O 0 moderador j}° 3*vtar Wav* «ao dorvsc^c G rà M cr o <«e afconteieu. »d ia— lllll[}ipiSiliI. score S u m 21 2008-05-01 20:36:07 Belita Chevy 282470 belitasscore.gif 1 22 2008-05-01 20:36:45 Jacob Scorcherson 389740 jacobsscore.gif 1 23 2008-05-01 20:37:02 Nevil Johansson 98430 nevilsscore.gif 1 24 2008-05-01 20:37:23 Paco Jastorius 127650 pacosscore.gif 1 25 2008-05-01 20:37:40 Phiz Lairston 186580 phizsscore.gif 1 26 2008-05-01 20:38:00 Kenny Lavitz 64930 kennysscore.gif 1 27 2008-05-01 20:38:23 Jean Paul Jones 243260 jeanpaulsscore.gif 1 28 2008-05-01 21:14:56 Leddy Gee 308710 leddysscore.gif I 1 29 2008-05-01 21:15:17 T-Bone Taylor 354190 tbonesscore.gif ! 1 31 2008-05-02 20:32:54 Biff Jeck 314340 biffsscore.gif 1 1 32 2008-05-02 20:36:38 Pez Law 322710 pezsscore.gif r 33 2008-05-05 14:58:59 Ethel Heckel 1000000 ethelsscore2.gif 1 J c 9 K R W _____________________________ C É R E S R O Como você acha que o post falso de Ethel conseguiu passar pelo moderador? füsfca poM-tuaçao não ío'i aprovada <^to moderadorj e m o ewtairt»» a sua tolw«a approved esta deíinida tomo I» o «ue resulta em ela ser e*A>»da- você está aqui ► 331
  • 360.
    tente o golpeda Ethel E X E R C fT A W O « C É R E B R O E th e l H e cke l Ocorre que o hack de um milhão de pontos de Ethel não teve nada a ver com o formulário Aprovar Pontuação. Foi descoberto que a invasão dela se baseou apenas no formulário Adicionar Pontuação. Segue abaixo os dados exatos que Ethel digitou no formulário Adicionar Pontuação; digite os mesmos dados no seu próprio formulário e adicione o registro. O que você acha que está acontecendo? Não sc es^ueí-â do espaço depois de — . d<ü- 1000000 ' e t h e l s s c o r e 2 . g i f ' , 1 ) Este pode ser ^uai^uer dr^uivo yrS-Çito éflF ou JPE$ tem menos de 1 Z W . ethelsscore2.gif
  • 361.
    segurança para asua apficação Conto exatamente ela fez isso? Para entender o que está acontecendo neste inteligente tipo de ataque a formulários, vamos rastrear o fluxo dos dados enquanto eles viajam através do script Adicionar Pontuação. Êihel digitou â sua poniuâdao-.. C mais um morrte de doisas estranhas/ $score = $ POST['score']; 0 indomum donteudo do d3mpo Pon-tua^ae do -formulário e armazenado na variável fsdore, o <uâl vai parar dire-tamen-be na donsul-ta INSERT. '$screenshot', 0) O campo Pontuação espera receber apenas um valor numérico, como 1000000, mas em vez disso ele tem diversos valores colocados entre aspas simples, separados por vírgulas e terminando com um estranho hífen duplo. Muito estranho. Esses estranhos dados são primeiramente armazenados na variável $score, após o que são incorporados na consulta INSERT. Isso resulta apenas em uma pontuação inválida, certo? Ou tem algo mais sinistro acontecendo aqui? Aponte seu lápis Usando os dados exatos que foram mostrados na página anterior, escreva aqui a consulta SQL inteira do ataque de um milhão de pontos. Certifique-se de substituir as variáveis da consulta pelos dados propriamente ditos. Escreva também o que você acha que está acontecendo. você está aqui ► 333
  • 362.
    como uma injeçãode SQL funciona tpowteseu lápis--------------- ----------------- -----------— Ç n l l i r ã n Usando os dados exatos que foram mostrados na página anterior, ^ escreva aqui a consulta SQL inteira do ataque de um milhão de pontos. Certifique-se de substituir as variáveis da consulta pelos dados propriamente ditos. Escreva também o que você acha que está acontecendo. IffJQ. w b r & r * ............................... .............................................................................. |LUE£ (O, MWO, 'E-thel ttefckel', 'lOOOÔÔO1 , 'eihelss£oreZ<ji-(-lÍ^— 'e-thelsstore2-<yí O) Uma vez. < ^u e a eo!u*a approved t a uiíima r> a estrutura do bando de dados De alguma -forma, í Que consul+a estranha. —_ ela está s e s ndo íorçada a ter Éthel t *iou a sua ) > ^quivo gráfico aparece um valor de I... aprovado/ própria versão da ( e n3° Sei 0 ^ue si9nifica • ) ° 0 ícm uIU 3 ^ual ^ essa consulta funciona? tiíâ substituindo â òonsulta origina). Enganando o MySQl com comentários O verdadeiro culpado pelo ataque de um milhão de pontos de Ethel, por incrível que pareça, são os comentários SQL. O hífen duplo (— ) é usado, em SQL, para desativar o restante de uma linha de código SQL, transformando-o em um comentário. E preciso haver um espaço depois do hífen duplo para que ele funcione (— ), mas tudo o que vier depois do espaço é ignorado. Agora, dê outra olhada na consulta de Ethel, levando em conta esse novo conhecimento. INSERT INTO guitarwars VALUES ( 0 , NOW() , 'Ethel Heckel', 11000000' Faz mais sentido agora? Na prática, o comentário apagou o restante do código SQL, para que ele não gerasse um erro, permitindo que a versão da consulta criada por Ethel pudesse chegar ao sistema sem percalços. O resultado final é uma pontuação instantaneamente aprovada, a qual o moderador nunca teve a chance de analisar. Ô dome*iario — íaz. dom «ue o restante da linha de tcdo.o SQL seja ignorado. / 'ethelsscore2.gif1, 1) — £thel chamou o sistema, íazendo-o aprovar a sua potfUaça«
  • 363.
    segurança para asua aplicação 0 formulárioAddScorerecebeuumainjeçãodeSQL O ataque de Ethel é conhecido como injeção de SQL, e envolve um truque extremamente sorrateiro, no quai os dados do formulário são usados para se modificar a operação fundamental de uma consulta. Assim, em vez de o campo do formulário apenas fornecer uma informação, como um nome ou uma pontuação, ele altera a própria consulta SQL subjacente. No caso do Guitar Wars, a injeção de SQL de Ethel usou o campo Pontuação como um meio de não somente fornecer a pontuação, mas também o nome do arquivo gráfico, o valor para approved e um comentário no final, para evitar que o código SQL original gerasse um erro. Os octnipps do f o r a u la r í p s § 9 um p9nt9 feac< na segurança das aplicações W e b , p Ç fíjfu e eles petmitem <jue Ps usuátíps lusfraifl INSERT INTO VALUES (0 , NOW() 1$name ’ 1$screenshot' não exîstem ?eïgimt£ts idiotas l - Existem outros tipos de comentários em SQL, fora --? K : Sim. Outra variante de comentário envolve o uso de # emvez de mas tem obviamente o mesmo efeito de anular qualquer código SQLaté o final da tinhaque contém o comentário. 0 SQLtambém oferece suporte a comentários multilinhas, semelhantes àqueles do PHP no sentido que você coloca o código comentado (desativado) entre /* e */. • 0 ataque de injeção SQL de Ethel ainda teria funcionado se a coluna approved não fosse a última da tabela? Não, e essa é uma questão realmente importante. Aconsulta INSERTque foi usadadependeda ordem padrão das colunas natabela. Golocar 1nofinal da consulta funcionou por acaso, porque approvedera a última coluna, aparecendo imediatamente depois da coluna screenshot. você está aqui ► 335
  • 364.
    prevenindo injeção desqi Proteja seus dados contra injepões de SQL A fraqueza que as injeções de SQL realmente exploram reside nos campos de formulários que não são validados para impedir a inserção de caracteres perigosos. "Caracteres perigosos" são todos aqueles que tenham o potencial de modificar a natureza de uma consulta SQL, como vírgulas, aspas ou caracteres de comentários como — . Até mesmo espaços ao final de algum dado podem se revelar perigosos. É fácil eliminar espaços com a função interna do PHP trim() - basta passar todos os dados de formulários através da função trim() antes de usá-los em uma consulta SQL. $name = | j | | i | | | ($_POST ['name ']); $score = i($ POST['score'] ) ; $screenshot = |||||||j($_FILES ['screenshot'1]['name']); Mas os espaços não são o único problema. Ainda existem as vírgulas, aspas, caracteres de comentários e assim por diante. Portanto, além de retirar os espaços em branco, nós também precisamos de uma forma de encontrar e neutralizar outros caracteres problemáticos. O PHP nos auxilia com outra função interna, mysqli„real_escape_string(), a qual faz escape de caracteres potencialmente perigosos, para que eles não possam afetar o modo como uma consulta se executa. Esses caracteres ainda poderão aparecer como dados em campos do formulário, eles só não serão capazes de interferir nas consultas. Juntas, as funções trim() e mysqli_real_escape_string() fornecem uma sólida linha de defesa contra injeções de SQL. A -PunÇao -fcW iwO sc livra de ^ais^ucv . / espaços <^e apareçam antes < x » depois dos dados deste •foriwulario. As Injeções SQL podem ser eVitadas p ro c e s s c in d o -s e d e Y id c im e n te os dados de Çprmuláríps. A íunçao n*ys^r«_jreaS__esòape__ stringO tonverte daratteres perigosos cm um -formato tom estape, o ^uaS «ao e dapaz. de aíetar as donsultas £$L- $name = $score =4 $screenshot = ['name'])); Processar os três campos do formulário Guitar Wars com as funções trim() e mysqli_real_escape_string() reduz em muito as chances de um outro ataque de injeção SQL. Mas elas não são o suficiente - talvez haja uma forma de tomar a própria consulta menos vulnerável... ($dbc, trim( $_POST['name 1])); {$dbc, trim($_POST['score'])); |â|($dbc, trim ($ FILES [ 'screenshot'] mys^lijreâLesdapej^ringO t donsiderada uma -função ‘de bandos de dados, e é por sso eue ela e*ige <ue vode lhe íornedà uma variável de done*3o a bando de dados, da mesma -forma <*e aquela usada ao se submeter donsultas.
  • 365.
    segurança para asua aplicação Um INSERT mais seguro (com parâmetros) Uma consulta Í]SÍ$EflT~p9d e se t e s c ríta d e fo rm a a especiíicar exatamente Valetes Vãp pava <jua!s colunas. Além da fraqueza dos campos do formulário, a injeção de SQL de Ethel também explorou o fato de a coluna approved vir depois da coluna screenshot na estrutura do banco de dados. Foi assim que ela conseguiu hackear o sistema apenas adicionando 1 ao final de INSERT, e fazendo-o ser colocado na coluna approved. O problema é que a consulta INSERT é estruturada de forma tal que ela precisa inserir dados em todas as colunas, o que aumenta desnecessariamente o risco. 0 ideal e <ue «ao prensássemos deímir as toiunas id e approved, uma vez. ^ue elas pode» -fitar tom os valores padrões INSERT Ií^pO guitarwars VALUES (0, NOW(), 1?name' , '$score', '$screenshot Quando dados são inseridos em uma tabela desta forma, a ordem deles precisa bater com a ordem das colunas na estrutura da tabela. Assim, a quinta informação será colocada na coluna screenshot porque esta é a quinta coluna da tabela. Mas na verdade não é necessário inserir explicitamente as colunas id ou approved, uma vez que id é autoincrementada e approved deve sempre ser 0. Uma abordagem melhor é inserir apenas os dados explicitamente requeridos em uma nova pontuação. As colunas id e approved poderão então usar os padrões de AUTO_INCREMENT e 0, respectivamente. Nós precisamos de uma consulta INSERT reestruturada, que espere uma lista de colunas antes da lista de dados, com um pareamento exato. Isso elimina o risco de a coluna approved ser definida - ela não faz mais parte da consulta. Se esse tipo de consulta parece familiar, é porque você a usou diversas vezes em outros exemplos. , . . . r ^ r Nada pode ser iwsendo na doluna approved, porque ela *âo esta istada domo parie da INSERT INTO guitarwars VALUES {NOW(), '$name' A toluna id pode ser dei*ada de -fora, uma vez. « ^ue ela se au-koindv-emen-ta de <ua!<uer íorw>3- Esta versão da consulta INSERT informa exatamente em qual coluna deve ser colocada qual informação, permitindo que você insira dados sem ter de se preocupar com a estrutura subjacente da tabela. Na verdade, usar esse tipo de INSERT é considerado como um melhor estilo de programação, porque os dados são inseridos exatamente onde você quiser, em vez de o destino deles ser ditado pelo layout da tabela. você está aqui ► 337
  • 366.
    o commando DEFAULT Nãosó é possível, como é uma ótima ideia especificar valores DEFAULT para as colunas sempre que possível. O comando SQL DEFAULT é o que lhe permite especificar um valor padrão para uma coluna. Se a coluna dver um valor padrão, você não precisa defini-la em consultas INSERT, e pode ter a certeza de que ela automaticamente adotará o valor padrão. Isso é perfeito para a coluna approved da tabela guitarwars. Agora nós só precisamos modificar a tabela mais uma vez, para definir o valor padrão de approved como 0 (não aprovado). Uma vez. a doluna approved ja enisle hesta instrudao ALTER TjABL-E, nos te»wos de war MODIFYCOLUMN C0LUMH- ALTER TABLE guitarwars MODIFY COLUMN approved TINYINT Com a coluna approved agora alterada para adotar um valor padrão, a nova e melhorada consulta INSERT do script Adicionar Pontuação pode inserir pontuações sem sequer mencionar a coluna approved. Isto é um bom design, uma vez que não há necessidade de inserir explicitamente um valor que pode ser padronizado, e ainda adiciona uma pequena dose de segurança, ao não expor a coluna approved a potenciais ataques. DEFAULT a appvo^d ser assinalada a b a te m e n t« to menos «ue u» I.NStKl cs?etiíi*V*€ de outra W * to n 0 , a menos °*e Vode predisa espedi-fidar o tipo da doîuna —garanta ^ue seja o mísmo da /"vez. <^*e âdidionou â dolunâ-
  • 367.
    segurança para asua aplicação A validação de formulários nunca é inteligente demais U m último passo para se minimizar o risco de ataques de injeção SQL envolve a validação do formulário no script Adicionar Pontuação. Antes de verificar se o tipo ou o tamanho do arquivo gráfico estão dentro dos limites estabelecidos pela aplicação, os três campos do formulário são verificados para garantir que não estejam vazios. if (!empty ($name) & & ||^ |^ ||g |($ sc o re ) && !em p ty ($ screen sh o t) ) { } Não há nada de errado com o código atual, mas o processo de garantir a segurança de uma aplicação frequentemente exige que você dê um passo além do habitual. Uma vez que o campo Pontuação espera um número, faz sentido verificar não apenas se existe um valor, mas se o valor existente é numérico. A função PHP is_numeric() faz exatamente isso, retomando true se o valor passado a ela for um número ou false caso contrário. Ela está sempre fazendo os trabalhos triviais, como por exemplo, verificar se foi recebido um número quando um número era o que você esperava, que no fim das contas vão tomar a sua aplicação tão segura quanto possível. £$tãi dcdlara^ao •í vsn-Tidâ se iodos os dai*p©s do ■formulário esiào preenchidos. is numeric(465730) ^ is_numeric('one million! Vcrdadeirol f is numeric(0) Fals ftcício Verdadeiro ou -falso, dependendo de « usuário di^iW ou nâo um numero no £3mpo Pontuação- C is_numeric($score) S e lflp le c[ue pPssíV el, eX ljA c(u e p s dadPS d e Ç ptrnuláíiP e ste ja m n o ÍPVmatP ^U e V pce e sp e c iífc p u . Reescreva a declaração ifde validaçãodo formulárioAdicionar Pontuação, de modo que ela use afunção is_numeric() para permitirapenas pontuações numéricas. você está aqui ► 3 3 9
  • 368.
    test drive onovo addscore.php ^ Reescreva a declaração if de validação do formulário Adicionar Pontuação, ^ de modo que ela use a função is_numeric() para permitir apenas pontuações IO numéricas. Aprimore o tratam ento dos dados do formulário no script Adicionar Pontuação. Ajuste a atribuição de dados do formulário às variáveis, no script addscore.php, de modo que as funções trim() e mysqh_real_escape_string() sejam usados para limpar os dados do formulário. Depois, modifique a consulta INSERT para que ela especifique tanto os nomes das colunas quanto os valores, eliminando-se a necessidade de fornecer valores para as colunas id e approved. Modifique também a declaração if que valida os campos do formulário para que ela verifique se a pontuação é numérica. Finalmente, use uma ferramenta MySQL para rodar a consulta ALTER que estabelece o padrão de 0 para a coluna approved. Envie o novo script Adicionar Pontuação para o seu servidor, navegue até ele, e depois tente realizar o mesmo ataque de injeção de SQL novamente. } T te S T O r i v e é da*-o <«e esta mensagem de erro poderia ser um pouio m3is espetí-fita» m3s ela atende às nossas necessidades sem prefcisârmos adií-ionar muito mais programaçao ao sdript-- um topido t^ue vai muito alem da segurança de bandos de dados. 0 Capítulo lô revisitará a validação tom muito mâis detalhes... TTvaMa^ao de -formulários e
  • 369.
    segurança para asua aplicação Cessar fogo! Parece que a determinação de Ethel de interferir nas pontuações do Guitar Wars Finalmente foi quebrada, graças às melhorias que tornaram a aplicação imune a injeções de SQL. O verdadeiro campeão do Guitar Wars respondeu inserindo um novo recorde. GaitarWars-HighScores Welcome.GuitarWamor. do you ba»ewiwi it takesto crack the ingb scarelist? If so,just addvo aroyn sPMS. 465730 w JacobScotchefson Date: 200S-G5-G5 23;28i'7 Top Score: 465730 Gui t a r Feliz. pelas pontua^oes âgora estarem protegidas £©«tra tateríerendias externas, Jatob «*via u» «ovo reíorde ^ue será di-Pfeii de bater. Oh( nao! Venceram-me novamente. Talvez seja hora de aprender a tocar guitarra virtual. tom o •fato de elhor sejuntar a eles £ ^u e tontmuar perdendo para eles, Ethel pertebe <ue talvez, seja hora de se W *ar uma éjuitar Warrior. você está aqui ► 341
  • 370.
    CAPÍTULO 6 caixa de ferramentasphp e mysql Sua Caixa de Ferramentas FHF£ MySftl & fflH H JP Além de aprimorar a aplicação de recordes do Gultar Wars, você adquiriu várias novas ferramentas e técnicas. Vamos rever as mais importantes.
  • 371.
    Sfrß i tnbeBisa booa oeöeoude e n $ e ejed eöuejnßos
  • 373.
    criando aplicações webpersonalizadas 7 Ctíífficlo Aplicações Web peís°ilcllizílclcls % ^ Lembra de Mim? % Ninguém gosta de ser esquecido, especialmente usuários de aplicações web. Se a aplicação tiver que trabalhar a noção de “comunidade”, ou seja, se for planejado que os usuários interajam com a aplicação de uma forma pessoal, então ela terá de se lembrar dos usuários. Você detestaria ter que se apresentar novamente à sua família a cada vez que entrasse em casa. Não. precisa fazê-lo porque seus parentes possuem uma coisa maravilhosa chamada memória. Mas aplicações web não se lembram das pessoas automaticamente - é preciso que um desenvolvedor web esperto use as ferramentas disponíveis (PHP e MySQL, talvez?) para criar aplicações web personalizadas que realmente sejam capazes de se lembrar dos usuários. este é um novo capítulo ► 345
  • 374.
    uma boa incompatibilidade é d ifícil de encontrar Pizem queos opostos seatraem É uma história antiga: garoto conhece garota, garota acha que o garoto é completamente insensível, garoto acha que a garota é maluca, mas no fim das contas as diferenças se transformam na atração, e eles acabam vivendo felizes para sempre. Essa história é a inspiração do novo e inovador site de encontros mis-match.net. O Mismatch - "Desencontro"- usa a teoria de que "os opostos se atraem" para combinar encontros entre as pessoas com base nas suas diferenças. O problema é que o Mismatch ainda precisa de um desenvolvedor web para terminar de construir o sistema. É aí que você entra. Milhões de corações solitários estão esperando ansiosamente que você termine a aplicação... não os decepcione! Sidney adora reality shows, yo^a e sushi, e espevâ donse^uir um desendoivbro Johan Nettles Male (Masculino) 1981-11-03 Athens, GA As aplicações web pessoais dependem fundamentalmente das informações dos usuários, portanto estes deverão ter a capacidade de acessar a aplicação em um nível pessoal. - ► Sidney Kelsow Female (feminino) 1984-07-19 Tempe, AZ Joha« adora luta livre pressionai, levantamento de pesos e Spam, e tem interesse e» <ual<uer uma <ue responda ao seu âhundio. Os usuários do Mismatch precisam ser capazes de interagir com o site em um nível pessoal. Isso significa, entre outras coisas, que eles precisarão de perfis pessoais, nos quais inserirão informações sobre si mesmos, as quais poderão compartilhar com outros usuários do Mismatch: sexo, data de nascimento, localização, etc.
  • 375.
    criando aplicações webpersonalizadas 0 negócio do Mismatch são os dados pessoais Portanto, o negócio do Mismatch é estabelecer conexões através de dados pessoais. Essas conexões devem ocorrer dentro de uma „ cada um dos quais devendo ser capaz de interagir com o site e gerenciar os seus próprios dados pessoais. Uma tabela chamada mismatch_user será usada para guardar as informações dos usuários do Mismatch. Este e o bando de dados do M'smâtdh- Dentvo do bando de dados, a tabeia mis«.atdh__ usev armazma os usuários t as $uâs iivPoJrmaÇoes pessoais. As páginas Editatr c Vev Peir-Çil pvedisam sabev <^uai perfii devem adessav. J Cada linha da tabela mismafcdh__ user dontém dados pessoaismeímentes a umusuatrio- Sidney Kelsow Female(Feminino) 1984-07-19 Tempe, AZ Além de visualizar o perfil, os usuários do Mismatch podem editá-lo usando a página Editar Perfil. Mas há um problema: a aplicação necessita saber qual perfil ela deve editar. A página precisa de algum modo de saber qual é o usuário que a está acessando. WCÉRÉSRO Como o Mismatch poderia personalizar a página Editar Perfil para cada usuário do sistema? você está aqui ► 3 4 7
  • 376.
    adicionando log-ins paramismatch 0 Mismatch precisa de logins para os usuários A solução para o problema de acesso aos dados pessoais no Mismatch envolve o uso de logins, o que significa que os usuários precisam de um meio de fazer login na aplicação. Isso dá ao Mismatch a capacidade de fornecer acesso a informações personalizadas para cada usuário. Por exemplo, o usuário logado só poderia editar o seu próprio perfil, mas poderia também ter acesso de visualização aos perfis dos outros usuários. Os logins são a chave para a personalização no aplicativo Mismatch. Um login geralmente requer duas informações: um nome de usuário e uma senha. O s lp g ín s permitem <}ue as aplicações V e b tr a te m PS usuários de forma p^sspaL Nome do Usuário (Username) A tarefa do nome do usuário é fornecer uma identificação para cada usuário individual dentro do sistema. Os usuários poderão acessar e potencialmente comunicarem-se uns com os outros através dos seus nomes no sistema. s id n e y f e Senha (Password) A senha é responsável por fornecer um determinado grau de segurança ao login dos usuários, o que ajuda a proteger os seus dados pessoais. Para fazer o login, o usuário precisa digitar tanto o nome quanto a senha. j n e t t l e s ^ ^ 0* no».es de usuário geralmente Consister* de caracteres al-fanuméridos, e são escolhidos fel® próprio usuário. * * * * * * * * * * * * * * ^ ^ As senhas sao dados ^ extremamente sensíveis, e nao devemjamais £icar visíveis em uma aplitação, nem mesmo dentro do banCo de dados. A combinação de nome de usuário e senha permite ao usuário fazer login na aplicação Mismatch e acessar dados pessoais, por exemplo, para editar o seu perfil. A página £d>tar Períil agorâ 'mdi£3 ^ e o usuário esta logado- O^nome e a senha sao tudo de < ^u e a aplidaçao precisa para saber ^uem £ o usuário- ^uândo um usuário login, a aplicada© torna-se capaz, de lembrar «juem e e de -fornecer u»*a experiência personalizada. Youareloggedinassidneyk. Mismatch- EditProfile PfejscmalioftHiaaiKMi First name: L a s t n a m e; G ander: ite
  • 377.
    Elabore um planopara os logins dos usuários Adicionar o suporte a logins ao Mismatch não é tarefa fácil, e é importante estabelecer exatamente o que precisará ser feito antes de começarmos a escrever código e executar consultas ao banco de dados. Nós sabemos que existe uma tabela a qual armazena os usuários, então a primeira coisa a fazer é modificá-la para que ele armazene as informações de login. Também precisaremos de uma forma de permitir que os usuários digitem os seus dados de login, e isso precisará ser integrado de alguma forma ao restante da aplicação Mismatch, para que páginas como Editar Perfil só fiquem acessíveis depois de um login com sucesso. Eis aqui os passos que estabelecemos até o momento: criando aplicações web personalizadas Usar ALTER para adicionar colunas username e password à tabela. O banco de dados agora precisa de novas colunas para armazenar os dados de login - nome e senha - de cada usuário. J |L Conectar o script de Login ao V restante da aplicação Mismatch. As páginas Editar Perfil e Ver Perfil da aplicação Mismatch só devem ficar acessíveis para os usuários logados. Assim, precisamos nos certificar de que os usuários tenham de fazer login. através do script apropriado, antes de receberem acesso a essas páginas. Criar um novo scrint rio . - p zr-s& z- prc “ p á t f n í ™ U ltim ainstância, F gmas pessoazs, poron^ 4 que pede um nome e um* u vá^ o s . Essas informações digitadas corretamenrI PreC1Sam que M ism atch possa e xib ir da T específicos „ - ■ dados ^ p Z * z z r 0^ im’° Páginas personalizadas de f„° “ que elas não possam T’ ma 131 um login válido ervistassem você está aqui ► 349
  • 378.
    configuração do mismatch Antesde seguir adiante, tire um momento para testar a aplicação Mismatch e pegar o jeito de como ela funciona. Baixe todo o código para a aplicação Mismatch no site da Alta Books, em www.altabooks. com.br. Envie todo o código para o seu servidor web, exceto os arquivos .sql, os quais contêm instruções SQL para criar as tabelas necessárias. Certifique-se de executar a instrução de cada arquivo .sql em uma ferramenta MySQL, para que você tenha as tabelas iniciais das quais irá precisar para o Mismatch. Quando estiver tudo pronto, vã até a página index.php no seu navegador web, e experimente a aplicação. Tenha em mente que as páginas Ver Perfil e Editar Perfil inicialmente não estarão funcionando, uma vez que elas dependem dos logins dos usuários, funcionalidade essa que estamosjustamente implementando agora. Estes dois iihks levam a partes personalizadas da aplieadâo. TMKcmfttfil.Wh««opposflesattract! «»V i e w P l o S t e «»EdfrfTOflte Latcsrmember A fágmâ principal do /V|is»atdH iKe permite ver ©nome e a -foto dos usuários »ais redentes, porem nadd maisj se vode nao estiver locado- O código-fonte completo da aplicação Mismatch está disponível para download no site da Alta Books: www.altabooks.com. br
  • 379.
    criando aplicações webpersonalizadas Preparando obanco de dados para os logins OK, de volta à construção. A tabela mismatch_userjá está fazendo um bom trabalho de armazenar informações do perfil de cada usuário, mas ainda fica a dever no que se refere às informações de login. Mais especificamente, faltam na tabela colunas para se armazenar o nome e a senha de cada usuário. mismatch user A tabeía »istoatdh_user predisa de dolunas parâ « tV ”nr>d££hâV - o home e a senha de login dos usuários. Tantos os dados dos nomes quanto os das senhas consistem de texto puro, portanto, é possível usar o familiar tipo de dados VARCHAR do MySQL para ambas as colunas. Porém, ao contrário de alguns outros dados dos usuários, você não pode permitirjamais que o nome ou a senha fiquem vazios (NULL). nao eXistefll Perguntas idiotas As dolunas userna»e e password donte*w dâdos de ■texto sWples, w *as nunda deve» -fidar vazias. r- ^Aponte seulápis Por que eu não posso simplesmente usar userjd, em vez de username, para identificar os usuários? í ^ * Você até pode, se quiser. De fato, o propósito de userjd é justamente fornecer um modo eficiente de se identificar individualmente as linhas referentes a cada usuário. Porém, IDs numéricas tendem a ser difíceis de memorizar, e os usuários realmente preferem escolher os seus próprios nomes ao se cadastrarem em aplicações web personalizadas. Assim, trata-se mais de uma decisão de usabilidade permitirque Johan faça login como "jnettles" em vez de "11". Ninguém quer ser diminuído a um mero número! fW as pessoas gostaria» de te r de lembrar uma seoha do*» mais de daradteresj Termine de escrever uma instrução SQL que adicione as colunas username e password à tabela posicionada conforme abaixo, sendo que username precisa ser capaz de armazenar 32, password 16 caracteres e nenhuma delas deve permitir dados NULL. você está aqui ► 351
  • 380.
    aponte seu lápissolução s : tponte seu lápis ^ Solupão Termine de escrever uma instrução SQL que adicione as colunas username e password à tabela posicionada conforme abaixo, sendo que username precisa ser capaz de armazenar 32, password 16 caracteres e nenhuma delas deve permitir dados NULL. ALTER t a b l e é usada para aditionar colunas a u»a tabela existente. WALTER . W mismattb__usçr APP. userna»« YARÇlfAR^yP. NOT NULL AFTER user_id, K - I r W p password VftRCHMd« NOT HULL AFTÍR u « n *M ^ ----Atolw >awen^c c ....... ..................................... ........................................................ adicionada primeiro, Aihstir^o AFTER donWa, «3 tabtla, onde as «ovas colunas serao adicionadas. adicionada primeiro, portanto, vote pode re-ferendia-la a<ui. m i sm atch _ _ u s e r { A posição das dolunas em uma tabela nao necessariamente íaz. di+erença, embora possa ser mais adequado, do ponto de vista organizacional posicionar as Colunas mais «mportahtes primeiro- Usar A V T B K ia § i(^ ic io n a r colunas username e password à tabela. É claro que você nao vai simplesmente armazenar a senha no banco do jeito que ela está... não é preciso criptografar as senhas antes de armazená-las? Boa observação... as senhas precisam ser criptografadas. A criptografia no Mismatch implica converter a senha em um formato irreconhecível, ao ser armazenada no banco de dados. Qualquer aplicação com suporte a login dos usuários precisa criptografar as senhas, para que os usuários possam ter a certeza de que as suas senhas estão sãs e salvas. Não é aceitável expor as senhas nem mesmo dentro do banco de dados. Assim, nós precisamos de uma forma de criptografar as senhas antes de inseri-las na tabela mismatch__user. Porém, antes disso, a criptografia não nos será muito útil se não tivermos uma forma _ ______ __ _____ i_ _ _____ r.
  • 381.
    criando aplicações webpersonalizadas Construindo uma interface de usuário para ologin Uma operação de log-ln te^ueí uma Intetíace pata 9 n9me de usuárfc e a senfca Com o banco de dados alterado para armazenar os dados de login dos usuários, ainda precisamos de uma forma que permita que eles digitem os dados e realmente façam login na aplicação. Esta interface de login precisa consistir de campos de edição de texto para o nome e para a senha, bem como de um botão para executar o processamento do login. 0 damp© senHa é proteÿdo> para ^ue â senha não fossa ser vista- (jnettles Password: m is m a tc h _ u s e r CWtzr bota« U0 5 1 ln íaz- a agitação veri&tar o nome e a senha junto ao bànto de dados- não existem fergimtas Idîptas r o » F i i f r l 1 dierdre * ****** 1 baldpaul * ** ** * 1 jnettles * ** ** * ** pppsws £e o nome e a senha baterem, o usuário é locado dom sudesso- 0 que fica realmente armazenado no banco de dados não são asteriscos, certo? Certo. Os asteriscos mostrados em um campo de senha simplesmente servem para fornecer segurança visual, impedindo que alguém olhe por sobre os seus ombros enquanto você digita a senha. Quando 0formulário é submetido, é a própria senha que éenviada, e não os asteriscos. Épor isso que é importante a senha ser criptografada antes de ser inserida no banco. f - 0 ................. Caso estejapreocupado sobre como os usuários poderão fazerlogin, se aindanão atribuímos nomes e senhas a e l e s . . .relaxe. Nós iremos criar os nomes e as senhas em um instante. Por enquanto, é importante elaborar os alicerces do login, mesmo que ainda tenhamos de realizar mais tarefas para que tudo funcione a contento. você está aqui ► 353
  • 382.
    a função sha() Criptografe as senhas comSHÀO Aíunçã° SHAO d p jV W S o I/ A interface de login é bem simples, mas ainda não nos detivemos p na necessidade de criptografar a senha. O MySQL oferece uma c n p t p g w a u m função chamada SHA() que aplica um algoritmo criptográfico a W p V T n ín l ío “ fpVfO uma string de texto. O resultado é uma string criptografada que * possui exatamente 40 caracteres hexadecimais, independentemente tía n s íP tÜ lc lJ lc lP ''P do tamanho da senha original. Assim, a função na verdade gera um * ío T código de 40 caracteres que representa individualmente a senha. ^ 0 1 U H ] C P c ll^ P Uma vez que SHA() é uma função do MySQL, e não uma função 4 0 PHP, você pode chamá-la como parte de uma consulta que insira uma senha na tabela. Por exemplo, este código insere um novo usuário na tabela mismatch_user, criptografando a senha com SHA() durante a operação. INSERT INTO mismatch_user (username, password, join_date) VALUES { 'jnettles ' , j f f § | | j { 'tatlover' ), NOW ( )) A fun^ao SttAO driptoya£a a senha «a -forma de um todiy» ^ _ de daradteres Hexadedimais, o *y*al t armazinado «a doluna password da tabela mismatdhjASer. A mesma função SHA() trabalha do outro lado da equação do login, verificando se a senha digitada pelo usuário bate com aquela que foi armazenada criptografada no banco de dados. £sta i a s«nha real, na forma dom© -foi digitada «o respedíivo dampo do ío rm irio . U. * * * " F T 00* ' A senha propriamente dita. SHA ('tatlover ') ' f mismatch user uwMUB’ username iÜÜii m 9 dierdre 08447b... 10 baldpaul 230dcb... 11 jnettles ^ S r í d ^ 4 ^ A -fundão SâlA^ transforma a senKa, de 0 daradteres, trr, uma sbri*$ de texto drípto^raíada, donte«do f daradteres. 'e511d793f532dbe0e0483538ell977f7b7c33b2 8 ' £m vez. de armazenarmos a senha d û » ^ dnptogra-fado d t f O daradteres. You are fogged m asjn&tüês
  • 383.
    criando aplicações webpersonalizadas Pcsoriptografando Comparando senhas Uma vez que você tenha criptografado uma determinada informação, o instinto natural é pensar que ela deverá ser descriptografada em algum ponto. Mas a função SHA() é de mão única - ela apenas criptografa, sem poder voltar atrás. Isso foi feito de caso pensado, para preservar a segurança dos dados criptografados - mesmo que um hacker invada o seu banco de dados e roube todas as senhas, ele não conseguirá decodificá- las. Assim, como é possível fazer login do usuário se você não pode decodificar a sua senha? Você não precisa saber a senha original do usuário para saber se ele a digitou corretamente na tela de login. Isso é porque SHA() gera o mesmo código de 40 caracteres, desde que você forneça a ela a mesma string de texto. Assim, você pode simplesmente criptografar a senha digitada pelo usuário e comparar o código resultante com o valor presente na coluna password da tabela mismatch_user. Isso pode ser feito com um consulta SQL, que tenta selecionar a linha referente a um usuário com base na senha. Esta t a senKa digitada pelo ^-usuário para -Pa«r Ologin. AíunçãpSBAO Çoj-nece apenas a o p e ra ç â p c t í p t o g r a f e - n a p e p p s s íV e l Jeoojlíícai: ciados ^ U e te llfc a n i sido c r ip to g r a fa d o s . SELECT * FROM mismatch_user l WHERE password = §§jj('tatlover ' ) f £*ç2o SHAO é tomada para J Criptografar a senha» de modo *w e ela pode aparefier na clausula VVHERfc- Esta consulta SELECT seleciona todas as linhas da tabela mismatch_user cuja coluna password bata com a senha digitada, ’tadover' neste caso. Uma vez que estamos comparando versões criptografadas da senha, não é necessário saber a senha original. Uma consulta para realmente fazer o login do usuário usa SHA (), mas ela precisaria também fazer SELECT na ID do usuário, como veremos em instantes. Abrindo espaço para a senha criptografada A função SHA() apresenta um problema para o Mismatch, uma vez que as senhas criptografadas acabam tendo 40 caracteres de extensão, mas a nossa recém-criada coluna password só armazena até 16 caracteres. Precisamos de um ALTER para ampliar a coluna password, de modo que ela possa armazenar as senhas criptografadas. ALTER TABLE mismatch user CHANGE ® T NDLL 0 ta»anKo da Coluna password t 4 Modvfitado parà*rO> para caberem as ^ senhas Criptogrâíadas. não existem Pel-guntíls idiotas 0 que significa 0acrônimo SHA()? SignificaSecureHashAlgorithm,ou "AlgoritmodeHashSeguro". 0 "hash"éum termousadoemprogramaçãodecomputadores, queserefereaumastringúnica, deextensão fixa, aqual representaindividualm enteum a stringdetexto. NocasodeSHA(), 0hashéa stringdetextocriptografada, com40caracteres hexadecimais, aqual representedeformaúnica asenhaoriginal. Existem outras formas de se criptografar senhas? Sim. OMySQLofereceumaoutra funçãosemelhanteaSHA() chamadaM D5{), queexecutaumtipoparecidodecriptografia. Mas0algoritmoSHA() éconsideradoum poucomaissegurodoqueMD5(), portantoé melhorusarSHA(). 0 PHPtambémoferece funçõesequivalentes(sha1{) emd5()), para0 casodevocêprecisarfazeralgumacriptografia emcódigoPH P, emvezdedentrodeum a consultaSQL você esfá aqui ► 355
  • 384.
    modificando mismatch user TÉ J S T O R ÍV e Adicione as colunas username e password à tabela m ism atchuser, e depois teste-as. Usando alguma ferramenta MySQL, execute a instrução ALTER para adicionar as colunas username e password à tabela mismatchjuser. ALTER TABLE mismatch_user ADD username VARCHAR(32) NOT NULL AFTER user_id, ADD password VARCHAR {16)NOT NULL AFTER username Mas a nossa coluna password precisa ser capaz de conter uma string de 40 caracteres, portanto emita ALTER mais uma vez para abrir um espaço maior para os dados. ALTER TABLE mismatch_user CHANGE password password VARCHAR(40) NOT NULL Agora, para testar as novas colunas, vamos fazer um INSERT de um novo usuário. INSERT INTO mismatch_user (username, password, join__date) VALUES ( 'jimi ' , Para certificar-se de que a senha foi de fato criptografada no banco de dados, dê uma olhada nela, executando um SELECT no novo usuário. SELECT password FROM mismatch user WHERE username = 'jimi' _ , . » — Par l*m login bevn- E, finalmente, você pode simular uma verificação de login fazendo um sucedido, SELECT no nome do usuário e usando a função SHA() com a senha em se,r 3 rr,C S rr‘3 **<^3 uma cláusula WHERE. usada < ua"do sc irvserc d linha- SELECT username FROM mismatch_user WHERE password = l | | | § j (1 heyjoe ' ) Mao sc esy*c$a de iíripiogra+ar a senha, chamando SHAO. í i'heyjoe 1), NOW ( )) IF i l eE d i tWindow H e l o O ü o o s i t e s A t t r a c t
  • 385.
    criando aplicações webpersonalizadas EntSo agora a senha está criptografada, mas ainda precisamos criar um formulário de login. Será que poderíamos simplesmente usar autenticação HTTP, uma vez que ela requer um nome de usuário e uma senha para conceder acesso a páginas protegidas? Sim! A autenticação HTTP certam ente pode ser usada como um sistema simplificado de login dos usuários. Se você se lembrar da aplicação Guitar Wars do capítulo anterior, a autenticação HTTP foi usada para se restringir o acesso a determinadas partes da aplicação, pedindo um nome e uma senha ao usuário. De modo geral, essa é a mesma funcionalidade requerida pelo Mismatch, exceto pelo fato de que agora nós temos um banco de dados inteiro contendo combinações possíveis de nome de usuário/senha, em vez de apenas um nome e uma senha. Os usuários do Mismatch poderiam usar a mesmajanela de autenticação HTTP; porém, cada usuário irá digitar o seu próprio nome e a sua própria senha. Te page,youneed( oi o gi ni òarea' Yóíir passwprd wilí be semr intbe t*ear. S í a m e :■ Password: A janela de au-ten-bcatao HTTP padrao, <ue "tem aparenCia diferente Conforme o navegadorj pode servir Como uma interface de iogin simplificada* você está aqui ► 3 5 7
  • 386.
    autenticação http paramismatch Autorizando usuários com HTTP Como foi mostrado no Guitar Wars, é preciso que sejam enviados dois cabeçalhos para se restringir o acesso a uma determinada página através da janela de autenticação HTTP. Esses cabeçalhos têm o efeito de pedir que o usuário digite um nome e uma senha para obter acesso à página Admin do Guitar Wars. £stes dois eabeçalWos predisa™ sev- enviados para ® iue o atesso a uma pagina seja restrito »»ediante autentitaçao HTTP- header('HTTP/l.1 401 Unauthorized'); header('W W W -Authenticate : Basic realm="Mismatch"'); O envio dos cabeçalhos para autenticação HTTP resulta em duas linhas de código PHP - uma chamada à função header() para cada cabeçalho sendo enviado. — A autentidaçao HTTP requer < ^u e Á «os enviamos dois Este c o reaU da J dabeçalkos. autenticarão,. <ue íerr. eíeito sobre toda a aplicaça©- r H nedessirio digitar um nome e umâ senka para se acessar paginas restritas na aplicaçao Quitar lA/ars. Guitar ;Bekwisalii A sh tO DS im EddieVanil BeBtaC hev PhizI^airsii Toviewthis page, youneedtologiatoarea ' ’^itar'Wars’*onwww;gù)terwars.net ; Vou/ sasaucrd-wi(Jfoe inttir dear! Name; trock f 7.. - - ....i H Remeimber this password in m y keydw in fC a n c e l i NevaJohanaoa 2008-04-2408:02:11 98430 8 ^ , KennyLwfc* 2008-04-23 14:09:5064930 Remove 0 wsuirio só podera ver e usar esta página se -forneier o nome e a senba dorretos. fsc o re sa sn e e d e d .
  • 387.
    criando aplicações webpersonalizadas £is o sòvift At login- Circule as diferentes partes da aplicação Mismatch que sejam impactadas pelo script de login (login.php) e pelo seu uso da autenticação HTTP para controlar o acesso. Em seguida, escreva abaixo de que modo essas partes são afetadas. login.php index.php mismatch__user I l I í l l i S I IfÜ! viewprofile.php editprofile.php você está aqui ► 359
  • 388.
    exercício soiução ftcício S oL u Ç ã o login.php guando umusuário fâz. login, o seu nome e â sua senha são verificados em relação ao Conteudo do banCo de dados, para garantir <y*e pertençam â um usuário registrado- Circule as diferentes partes da aplicação Mismatch que sejam impactadas pelo script de login (login.php) e pelo seu uso da autenticação HTTP para controlar o acesso. Em seguida, escreva abaixo de que modo essas partes são afetadas. A home page nao tem nenhum pape! direto nos logins dos usuários, porque ela precisa ficar acessTvel a todos. A visualização e a ediçao dos perfis ficam restritas, sighifiCândo c^ue apenas os usuários «ue f izerem login poderão acessar essas paginas. £e nao for enContrada uma linha Cujos dados batam com o nome e a senha fornecidos, o sCript de logih e*ibe uma mensagem de erro e impede o acesso. A pagina Editar Perfil nao só utiliza o sCript de login para restringir o acesso, Como também precisa do nome do usuário para determinar <^ual e o perfil c^ue deverá ser editado- nat» existem P: r & r g u n t a s id io t a s Por que não é necessário incluir a home page na exigência de login dos usuários? Porque a home page é o primeiro lugar que o usuário acessa ao visitar o site, e é importante que os visitantes possam olhar o site antes de exigir deles um login. Assim, a home page serve ao mesmo tempo como uma propaganda e um ponto de partida - propaganda para os visitantes e ponto de partida para os usuários registrados, os quais precisam fazer login para acessarem qualquer ponto mais profundo da aplicação. T * * Os usuários logados podem ver o perfil de qualquer outro usuário? Sim. A ideia é que os perfis fiquem visiveis para todos os usuários que fizerem login, mas permaneçam invisíveis aos visitantes não registrados. Em outras palavras, você precisa ser um membro do Mismatch para ver o perfil de outro usuário. 1 • Como a criptografia da senha afeta a autenticação HTTP? Existem duas questões em jogo aqui: transmitir a senha e armazenar a senha. A função SHAQ do MySQL concentra-se em armazenar uma senha, de forma segura e criptografada, no banco de dados. 0 banco não está preocupado com a forma como você transmitiu a senha originalmente, de modo que este tipo de criptografia não tem impacto nenhum sobre a autenticação HTTP. Porém, poder-se-ia argumentar que a criptografia deveria também ser realizada durante a transmissão da senha, quando a janela de autenticação HTTP a submete ao servidor. Esse tipo de criptografia está fora do escopo deste capítulo e, em todo caso, só é necessária quando se está lidando com dados extremamente sensíveis.
  • 389.
    criando aplicações webpersonalizadas Fazendo login dos usuários comautenticação HTTP O script de login (login.php) é responsável por pedir um nome e uma senha do usuário, usando cabeçalhos de autenticação HTTP, por obter os respectivos valores de nome e senha da superglobal $_SERVER, e por verificar se eles batem com os dados contidos em mismatch_user antes de conceder acesso a uma página restrita. <?php Se o nome c a senha nao tiverem sido require once{'connectvars.php' ) ; digitados, CnVie os £abe£alhos dc âutent'£a£3o para pedir que o usuário digite esses dados. if (!isset($_SERVER['PHP_AUTH_USER']) | | !isset($_SERVER[’PHP_AUTH_PW'])> { I / / O nome/senha não foram digitados, portanto, enviar os cabeçalhos de autenticação headers " M’ Mexit(’<h3>Mlsmatch</h3>Desculpe, você deve digitar seu nome e senha para fazer' login e acessar esta página. '); } // Conecta-se ao banco de dados $dbc = mysqli_connect(DB_HOST, DB__USER, DB_PASSWORD, DB_NAME) ; // Obtém os dados de login digitados pelo usuário Ôbtem o nome e a senha distados pelo usuário- // Procura o nome e a senha no banco de dados mm « wdom aqueles if (mysqli_num_rows ($data) -- 1) { dtàrfcados. // 0 login foi bem-sucedido, portanto, definir as variáveis de ID e nome do usuário £e fo r enòontrâda uma l«»ba, *y»if'*a que o login foi bem— sudedido e apodem os definir as variáveis fuser_jd c fusername- else { // 0 nome/senha estão incorretos, portanto, enviar os cabeçalhos de autenticação exit{1<h2>Mismatch</h2>Desculpe,você deve digitarseu nome e senha para fazer! login e acessar esta página.'); // Confirma o login bem-sucedido. Se nenhuma linha no bânio de dados bater dom o nome e a senha digitados, envie novamente os dabedafhos de autentidadao para que o usuário possa tentar outra vez. ?> S . Chegando a este ponto, esta tudo bem, portanto donfirme o login bem-sudedido. Criar unftdVQ ’StíHpTde Login que peça ao usuário para digitar seu nome e senha. você está aqui ► 361
  • 390.
    test drive mismatch OR 1 V E ______________ Crie o novo script de login, e o inclua nos scripts Ver Perfil e Editar Perfil. Crie um arquivo de texto chamado login.php e digite nele o código para o script de login (ou baixe o script no site da Alta Books, www.akabooks.com.br). Em seguida, adicione algum código PHP no início dos scripts viewprofile.php e editprofile.php para incluir o novo script de login. Envie todos os scripts ao seu servidor web, e em seguida, abra a página principal do Mismatch em um navegador. Clique no link Ver Perfil ou Editar Perfil para fazer login e acessar as páginas personalizadas. E claro que isso só funcionará se vocêjá tiver adicionado um usuário, com respectivos nome e senha, ao banco de dados. Estes dois links levam as páginas protegidas, as ^uais dhamam o sdript de login das© o usuário «ao esteja logado- Esta sento é driptcgva£ada to * SttAO c deparada dom aquela presente no banda de dados, para determinar se o login deve ser permitido- ToViewthispage, y»u{ ne«fft ‘Misafatch"onwww.mis-ma raurp a s s w o rd b e$ e n { j^ctearj ♦torté:1. ijnettles 0 sdript de login usa âu ten tid ad âo HTTP para impedir adesso não autorizado as paginas Ver Per-í-il e Editar Períil. A home page nao t protegida pelo sdript de login, mas serve de ponto de partida para se navegar ate níveis mâis profundos da aplidadao
  • 391.
    criando aplicações webpersonalizadas $uaJ^uer página do /Wismatdh c^e predisar exigir login s« predisará indluir ° ^ 'p t login.php no irtidio do seu dódigo- 0 sdript de login e a primeira doisa a ser indlwídâ nos sdripts- Ver Per-Çil e Editar Períil* para proteger as respedtwas páginas. £e o nome e a senha íorew* validos, o usuário e logado, e o restante da página pode ser enviado- Cada usuário redebe a sua própria experiendia personalizada do Mismatdh. Conectar o script de Lftgl-------- - , restante da aplicação Mismatch. você está aqui ► 363
  • 392.
    mismatch precisa deum formulário de cadastro Ruby èdorâ íilmes de tev-v-ov-, vcsolvcr Quebra— dâbcÇâS e tormidâ apimentada, mas neste exato mo»*»e«to, ela odeia o Alismátdh por hão permitir ^ue se fiâdastre e use o sistema- 0 Os usuários novos do Mismatch precisam de uma forma de se cadastrarem . O novo script de login faz um bom trabalho ao usar a autenticação HTTP para permitir que os usuários façam login. O problema é que os usuários não têm nenhuma forma de se cadastrarem - fazer login é difícil quando você ainda nem sequer tem um nome e uma senha. O Mismatch precisa de um formulário de cadastramento, o qual permita que nóvos usuários sejuntem ao site, criando um nome e uma senha para eles. Nome de Usuário? Senha?
  • 393.
    Um formulário paranovos usuários se cadastrarem Como este novo formulário de Cadastro deve ser? Nós sabemos que ele precisa permitir que o usuário digite o nome e a senha desejados... mais alguma coisa? Uma vez que o usuário está estabelecendo a sua senha com o formulário e as senhas em formulários web geralmente são escondidas com asteriscos por motivo de segurança, é uma boa ideia ter dois campos para a senha. Dessa forma, o usuário digita a senha duas vezes, apenas para nos certificarmos de que não houve nenhum erro de digitação. Assim, a tarefa da página de cadastramento é obter o nome e a senha do usuário, certificar- se de que o nome ainda não esteja sendo usado por ninguém, e finalmente adicionar o novo usuário ao banco mismatch_user. criando aplicações web personalizadas WieVhdmc: ( j Password; ruibyr Pâssword: ('rcíyye) ! J $ í*ÿtada d*as ve«s3?ara ^ ------ — ____ J ^— — — ■ 3jud3^ d eíim'mâr--se o rtsdo dc o uswirto de-finir u»a senha mdorretâ para S I . t ciitá r no botao Cadastrar resulta «as aplitações adidionar o nome e 3 senha ao bando de dados. mismatch user l í § í » l l usemam *! password íTTTífyl fiilsife 10 baldpaul d8a011... 11 jnettles e511d7... ip r 12 rubyr 062e4a... Uma vez. que as senhas apora estão driptoÿra+adas, elas esiao securas mesmo ^ue al^uem donsíc^a ver o donteudo do bando. Um problema potencial com o script de cadastro é o usuário tentar se inscrever com um nome que já exista. O script precisa ser esperto o suficiente para capturar esse problema e fazer o usuário digitar um nome diferente. Assim, a tarefa da página de cadastro é obter o nome e a senha do usuário, certificar-se de que o nome ainda não esteja sendo usado por ninguém, e finalmente, adicionar o novo usuário ao banco mismatch user. v o c ê e s tá aqui
  • 394.
    signup.php finalizando Imas deGeladeira dp PHP &My$QL O script de cadastro do MySQL usa um formulário personalizado para pedir ao usuário que escolha o seu nome e senha desejados. O problema é que o script encontra-se incompleto. Use os imas abaixo para finalizá-lo, de modo que novos usuários possam se cadastrar e z' tâdashr, se juntar à comunidade Mismatch. y Êis o •foirmulario àe Mismatch - Sign Up Please enter your username and desired pRegistration Info— I ' U s e rn a m e ; j P a s s w o r d ;jTZT, I Password passwartf to Sign up to Mismatch. (retype): <?php require_once(’appvars.php’); require_once(’connectvars.php1); // Conecta-se ao banco de dados $dbc= mysqli_connect(DB_HOST, DB_USER, DB_PASSWORDf DB__NAME); if (isset($_POST[’submit'I)) { // Obtém os dados do perfil a partir de POST ...............= mysqli_real_escape_string($dbc, trim ($_POST [’ ...............]) ); .................= mysqli_real__escape__string ($dbc, trim($_POST[1............... ’])); ................ = mysqli__real_escape_string {$dbc, trim ($_POST [’ ............... . ’])); if (!empty($username) && !empty($passwordl) && !empty($password2) && ( ............................==.............................)) I // Certif íca-se de que ninguém já tenha se registrado com o mesmo nome $query = "SELECT * FROMmismatch_user WHERE username = 1...............' $data - m y s q l i _ q u e r y ($dbc, $query); if (mysqli_nui7 i_rows ($data) ==0) { //O nome do usuário é único, inserir os dados no banco $query= "INSERT INTO mismatch_user (username, password, join_date) VALUES" . Nao se esqueça vete -tem à th - z t* estape de ^ual^uer apostroío apareça dentvo " ('.............. ;, SHA( ' .......’), NOW { ) ) mysqli_query($dbc, $query); L de ãspâs simples. // Confirme o sucesso com ousuano > » * echo ' <p>A sua conta foi criada com sucesso. Agora você pode fazer login e ' ' <a href=”editprofile.php">editar seu perfil</a>. </p>' ; mysqli_close($dbc); exit( ) ;
  • 395.
    criando aplicações webpersonalizadas else { //Já existe uma conta comeste nome, exibir mensagem de erro. echo 1<p class="error, l >Já existe uma conta com este nome. Por favor, escolha outro. 1 . 'nome.</p>'; _ nn. } } else { echo '<p class='Terror">Você deve digitar todos os dados de login, incluindo a senha ' . 'desej ada duas vezes ,</p>'; } } mysqli_close($dbc); ?> <p>Por favor, digite seu nome de usuário e senha desej ados para se cadastrar no Mismatch.</ P> <form method="post" action="<?php echo $_SERVER [1PHP_SELF’]; ?>"> <fieldset> <legend>Informações de Registro</legend> <label for="username">Kome de Usuário:</label> <input type=',text" id=” ............. " narae=" _ ..... " value="<?php if (!empty(.. ............)) echo ; ?>" / x b r /> <label for=" . . . ........ ">Senha:</label> <input type="..............." id=" ................" name=" ............... V /><br /> ciabel for=".............. ">Senha (digite novamente) :</label> <input type="............ " id="..............." name=M ............... " / x b r /> você está aqui >
  • 396.
    signup.php completo I ma s d e G e l í c l e n < d o P H P & M/SQL - Soluçã® O script de cadastro do M ySQ l usa um formulário personalizado para pedir ao usuário que escolha o seu nome e senha desejados. 0 tis o problema é que o script encontra-se incompleto. Use os imas abaixo -formuláriode para finalizá-lo, de modo que novos usuários possam se cadastrar e J dâdastro- se juntar à comunidade Mismatch. — ▼ <?php req u í r e _ o n c e ('appvars-php'); require__once('connectvars-php'); // Conecte-se ao banco de dados $dbc= mysqli_Connect(DB_HOST, DB_USER, DB__PASSWORD, DB_NAME); Obtenha - t o d o sos dados digitados :mysqli__real_escape_string ($dbc, trim ($_POST [’ i f (isset ($_POST t submit ] ) ) { pelo usuário, prii*eira«*ente- // Obtem os dados do perfil a partir de POST $username $passwordl $password2 Jr=my s q l i__real_escape_s tr ing ($dbc, trim ($_POST [' :mysqli_real_escape_string ($dbc, t r i m ($ _ P O S T [ . if (!empty(Çusernarae) && !empty($passwordl) && !empty($password2) && <, Spasswordl | | $passMoraL B l (4r atytadês sejãm tdcwfcttss* // Certifique-se que ninguém já tenha se registrado com o mesmo nome $usemame ealizí v^a donsulta para ver $data =my s q l i_ query ($dbc, $query) / 'v. sc e*,stem i'mKas batendo dom o if (mySqli_num_rovs ($data> = 0) { ^ dc ^ 0 deitado. $query = "SELECT * FROM mismatch_user WHERE username = //O nome do usuário é único, inserir os dados no banco $query= "INSERT INTO mismatch_user (username, password, join_date) VALUES " . S H A (1 £e não houver nenhunta linha, entao o usuário é novoj entâo $passwordl ^ ,now ( )) , . (í, ,, t ^ ^ P S a das sínhas poderia % e r P f a z e r o ÍNSERT. mysql^querylSdbc, $query>; ar i , « M „£ £ s dev„, // Confirma o sucesso com o u s u á r i o " ’ d“ ‘ tiUs f * «•*»<«« a trtt pont». echo 1<p>A sua conta foi criada com sucesso.Agora você pode fazer login e 1<a href="editprofile.php">editar seu perfil/a>.</p>1; CcM-firma o Lddâskro do mysqli_close($dbc); exit (); g- usuário e f inaliza o siript- }
  • 397.
    else { //Já existeuma conta comeste nome, exibir mensagem de erro echo ’<p ciass="error">Já existe uma conta com este nome.Por favor, esc nome</p>1; Limpa a variável ?user*3me, para <ue o rcspediivo dampo ro •formulário seja esvaziado. 0 nome de w já está sendc eivfcao exibi»* mensagem de 01S 0 { echo 1<pclass="error”>Vocêdeve digitar todos os dados de login, inclu ’ desejada duasvezes.</p>'; A } V Um OUmais dos dámpos do } -formulário e s t ã ovazios, en-fcão mysqli_close ($dbc) / " ibi“ “ “* * * « « ■ ?> <p>Por favor, digite seu usuário e senha desej ados para se cadastrar no Mis <form method="post" action="<?php echo $_SERVER[ 'PHP_SELF’]; ?>"> <fieldset> <legend>Informações de Registro</legend> <label for-"username">Nome de usuário:</label> <input type=”text" id=". value="<?php if (lempty <label for=".: <input type^",, <label for=".. <input type=" |„ id=„ J password! H name=" . |passw0rdlj| /><br /> »Password (retype):</label> id=" I passwords Bina.ni6="> ^^P^sswofd2 /xbr /> </fieldset> <input type="submit" value="Sign Up" name="submit" /> </form> T: existem V&tgimfàs idiotas signup.php Por que não poderíamos simplesmente usar autenticação HTTP para o cadastro de novos usuários? K . * Porque o propósito do script de cadastro não é restringir o acesso a determinadas páginas. A sua tarefa é permitir que o usuário escolha um nome e uma senha, e então adicioná-los ao banco de dados. Certamente é possível usar a janela de autenticação HTTP como formulário de input para o nome e a senha, mas usar a funcionalidade de autenticação apenas para cadastrar um novo usuário seria como usar uma espingarda para matar um mosquito. É melhor criar um formulário personalizado para os cadastros - assim você obterá o benefício da verificação dupla da senha, para se evitar erros de digitação. T:Então o script de cadastro faz login dos usuários depois que eles se cadastram? H : Não. E o motivo tem a ver principalmente com o fato de que o script de login já lida com a tarefa de logar o usuário, portanto não há necessidade de duplicar esse código no script de cadastro. Em vez disso, o script de cadastro apresenta um link para a página Editar Perfil, aonde o usuário presumivelmente desejará ir após se cadastrar. E uma vez que ainda não estará logado, a janela de login lhe será apresentada em resposta à tentativa de acessar a página Editar Perfil. Assim, o script de cadastro leva o usuário até a janela de login através da página Editar Perfil, em vez de fazer o seu login automaticamente. você está aqui ► 369
  • 398.
    criando aplicações webpersonalizadas T fe S T O R fv e Adicione a funcionalidade de cadastro ao Mismatch. Crie um arquivo de texto chamado signup.php e digite nele o código do script de cadastro (ou baixe o script no site da Alta Books, www.altabooks.com.br). Em seguida, modifique o script login.php, adicionando-lhe links para o script de cadastro para os usuários que não conseguirem fazer o login. Envie os scripts ao seu servidor web, e em seguida, abra a página Cadastrar no seu navegador. Cadastre-se como um novo usuário e depois faça login. Em seguida, edite e visualize o seu perfil para confirmar que o cadastro e o login funcionaram corretamente. A aplicação agora tem aquele toque pessoal que estava faltando. A au-fcch-tida&io HTTP e usada para io^ar Ruby to m base *as »»-foirmaçoes «|ue ela íornedeu no seu cadastro.
  • 399.
    mismatch também precisapermitir que os usuários façam logout Eu compartilho um computador com duas colegas de quarto e não gostaria que elas tivessem acesso ao meu perfil do Mismatch. Preciso da capacidade de fazer logout! Os sites de comunidades precisam perm itir que os usuários façam logout, para que os seus dados pessoais não possam ser acessados por terceiros em um computador compartilhado. Permitir que os usuários façam logout pode parecer algo extremamente simples, mas apresenta um problema relativamente sério quando se usa a autenticação HTTP. O problema é que esta serve para ser executada uma vez para uma determinada página ou conjunto de páginas - ela só é resetada quando o navegador é fechado. Em outras palavras, o usuário nunca é "deslogado” de uma página web autenticada via HTTP até que o navegador seja fechado ou que o usuário manualmente finalize a sessão de autenticação HTTP. Esta última opção é mais fácil de executar em alguns navegadores (Firefox, por exemplo) do que em outros (Safari). Umâ ve2- -Peito o loÿ*, vote permâvtcte locado aie íeihav o »ave^ado*- Y o uo r el o g g e dí i t a ss í d n e y k . Mismatch -EditP r o f i l e T$vtçwíthispage,youneedtotogintoarea “fcBsmafc*”<«!ww.m>s-*natchj»et w i ib t i n i h *c l e i r . Firslnam e: S i d n e y L a s tname; FEr^T G ender: jSSfeäi BMidate: [1984-07-19' Mame. sidneyk P a s s w o r d : ! « « » » * City: T im p e State: H Rememberthispasswordinmykeychain Ptenre: U w > veiurso de logout pevmjtiria a Sidh«y ton-kv-olar diAidadosa»ente o atesso ao seu ^erí»! pessoal- Embora a autenticação HTTP apresente uma forma simples e útil de estabelecer os logins dos usuários na aplicação Mismatch, ela não fornece nenhum controle para fazer o logout do usuário. Nós precisamos tanto do recurso de lembrar dos usuários quanto de permitir que eles saiam do sistema quando quiserem. ■970
  • 400.
    criando aplicações webpersonalizadas você está aqui ► 3 7 3
  • 401.
    introduzindo cookies . *, . . ,. Aautenticação Asvezes voce so precisa de um cookie y-jyp O problema originalmente resolvido pela autenticação HTTP tem duas faces: há a questão de se limitar o acesso a certas páginas, e há a questão de lembrar que o usuário digitou informações sobre si mesmo. O segundo problema é o mais complexo, porque ele envolve a capacidade de a aplicação se lembrar de quem o usuário é ao longo de diversas páginas (scripts). O Mismatch resolve essa questão verificando o nome e a senha armazenados na superglobal $_SERVER. Assim, nós podemos tirar proveito do fato de que o PHP armazena o nome e a senha da autenticação HTTP em uma superglobal que persiste ao longo de diversas páginas. armazena dadps persiStentenielite no cliente, mas nã° permite <jue Vpce Q Sapague guando termina de usa-fcs. Tb view this paçe, you r.eod W to area “ Mismatch” òn ttfww.fflis-match.net t o u rp a s s w w d w i i l b es w i t m ' r h e d e a ' .- 1 Mame: sidneyk P a s s w o r d :1 n RememberThispasswordinmykeychain Cancei Asufevjiobal /_ _SERVER [ ’ PHP_AUTH_USER' ] £ÊR/ER a ^ a « ^ f O*o»>e e a senha $_SERVER [ ■PHP_AUTH_PW' ]J W |l i e Mas não podemos mais nos darmos ao luxo de usar a autenticação HTTP, porque ela não tem suporte a logouts. Assim, precisamos procurar outro meio de implementar a persistência do usuário ao longo de diversas páginas. Uma possível solução são os cookies, pedaços de dados armazenados pelo navegador no computador do usuário. Os cookies são bastante parecidos com variáveis PHP, exceto pelo fato de que eles continuam existindo depois que você fecha o navegador, desliga o computador, etc. E o que é mais importante, os cookies podem ser apagados, significando que você pode eliminá-los quando tiver terminado de armazenar dados, por exemplo, quando o usuário indicar que deseja fazer logout. Õs cookies lfce permitem a rm a z e n a r h p c lie n te pequenos pedaços de dados de Çprma persistente, signlíicandp <jue eles ppdem continuai: existindo mesmp depois de Íínalizado o script».. e ppdem também ser ap^gadps a ^ual^uer m o m e n to ! Navegador wêb do cliente Os dados dos cookies são armazenados no computador do usuário pelo seu navegador web. Você tem acesso aos dados através de código PHP, e o cookie é capaz de persistir ao longo não só de várias páginas (scripts), mas até mesmo ao longo de várias sessões do navegador. Assim, fechar o navegador não faz o usuário se deslogar automaticamente do Mismatch. Isso não é problema para nós, porque podemos apagar um cookie a qualquer momento, a partir de código de script, o que toma possível oferecer um recurso de logout. Podemos dar aos usuários controle totalmente sobre em que momento eles querem sair do sistema. Servidor
  • 402.
    criando aplicações webpersonalizadas Po que é feito ocookie? O cookie armazena um único dado, sob um nome único, praticamente da mesma forma que uma variável em PHP. Ao contrário das variáveis, o cookie pode ter um prazo de validade. Quando a data de validade é atingida, ele é destruído. Assim, os cookies não são exatamente imortais - eles apenas vivem por mais tempo do que variáveis PHP. Você pode criar um cookie sem prazo de validade, em cujo caso ele se comporta do mesmojeito que uma variável PHP - é destruído assim que o navegador é fechado. Os cookies lhe permitem armazenar uma string de texto sob um determinado nome, mais ou menos como uma variável de texto PHP. O que torna os cookies tão poderosos é o fato de poderem viver por mais tempo do que os dados de um script, especialmente em situações em que a aplicação consiste de várias páginas que precisam se lembrar de alguns dados, por exemplo, informações de login. precisamos realmente manter a senha, poderia ser dados permaneçam existindo por mais tempo do que mais útil armazenar a ID do usuário em vez disso. uma página (persistência), mas não eternamente. Home O nome único do cookie Valor O valor armazenado no cookie Pata devalidade A data em que o cookie expira... e deixa de existir "perguntas idïçtas não existem ? 1 * Qual é a grande vantagem dos cookies serem persistentes? Os dados armazenados em um banco de dados MySQL não são também persistentes? Dcíihiy o prâzo de vaiidade de um $uândo voe« *3© dookic tom uma dãtã bâstâhte -fuiuvâ ajuda a -barná-lo mais permanente. •Çorneôe ftCrtHu» de vâlidadcj o tockit e apagado assim que o navegador fo r Sim, os dados de um banco certamente são persistentes. Na verdade, são tecnicamente muito mais persistentes do que um cookie, porque não há nenhum prazo de validade envolvido - depois que você coloca dados em um banco, eles ficam lá até que você os remova explicitamente. A questão real, no que se refere aos cookies e a persistência é a conveniência. Nós não precisamos armazenar para sempre a ID atual ou o nome do usuário só para permitir que ele acesse seu perfil; só precisamos de uma forma rápida de saber quem ele é. 0 que realmente precisamos é de persistência temporária, o que pode parecer paradoxal até você considerar o fato de que precisamos que os fedKado. Assim, o Mismatch pode imitar a persistência fornecida pela superglobal $_SERVER configurando dois cookies - um para o nome do usuário e outro para a senha. Mas nós não você está aqui ► 375
  • 403.
    A função setcookieQ Usecookies corn PHP O PHP fornece acesso a cookies através de uma função chamada setcookie() e uma superglobal chamada $_COOKIE. A função setcookie() é usada para se definir o valor e a data de validade (opcional) de um cookie, e a superglobal $_COOKIE é usada para se obter o valor de um cookie. setcookie('username' , 'sidneykT); ......... * ô pvimeivo J para srfôookieO é o naw »e do Cookie 0 valor a s«- ado *o tooki« t passado to *° o secundo âr<y*»netïfco' echo(’ <p class="login">Você está logado como ’.</p>’); 0 nom e do ôookic t wtâdo para re-IWcniiav' o seu y/aiov na supcrjlobâl f_COO£i£. A vantagem de se definir um cookie é que os seus dados persistem ao longo de vários scripts, portanto nós podemos nos lembrar do nome do usuário sem ter de pedir que ele o informe a cada vez que passar de uma página para outra na aplicação. Mas não se esqueça, precisamos armazenar a ID do usuário em um cookie, uma vez que ela serve de chave primária para consultas ao banco de dados. ■p i A função s e tc o o la e Q J o PB? iLe permite a rm a z e n a r d a c fe s e m c o o k ie s * s e t c o o k ie ( ’ u s e r _ id 0s tookies são sewfre arma^^ados tomo áe modo ^*e, w*csmo *ue a iP do usuário seja u» numero^ v > c & a avwaz^namos e» u w » dookie l<mo a stvín^ j . A função setcookie 0 também aceita um terceiro argumento opcional, o qual define o pra2o de validade do cookie, que é a data na qual este é automaticamente apagado. Se você não especificar um prazo de validade, como no exemplo acima, o cookie expira automaticamente assim que o navegador for fechado.
  • 404.
    criando aplicações webpersonalizadas Aponte seu lápis Ajustar o Mismatch para usar cookies envolve mais do que apenas escrever um novo script de logout. Primeiramente, nós temos de rever o script de login e modificá-lo para usar cookies em vez da autenticação HTTP. Circule e comente as partes do código de login que você acha que precisa modificar para acomodar os cookies. <?php requíre__once ( 'connectvars -php'); if (!is-set ($_J3ERVER[ 'PHP_AUTH_USER' ]) ] [ !isset ($_SERVER[ 'PHP_AUTH_PW' J)} { / / O nome/senha não foram digitados, portanto enviar os cabeçalhos de autenticação header(1HTTP/l.1 401 Unauthorized'); header('WWW-Authenticate: Basic realm="Mismatch" 1); exit{1<h3>Mismatch</h3>Desculpe, você deve digitar seu nome e senha para fazer’, 'login e acessar esta página. Se ainda não for um usuário registrado, por favor'. ’<a href="signup.php">cadastre-se</a>.'); // Conecta-se ao banco de dados $dbc = mysqli_connect(DB_H0ST, DB_USER, DB_PASSWORD, DB__NAME); // Obtém os dados de login digitados pelo usuário $user_username = mysqli_real_escape__string($dbc, trim($_SERVER['PHP_AUTH USER’])); $userp a s s w o r d = mysqli_real_escape_string($dbc, trim($_SERVER['PHP_AUTH_PW'])); // Procura o nome e a senha no banco de dados $query = "SELECT user_id, username FROM mismatch_user WHERE username = " . "'$user_usernaine' AND password = SHA('$user_password' )"; $data = mysqli_query($dbc, $query); if (mysqli_num_rows($data) == 1) { // O login foi bem-sucedido, portanto definir as variáveis de ID e nome do usuário $row = mysqli_fetch_array($data); $user_id = $row[’user_id']; Çusername = $row['username’]; else { // O nome/senha estio incorretos, portanto enviar os cabeçalhos de autenticação header('HTTP/l.1 401 Unauthorised'); header (’WWM-Authenticate: Basic realm="Mismatch"1); exit('<h2>Mismatch</h2>Desculpe, você deve digitar um nome e '. 'senha válidos 'para fa2er login e acessar esta página'. 'Se ainda não for um usuário registrado, por favor,'. '<a href="signup.php”>cadastre-se</a>.'); // Confirma o login bem-sucedido. echo(’<p class="login">Você está logado como ' . ?> headers lo g in .p h p você está aqui ► 3 7 7
  • 405.
    aponte seu lápissolução .ponte seu lápis Solupão Ajustar o Mismatch para usar cookies envolve mais do que apenas escrever um novo script de logout. Primeiramente, nós temos de rever o script de login e modificá-lo para usar cookies em vez da autenticação HTTP. Circule e comente as partes do código de login que você acha que precisa modificar para acomodar os cookies. <?php *quire_once('connectvars.php' ) Kós predisamos veriíidar a e*istendia de um dookie para ver se o usuário está locado ou nao. Em vez. de obter o nome e a senha a partir de umajanela de autentifia^a©» pretisâm os usar u» -formulário C omdados POST. ' SERVER[’PHP AUTH USER’]} /senha náo toram c t j . c r if a r i r f S * : [I !isset($_SERVER[1PHP_AUTH_PW'])) '.uuii r am o enviar oa cabêCcilEiôè üê autenticação header (’HTTP/l.1 401 Unauthorize ^-Authenticate: Basic realm^'Mismatch"'); - . L . 5 - 4 “ i-Lsmatch</h3>Desciilpe, você deve diyiLaL seu nome e senha para fazer : esta página. Se ainda não for um usuário registrado, por favor', "signup.php">cadastre-se</a>.'); Nao precisamos mais enviar dabeçalhos de autenticarão HTTP. // Conecta-se ao banco de dados $dbc = mysqli__connect (DB_HOST, DB_USER, DB PASSWORD, DB NAME) // Obtém os dados de login digitados pelo usuário $user_username = mysqli_real_escape_string($dbc, tri $user^password - mysqli_real_escape string($dbc, tri. í ($_SERVER['PHP_AUTH_USER' ] )’ ($ SERVER['PHP AUTH PW'])); // Procura o nome e a senha no banco de dados $query = "SELECT user^id, username FROM mismatch_user WHERE username = "'$user_username' AND password = SHA('$user password')"; $data = mysqli_query ($dbc, $query); A Consulta nao predisa se modi-fidar em nada^ if (mysqli_num_rows($data) — 1) „ // 0 login foi bem-sucedido, portanto definir as variáveis de ID e nome do usuário $row - mvsali fetch array($data); C ?user_id - $row {'user_id1] ; $username = $row[ 'username' ] s else J J O nome/^pnha estão incorretos, portanto enviar os cabeçalho* header(’HTTP/1.1 401 Unauthorized1); v^^eader ('WWW-Authenticate : Basic realm="Mismatch"' ) ? e x i H '' - l i 2 >Mj.am, atch</hZ>Uesdaigiê, voce deve digital TUlL'nome e 'senha válidos 'para fazer login e acessar esta página'. 'Se ainda não for um usuário registrado, por favor, ’<a href="signup.php">cadastre-se</a>.1); A«ui nós te»*« de deíinir dois tookies, e» vez. de deíinir variaveis do sdript i s de autenticacao headers // Confirma o login bem-sucedido. echo(1<p class="login, l >Você está logado como ' . Çusername . '.</p>'); Uma vez. *^u e nao irernps usar ajanela de autentidaçao HTTP para diytaçao do nome t da senha, temos de driar um íormulário de lo^in HTML- para o usuário -Pomcder essas informâdoes. lo g in .p h p
  • 406.
    criando aplicações webpersonalizadas Repensando o fluxo dos logins Usar cookies em vez de autenticação HTTP para os logins do Mismatch envolve mais do que apenas repensar o armazenamento dos dados dos usuários. E quanto à interface do login? O login baseado em cookies precisará fornecer o seu próprio formulário, uma vez que não poderá usar ajanela de autenticação para a digitação de nome e senha. Nós não só precisamos criar esse formulário, como também temos de pensar em como ele modifica o fluxo da aplicação, à medida que os usuários fazem login e acessam outras páginas. Um novo -formulário de l©gm tomS o iugar da janela de autentidaçao HTTP para a dityiacao do nome e da senha- Mismatch - Where opposites attract! •LssJn ■ ► s ig a ü R Latestmakers: % ■ f t 1 £ ' A 'V . Clidar no novo link *L03 fn” leva a pagina de login, onde o usuário pode digitar as su3s m-íormâí-oes para donedtar-se ao sistema #i*ando o usuário não está logado, os membros mais index.php redentes sao mostrados domo homes estátidos. u sernamer Password-- [ * * * * & £ [ j ^ n Após íaz^r login Cct* sudesso, o usuário e rediredionado para a Kome page, onde o menu agora revela <ue ele esta logado. M hm stch * W hoe opposites attract! V LogOut(skfaevkl 0 sdripi de logout íidâ ddessivel atraves de um link ^ue íâz- parte do status de logout- $s paginas restritas agora estão adessíveis, uma vez.<ue ° usuário está logado- 0 menu de navegaçao príndipal indlui um link Log Oui « ^u e mostra tambem o nome do usuário logado. Afos o login, os nomes dos membros mais redentes se trans-formâm em links para os seus respedtivos per-m. viewprofile.php você está aqui ► 379
  • 407.
    login.php —agora comcookie Vut login baseado ew cookies A nova versão do script de login, que usa cookies para implementar a persistência, é um pouco mais complexa do que a sua predecessora, uma vez que ela precisa fornecer o seu p ró p rio fo rm u lá rio p ara a d ig itação d o n o m e d o usu ário e da senha. Mas é também mais poderosa, uma vez que oferece a funcionalidade de logout. <?php k A ** require once ('connectvars.php 1); mCfisajCftS Ot Crvo â^OTS SâO armaz<»adas e**uma variável e exibidas, // Limpa a mensagem de e r r c i ^ ^ ^gsslrio, »ais adiânt« «O Séript- :$erxox_.msg’ = ' C ' — — , , , „ , . . /eri-(We o tockt userjd ?ara Se q usuariQ .nao es.tiver. Ipgaçio, tenta fazer o logm v i , t^ « _i - - se o usuari©esta locado- login.p £is e «ovo -formulário de io<ÿ*. I if (!isset {:£^qx>KiEj ’ V£V ifV(isset {S^POSTi;1submit1 1 J5 // Conecta-se ao banco de dados Se o usuário «ao estiver iodado, verificar se ele submeteu dados de lo^in. $dbc = mysqli_connect(DB_HOST, DEMJSER, DB_PASSWORD, DB_NAME); // Obtém os dados de login digitados pelo usuário . . . $ u se r_ u se r n a m e = m y s q li_ r e a l_ e s c a p e _ s t r in g { $ d b c , tri^ $^ E iQ S Í;r.'!üSernam e 1] ) ) ; $ u s e r _ p a ssw o r d = m y s q li_ r e a l_ e s c a p e _ s t r in g ( $ d b c , trim l^ ^ ^ fer^ p às^ W ord ''* ] } ) ; { if (!empty($user_username) && !empty ($user_password)) // Procura o nome e a senha no banco de dados $query = "SELECT user_id, username FROM mismatchjjser WHERE username = ••password - SHA('Çu«rj,a,s„ord')-; ftl» « » * < • $ d a ta = m y s q li q u e r y ($ d b c , $ q u ery ) ; a ? * J n a^ora vem de P0ST, e *3o de um a if (mysqli_num_rows ($data) = = 1 ) { i^elâ d c a u t c n t i ^ â O / / O login foi bem-sucedido, portanto definir os cooKles de ID e nome do usuário e redirecionar para a home page $row - mysqli fetch_array ($data) ; ^Fâáa loAin do usuirío dfíinmdo •- - seteopkiél^sèítági^^ -Çhpíae'.nrl ■ is ípindèx .php'* ■ h e á c ^ r f t L o G a t i o n ; , ; ■ ' *s Redirefiiow: o usuário para ilse{ ^'■~~^a bome fa^e do Mismâttb // 0 nome/senha estão incorretos, portanto definir uma mensqjj^gg Su£edido- rric^rr — 1Hq c í-/~ < i11 ^-í rrS i-a v irm ri/'-vmA o ■conVi 3 Tr^l r^a ‘7tz>Y%1r v n n * í os Ûookies user_id e user«ame. Çsrror msg = } else válidos para fazer login. // 0 nome/senha não foram digitados, portanto definir uma mensagem de $error_msg = ’Desculpe, você deve digitar seu nome e senha para fazer login <html> <head> <title>Mismatch - Log In</title> <link rel=”stylesheet" type="text/css" href-"style.ess" /> </head> <body> <h3>Mismatch - Log In</h3>do«tmua n âpagina d iâd Deíi*a a variável da mensagem de erro c a s o aígo esteja errado dom os dados de login. 0 sírift de login agora e k um a ’ «eb tomfWa pertânto de requer todos os demente* HTML padrões-
  • 408.
    criando aplicações webpersonalizadas / / Se o c o o k ie e s t i v e r v a z io , e x i b i r m ensagem de e r r o (s e h o u v er) e o fo r m u lá r io d e lo g in ; c a s o c o n t r á r io , c o n fir m a r lo g i n r^/^v4ii3ifiiííííuíil«llll^lí»ííiií£íí2ffiilfíiy-'1 •: ■ <?php ?> <form m eth o d = " p o st" a c tio n = " < ? p h p e ch o $ _ S E R V E R [ 1PHP_SELFV < f i e l d s e t > < ieg en d > L o g I n < /le g e n d > < la b e l for="u sernam e">N om e d e U s u á r i o : < /la b e l> yiimli Sc o usuário âmdá r is o estiver logado «este ponto» exibir 3 »ervagem de erro. ?>"> <ííiput;.,Í "text value="', <?php , i ' f . (^user^uSerngmi lisé-Enáme;. ; '/X fe r . /> < la b e l fo r = " p a ss w o r d " > S e n h a :< /la b e l> ■ <input':;tiype=‘'pás.éwèrd'?''.V.................. < / f Í : e ld s 'e t> '.... < in p u t ty p e= " su b m it" v a lu e = " L o g In" nam e=" sub m it" /> Tudo ^ue ven» antes desta dhave ainda <?php ^ parte da primeira dáusula ií e l s e f ■ //■ C o n firm a ■o la g ijír echoi’< p cÍass=*l^fi3?f:K Estes dois dampos do •formulário s3o usados para o usuirio digitar o n o m eea senha. r < /b od y> < /h tm l> Finalize o óódigo HTAIL para dompietar a página web de logm. P:Por que é necessário armazenar tanto a ID quanto o nome do usuário em cookies? í { l Uma vez que essas duas informações identificam individualmente os usuários dentro do banco de dados do Mismatch, você poderia usar apenas uma das duas como propósito de manter a aplicação sabendo queméo usuário logado. Porém, userjd é uma referência melhor (mais eficiente) noque diz respeito ao bancode dados, porque é uma chave primária numérica. Por outro lado, userjd é pouco informativa e nãotem nenhumsignificado para o usuário, portanto o username éútil para o usuário saber que está logado, pois ele vê o seu próprio nome na página. Uma vez queocorre de várias pessoas compartilharem o mesmo computador, é importante nãosó existem P e r g u n t a s i d i o t a s informar ao usuário que ele está logado, mas tambémqual é o nome que está logado. - Então por que não armazenar também a senha em um cookie, como parte dos dados de login? f^lAsenha só é importante para verificar inicialmente se o usuário realmente é quemelediz ser. Uma vezque o processo de login verifica a senha, não há motivo para mantê- laemjogo. Além disso, senhas são dados muito sensíveis, portanto é uma boa ideia evitar armazená- las temporariamente sempre que possível. Se o usuário estiver locado neste ponto, informe-o disso. - Parece que o formulário do script de login está dentro da declaração if? Isso é possível? l l Sim. Na verdade, é bem comumver código PHP "dividido" emtorno de código HMTL, como acontece no script de login. Só porque você fechou uma seção de código PHP com?>, não quer dizer que a íógica do código está fechada. Quando você abre ouíra seção de código PHP com <?php, a lógica continua exatamente de onde parou. No script de login, oformulário HTML é contido dentro da primeira ramificação de if, enquanto que a ramificação else aparece depois do código do formulário. Dividir código PHP comcódigo HTML, desta forma, evita que você tenha de gerar oformulário comummonte de instruções echo confusas. você está aqui ► 3 8 1
  • 409.
    menu dinâmico domismatch Navegando na aplicação Mismatch O novo script de login modifica o fluxo da aplicação Mismatch, passando a requerer um menu simples que apareça na home page (index.php).Esse menu é importante porque fo rn e c e acesso às d ife re n te s p artes p rin cip ais d a ap lica çã o , atualmente as páginas Ver Perfil e Editar Perfil, bem como a possibilidade de os usuários fazerem login, se cadastrarem e fazerem logoiit, dependendo dos seus estados de login atuais. O fato de que o menu se modifica com base no estado de login do usuário é significativo, e em última análise, é o que dá ao menu o seu poder e a sua utilidade. Bsie menu afâveíc guando o usuário nao csbá locado, dando a eíe a oportunidade de íâzcr ío^tn ou se £adastvar Uïn menu di-kv-ente t **orbrado defendendo de se o dookie username está de-finido ou ndo- 0 sdirípt indcíC. pH p sabe < ^ u e deve mostrâr o raçnu imitado guando nio donseguir endontrav o dookie uscvname. O menu é gerado por código PHP dentro do script index.php, e esse código usa a superglobal $_COOKIE para procurar o cookie username e ver se o usuário está logado ou não. O cookie com a ID do usuário poderia também ter sido usado, mas como o nome do usuário é o mostrado no menu, faz mais sentido usá-lo.
  • 410.
    criando aplicações webpersonalizadas ^Stanatch • ................ I* yicwj'iufhj " -;.. ";■:'k~ /;v ' : - v i r - - '--a I ^ rj<iiiJ'-:,'.:.K: ■ ■ ' : . : ^ x .rr^ -^ V ^ iS V .; r u ~ ° ^ ,jr~ ^ Latestmembers: ; ’! 'y :^»"‘. ■ ' ■>' s : / W í - s ^ - S S B sE s . . . .„. . I ...' ^toolcfç .,.■ .;■ ?j ■ ;yl_' uséráâfoe ■ ;■ ■ v> . ■.•■'ytem'pii':."■r." kjafc. :•• -n ..:•//» .' j « l i r £) dookic user__id r»3o e usado pelos di£ere»vfc«s »Cnus, »»as ãmdâ t importante parâ â persistentia do usuário no M»s»*at£b. user id = Ô tookie determina <ua! menu é exibido { / u s e r n a m e — s i d n e y k /v |eY » v »para usuirios locados. _____. ü ) ) ’&I10084; <a href="viewprofile.php">Ver Perfil<Vaxbr />'; '&#10084; <a href="editprofile .php">Editar PerttrK/aXbr />’; ’&#10084 ; <a href="logout. php">Log Out ( ' . username' 3 . // Gera o menu de navegação if ( isset ($■COÓKíE r*~ echo echo echo ')</a>1; } else { echo ’&#10084; <a href="login.php">Log In</a><br /> echo 1&.#10084; <a href="signup .php">Cadastrar-se</a> 11 Os símbolos de doradoeziftbosjio lado de £âda item do menu sSo , — possibilitados por este dod'130 HTML, < ^ u e é suportado nâ maioria dos navegadores- Menu para visitantes íusuários ainda «ao !o$ados). você está aqui > 3 8 3
  • 411.
    log out deusuários deletando cookies O Oi, lembra de mim? Eu realmente, realmente ainda preciso fazer logout. a N ó s realm ente p re cisam o s perm itir que o s u suários façam logout. Os cookies facilitaram o login e a navegação no Mismatch, mas o nosso propósito inteiro, ao mudarmos da autenticação HTTP para os cookies, era permitir aos usuários fazerem logout. Nós precisamos de um novo script de logout que apague os dois cookies (user ID e username), para que o usuário não mais tenha acesso à aplicação. Isso impede que alguém use o mesmo computador mais tarde e acesse os dados privados do usuário. Uma vez que não há nenhum componente de interface de usuário envolvido na operação de logout, basta redirecionar o usuário para a home page após o logout. ' t Sidney âindâ está esperâttd© pelo logout- ô script de logout apa^a os cookks de io^m do usuário e redíretíons pava a W e page. % logout.php
  • 412.
    criando aplicações webpersonalizadas Fazer logout significa apagar cookies Fazer o logout de um usuário envolve apagar os dois cookies que mantêm registro do usuário. Isso é feito chamando-se a função setcookie(), e passando-se a ela uma data de validade que faça os cookies serem apagados na data em questão. setcookie(1username1 Ahov a a tw l S n m ic s rtoras S ' * 8}) ; — V " Este código define um prazo de validade de 8 horas no futuro, o que significa que o cookie será automaticamente apagado 8 horas depois da hora atual. Mas nós queremos apagar o cookie imediatamente, o que requer a definição do prazo de validade para um momento no passado. Quanto tempo no passado não importa muito - basta escolher um espaço de tempo qualquer, digamos uma hora e subtraí-lo da hora atual. setcookie(’username 1, 'sidneyk', l>0 segundos ^ ^0 minutos ~ ^ 0 0 segundos, o da ur»a Hora no passado. £sta expressão de-f»*€ um pra*o d« validade < ^u e v e 3 horas apo* a hora atual Yara apagai* um c o o k ie , b a s ta definir 9 seu pta^P de validade como mntempo hp passado. Estão faltando algumas partes do código do script de logout do Mismatch. Escreva o código que está faltando, certificando-se de apagar os cookies antes da página de logout ser redirecionada para a home page. < ?p h p / / Se o u s u á r io e s t i v e r lo g a d o , a p a g a r o c o o k ie p a r a f a z e r o l o g o u t i f ( ) {■ / / A p aga o s c o o k i e s u s e r ID e u se r n a m e , d e f i n i n d o o s s e u s p r a z o s d e v a lid a d e com o uma h o r a a t r á s (3 6 0 0 ) } / / R e d ir e c io n a p a r a a hom e p a g e $ h o m e_ u rl = ' h t t p : / / ’ . $_SERVER[ 1HTTP_HOST'] . d irn am e($_S E R V E R [ ' PHP_SELF' ] ) . í T* h e a d e r ( ' L o c a t i o n : ' . $ h o m e _ u r l); ?> você está aqui ► 385
  • 413.
    o script completologoutphp Estão faltando algumas partes do código do script de logout do Mismatch. Escreva o código que está faltando, certificando-se de apagar os cookies antes da página de logout ser redirecionada para a home page. * S o L u Ç ã o , * usudVio se este à ^?p p estiver iodado- // Se ousuário estiver logado, apagar o cookie para fazer o logout t if (isset(f_C00^|£rusev_icn) ) { // Apaga os cookies user ID e username, definindo os seus prazos de validade como - UOO); Defwe t i i i tookie í^ o vwttndo - J W a I Rcdiredioftá para a Kom c paje do É /V]is»«aidK, ^we c L o n sb rw à èto m o un»a URL absoluta. Redireciona para a home page ome_url = 'http://' . $__SERVER['K T T P _ H O S T '] . dirname($_SERVER['PHP_SELF']) . nde*.pKp 1; header {' Location: ' . $home_url) ; ^ ^bcÇaibo d co U W zX $ oWSulta em o ?> navegador redírtóofcâr para outrâ página* — ____T f e S T O R f V G -------------------------------- U se co ok ie s para adicionar a funcionalidade de logout ao M ism atch. Modifique os scripts do Mismatch para que eles usem cookies para permitir que os usuários façam login e logout (ou baixe os scripts do site da Alta Books, www.altabooks. com.br). Deverão ser feitas modificações nos scripts index.php, login.php, logout.php, editprofile.php e viewprofile.php. As modificações nos dois últimos são poucas e envolvem principalmente modificar as referências das variáveis globais $userjd e $username para que elas passem a usar a superglobal $_COOKIE. Envie os scripts para o seu servidor web e depois abra a página principal do Mismatch (index.php) em um navegador web. Tome nota do menu de navegação e depois clique no link ”Log In" para entrar no sistema. Repare em como o script de login leva você de volta à página principal, enquanto que o menu se modifica para refletir o seu status de logado. Agora clique em "Log Out" para pulverizar os cookies e sair do sistema.
  • 414.
    criando aplicações webpersonalizadas Ou dookies sâo íriâdos para Os tookies sâ« jogados íora para «y*eaaplitaçao*e es^ueta do usuário e íaça o logout na» existem __r»cy esta ioníí«ie porque agora ela pode íâzír logout e ler fierteza de gue o seu períil do /V fuaw atfiH Petrurrtas Ídipías ^ H®»w v * ” H ní & enquanto ela estiver Wâ- 1 Então tudo o que é preciso fazer para o logout éapagar os cookies? Sim. Os cookies são responsáveis por armazenar todas as informações de login do Mismatch (IDe nome do usuário), de modo que apagá-los resulta emumlogout completo. T * * Por que os cookies são definidos como vencendo uma hora atrás, para serem apagados? Existe aigo significativo sobre o espaço de tempo de uma hora? Não. Ocookie éautomaticamente apagado pelo navegador assimque oseu prazo de validade vence. Assim, aoperação de apagar umcookie imediatamente exige que se defina o prazo de validade como vencendo emalgummomento do passado. Uma hora (3600 segundos) é apenas umespaço de tempo arbitrário, escolhido para indicar consistentemente que estamos apagando umcookie. você está aqui ► 387
  • 415.
    armazenando dados dousuário no servidor; ao invés no cliente Bsfce Co uSu3vio do ATtsm âtfiH Jasoh, f í dc estaladas, dc picrd‘ m$s e de ttoward Slcvn- £!c dcsabiirb* os dookies «o seu navegador, o <ue reprcsewta «rr. ^voklcmâ pavâ Oh-oh. Eu tenho os cookies desabilítados no meu navegador e não consigo fazer fogin. E agora, o que faço? Umâ vez. < ^ w Co sí-ockies estâo dcsabiivtados, o sdrípl -falKa t simplesmente e*v>a u ss/3v*o dc vol-fca 3 Ho»«€ sc»* -fasev o logjm* 0 «ave^adov rejei-fca os dookies, pedindo <ue o sdHpi dc loai* os deW ^ 0 sevvidor 'teftla definir os dookies de !P e dc r)o»e do uswáno no «ave^ador- Quem se importa com o Jason? Não é verdade que a maioria das pessoas tem os cookies habilitados? Sim , m a s a s a p lica çõ e s w eb devem se r o m ais a c e ssív e is ao m aior núm ero de p e sso a s possível. Algumas pessoas simplesmente não se sentem àvontade para usar cookies, então elas optam pela segurança de desabilitá-los. Sabendo disso, vale a pena tentar acomodar os usuários que não terão a opção de usar cookies para o login. Mas tem mais: acontece que há outra opção que usa o servidor para armazenar os dados de login, em vez de usar o cliente. E umavez que os nossos scriptsjá estão rodando no servidor, faz sentido armazenar também dados de login nele.
  • 416.
    criando aplicações webpersonalizadas As sessões não dependem do cliente Os cookies são coisinhas poderosas, mas têm as suas limitações, como por exemplo, ficarem sujeitos a limitações que vão além do seu controle. Mas e se não tivéssemos de depender do navegador? E se pudéssemos armazenar dados diretamente no servidor? As sessões fazemjustamente isso, e lhe permitem armazenar pedaços individuais de informações da mesma forma que os cookies, mas os dados são armazenados no servidor em vez de no cliente. Isso coloca os dados das sessões fora dos limites impostos pelo navegador aos cookies. As sesspes ljie p e rm ite m a rm a z e n a r persistentemente p e^ u en P S pedaços cie dadPS np serYidpr, Independentemente dp cliente. Servid or w eb Armazena dados em cookies Ao tm brèrio dos Êookies, ôs sessões a r m a o s seus dados n© servidor. Obtém dados a partir de c o o k ie s 0 navegador nao ifcteríere d ire ta ^ te na armaz^agem dos dados de sess3es> uma vez. tudo íifiano servidor. As sessões armazenam dados em variáveis de sessão, que são os equivalentes lógicos dos cookies no servidor. Quando você coloca dados em uma variável de sessão usando código PHP, eles são armazenados no servidor. Você pode então acessar os dados na variável de sessão a partir de código PHP, e eles continuam persistentes ao longo de várias páginas (scripts).Como no caso dos cookies, você pode apagar uma variável de sessão a qualquer momento, o que nos possibilita continuarmos a oferecer o recurso de logout com código baseado em sessões. Certamente existe alguma desvantagem, certo? Mais ou menos. Ao contrário dos cookies, as sessões não oferecem tanto controle sobre o tempo durante o qual a variável de sessão armazenará os dados. Asvariáveis de sessão são automaticamente destruídas assim que a sessão termina, o que em geral, coincide com o ato de o usuário fechar o navegador. Assim, embora as variáveis de sessão não sejam armazenadas no navegador, elas são afetadas indiretamente por ele, uma vez que são apagadas quando a sessão do navegar finaliza. N avegador w eb do cliente Uma Vez*<JuePs dadps de sesspes sâp armazenados np serVidpr, eles sãp ma!s seffurps e mais cpníiáVefs dp c[ue dadps armazenadps em cookfes. 0 usuirio hão e fiapaz. de apagar dados de sessões **a*ualme»-fce tom o seu have9adorJ ® ^ue pode ser w* problema ^ua»do se usam cookies. Kao bá um praz« de validade assodiado tom as variáveis de sessão, porque elas são automaticamente apagadas guando a sessão termina- você está aqui ► 389
  • 417.
    as funções sessionjstart{)e sessfon destroyQ A vida e a obra das sessões As sessões recebem esse nome por um motivo —elas têm um início e um fim muito claros. Os dados associad os co m u m a sessão vivem e morrem de acordo com o tempo de vida da sessão, o qual você controla através de código PHP. Aúnica situação em que você não tem controle do ciclo de vida da sessão é quando o usuário fecha o navegador, o que resulta no fim da sessão, quer você goste disso ou não. Você precisa informar à sessão quando estiver ponto para iniciá-la, chamando a função PHP session_start(). A Çunção PHP sessíP tL -S târtO toída u m a se sse b e p e rm ite C[ueVç>cecomece a a rm a z e n a r d a d o s e m VaríaVels da sessão session_start () ; — tsfca -Çu^ao PH? } 0 3 u»a sessão Servidor web Chamar a função session_start() não define quaisquer dados - a tarefa dela é apenas iniciar a sessão. A sessão é identificada internamente por uma ID individual, com a qual você geralmente não precisa se preocupar. Essa ID é usada pelo navegador para associar uma sessão com diversas páginas. £sta é a IP da sessão, *^ u e e gerada automaticamente domo ^arte de C è d â nova sessa». 'ndex^pnpj ^uâhdo uma sessão e ihidiadâ, ur»a IP e deíinida para identi-í-ifia-la individualmente. N avegad or w eb do cliente A IP da sessão e usada no$ bastidores para permitir «ue diversas fainas òompartilbem o acesso âos dados da sessão- viewprofile.php editprofile.php AID não é destruída até que a sessão seja finalizada, o que acontece ou quando o navegador é fechado ou quando você chama a função session_destroy(). session destroy(); Bsiâ -funÇâo PffP -íinâlizj lAtnã sessêo. A íunçãp sessi9n_ desfro/O îînalîza a sessão- Quando você fecha uma sessão com esta função, ela não destrói automaticamente quaisquer variáveis de sessão que você tenha armazenado. Vamos dar uma olhada com mais detalhes no modo como as sessões armazenam dados, para descobrir por que isso acontece.
  • 418.
    criando aplicações webpersonalizadas Mantendo-se atualizado com os dados das sessões ú nome da variável da sessãoJ e usado tomo um índifie para s superglobal /_S£££Í0N'.., O legal sobre as sessões é que elas sãobastante semelhantes aos cookies, em termos de comovocê asusa. Umaveziniciadauma sessão com uma chamada a session_start(), você pode começar a definir asvariáveis, como por exemplo os dados de login do Mismatch, com a superglobal $_SESSION. ’sidneyJc’ 0 valor a ser armazenado e apenas atribuído a superglobal f_SÊSSÍ0K echo ( '<p class="login">Você está logado c c a t i o '.</p>') ; Ao contrário dos cookies, as variáveis de sessão não requerem nenhum tipo de função especial para defini-las - basta atribuir um valor à superglobal $_SESSION, certificando-se de usar o nome da variável como o índice do array. E quanto a apagar asvariáveis de sessão? Finalizar a sessão através de session_destroy() não destrói as suas variáveis, portanto, você precisa apagá-las manualmente se quiser que elas sejam eliminadas antes de o usuário fechar o navegador (logout!).Uma forma rápida e eficiente de destruir todas asvariáveis de uma sessão é definir a superglobal $ SESSION como um arrayvazio. A variável da sessão e driada t art*a«nada no servidor- $_SESSION = array(); fiódijo elimina -todas as variáveis da sessão atual. Mas isso ainda não é tudo. As sessões podem usar cookies nos bastidores. Se o navegador os tiver habilitados, a sessão pode definir um cookie para armazenar temporariamente a ID da sessão. Assim, para fechar completamente uma sessão via código PHP, você precisa também apagar qualquer cookie que possa ter sido criado automaticamente para armazenar essa ID no navegador. Como qualquer outro cookie, você o destrói definindo o seu prazo de validade como um tempo no passado. Tudo o que você precisa saber é o nome do cookie, que pode ser descoberto usando-se a função session_name(). Í § É § « ~ - ; i • Para aeessar a variavel da sessão, basta usar a superglobal fJS£££IOH e o nom« da variável. As VoriaVels de sessão nS jO sã» apagadas autornatícamerite ^uandp a sessã° é desÇefta. £e a sessão estiver usando um tookte para ajudar 3 sc lembrâr da sua !Pj e*tao a IP é arma^nâda ern um dookie fcom »esmo nome da sessão. if (isset($ COOKIE! setcookie FVimeiramcrtte, veri-fi^ue - realmente existe um dookie da sessão- £ « ] > > < tim eO - 3 6 0 0 ); y * Destrua o dookie da sessão ( de-finindo o seu prazo de validade para uma hora atrás. você está aqui > 391
  • 419.
    como o mismatchtrabalha com sessões Comeda a«u 'v / s e s s io n _ s ta rt() ; % £unÇao sessioh_stârtO abre a sessão Renove o Mism atch com as sessões Repaginar a aplicação Mismatch para que ele use sessões para armazenar dados de login não é tão complexo quanto pode parecer. Na verdade, o fluxo da aplicação se mantém quase o mesmo —você só precisa tomar um pouco mais de cuidado nas operações de iniciar e destruir a sessão e de limpar a sujeira uma vez terminada a sessão. As duas variáveis da sessão sao driadas para ârma«narem 5 JP e o nome do vtsvtino, para o lojm- session_destroy(); Se os dookies estiverem habilitados, o servidor dria m* para armazenar a IP da sessão - daso dontrário, a |P e passadajuntamente dom a URL de dada página. A-fwr^ao session_ destro^O -finaliza a sessão iwpedmdo «ue ela seja usada em outrâ pagina As variáveis da sessão sao destruídas limpando— se o array ?_££££m £ tum dookie tiver sido usado para armazenar a [D da sessão, ele e destruído- jOs dados do lo^in Xí agora sao memorizados usa«do-se uma sessão, em vez. de dookies-
  • 420.
    criando aplicações webpersonalizadas Fapa Logout com sessões Para se fazer o Iogout do usuário, é preciso um pouco mais de trabalho com as sessões do que em versões anteriores, em que usávamos apenas cookies. Estes passos precisam ser executados para se fazer logout com sucesso, nas sessões do Mismatch. Q A p a g a r a s variáveis da se ssã o . Verificar se existe um cookie de ^ s e ssã o e, se existir, apagá-lo. O Destruir a se ssã o . 0 Redirecionar o usuário à hom e page. Aponte seu lápis Sem veH-ftcav, vote «ao sâbev-a dom ierteza se umdookie de sessão esia sendo usado. esse a^ul e um passo na© essendal pava o logout do usuaVio, mas é u-til de ^uai^wer iorma- N T 0 script de logout do Mismatch está sendo reelaborado para usar sessões, em vez de apenas cookies, para a persistência dos logins. Escreva o código que está faltando para "sessionalizar" o script, e depois escreva a qual passo do processo de logout cada inserção corresponde. <?php // Se o usuário estiver logado, apagar as vars de sessão para fazer o logout session_start(); if ( ............................... ) { // Apaga as vars de sessão limpando o array $ SESSION, // Apaga o cookie de sessão, definindo o seu prazo de validade como uma hora atrás (3600) if (isset($ C O O K I E [session n a m e ()])) } } // Destrói a sessão } // Redireciona para a home page $home_url = 'http://' . $ _ SERVER['H TTP _ H O S T '] . d i r n a m e ($ _ SERVER['P HP_SELF'] ) . '/ index.php'; h e a d e r {’Location : ' . $home_url); ?> você está aqui ► 393
  • 421.
    logout.php "sessionallzado " t^ponteseu lápis Solupão O script de logout do Mismatch está sendo reelaborado para usar sessões, em vez de apenas cookies, para a persistência dos logins. Escreva o código que está faltando para "sessionalizar" o script, e depois escreva a qual passo do processo de logout cada inserção corresponde. © © J Apagar as variáveis cia sessão. z ) Veri-fidar se existe umdookie de sessão e, se existir, apagá-lo. Destruir d sessão Rediretionar o usuário a home page- Mesmo ao ía « r o logout, vote tem de mitiar a sessão para poder <, php atessar as variáveis. / // o usuário estiver logado, apagar as vars de sessão para fazer o logout session^ttart o ; ------- Agora, esta sendo usada uma variável de sessão, em if iketÇ s£S£|0N fuserJítt) ) ( VCi dc ur" Cock'*> P^ra verifidar o status do login. // Apaga as vars de sessão limpando o array $_SESSION. f_£6 ££l0 N = • airayO; ^ ----- Para Uya" f ........................................... (j^) array «a^o a superglobal // Apaga o cookie de sessão, definindo o seu prazo de validade como uma hora atrás (3600) if (isset{$_COOKIE[session_name()])) { settookiefsessiôh__hâmeO, w , timeO —?>&Oõ); Se existir um dookie da sessão, apague-o, definindo o seu praza de // Destrói a sessão validade domo uma hora atras, session_destroyí)j Destrua a sessão dom uma J .............................. dhâmada a íunção sessioift__ destroyO. l i Redireciona para a home page $home_url = 'http://' . $_SERVER['HTTP_ H O S T 1] . dirname($_SERVER[’P H P_SELF’]) . '/ i n d e x .php1; h e a d e r ('L o c a t i o n : ' . $home_url); ?> ■ ©
  • 422.
    l A UM l 1 A mudança dos cookies para as sessões tem impacto sobre mais coisas do que apenas o script de logout. Ligue cada parte da aplicação Mismatch à modificação por que elas têm de passar criando aplicações web personalizadas connectvars.php Nenhuma modificação, pois este script nao tem influência direta na persistência dos logins. As sessões precisam se lembrar de quem o usuário é. Chame a função session_start() para iniciar a sessão, e depois modifique as referências a $_ COOKIE para $_SESSION. As sessões precisam controlar o menu de navegação. Chame a função se ssio n -sta rt () para iniciar a sessão, e depois mude as referências $-COOKIE por $-SESSION. editprofile.php você está aqui > 395
  • 423.
    como Bu mudosolução A mudança dos cookies para as sessões tem impacto sobre mais coisas do que apenas o script de lo g o u t. L ig u e cad a p a rte da aplicação Mismatch à modificação por que elas têm de passar para acomodar as sessões. Nenhuma modificação, pois este script não tem influência direta na persistência dos logins. As sessões precisam se lembrar de quem o usuário é. Chame a função session_start() para iniciar a sessão, e depois modifique as referências a $_COOKIE para $_SESSION. As sessões precisam controlar o menu de navegação. Chame a função session- s ta rt () para iniciar a sessão, e depois mude as referências $-COOKIE por $-SESSION. editprofile.php
  • 424.
    criando aplicações webpersonalizadas PONTOS DE BALA ---------------- ■ Aautenticação HTTPé útil parase restringiro ■ acessoadeterminadas páginas, mas não oferece nenhumaforma deo usuáriofazer "logout" após terminar de acessara página. B ■ Os cookies lhe permitemarmazenar nocliente (web browser) dados de pequeno porte, como por exemplo, os dadosde logindos usuários. ■ Todosos cookies têmumprazode validade, que ■ podevencer numfuturo muitodistante ou então logo ao final da sessão do navegador. Paraapagar umcookie, basta definiro seu prazo de validade paravencer emalgumtempo nopassado. Assessõesoferecemrecursodearmazenamento semelhanteaodoscookies, massãoarmazenadas noservidore, portanto, nãoficamsujeitasàsmesmas limitaçõesdonavegador- comoporexemplo, a possibilidadedesedesabilitaroscookies. Asvariáveisde sessão têmumtempode vida limitado, esão sempre destruídas umavez terminada asessão (por exemplo, quando o navegador éfechado). nã9 existem F e r g u n ta s id io ta s r • A função session_start() é chamada em vários lugares diferentes, mesmo depois de a sessão ter sido iniciadas. Não estamos criando múltiplas sessões com cada uma dessas chamadas a session start()? Não. A função session_start() não serve apenas para iniciar uma nova sessão - ela também trabalha com sessões existentes. Assim, quando um script chama session_start(), a função primeiramente verifica se já existe uma sessão, o que é evidenciado pela presença de uma ID de sessão. Se não existir, a função gera nova ID e cria a nova sessão. Chamadas futuras a session^startQ vindas de dentro da mesma aplicação irão reconhecera sessão existente e irão usá-ia, em vez de criar outra. ” P• Como a ID da sessão é armazenada? É nesse ponto que as sessões às vezes usam cookies? Sim. Embora os dados de sessões sejam armazenados no servidor e, portanto, tenham os beneficios de serem mais seguros e ficarem fora do controle do navegador, ainda precisa haver um mecanismo para o script saber da existência desses dados. É para isso que serve a ID - identificar individualmente a sessão e os dados associados com ela. Essa ID precisa persistir no cliente, de alguma forma, para que várias páginas possam fazer parte da mesma sessão. Uma forma pela qual essa persistência da ÍD é executada é através de um cookie, significando que a ID é armazenada em um cookie, que é então usado para associar um script a uma determinada sessão. P * Se as sessões ainda dependem dos cookies desse jeito, qual é então a grande vantagem de usá-las em vez dos cookies? As sessões não são inteiramente dependentes dos cookies. É importante entender que os cookies servem como uma otimização para se preservar a ID da sessão através de vários scripts, mas não como uma necessidade. Se os cookies estiverem desabilitados, a IDé passada de script parar script através de uma URL, de forma semelhante a como já vimos dados serem transmitidos em uma requisição GET. Assim, as sessões podem funcionar perfeitamente sem cookies. Os detalhes sobre como as sessões reagem em resposta aos cookies estarem desabilitados são controlados no arquivo de configuração php.ini presente no servidor web, através das configurações de session.use_cookies, session.use_oniy_ cookies e session.use_trans_sid. P • Ainda parece estranho que as sessões possam usar cookies, quando a justificativa em usá-las é justamente que elas supostamente são melhores que os cookies. Qual é a explicação? R:Embora as sessões de fato ofereçam alguns benefícios claros em relação aos cookies, em determinados cenários, elas não necessariamente têm uma relação mutuamente exdusiva com os cookies. As sessões certamente têm o benefício de ficarem armazenadas no servidor em vez de no cliente, o que as toma mais seguras e confiáveis. Assim, caso você precise armazenar dados sensíveis de forma persistente, uma variável de sessão forneceria mais segurança do que um cookie. As sessões também são capazes de armazenar quantidades maiores de dados do que os cookies. Portanto, existem vantagens claras em se usar sessões, independentemente de os cookies estarem disponíveis ou não. Para os propósitos do Mismatch, as sessões oferecem uma conveniente solução para se armazenar dados de login no lado do servidor. Para os usuários que têm os cookies habilitados, as sessões fornecem melhor segurança e confiabilidade, ao mesmo tempo ainda usando os cookies como uma forma de otimização. E no caso dos usuários que não têm cookies habilitados, as sessões funcionam sem serem afetadas, ao passarem a ID da sessão através de uma URL, evitando os cookies completamente. você está aqui ► 397
  • 425.
    migrando de cookiespara sessões Complete a sessão de transformações Embora as diferentes partes do Mismatch afetadas pelas sessões as usem para realizar coisas diferentes, em última análise os scripts precisam de modificações semelhantes para se fazer a migração dos cookies para as sessões. Por exemplo, todos eles precisam chamar a função session_start() para iniciar as sessões. Além disso, todas as modificações envolvem a troca da superglobal $_COOKIE pela $_SESSION, que é responsável por armazenar asvariáveis da sessão. Tõdos os sdHpb baseados em sessões domeça* £om uma chagada a sessio*_startO, para inieiar a sessão // Se o usuário não está logaáo, loga-o. íf (!issetÇ$~SESSIOKf ’• j ' s e r _idl ~Jj) { if (isset (5_PCST [’submit' ])) { // Coneta com o banco de dados Sdbc = raysqIi_connect (DB^HOST, DB_USERr DS_PASSKORD, BB_NAME) ; // Pega o dado do login digitado $user_userna?r.e = mysqli_real_escape_string($diic, trim(S__POST['-asemame'])) ; $’ jser_passworcS = mysqli_jreal_escape_string($dbc, trim ($_ECSTI ’ password'])); í ( !enpty ($’ jser username) && !empty (?user_password)) í // Olha o usuário e senha no banco $query = "SELECT user_id, username FROM mismatch_‘ Jsei ’ ’ password = SHA( ’$user_password') Sáata = mysi?ii_query ($dbcf Squery); VÍHERE username = '$user_username AND if (mysqlijrcum^rows($data) == 1) ) // 0 login é OK, defina a variável de sessãolD so none do usuário $row = mysqll fetch array($data) ; Çs SESSION [ 'user" id = $row['user id']' C H E E s I ( ! i j■ ■'useinamc row['username'’; $'ncme_url = 'http:/./' . $_SERVER[' KTT?_HOST 'j . dirname ($_SERVER L1?HP_3ELF']) header(’Location: 1 . $home_url); redireciona o/ hone page. '/index.php’; "// 0 usuário/senha estão incorretos, seta uma para f « « login. Sector msg = ’Desculpe, você deve digitar ut, usuarro * senha ,QlrdO- para 0 sdript de lo«yn usa sessões para se {embrar da IP e do «ome do usuário, obtendo assim a persiste*£i3 do îo^'m , e o -(-az. usândo á superglobal em vez- da login.php
  • 426.
    criando aplicações webpersonalizadas lf ^65e^SESSI0MFUSer^ ^ . ', , echo ’s#iõu84; <a h-efS^vTS^Í, -■ i echo 'ítlOOQí; <a hreí-"ed^r"fiTrP?P">VÍeW Profile</«><br />-; echo '£*10084; e,php >Edlt Profiie</a><hr /%-. - n-e- logout.pnp">Lcg out Cf. $ SESSTOMf. ^ [ username^i else { echo '&4I0Ü84; <a href="login.pnpT , >Lcç In</axtt /> echo '&#1008í; <a hre£=’ ’ signup.php">Sign tfp<7a>'; ) // Varre c array de dados de usuário formatado para HTML echc '<h4>Latest membÊrs:</h4> ' e c . h o '<table>’; while (?rcw = mysqli_fatch_array($õata)) { if ( is3etffsESSIONf'userTdJ> ) ( echo '<tdxa hrei'=< l viewprõr±le.php?uEer_id=’ , $rowf ’ user_id' ] . $row[’first^name' J . ' c/ax/tdx/tr>'■ ] else ( ')</a>' echo '<td>' . 5rcw[ 'first_name'] . ' </tdx/tr>'; i echo '</table>'; A home pa$e ^° |7Vfis«*atdh usa |a superglobal Í/JSESSION em fvez. de f__Cí)0^!£ para adessar dados de lo^hj ao mesmo temp© em «ue jera o menu e dedide se deve ou nâo exibir um !‘ mk para os per£is dos membros mais redewtes. Semelhahie a pa^i^a de lo^m e a home pa^e, o sdript Editar Per-Ç i! agora usa f__S£S£f0N em vez. de f_C00£ífc para adessar os dados de |oõ|m. index.php // r^^antirJ-.» o usuário está logado. - <' iq s p t -« g " f i F , 5 SIONi 'user id']H> t ,. echo '<p class="login">Please <a href="login.piip">log i.K/a> to access tnis page.</p> exit ( ); ^else echo('<p class="login">You are logged in as ’ .^^SESSIONÍ1 userr.ame’ T'X <a href“"logout.php">Log out</a>. </p>' ) ; — ------ — if ( !empty ($£irst_na;ne) && íempty ($last_name) && ! errpty (Sgender) £ • £ !empty(íbirthdate) && ! empty{$eity) &£ ! empty(Sstate)) ( // Apenas seta a coluna picture se existir - j i c a foto nova- if (!empty(Snew_picture)) { $query = "UPDATE mismatch_user SET first_name = '$first_name ’, last_nartte = '$last_name "çender = 'Sgersder’, birthdate = 'çbirthdate', city ~ 'Scitv1. state = 1Sstate', " . "picture = '?new_pioture 1 WHERE user_id = - Ç* SESSION [ 'user_idH~~~'>y''"; else { Squery - "UPDATE mismatch_'aser SET first_ne.Tie = ' $first_name', last_narae = '$last_name1 "gender = ’ $gender', birthdate - ’$fcirthda.te',city = '$city', state = 'Sstate' " . “MRERE user_id = - ^.SESSION [1 user mysqii_que:y(Sdbc, $query); viewprofile.php Bmbora y»ao esteja sendo mostrado, o sdript /er Períil usa sessões pratidâmcnte da mesma íormâ «ue tditar PerliL você está aqui ► 399
  • 427.
    convera informal entrecookie e varíavel de sessão Conversa Informal Conversa de hoje: Cookie e variável de sessão discutem quem tem a melhor memória. Cookie: Variável de sessão: Temhavido muitaconversa aqui entre nós, cookies, sobre oque exatamente estáacontecendo aí no servidor. Os boatos dão conta quevocê está tentando entrarno nosso território eroubar nossosempregos de armazenamento de dados. Qual éa história? Espera aí, roubar éuma palavra muito séria. A verdade é que àsvezes simplesmente fazmais sentido armazenar os dados no servidor. Não faz nenhum sentido para mim. O navegador é um lugar perfeitamente bom para se armazenar dados, e eu sou o cara perfeito para fazer esse trabalho. Mas e se o usuário te desabilitar? Ahn, bem, essaé outra história. Seousuário decidir me desabilitar, então claramente elenão tem nenhuma necessidade de armazenar dados. Nãoéverdade. O usuáriofrequentemente nem sabeque aaplicaçãowebestáarmazenandodados, porque, emmuitoscasos,sãodadosque sóficam nosbastidores, como por exemplo, osnomes de usuário. Assim,sevocê não estiverdisponível, ele acabasemnada. Então eu suponho que asuarespostaé armazenar osdadosno servidor? Que conveniente. Exatamente. Eo legal é que o usuário não tem como desabilitar nada no servidor, assimvocê não precisa se preocupar se os dados poderão ou não realmente ser armazenados. Ok, gênio.Já quevocêparece ter soluçãopara tudo, por que é que você, àsvezes, aindame usa para armazenar asuapreciosaID no navegador? Er, bem, a maioria das pessoas não sabe disso, portanto não precisamos falar disso aqui. Podemos falar disso fora do microfone. O mais importante é que eu estou sempre alerta, pronto para armazenar dados no servidor.
  • 428.
    criando aplicações webpersonalizadas Cookie: Variável de sessão: Não senhor, diga a todos o quanto você precisa de mim! Espera aí, roubar é uma palavra muito séria. A verdade é que àsvezes simplesmente faz mais sentido armazenar os dados no servidor. Ah, eu sei que pode, mas a verdade é que prefere depender de mim. E, no fundo, talvez até goste de mim. Olhe, eu não tenho nenhum problema com você. Só gostaria que fosse um pouco mais seguro. E você tem aquela limitação para o tamanho dos dados, que nem sempre são tão pequenos. Ah, então agora vocêvai me tirar só porque eu sou pequeno. Ok; posso não ser capaz de armazenar tanto quanto você, e admito que viver no cliente me toma um pouco menos seguro. Mas com certeza é mais emocionante! E eu tenho algo com que você só pode sonhar. Ah, sim? E o que seria? Bem, todo esseespaçode armazenamento e segurança de que vocêse orgulha tanto têm um custo... uma vida breve! Eu não queria ter de te dizer, mastoda asua existêncianão ultrapassa a duração de umasessão do navegador.Acho que é daíque vemo seu nome. Quer dizer que você pode viver além de uma única sessão? Como isso é possível?! Esimples. Eu não sou destruídojunto com a sessão, apenas termino omeu prazo devalidade. Assim, posso serconfigurado paraviverumavida longa epróspera, muito maislonga do que o determinado poralgum suiüsta felizdaweb que achabonito abrir efechar onavegadora cada oportunidade que tem. Uau. Aimortalidade deve sersensacional. A minha únicaesperança é que algum programador preguiçoso acidentalmente se esqueça de me destruiraofechara sessão... mas onavegador aindavaiacabar comigoassimque forfechado. Oproblemaé que essesmesmosprogramadores frequentemente definem omeu prazodevalidade comum período tão curto que naverdade eunão chegoa experimentaravidalongaque mereço. Quer dizer, eu... Alô?Você está aí? Caramba, esse negócio de prazo de validade é sério mesmo. você está aqui ► 401
  • 429.
    test drive the"sessionaHzado" mismatch T f e S T O R t v e M odifique o M ism atch para u sar se s s õ e s em vez de cookies. Modifique os scripts do Mismatch de modo que eles passem a usar sessões, em vez de cookies, para implementar a persistência do login (ou baixe os scripts do site da Alta Books, www.altabooks.com.br). Isso envolverá modificações nos scripts index.php, login. php, logout.php, editprofile.php e viewprofile.php, principalmente para iniciar a sessão com uma chamada à função session_start() e trocar as referências à superglobal $_ COOKIE por referências a $_SESSION. Envie os scripts para o seu servidor web e depois abra a página principal do Mismatch (index.php) em um navegador web. Tente fazer login e logout para se certificar de que tudo funciona como antes. A não ser que tivesse os cookies desabilitados antes, você não deverá perceber nenhuma diferença —isso é bom!
  • 430.
    criando aplicações webpersonalizadas !' Para as sessões poderem funcionar com os cookies desabilitados, precisa haver outro mecanismo para se enviar A s se s s õ e s sem co o k ie s poderão não funcionar se php.ini não estiver devidam ente configurado no servidor. a ID da sessão de uma página para outra. Esse mecanismo envolve a anexação da ID à URL de cada página, o que ocorre automaticamente caso session.use_trans_id esteja defínida como 1 (true) no arquivo php. ini do servidor. Se você não tiver a capacidade de alterar esse arquivo no seu servidor web, terá de anexar manualmente a ID à URL das páginas da sessão, caso os cookie estejam desabilitados, usando um código como este: sc s s à o ,a <uai tenviada ífo-avés da URL fè ra<ue a fá$inâ EdvUr Perlil sâiba da e*isfcen£ia da sessão. você está aqui ► 403
  • 431.
    porque o logoutautomático? Os usuários não estão se sentindo bew-vindos A p esar d e ser u m b o m aprimoramento em relação aos cookies, algo não está muito certo com a nova aplicação Mismatch baseada em sessões. Vários usuários relataram que estão sendo deslogados do aplicativo apesar de não terem clicado no link "Log Out". A aplicação não parece mais tão amistosa... isso é um grande problema. UsiASrie ■ Çrvsb-adô fMntè t âi^o b o * * » 0s usuivios esèâo sehdo deslocados do /VJismaidH stm tév ilidado no tmk w Loft 0ut'
  • 432.
    criando aplicações webpersonalizadas 4 > 0 ____________ c x t c é r é w q O que você acha que está fazendo os usuários serem desiogados automaticamente do Mismatch? Será algo que eles estão fazendo sem saber? você está aqui ► 405
  • 433.
    o tempo devida dos cookies e sessões As sessões têm vida curta... O problema com os logouts automáticos no Mismatch tem a ver com o tempo de vida limitado das sessões. Como v o cê deve se lem b rar, as sessões só duram pelo tempo em que a instância atual do navegador permanece aberta, significando que todas asvariáveis da sessão são eliminadas quando o usuário fecha o navegador. Em outras palavras, fechar o navegador resulta em o usuário ser deslogado, independentemente de ele gostar disso ou não. Isso não só é inconveniente, como também é um pouco confuso, uma vez quejá temos um recurso de logout. Os usuários presumem que não sairão do sistema a não ser que cliquem deliberadamente no link Log Out. __^ tom ressoes resulta *a driaça© de duâs variaveis de sessão. Esíejâ voôe usando sessões O MCookies, o prodesso de « o 1« o *odo persisie»te na aplidaça©. U»â vez. destruídas as variáveis da sessão, o usuário e deslocado- t^uer queira? *s*er n3o! M variaveis sao destruídas junto dom a sessão, guando o "X «avegador t -fedhada 0 usuário íedha _ i^vejador, *»as pode *ao perceber *^ u e âdabou de se desiogar do sistema. Embora você possa destruir uma sessão ao terminar de usá-la, não pode prolongar a sua existência para além da instância do navegador. Assim, as sessões são uma solução de armazenamento de prazo mais curto do que os cookies, uma vez que estes podem ter uma data de validade definida para daqui a horas, dias, meses ou anos. Isso significa que as sessões são inferiores aos cookies? Não, dejeito nenhum. Mas significa que as sessões apresentam um problema caso você precise memorizar informações para além de uma instância do navegador... como é o caso dos dados de login! As variáveis de sessão sã° d e stru íd a s «JUctndp p usuárxp íinalíza a sessãp fee])and° 9 naVegadpr.
  • 434.
    criando apficações webpersonalizadas ^ ----------- ...mas os cookies podem durar para sempre! Ao contrário das variáveis de sessão, o tempo de vida de um cookie não fica limitado à instância do navegador; assim, os cookies podem continuar vivendo, pelo menos até vencer o seu prazo de validade. O problema é que os usuários têm a capacidade de destruir todos os cookies armazenados na sua máquina com uma simples configuração do navegador, portanto, não fique muito contente com a permanência dos cookies - de uma forma ou de outra, eles ainda se prestam apenas para o armazenamento de dados temporários. lãivez. «ao para sempre, mSs íempo su-Pidichte para durar »dis do * V * e 3 sessão. ^ De -forma se»e!ha«-fce às sessões, os doeíties sâo driâdos ho w>on>eivèo d olo^ih. I I / 0% dookies só sao destruídos *^u3w do o seu prâzo de vâlidâde e-^fíra- 0 de vida do dookie é detevWinado pe!o seu pvâzo de validade. Ce^ldes são desítuídes guando a sua Validade expira, o lJue dá a eles um tempo de vida mais lo n g o d o Lju e a s V a r iá v e is de sessão. você está aqui > 407
  • 435.
    usando cookies esessões em paralelo Então faria sentido usar tanto sessões quanto cookies, sendo que esses ajudariam a manter os usuários íogados por períodos de tempo mais longo? Isso funcionaria para os usuários que têm os cookies habilitados. Desde «ue não esteja lidando tom dados al-bmente sensíveis, ew Cujo tèso a W itè seaurança dos òookies seria u» argumento fâra se redowendar o uso apenas das sessões. Sim , não há nada errado em tirar proveito d a s va n ta ge n s d a s s e s s õ e s e d o s co o k ie s para tornar o s lo gin s do M ism atcti m a is flexíveis. Na verdade, isso pode ser bastante útil. As sessões são melhores para a persistência de curto prazo, uma vez que elas são mais amplamente suportadas e não se limitam pelo navegador, enquanto que os cookies permitem que você mantenha os dados de Iogin memorizados por um período de tempo mais longo. Certamente que nem todo mundo poderá se beneficiar do uso dos cookies, mas será benéfico para muitas pessoas, o quejustifica esse uso. Sempre que puder aprimorar a experiência de usuário para uma parte significativa da sua base de usuários sem piorar para os outros, é bom fazê-lo.
  • 436.
    criando aplicações webpersonalizadas Sessões + Cookies * Persistência de login superior Para a melhor persistência de login possível, você precisa ser criativo e combinar tudo o que aprendeu neste capítulo para tirar proveito dos benefícios tanto das sessões quanto dos cookies. Ao fazer isso, pode reestruturar a aplicação Mismatch de modo que ela tenha o melhor desempenho possível tanto na persistência de login de curto prazo quanto na de longo prazo. $ua*do ' £ idnío âs vanlvfiis da os eookies sâo j para » rto to a *** ^ a IP e ° do usuário- ^ave^âdov v/cb, finalizando Os dados de So^in avmâz^nâdos nos dookics sao usados pârâ SC *as vaviávcis da sessão. s Bvm vez. de mânter os usuários logados para sempre, os ôookles sáo destruídos 10 dias depois. você está aqui > 409
  • 437.
    não existem perguntasidiotas sobre cookies e sessões m9 existem fe rg u rríc L s I d io ta s ~L - Então a razão para se optar entresessões e cookies é a questão persistência de curto x de longo prazo? Não. Essa por acaso acabou sendo aestratégia que ajudou aguiar o design da aplicação Mismatch, mas cada aplicação é diferente, eexistem outros aspectos das sessões e dos cookies que frequentemente precisamser ponderados. Por exemplo, os dados armazenados em uma sessão são mais seguros do que aqueles armazenados em umcookie. Assim, mesmo que os cookies estejam habilitados e umdeles esteja sendo usado unicamente para manter registro da IDda sessão, os dados armazenados na sessão propriamente dita são mais seguros do que se estivessem armazenados diretamente emum cookie. Omotivo éque os dados das sessões sãoarmazenados no servidor, o que torna bastante difícil seremacessados por usuários que nãotenham os devidos privilégios. Assim, se você estiver lidando comdados que precisem ser seguros, as sessões são mais apropriadas que os cookies. T * - E quanto ao tamanho dos dados? Isso tem alguma influência? Sim, otamanho dos dados tambémfaz diferença. As sessões são capazes de armazenar pedaços de dados maiores do que os cookies conseguem, portanto essa éoutra razão para preferir as sessões caso você precise armazenar dados maiores doque algumas strings de texto simples. Éclaro que umbanco dedados MySQLéainda melhor para armazenar dados muitograndes, portanto cuidado para não se animar demais ao trabalhar comsessões. > Então por que eu deveria optar por uma sessão ou um cookie em vez de um banco de dados MySQL? Conveniência. Armazenar dados emumbanco demanda muito mais esforço, e não se esqueça de que os bancos são mais adequados para armazenar dados permanentes. Dados de login nãosão realmente permanentes, numcontexto mais amplo. Éaí que os cookies e as sessões entram emjogo - eies são melhores para dados que você precisa ter memorizados por umcurto período de tempo, e depoisjogados fora.
  • 438.
    Imas de Greladeítctdç> Aaplicação Mismatch foi reelaborada para usarsessõesecookies ao mesmo tempo, com o objetivo de conseguiramelhor persistência de login possível. Oproblema éque parte do código estáfaltando. Useos imasde sessõesede cookies para completar o código. criando aplicações web personalizadas if (mysqli_num_rows ($data) — 1) { // Login OK, definir as vars de sessão (e os cookies) de ID e nome do usuário, // e depois redirecionar para a home page $row = mysqli_fetch_array($data); ['user id'] = S r o w [’u s e r _ r d ']; [’u s e r n a m e ’] = $ r o w ['u s e r n a m e ']; ' set coo ki e (''user_id', $row ['user_id' ], time ( ) + (60 * 60 * 24 * 30)); // expira em 30 dias setcookie(’username’, $row[ ’username'], time ( ) + (60 * 60 * 24 * 30) ); // expira em 30 dias $home uri = ’h t t p : / / ’ - $ _ S E R V E R [’HTTP_ H O S T ’] . d i r n a m e ($ _ S E R V E R ['P H P _ S E L F ']) . ’/ index.php’; header (’L o c a t i o n : 1 . $horae_url) ; login.f |p <?php : ‘ ~ ‘ ------- s e s s i o n - s t a r t ^ ® st^ver apagar as vara de sessão para fazer o logout if (isset(................. [iu s e r _ i d []) ) { // Apaga as vars de sessão limpando o array $ SESSION ................= array ( ) ; // Apaga o cookie de sessão, definindo o seu prazo de validade como uma hora atrás (3600; if (isset( ................[session_name ( ) ])) ( setcookie(session_name(), time() -3600); // Destrói a sessão session^destroy(); ÍLT?3Z>°°k Íe Sde ID 6 de "0me d° USUárl°' definind° 05 de validade como uma hora setco o k i e (’u s e r _ i d ’, time 0 -3600); setcookie ('username', time() - 3600); logout,php I <?php session_start (); // Se as vars de sessão não estiverem definidas, tentar defini-las com if (!isset ( .............. (issetí ['user_id']) && isset ( _l 'u s e r _ i d '] = 1u s e r n a m e '] -
  • 439.
    Inicis de Geladeirad v f [ í f - Solução A aplicação Mismatch foi reelaborada para usar sessões e cookies ao mesmo tempo, com o objetivo de conseguir a melhor persistência de login possível. 0 problema é que parte do código está faltando. Use os imas de sessões e de cookies para completar o código. $ SESSION if ( m y s q l i n u m _ r o w s ( $ d a t a ) — 1 ) { _ / / // Login OK, definir as vars de sessão (e os cookies) de i d e nome do u s u a n o , // e depois redirecionar para a home page $row = mysqli_fetch__array ($data) ; O snoves dookies s â o [ ' u s e r _ i d ' ] = $row [ ’u s e r _ i d ’ ] ; d e iiw d o s, âl«w d â s $ SESSION S j. <usernam e' ] = $row [ ’usernam e' ] ; ^ Vâriaveis dâ ses$a©. setcookie('user_id’, $row[' userid' ], time ( ) + (60 * 60 * 24 * 30) ); // expira em 30 dias setcookie (’username ', $row [’username’], time ( ) + (60 * 60 * 24 * 30)■ ; i / expira em 30 dia $home url = ’ h t t p : / / ’ - $ _ S E R V E R ['HTTP_ H 0 S T 1] . d i r n a m e ($_SE R V E R [ PHP_SELF ]) . / index.php’; h e a d e r (’Location : ' . $home_url); usuário estiver logado, apagar as vars de sessão para faser o logout + ■^ v “+ - / ♦ <?php // Se o s e ssion_start{); if <isset(j $_SESSION M ' u se r_ i d ' ])) { // Apaga a s Wr'à"3g"£<?§^io limpando o array $_SESSION a r r a y (); login.f $ SESSION / / Apaga o cookie de sessão, def: . . . ^ , i $ COOKIE if ( i s s e t ( L _ ^ ^ tinindo o seu prazo de validade como uma hora atrás (3600) |tsession_name ()])){ ^ ^ 0 setcookie (session_name ( ) , 11, time ( ) - 3600) ; ^ " logout, C pVCdiSO âpa^âr ^ taivbo o ôookic da // Destrói a sessão w . ± session_destroy ( ) ; .SC£S3o ^uânxo O ) / dookies d« l o j í i r » . // Apaga os cookies de id e de n o m e do usuário, definind' uma hora atrás (3600) setcookie ('user_id’, ’', time ( ) - 3600); Câso o wsuirio t^ao «st«a setcookie ('username', ’ ’, time ( ) - 3600) ;^ Ic ^ d o atrâv« da StSSèo, ______________________ verilidav *r f — logoutfphp os seus prazos de validade como e siâ cd e fin id o s . <?php session_start(); // Se a s vars de sessão não estiverem definidas, tentar defini-las com um coofclí §[ 'user_id' ])) M ' u s e r id' ]) && isset ( '■ I 'username ']) ) { I ?> ['user_id'] = 1u s e r n a m e '] ['user _ i d ’]; [’username ’] ï 0 wicswo dodf^o de ifldfiX.php $__cookie M ô o o k ie s/s e s s o c sdeve se r n doiodâdo e» edi-frproíiie- Pehna as variaveis da ?h? c vic^ciilefhf. sessao usahdo os dookigs. ____________
  • 440.
    ffgPíjPP TteSTORtve________________ criando aplicações webpersonalizadas Modifique o M ism atch para u sar s e s s õ e s £ cookies. Modifique os scripts do Mismatch de modo que eles usem tanto as sessões quanto os cookies para implementar a persistência do login (ou baixe os scripts no site da Alta Books, www.altabooks.com.br).Será preciso modificar os scripts index.php, login.php, logout.php, editprofile.php e viewprofile.php. Envie os scripts para o seu servidor web e depois abra a página principal do Mismatch (index.php) em um navegador. Tente fazer login e depois fechar o navegador, o que fará com que asvariáveis da sessão sejam destruídas. Abra novamente a página principal e verifique se você ainda está logado - os cookies tornam isso possível, uma vez que eles persistem para além de uma sessão do navegador. Combinando tockes e sessões, nos obremos pevsistenüa mâis lon^a, ale*» da oti»a pevsistenóia de duvfce prâto < < * eja esta sendo possibilitada pelas sessões. f ! / Z 7 0 uso de Cookies pâta *>e!horar as sessões «â'0 ajuda os usuirios ^ue desabílfta<ram os íookies *< > s seus navegadores... não * fossfvel a^ada*- a todos. você está aqui ► 413
  • 441.
    cA m o L o 7 caixa deferramentas php e mysql Sua Caixa de Ferramentas do PHP & M ySQ L V o cê aprendeu bastan te sob re com o criar um siste m a de gerenciam ento d o s u su ário s para fazer parte da a p licação M ism atch. V a m o s recapitular a lg u n s d o s pontos principais. f £sta £wr>çao ív^fce^a-4?!. '■ ■ ::il .I: ? razo de O ^ a l O Òookic é dcst^W o, Se não &>r íornedido nenbum ftòTo, o toolôee â f a ^ o â ss^ ^ue o ^í5 i_m > ?fíIí#iV i-íí 1 i-iíi;V '' * ' $vtefcna;$© t ,., f. iáfe,-’ ^ '1. : £if lí doofciee abwaàé í;'W :3éè&& .«ç.^tl^r ;' <& * * * < :< -> *x* ■ * !> .« « * » •* -IW * * « * > ■ * « ■ * EstaíwnÇaowvtevr«^^ in^iâ ja existente* Vpdt predisa tKái»>aV' :;;efe/:$|à^ . ^ is^ u e * variáveis da sessão ^< í; jdof _ ................ w*> té*t»> resultando t** mà sfcring de ^O daradteres H e^èdi*aii£<^ ítthçao -fórnctc : u»*á ofantâ maneira dt se d rip t^ ra í^ <ue fredise** 3« «^htarj^donbedrveis mesmo dentro do bando dt dados É, porem, vim prodesso se&> volta# si^niíidando <^ue nao evúste uma fen^So de "desdripto^ra&r W $Ê Ê Ê & È Ê & se ssio n _ _ d e s t r o y () £sta &n$ão interna do PHP íedka */^ses$ão,e deve ser dhamada á<a»ifv*e <ue vode tiver terminado de ■ - ;-<ierjb»r»»iir%adl3 sessão. £sta ;j&»v^:*iâo destrói as variaveis ; • ^■;^e«sâoí yorem, éimportante eli^na-las manualmente, esvaziando t. super^lobal interna do usada para se acessar dados da sessão- Trata-se de v>** array, e dada variável da sessão e armaxenâda domo uma entrada noarray Assim, para se adessar o valor de uma variável, e prediso espediAdar o seu nome» na forma de »»dite do array
  • 442.
    criando aplicações webpersonalizadas + A u c k à « rk ? f i m m Alguém bagunçou várias partes do código da aplicação Mismatch e não conseguimos nos lembrar do que elas fazem. Desenhe linhas conectando cada pedaço de código com o que ele faz. C ódigo PH P/M ySQ L D e scriçã o empty($_COOKIE['user_id']) setcookie (session name(), 11, time() - Usa uma variável de sessão para determinar se o usuário está logado ou não. 3600) ; Use um cookie para determinar se o usuário está logado ou não. SHA( '$user_password') Destrói um cookie de sessão, definido o seu prazo de validade como vencendo uma hora atrás. session_destroy( ) setcookie{'user_id' , $row['user_id']) Criptografa a senha do usuário, colocando-a em um formato irreconhecível. Armazena a ID do usuário em um cookie. $_SESSION = array( ) Inicia uma sessão. session start ( ) Fecha a sessão atual. isset{$ SESSION['user id']) Destrói todas asvariáveis de sessão. você está aqui ► 415
  • 443.
    quem faz oque solução Alguém bagunçou várias partes do código da aplicação Mismatch e não conseguimos nos lembrar do que elas fazem. Desenhe linhas conectando cada pedaço de código com o que ele faz. P H P /M ySQ L Code Description empty ($_COOKIE ['user_id ']) setcookie (session name(), time() - 3600) SHA(1$user_password' ) session destroy( ) setcookie('user id' , $row['user idT]) $_SESSION = array( ) session start ( ) isset{$ SESSION['user id']) Usa uma variável de sessão para determinar se o usuário está logado ou não. Use um cookie para determinar se o usuário está logado ou não. Destrói um cookie de sessão, definido o seu prazo de validade como vencendo uma hora atrás. Criptografa a senha do usuário, colocando-a em um formato irreconhecível. Armazena a ID do usuário em um cookie. Inicia uma sessão. Fecha a sessão atual. Destrói todas as variáveis de sessão.
  • 444.
    7 Vi ElimineÇ&cligoDuplicado ^k_ * Compartilharé Cuidar Guarda-chuvas não são a única coisa que pode ser Compartilhada . Em qualquer aplicação web, você poderá encontrar situações em que um mesmo código encontra-se duplicado em mais de um lugar. Isso não só é um desperdício de recursos, como também pode levar a problemas de manutenção, uma vez que inevitavelmente acabará fazendo modificações, e estas terão de ser efetuadas em mais de um lugar. A solução é eliminar o código duplicado, compartilhando-o. Em outras palavras, você mantém o código duplicado em apenas um lugar, e depois referencia esse código sempre que precisar dele. A eliminação de código duplicado resulta em aplicativos mais eficientes, de manutenção mais fácil e finalmente mais robustos. você está aqui ► 417
  • 445.
    localizar o códigoduplicado A aplicação Mismatch evoluiu ainda mais desde a última vez que você a viu, com uma navegação aprimorada e uma aparência mais consistente. Mas essas melhorias acarretaram um custo... código duplicado. Apenas olhando as próprias páginas, veja se você consegue descobrir quais partes do Mismatch poderiam estar representando um problema de código duplicado. Circule e escreva comentários nessas partes da aplicação, e escreva também qualquer coisa não visível que você ache que também possa estar tendo problemas com código duplicado. Mismatch -W hat opposites attract! Home ** View Profited StüLfteâk L atestbb® * » « t * A M' J l Bad Ccpyngh-£2009M enm ck£olKpr,«i-ta index.php
  • 446.
    elimine código duplicado Mismatch- View Profile Ho« « ** View Profile * Edit Prutile L op Qm limillles'l Username: jneities Firstsane: Johan Lastname: Nettles Gender: Male Birthdate; 1981-11-03 Location; Atheas,GA Picture: Wouldyooliketoedityourpmttte? Copyxíjbt& 2009Misratcfe Enterprises*fee. viewprofile.php editprofile.php você está aqui ► 419
  • 447.
    código duplicado domismatch SoLuÇâo A aplicação Mismatch evoluiu ainda mais desde a última vez que você a viu, com uma navegação aprimorada e uma aparência mais consistente. Mas essas melhorias acarretaram um custo... código duplicado. Apenas olhando as próprias páginas, veja se você consegue descobrir quais partes do Mismatch poderiam estar representando um problema de código duplicado. Circule e escreva comentários nessas partes da aplicação, e escreva também qualquer coisa não visível que você ache que também possa estar tendo problemas com código duplicado. 0 título W /Vlism3tdh apârede cr» todas as páginas, to» apenas a Jü? o titulo detalhado Q® variando de pagina para pagina* 0menu de «avegação £ ideníido eih * trespaginas. viewprofile.php index.php 0 rodapé da página, *ue dontem âs iníormaÇoe* de dopyright da aplidadao, e sempre o mesmo- Tõdas as paginas ^ue dependem do login do usuário requere» exatamente o mesmo dódigo de inicialização da sessão e de veri-fidação do logi». editprofile.php
  • 448.
    0 Mism atchestá em pedaços Portanto, a aplicação Mismatch tem alguns elementos comuns que estão repetidos nos principais scripts, no momento. Por que isso é tão ruim? Porque toma a manutenção da aplicação mais difícil. O que acontecerá se você decidir adicionar uma nova página, que requeira um novo item de menu? Você terá de modificar o código do menu em cada um dos scripts, para exibir o novo item. O mesmo se aplica ao aviso de Copyright. A solução para o problema é só armazenar cada informação apenas uma vez. Então, se algum dia o código precisar ser modificado, você só o modifica em um lugar. Com isso em mente, é possível repensar a organização do Mismatch em termos de componentes reutilizáveis. elimine código duplicado header,php 0 cabepalho das páginas O script header.php contém o título da página, o qual referencia uma variável para apresentar um título diferente em cada página. O cabeçalho também inclui código HTML padrão e cuida de tarefas tais como vincular a folha de estilo CSS. 0 menu de navegação O script navmenu.php gera um menu de navegação para a aplicação, baseado em se o usuário está logado ou não. O menu navmenu.php ^e navegação apresenta links "Log In”e "Log Out" conforme necessário. Este do>*p<m en-fce *ao resulta a* dódi^o ttMTL visível, mds ele te» uw papel vital no $e<rehí.iarr>e»to dos lojins dos usuários e» -toda â aplicaçao ^ ATismatéH- 0 micializador de sessão O script startsession.php é responsável por iniciar a sessão e verificar se o usuário está logado. startsession.php footer,php 0 rodapé das páginas O script footer.php exibe um aviso de Copyright para a aplicação e fecha as tags HTML abertas no cabeçalho. Assim, o cabeçalho e o rodapé trabalham em conjunto, tendo sempre de ser usadosjuntos. você está aqui ► 421
  • 449.
    mismatch precisa deum template Reconstruindo o Mism atch a partir de um template Ok, então nós dividimos os Mismatch em váriosscripts, mas como fazemos para elesfuncionarem bemjuntos? Vocêjá está familiarizado com o conceito de arquivos incluídos, e estes fazem parte da solução. Masvocê tem que pensar mais alto do que apenas incluirarquivos... você tem que pensar em termos de templates ("modelos"),os quais lhe permitem criaruma única página como a combinação devários arquivos incluídos. O templates é como uma planta para aspáginas da aplicação, onde todo o conteúdo, exceto aquele que é realmente único à página em questão,vem de arquivos incluídos. Aversão do Mismatch com templates requer que coloquemos os códigos comuns em scripts que desempenhem papéis bastante específicos: alguns responsáveis por gerar código HTML visual, outros por alguma outra função. A ideia é destilar o máximo possível de funcionalidades comuns em arquivos a serem incluídos e então só deixar em cada página o código que seja completamente único a ela. Ostemplates permitem c jue uma aplfraçã® ?B T seja constmída a pattír d e C Q m pQ netites sc rip t te u tíliz á V e ls. 0 dabedaiho aparede n©alto de dada pagina do Mismatdh, e exibe o título da aplidação juntamente do*» un« título espedífido da página- ^startsession.php Cada página do /Vlismatdh e^ u e -for personalizada para o usuário exigira um dodigo de login, o <uâl mantém registro do usuário. 0 rodapé Comede donteúdo na parte de baixo de todas as páginas do Alismatdh, o < ^ ual indlui um aviso de dopyright- Copyright©2Û C9Mimatch f navmenu.php 0 menu de nâvegadao aparede logo abaixo do dabedalho, e iornede a dada pagina do Mîsmatdh um menu donsistente, < ^ u e pode ser usado para navegaça© entre as paginas prindipais. footer,php index.php Com tantos outros sdripts ajudando, index.php -fida endarregado apenas do seu pape! prindipai, «ue é exibir a listâ prindipai de usuários-
  • 450.
    elimine código duplicado nãoexistem Perguntas Idiotas I • 0 que é exatamente umtemplate? Ele não é apenas um monte de arquivos incluídos? Sim. Umtemplates é umconjunto de arquivos incluídos, mas é umconjunto elaborado especificamente para dividir uma aplicação em componentes funcionais, 0 objetivo é reduzir cada página ao que é realmente específico aela, e somente aela. Assim cabeçalhos, rodapés, menus de navegação e quaisquer outras-partes'da aplicação que sejamas mesmas, ou semelhantes, emmais de uma página são candidatos ideais para inciusão em umtemplates. 0 resultado final é que você coloca o código dos templates emarquivos PHPque serão referenciados por outros scripts que precisem deles. Você pode pensar notemplates como umgrupo de arquivos que vão além de apenas reduzir aquantidade de código duplicado- eles ajudama organizar as funcionalidades de uma aplicação. OMismatch é umexemplo relativamentesimples de como usar os templates - aplicações PHPmaiores e mais complexas, frequentemente empregamsistemas de templates bastante sofisticados. - O código do template não tem de ser exatamente o mesmo para poder ser compartilhado entre vários scripts? Não. Éperfeitamente aceitável que o código do templates seja apenas semelhante, e nãoexatamente igual. Omotivo é que você pode usar variáveis para permitir algumgrau de personalização aoaplicar o script a diferentes páginas. Otítulo das páginas no Mismatch é umexemplo perfeito disso. 0 modelo do cabeçalho é semelhante em.cada página, no sentido que otítulo sempre começa com"Mismatch -". Mas otítulo específico é diferente, e é por issoque precisamos de uma variável para fornecer um meiode mudar ligeiramente otítulo emcada página. você está aqui ► 423
  • 451.
    mismatch—agora usando templates! Reconstruao Mism atch com templates O trabalho de design envolvido em se dividir uma aplicação em templates geralmente é recompensador. No fim das contas, você terá um conjunto de scripts pequenos e bastante focados, bem como terá um código radicalmente simplificado nos scripts principais da aplicação, os quais agora dependem dos scripts templates. 7ênta resetar a variáveis da s«sao dom dookies, dáso fc^elas não inicia a sessão tente defini-las <?php session_start( ) ; // Se as vars da s e s s è o n ã o estiverem definidas, com um cookie if (!isset{$__SESSION['user^id'1)) { ‘ if (isset($_COOKIE[’user_id’]) && isset($_COOKIE['username'])) $_SESSION [’user__id'] = $JTOOKIE[’user_id']; 5_SESSI0N['username’] - $_COOKIE[’ u s e r n a m e , ) } ?> !»»tia o toôi^o H/VlTL oíitial - tom um P0CTYPÊ e um3 tâ$ <KW>- Cria umtítulo personalizado usando a variável fpdgc__ií-tlc, <ue e -fornedida pelo sdripi < ^ u e indluir este arquivo. Cria um link para a •PolHa de estilo da apliiaçao. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML .1.0 Transitional//EN "http://www.w3.org/TR/xhtmll/DTD/xhtmll-transitional.dtd"> <html xmlns=”frttp;//www.w3.org/Í999/xhtml" xml; <head> <meta http-equiv=''Content-Type lang="en" lang content^”text/html; charset <?php echo ?> '<title>Mismatch - $page_title , '</title> re;L^"3tylesheet" type="text/cas" href=" </head> <body> style.cs <?php echo ?> '<h3>Mismatch - $page_title . ’ < / h 3 > ' <?php // Gera o menu de navegação echo '<hr />'; if (isset($_SESSION['username'])) { echo ’<a href="index.php">Home</a> &I10Q84; 1<a href="viewprofile.php">Ver Perfil</a> s#10084; '<a href="editpro£ile.php">Editar Perfil</a> S#10084; ’<a href="logout,php">Log Out ( ' . $_SESSI0N['username' ] echo echo echo 1)</a>1; '<a href="login .'php">Log In</a> &#10084; ■<a href=”signup.php">Cadastrar-se</a>'; echo header,php /VJostra um aviso de dopyright e íedha o dodigo H M T L . Ift se o usuário está logado, e então, gera o menu de navegarão <hr /> ^ <p class="footer">Copvright &copy;2008 Mismatch Enterprises, </body> </html>
  • 452.
    elimine código duplicado 0sdript startsession.php predisa ser o primeiro a ser indiuído, para ^ue a sessão seja inidiada e o restante do sdript tenha adesso aos sews dad A variável /pagejrák determina o título da página «ue é exibido dentro do dabedalh© < ?php '7/ Inicia a sessão ,require_once ('startsession.php1} i Insere o cabeçalho da p a g m a — $page_title = 'Onde os opostos se a t r a e m ! ^ kr e quire_once('h e ader.php'); r e q uire_once('app v a r s .p h p '); r e q uire_once(1connectvars.php'); // Mostra o menu de navegação .require once ('navmenu .php ' ) } , f// Conecta-se ao banco de dados As variáveis da denexão e as da apíidaçao ainda são indluidas a partir de sdripts ^separados, do»»o antes. 0 menu de navegado é gerado depois do dabedalho, mas antes do dorpo da pagma- $ d b c = mysqli_connect(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME); // Obtém os dados do usuário a partir do MySQL $query = "SELECT user_id, first_name, picture FROM m i smatch_user WHERE first_name IS NOT) NULL ” . "ORDER BY join_date DESC LIMIT 5"; $data = mysqli_query($dbc, $query); // Faz loop através do array de dados do usuário, formatando-os como HTML echo '<h4>Membros mais novos:</h4>' ; echo '< t a b l e > '; while (?row= mysqli_fetch_array($data)) { if (is_file(MM_UPLOADPATH . $ r o w ['pi c t u r e ']) £ & filesize(MMJJPLOADPATH . $row [1picture ’3) >0) { echo ' < t r > < t d X i m g src=" ' . MM_U PLOAD PATH . $row [’picture '] . '" alt=" ' . $row['first_ n a m e '] . 1" />< / t d > ’; } else { echo 1< t r > < t d x i m g src=" 1 . MM_UPLOADPATH . 'nopic.jpg' . '" alt=" ' . $row['first_ name'] . /></td>'; } if (isset($_SESSION[’u s e r _ i d ’])) { echo '< t d x a href="viewprof ile .php?user_id=' . $row ['user_id'] . , ,1>' . $row['first_ n a m e '] . '</a></td></tr>1, • } else { echo '<td>' . $row['first n a m e ’ } echo '</table>'; mysqli__close ($dbc) ; ?> 1 < / t d > < / t r > '; oú à s* f> v c r ft I modeto agora t reaWe^te untdo a esta portant» há m uV to »ew» dele- <?Bte 0 rodape -finaliza a pagina, e -,, , , , predisa vir por ultimo, u»a vez. // Insere o rodape da pagina r . i < ^ u e e ele <ue -redha as tags HTML. ,^equire_once ('f o oter.php '); ?> você está aqui ► 425
  • 453.
    uma aplicação phpbem desenhada 0 Mismatch está novamente em pá., e muito melhor organizado Embora o pensamento de destrinchar o Mismatch em pequenos pedaços possa nos ter deixado um pouco nervosos, o resultado final definitivamente valeu o esforço. A aplicação agora está dividida em vários novos arquivos templates (inclusos), os quais oferecem muito melhor organização e maximizam o compartilhamento de código. Se você precisar modificar um desses pedaços, basta editar um arquivo e o efeito se fará sentir em toda a aplicação... esse é o poder dos templates! 0 sdrift star-bessionfKf lida to» as -tareias de log's nos bastidores c nâo odupa néctar* espaço virtual «a página- 0cabeçalho da pagina indlui tídigo HTML e o irtulo da pagina. 0 tódigo de ^ midialização da sessão e wsado por <*al«ue<r página <ue requeira login do usuavio. 0 vodape da pág^a í.on-téw>ift-Çov-matoes de topYnghí para -boda a aplitação- se vote predisar m tadav o aviso, basta modi-fita— io em apenas w w >lugarj V-------^ startsession.php 0menu de navegação íornede links úteis para as partes pHndipais da aplida^ão. C ' navmenu.php footer,php
  • 454.
    8 Controle SeuM u n d o Colhendo Dados ■ w Nada como uma boa colheita de dados no outono. Um sem-fim de informações prontas para serem examinadas, classificadas, comparadas, combinadas, enfim, qualquer coisa que a sua excelente aplicação web precisar que seja feito. Compensador? Sim. Mas assim como as colheitas na vida real, é preciso muito trabalho duro e uma boa dose de conhecimento para se obter controle sobre os dados em um banco MySQL. Os usuários da web exigem mais do que dados estáticos e enfadonhos. Eles querem dados enriquecedores... dados compensadores... dados relevantes. Então, o que você está esperando? Dê a partida no seu trator MySQL e mãos à obra! este é um novo capítulo ► 427
  • 455.
    procurando uma relaçãode amor-ódio Fazendo o desencontro perfeito O aplicativo Mismatch tem um número cada vez maior de usuários registrados, e eles estão prontos para ver resultados. Precisamos permitir que os usuários achem os seus opostos ideais, comparando o que amam e o que odeiam com as preferências dos outros usuários, em busca de desencontros. Para cada "adoro”combinado com um "odeio", maior a probabilidade de um casal formar um par imperfeito. Sidney ainda pvodura o seu prfhdipe e^tantado, i»i3s ela “ te*" a sensação de < ^ u e ele vai odiar reality shows -fcan -fco < ^ u a > v fco ela os adorâ- Lewbra do Oo^a») w* doratSo solitário e» bus£a de al^Vké» «ue odeie'levantamento pesos tanto quanto adora? Odeio tatuagens Adoro botas de caubói Adoro realíty shouís: Odeio filmes de terror Odeio presunto Adoro comida apimentada" Odeio Hooíard £tern Adoro Barbara Çtreisand^ Odeio levantamento de^ peso ~ Adoro escalada h l»»ta âkW S rvt odeio da Sidney tonhrãslê bâshnic tom a de Johan, o «u »e O S torna um potential par i»per+eito- 4doro tatuogerts Adoro bofas de caubói * Odeio resfity shows -Àdoro film es dk te rro r "Adoro presunto . *doro comida apimentada1 ^doro Howard Stem ■°dcío Barbara Streisand ^doro íevantamento de peso Odeio escalada r *_ çx.
  • 456.
    controle seus dados,controle seu mundo Os desencontros se referem aos dados Para podermos estabelecer desencontros entre os usuários, precisamos primeiro determinar o melhor modo de organizar os dados que informam o que eles adoram e o que odeiam. Saber que as informações serão armazenadas em um banco de dados MySQL não é suficiente. Precisamos organizar esses tópicos de adoro/odeio de forma que sejam mais fáceis de gerenciar, permitindo que os usuários respondam a tópicos relacionados, indicando que eles adoram ou odeiam cada um. Topidos semelhavas sao agrupados, tomo este a<w para aparoxdia íísidâ- Cada tópido individual redebe uma resposta adoro/odeio, ^ue e domparado dom as respostas dos outros usuários. Escreva aqui como você organizaria os dados do Mismatch em grupos separados que possam ser armazenados em um banco: você está aqui ► 429
  • 457.
    um modelo dedados para mismatch Pivida os dados do Mism atch Criar um modelo de dados para uma aplicação como o Mismatch é um passo extremamente importante, uma vez que ele tem um grande controle sobre o modo como a aplicação é construída. No caso do Mismatch, nós p o d em o s dividiros seus dados em três tipos. As daíegorias s3o Categorias As categorias são usadas para ajudar a organizar os tópicos. Embora elas não desempenhem um papel direto no estabelecimento de um par imperfeito, elas ajudam a facilitar a tarefa de os usuários digitarem as suas respostas. ■ j usadas para se agrupar -bofidos relational aos. Os -èopidos iorwiâm o tev«e dos dados do yV jisft.atc.K , detîdmdo t^ais parâmetros pode** ser tombados pava se estabelederen» os pares. Respostas Os usuários se descrevem, para os propósitos do Mismatch, respondendo _ aos tópicos. Cada resposta individual é apenas um valor de adoro ou odeio em resposta a um tópico. 'RpdlityT V 1 ^ m- Weightlifting Horrf HiWng Tópicos O estabelecimento de pares é feito encontrando-se opostos, tais como o gosto por tatuagens ou comida apimentada, cada um dos quais recebe uma resposta do usuário - adoro ou odeio. $s respostas são as de adoro/odeio ■para dada tópido, e são espedííidas para dada usuário do /V}ist*akdH. Como exatamente esses dados levam a um desencontro entre dois usuários? Nós comparamos as respostas que os usuários deram a cada tópico. Por exemplo, uma vez que Sidney eJohan têm respostas opostas para o tópico "Filmes de terror", achamos um desencontro nesse tópico particular. Para descobrir o melhor par imperfeito para um usuário, temos de encontrar o usuário com a maior quantidade de tópicos respondidos de forma oposta ao primeiro. Adoro^ £ FÜffle de terror 0 -(-ato de Sidney «3o gostar de -fiWes de terror leva a u n > desentomkro. Um desencontro! t
  • 458.
    controle seus dados,controle seu mundo Modele o banco de dados com um schema Para podermos traduzir os requerimentos de dados da aplicação Mismatch em um projeto de banco de dados propriamente dito, precisamos de um schema. O schema é a representação de todas as estruturas do seu banco de dados, como por exemplo, tabelas e colunas, além do modo como eles se conectam uns aos outros. Criar uma representação visual do seu banco pode ajudá-lo a ver como as coisas se conectam quando você estiver escrevendo suas consultas, sem falar que ela esclarece o que cada coluna é responsável por fazer durante a conexão. Como um exemplo, vejamos o schema do banco de dados original do Mismatch, do capítulo anterior, que consistia apenas da tabela mismatch_user. 0 rtom c dâ tâbelâ- Uma descrição dps ciadas (as tabelas e as colunas) <fc seu bancp de dadps, juntP com ^iials^uet P ufrP S objetos íelaclpnadps e a f o r m a c o m p eles se conectani, é um scíiema. ^ m á m a t c h u s c » 111: userjd O“ “"'* username password join_date first_name !ast_name gender birthdate city state picture Este símbolo indida íue â doluna C(A m a dhave pvimâvia para < 3tabela. outras tolunai da "tabela sao listadas da -Porm a ttmo cias aparedem na estrutura do banCo de dados. Esta forma de se considerar a estrutura de uma tabela é um pouco diferente do que viu até agora. As tabelas normalmente têm sido representadas com os nomes das colunas na primeira linha, com os dados logo abaixo. Essa é uma ótima forma d« se visualizar tabelas individuais e tabelas preenchidas com dados, mas não é muito prática quando queremos criar um diagrama estrutural de várias tabelas e do modo como elas se relacionam. E o Mismatchjá está precisando de mais de uma tabela... Criai- um diagrama l]je petmffce manter 9 d e s i g n databela separadp dos dadps cpntídps nela. você está aqui ► 431
  • 459.
    escolha o melhorschema do mismatch 0 banco de dados do Mismatch está precisando armazenar as respostas dos usuários para tópicos do tipo adoro/odeio, bem como os nomes dos tópicos e as suas respectivas categorias. Apresentamos aqui três projetos de bancos de dados para incorporar as categorias, os tópicos e as respostas no banco do Mismatch. Circule o schema que você acha mais apropriado, e escreva por quê. category II topic response - é r □ s è oos novos dddos fvefiisamos armazenar para dav- suporte âo «ovo redurso de bus£<3 por pav-es do /WismaUh. mismatch_topic m is m a tc h _ _ u s e r topic«. ÍW IÜ BÍÍÍI8 -iqrtegory": 1 Tattoos Appearance 2 Cowboy hats Appearance 3 Reality TV Entertainment . ^ , 1 _ _ ******** 11 jnettles 4 Horror movies Entertainment 1 mismatch resbons î ♦ response. ■ 1 niirr ’ If S i* *Sit iíííHBiWIi 101 Love 11 1 102 Love 11 2 103 Hate 11 3 104 Love 11 4 “ mi^matdi response c - fill IIHwnuw*!.._ _ t_ ^r t 1 i response id response to p ic jd user id name tooic id category
  • 460.
    controle seus dados,controle seu mundo «serjd mismatch user i i i i i ü á ! h jnettles mismatch_response ufSt" T * 101 Appearance Tattoos Love 11 102 Appearance Cowboy boots Love 11 103 Entertainment Reality TV Hate 11 104 Entertainment Horror movies Love 11 mismatch user !« § r""**1 "* ■ H l i l S f S l h jnettles * * * * * * * * 1 Love h jnettles ********* 2 Love h jnettles * ******* 3 ] Hate 11 jnettles * * * * * * * * 4 Love mismatch_topic litopfcld l r ;. name ■ / . .category 1 Tattoos Appearance 2 Cowboy hats Appearance 3 Reality TV Entertainment 4 Horror movies Entertainment ❖ você está aqui ► 433
  • 461.
    mefhor schema dabase de dados mismatch’s 0 banco de dados do Mismatch está precisando armazenar as respostas dos usuários para tópicos do tipo adoro/odeio, bem como os nomes dos tópicos e as x , suas respectivas categorias. Apresentamos aqui três projetos de bancos de dados & C |C |0 para incorporar as categorias, os tópicos e as respostas no banco do Mismatch. § O L u Ç Ü O Circule o schema que você acha mais apropriado, e escreva por quê. £m primeiro lugar, é importairfte -Pidar diaro ^ue os úm idos dados novos m o prodesso d« se obter respostas adoro/odeio do usuirio são as próprias respostas —tudo o «»ais no ba^do de dados permanede o mesmo, pelo menos do ponto de vista do usuário- Quem disse <ue o mais simples e sempre o melhor? £ste sdhema armazena as respostas em uma tabela própria para elas, separada dos ovtros dados <ue *>ao sejam impadtados diretamente por elas. Na© há duplidadão das respostas, porque os usuários, as tate^orias e os tópidos íidam todos -fora da tabela mismatdbjresponse. mismatchjaser h jnettles * * * * * * * * topicid iis iiii 1 Tattoos Appearance 2 Cowboy hats Appearance 3 Reality TV Entertainment 4 Horror movies Entertainment mismatch ❖ _res] >onsej^ ism ffr "S'- 101 Love 11 1 102 Love 11 2 103 Hate 11 3 104 Love 11 4 A nova tabela mismatdh_topid armazena os nomes dos topidos e as suas respedtivas dategorias Kao H a dados duplidados para dada resposta, o «^ u e e muito bomj response id H H B M H M M Q i response — topicjd ^ user id name topic id 4 """" category A tabela mismâtdh__user original permânede sem modiíidadoes. A tabela mismatdhjresponse donedta os usuários e os tópidos através das doiunâs user_jd e topid_jd-
  • 462.
    controle seus dados,controle seu mundo As ("espostas nâOÇltdrrt dV-»n3Z£»dclâSdentro dâ tabela dos usuários, Oque e otimo- Mss existe uma quantidade excessiva de dados duplicados, porque as categorias e os tópicos são replicados para cada resposta. ^ mismatch__user • • • - : V. : : ü lé ir M « se ra a ^ passv««» - 11 jnettles * * * * * * * * mismatch_response i i S i | | P | y |S ! | í É A I h í ilÉrtMftfi líWílÍsítíiÍMíllikâll ^âsíJíílâliSiíllfl user: a 101 Y Appearance Tattoos"-^ j Love h 102 I Appearance Cowboy s) Love boots ^ ii 103 { Entertainment Reality TV | | Hate 11 104 ' ^Entertainment Horror movieyi Love h . - - K ........................ Os dados dos usuários sao pessimamente replicados a cada resposta- As categorias e os tópicos são duplicados para^cada resposta, 0 * V * e « um desperdício, inaceitável de reCursos- mismatch__user È É f s t » vM m ä B H i Ip ill èmm 11 / jnettles * * * * * * * * Love 11/ jnettles * * * * * * * * I 2 Love 11 jnettles * * * * * * * * ... 3 Hate 11 ^ O nettles * * * * * * * * J 4 Love ... Nao e mi ideia dividir as categorias e os tópicos em uma tâbela para cada um, mas da -forma Como esta sendo -feito, temos de criar uma linha para cada resposta- (sso nos deixa com 4r Johans para respostas. Nada bontf mi smatch_topic t * i c j d íl!l!WltíwttlSà%8s! 1 Tattoos Appearance 2 Cowboy hats Appearance 3 Reality TV Entertainment 4 Horror movies Entertainment * 435
  • 463.
    schema do mismatchusa chaves estrangeiras Junte várias tabelas Para conectarmos as tabelas de modo a formar um sistema de dados coeso, precisamos usar chaves. Nósjá usamos chaves primárias para fornecer um identificador único para os dados de uma tabela, mas agora precisamos de chaves estrangeiras paravincular uma linha de uma tabela a uma linha de outra tabela. Uma chave estrangeiras de uma tabela referencia a chave primária de outra, estabelecendo entre as duas uma conexão que pode ser usada em consultas. O schema que elaboramos para o Mismatch no exercício anterior depende de um par de chaves estrangeiras na tabela mismatch_response para conectar linhas de respostas a linhas de usuários e tópicos em outras tabelas. Uma cLaVe estrangeira (foreígn key) é uma coluna, em umatat>ela, que referencia a cJiflVe prmáfla (ptínwy key) de outra tabela. username password join_date first name last name gender birthdate city state picture Lembre-se, este símbolo ideht»-(-ida u»a dhave primária. £sta dhave primária nao apenas idcwtifida individualmente os tópidos dentro da "tabela n>ismatdh_topid, tom no também donedta os tópidos às respostas da tabela mismatdh__response. &ta seta mostra a tabela »'smatdhjíser esta donedtada à tabela i*ismat£h_jresp©Me por meio das dhaves. Sem as chaves estrangeiras, seria muito difícil associar dados de uma tabela com dados de outra. E dividir os dados entre múltiplas tabelas é justamente o modo que encontramos para eliminar a duplicação de dados e conseguir maior eficiência para o banco. Assim, as chaves estrangeiras desempenham um papel importante em todo schema de bancos de dados, por mais simples que o banco seja. As tabelas mismatch response c l ' l i I * „ , , e '*IStt'atdh_topid trabalha* £ y * »»boi« Msbr» Y * para to U a t uma dkave „ sposbs adaro/edeic a qua! re-Vereda uma dhave primaria em outra tabela- As setas grandes . mostram as ctaVes prlmárías cpnectandp-se às cfcaVes estrangeiras, para Vincular as ^ tabelas entre sx.
  • 464.
    controle seus dados,controle seu mundo Chaves estrangeiras em apão Muitas vezes, é útil visualizar os dados fluindo para as tabelas e conectando-as umas às outras através de chaves primárias e estrangeiras. Dar uma olhada com mais atenção nas tabelas do Mismatch, com alguns dados nelas, ajuda a revelar como as chaves primárias e estrangeiras se relacionam umas com as outras. Sendo uma tHave prímâriâ, user_id predisa ser unida dentro da "tabela mísmatdh_ user. Pe -fato, esse e o seu propósito —íorneder um a reíerendia unifia a dada linha- A dhave estrangeira user id serve £om ©um â vrPerendia às linhas dos usuários nâ tabela mismatdh_user, permitindo «jue vode saiba ^ual usuário esta assoòiado dom ^ual recosta. mis: A dhave primária topidjd serve domo um (ndide unido para as linhas da tabela miSmatdh__topid ch topic Lembre-se, dada linha desta tabela dorresponde a um usuário do /Wismâtdh- Cada linha desta tabela é uma unida resposta adoro/odeio •Çornedida por um determinado usuário. iilBiii;i;iÜiÉÍ Tattoos Appearance 2 Cowboy hats Appearance 3 Reality TV Entertainment V Horror movies Entertainment P U T “ ■ H M M 1 > 101 Love ( 1 1 102 Love 1 1 1 2 103 Hate 1 1 1 1 3 104 Love v u j m____ V 4 / Cada linha desta tabela e o nome/dategeria de uma resposta adoro/ odeio, mas ndo a resposta propriamente dita- A dhave estrangeira /top»d_id reíerendia as linhas dos topidos na tabela m»smatdh_ topid, e nao é unida, uma vez. < ^ u e muitos usuários diíeren-tes ■terao as mesmas respostas para os mesmos tópidos. Dentro da tabela mismatch_jresponse, você pode encontrar mais informações sobre o usuário que digitou uma determinada resposta procurando pela user_id na tabela mismatch_user. Da mesma forma, você pode descobrir o nome do tópico de uma resposta, bem como a sua categoria, olhando o topicjd na * , ' tabela mismatch.topic. vindulIUa linha de resp^ta a Vincular tabelas atravésde chavesprimárias e chaves estrangeiras uma linha de usuário na tabela nos permite conectar os dados entre elas de uma forma consistente. mismatdh__user Ela nao e unida, Vocêpode até mesmo estruturar o seubanco de dados de fornia uma vez. <^ue um mesmo usuano aexigiruma correspondência entre aschaves primárias e assuas pode "ter diversas respostas respectivaschaves estrangeiras. Isso é conhecido como integridade adoro/odeio, referencial, o que é uma forma chique de dizerque todas as referências das chavesprecisam serválidas. você está aqui ► 437
  • 465.
    tipos de relacionamentoentre tabelas Eu entendi que as chaves primárias e estrangeiras conectam várias tabelas entre si, mas a direção das setas nos diagramas tem algum significado? Sim, a direção das setas nos informa como as linhas de cada tabela se relacionam umas com as outras. Falando mais especificamente, elas nos dizem quantas linhas em uma tabela podem ter linhas correspondentes em outra, e vice- versa. Este é um aspecto importantíssimo do projeto do schema, e envolve três padrões de dados possíveis: um-para-um, um-para- muitos e muitos-para-muitos. Astabelaspodemcorresponderlinhaporlinha O primeiro padrão, um-para-um, determina que uma linha na Tabela A pode ter no máximo UMA linha correspondente na Tabela B, e vice-versa. Assim, só há uma correspondência em cada tabela para cada linha. Como um exemplo, digamos que a tabela dos usuários do Mismatch sejaseparada em duas tabelas, uma apenas para asinformações de login (TabelaA) e uma com os dados dos perfis (Tabela B).Ambas as tabelas contêm IDspara manter os usuários conectados aos seus perfis. Acoluna user_id da tabela de login é uma chave primária que garante a individualidade de cada login. Na tabela dos perfis, user_id é uma chave estrangeira, e desempenha um papel diferente, uma vezque a suafunção é apenas conectar um perfil a um login. , Um-parâ-u», portâ«tX> âs U i líüil corresponde APENAS UMA - A - APENAS UMA destas linhas destas linhas setas ndo tò» poft-Us user »d username join .date « S i i á i i l — 9 dierdre 08447b... 2008-05... 10 baldpaul 230dcb... 2008-05... jnettles e511d7... 2008-05— 12 ' 062e4a... 2008-06... 13 theking "*b4ß B 3 r- 120080G-- mismatch__user_j?rofile lÉSllIll fiKtnam e last name lIllSlB gender ili&ljlfilíisliiSfllsi Johan Nettles M 8 Jasor> Filmington M 1 7" 9 Paul Hillsman... M 10 de um -para-w * através de wser_id No que diz respeito às duas colunas user_id, a tabela dos logins é considerada como tabela parent(pai), enquanto que a dos perfis é considerada como child(filho) - uma tabela com uma chave primária tem uma relação parent(pai)-child(filho) com a tabela que possui a chave externa correspondente.
  • 466.
    controle seus dados,controle seu mundo | liH M M H i l i l l i f l l ► corresponde UMA---- A MUITAS destas linhas destas linhas Chave primaria. mismatch_user « « « o * -* ! i l l 9 dierdre 08447b... 10 baldpaul 230dcb... jnettles e511d7... — S í ir ^ rubyr 062e4a... « V “ theking b4f283... I ■ ■ ■ I------ 11r 1 Uma linha leva a muitas outras Um-para-muitos significa que uma linha na TabelaA pode ter muitas linhas correspondentes na Tabela B, mas uma linha na Tabela B só pode corresponder a uma linha na TabelaA.Adireção da seta no diagramasempre sai da tabela com uma linha e vai para a tabela com muitas linhas. Usando novamente o banco de dados do Mismatch, o schema atual sempre tira proveito de um padrão de dados de um-para-muitos. Uma vez que um mesmo usuário pode ter muitas respostas para os tópicos (adoro tatuagens, odeio escaladas, etc.), há uma relação de um- para-muitos entre as linhas dos usuários e as linhas das respostas. A coluna user_id conecta essas duas tabelas, como chave primária em mismatch_user e como chave estrangeira em mismatch_response. «^a^cW . mismatch_response y um— fâtrâ— rnurtos aivavés de user id- i l ï l l l l l ï l l i i l l l l l i ï î î ! ! H I P ! 101 Love f 11 1 ^ 102 Love I 11 2 103 Haïe 11 3 104 Love l 11 J 4 Um-para-Um: e x a ta m e n te umalínfea databela paxerrt(pa2) se relaciona com uma linjbadatabela chíld(Mho). na« oxístem — — " P e rg u n ta s id io ta s — I * Como eu sei se as linhas de duas tabelas têm uma reiação de um-para-um ou um-para-muítos? Há uma tendência de se usarpadrões de um-para- muitoscom muitomaisfrequência doque um-para-um, e com bons motivos. Écomumse terumatabela principal (parent) contendo dados primários, como porexemplo, os usuários do Mismatch, a qual se oonecta a umatabela secundária (chíkJ)em umarranjode um-para-muitos. Isso aconteceduas vezes noesquemado Mismatch,ondetanto os usuáriosquanto os tópicos têm relaçõesde um-para- muitoscomas respostas. Emmuitoscasos, as linhasde uma relação de um-para- umem duastabelas podem ser combinadasem uma só tabela. Porém, certamente existem situaçõesem que faz sentido optarpelopadrão de um-para-um, como noexemplo hipotéticodos perfisdos usuários na páginaanterior, onde há uma motivaçãode segurança parase colocar uma parte dos dados em umatabela separada. Um-para-Muït°s: exatamente uma linha databela parent(paî) se relaciona cem várías lïnfcas databela cjnlc[(eifco). você está aqui > 439
  • 467.
    o relacionamento muitospara muitos Checando linhas de wuitas-para-muitas O terceiro e último padrão de relacionamento de dados é o de muitos-para-muitos, que tem muitas linhas de dados na TabelaAcorrespondendo a muitas linhas na TabelaB... parece um caso de sobrecarga de dados! Mas na realidade não é. Existemvárias situações em que um padrão muitos- para-muitos é o mais apropriado. Seria o caso do Mismatch? Vamos dar uma olhada. Os usuários e os tópidos tem uma reiôtso de m uitos-para- muitos, axraves das respostas. 1 fat,!«iííis -j— 4 - - i l ã S t t f s í * • — mismatch_user MUITAS A MUITAS destas linhas destas linhas mismatch__topic Sun 9 dierdre 08447b... 10 baldpawt’" ""2353cb... j nettles e511d7..n i 12 rubyr 062e4a... 13 theking I b4f283... 1 ú ____ /Vjuitos-para-muitos/ Um-para-Wstos i_respons> '2 E I Tattoos Cowboy hats Reality TV Horror movies Appearance Appearance Entertainment Entertainment Wm— para— muitos. mismatch response e uma tabela de > nçao que estaW ctó w*, reladiowameht?^ tnbrt os usuarios e as suas respostâs dos topifios- á ü B l ff^" S t :: . X 1 81 Hate 1 À 82 Love 9 2 / / 83 Love Hate .® A V 101 Love '111 I 1 . / 102 Love 11 I 103 Hate 11 ^ 3 ) 104 Love I11/ 4 s b k O padrão muitos-para-muitos no Mismatch é indireto, significando que ele ocorre através da tabela mismatch_ response. Mas o padrão ainda existe. Basta ver quantas das ^ mesmas user_ids e topic_ids aparecem em mismatch_response. M uitP S -pcir^M Ü Ít^S : Além de aimazenar os dados das respostas, a tabelamismatch_ response está agindo como o que é conhecido como tabela de junção, ao servir como um conveniente intermediário para os usuários e os tópicos. Sem a tabela dejunção, nós teríamos muitos dados duplicados, o que é ruim. Casovocê não esteja convencido disso, volte para o exercício dos esquemas no início deste capítulo e dê uma olhada com atenção no Projeto 2. Naquele projeto, a tabela mismatch_topic era repetida na tabela mismatch_response, resultando em muita duplicação de dados. V á ria s lînfcas <Je um a tabela parent(paí) s e re la c io n a m co m Varias llntas Je uma tabela cfcîlJ(îll}io).
  • 468.
    controle seus dados,controle seu mundo Em cada uma das tabelas abaixo, existem colunas circuladas que poderiam ser movidas para as suas próprias tabelas. Escreva se cada uma dessas colunas seria melhor representada por uma relação de um-para-um, um-para-muitos ou muitos-para- muitos com a sua tabela original, e depois desenhe a relação na forma de uma linha conectando as duas tabelas, com as setas apontando para os lados apropriados. (endereço) m iffSi i l l i ü f f i l f t f l l i l i j i i l l l . lü ilS i il - H ! . . id_do_tópico nome ([categoria^) wmmmmm . I I I L você está aqui > 441
  • 469.
    qual é relação?solução ® B ® O â © t Em cada uma das tabelas abaixo, existem colunas circuladas que poderiam ser movidas para as suas próprias tabelas. Escreva se cada uma dessas colunas seria melhor representada por uma relação de um-para-um, um-para-muitos ou muitos-para- muitos com a sua tabela original, e depois desenhe a relação na forma de uma linha conectando as duas tabelas, com as setas apontando para os lados apropriados. £© ha um chdeveço para dada usuirio, o «^U C si^niíidâ q y t a jínKa de endereço tem umâ relaçao de um-para-wm dom dada linha de uswario. ismatc id do usuário (endereço) I um— para— um l/ári 105 usua'r,0s tvabaíhar para a mesma iiífflM B M 1 1 IB s S â ië iî I empresa, resultando em uma r e la to de u m -para- muitos en tre uma linha de empresa e varias linhas de usuários- /ári©s usuários podem te r varias amidos, sie^iíidando <^ue as linhas de amidos têm uma relâdao de muitos— para— muitos dom as linhas de usuários. .V 1!?1rrparâ— muitos muitos— para— muitos vários tópidos podem pertender a mesma dâte^oría, resultando em umâ relaçao de um- para— muitos entre umâ linha de date^oria e varias linhas de tópidos. Mas dada tépido nao pode pertender a mais de uma datejoria- Tabelas «y*e dontem uma relação de m u iW p a ra - murtos geralmente são donedtados através de uma ta b e b de jundao, «ue nao é m ostrada a«ui- ÊÊÊSm m : id_do_tópico nome (categorí^ um— parâ— muitos AAO
  • 470.
    controle seus dados,controle seu mundo Espere um momento! Tire um segundo para organizar o banco de dados do Mismatch, para que possamos encontrar os pares imperfeitos. Baixe os arquivos .sql da aplicação Mismatch no site da Alta Books, em www.altabooks.com. br. Esses arquivos contêm as instruções SQL.que criam as tabelas necessárias: mismatch^ user, mismatch_topic e mismatch_response. Certifique-se de rodar a instrução de cada arquivo .sql em uma ferramenta de MySQL, para ter todas as tabelas de que precisa para iniciar o Mismatch. Quando estiver tudo pronto, execute uma instrução DESCRIBE em cada uma das noras tabelas (mismatch_topic e mismatch_response) para checar as suas estruturas. Essas tabelas são importantíssimas para os scripts PHP que estamos prestes a escrever para o Mismatch. você está aqui ► 443
  • 471.
    colocando resposta emmismatch_response Coloque as respostas no banco de dados Embora possa parecer que nós devamos começar gerando o formulário, este depende da existência de dados de resposta na tabela mismatch_response. Portanto, vamos começar pelo começo: temos de "preencher" a tabela mismatch_response com linhas de respostas vazias, na primeira vez que o usuário acessar o questionário. Isso nos permitirá gerar o formulário a partir da tabela mismatch_response sem termos de nos preocupar se o usuário realmentejá forneceu quaisquer respostas. r e s is ta s são dei*adas em brando „a primeira vez. em que o usuano visita o -formular'*©- 3 Os topidos do -formulário, inidialmente, «a© tem respostas esdoihidas, vez. que preendhemos mismatdh__response dom respostas vazias. Assim, do ponto de vista do formulário, sempre existe uma linha de dados, na tabela mismatch_response, para cada questão. Isso significa que, quando o usuário submete o formulário, nós apenas atualizamos as linhas de dados para cada resposta fornecida. Agora que o usuário respondeu a algumas das questões, ftós temos dados de resposta reais para armazenar «a tabela mismatdh_ response- Embora o processo dc sc armazenar respostas no banco do Mismatch tenha, em última análise, dois passos, o primeiro deles (INSERT) só ocorre umavezpara cada usuário. Uma vez que as respostas vazias tenham sido adicionadas, todas as modificações futuras são realizadas no segundo passo, por meio de UPDATEs SQL. A.A& ran/í(ífn à As respostas são âtudiiz^dds nc bãndo de dados, para registrar as m-formâdoes -fomedidas feio usuário-
  • 472.
    controle seus dados,controle seu mundo fciíis de ôeladefm dç PHP &My$QL 1 O código seguinte cuida de inserir respostas vazias na tabela mismatch^. | I response, na primeira vez em que o usuário visita o formulário. Ele também j I atualiza as respostas quando o usuário faz modificações e submete o formulário. Infelizmente, parte do código se perdeu e precisa ser reestabelecida. Use os imas para completar o código que está faltando. / / S e este usuário jamais respondeu ao questionário, inserir respostas vazias no banco de dados $query = "SELECT * FROM mismatch__response WHERE user_id = ” ' . $_SESSION ['user__ i d ’] . $data = mysqli_query($dbc, $query} ; if ( ......... .............. ($data) == 0) { // Primeiramente, obtém a lista de IDs dos tópicos a partir da respectiva tabela $query = "SELECT............ FROM mismatch_topic ORDER BY category_id, topic_id"; $data = mysqli_query($dbc, $query); $topicIDs = array(); while ($row = mysgli_fetch_array($data)) { array_push($topicIDs, $row[rtopic_id']); } // Insere linhas de respostas na tabela respectiva, uma para cada tópico foreach ($topicIDs as $topic_id) { $query = ” .................... mismatch_response " . - ( .............. , ............... ) VALUES ('" . $_SESSION ['user_íd']. $topic_id')"; mysqli_query ($dbc, $query) } } // Se o formulário tiver sido submetido, escreve as respostas no banco if (isset {$__POST[1submit’]) ) { // Escreve as linhas de respostas na respectiva tabela foreach ($__POST as $response_id => $response) { $query = " mismatch_response response = '$response' "WHERE = '$response_id’"; mysqli_query($dbc,.$query); } echo '<p>As suas respostas foram registradas.</p>’; }
  • 473.
    ímãs php &mysql solução jgF | Imas de Geladeira d®PHP & M/SoL - Solução 1 0 código seguinte cuida de inserir respostas vazias na tabela mismatch_response, na I primeira vez em que o usuário visita o formulário. Ele também atualiza as respostas I quando o usuário faz modificações e submete o formulário. Infelizmente, parte do etóittlW# código se perdeu e precisa ser reestabelecida. Use os imas para completar o código que está faltando. // Se este usuário jamais respondeu ao questionário, inserir respostas vazias no banco de dados $query = "SELECT * FROM mismatch_response WHERE user_id SESSION['user_id'] . ’ ’ $data = mysqli_query($dbc, $query) ; Vcri-pida SC ê Consulta retornou O linhas de dados... nâo ha dados^ if ( mysqli_num_rows |.($data) == 0) { // Primeiramente, obtém a lista de IDs dos tópicos a partir da respectiva tabela OM mismatch_topic ORDER BY category_id, V $data = mysqli_query ($dbc, $query) ; Pára ^erâir w array V3ZJO de ÇtopicIDs = array O ; respostas, primeiramente »»0s temos de obter todos os topiCos, na respectiva tabela $query = "SELECT topic id”; while ($row = mysqli_fetch_array($data)) { array p u s h ($topicIDs, $row['topic_id']); // Insere linhas de respostas na tabela respectiva, uma para cada tópico foreach ($topicIDs as $topic_id) { $query = " . . "( '$topic_id1)” inysqli query($dbc, $query) ; mismatch_response " . VALUES ('" . $_SESSI0N ['user__id' AJinha da resposta se enfiontra nao respondida neste ponto, ^ urwâ vez. q«e o usuário ainda nao j escolheu adoro ou ' odeiow no ■formulário. // Se o formulário tiver sido submetido, escreve as respostas no banco if (isset(S_P0ST[1submit'])) { // Escreve as linhas de respostas na respectiva tabela foreach ($ POST as $response_id => $response) { $query = " , mismatch_response "WHERE I response id i|= '$response_id' mysqli_query($dbc, $query); } echo '<p>As suas respostas foram registradas-</p>' response = '$response' V Só o que mudd quândo ousuário submete o -formulário e 3 Coluna resposta da respectiva tabela, portanto é só isso que nósatualizamos.
  • 474.
    não existem Fetgimtas Idiotas •Qual é a da função array_push()? Acho que ainda não usamos essa função.. Realmente, ainda não a usamos, porqueainda não precisamos criar umarray dinamicamente, umelementode cada vez. Afunção array_push() anexa umnovo elemento ao final do array, fazendo-o crescer emumelemento. N ocódigo da página anterior, nós estamos usando array_ push() para criarumarrayde IDsde tópicosa partir da tabela mismatchjopic. Esse array é então usado para se inserirrespostas em branco natabela mismatch_response... uma para cada tópico.. controle seus dados, controle seu mundo Use INSERT para adicionar linhas vazias de Q respostas ao banco de dados, na primeira vez que o usuário acessai Ba»/ A&abâmos dc afieríav dois toeiHos viH>aU dom uma cajadada so, e agora já -temos »*e£ade do sdtripi pv-onio. í J Use UPDATH^pãrâPIfiodificar as linhas de respostas com base nas informações fornecidas pelo usuário. Mas a'mda íal-fca» dois passos fava podermos tomctav- a favcs no £ Use SELECT para obter os dados necessários para se gerar o form ulário. T l Gere o formulário HTML com o questionário a partir dos dados de resposta. você está aqui ► 449
  • 475.
    utilizando formulários comandadospor dados Épossível comandar um formulário com dados Não é novidade que formulários web sãousados para se obter dados Q g dos usuários através de campos de texto, listas de seleção, botões de rádio, etc., mas pode não ser muito óbvio o fato de que você pode gerar formulários HTML a partir de dados do banco, usando PHP. Aideia, no caso do Mismatch, é gerar dinamicamente um formulário HTML contendo o questionário criado a partir de dados de resposta. O script do formulário assume quejá existem dados de resposta, o que o permite gerar o formulário a partir da tabela mismatch_response. Nós sabemos que é seguro assumirisso, porque acabamos de escrever o código que adiciona respostas vazias na primeira vezque o usuário visitao formulário. $ dHâve primária response_jd c fcsâdâ pèirâ ide*tií»dar mdWidwalmChtÉ os da»*pos do -formulário H T M t e sí assodiar tèdâ dâropo tom un*a ImHS do bardo- 0 dodigo do íormulario ttT/WL e jerado a partir primária do ba*do- / de dados na tabela miSmátdh_respohsc. re s p o n s e jd ^ ^ response userjd c o m ^ d a d o s p o r dadps (data-drlVe) dependem de dadps ^resentes em um ?moo M/SqL para gerar campos de íp rm u lá rip s H T M L . Os da»pos do £cm*i*lário sôo vindulados a linhas do bâftdo dc^m m do-sc o «on»€ de dada dantpo do»o a cbsve topic.i d ^ i r <form method="pcst" ac;ior.=”"> <p>How do you feel about each <fieldset> <-sgend>Appearance</iegend> ■ clabei for=’-76">TattooS:</iabel><input type=-radio />Love <mput type="radio" id«"7 7»name="7 7 " />Loveabel f°r=,,78">Bo^ Pacings:</label><ira e" />Hate<br /> <mput type^’ radio" id- <label for />Lo v < 5 <inr)u O form ulário reflete as respostas do usuário para cada tópico.
  • 476.
    controle seus dados,controle seu mundo Kcício 0 questionário do Mismatch é gerado a partir de respostas do usuário que são armazenadas na tabela mismatch_response. Para gerarmos o código do formulário HTML, é necessário ler essas respostas, certificando-nos de verificar o nome do tópico e o da categoria para cada resposta, na tabela mismatchjopic. Ocódigo a seguir cria um array de respostas com tópicos e categorias, realizando duas consultas: a primeira obtém as respostas do usuário, enquanto que a segunda verifica o tópico e a categoria para cada resposta, Oproblema é que parte do código está faltando... preencha as lacunas para fazê-lo funcionar! jW ay de tor* -fcópidos c Ss*~ £atejo**iâs. ^ 76 1 Love Tattoos Appearance 77 2 Love Gold chains Appearance 78 3 Love Body piercings Appearance 79 4 Love Cowboy boots Appearance 80 5 Love Long hair Appearance 81 6 Hate Reality TV Entertainment 82 7 Love Professional wrestling Entertainment 83 8 Love Horror movies Entertainment / / O btém o s d a d o s d e r e s p o s t a d o b a n c o , p a r a g e r a r o f o r m u lá r i o $ q u e r y = "SELECT r e s p o n s e _ id , t o p i c _ i d , re s p o n s e FROM m is m a tc h _ re s p o n s e " . "WHERE u s e r _ id = ' " . $ _ S E S S IO N [ 'u s e r _ i d ’ ] . $ d a ta = m y s q li_ q u e r y ( $ d b c , Ç q u e ry ) ; $ re s p o n s e s = a r r a y ( ) ; w h ile ($ ro w = m y s q l i_ f e t c h _ a r r a y ( $ d a t a ) ) { / / V e r i f i c a o nome d o t ó p ic o c o r r e s p o n d e n te à r e s p o s t a , na t a b e la d o s t ó p ic o s $ q u e ry 2 = " ............................................................................................................................ ” . "WHERE t o p i c _ i d = . $ ro w [ 't o p i c _ i d ' ] . P H P iHí i « W 4 ? d a t a 2 = m Y s q l i _ q u e r y ( $ d b c , ........... ); . . . i f {m y s q li_ n u m _ ro w s ( ......... ........... ) = = 1) { quantas i« as $ ro w 2 = m y s q li_ f e t c h _ a r r a y ( $ d a t a 2 ) / de dados-roram $ ro w [ r to p ic _ n a m e 1] = vC“fcov^adas tomo $ ro w [ ' c a te g o ry _ n a m e ' ] = resultado^ da a r r a y _ p u s h ( ^ r e s p o n s e s , $ ro w ) ; tonsvii'ta- } } você está aqui ► 451
  • 477.
    R c ício SoLuÇão 0 questionário do Mismatch é gerado a partir de respostas do usuário que são armazenadas na tabela mismatch_response. Para gerarmos o código do formulário HTML, é necessário ler essas respostas, certificando-nos de verificar o nome do tópico e o da categoria para cada resposta, na tabela mismatch_topic. Ocódigo a seguir cria um array de respostas com tópicos e categorias, realizando duas consultas: a primeira obtém as respostas do usuário, enquanto que a segunda verifica o tópico e a categoria para cada resposta. O problema é que parte do código está faltando,., preencha as lacunas para fazê-lo funcionar! 0 array fresponses serve tomo uma "tabela" t«>*porária de dados de resposta a serem usados para se gerar o -rormulãrio- A rray de respostas íompieto, dom tépidos e dategorias. A ÍP do topido t usada para se adhar os nomes do topido c da date^o^'â; a p a rtir da tabela mismatdh__topid- 76 /A Love Tattoos Appearance 77 M Love Gold chains Appearance 78 3 Lève Body piercings Appearance 79 4 Love Cowboy boots Appearance 80 5 Love Long hair Appearance 81 6 Hate Reality TV Entertainment 82 7 Love Professional wrestling Entertainment 83 w Love Horror movies Entertainment . ^ Certi-Pique— de haver dados de resposta aqui. / / O btém o s d a d o s d e r e s p o s ta d o b a n c o , p a r a g e r a r o f o r m u lá r i o $ q u e r y = "SELECT r e s p o n s e _ id , t o p i c _ i d , re s p o n s e FROM m is m a tc h _ re s p o n s e " . "WHERE u s e r _ id = 1" . $ _ S E S S IO N [ ’ u s e r _ i d 1] $ d a ta = m y s q li_ q u e r y ( $ d b c , $ q u e r y ) ; $ r e s p o n s e s = a r r a y { ) ; w h ile ($ ro w = m y s q l i_ f e t c h _ a r r a y ( $ d a t a ) ) { / / V e r i f i c a o nome d o t ó p ic o c o r r e s p o n d e n te à r e s p o s t a , na t a b e la d o s t ó p ic o s $ q u e r y 2 - " ... S E L E C T . .*?àm.e, d â tegory mismptt^.h^.topid................ "WHERE t o p i c _ i d = . $ ro w j, ’ t o p i c i d ' ] . $ d a ta 2 = m y s q li_ q u e r y ($tdbc, .?query2-. j ; i f ( m y s q li num r o w s ( _ 7 _ d a k 2 -j. = = i ) { é murtoimj**ta*teusarw ow as «ariáveispartserealizaruma segwwiò tar&ulta (m-tema), de modo <ue ã tWiSul-fca criminal rào sejaafetada } $ ro w 2 = m y s q l i_ f e t c h _ a r r ^ y $ r o w [ 't o p ic ^ n a m e ' ] = ....fr ? ............................. $ ro w [ ' c a t e g o r y name ' ] = fro y /Z rd a ^ ^ o r y ,;]; a r r a y _ p u s h ( $ r e s p o n s e s , $ r o w ) ; ' A íunção MRAV-PMSHO adidiona um vtem para o Cs «omes do topido e da r ^ y ( $ d a ta 2 j) ; ___dategoria sao adidionddos Ao í ^ array de resposta, atribuindo- se dados originários dâ segunda donsultâ- •final de u» array- «f Use para obter os dados necessários para se gerar o
  • 478.
    controle seus dados,controle seu mundo A reposta do usuário é armazenada como texto no banco de dados, como "Adoro" ou "Odeio" literalmente? Se sim, isso não seria pouco eficiente? Não e Sim , e é por isso que é im portante usar o tipo de dados m ais eficien te possívei para arm azenar dados em um banco MySQL. Pensando bem, uma resposta no Mismatch é na verdade uma resposta do tipo true/false (verdadeiro/falso), porque ela é sempre um (adoro) ou o outro valor (odeio).Na verdade, um terceiro valor (desconhecido) pode ser útil para informar à aplicação que o usuário ainda não respondeu um determinado tópico. Então, nós precisamos manter registro de três valores possíveis para cada resposta. Esse tipo de problema de armazenamento é ideal para um número, como por exemplo, TINYINT. Com esse tipo de dados, basta você usar diferentes valores numéricos para representar cada resposta possível. ? V 0 Desconhecido = 0 Adoro = 1 Odeio 2 Minimizar os requerimentos de armazenamento de dados é uma parte importante do projeto de bancos de dados, e neste caso é uma parte sutil, porém, importante da aplicação Mismatch. Essas respostas numéricas desempenham um papel direto na geração de campos do formulário do Mismatch. — ^Aponte seulápis Não sc preoiupe i-©** os botões de radio p3r3 > JOdeio” por en^âwfco — eles s3o gerados e'^âtsw'ewte da n>esmd-forma- O seguinte código faz um ioop através do array de respostas que você acabou de criar, gerando um campo do formulário HTML para cada botão de rádio "Adoro". Escreva o código que está faltando para que o campo fique inicialmente marcado, caso a resposta seja definida como "adoro" (1). Além disso, certifique-se de que o valor da tag <input> seja definido corretamente. f o r e a c h ($ re s p o n s e s a s $ re s p o n s e ) { i f ( ................................................................. ) { e c h o 1c i n p u t t y p e = " r a d i o " n a m e = " ' . $ r e s p o n s e ['r e s p o n s e _ i d '] ' " v a lu e = c h e c k e d = ........................./> L o v e ' ; } e ls e { e c h o '< i n p u t t y p e = ''r a d io " n a m e = "1 . $ re s p o n s e [ ’ r e s p o n s e _ id ' ] . v a lu e = .......... /> A d o ro } você está aqui ► 453
  • 479.
    aponte seu lápissolução Iiponte seu lápis Solupão O seguinte código faz um loop através do array de respostas que você acabou de criar, gerando um campo do formulário HTML para cada botão de rádio "Adoro". Escreva o código que está faltando para que o campo fique inicialmente marcado, caso a resposta seja definida como "adoro" (1). Além disso, certifique-se de que o valor da tag <input> seja definido corretamente.. 0 botão de rádio para "Adoro" e mardâáodom base «o valor da resposta 0 representa adoro no bando)- f oreach ($responses/as $response) { Se c s k resposta -kr deíinida "adoro” (l)} marda o botão de seleção, de-Pinindo / o seu atributo dhedked dom o / valor "dtiedked" i f (. f responsçrrespcms^J I......... ) { / echo ’<input type="radio" n a in e - " '^ . $response [1response_id' ] '" v alue= BIW checked= W dhedkedW />Love 1; } else { echo 'cinput tjpe="radio' value= wl />Love 1 @ va^ à s tag <input> t definido domo I >para ^ue -Pi^ue mais -Pádii de arm azenar a resposta m bando, ^ua^do o -formulário ío r submetido. ="' . $ r e s p o n s e ['r e s p o n s e _ i d ' Deitar dfcedked^tkedkedf resulta m> botão de seledâo íid a r deswardado, se a resposta não estiver de-Pinida domo "adoro” íí)- foreach (Sresponses as Sresponse) { if ($response['response 1) == 2) { echo 'cinput type="radio" name=" value="2" cnecked="checked" 1 . $response [’ .response_id’] . />Hate ' ; else ( echo 'cinput type="radio" name=” 1" value=”2” />Biate V ; ' . . $response [ . 1response_id'] . 1 A Caso esteja durioso, 0 dodigo para gerar os botões "Odeio" íundiona exatam ente da mesma torm a - ele apegas produra por uma resposta ligeiramente di-Perente- verdade, existe uma maneira mais elegante de jje ra r ta n to os botoes "Adoro" quanto 05 $deio dom menos dodigo-..
  • 480.
    controle seus dados,controle seu mundo Falando em eficiência... A eficiência do banco de dados não é o único tipo de eficiência que vale a pena considerar. Há também a eficiência do código, que pode vir em muitas formas. Uma forma é tirando-se proveito da linguagem PHP para simplificar declarações if-else. O operador ternário é uma forma útil de se programar declarações if-else simples, de modo que elas fiquem mais compactas. Sc a &*pressaoDe7este /*“ -for verdadeira (true), a JL Insbruçaol é executada. E xp ressã o D eT este^T jln stru çã o lInstrução true 0 operador ternãtiP ? : pode ser usadp para se programar declarações íí-e lse de uma Çprmamais compacta- false Se 3 E*pressãoDeTeste f<*" ■falsa (-faUc), 3 detlar3Ç3o2- e e*etwtdda. O operador ternário, na verdade, é apenas um atalho para se escrever uma declaração if-else. Ele pode ser útil para simplificar essas declarações, especialmente quando você está fazendo uma atribuição de variável ou gerando código HTML em resposta à condição if. Eis aqui o mesmo código para o botão de seleção "Adoro", reescrito para usar o operador ternário: e ch o ’ < in p u t t y p e = " r a d io " n a m e -'" . $ re s p o n s e [ ' r e s p o n s e _ id ' I& ÍM Ím ííM iiiiia iis i *i Este teste true/•false Controla o J resultado do operador ternário. Se o valor de resposta armazenado em $response ['response'] for igual a 1, então o atributo checked será gerado como parte da tag <input>, resultando no seguinte botão de seleção "Adoro", marcado: " * v a lu e = " l" ' . . ' /> A d o r o ' ; 0 atrib u to checked da ia s <ir»put> a^ora c gerado usando— se o operador ternário, em vez. de uma declaracao -f-eise- 1 Por outro lado, um valor de resposta diferente de 1impedirá o atributo checked de ser gerado, resultando em uma tag <input> não marcada para o botão "Adoro". você está aqui ► 455
  • 481.
    Gere o formuláriodo questionário Mismatch o script inteiro questionnaire.php Agora nósjá temos pedaços suficientes do questionário do Mismatch para usarmos o array de resposta ($responses) que criamos anteriormente para gerar o formulário HTML inteiro. Lembre-se, esse array foi construído obtendo-se as respostas atuais do usuário presentes na tabela mismatch_response. Vamos ver o código de geração do questionário no contexto do script questiónnaire.php inteiro. Ihilui os arquivos tem plate que ihiÊiâm a sessão e exibe» o cabeçalho da p%i»a. a questionnaire.php Í^estv“ ih0e a pagina aos usuirtos locados. <?php // Inicia a sessão require__once (1startsession .php') // Insere o cabeçalho da página $page_title = 'Questionnaire'; require once{'header.php'); require_once('appvars.php'); require_once('connectvars.php' ) // Assegura que o usuário está logado antes de seguir adiantj if (!isset($_SES5I0N['user_id'])) { echo '<p class="login">Por favor <a href="login.php"> faça </a> login para acessar esta página.</p>'; exit); } // Mostra o menu de navegação require_once('navmenu.php' ) ; // Conecta-se ao banco de dados $dbc = mysqli_connect(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME); / / S e este usuário jamais respondeu ao questionário, inserir respostas vazias no banco $query = "SELECT * FROM mismatch_response WHERE user_id = . $_SESSION['user_id'] . ; $data = mysqli_query($dbc, $query); if (mysqli_num_rows($data) == 0) { // Primeiramente, obtém a . lista de IDs dos tópicos a partir da respectiva tabela $query = "SELECT topic__id FROM mismatch_topic ORDER BY category_id, topic_id"; ?data = mysqli_query($dbc, $query); $topicIDs = arrayO; while ($row = mysqli_fetch__array ($data) ) { array_push($topicIDs, $row['topic_id']); } I I Insere linhas de respostas na tabela respectiva, foreach (ÇtopicIDs as $topic_id) { $query = "INSERT INTO mismatch_response (user_id, SESSION[1user_id'] . "', 1$topic_id')"; mysqli_query($dbc, $query); } uma para cada tópico topic_id) VALUES (1" . $ // Se o questionário tiver sido submetido, escreve as respostas do formulário no banco if (isset($_POST['submit1])) { // Escreve as linhas de respostas do questionário na tabela de respostas foreach ($_P0ST as $response_id => Srespons.e) { $query = "UPDATE mismatch_response SET response = '$response' " .
  • 482.
    controle seus dados,controle seu mundo "WHERE response_id = '$response_id'"; mysqli_query($dbc, $query); } echo '<p>As suas respostas foram registradas..</p>’; } O ( // Obtém os dados de resposta do banco, para gerar o formulário $query = "SELECT response_id, topic_id, response FROM mismatch_response WHERE user_id = ’" . $_SESSION ['user_id1] . $data = mysqli_query($dbc, $query); Çresponses = array (); while ($row = mysqli_fetch_array($data)) { // Verifica o nome do tópico correspondente à resposta, na tabela dos tópicos $query2 = "SELECT'namef category FROM mismatch_topic WHERE topic_id = ’" . $row[1topic_id’] . $data2 = mysqli_query{$dbc, $query2); if (mysqli_num_rows($data2) == 1) { $row2 = mysqli_fetch_array($data2); $row[’topic_name1] = $row2 [1name ’]; $row [rcategory__namer] = $row2[’category’ array_push($responses, $row); } mysqli close($dbc); ôbiem a categoria da Cada dategoria e primeira resposta, tríada domo w* para inidiar o dowjuivtode tampos, prodesso ãnies de ^y-a ajudar a entrar no loop. organizar os topidos. // Insere a página require_once{’footer.php’); Cada w*a destas iftstsn*doesedKo gera um botao de selelâo - w para ftàaro’ e outro pâra ôdóo - Lembre— se, —adoro e 2. —odeio- rotulo seguido de botoes de seleção "hdcK o e "O dãa • X Ge Q o c I da Ger#o fOFAufário HTML com o questionário a partir dos dados de resposta. você está aqui ► 457
  • 483.
    test drive questionaire.php TtesTORive Teste o novo questionário do Mismatch. Modifique o Mismatch para que ele use o novo script do questionário, (ou baixe a aplicação no site da Alta Books, em wvw.altabooks.com.br). Para isso, você terá de criar um novo script questionnaire.php, bem como adicionar um item de menu “Questionário”ao script navmenu.php, para que os usuários possam acessá-lo. Envie os scripts para o seu servidor web e depois abra a página principal do Mismatch (index.php) em um navegador. Certifique-se de fazer login, e então clique no item de menu "Questionário”para acessá-lo. Repare que nenhum dos tópicos tem repostas, uma vez que esta é a sua primeira visita ao questionário. Responda aos itens e submeta o formulário. Retorne à página principal, e depois volte ao questionário para confirmar que as suas respostas foram corretamente carregadas a partir do banco de dadòs. 0 seríp-fc d© questionário permite °[^c os usuários responda*. a i-fcchs ddoro/odeio e armâz«hem os resultados ho bân£o de dados. Howdoyoufedabouteachtopic? —Appearance Tattoos: GoW chains: ULove 0Haß 0Love QHate £Love 0Haie ^Love ©Haie #Love ©Hate Bodypiercings: Cowboyboots: Longhair; —Fnterrainment- RealityTV: Professional wrestling: OLove IgHate - se vofiê aditio^ar r.ovos topidos, o -Çormulari© se modiíitârá- questões ho iormulario são geradas d'inav*i£àw*.eft£e a p a rtir do bahfio de dados O código-fonte completo da aplicaçao Mismatch está disponível para download no site da Alta Books: www. a lta b o o k s.com .br ► If
  • 484.
    controle seus dados,controle seu mundo nab existem p e rg u n te is I d io fö s P - Como o botão de seleção “Adoro" sabe que o resultado do operador ternário é uma string? 0 operador ternário sempre resolve em uma das duas instruções separadas pelos doís-pontos, com base no vaíor (true ou false) da expressão de teste. Se essas instruções forem strings, então o resultado do operador será uma string. É isso que torna o operador tão útil - você pode inseri-lo no meio de uma atribuição ou concatenação. • O operador ternário faz o meu script rodar mais rápido? Não, provavelmente não. O operador ternário serve para adicionar eficiência estilística ao seu código, e não exatamente para melhorar a eficiência do desempenho, o que significa dizer que a sua vantagem é exigir menos linhas de código. Em alguns casos, é mais conciso usar o operador ternário do que uma declaração if-else completa, embora os dois sejam logicamente equivalentes. Mesmo assim, não fique muito entusiasmado com o operador ternário, porque ele pode tornar o código mais difícil de entender, caso você esteja tentando substituir uma declaração if-else complexa. A ideia é usar o operador ternário em lugares onde a eliminação do if-else pode realmente ajudar a simplificar o código, em vez de torná-lo mais complicado. Isso geralmente envolve usar o operador para controlar seletivamente um valor sendo atribuído a uma variável ou inserido em uma expressão. No caso dos botões de seleção do Mismatch, esta última abordagem foi usada para se controlar seletivamente a inserção de um atributo HTML (checked). - Como é possível gerar o questionário do Mismatch a partir da tabela mismatch_response, quando o usuário ainda não respondeu a nenhum tópico? Excelente pergunta. O formulário do questionário tem de lidar com dois cenários possíveis: o usuário está respondendo ao questionário pela primeira vez, ou o usuário já o respondeu e está revendo as respostas. No primeiro cenário, não há nenhuma resposta ainda, portanto a tabela mismatch_response ainda não tem dados para este usuário. Mas nós ainda temos de gerar o formulário dinamicamente. Poderíamos usar a tabela mismatch_topic para isso. Porém, não funcionaria para o segundo cenário, porque desta vez o formulário precisa ser gerado com base nas respostas específicas do usuário; lembre-se, os botões de seleção para "Adoro" e "Odeio” são gerados como parte do formulário. Assim, nós temos um problema, no sentido que o código para gerar o formulário é completamente diferente, dependendo de se os usuários já responderam ou não o questionário. Não apenas isso, e se o usuário tiver respondido apenas a algumas questões? Pode ficar muito complicado bem rápido. A solução adotada pelo Mismatch é preencher antecipadamente a tabela mismatch^response com respostas em branco, na primeira vez que o usuário acessa o questionário. Isso nos permite sempre gerar o formulário a partir da tabela mismatch_response, e não precisamos nos preocupar com a complicação de gerar o formulário diferentemente dependendo de se o usuário já respondeu ou não ou de quais tópicos ele tenha respondido. É claro que o código para geração do formulário ainda não é exatamente trivial, mas é mais simples do que se não tivéssemos usado esta abordagem. Para s»v*pli-Pi£ar o o Misma-fcdh »ao sc ajusta F - i O autowatidam ehte 3 -novos tépidos, pelo meros »ao *0 r 3-9*1 ^ S tc l ^ que se re-fere a usuários que la tenH a* respondido o , E x p e í f e n c i a ! < V*«st |ot’ tfrio- Assim, vodê te ra de esvaziar a tabela ^ »>is»»*atdH_respoKse após adidionar um novo topido. O Adicione um novo tópico à sua própria tabela mismatch_topic, com esta instrução SQL: INSERT IN TO m is m a tc h _ to p ic (na m e , c a te g o r y ) VALUES ( ' V i r t u a l g u i t a r s ' , ' A c t i v i t i e s ' ) 0 Esvazie todos os dados da tabela mismafch_response, com esta instrução SQL: DELETE FROM m is m a tc h _ re s p o n s e o Visualize o questionário na aplicação Mismatch para ver o novo tópico. Q Responda ao novo tópico, submeta o formulário e verifique a sua resposta gravada. você está aqui ► 459
  • 485.
    lidar com dadosruins do banco de dados Agora os dados estão comandando o formulário Foi preciso algum trabalho, mas agora a aplicação Misraatch está gerando dinamicamente o questionário a partir de respostas armazenadas no banco de dados. Isso significa que quaisquer modificações feitas ao banco serão automaticamente refletidas no formulário —essa é a vantagem de se gerar a interface de usuário de uma aplicação web a partir de ura banco de dados. Mas o que acontece quando nós temos dados inválidos? l Ä j l ß ä ü ö ä i l l l j j ä E1p 1h 111í 1 re sp o n se jd response u s e rjd to p ic jd topicJd category How do yon lesäaboateachtapie? Estes tmes donjuntos de da>*pos deveria» sev- um so, de »odo ^ue todos os topidos de Entvetenim ento ii^uew* juntos. 0 -formulário e gerado de -forma ta l <ue u»a mudança de date^oría resulta e» um novo óorvjunto de da»pos, ^ue é o motivo pelo ojual »ais um Conjunto desnede*saHo t Lriado a<ui- —Appearance-----------— Tattoos: ©Lave 9 Hate Gold chains: ©Love # H aie Body piercings: ©L0V2 #H3K Cowboy toots: igLove @Hafe Long hair: 9 Love Q H ate —Entertainment------------- Reality TV : (SLove 0Hate Professonal wrestling: 0 Lovc # H aie Horror movies.’ © Love 0 Haie i-Eat&rtimDeni — - ' Easy &te5ng Omsk; 9 Lore ©Hate —EnttftaiiBsent -............................ .... Hie opera: © Love QHste ’ —Food Sushi: #Love OHare l Spun: 0 Lovc @Hate 1 Spicy food: @ Lovc ©Hale um erro de digitaçao nesta W tegona, o ^ue resulta nela apareder no seu próprio doiÿunio At dâmpos no •formulário, o ^ue e bastânte don-fuso. Os dados estão determinando o formulário como queríamos, mas algo ainda está errado. Parece que uma das categorias foi escrita no banco de dados com um erro de digitação, fazendo o código PHP gerar um conjunto de campos separado para ela. Isso é um grande problema, porque arruina o efeito de se usar conjuntos para ajudar a organizar o formulário e facilitar a resposta aos tópicos.
  • 486.
    controle seus dados,controle seu mundo mismatch topic Ok, entao uma das categorias foi escrita com um erro de digitação no banco, o que está estragando o nosso formulário. Como vocês acham que devemos consertar isso? Kos j i sabemos que e s t a ^ / i r ta te jo ria dom ev-ro de di^i-fcaçao esÜ dausand© pvoblemâs — e aqui temos mais uma £3usâ*do o mesmo pvobíemâ «o í^rmv*iav*io- Frank: É fácil. É só corrigir a grafia da categoria na tabela mismatch_topic. Joe: Mas tem mais de uma categoria escrita errada. E agora que pensei nisso, não entendo por que os nomes das categorias têm de ser armazenados mais de uma vez. Jill: Concordo. Nós nos demos ao trabalho de eliminar dados duplicados ao projetarmos o esquema do banco de dados, e aqui estamos nós com um monte de nomes de categorias duplicados. E não apenas isso, mas temos até alguns nomes com erros de digitação. Frank: Ok, e se nos livrássemos dos nomes das categorias, e talvez fizéssemos a referência a elas por números? Assim não haveria o risco de termos erros de digitação. Joe: Everdade, mas ainda precisamos dos nomes das categorias para usá-los como títulos no questionário. Jill: Talvez possamos nos referir às categorias por número, semjogar fora os nomes. E mais ou menos o quejá estamos fazendo com os tópicos na tabela mismatch_topic, não é? Joe: Certo! Nós não queríamos armazenar um monte de nomes de tópicos duplicados na tabela mismatch_response, e portanto, colocamos esses nomes na tabela mismatch_topic, e vinculamos os tópicos às repostas usando chaves numéricas. Frank: Vocês estão dizendo que poderíamos resolver o problema dos nomes de categorias duplicados criando uma nova tabela para as categorias? Jill: E exatamente isso. Nós podemos criar uma nova tabela mismatch_category, onde cada nome de categoria é armazenado exatamente uma vez. E depois, conectamos as categorias aos tópicos usando chaves primárias e estrangeiras entre mismatch_topic e mismatch^ category. Brilhante! você está aqui ► 461
  • 487.
    normalizando seus dados Nlorrrtal«'®slgruífca Procure por um pouco de normalidade e laW üm O processo de reelaborar o banco de dados do Mismatch de modo clckl0 5 d e Ul°cl0 cl a eliminar dados duplicados, e a dividir e conectar tabelas de uma forma lógicae consistente é conhecido como normalização. A JXíduZJl’ a d UPlíC3C3p normalização é um assunto relativamente aprofundado no que i ‘ diz respeito ao projeto de bancos de dados, e pode ser um tanto d ad °S e a intimidante. Mas não precisa ser. Existem váriastécnicas simples de projeto de bancos de dados, das quais nós podemos nos aproveitar m e lllP ta í ctS íelaÇ ^eS para tomar os nossos bancos MySQLmuito melhores do que se simplesmente tentássemos adivinhar como é que os dados ellt^e PS dadPS- deveriam ser dispostos. Eis alguns passos gerais que você pode usar para iniciar o processo de design do banco de dados, os quais levarão naturalmente a um banco de dados mais "normal": 1. Escolha uma coisa, apertas uma coisa que t- você queira que a tabela descreva. 2. Faça uma lista d as inform ações que você precisa saber sobre e ssa coisa, ao usar ^ a tabela. 3. Usando a lista, divida a s inform ações sobre e ssa coisa em pedaços que você possa usar para organizar a tabela. Um conceito fundamental na normalização é a ideia dos dados atômicos, que são dados divididos até a sua menor forma possível que faça sentido, considerando-se o uso do banco de dados. Por exemplo, as colunas first_name e last_name do banco de dados do Mismatch são atômicas no sentido de que elas dividem o nome do usuário em mais pedaços (primeiro nome e sobrenome) do que uma única coluna para o nome inteiro o faria. Isso é necessário no Mismatch porque queremos poder nos referir ao usuário apenas pelo seu primeiro nome. Talvez não seja sempre necessário que a aplicação divida o nome em colunas separadas para primeiro nome e sobrenome, porém, em cujo caso uma tabela "name" sozinha seria atômica o suficiente. Assim, quando estiver dividindo a "coisa" da tabela em partes, pense em como os dados serão usados, e não apenas no que eles representam. <$ual t a principal iósa que vote quer que seja o assunta da sua tabela? Corno a tabela? vode ira $ual e o vnodo mais %>Lis Aoftsultar essa tabela? Dadps atPUlicos sã.P dadps <]ue {gram díVidídPS ate a nietiPt fpvma necessária para um determinado bancp de dados.
  • 488.
    controle seus dados,controle seu mundo Ao normalizar, pense emtermos de átomos^ Para ajudar a transformar as suas ideias sobre o projeto do banco em ações, é útil fazer perguntas específicas aos seus dados. Isso ajudará a determinar como os dados se encaixam na tabela, e permitirá saber se eles realmente foram divididos até a sua representação atômica apropriada. Ninguém disse que dividir o átomo seria fácil, mas esta lista de perguntas poderá lhe ajudar. JÜft w ‘'V1 U1 V°S se-us dados atômicos e 9 p rim e iro pctSS9 se criar umatabela normalizada. 1.Qual é a principal coisa que a sua tabela descreve? a** ta b e lad e se rv ea v ista m ^ -k »d « 0V^ de uma lista de emails, pc^tuadoes máximas de um videogame, «ornes de româívfcidos inóuvâvcis? 2. Como você U S a t a a tabela para chegar até essa principal coisa? 3. As suas colunas contêm dados atômicos, para tornar suas consultas curtas e diretas? XÃ9 existem ---------------------------------------------------------- " p e rg u n ta s id io ta s — Elabore sua -tâbeia de modo «*e ela seja íádi! de donsultar! Certi-fi^ue-sc de «ue os dados sejam apenas -fcao pequenos Quanto rsedessario. ^ • Eu devo tentar dividir os meus dados até os menores pedaços possíveis? Como os dados atômicos me ajudam? K-.Não necessariamente. Tomar os seus dados atômicos significa dividi-los até os menores pedaços de que você precisa para criar uma tabela eficiente, e não até os menores pedaços possíveis. Não dividia os seus dados mais do que realmente precisar. Se não precisar de colunas extras, não as adicione à toa. í ^ t Eles lhe ajudam a garantir que os dados da sua tabela sejam precisos. Por exemplo, se você tiver uma coluna para o endereço de um avistamento de ETs, poderá querer dividiro endereço em duas colunas: uma para a rua e uma para o número. Então, você poderá certificar-sede registrar apenas números na coluna referente ao número. Os dados atômicos também lhe permitemexecutar consultas de modo mais eficiente, porque as consultas ficam mais fáceis de escrever e rodam em menos tempo, o que é eficiente quando você tem uma quantidade muito grande de dados armazenados. você está aqui ► 463
  • 489.
    normalize a bancode dados do mismatch 0 banco de dados do Mismatch está precisando ser normalizado, para resolver o problema de nomes de categorias duplicados. Dada a estrutura existente do banco, esboce um projeto modificado que resolva esse problema, eliminando o risco de erros na inserção dos dados. Escreva comentários no projeto, explicando como ele funciona. user id username password join_date first name last name gender birthdate city state picture illlliiljjjd ;j*j| r i I^ Q jjt jJ S response id v w " topic id ^ i response name MW i l ) ^ » category tooic iri
  • 490.
    controle seus dados,controle seu mundo TWgutitíis idiotas 1 • Como eu faço para aplicar o terceiro passo de normalização ao Mismatch, para consertar o problema hipotético com a cidade/estado/CEP? A solução é colocar os dados de localização do usuário em uma tabela própria, e então conectar a tabela mismatch_user à nova tabela por meio de uma chave estrangeira. Assim, você poderia criar uma tabela chamada mismatchJocation, com uma chave primária locationjd, junto com colunas para armazenar a cidade e o estado do usuário, por exemplo. Então, as colunas city ("cidade") e state ("esíadò") são removidas de mismatch_user e substituídas por uma chave estrangeira locationjd. Problema resolvido! O que faz esse design funcionar é que a coluna locationjd na verdade usa o CEP como chave primária, eliminando o problema de dependência de colunas que não sejam chaves. ? • Caramba, isso parece um monte de trabalho só para atender a um requerimento de projeto exigente. Isso é realmente necessário? Sim e não. Os dois primeiros passos da normalização são obrigatórios, porque os dados atômicos e as chaves primárias são essenciais para qualquer bom projeto de bancos de dados. É no terceiro passo que vocâ passa a ter que pesar a atratividade de um projeto perfeito, por um iado; contra as realidades práticas do que a aplicação realmente precisa, por outro. No caso do problema com cidade/estado/CEP do Mismatch, provavelmente vale a pena aplicar esse requerimento, pela simplicidade que ele proporciona. Essa não é uma decisão a ser tomada sem pensar bem, e muitos puristas defendem que você deve aderir estritamente a todos três passos. A boa notícia é que a coluna com o CEP é puramente hipotética, e não faz parte realmente da tabela mismatch_ user, portanto não precisamos realmente nos preocupar com ela. • Mesmo sem uma coluna para o CEP, não seria necessário mover city ("cidade") e state ("estado") para as suas próprias tabelas, para atender ao terceiro passo? í ^ ’ Possivelmente. Sem dúvida você acabará tendo dados duplicados, referentes a cidades e estados, na tabela mismatch_user. O problema em separar cidade e estado numa tabela própria, sem uso do CEP, é que você teria de preencher essas tabelas com todas as cidades e estados existentes. Caso contrário, os usuários sem dúvida escreveriam alguns nomes de cidades com erros ortográficos, e ainda acabaria tendo dados problemáticos. Este é um bom exemplo de caso em que você tem que pesar seriamente o benefício da normalização estrita contra a realidade de uma aplicação real.Uma interessante solução possível para todos os problemas é usar o CEP na tabela mismatch_user, em vez de cidade e estado, e então procurar a cidade e o estado em uma tabela estática ou em algum serviço web, conforme necessário. Isso é mais complexidade do que precisamos no momento, portanto vamos ficar com as colunas city (cidade) e state (estado). existem você está aqui ► 467
  • 491.
    a base dedados mismatch—agora normalizada! SoLuÇSo 0 banco de dados do Mismatch está precisando ser normalizado, para resolver o problema de nomes de categorias duplicados. Dada a estrutura existente do banco, esboce umprojeto modificadoque resolva esse problema, eliminando o riscode erros na inserção dos dados. Escreva comentários no projeto, explicando como ele funciona. h nova tabela para as userjd username password join_date first name last name gender birthdate city state picture Lembre-se, mismatch_ response e wmô "tabela de junjao <ue donedta os usuários às respostas cyuC derâm 3os topidos. 0 restan te do Alismatdh não t a íe ta d o pelas modi-fidaçoes has■ d a t e r a s e nos tópidos. dateyw ias arm azena os nomes das d a t e r a s separados dos topidos, eliminando os dados redundantes. dategory__id © — rf name Ihlçiftatcfrtopic topicjd 0 “ "jr name ^gategery: •>. tifejaryjd Em vez. de arm azenar o nome da dategoria em dada linHa de tópido, agora nós armazenamos apenas uma reíerendia (ft>) à linha, na tabela das dategorias. ; Cada linha de dategoria na nova tabela tem uma relaçao de um— para— muitos dom os topidoS da tabela mismatdK__topid- nÊb eXÍStfGl perguntas idiotas I * Como exatamente a nova tabela mismatch, category resolve o problema de dados duplicados? A nova tabela separa os nomes das categorias da tabela mismatchJopic, permitindo que eles sejam armazenados isoladamente. Com as categorias armazenadas em tabela própria, não é mais necessário duplicar os seus nomes - você tem uma linha para cada categoria, e essas linhas são então referenciadas por linhas da tabela mismatchJopic. Isso significa que as linhas de categorias da tabela mismatch_category têm uma relação de um-para-muitos com as linhas de tópicos da tabela mismatchjopic. T * - Então isso significa que mismatch_category tem apenas cinco linhas, uma para cada categoria? Sim, isso mesmo: r o i s m a t c h _ c a t e g o r y 0 nome de dada dategoria só e armazenado umâ vez/ üSklàiii mm J d y liiP P » 1 Appearance 2 --- > - Entertainment 3 Food 4 People 5 Activities
  • 492.
    controle seus dados,controle seu mundo Alterando o banco de dados do Mismatch Para tirar proveito do novo schema, o banco de dados do Mismatch requer algumas modificações estruturais. Mais especificamente, nós precisamos criar uma tabela mismatch_ category, e depois conectá-la a uma nova chave estrangeira na tabela mismatch_topic. E uma vez que a velha coluna category da tabela mismatch_topic, contendo os dados duplicados, não é mais necessária, podemos apagá-la. Crie a nova -tabela ^ue irá ârm az^nar os nor»e$ dâs dategorias isoladamente- category_id INT NOT NULL AUTO_INCREMENT, name VARCHAR(48) NOT NULL, PRIMARY KEY (category id) a an ti5a doluna tategoryj u»a vez. agora irewos re-(-erend»3r as tategorias a p a rtir de tabela prêpriâ- rateaorvjd name ALTER TABLE mismatch topic ALTER TABLE mismatch_topic ^ « l i S Ü H i i l i i INT n o t n u l l Edition« u»a dKave estrangeira dategory_jd, para donedtar dada topido a u»a dategcria da nova tabela- mismatch topic 8 Horror movies 2 9 Easy listening music 2 10 The opera 2 11 Sushi 3 12 Spam 3 13 Spicy food 3 14 peanut butter & banana sandwiches 3 15 Martinis 16 Howard Stern 4 17 Bill Gates 4 18 Barbara Streisand 4 - 4 — - A nova tabela mismatch_category precisa ser preenchida com os dados referentes às categorias, o que é feito através de algumas instruções INSERT. INSERT INTO mismatch_category (name) VALUES (’Appearance'} INSERT INTO mismatch_category ('Entertainment1) (name) VALUES INSERT INTO mismatch_category (name)VALUES ('Food') INSERT INTO mismatch_category (name)VALUES ('People') INSERT INTO mismatch_category (name)VALUES ('Activities' ) A nova coluna category_id precisa, então, ser preenchida com dados para ligar corretamente cada tópico à sua categoria apropriada da tabela mismatch_category. UPDATE mismatch_topic SET category id = 3 WHERE name = 'Martinis' E sta (V deve ser a nscsmâ ID âutoindrem entâdâ «ue a dategoria te » na tabela »isr*atdh__dategory. você está aqui ► 469
  • 493.
    O R fV e test drive as tabelas normalizadas mismatch Crie e preencha a nova tabela m ism atch_category. Usando alguma ferramenta MySQL, execute o comando SQL CREATE TABLE da página anterior para adicionar uma nova tabela, chamada mismatch_category, ao banco de dados do Mismatch. Em seguida, emita instruções INSERT para preencher a tabela com dados referentes às categorias. Agora, execute as duas instruções ALTER para modificar a tabela mismatch_topic para que ela tenha uma coluna category_id. Finalmente, use UPDATE em cada linha da tabela mismatch_topic, para que as suas colunas category_id apontem para a categoria correta na tabela mismatch_category. Agora execute um SELECT em cadauma das tabelas, sópara certificar-se de que está tudo certo. Então, o Mismatch realmente é normal? Sim. Se você aplicar as três regras principais da normalidade a cada uma das tabelas do Mismatch, verá que ele passa no teste com louvor. Mas mesmo se não passasse, nem tudo estaria perdido. Assim como nas pessoas, existem graus de normalidade no que se refere aos bancos de dados. O importante é tentar elaborar bancos que sejam completamente normais, só aceitando menos que isso quando houver um motivo muito bom para burlar as regras. O e e Em todo o ba*do de dados, os homes são n3 sua _____£orma mais atomida, € f sâo repetidos «*ais de uma doluna. | user_id 0 “ username password join.date first_name last name gender iiiäiSimftlliSili« birthdate fjü responsejd ö “ "8 ^ city I O response state ------¥ id / picture topic id Certifique-se de que as suas colunas sejam atômicas. Dê a cada tabela a sua própria chave primária. Certifique-se de as colunas que nâo são chaves não sejam dependentes umas das outras. Todas as tabelas tem dhave primária wum£vi£a; para ^ara^tir a uhiôidãde- Sem a bipotétidâ depe*de*dia Áo CEP, as doUas <^*e se reíerem a lofiaiizadâo do usuário »ao tem mais probiemas de dependerias.
  • 494.
    controle seus dados,controle seu mundo O novo projeto das tabelas do Mismatch não afeta as consultas que estão sendo feitas no código do script do questionário? O i i ü « MÜHR891 category id O""-)* name // Obtém os dados de resposta do banco para gerar o formulário $query = "SELECT response_id, topic_id, response FROM mismatch_response "WHERE user_íd = . $_SESSION['user_id' ] . " ; $data = mysqlí_query($dbc, $query); $responses = array 0; while ($row = mysqli_fetch_array($data)) { // Verifica o nome do tópico correspondente à resposta na tabela dos tópicos $query2 = "SELECT name, category FROM mismatch_top:LC " • "WHERE topic_id = . $row[[topic_id'] . "; $data2 = mysqli_query($dbc, $query2); if (mysqli_num_rows($data2) ==. 1) { $row2 = mysqli_fetch_array($data2); $row[1topic_name' 3 = $row2['name']; $row['category^name1] = $row2[1category']; array_push($responses, $rowj; questionnaire.php Sim. De fato, a maioria das modificações estruturais em bancos de dados exige que nós ajustemos quaisquer consultas que envolvam as tabelas afetadas. Neste caso, modificar o projeto do banco para adicionar a tabela mismatch_ category afeta qualquer consulta envolvendo a tabela mismatch_topic. Isso ocorre porque o projeto anterior tinha as categorias armazenadas diretamente na tabela mismatch_topic. Após colocarmos as categorias na sua própria tabela, o que nós agora sabemos que é uma ótima ideia graças à normalização, torna- se necessário rever as consultas e programá-las para trabalhar com uma nova tabela (mismatch_category). você está aqui ► 471
  • 495.
    usando rotação compontos Ligue com pontos Uma vez que osjoins envolvem mais de uma tabela, é importante ser claro sobre cada coluna referenciada em umjoin. Mais especificamente, você deve identificar a tabela de cada coluna, para não haver nenhuma confusão - diferentes tabelas frequentemente têm colunas com os mesmos nomes, principalmente no que se refere às chaves. Basta prefixar o nome da coluna com o nome da tabela e um ponto. Por exemplo, eis aqui a consulta INNERJOIN anterior, que cria um conjunto de resultados de IDs de tópicos e nomes de categorias: E ste e o Mwe dà doiuna dentro da Anptaçãp com pont°S lfee peO Tite te îe îe n cîa t 3. tabela. à-juEÜ a coluna pertence, detiti'O de umjoin. • £ ste é o nome da tabela- 0 ponto/ tabela, separado do nome da tabela por um ponto- SELECT FROM mismatch__topic INNER JOIN mismatch_category isijiiij«« 1® à £ IS ©wfcra reierendia â ^ _ tabila/èoiw na usando a ta ç a o to*» ponto- not £ a^wi <ue o uso do ponto realmente dompensa - os nomes dâs doiunas são identidos^resultando em ambiguidade total se vote nao espediíidar os nomes das tabelas. Sem a capacidade de especificar as tabelas associadas com as colunas, nesta consulta, nós teríamos uma ambiguidade problemática. Na verdade, seria impossível entender a parte ON da consulta, porque ela estaria verificando se a coluna category_id é igual a ela mesma, presumivelmente dentro da tabela mismatch_topic. Por esse motivo, é sempre uma boa ideia ser bastante explícito na hora de identificar as tabelas associadas com colunas, ao criar consultasJOIN. n u.sm atch_ topic. c a te g o ry id Sozinho, o nome da doiuna rôo nos d»2- nada sobre a ^ual tabela ele pertende- Pentro de uma Consulta OÖlK, o nome desta doiuna lid a a»bí< nao se esqueça do ponto/ mismatch topic i_category (dentiiidar a tabela resulta em uma donsulta Jö lK mais expifdíta. l i s l l ^ f c i s i i í í 1 l;-=A pp^àflce'‘ ': 2 ÏKt-ect^irî^jtiV. 3 i ■fo&p ' .. 1 ... ilr'i-'-;"-- 474 Capítulo 8
  • 496.
    controle seus dados,controle seu mundo Certamente podemos fazer mais comos innerjoins Os innerjoins não servem apenas para combinar dados de duas Um tabelas. Uma vez que um innerjoin é, em última instância, apenas T Q jf^ COOlLullâ uma consulta, você ainda pode usar construtos normais de consultas para controlar ainda mais os resultados. Por exemplo, linhas de duas caso queira obter uma linha específica do conjunto de resultados unidos, você pode colocar uma instrução WHERE na consulta INNERJOIN para isolar apenas essa linha. SELECT m is m a tc h _ to p ic . t o p ic _ id , m is m a tc h _ c a te g o r y . name FROM m is m a tc h _ _ to p ic INNER JO IN m is m a tc h c a te g o r y tabelas usando opetadotes de c o m p a ra ç ã o eIfl uma condiçap. ON ( m is m a tc h _ to p ic . c a te g o r y _ id = m is m a tc h _ c a te g o r y . c a te g o r y _ id ) IsIIlimillflíf«ÍI4ÍÍHr«ííH fllifíHlííiíli Então, o que é que esta consulta retorna, exatamente? Lembre-se, primeiramente, que a cláusula WHERE serve como um refinamento da consulta anterior. Em outras palavras, ela restringe o número de linhas retornadas pela consulta INNERJOIN original. Para recapitulação, eis aqui os resultados do innerjoin sem a cláusula WHERE: Esta fioluna reíina os (resultados, iowo parte de ur*a instrudao WH£R£. ' M IDs dos tópidos sao e*traídas da tabela mis^atdK topií- 1 Appearance 2 Appearance 3 Appearance 4 Appearance 5 Appearance 6 Entertainment 7 Entertainment 8 Entertainment Estas duas dolunas dofttvola«* a juní-âo entre as duas tabelas. O i homes das datejorías sao retirados da tabela mismatch category. A cláusula WEHERE tem o efeito de diminuir este conjunto de resultados a uma única linha, aquela cujo tópico tenha o nome igual a 'Horror movies' ("Filmes de terror"). Nós temos de olhar novamente na tabela mismatch_topic para ver qual é essa linha. mismatch_topic Esta linha bate tom a dlausula HMERE. I I I , cateqorvJd ^ n am e I l f t M f l i i l ta R K iiiM l í ií iillp » « ® íjí rtí1 iililiíííif«Kif rfriJ I H p —. 7 Professional 2 wrestling C 8 Horror movies 9 Easy listening music 2 0 donjunto de resultados da IKKEK JOIN original e reduzido a esta linha solitaria, devido a dliusuia WHERE- $ (lausula ítfttERE restringe ^ os resultados da junção a apenas uma linha- você está aqui ► 475
  • 497.
    Os joins sã9 maiseîîcîentes Joins, ao trabalho! Assim, osjoins possibilitam envolver mais de uma tabela em uma consulta, na prática retirando dados de mais de um lugar e colocando- se em uma única tabela de resultados. A consulta do Mismatch que IQeTlPS C-Qcll^P cria um array de respostas é um candidato perfeito parajoins, uma vez j j. que ela contém nada menos do que três consultas aninhadas para lidar X ~ com várias tabelas. Vamos começar com o código original: reescrevendo a consulta com osjoíns // Obtém os dados de resposta do banco, para gerar o formulário $query = "SELECT response_id, topic_id, response FROM mismatch__response " "WHERE user_id = '" $_SESSION[1user_id' ] . $data = mysqli__query ($dbc, $query); $responses = array (); while ($row = mysqli_fetch_array($data)) { // Verifica o nome do tópico correspondente à resposta, na tabela dos tópicos ....................l i l $data2 = mysqli_query($dbc, $query2); if (mysqli_num_rows($data2) == 1) { $row2 = mysqli_fetch_array($data2); $row['topic name'] = $row2[J áuas ultimâs donsultas do dódi^o são responsáveis por obter os now>€s do topido e da date^oría das suas respectivas tabelas — uma dotówlta por tabela. // Verifica o nome da categoria correspondente ao tópico, tabela das categorias ip IiSilSiL $data3 = mysqli_query($dbc, $query3); if (mysqli_num_rows($data3) = = 1 ) { $row3 - mysqli_fetch_array($data3); $row['category_name'] = $row3[ “ array_push($responses, $row); } Com utwjoin, t possível obter ta«to o notme d o topido ^wanto o dâ dategorsa, em »uma so donsi»lta- E aqui vai a nova versão do código, usando umajunçao: // Obtém os dados de resposta do banco, para gerar o formulário $query = "SELECT response_id, topic_id, response FROM mismatch^response " . "WHERE user_id = . $_SESSION['user_id'] . " $data = mysqli_query($dbc, $query); ^responses = array (); while ($row = mysqli_fetch_array($data)) { // Verifica os nomes do tópico e da categoria correspondentes à resposta, respectivas tabelas Síl l l l i ... llfíf $data2 = mysqli_query($dbc, $query2); if (mysqli_num_rows($data2) = = 1 ) $row2 = mysqli fetch array($data2); ^ — “ í f , p í % ? , Í S m Srow [1topic_name '] = $row2 [u i $row[1category_name’] = $rowá array p u s h ($responses, $row); | £ao usados aliases h pâra ajudar a sW plm dar o dodigo. A ID do tápido t usado doTMo base para s donsulta prindipal, »as a |D da date^oría dontrola o próprio join. 47R Canítulo 8
  • 498.
    controle seus dados,controle seu mundo Não entendo, ainda temos uma consulta extra que procura o nome da categoria. Se os joins continuam tão bons, por que ainda precisamos de duas consultas? Nós não precisamos de duas consultas, pelo menos não se usarmos todo o potencial dos joins. E possível unir mais de duas tabelas, que é o que realmente precisamos fazer no código do array de respostas do Mismatch. Precisamos de uma única consulta que realize três coisas: obter todas as respostas para o usuário, obter o nome do tópico para cada resposta, e finalmente obter o nome da categoria para cada resposta. O novo e melhorado código da página anterior realiza as duas últimas em uma só consulta, que envolve umjoin entre as tabelas mismatch_topic e mismatch_category. O ideal é que tivéssemos uma única consulta, com doisjoins, para acertar os três coelhos com apenas uma cajadada em forma dejoin. RCÍCIO Segue algum código capaz de obter dados de resposta do banco com apenas uma consulta, graças ao uso inteligente dos joins. Seja inteligente e escreva a consulta SQL que fará a junção entre as tabelas mismatch_response, mismatchjopic e mismatch_category. // Obtém os dados de resposta do banco, para gerar o formulário Squery - Sdata ■= mysqli_query($dbc, $query); $responses = array(); while ($row = mysqli_fetch_array($data)) { array_push($responses, $row); > você está aqui > 479
  • 499.
    hora de brincarmismatch 0 «uestiortfirio de Sidney está preendHido, an»ãz£nâdo e pronto pava ser usado ao AliSnrvòtdVí O Mismatch agora se lembra das respostas dos usuários, mas ainda não está fazendo o que gostaríamos com elas... como por exemplo formar pares! O conjunto dos dados dos usuários só nos leva até metade do caminho para formarmos pares imperfeitos. A aplicação Mismatch ainda precisa de um mecanismo para disparar a flecha de Cupido no banco de dados para encontrar conexões amorosas. Para isso, precisamos examinar de alguma forma as respostas de todos os usuários no banco, para ver quais formam pares imperfeitos ideais. 48 2 CsDÍtuio 8
  • 500.
    controle seus dados,controle seu mundo Encontrar um par imperfeito ideal parece bem complicado, com todas aquelas categorias, tópicos e respostas. Tem certeza que é possível fazer isso? Certamente; nós só precisamos de uma forma consistente de calcular quantos tópicos dois usuários quaisquer têm com respostas opostas. Se elaborarmos uma forma razoavelmente simples de calcular quantos tópicos respondidos de forma oposta dois usuários quaisquer têm, toma-se possível fazer um loop através do banco de dados, comparando usuários. A pessoa com o maior número de opiniões contrárias a um determinado usuário é o par imperfeito ideal para esse usuário! = Par imperfeito! Escreva abaixo como você faria para calcular a ’'desencoutrabilidade"de dois usuários, usando dados armazenados no banco do Mismatch:
  • 501.
    a lógica domismatch 0 amor é um jogo de números Como você deverá se lembrar, as respostas do Mismatch são armazenadas na tabela mismatch_ response na forma de números, com 0, 1 e 2 tendo significados especiais em relação a uma determinada resposta. ¥ Adoro= 0 Odeio = 2 response^ response user_id Esses são os dados usados para se calcular a desencontrabilidade entre dois usuários, e o que estamos procurando especificamente é uma combinação de adoro com odeio ou de odeio com adoro. Em outras palavras, estamos procurando por linhas de resposta em que response é um 1em oposição a um 2 ou vice-versa. topicJd Asegunda Coluna destas iinbas c â resfosía, ^ue pode sev O (ndorespondido), / (adoro) ou 2 (odeio). 28 r ? > ® i ' I ’ I 29 4 30 5 31 . T O * 1 J 5 I Uma com binação ► 278 r < ; ¥ i i 3 | 279 i * i n i, j __j. I 280 1ff 1 1 I 5 J _J-----— 2 8 1 11 5 Uma vesposta adoro 0 ) Combinada dom uma odeio ( X ) para o mesmo tópit o freality shows) 'resulta e» uma dombinatao posrtiva- Ainda nos falta uma forma de determinar, através de código PHP, os momentos em que ocorre uma combinação entre duas respostas. Certamente poderíamos escrever algumas declarações if-else para verificar se há um 1 e um 2 ou então um 2 e um 1, mas a solução pode ser mais elegante do que isso. Em qualquer um dos cenários, adicionar os valores das duas respostas resulta no valor 3. Assim, podemos usar uma simples equação para detectar a combinação desejada entre duas respostas quaisquer. S e ile s p P s ta A + íle s p P s ta B = 3 , te m p s u m a c o m b in a ç ã o ! Assim, achar uma conexão amorosa acaba sendo mesmo uma simples questão de matemática. Isso basta no que se refere a comparar as combinações individuais, mas não atende ao problema maior de como realmente criar o script Meu Par Imperfeito.
  • 502.
    controle seus dados,controle seu mundo Cinco passos para um desencontro com sucesso Encontrar o par imperfeito ideal para alguém não é apenas uma questão de comparar linhas de respostas. O script Meu Par Imperfeito tem de seguir uma série de passos cuidadosamente orquestrados para formarmos pares com sucesso. Estes passos são a chaves para finalmente satisfazermos os usuários e usarmos de forma significativa as respostas que eles deram ao questionário. A Obter as respostas do usuário na tabela T mismatch response, certificando-se de juntar I os nomes dos tópicos aos resultados. À Inicializar os resultados de busca do Mismatch, incluindo as variáveis que registram o “melhor par imperfeito". 0 Fazer um loop através da tabela dos usuários, comparando as respostas dos demais às do usuário em questão. Para isso, comparar as respostas de cada pessoa no banco de dados às respostas correspondentes do usuário em questão. Um "placar" mantém registro de quantas respostas opostas o usuário tem em relação a cada pessoa. i | Após cada ciclo do loop, analisar se o par y imperfeito atual é melhor do que o melhor par encontrado até agora. Em caso afirmativo, armazená-lo como o novo "melhor par imperfeito", certificando-se de arm azenar também os tópicos em oposição. £ Certificar-se de que um "melhor par imperfeito" foi encontrado, e então fazer consulta para obter mais informações sobre o usuário considerado como o melhor par, e m ostrar os resultados. você está aqui ► 485
  • 503.
    introduzindo o logofor Tudo o que precisamos é um loop FOR O PHP oferece outro tipo de loop que tem exatamente a funcionalidade de que precisamos para as comparações de respostas no Mismatch. Chama- se loop for, e é ótimo para repetir algo uma determinada quantidade de vezes. Por exemplo, os loops for são ótimos para tarefas de contagem, como contar regressivamente até zero ou contar progressivamente até algum valor. Eis a estrutura de um loop for, que revela o modo como o loop pode ser estruturado para atravessar um array usando uma variável para contar ($i). //nidializa o doirfcador do loop C omum deteirmihddo valor, àh-tís de o prodesso domedar. Inicialização Começa o loop com o contador, $i, em 0. Condição de teste Só realiza outro ciclo do loop se o teste avaliar como true, ou seja, se $ifor menor do que o número de respostas dos usuários. Atualização Atualiza o contador, adicionando 1a $i. $uâ!<^uer dódijo dolodado d en tro das dhaves e e*edutado em dada «teraçao do loop. N A-função dountO retorna Atualiza o dontador uma dofttay» do numero de adidionando I a ele elementos do 3rr3y> o <^ue - isto e o mesmo <^ue serve domo parte da dondidao dizer fi =. /, + J. de teste do loop. 0 Passo 3 do script Meu Par Imperfeito faz a comparação de dois usuários através de um loop através de cada uma das suas respostas, calculando uma "pontuação" com base em quantas respostas são opostas. Com os pedaços de dados a seguir, termine de escrever o loop for que calculará essa pontuação. $user__responses É o array com as respostas do usuário. $mismatch_responses E o array com as respostas do usuário que é o par potencial sendo considerado. f o r < $ i = 0 ; $ i < c o u n t ( $ u s e r _ r e s p o n s e s ) ; $ i+ + ) { i f ( + $score A pontuação a ser calculada dentro do loop. ) í a r r a y _ p u s h ( $ t o p ic s , $ u s e r_ _ re s p o n s e s [ $ i ] [ ' to p ic _ n a m e 1] } ; } } AQQ ©
  • 504.
    controle seus dados,controle seu mundo não existem perguntas idiotas 1 • Por que não simplesmente usamos um loop foreach para calcular a pontuação, em vez do loop for? Embora um loop foreach funcionasse perfeitamente para fazermos o loop através de todas as respostas, ele não nos forneceria um índice (i$) em qualquer iteração do loop. Esse índice é importante porque o código está usando tanto para acessar o array das respostas do usuário A quanto o das respostas do usuário B, Um loop foreach eliminaria a necessidade de um índice para um dos dois arrays, mas não ambos. Assim, precisamos de um loop for regular, com um índice que possa ser usado para se acessar elementos semelhantes de cada array. * Qual é o propósito de se armazenar as repostas do usuário B em um array próprio? 0 array com as respostas do usuário B é importante para que os usuários saibam exatamente como eles se comparam com os seus pares ideais. Não é suficiente simplesmente dizermos a identidade da pessoa que é o par imperfeito ideal - melhor do que isso é dizer em que tópicos específicos o usuário tem respostas diferentes das dessa pessoa. Isso ajuda a dar um pouco mais de contexto ao resultado, e permite que os usuários saibam um pouco mais sobre por que esta pessoa em particular seria um par imperfeito tão bom. • No Passo 5 do script, como seria possível não haver um melhor par para o usuário em questão? Embora improvável, você tem de considerar o cenário em que haja apenas um usuário no sistema inteiro, em cujo caso não haveria ninguém com quem comparar esse usuário. você está aqui ► 489
  • 505.
    exercício solução 0 Passo3 do script Meu Par Imperfeito faz a comparação de dois usuários através de umloop através de cada uma das suas respostas, calculando uma "pontuação" com base emquantas respostas são opostas. Com os pedaços de dados a seguir, termine de escrever o loopfor que calculará essa pontuação. SOLUÇÃO $user responses ^mismatch sponses 1 1 Hate Tattoos 2 2 Hate Gold chains 3 3 Hate Body piercings 4 Love Cowboy boots 5 Love Long hair 6 Love Reality TV 7 Hate Professional wrestling 8 8 Hate Horror movies 76 1 1 Love Tattoos 77 2 Love Gold chains 3 Love Body pierdnqs 4 Love Cowboy boots 5 Love Long hair 6 Hate Reality TV 7 Love Professional wrestJ/nq U - 8 j Love Horror movies ! ------- - $ variável fstore adaba rxã -faixa de O (nenKu» par endontrado) ate o numero to ta l de topidos (desendontro períeito)- $ pontuaca© e mdrementada a dada resposta oposta endontrada* Lembre-se, o numero de a p o s ta s do usuário é o mesmo lue o numero Uiãi de tópidos, un»â vez.nue as respostas direto do questionário. f o r ( $ i = 0 ; $ i < c o u n t ( $ u s e r _ r e s p o n s e s ) ; $ i+ + ) { if (fuser_responsesCfi3Ctr^sponse> 3 +?mismatdh__responses£fi3rresponse,J fsdore +—Jj ; ' to p ic _ n a m e 1] ) a r r a y p u s h ( $ t o p ic s — / 0 dontador do loop e usado para se passar através de dada resposta do usuário- f u s e r r e s p o n s e s [ $ i] ; Cada topido dom respostas opostas e adidionado a um array, para que possa ser exibido ao usuário quando o sistema !Ke apresenta o par im períeito endontrado- Fazer um loop através <fa tabela dos usuários, comparando as respostas dos demais às do usuário em questão. Uma dombi«3£ao positiva donsiste de um adoro (j) dombinado a um odeio (Xi, de modo que adidionar os dois sempre resulta em um valor 3, daso haja a dombinaçao produrada-
  • 506.
    controle seus dados,controle seu mundo Finalizando o desencontro B-six Sdript Qntomhrd o par im períçito para o usuário^ O loop que acabamos de criar para calcular a pontuação de desencontro faz parte de um script maior (mymismatch.php),o qual cuida de encontrar o par imperfeito ideal para o usuário, e depois exibir as informações. mymismatch.php // Só procura pelo par se o usuário tiver respostas armazenadas $query = "SELECT * FROM mismatch_response WHERE user__id = '" . $_SESSION['user_ id'] . So é possível adKar um par para o usuarto " tiver respondido o Questionário- if (mysqli num rows($data) != 0) { $data = mysqli_query($dbc, $query}; // Primeiro, obtém as respostas do usuário a partir da respectiva tabela (JOIN para obter o nome do tópico) $query = "SELECT rar.response_id, mr.topic_id, mr.response, mt.name AS topic_ name " . "FROM mismatch_response AS mr " ■ . "INNER JOIN mismatch_topic AS mt " . "USING (topic_id) " . "WHERE mr.user_id = '" . $_SESSION['user_id'] $data = mysqli__query ($dbc, $query); $user_responses = array 0; while ($row = mysqli_fetch_array{$data) ) { array_push($user_responses, $row); } ■familiar )0fH e usado para se o b ter o home do topito, so se seledionar as respostas do usuário. 0 array fuser__responses armazena todas as respostas do usuário- Il Inicializa os resultados da busca $mismatch_score = 0; $mismatch__user_id = -1; $mismatch_topics = array( ) E stas variáveis mantem registro da busda do Mismatch, a medida Que o prodesso odorre- Aguente -firme> ainda tem muito mâis — virc a pagina/ você está aqui ► 491
  • 507.
    ____ T feS T O r iv e faça um par imperfeito! Encontre o seu par imperfeito ideal! Modifique o Mismatch para que ele use o novo script Meu Par Imperfeito (ou baixe a aplicação no site da Alta Books, em www.altabooks.com.br). Será preciso criar um novo script mymismatch.php, bem como adicionar um item de menu ’’Meu Par Imperfeito" ao script navmenu.php, para que os usuários possam acessá-lo. Envie os scripts ao seu servidor web e depois abra a página principal do Mismatch (index.php) em um navegador web. Certifique-se de que está logado e quejá respondeu o questionário, e então clique no item de menu "Meu Par Imperfeito" para encontrar o seu par. I Si A p%*a Meu Par jw.períe'fbo de JoHa* revela *ue SidUey e o seu oposto per-ferfco. AQA f^ a n ítu ín S
  • 508.
    controle seus dados,controle seu mundo Imas de Geladeira do Scfcema d» Banco de Dados Lembra-se da aplicação Guitar Wars, de séculos atrás? A sua tarefa é estudar o banco de dados do Guitar Wars, o qual poderia se aproveitar de um pouco de normalização, e criar um schema melhor. Use todos os imas abaixo para completar os nomes das tabelas e colunas, e identifique também as chaves primária e estrangeira. 0 bando de dados d€'tí'rw,í^ a exibiçào dai pontuadÕes «a página prwdípal do éjui-tar Wars. Eis o bando de dados original do g u itar Wars, o ^al arma«na pohtua^ocs submcildàs pelos usuários. você está aqui ► 495
  • 509.
    ímãs do schémado banco de dados solução Imas de Geladeira d° scfcemado Bancp de Dados - Solução Lembra-se da aplicação Guitar Wars, de séculos atrás? A sua tarefa é estudar o banco de dados do Guitar Wars, o qual poderia se aproveitar de um pouco de normalização, e criar um schema melhor. Use todos os imas abaixo para completar os nomes das tabelas e colunas, e identifique também as chaves primária e estrangeira. 0 bando de dados determina a exibidao das pOnt^dOCS *a pâgind prindipal do g u itar Wars. A tabela predisa de uma dhave primaria, Que e uma p arte importante de QuaÍQuer bando de dados normâlizado- Uma v er Que o mesmo usuário fode postar diversas pontuadoes; a doluna «ame resulta em dados redundantes- nada bom^ A nova doiuna sdore_id serve domo uma dbave primaria muito nedessaria para a tabela sdore. A tabela sdore re-ferendia os jogadores através de uma nova dhave estrangeira- “O “- As tabelas a^ora tem novos nomes, uma vez. Que servem a propósitos mais espedífidos- IXmarelaya© dc um— para-'***»' en tre jogadores e pontuâ^oesj 0 nome de dada jogador agora é dividido em primeiro nome e sobrenome, para ser mais atomido, e só e armazenado uma vez., nao portando Quantas pohtuadoes o oftador envie-- — — > T A redundândia nos dados V dos nomes dos usuários e resolvida driando-se uma «ova tabela para arm azenar os nomes dos jogadores, a Qual se donedía a tabela ^ Certifique-se de que as suas colunas sejam atômicas 0 Dê a cada tabela a sua própria chave primária. 0 Certrfique-se de as colunas que não são chaves não sejam dependentes umas das outras. K . sdore através de uma dHave- 0 bando de dados do éjuitar Wars não tinHa nenKum problema de dependèndía nas dolunas. Bis aQui as regras mais uma vez, 3fe*as^para assegurarmos Que vode nao as esQuedeu^ A r r > o
  • 510.
    controle seus dados,controle seu mundo r^aVras-CtuzacUis ?B P & M / Sq L Está preocupado sobre se o seu par imperfeito ideal ainda está por aí esperando para ser encontrado? Tire esse pensamento da cabeça completando estas palavras cruzadas. Horizontais I. Uma representação de todas as estruturas, como tabelas e colunas, do seu banco de dados, junto com o modo como elas se conectam. 4. Isto acontece quando múltiplas linhas de uma tabela relacionam-se com múltiplas linhas de outra. 5. Isto lhe permite converter entre diferentes tipos de dados PHP. 7. Use isto para combinar resultados de uma tabela com os resultados de outra, em uma consulta. 10.0 processo de se eliminar redundâncias e outros problemas de design em um banco de dados. II. Você pode abreviar algumas instruções if-else com este útil operador. 12. Quando uma linha de uma tabela relaciona-se com múltiplas linhas de outra Verticais 1. Uma junção possibilita nos livrarmos de joins. 2. Uma coluna, em uma tabela, que referencia a chave primária de outra (em inglês). 3. Quando um formulário é gerado a partir de um banco de dados, ele é considerado........... 6. Não é nuclear, apenas dados no menor tamanho apropriado para um determinado banco de dados. 8. Linhas de duas tabelas têm esta relação quando há exatamente uma linha em uma tabela para cada linha da outra. 9. Um destes pode ajudar enormemente a se entender o projeto de uma tabela. 13. Um nome temporário usado para se referenciar uma determinada informação, em uma consulta. você está aqui ► 4 9 7
  • 511.
  • 512.
    controle seus dados,controle seu mundo Sua Caixa de Ferramentas do PHP £ MySftl Um bom número de novas técnicas para bancos de dados MySQL foi apresentado neste capítulo, sem mencionar alguns novos truques com o PHP. Vamos fazer uma rapida recapitulação». . ,t:' ;.•! U**çs«^a* e CAFÍTOLO 8
  • 513.
    Um bom trabalhoarriscado édifícil de encontrar O novo site Riskyjobs.biz tem como missão ajudar as empresas a encontrar as pessoas certas para os trabalhos mais arriscados oferecidos por elas. O modelo de negócios é simples: para cada candidato que conseguirmos achar para um emprego arriscado recebemos uma comissão. Quanto mais combinações de candidatos e empregos conseguirmos, maior o nosso lucro. O Riskyjobs precisa de ajuda para melhorar a sua funcionalidade de busca por vagas. Dojeito como está agora, ha um banco de dados cheio de empregos arriscados só esperando para serem descobertos pelas pessoas certas. Vamos dar uma olhada no formulário de busca do Risky Jobs e no banco de dados subjacente, que contém asvagas disponíveis. 0 íormulâHo de busCa ddiOhâ um3 Cor»sulta na tabela riskyjobs, a qual produra fo r empregos que batam dom o driterío de busca- riskyjobs precisa de uma ferramenta de busca em seu site Éste -Pormulario de busca simples dhama umsdript que -Paz. a busca na "tabela riskyjobs. A tabela riskyjobs Contem títulos e descrições de emprejos, junto Com m-formaÇoes sobre a localização e a data do anundio- [ iü i l i i i i i l l i I lililM * « ! .™.p,ny. =• ' ■ ■ ■ ■ - 1 Matador Bustling dairy farm... Rutland VT 05701 Mad About Milk Dairies 2008-03-11 10:51:24 2 Paparazzo Top celebrity... Beverly Hills CA 90210 Diva Pursuit, LLC 2008-03-24 10:51:24 3 Shark Trainer Training sharks to do... Orlando FL 32801 SharkBait, Inc. 2008-04-28 03:12:45 4 Firefighter The City of Datavilie... Dataville OH 45490 City of Dataville 2008-05-22 12:34:17 5 Voltage Checker You'll be out in the... Durham NC 27701 Shock Systems, LLC 2008-06-28 11:16:30 6 Crocodile Dentist Do you love animals... Everglades City FL 34139 Ravenous Reptiles 2008-07-14 10:51:24 7 Custard Walker We need people... Albuquerque NM 87101 Pie Technologies 2008-07-24 10:54:05 8 Electric Bull Repairer Hank's HonkyTonk... Hoboken NJ 07030 Hank's HonkyTonk 2008-07-27 11:22:28 A , Cada > t identificado mdividuaUente atrases da cKave primaria job_id- Mostra os resultados ■^da busca! 502 Capítulo 9
  • 514.
    stings e funçõespersonalizadas Ernest», nosso âtét^ào Weivo, esta ^ar-^ado pov-^ue â sua Wsta «ao esta p ro d u zid o 'resultados. ponte seu lápis Quando o formulário do Risky Jobs é submetido, a string de busca é armazenada na variável $user_search, que é colocada na consulta SQL abaixo para ser feita a busca propriamente dita. Escreva aqui quantas linhas do banco de dados riskyjobs da página anterior serão encontradas como resultado da busca de Ernesto. $ s e a r c h _ q u e r y = "SELECT j o b _ i d , ti t l e , Sta t e , d e s c r i p t i o n FROM r i s k y j o b s M "WHERE t i t l e = 1 $ u s e r _ s e a r c h ' $ r e s u l t = m y s q l i _ q u e r y ( $ d b c , $ s e a r c h _ q u e r y ) ; Esdrevâ sua vesposta a«uif você está aqui ► 503
  • 515.
    riskyjobs code setup Tempo!Tire um momento para se fam iliarizar com o banco de dados do Risky Jobs... e experimente fazer algumas buscas. Baixe o arquivo riskyjobs.sql, da aplicação Riskyjobs, no site da Alta Books em www. altabooks.com.br. Esse arquivo contém as instruções SQSL para criar e preencher a tabela riskyjobs com dados de exemplo. Após ter executado as instruções de riskyjobs.sql em alguma ferramenta MySQL, experimente fazer algumas consultas para simular as buscas dos usuários. Eis alguns exemplos: SELECT * FROM r i s k y j o b s ^ SELECT j o b _ id , t i t l e , d e s c r i p t i o n FI ^ S€òa Bull pi^Kiev ft/lstiadar”. SELECT j o b _ id , t i t l e , d e s c r i p t i o n FROM r i s k y j o b s WHERE d e s c r i p t i o n L IK E '% a n im a ls % ' O código-fonte completo da aplicação Riskyjobs está disponível para download no site daAlta Books: w w w . a l t a b o o k s . c o m . b r 506 Caoitulo 9
  • 516.
    stings e funçõespersonalizadas Imos de Geladeira da CláusulaLÍKp Temos um monte de cláusulas LIKE bagunçadas pela mesa. Você é capaz de ligar as cláusulas com os seus resultados? Quais imas não serão encontrados por nenhuma destas cláusulas LIKE? Algumas fôderao itr mais de wmâ <r«sposta. LIKE '%test %' LIKE '%Tipper Cow%' Team M a s c o t (M a s c o te ) R od e o C lo w n ( P a lh a ç o d e R o d e io ) Human C a n n o n b a l ( B a la Hum ana) C a t H e r d e r (Pastor d e G a to s ) ....... ••■ -r ( P e t F o o d T è s t e r ) E x p e r im e n ta d o r de R a çõ e s p a r a A n im a is ( T o u r e ir o ) P o l i t i c i a n 1 C l í f f D iv e r (M e rg u lh a d o r d e J ? e n h a s c o s ) C ra s h T e s te Dummy (B o n e c o d e T e s te s d e Im p a c to ) ( E n c a n ta d o r de S e r p e n te s ) ( V ir a d o r d e V a c a s ) (C a ç a d o r d e T u b a rõ e s ) você está aqui ► 507
  • 517.
    É M T fc S T O R f v e ___________________ stings e funções personalizadas Leve o formulário de busca do Risky Jobs para dar uma volta. Baixe a aplicação RiskyJobs no site da Alta Books, em www.altabooks.com.br. O script search.php contém o código para a geração das consultas, no qual você acabou de trabalhar, e é usado para processar os dados de busca digitados no formulário da página search.html. Envie o script e os outros arquivos do Riskyjobs para o seu servidor web, e depois abra o formulário de busca (search.html) em um navegador. Faça algumas busca para ver como o seu código gerador de consultas se comporta. Não se esqueça de testar a busca “Buli Fighter Matador”de Ernesto, que é um bom teste para o novo código com implode(). Danger! Your dream job is out there. Do you have the guts to go find It? Risky Jobs-SearchResults Job Title Ptücfighter Toreador Electric Bull Repairer & Description UpandcoifiiBgsuperflygoat wightboxeraa opponenttokelpbuilshiswinningneeas'd.Sk sloppyhands,andaglassjawsibpreferred.No experiencerequited.TWsisnotafell»t!nsssois position.Wellmeetyoumthealleybehindthe toshape,thepons.LetRocKingmakeyoua championshipfighter.oratieastMp youloseto ©net Lovelybovineswaitingforyearsuperiorjsoe- violefitc& pewavingskills.Mustpassbasicbull fightiBgaptitudetest. Hick’sHoakyTaskneedsaftexperiencedelestac btdiropakcrjFiccndcsRafteryoufixit)ssdhalfofif hotwusgsaresonseofthebenefits. Eirnes-f» hâo en£or>-èrou «media^a^chie o seu iv-abalho avmdado períei-U »as cie de+i«iiivairr,«híc esiá -farchdo pro^vesso, agora < ^ u c o siHpt de busfia pv-oéutra pov- èada ia-me mdividuaUenie.
  • 518.
    podemos melhorara busca? SeUa,equilibrista de tordas bawbas, está ie*<Ao multa sor-te dom o -formulário de busias do Risky Jobs- 0 S " te r m o s d a r a m e n 'f c e m o s t r á m uma busóa por va^as para equilibristas de dordas bambas de dirdo, mas os resui'tados não sao e/aíameri-te apropriados. D anger!V ou rdream;obisout(her«. D oyouhavethegutstogofindIt? RiskyJobs. SearchResults JobTifie M aster C at Juggler Tightrope Tester Description Areyt® a practitioneroftheJostart ofcatjnggjing? AZ Bsnaed in forty cotrntries, only theJim Ruiz Circus bastefiaed catjuggling forthe sophisticated tastes of the modemaudience. Ply yourtrade with premierscat jugglersat ourcircus,tie only placean eãtí) to master sywdinmized catjuggling.It's fnie,juggling than ii even haulerteas herdiEgitem. Wea m aa equal ©ppafttt&ityemployer,and look ibrward to addiag you to ourteam. Pleasebe preparedto ondsi^o a thorough battery oftests toproveyourdeft haadlingof felirses. Only ttsecrean oftbe crop will be accepted iato our MasterCatJugglerprogram, I f th e t h o u g h t o f d a n g lin g & w h o u r s o h e n d 6 o m g r e z t M T h e ig b t s is y o u r i d e a o f a g o o d tim e , th e n th i s j o b ju s t m a y b e f o r y o u . E y & iy o r * o f o u r r ig b b o p e s g o « th r o u g h n g o w o s a 4 3 p o i e t t e a , c u ln a tt a tin g i s a z e a l l iv e fc u jn a a h a n g in g f e f a p r o lo n g e d p e r io d o f tim e . T hat could b e ya a i W e do provide safety nets but y«u*U need to b an g y o u r ow e helm et and gloves. Hens s t o a r m anufactoriag anã tearing facility in B ig T op, M ontana* w e offer a c icciedibie em ploym ent package w itk fceoefits ranging fiom B ring Y ourP et to W ork W eek and Fw m al Fridays. W e w fll need fluee references, including you r verified sax im u i» bang tim e and num ber o f past fails. W ere the ciictti behind t is e c u c a s ! Stale DatePosted 2008-11-14 21:13:35 2008-11-14 21:17:16 ierá que o iroblema são |os termos le busca, ou Irealm ente não há vagas para [equilibristas?
  • 519.
    stings e funçõespersonalizadas aponteseu lápfs-------------------------- ------------------- Escreva abaixo a consulta SQL gerada quando Selma digita "tightrope, walker, circus" ("corda bamba", "caminhante", "circo") como a sua busca, e depois escreva quaisquer problemas que você acha que poderão ocorrer. você está aqui ► 517
  • 520.
    préprocessando a stringde busca ponte seu lápis Solução Escreva abaixo a consulta SQL gerada quando Selma digita "tightrope, walker, circus" como a sua busca, e depois escreva quaisquer problemas que você acha que poderão ocorrer. SELECT * FROM nskyjobs IfVttÊREdescription LKfc^K-tvopc,%#OR description Lf^E '%ydlkeví%í OR description L|£E 'Vofcirdus'Jo A£unÇ3© e*plodeO usa espaços to»o delimitadores, mâs não pega as vírgulas. /s vírgulas sao Consideradas tomo parte dos -termos de busta, e nao Como serradores entre os -termos. unido termo de busda «^ue esta realmente sendo usado e Cirdusw , porque ele não tem uma virgula acidentalmente libada a ele- Naovejo qual é o problema. Basta chamar a função explode() duas vezes - uma para se livrar dos espaços e a outra para se livrar das vírgulas. O A função explode() lhe permite dividir uma string em substrings, mas neste caso nós já temos substrings. Aprimeira chamada à função explode() nos deixa com várias strings armazenadas em um array, portanto não existe mais uma única string a ser explodida. E tentar explodir cada uma das strings do arrayprovavelmente só criaria mais problemas. Emvez de tentar resolver o problema do delimitador com várias chamadas a explode(), o que nós precisamos é pré-processar a string de busca, para reduzi-la a um único delimitador antes de sequer fazermos a chamada a explode(). Então, essafunção poderá fazer o que faz melhor - dividir a string usando um delimitador.
  • 521.
    stings e funçõespersonalizadas Pré-processe a string de busca Nós queremos passar à função explode() uma string que ela possa dividir sem problemas, de uma só vez. Como fazemos isso? Certificando-nos de que explode() só precise se preocupar com um delimitador, por exemplo um caracter espaço. Isso significa que temos de pré-processar a string de busca, de modo que cada termo seja separado por um espaço, mesmo que o usuário tenha digitado vírgulas. Predisamos trans-formar isto-.. tightrope walker circus £er* vir^uias/ ...nisto- 0 p té -p rPoesscin} etifco p e rm ite <£ue n p s liV rem og d e Oc|3:ctctetes ín J e s e jtlJ o s e ^U e iP tn e n iP s o s d a d p s m a is íá e e is d e p r p o e s s c jí - ■para cxplodeO nos -í-orneça isto/ nãQ e x is te m $search words -p e r g u n ta s Id lo t a s - Podemos usar mais de um caracter como delimitador, ao explodirmos a string de busca? J ^ Z Sim, você pode especificar qualquer número de caracteres para servir como o seu delimitador, mas isso não é o mesmo que especificar diferentes delimitadores, e não resolverá o nosso problema aqui. Se usássemos explode(',$user_search) para dividir a nossa string, isso usaria uma vírgula e um espaço combinados como o delimitador e funcionaria se o usuário digitasse “tightrope, walker, circus". Mas falharia se ele digitasse “tightrope walker circus”. Nesse caso, acabaríamos tendo apenas uma longa string - nada bom. Q ? Podemos simplesmente apagar as vírgulas, em vez de transformá-las em espaços? A:Isso Sófuncionará se os usuários separarem os seus termos de busca com uma vírgula e um espaço, e não podemos confiar que será sempre assim. Se apagássemos as vírgulas, correríamos o risco de transformar "tightrope,walker" em "tightropewalker", o que provavelmente não encontraria nada no banco de dados do Risky Jobs. você está aqui > 519
  • 522.
    php função str_replaceQ Substituacaracteres de busca mdesejados Se você pensar bem, o pré-processamento da string de busca no RiskyJobs funciona de modo bastante parecido com o recurso de localizar e substituir de um processador de texto. No nosso caso, queremos encontrar vírgulas e substituí- las por espaços. Afunção str_replace() do PHP lhe permite fazer exatamente isso, usando três parâmetros: o texto que você quer encontrar, o texto que deseja colocar no lugar do primeiro e a string na qual você quer realizar a operação de localizar e substituir. Eis um exemplo de str_replace() em ação: Esta t a substring «ue vote deseja substrtuir $clean search = * (' milhares — e esta e a string a s«r £ofo£ada no lugar da pVi**<íVâ- r 1centenas' , ’ Ganhe milhares de reais logo no primeiro mês. Candidate-selagora!'); V 0iccteWo parâmetro t a string <y*e será — modificada- A^ui, estamos adtàonando um poudo de verdade ao anundto» substituindo M mÍÍKaresMpor ^entends*. Mas, e quanto às vírgulas na string de busca? Afunção str_replace() trabalha igualmente bem na substituição de caracteres individuais: Lembre-se, esta é a substring *V *e vode esta substituindo... •e esta é a string substituta- < r $clean_search = str_replace( ' ,', ' ' , 1tightrope, walker, circus’); Sempre <ue aparefier uma vírgula nesta __ string, ela sera substituída por um espado. Depois que este código for executado, a variável $clean_stiing conterá a string “tightrope walker circus”. Você vê algo suspeito nos resultados da função str_jeplace()? Você acha que a substituição das vírgulas por espaços irá funcionar da maneira que queremos?
  • 523.
    stings e funçõespersonalizadas Dado o código PHP abaixo, mostre qual seria o output do array $search_words para cada uma das seguintes strings de busca. Certifique-se de escrever dados para os elementos apropriados do array e risque os elementos que sobrarem caso o array $search_words acabe contendo menos elementos. $clean_search = str_ re p la c e ( ', ', '', $user_search); $search_words = explode(' ', $clean_search); bull,matador cape $search words 3 cspatos;— buli matador cape $search words $search words você está aqui ► 521
  • 524.
    exercício solução Dado ocódigo PHP abaixo, mostre qual seria o output do array $search_words para cada uma das seguintes strings de busca. Certifique-se de escrever ^ » dados para os elementos apropriados do array, e risque os elementos que ftCIClO sobrarem caso o array $search_words acabe contendo menos elementos.. SoLuçao $clean_search = str_replace (', ', 1 1, $user_search) ; Este array tem $search_words = explode( ' $clean search) ; fc a tres elementos bull,matador cape 3 espatosf — buli matador cape Estes dois elementos do array «a verdade esta© vadios, por òausa da<weles dois espaços entras entre ftâtador e tâft na string de Ws£3 $search words $search words bull , matador cape Nova»>ehte, dois elementos vazios, porque a vírgula e substituída por uimespado. X espatos' buli, matador, cape $search words
  • 525.
    stings e funçõespersonalizadas Ahn, não. O pré-processamento nos livra de caracteres indesejados, mas, infelizmente, não resulta em um array contendo apenas termos de busca úteis. Lembre-se, o nosso objetivo é ter uma string em que cada termo de busca seja separado exatamente pelo mesmo delimitador, um espaço. Dê outra olhada no que aconteceu nos três últimos exemplos da página anterior. Alguns dos elementos do array $search_words estão vazios. Se tentarmos criar a nossa cláusula WHERE com os elementos vazios, poderíamos acabar com algo parecido com isto: SELECT * FROM riskyjobs WHERE description LIKE '%bull%' OR description LIKE '%matador%1 OR '% %' OR Errado! Eles vão encon Se houver um único espaço, < descrição de um emprego (e menos um), esta consulta o e como resultado. Assim, todos dados do Riskyjobs serão en< por esta consulta. Precisamos vazios no array antes de pode SQL para tomar o script de t description LIKE 1% % 1 OR description LIKE '%cape%1 B-sfós espaços irdo Cht0h"tV "3V *fiãdâ CSpâÇo «steja jjvesen-fce em taâd díSÍri^áo dc figs sa© um problema t Îànbo. você está aqui ► 523
  • 526.
    tirando itens vaziosda busca A consulta precisa determos de busca legítimos A boa notícia é que não é muito difícil consertar os nossos termos de busca antes de usá- los em uma consulta. Teremos de criar um novo array que contenha apenas os termos de busca reais. Para isso, copiarem os todos os elementos nâo vazios do nosso array original para um segundo array, e então usaremos este último para construir a consulta SELECT. Para construir o novo array, podemos usar um loop foreach para realizar ciclos através de cada elemento do array original, e depois usar uma declaração ifpara encontrar os elementos não vazios. Sempre que encontrarmos um elemento não vazio, basta adicioná- lo ao novo array. O processo se dá mais ou menos desta forma: Eis o array original dontém os -termos dc busda e os elementos vazios Asados feios espaços extras. Estes dois elementos vazios predisâm ser eliminados^ Nós precisamos adicionar algum código ao nosso script para criar um novo array, contendo apenas os termos de busca não vazios. 0 novo array c menor, porque ele dontem apenas termos de busòâ ^eais — nada de elementos vazios. $final search words
  • 527.
    stings e funçõespersonalizadas Copie elementos não vazios para um novo array Agora, vamos dar uma olhada no código que copia os elementos não vazios do nosso array Ssearch words para o novo array $final_search_words. $search_query = "SELECT * FROM r is k y jo b s " : // Extrai as palavras-chaves de busca e as coloca em um array $clean_search = str_replace(1,', T ' , ?user_search); $search_words = explode( ' $clean_search); / espaços usdndo strjreplateO. Faz. «m loop através de fiada elemento do array ?searfih_j«ord. Se o elemento nao estiver vazio, fiolofia-o no array fika»ado ?fina!_ searfih words. J Após verificar que há pelo menos um termo de busca no array $search_words, o loop foreach percorre o array, procurando por elementos não vazios. Quando encontra um, usa o operador [] para adicionar o elemento ao final do array $final_ search_words. E assim que o novo array é criado. E depois? Bem, nós geramos a consulta SELECT da mesma forma que antes, exceto pelo fato de que agora usamos o array $final_search__words em vez de $search_words: // Gera uma cláusula WHERE usando todas as palavras-chaves de busca $where_list = array{); , if (count ( ^fina'L-_search_■ l i ) > °) { Este é o mesmo tódiy><ueja foreach as-$word) {-=£r* ^ a f i r i a r a f i l á u s u l a $where_list [ ] = "description LIKE '%$word%'"; vVttERE da fio n su lta de bustâ, $where_clause = implode( ' OR ' , $where_list); mas desta vez- ele usa o novo array ^i'maljsearfiK.jMords, <ue *ao tonte** nenhum elemento // Adiciona a cláusula WHERE à consulta de busca, if (!empty{$where_clause)) { $search_query .= " WHERE $where_clause"; v a z i o . Esse código nos fornece uma consulta de busca que não possui mais nenhum elemento vazio. Eis a nova consulta para a busca “buli, matador, cape” ("touro, toureiro, capa"): SELECT * FROM riskyjobs WHERE description LIKE 1%bull%' OR description LIKE '%matador%' OR description LIKE '%cape%' você está aqui ► 525
  • 528.
    teste search.php T tEJS T O R f V e Atualize o script Search para que ele pré-processe a string de busca do usuário. Atualize o script search.php de modo que ele use asfunções explode() e implodeO para pré-processar a string de busca do usuário e gerar uma consulta SELECT mais robusta. Depois, envie o script para o seu servidor web e experimente fazer algumas buscas. Danger!YourdreamJobisoutthere, Doyou have the guts to gd find it? RiskyJobs -SearchResults JobTitle Tightrope Walker Tightrope Tester Description State DatePosted Master Cat Juggler Fledgling big top looking fcrtkiee-riikg profess*anal TX2008*11-14 with 1-3 years of experieace to pesfcim tightropes 21:16:19 acrobatics,with pudgy elephant. Willingness to sweep excrement a big piss. Exeslleat fceueSti iccluding mcdical aad dental pirns* 4G1 (k),stack ownmhip and discount purchase plan,prescription coverage, merchandise discount,shczt acd long term disability insurance,life and business travel insuraae®, vkkm discount p5aa*attis> and home jDsinance discounts* medical care and dependent care eeiHfeniseEaeiiti educational a»htance, paid vacation aad holidays, and adaption assistance. Flexible starting salaries based ob skilU aod abilities,experience aud geographic market. Proraorioa opportunities based on pezfonnaace. The only thing stopping you from the highest winein the big tent is your desire and work ethic™aisdyoux balance1Otherduties mclude planning 4k■organizing wiias,handling minorelephaat admicistation,processing consnsexst cards from children.Leading by example (dca't tall!), showing mitialiva and a sease ofurgency and being results- drivexs help acispfeaticprofessionals become successful. Ifyon want to be challenged and your talent needs meatoriag and opportunity. Bicgliag Brothers can ©fieryou a fasttrack to success? Are yon a prartitinuercf ths lost art of cat juggling? AZ Banned in Sbrtyconntries,only the Jim R1112 Circus has refined cat juggling for the sophisticated tastes of the modem auditnce.PIy yourtrade with premiere, cat jugglere at our circus, the only place on earth to inaster synchronised catjuggling. It’s true,juggling them is even harder than herding them. We axe. an equal opportunity employer, and look fonvaid to adding you to our team. Haase he prepared to undergo a thorough battery of tests to prove yourdeft handling of felines.. Only the cream of the crop will be accepted icto our MasterCat Jugglerprogram. Ifthe thought of dangling forboms on end from great MT heights is your idea of a good time, thee thisjob just may be for you. Every oee of ourtightropes goes through rigorous a 4-3poiat test, culminating la a real ^ W i i t Stka f«- "^Wlro,*, „aii^ a9«-â p jf t í í Cstâr ttotombrïvdo a^tóios »ais relevâtes / 200S-U-H 2 1 : 1 3 :3 5 2008-1144 2 1 : 1 7 :1 6
  • 529.
    stings e funçõespersonalizadas Estou obtendo anúncios de emprego, mas estou recebendo descrições enormes para cada anúncio. Nao preciso de todas essas informações. Talvez seja melhor eu tentar em hazardpays.com, onde eles mostram apenas parte da descrição, e eu posso ver mais anúncios por página. Embora o Risky Jobs esteja fazendo um trabalho muito melhor para achar anúncios, as enormes descrições deles são um exagero. O que realmente estã irritando Selma é que para ver mais anúncios, em seu navegador, ela tem de passar por várias telas. Não é necessário mostrar a descrição inteira de cada emprego nos resultados de busca. O ideal é mostrarmos apenas parte da descrição de cada anúncio, talvez apenas as primeiras frases. Escreva abaixo como nós poderíamos diminuir as descrições dos anúncios, de modo que eles não fiquem tão grandes nos resultados da busca:
  • 530.
    a função phpsubstQ Às vezes você só precisa de parte de uma string Uma vez que a extensão das descrições de empregos no banco A íimçãp FHP de dados do Riskyjobs varia bastante, algumas delas sendo muito 1 ,v , longas, nós poderíamos melhorar os resultados de busca reduzindo Su d Su J ô as descrições a um tamanho melhor. E para não confundirmos os P o usuários, podemos colocar reticências (...) ao final de cada uma, para PmTh deixar claro que eles estão vendo apenas parte de cada descrição Você passa à função a string original e dois números inteiros. O primeiro é o índice de onde você deseja começar a substring, e o segundo é a sua extensão, em caracteres. A sintaxe é a seguinte: e-xtran-m os p c ttte d e u m a strin g . s u b s t r ( s t r i n g , i n í c i o , e x te n s ã o ) 5 t * „„3 su b str eeKefar 1 tavae-teres a sevem rcíornâdos- No que diz respeito à função substr(), você pode pensar na string como sendo um array em que cada caracter é um elemento diferente. Considere a seguinte string:: $job_desc = 'Are you a practioner of the lost art of cat juggling? 1; De forma semelhante a elementos de um array, cada caracter desta string possui um índice, começando e 0 e indo até o final da string. >ractioner of the lost art of cat juggljjiçr^ 3 4 5 6 7 8 9... Podemos usar esses índices com a função substr() para obter partes da string: Cowete «o ,__ 4*) re-tovifte 3 tairatteres ComcCe m t, W lna vez.<uenao espediíiiamos o S e W U f i d o siy»iítca <uea -íU^aodeve seguirate o -Pinal da sfcring. " r â » . substr ($job_desc, 4, 3) jpr substr($job_desc, 49) substr($job_desc, 0, 3) substr($job_desc, 0, 9 ) 50 51 52 you ing? Are Are you a
  • 531.
    Extraia substrings doinício ou do fim Afunção substr() não se limita a obter substrings a partir do início de uma string. Você pode também extrair caracteres começando do final da string. A extração ainda correrá da esquerda para a direita; você apenas usa um índice negativo para identificar o início da substring. stings e funções personalizadas Aç^^ou^a^practitioner of the lost art of cat juggljjijj? -53 -52 -51 -50 ... ... -3 -2 -1 Eis alguns exemplos: Comete £ » * ^ ^substr ($job_descf -53, 7 ) vc'bo'T'^c"7tâ'rôt'tc'rcs- Co»*M £ su b str ($job_desc, - 9 ) h*do 3 paHir dit ponte seu lápis Segue abaixo algum código PHP para gerar uma tabela HTML para os resultados de busca do Risky Jobs. Termine o código, cuja tarefa é limitar a descrição dos anúncios a 100 caracteres, e também reduza o texto referente à data do anúncio de modo que ele mostre apenas o mês, o dia e o ano. echo '<table border="0" cellpadding="2">'; echo '<td>Job Title</td><td>Description</tdXtd>State</td><td>Date Posted</td>' ; while ($row = mysqli_fetch_array($result)) { echo '<tr class=,,r e s u l t s ; echo ' <td valign="top"width=''20%"> 1 . $row [1title ’] . '</td>'; echo '<td valign~"top"width="50%">' . ............................... . ’...</td>1; echo ’ <td valign="top"width="10%">' . $row[1state' ] . '</td>'; echo '<td valign="top"width="20%">1 . ..... ........................... . f</td>1; echo '</tr>'; } echo '</table>'; você está aqui ► 529
  • 532.
    aponte o seulápis solução — ^Aporte seu lápis —--------- — — — -----------— ------------ 0 1 Segue abaixo algum código PHP para gerar uma tabela HTML > 0 lU p c l0 para os resultados de busca do Risky Jobs. Termine o código, cuja tarefa é limitar a descrição dos anúncios a 100 caracteres, e também reduza o texto referente à data do anúncio de modo que ele mostre apenas o mês, o dia e o ano. echo ' ctable border="0" cellpadding="2">'; echo ,<td>Título</td><td>Descrição</td><td>Estado</td><td>Data do Anúncio</td>' ; , .n „ Coloque veiido^tias do £ i * a l , while $row = mysqli fetch array($result)) { . .l f - pava mdidar < u e « s t o c echo ' <tr class=''results">' ; afends p a i r f c e dè d e s i - ^ i ç a o echo '<td valígn="top" width="20%">' . $row['title1] . '</td>1; 1 echo 1<td valign="top" width="50%"> T ’...</td> ' } echo '<td valign="top" width="10%">' . $row['State’] . '</td>'; echo ' <td vaiign="top" width="2 0 % " 1 0 ) .... . ' </td>' ; echo '</tr>'; Todos os dados dt d ití_ fosted domeçam tom M M - } DD-MAA, o ^ue odufa e*âta»einie fõ t a v - a t f c e v e s . echo '</table>'; jvjptíl Geek É possível dispensar a função PHP substr() e limitar os dados da descrição na própria consulta SQL. Para isso, usa-se uma função MySQL muito semelhante, chamada SUBSTRINGO, a qual aceita os mesmos argumentos que substr{). A única diferença é que o índice começa em 1, em vez de 0. Assim, para obter o 100 primeiros caracteres da descrição, usamos isto: SELECT SUBSTRING( job_description, 1, 100) FROM riskyjobs; A vantagem de usarmos a função PHP é que teremos tanto a descrição parcial quanto a descrição inteira disponíveis para nosso uso. Se usarmos o MySQL, só teremos a descrição parcial, e teríamos de criar outra consulta para obter a descrição completa. nao existem p e r g im ta s i d i o t a * Substr{) trabalha com valores numéricos? Não, ela funciona apenas com strings. Porém, se você tiver um número armazenado como CHAR, VARCHAR ou TEXT, ao obtê-lo através de SQL, esse número é tratado pelo PHP como uma string, e não um número, de modo que você pode usar a função substr() nele. " P • E se o valor referente à extensão for maior do que a string? Será retomada uma string com espaços depois dela, para atender ao valor da extensão? Será retornada a string inteira. Mas a função não insere espaços depois da string para mudar-lhe a extensão. Por exemplo, o seguinte código retorna a string 'dog': substr('dog', 0,10).
  • 533.
    stings e funçõespersonalizadas T e js t O R í v e Ajuste o script Search de modo a lim itar o texto exibido para descrições e datas dos anúncios. Modifique o script search.php de modo que ele passe a usar a função PHP substr() para reduzir os textos de descrição e a data dos anúncios retornados pela busca. Depois, envie o script paira o seu servidor web e teste-o com algumas buscas. Selma esia tonixnixi por<ue cia yodc V€y os resul-fcados da sua busta se* iev- de passar pelas enojes desoiçSes dos ahundtos. Oangerl Youf job is out there Do you have ths guts to go find It? RiskyJobs-SearchResults Description State JobTitle Description Tightrope Walker top lcokbgfbr P " “ “ 1 ^ ® -uiaaTt nfffKoeneiscc- tQperform tsga.tr,.. AZ 20084144 w tb 1-3 years, ofexpetisRcs tQperform tigktr MasterCat Juggler Are you a practitionerpf* el°! B&owedin forty cauatnes.,oaly the Jim Ruiz... Tightrope Tester Ifthe t h o ^ t dasrfiM forhems oa « ri * » » g*at fcTF „jbs& tb*. Eurealmentegostaria de ver os resultados classificados pela data dos anúncios ou talvez por estado. Eurealmente gostaria de achar um emprego de toureiro em Vermont. A data do anundio ‘ iambem Íí ê o u u» fouo r*ais íádil de lev, agcra ^ue »ostva apenas a daia e k3o a hora de pos-kagew». Como nós poderíamos mudar o layout da página e a consulta para podermos classificar os resultados pr data, estado ou títuio? você está aqui ► 531
  • 534.
    adicionando classificação àbusca dos resultados Podemosclassificarnossos resuHados commúltiplasconsultas Para permitirmos que os visitantes classifiquem os resultados das suas buscas, é preciso que eles possam identificar como querem os resultados ordenados. Talvez um formulário... ou um botão? Na verdade, é bem mais simples que isso. Podemos usar HTML para transformar cada cabeçalho de coluna, na tabela de resultados, em links. Os usuários poderão então clicar no link para indicar por qual coluna eles querem classificar os resultados. Danger!Yout dreamjob t*outthere. Do you have the girts togofind It? RiskyJobs-SearchResult^ Description lobTitle Prizefighter Toreador ElectricBull Repairer ÍOS *3is &di!mc»ic terias audios dlassi-Pidando os resultados através desks dabedalhos. Podemos -b-ansfovmav os dabedalhos er* links ^ue perm i-fcam 3os usuirios dlidar hfilcs para ordenar os anundtos. sL DatePosted State an MO Up and coming suj™. ~4 c------ ~ r opponent to help fetald Som t.. Lovelyb o v m esw aitm g fcry o w su i^ r^ -Y irfm t ID cape waving skills. Must pass basic bull fight*... Haflk'i Honky T eat needs an experienced elactiic bull repaker. Free rides isferyc* fi* it) «adhal.-. NJ 2008-11-14 2008-11-14 2008-1144 Nós podemos usar esses links para recarregar o mesmo script Search, porém com uma consulta que classifique os resultados de acordo com o link clicado.Já sabemos como usar ORDER BYpara estruturar uma consulta com resultados classificados. Se criarmos diferentes consultas SQL para classificar através de cada coluna individual, permitiremos que o usuário ordene os resultados alfabeticamente por título, descrição ou estado, ou cronologicamente por data do anúncio. Eis a consulta SQL para classificar os resultados alfabeticamente, pela descrição: SELECT * FROM riskyjobs WHERE description LIKE '%Bull%' OR description LIKE ' %Fighter%' OR description LIKE ’%Matador%' domando dlassi-Pida os resul-tados da donsul'fca pelas desdrições dos empregos, cm ordem alíabétida dresdenie-
  • 535.
    stings e funçõespersonalizadas você está aqui ► 533
  • 536.
    ORDER BY ordenao resultado da consulta [ — %Aponte seu lápis OaIiiaSa Escrevatrêsconsultasdiferentesqueclassifiquemosresultados ^ 8^ OUIUyttU doR jskyJobsdeacordocomotítulodoanúncio,oestadoea data.Assum aqueousuáriotenhadigitadoastringdebusca "window,washer,skyscraper"("janela,lavador,arranha-céus"). SELECT* W H ER Edescription L|^E'%window7e>O Rdescription L|^E'^wasHe^1O R description L|£E'%skysCraper%> ^ — -^RPERByj©b_title 0 padrão de O RPERBVt . .SELECT.ff.FR O /ytxkltyjefc»....................................................... ASCcndcnte W H ER EdescriptionLjKE'% w ii?d?;w % ’O R .descriptionL[^E.'.^Yí®?h,ç)P R . (fcresiente)^ desdriptiwi L|^E ^^Craper%' OmCSm©*V iC ORPER jo b jàtl*... ORDER BY.state ASC. SELECT ff FROM risk^jobs WHERE description L(^E '% Y/ihdovi% JOR description L|^E '%yiasher%i OR description L|^E t%sk^scraper%i Com opoderíam osreescreveressasconsultassevocêquisesseverostítuloseosestados emordeminversa?Esequisesseterosanúnciosm aisnovosaparecendoprim eiro? /SELECT FROM risk^jobs WHERE desÇription Lj^E t% window%>OR desCription L(^E t% y/asKer% >OR Poderíãmos ^ r estes, caso Jâ tínhamos classilicad© por uma dâs CoíuhâsT c entao o usuário clica nela novamente pâra inverter a ordem. description Ll^E '% sleyscraper% * ORPER BV job^tle.PESC ff FROM riskyjobs description LlJ^E '^^Ssher^ OR description L(íxE ^skysCrape^* . * r i sto > k WHERE description L|£E ^v/indov^ OR description LÍ^E '% y/asKer% ) OR description Lj^E ^skysCrape^* ^ ORPER BV date_posted PESC 5 3 4 Canítitin Q
  • 537.
    stings e funçõespersonalizadas Parece que vamos precisar de ummonte de código redundante para gerar todas essas consultas. Será que não podemos evitar essa situação de ter o mesmo código repetido três, ou até mesmo seis vezes? Sim. Embora seja verdade que precisaremos executar uma consulta diferente sempre que o usuário clicar em um link diferente, é possível construir uma única consulta baseada no link clicado, Na primeiravezque os resultados são exibidos, nenhum link foi clicado ainda, portanto não temos de nos preocupar com a classificação. Podemos simplesmente pegar aspalavras-chaves submetidas no nosso formulário e construiruma consulta sem ORDER BYOs resultados são exibidos com cabeçalhos clicáveis, cada um dos quais com um link de voltapara o script, mas com uma ordem de classificação diferente. Assim, cada link consiste de uma URL com as palavras-chaves originais e um parâmetro chamado sort, que indica a ordem na qual os resultados devem aparecer. O que realmente nos ajudaria aqui seria criar a nossa própria função personalizada, a qual possa pegar informações sobre o modo de classificar os dados e retomar uma string com a cláusula WHERE e ORDER BYnos seus devidos lugares. A nossa nova função personalizada consulta o parâmetro sort para descobrir como classificar os resultados da busca. Eis aqui os passos que a função tem de seguir: Pré-processar as palavras-chaves da busca, e armazená-las em um array. O Opcionalmente, usar um parâmetro sort que diz à funçao qual coluna usar para a classificação. Livrar-se de quaisquer palavras-chaves vazias. Criar uma cláusula WHERE contendo todas as palavras-chaves de busca. O Verificar se o parâmetro sort tem um valor. Se tiver, anexar uma cláusula ORDER BY. Retomar a consulta recém-formada. Isso pode parecer muito trabalho, masjá temos a maior parte do código escrito. Só precisamos transformá-lo em uma função. Mas antes de fazermos isso, vamos dar uma olhada no modo de escrever funções personalizadas... você está aqui ► 535
  • 538.
    escrevendo funções phppersonalizadas As fimpões lhepermitemreutilizarcódigo A s íu n çs& s Uma função é um bloco de código separado do resto do seu código, o qual você pode executar em qualquer ponto do seu código que quiser. Até agora, tem usado funções internas que o PHPjá criou para você. explode (), substr() e mysqli__query() são funções pré-definidas pelo PHP, e podem ser usadas em qualquer script. Mas você pode também escrever as suas próprias funções personalizadas, para implementar recursos não fornecidos pela linguagem. Criando uma função personalizada, você pode usar o seu próprio código várias vezes, sem ter de repeti- lo no seu script. Em vez disso, basta chamar a função pelo nome, quando quiser rodar o seu código. Segue um exemplo de função personalizada chamada replace_commas(), a qual substitui vírgulas por espaços, em uma string: o nome da sua W a© e vode tem liberdade para esdolher o nome quiser —íada— o o »ais descritivo possfvel- runtao .A Para driar uma & personalizada, vode a inicia dom a palavra "lunctien / p e rso n a liz a d a s ljie p e r m i t e m o r g a n i z a r um p eclaç^ c[e c ó d ig o "PH P p p f n o m e , d e m o d o <jUe V °ce p o s s a lreu tlllzá- l o f a c i l m e n t e . Um domunto de parenteses vem j / ' ^ » / .A depois do nome da -rwnÇao- vode pode enviar um ou mais valores para a sua -fundão na íorma de ar^umehtos, dada um separado por vírgula - «este daso, só Ha um ar^umento- function replace_commas($str) { $new_str = str_replace(',', 1 1, $str) return $new_str; } Uma íundão é capaz, de retomar um valor âo dod^o <^ue a dlnâmou - neste daso, «os retomamos a string alterada. Quando estiver pronto para usar uma função personalizada, basta chamá- la pelo nome e digitar, entre parênteses, quaisquer valores que ela espere receber. Se a função tiver sido elaborada para retomar um valor, você pode atribuí-la a uma nova variável, desta forma: As dhaves indicam onde estará o Codigo àã íuhÇao, da mesma íormâ domo em um ou uma mstrudao. oop /s/ós passamos uma string "tigKtrope, Vialker, dirdus'. $clean_search = replace_coimnas('tightrope, walker, circus'); A -fundão retoma uma nova string dom as vírgulas substituídas por espaços.
  • 539.
    stings e funçõespersonalizadas Construa uma consulta com uma função personalizada Nósjá escrevemos a maior parte do código de que precisamos para criar a função personalizada que irá gerar as consultas de busca no RiskyJobs. Só o que falta é colocar o código dentro de um esqueleto de função PHP. Eis a função personalizada build_query(): tstamos passando pava a íunçao o array fuser__seardh < ^ u c driamos a partir dos dados diytados no •formulário. // Extrai as palavras-chaves de busca e as coloca em um array $clean_search = str_replace(',T, ' $user_search); $search_words = explode( ' $clean_search); $final_search_words = array(); if (count($search_words) > 0) { foreach ($search_words as $word) { if (!empty($word) ) { $final_search_words[ ] = $word; } } } // Gera uma cláusula WHERE usando todas as palavras-chaves de busca $where_list = arrayO; if (count($final_search_words) > Û) { foreach($final_search_words as $word) { $where__list [ ] = "description LIKE '%$word%'"; } } $where clause = implode{1 OR $where list); Kada de «ovo dentro da luhção/ // Adiciona a cláusula WHERE à consulta de busca if ( !empty ($where__clause) ) { $search_query .= " WHERE $where_clause"; ____ / * JJ Ka verdade, isto a^ui e novo- £ a«w eye retornamos a nova donsulta, para «ue o dodíjo ^ue dHamou a fundão possa utiliza-la Afunção build_query() retoma uma consulta SQL completa, baseada na string de busca passada a ela através do argumento de $user_search. Para usar a função, nós simplesmente repassamos a ela os dados de busca digitados pelo usuário, e então armazenamos o resultado em uma nova string, que chamaremos de $search_query: Çsearchjquery = build_query($user_search) í Isto nos permite dapturar o valor V e^ u e â nossa -função retorna, neste daso, a nossa nova donsultâ- £ste e o valor submetido pelo usuário através do -formulário. você está aqui > 537
  • 540.
    F u nd e s F erso n allzad as E x p o stas Na entrevista desta semana: Funções personalizadas: o quão personaliza­ das elas realmente são? entrevista com a função função personalizada Use a Cabeça: Olhe, nós estamos todos curiosos sobre uma coisa: o que há de tão errado com código redundante? Quer dizer, ele é fácil de criar, basta copiar e colar e pronto. Função Personalizada: Ah, nem me fale de código redundante. Ele é simplesmente feio e torna o seu código mais difícil de ler. Issojá é ruim o suficiente. Mas existe um motivo ainda muito mais importante para se evitar código redundante. Use a Cabeça: Que é...? Função Personalizada: Bem, e se algo se modificar no seu código? Isso acontece com bastante frequência. Use a Cabeça: E daí? As coisas mudam o tempo todo. Você simplesmente vai lá e conserta. Função Personalizada: Mas e se a coisa que se modificou estava no seu código redundante? E ela estava em cinco, ou talvez dez, lugares diferentes espalhados pela sua aplicação? Use a Cabeça: Não vejo qual é o problema. Basta achar todas as ocorrências, consertá-las e pronto. Função Personalizada: Ok, tudo bem. Mas e se você se esquecer de consertar uma das ocorrências? Vocês, programadores, são humanos. Se cometer um erro, poderá ser muito difícil achar a fonte do problema. Use a Cabeça: Sim, é claro que isso pode acontecer. Mas como é que você ajuda? Função Personalizada: Ah, aí está a beleza de ser eu. Se esse código estivesse em uma função, você só precisaria modificá-lo uma vez. Uma vez, e pronto. Use a Cabeça: Eu tenho que admitir que isso é bem interessante. Mas ainda não vejo por que eu deveria me dar ao trabalho de usar você. Quer dizer, você é bem limitado, não é? Você só consegue usar strings. Função Personalizada: Ei, espere um minuto aí, amigo! Eu posso usar qualquer tipo de dados que você me enviar. Desde que o meu código lide com eles da forma correta, eu posso usar quaisquer dados. Caramba, eu usei até um array no úldmo exemplo. Eu diria que isso é bem sofisticado. Use a Cabeça: Mas você retornou uma string. Função Personalizada: Eu posso retornar qualquer coisa que você quiser. A questão é aproveitar ao máximo o que eu posso realizar, e me utilizar corretamente. Use a Cabeça: Essa é outra questão. Você é muito exigente. Você sempre quer receber dados. Função Personalizada: De onde você está tirando essas ideias malucas? Você pode me chamar sem nenhuma variável, se quiser, e se eu estiver configurada dessa maneira. Se você não quiser me enviar dados, é só não escrever nenhuma variável nos parênteses juntos ao meu nome, quando me criar. Embora eu não consiga pensar em muitos motivos pelos quais você não queira me enviar dados, nem recebê-los de volta com uma instrução de retorno. Use a Cabeça: Acabou o nosso tempo. Muito obrigado pela entrevista. Função Personalizada: Não há de quê. Eu vivo para servir. Ou será que sirvo para viver? Ou vivo e sirvo? Sei lã, alguma dessas coisas.
  • 541.
    stings e funçõespersonalizadas T t e S T D r i v e Modifique o script Search para que ele use a função build_query(). Crie a nova função builcLqueryO no script search.php, certificando-se de substituir o código original por uma chamada à nova função. Envie o script para o seu servidor web e experimente fazer uma busca no navegador, para certificar-se de que está tudo funcionando bem. Essa novafunçao personalizada build_query() é legal, mas eía ainda não esta classificando os resultados da busca. Será que nós poderíamos adicionar outro parâmetro para fazer isso? Sem problemas. Nós podemos passar dois parâmetros à função build_query()) em vez de um só. Nósjá estamos passando â função o argumento $user_search, que contém os termos de busca do usuário. Agora nós precisamos de outro argumento, $sort, que indica como classificar os dados. O novo argumento $sort precisa controlar a ordem dos dados retomados pela consulta nas seis maneiras que estabelecemos anteriormente: classificando pelas colunasjob_title, state e date_posted da tabela riskyjobs, tanto em ordem crescente quanto em decrescente. 'V Nós poderíamos armazenar as strings de ORDER BYem $sort para indicar a ordem de classificação. Ou poderíamos usar os números de 1a fV os esColhemos arbitrariamente Csses números c os seus significados. tão e*isU»> regras especiais sobre issoj fora usar as suâs esdoihas de for»â donsistente- 6 para representar cada ordem, desta forma: Çsort == 1 ORDER BY job_title $sort == 2 m ORDER BY job_title DESC $sort == 3 ORDER BY state $sort ==4 rn ORDER BY state DESC $sort == 5 ORDER BY date_posted $sort == 6 ORDER BY date_posted DESC *fâ2L VftUrto j sentido classificar feia descrito dos empregos, u»a vez. <^ue a orde» alfabética não significa »uita Coisa na descrícão. Mas os números não são ainda mais crípticos quando alguém está lendo o seu código? Sem comentários para ajudar, sim, mas há um motivo mais importante para usarmos números aqui. Se usássemos strings ORDER BY, os nossos dados apareceriam na URL do script como parte do link de cada cabeçalho. Isso inadvertidamente revelaria os nomes das nossas colunas, o que é algo que você não quer tomar público por motivo de segurança. você está aqui ► 539
  • 542.
    Permitindo ao usuárioescolher a ordenação Ok, eu entendi como o novo argumento $sort funciona, mas como saber qual valor de $sort nós devemos passar para a nossafunção? Não precisamos obter essa informação como ^usuário? Sim, o usuário precisa especificar o modo de classificar os resultados, da mesma forma como ele especifica os próprios termos de busca. Aboa notícia é quejá sabemos como queremos implementar essafuncionalidade: nósvamos transformar os cabeçalhos das colunas na nossa página de resultados em links. Quando o usuário clicaem um determinado cabeçalho, como por exemplo, "Estado", nós repassaremos à função build_query() o número referente à classificaçãopor estado. Mas ainda precisamos fazer com que a ordem de classificação vá do link até o script. Podemos fazer isso quando estivermos gerando os links para os cabeçalhos, anexando um parâmetro sort à URL: Queremos redarregar esta páginá «uando 0s resultados da busda são gerados os usuários ditarem no dabeçalho de uma como parte de uma tabela ttTWL, e è . td w * ?*ra tlassifidar os resultados, ^ por isso t^ue temos uma tag <td> a^ui. f portanto, temos de driar este formulário V $ s o r t _ lin k s .= '< td X a h r e f = " ' . $_SERVER[' PHPjSELF' ] . ' ?u sersea rch = ’ . $ u ser_ se a rch . ' & so r t= 3 " > S ta te < /a X /td > , ; A nossa funçao build_<^ueryO predisa das palavv-as-dhavcs Nós repassamos dados para indidar a de busda do usuário para dlassifidação desejada para a busda- Uma exibir resultados, portanto, v«z. *ue este é o tink para a dlassifidadão fornedemos essas informâdoes por estado, w sort” e igual a 3. através da URL. Quando a página dos resultados é gerada, cada link (exceto ’’Descrição") tem a sua própria URL personalizada, incluindo um valor sort para definir como os resultados devem ser classificados. <a W f~ K seardh-php?userseardh-bull fighter matador&sort^/H > Danger! Yourdream job Saout there. Do you have it » guts to go find it? Risky Job«-Search Results L Job Title Description Classifidar pela desdríção nao Síria muito informativo, portanto, nao ha motivo para transformar esse dabedalho em um lihk- Date Posted <a href^seardh.phpfuserseardh— bull f ighter matador&sort— 3W > 1 „ <a href— 'seardhphpfuserseardh— bull fighter matador&sort— 1 5 >
  • 543.
    stings e funçõespersonalizadas O Hm. Entendi como esses links funcionam nas três primeiras consultas, mas e quanto às outras três ORDERBYsque classificam por ordem decrescente? Onde elas ficam? Joe: Normalmente, o mesmo cabeçalho permitiria ao usuário classificar em ordem crescente ou decrescente. Jill: Correto. Cadavez que o usuário clicano cabeçalho, este apenas inverte a ordem. Frank: Isso não significa que nós agora precisamos de umjeito de manter registro do estado dos cabeçalhos a cadavez que o usuário clica neles, uma vezque o cabeçalho precisará apontar para um link diferente do link para o qual ele aponta atualmente? Joe: Não entendi o que você quis dizer. Frank: Bem, os cabeçalhos não fazem sempre a mesma classificação. Por exemplo, sevocê clicar em "Título'1e ele classificar o resultado pelos títulos dos anúncios, em ordem crescente, então o link precisará se modificarpaia classificarpelos títulos, mas em ordem decrescente, na próximavez que for clicado. Jill: Éisso mesmo. Mas tenha em mente que cada tipo de classificação tem um número na URLdo link, para que o script saiba qual tipo de ordenamento usar. Euma vez que nós estamos gerando esses links, podemos controlar exatamente quais números de sort colocamos em cada link. Joe: Entendo. Então o nosso desafio é estruturar de alguma forma o nosso código, de modo que ele possa gerar o link correto baseado no estado atual da classificação, certo? Frank: Ah,já sei! Não podemos resolver isso com algumas declarações if? Quer dizer, é para esse tipo de tomada de decisão que essas declarações servem, certo? Joe: Sim, issofuncionaria, mas estamos falando de várias decisões envolvendo exatamente os mesmos dados - o tipo de classificação. Seria muito bom se conseguíssemos bolar uma forma melhor de tomar essas decisões, que não seja com um monte de declarações if-else aninhadas. Jill: Muito bem observado, e esta é uma oportunidade perfeita para testarmos uma nova declaração que eu descobri. Adeclaração switch nos permite tomar múltiplas decisões, muito mais do que duas, com base em apenas um valor. Frank: Parece bom. Vamos tentar. Joe: Concordo. Qualquer coisapara evitar declarações if-else complicadas. Elas me dão dor de cabeça! Jill: Sim, a mim também. Acho que a declaração switch pode ser exatamente o que precisamos...
  • 544.
    a declaração phpswitch SWITCH toma muito mais decisões do queIF A declaração switch oferece uma forma eficiente de verificar TjU]3 cÍBclclJ*3cão um valor e executar um dentre vários blocos de código, rÍTT^Tr / dependendo desse valor. Isso é algo que iria exigir um O *VXI v j i CQtlteUl pequeno exército de declarações if-else, principalm ente em Utllct SCtle d e situações envolvendo mesmo um número pequeno de opções. , Em vez de escrever declarações if-else aninhadas para verificar C A . E cada valor possível, em vez disso, você escreve uma declaração <Jue e x e c u ta m switch com um rótulo case correspondente a cada valor possível. No final de cada rótulo case, você coloca a declaração Q liereilteS break;, que instrui o PHP a sair da declaração switch inteira e bloc-og d e COcIlP'O não considerar quaisquer outros casos. Isso garante que o PHP , , , - irá executar o código em um e somente um caso. clepetlcletlclQ clP Vamos dar uma olhada em um exemplo que usa switch: Val<?v d e u m a ^ _____ Este € O v a l o v<^ue 3 declaração V %-iaVel• switch ($benefit codeT^Í swk*» verificando - ele controla toda a declaração. case 1: $benefits = ’ Plano de saúde, 10 dias de licença médica'; break; A dctlaruS. Wtak <te ^ --- * * * ' j ‘**“kdo ao PHP para sair da °^ " do e c c a s e 2 : instrução switch. iguala i- $benefits = 'Apenas em caso de morte e esquartejamento, um mês de licença remunerada' ; break; Se você precisar fazer 3 mesma Coisa g __■ * ■ * - ' para dois cu mais valores, basta omitsr 5 case 3: declaração break ate chegar ao ultimo valor-. case 4: $benefits = 'Boa sorte!'; ^uaisyer v a l o r e sarmazenados em ; fbeneíit^Cade ^ue nãosejam /, Z, default: ^ °u -rarao Com ^ue o código & padrão seja executado. $benefits = 'Nenhum. ' ; > echo 'Nós oferecemos(guatro)pacotes de benefícios'; echo 'O plano que você^selecionou: ' . $benefits; Hso exatamente- Só existem tres pacotes, uma vez. ^ue ^ e 4“sao a mesma Coisa, devido ao fato de 3 não ter um break
  • 545.
    stings e funçõespersonalizadas 0 Risky Jobs tem uma nova função chamada generate_sort_links() que permite aos usuários classificar os resultados de busca clicando nos cabeçalhos dos resultados. Infelizmente, estão faltando partes importantes do código. Complete o código da função. E não se esqueça dos números para cada tipo de busca: 1 = por título, crescente; 2 = por título, decrescente; 3 = por estado, crescente; 4 = por estado, decrescente; 5 = por data de postagem, crescente; e 6 = por data de postagem, decrescente. generate_sort_links($user_search, $sort) { $sort_links = ''; ........ ($sort) { case 1: $sort_links .= '<td><a href = . $_SERVER['PHP_SELF1] . '?usersearch=' . $user_search . '&sort=.... ">Título</a></td><td>Description</td>'; $sort_links .= r <tdXa href - . $_SERVER[ 'PHP_J5ELF1] . ■ '?usersearch=' . $user__search . 1&sort=.... ">Estado</aX/td>', * $sort_links .='<td><a href = "1 . $__SERV£R[’PHP_SELF' ] . '?usersearch=' . $user_search . '&sort=.... ">Data</aX/td>' ; case 3: $sort_links .= '<td><a href = ’ " . $_SERVER[1PHP_SELF' ] . 1?usersearch=' . $user_search . '&sort= ....'^Job Title</a></td><td>Description</td>'; $sort_links .= ’ <tdXa href = . $_SERVER['PHP_SELF’] . '?usersearch=' . $user_search . '&sort=.... ">State</ax/td>1; $sort_links .= '<td><a href = ”' . $_SERVER[ 'PHPjSELF'] . '?usersearch=' . $user__search . ’&sort= ">Date Posted</a></td>' ; case 5: $sort_links .= '<td><a href ="’ . $_SERVER['PHPJSELF' ] . '?usersearch=' . $user_search '&sort=...... ">Job Title</aX/tdXtd>Description</td>1; $sort_links .= '<td><a href = . $__SERVER[1PHP_SELF' ] . ’?usersearch=’ . $user_search '&sort=.... ">State</a></td>'; $sort_links .= '<td><a href = . $_SERVER[1PHP_SELF' ] . 1?usersearch='. $user_search '&sort=.... ">Date Posted</a></td>'; $sort_links .= '<td><a href = "' . $_SERVER['PHP__SELF’] . 1?usersearch=' '&sort= .... ">Job Title</aX/tdXtd>Description</td> '; $user search $sort _ _ links 1&sort= . $sort_links '&sort= return <tdXa href = ’ " . $_SERVER['PHP_SELF’] .’^ S t a t e C / a X / t d ^ ; <tdXa href = "' . $__SERVER[ 'PHP__SELF’] ">Date Posted</aX/td>'; ' ?usersearch=' . $user search 1 ?usersearch= $user search Este e o tonjuft-bo padra© de devera apôreòer caso o usuário ainda nâo tenHa esÊolVido unv mcbodo de classiftca^âo- você está aqui ► 543
  • 546.
    a função completageneratejsortJínksQ «cícío SoLuÇão 0 Risky Jobs tem uma nova função chamada generate_sort_lihks() que permite aos usuários classificar os resultados de busca clicando nos cabeçalhos dos resultados. Infelizmente, estão faltando partes importantes do código. Complete o código da funçãc E não se esqueça dos números para cada tipo de busca: 1 = por título, crescente; 2 = por título, decrescente; 3 = por estado, crescente; 4 = por estado, decrescente; 5 = por data de postagem, crescente; e 6 = por data de postagem, decrescente. generate_sort_línks ($user_search, $sort) { $sort_links ' '; ^ ^ d }; signifida <uejá elassifiçamos feio título, porta«to> agora predisamos redlassifidar em ordem dedresdente- ($sort) switçK case 1: $sort_links .= ’ <td><a href = . $_SERVER[’ PHP_SELF' ] . '?usersearch= 1&sort= .7r.__">Titulo</a></td><td>.Description</td>1; $sort_links .= ’ CtdXa href = . $_SERVER[’ PHP__SELF*] '6sort= .3. . ">Estado</ax/td> 1; $sort_links .= '<tdXa href = . $_SERVER['PHP_S£LF’] '&sort= ^ . . ">Data</aX/td>' ; break;...... case 3: $sort_links .= '<tdXa href = . $_SERVER[ 'PHP^SELF1] _ _">Job Title</aX/tdXtd>Description</td $user_search '?usersearch=' . $user_search '?usersearch=’ . $user search = '<tdXa href = 4* $_SERVER['PHP_SELF' ; ">State</a></td>’; = ’ <tdXa href = * ' 1 . $_SERVER[’PHP__SELF' ; ">Date Posted</a></td>' ; ' ?usersearch=' . $user search search search 1?usersearch=' ?usersearch=' ctdXa href - "' . $_SERVER[r PHP_SELF'] . ’?usersearch=' ">Job Title</aX/tdXtd>Description</td>1; = ’ <td><a href = . $_SERVER[’PHP_SELF' ] . . ">State</aX/td>' ; = ' <tdXa href = . $_SERVER[’PHPJ3ELF1] . . ">Date Posted</aX/td> '; 1 ?usersearch=' $user $user $user '&sort= _ $sort__links '&sort= . $sort_links ’&sort= .$ . break;........ case 5: $sort_links .= 1&sort= .I $sort_links ’&sort=, $sort_links ’&sort=,$ . break;...... default; $sort_links .= ’ CtdXa href = "’ . $_SERVER[’ PHP_SELF' ’&sort= .í ... ">Job Title</aX/tdXtd>Description</, td>'; $sort_links .= '<td><a href = ' ” . $_3ERVER['PHP_5ELF' ] . ’?usersearch=1 '&sort= . . ">State</aX/td>1; $sort_links .= '<td><a href = . $_SERVER['PHP_SELF' ] . '?usersearch=' '&sort= .5. . ">Date Posted</aX/td>1; ^ Se /sort ainda não tiver sido definido ou se for igual a Z, 4*ou ^ »»os temos de exibir os links originais <ue dlâssifidâm os dados em ordem dresdente- search search ' ?usersearch=' . $user search '?usersearch=' . $user search $user search $user search return /sort links
  • 547.
    H a build.queryOa capacidade de classificar Agora nós temos duas funções para lidar com as buscas no RiskyJobs. build_query() constrói uma consulta SQL com base em termos de busca digitados pelo usuário, e generate_sort_links() gera hyperlinks para os cabeçalhos do resultado da busca, os quais permitem ao usuário classificar os resultados. Mas build_query() ainda não está totalmente pronta, uma vez que a consulta gerada por essa função ainda não faz a classificação. Afunção tem de adicionar uma cláusula ORDER BYà consulta. Mas precisa ser a ORDERBYcorreta, conforme determinado por um novo argumento $sort: Agora nós estados passa«do o argumento fsort para a nossa função, ale*» de fuser_search- stings e funções personalizadas function build_query($user_search, |1|111ÍÍ { $search_query'= "SELECT * FROM riskyjobs"; // Adiciona a clausula WHERE a consulta de busca if (!empty($where_clause)) { $search_query .= ” WHERE $where_clause"; Eis a^ui as adições ao códig< de build__^ueryO. Esta dedaraçao switch verifica o valor de fsort e adiciona a instruto ORDER BŸ Correspondente ao f inâl da Consulta de busca- iSSlw iR B w il ««»— return $search_query; Kos retornados ?seârCh__^uery Como âhtes, más desta vez. com u*a cláusula ORDER B / ao f inal guando os usuários carrega«* a pagina de resultados se» clicar Cm henKu» cabeçalho, fsort estará vazio, portanto, nós nào classificamos os resultados por padrão- você está aqui ► 545
  • 548.
    teste o scirptrevisado search.php T fe s T O R tv e Reelabore o script Search para que ele use as duas novas funções personalizadas. Crie a nova função generate_sort_links() no script search.php e depois adicione o novo código à função bmld_query() ,para que ele gere uma consulta com resultados classificados. Não se esqueça de fazer a chamada a generate_sort_links() no script, no lugar do código que ecoa os cabeçalhos dos resultados. Envie o script ao seu servidor web, abra a página search.html em um navegador e experimente fazer uma busca. Agora clique nos cabeçalhos das colunas da página de resultados para classificar os anúncios com base nos diferentes tipos de informações. Não se esqueça de clicar no mesmo cabeçalho mais de uma vez, para alternar entre a ordem crescente e a decrescente A -Punção build_jueryO pega os -termos de busca < i»e o usuário digitou, e*p!ode a Consulta e*» um array, remove «yuâis^uer sfcrings vazias do ârray, e Cria uma Consulta Com os termos e uma ORPBR 2>i Correspondente ao valor de Risky Jobs *S classificação; se Houver Findyottrriskyjoj iBuli n g h w Majador AfunÇao generate__sort_ linksO gera os cabeçalhos clicáveis, mcluindo o empacotamento das opções de classi-Hcaçao na URL- de cada link. OangsrlYourdreamjol» oatthere. DoyouHavemegirt»togofindit? Risky Jobs - Search Results Job Title Description State Date Posted Matador Bustling dairy £mn lookisgforpart-tkaematadora/ VT 26084)3-11 entertain spirited bull withnald cajeofADO. Firefighter The CityofDatavilleislurk";;iiiefjglitBivNo OH 2003^5-22 experienced required-you will be traised,Nor cmo EleciricBull Hank'sHcmlryToni needsan experienced eketric XI 2008-11-14 Repairer bidJropaiiBr.Freendes(afteryou fix it’;.'irif ael.. Agora eu consigover os anúncios maisantigos, aqueles emque os empregadores estao ficando realmente desesperados para achar umtoureiro em Vermont. O
  • 549.
    stings e funçõespersonalizadas Masàs vezes eu tento fazer uma busca mais ampla, e os resultados são muitos. O o It® Danger! Your frwm job Uoutthere, Do you Dwe the 9® » to 8° Ow* *t? RiskyJobs-SearchResults JobTitle Custard Walker Description State 1st» t urn bo&ddo de anúncios pairâ uma só P«ssoa lev* dc u»>«| S O Weneedpeople willingto testthe theorythatyou can MM walkdo CBSffiid-WcVegoingto fill a sm..< Training sharksto docate-tricksfortheaudjsece*atoat FL newtvatartben®parit,You’il speadtils... Ÿoolî beout in tisefieldcitEckiugax,aaddjc,foliages XC io tbsjcasgeof3 to250 ormore volts. Y... Yol'II heiartaOÎDg mtcnr.zsmá Q&eriuetaííic FL broadcast içeeívíBgsquipaieat c t oth» loois. ofMiami— Eicpkaji'.ProctoiogUr N&Kfcd:experienced proctologist-wiM'sagto-swsi with CA lajgeaaiaiiik.Efepfeactsatourzoo (in San Fr.„ Setairplanesceeding engine«deseed.fa seed cícieac- TX naaited individualswiHiegto baisdle rnsiaa... Buntijagdaiiy fami ïookiag forjrart-tiajamatnderlo VT entertainspirited,bull with mild c®æofADD. ... Top celebrityphotographyfera looidag Sirseasoned CA -------*- llrwcvrtrine Sharis Trainer WUagcC h e c k e r Aclencifcitalícr AkplansEngine Clearer Matador Püpnraîszo Tigbtroçc Waite- C ï w s d i î eD e n t i l * —o — - I--------- ■w ith i-3 jfeafsofexperience toperformtlghtr... Do you kffteanimalsandhutsplaque?Well,thentfeii PL might be thejob foryou! Ourcrocodik feno., .Mime WBueeds«»iBiiítEshnew£a£8s.Rjllhaa5íkÍE&ní&Ece NY and shits padsprovided.Must tove kids.... PetFooc Tester Wapride ourselveso«sbow good ourp«tfoodtastes. MO Newyoucan help mshxourproductseven better. Toreador Lovelyisovines waiting foryour superioroon-viclect ID cape ivaviug skills.Mustpas*basicballfigfeti... ElectricBull Rjepaiter Hack'sHanky Took aeedi an experiencedelectric buli HJ iw. fiee rides tafteryou fix it) andbal.. CityofDatavillekhiring firefigbtejvNo OB «<«1«™ *r . tf0a<yiube rraÍBad.Nba^ano. « R E S R Q B k * juggling? A2 Como será que os outros sites Í evitam ter muitos resultados em " uma mesma página? DatePosted 2008-07-24 2008-04-28 2008436-28 2008-09-04 200840729 2008-08-17 2008-03-1j 2008433-24 2008-11-14 2008-07-14 200S-1Î-02 2008-11439 2002.1144 2008-07.27 2008-05-22 2008-11-!á 200S-Î1-Ï4 2008*13-14
  • 550.
    use paginação paramostrar os resultados Podemos paginar os nossos resultados Atualmente, nós estamos exibindo todos os nossos resultados em uma só página, o que é um problema quando uma busca encontra muitos anúncios. Em vez de forçar os usuários a irem de cima a baixo em uma página enorme para ver todos os resultados, podemos usar uma técnica chamada paginação para exibi-los. Quando você pagina os resultados, divide o conjunto de resultados em grupos, e então, exibe cada grupo em uma página web separada, desta forma: Cada tnosforâ iindo resul-fcados»jwvio Ê on» links para se âôessar as ou-brd* pâginâs de resul-fcados. Os usuários pode» •Taiiin*e»vke dlidar para adessar cada pagina, sem predisar íifiar subindo e destcndo tom o mouse- VoJiage Checker Anlcarta Iisstalier Tm inLB gsrta our aewwnti Job Title You'll be on A ndjK ta,™ « intbenm ga C ta m e r Y oullbcis Matador b r o a d c a s t n Etephmt Rroctologisl Needed:ex Papam ^ la rg ea iiiß is <-12 34 -> Risky Jobs-Search Results £stes links fermiicm < ^ uc os usuários naveguem airaves de varias paginas. A pogii TigbtnppcW a& jei Crocodile Dentist <-1234 ■> T " " A farina aiual AÍ f Y Ú O C urn link - esta e a se^unda pag'ma de resul'tados. m pfc, JébTíüe will Mime Don Pet fvscniTester Dsscnpöon Weneedsomefreshecw Fall beallfemsBcasoe ««IshinpaäspravltieiLMustlovekids— W eptidC :rm jT W jlvcias howgoodcarpet foo4tastes, you.can kelp aafagoarproducts even better.... Toreador Loveiy bovines nom-v'iolca' ID capeTüiiricg sldiJa-Mustpassbawibtill figitj... Electric Bull Rcpiijct: ilaalc’ftffenky Tdnk needs ao expcrisoced eleetfiisboil NT spssra,Free fitteryoufixit)andfcsL. F L nsfiglsieT <-12 34-> ofDstavülei expetijecõedreqi Isso é ótimo, mas como nós dividimos os nossos resultados emgrupos? Anossa consulta SQL retorna todos os resultados encontrados pelastring de busca. in a ç a p d!V ide og re s u lta d o s e m g ru p o s, e e x ib e c a d a g r u p o e m uma págfna Web prppria. Nós precisamos de uma consufta que retorne apenas um subconjunto dos resultados, e não todos eles. Afortunadamente, o SQLjá nos oferece uma forma de fazer isso: a cláusula LIMIT. Vamos rever LIMIT e aprender como podemos usá-la para dividir os nossos resultados em grupos de cinco...
  • 551.
    stings e funçõespersonalizadas Obtenha apenas as linhas dequevocê precisa com UMIT Achave para controlar quais linhas nós iremos exibir em uma dada página é adicionar mais uma cláusula à nossaconsulta de busca, a cláusula LIMIT. Para obter um máximo de cinco linhas, nós adicionamos LIMIT 5 ao final da nossa consulta, desta forma: SELECT * FROM riskyjobs ORDER BY job_title Sc» Ufoâ dâttSulâ C sta donsulta retorní» _os os anundios do bando de dados, o ^ e e equivaleu-te a produrar sen* nenhum ‘ te'rvno dc bwsda- £o retorna os dindo primeiros resultados, nao importando quantos tenham sido reaImente endontrados. Sevocê se lembrar, nós usamos a função personalizada build_query() para criar a nossa consulta no Riskyjobs. Para forçá-la a exibir apenas os cinco primeiros resultados, nós simplesmente adicionamos LIMIT 5 ao final da string da consulta, após esta ter sido criada: $query = build_query($user_search, $sort); /^didionar uma í-láusulâ i~|A1|T âo íinâl dc umã donsulta limita Onumero de Imhas retornadas por ela, neste taso a dindo. Isso funciona bem para se obter as cinco primeiras linhas dos resultados, mas e quanto às cinco linhas seguintes, e às cinco linhas depois dessas? Para obter linhas posteriores no conjunto de resultados, temos de modificar um pouco o nosso LIMIT. Mas como? LIMIT 10 obteria as 10 primeiras linhas, portanto isso não funcionaria. Nós precisamos obter as linhas 6 a 10, e para isso nós usamos LIMIT com uma sintaxe diferente. Quando você fornece dois argumentos a LIMIT, o primeiro controla o número de linhas que quer pular, e o segundo controla o número de linhas que você recebe. Por exemplo, eis o modo de obter as linhas de 11a 25, o que seria a terceira páginas dos resultados: $query = build_que3ry ($user_search, $query = $query L J M rr c o n s o la <juaís e q u a n t a s lín h a s s re to rn a d a s u m a c o n su lta S Q L , 0 primeiro argumento di2. a L~/VT quantas linhas pular - as dez. primeiras. Ô secundo argumento dontroia quântas linhas são retornadas —dindo, o mesmo que antes. você está aqui ► 549
  • 552.
    use LIMIT paraajudar nos resultados de paginação Controle os links das páginas com LIMIT Uma tarefa importante da paginação é fornecer links que permitam ao usuário navegar entre as diferentes páginas de resultados. Nós podemos usar a cláusula LIMIT para definir os links de navegação na parte de baixo de cada página. Por exemplo, os links "próximo" e "anterior" podem ter, cada um, o seu LIMIT. O mesmo se aplica aos links numéricos que permitem ao usuário pular diretamente para uma página específica dos resultados. Eis as cláusulas LIMIT para as três primeiras páginas dos resultados,junto com LIMITs para alguns dos links: LIMIT 0, 5 / LIMIT 5, 5 LIMIT 5, 5 LIMIT 15, 5 LIMIT 10, 5 LIMIT 5, 5 Sem problemas. Nós só precisamos escrever ummonte de consultas, comumLIMIT diferente para cada uma, certo? Mais ou menos isso. Nós precisamos de um LIMIT diferente dependendo da página e do link, mas podemos gerá-lo em vez de escrever várias consultas. Tudo o que precisamos fazer é modificar um pouco mais a nossa função build_query(), para adicionar o LIMIT correto ao final da consulta que ela constrói.
  • 553.
    stíngs e funçõespersonalizadas Mantenha registro dos dados da paginapão Para adicionar a nova funcionalidade de paginação a build_query(), nós precisamos configurar e manter registro de algumas variáveis que determinem quais resultados devemos consultar e mostrar em uma dada página. Essas variáveis são importantes também para determinar como os links de navegação na parte de baixo da página serão gerados. $cur_page Obtém a página atual, $cur_page, a partir da URL do scriptvia $_GET. Se não houver nenhuma página atual para ser passada através da URL, define $cur_page como a primeira página (1), $results_j>er_j?age Este e o numero de resultados por página, que você pode escolher para melhor se adequar à aparência da página, colocando a quantidade de resultados que caibam bem no layout da sua página. É daqui que vem o segundo argumento para a cláusula LIMIT. flflRRWiii $skip Calcula o número de linhas a serem puladas antes de começar a exibir as linhas da página atual. Estavariável é o que controla onde cada página começa, em termos de resultados, fornecendo o primeiro argumento para a cláusula LIMIT. $total Executa uma consulta que obtém todas as linhas, sem nenhum LIMIT, e depois conta os resultados e armazena o resultado em $total. Em outras palavras, este é o número total de resultados da busca. $num__pages Calcula o núm ero de páginas, $num_pages, usando $total dividido por $results_per_page. Assim, para cada busca, existe uma quantidade $total de linhas de resultados, mas estas são exibidas uma página por vez, com cada página contendo um número $results_per_page de combinações. Existem $num_pages páginas, e a página atual é identificada por $cur_page.
  • 554.
    definindo varáveis necessáriaspara paginação Pefma as variáveis da paginapão A maioria das variáveis de paginação pode ser definida puramente através de informações fornecidas pela URL, que fica acessível por meio da superglobal $__GET. Por exemplo, asvariáveis $sort, $user__search e $cur_ page surgem todas diretamente a partir de dados GET. Nós podemos então usar essas variáveis para calcular quantas linhas devem ser puladas para chegarmos à primeira linha de dados, $skip. Avariável $results_per_page é um pouco diferente, no sentido de que nós simplesmente a definimos com o número de resultados que queremos ter em cada página, o que é mais uma questão de gosto pessoal, levando-se em consideração o layout da página de resultados. Obtém â ordem àt elassiíidâçãoí « um mime*-©inteiro í>btem a S ' * à t! 3 *' jagina atual, ^ Obtém a configuração de classificação e as palavras- ^ chaves de busca a partir da URL, usando GET partir da URL f Obtem a dc v i a SET. Se $sort = $_GET [ 'sort ']; bu^a que o usuino não houver uma §user search = $ get ['usersearch' ]; ^ digitou no -Pormuiario. pagina atuai, - _ ^ .f . ' Se o nu*»ero de+me f£ur ^ . « da pa<yna nao pay t o rn o I . I J c - // Calcula as informações de paginação s - esti v e r f l e - r m i G o , í o padrao é a $cur_page = isset {$_GET [1 page'] ) ? $_GET [ 'page '] : 1; p a g i n a . $results__per_page = 5; // número de resultados por página $skip = (($cur_page - 1) * $results_per_page); Pefine ° J K número de j ^ ^ Este ÚWo resulta em 0 resultados Caidula o número da primeira para a pagi*a I, 5 para a linha da página, /skip. pagina 1 , 10 para a página eit por pagina- Ainda faltam duas importantes variáveis: $total e $num_pages. Essas variáveis só podem ser definidas após realizarmos uma consulta iniciai para descobrir quantos resultados foram encontrados no banco. Uma vez que saibamos quantos resultados nós temos, é possível definir essas variáveis e então usar LIMIT nos resultados...
  • 555.
    stings e funçõespersonalizadas Revise a consulta para ter resultados paginados Agora que nós temos nossasvariáveis definidas, precisamos revisar o script Search para que ele, em vez de fazer consultas para todos os resultados, faça-as apenas para o subconjunto de resultados de que precisamos para a página que o usuário está visualizando no momento. Para isso, primeiramente fazemos uma consulta para que avariável $total possa ser definida, e avariável $num_pages possa ser calculada. Em seguida, fazemos uma segunda consulta que usa $skip e $i'esults_per_page para gerar uma cláusula LIMIT, que adicionamos ao final da consulta. Eis a seção do scriptsearch.php revisada, com essas adições salientadas: retorna um a dont3<jem de quantas linhas -foram reiornadas peia donsulta. Esta donsuita obtew •todas as linhas, ser* nenhum LiMÍT. // Confeulta para obter o total de res $query = build_query $result = mysqlí_que ’ •($dbc, $query) ; $sort); A íun^ão rowsO retorna o número ados l i n h a s C alfiw la o número àt painas, dividindo o numero total de linhas pelo número de resultados por pá^nâ,« depois arredondando o resultado- A -fundão dei10 arredonda um numero ate o inteiro »ais próximo —o w tetow. // Consulta novamente,. para obter somente o subconjunto dos resultados — e retorna este número de linhas- $result = mysqli_query{$dbc, $query); while ($row - mysqlijfetch_array($result)) { echo ’ <tr class="reaults', > 1; echo 1<td valign="tpp" width="20%"> 1 Puía este numero de linhas— echo '<td valign="t} op” width="50%">' 100) . '...</td>' ; echo '<td valign="tpp" width="10%"> $row['title' ] . '</td>'; substr($row['description'], 0, $row['state' ] . '</td>'; substr($row['date posted']/ 0, echo 1<td valign="t®p" width="20%">' 10) . *</td> '; _ , pmite uma sejunda Consulta, «as echo 1</tr> '; desta v e z .limitândo os resultados para a pagina atual- echo ’</table>'; você está aqui ► 553
  • 556.
    criando os linksde navegação (rere os links de navegação da página Então, nós definimos algumas variáveis e construímos uma nova consulta SQL que retorna um subconjunto de resultados para a página. Só o que ainda precisamos fazer é gerar os links de navegação da parte de baixo da página de resultados: o link "previous” ("página anterior”), links numéricos para cada página de resultados, e o link "next" ("página seguinte"). Nósjá temos todas as informações de que precisamos para criar os links. Vamos revê-las para nos certificarmos de que está claro o modo como elas serão usadas. $user search Cada link ainda precisa saber o que o usuário está realmente procurando, portanto nós temos que passar os termos de busca na URL de cada link. $cur_page Os links de navegação dependem inteiramente da página atual, de forma que é muito importante que essa informação seja empacotada na URL de cada link. $num_pages Nós precisamos saber quantas páginas existem, para podermos gerar links para cada uma delas. $sort A ordem de classificação também influi sobre os links de paginação, porque a ordem precisa ser mantida ou então a paginação inteira não faria muito sentido. Ok, nós sabemos quais são as informações de que precisamos para gerar os links de navegação, portanto, estamos prontos para escrever o código PHP necessário. Esse código poderia simplesmente ser colocado no script search.php, mas que tal se o colocássemos na suaprópria função personalizada? Dessaforma, o código principal do scriptque gera osresultados da busca pode permanecer muito mais simples, exigindo apenas uma linha de código para gerar os links das páginas - uma chamada a estanovafunção, que chamaremos de generate_ page_links(). O único senão é que nós não queremos que esta função seja chamada se houver apenas uma página de resultados. Assim, precisamos verificar o número de páginas antes de chamar a nova função generate__page_links(). Eis o modo como podemos realizar a verificação e chamar a função, sem nos esquecermos de enviar as informações necessárias na forma de argumentos para a função: if ($num__pages >1) { FVimciramCft-U) veviíique se e*iste mdis de Uimâ de V'CSul'fcâdoSj tdSO don-h-avio, r£o 0crc os l'mks- Ehvie a stHhj de busda; a orde* de dlassilidada«, a pagina atua! e o numéro ■tatal de pajihas a sever* usadas »a dvnadâo dos links.
  • 557.
    stings e funçõespersonalizadas Imas de Geladeira dp F B F A função generate_page_links() está quase pronta, mas estão faltando alguns pedaços de código. Use os imas para preencher o código que está faltando e dar ao Risky Jobs a capacidade de gerar links de navegação para as páginas. function generate_page_links($user_search, $sortf $cur_page, $num_pages) { $page_links = ' ' ; // Se esta página não for a primeira, gera o link "previous" if (...................... ) { $page_links .= '<a href=”'.. . $_SERVER ['PHP_SELF •] . ' ?usersearch=1 . $user_search . ’&sort=' . $sort . '&page=' . ( - - } else { $page_links .= '<- } .......... ) . '"><-</a> N link Previous òVèYttLt tomo urwâ I M w seta para 3 esquerda, < - • // Faz um loop através das páginas, gerando os links com os números das páginas for($i = 1; $i <= $num_pages; $i++) { if { ......................) { $cur_page $page_links . $i; } else { $page__links .= ' <a href=" ' - $_SERVER['PHP_SELF' ] . 1?usersearch=' . $user_search . '&sort=' . $sort . '&page=' . $i . '"> ' . $i . '</a>'; } //Se esta página não for a última, gera o link "next” if ( .............................. ) { $page_links .= ' <a href=r " . $JSERVER[1PHP_SELF1] . '?usersearch=' . $user_search . 1&sort=’ . $sort . '&page=' . ($cur page + 1) . T">-x/a>'; $num_pages } else { $page_lmks .= ’ -j>'; Q imk ’next" aparete tomo uma V seta para a direita, return $page links; você está aqui ► 555
  • 558.
    a função completagenerate_pagejinks() i InictS d e G e la d e ítc t d 9 F H P & M / S Q L - S o l u ç ã o A função generate_page_links() está quase pronta, mas estão faltando alguns pedaços de código. Use os imas para preencher o código que está faltando e dar ao Risky Jobs a capacidade de gerar links de navegação para as páginas. function generate_page_links ($user__search, $sort, $cur_page, $num__pages) $page_links = ’’; // Se esta página não for a primeira, gera o link "previous" if ( $cur_page P T m m m . ) { $page_links .= '<a href="' . $_SERVER[’PHP_SELF' '?usersearch=' . $user search . $sort . ” ■ 1&sort=1 ’&page=1 $cur_page 1 Nós ainda pvedisamos caviar os dados da busda ^ do usuário, bem domo a ordem de dlassi-fidaeão, else { $page_links .= 'o T; } 0 link ^previous aparede tomo uma seta para a esquerda, <- // Faz um loop através das páginas, gerando os links com os números das páginas for ($i = 1; $i <= $num_pages; $i++) { if ( S $cur_page I = I $ i i i ) í $page_links .= ' ' . $i; Cerii-Pi^ue-se de <ue dada link aponte de volta para o mesmo sdript - hós estamos apenas enviando um numero de pagina diferente dom dada link. $ SERVER['PHP SELF’] . } else { $page_links .= 1 <a href="' _ ’?usersearch=1 . $user_search . '&sort=' . Çsort . '&page=' . $i . . $i . '</a>'; 0 l i w k para uma pagina } espedí-fida é simplesmente } o numero da pagina. // Se esta página não for a última, gera o link "next" i f ( j $cur_page j < | $num_pages { $page__links .= ' <a href="' . $_SERVER['PHP_SELF’] 1?usersearch=1 . $user_search . '&sort=' . $sort . '&page=' . ($cur_page + 1) . '”>-></a>'; else { $page links .: return $page links; / 0 link “next" aparede domo uma seta para a direita,
  • 559.
    Montando o scriptSearch completo stings e funções personalizadas E finalmente nós chegamos ao script Search completo do Riskyjobs, que exibe os resultados apropriados coin base nos termos de busca do usuário, gera cabeçalhos clicáveis para a classificação dos resultados, faz a paginação desses resultados e gera links de navegação na parte de baixo de cada página. <?php // Esta função cria uma consulta de busca a partir das palavras-chaves de busca e da configuração de classificação function build_query($user_search, $sort) { // base na configuraçao de classificação es fu user_searchf $sort) { } // lavegação, com base na página atual e no nú fu user_search, $sort, $cur_page, $num_pages) cação e as palavras-chaves de busca a Mosjá criamos estas -funÇoes, porianio «3o e pvediso retolodar dada li»Ha do todíjo delas a«w- return $page_links; $user search = $ GET['usersearch']; // Calcula as informações de paginação. Ü n S t ros i t * $cur_page = isset($_GET['page']) ? $_GET['page' ] : 1; $results_per_page =5; // número de resultados por página $skip = {($cur_page - 1) * $results_per_page); Chama a -Punção genera^&jsoH^ // Gera os cabeçalhos dos resultados depois os exibe- echo 1<tr class="heading">' ; echo generate_sort_links{$user_search, $sort); echo '</tr>'; i você está aqui ► 557
  • 560.
    o final search.php 0script Search completo, continua... // Conecta-se ao banco de dados require_once(1connectvars.php'); $dbc = mysqli connect(DB HOST, DB USER, DB PASSWORD, DB NAME); Chama bv*ld_^uevyO pava dviav „a donsulia SQL pava a busda. // Consulta para obter o total de resultados $query = build__query ($user_search, $sort) ; $result - mysqli_query ( $dbc, $query) ; . _ $total = mysqli_num_rows($result) ; $num_pages = ceil($total / $results_perjpage); // Consulta novamente, para obter somente o subconjunto dos resultados Çquery = $query . " LIMIT $skip, $results per page’ ' ; . k i .hait * i + - n a*ui a dlâusula L W T çresult - mysqli_query($dbc, $query) ; l while ($row = mysqli_fetch_array ($result) ) í busdâ apenas o s echo '<tr c l a s s = " r e s u l t s ; echo '<td valign="top" width=; "20%">' echo ’<td valign="top" width="50%">1 100) . ' . . . </td>' ; echo ’<td valign= , , top" width="10%">1 echo '<td valign="top" width=', 20%">, 10) . *</td>’; echo ’</tr>’; } echo '</table>’; subdonjunios do vesuliado . ?row['title1] . , </td>'; .^substr($row['description'], 0, .l$row[Tstate' ] . '</td>'; .substr ($row [' date_posted '], 0 , £ a«ui vai o dodî^o < ^u e esdvevemos pava reduziv a desdviçao e a da-b de postagem dos 3hindios; wsando a -fun^ao subyfcrO. // Gera links de navegação, se tivermos mais de uma página if($num_pages > 1) { echo generate_page_links($user_séarch, $sort, $cur_page, $num_pages); mysqli_close($dbc) ; — Mantem a dasa awumada, ■redhando a donexão dom o bando de dados. Chama a -fundão genevate__page_ linksO para gev-av os links das páginas, e depois os exibe- nap exístem P e r g u n ta s id io ta s Nós realmente precisamos enviar as informações de busca, classificação e paginação para generate_page_links()? I - Ok, e quanto a ecoar dados? Por que generate. pageJinksO simplesmente não faz echo dos links? H: í l : o Sim. Eo motivo para isso tem a ver com o fato de as funções, quando bem elaboradas, não devem manipular dados fora do seu próprio código. Assim, uma função só deve acessar dados enviados a ela em um argumento, e só fazer modificações em dados que ela retornar. mesmo problema. Ao ecoar dados para o navegador, a função estaria, na prática, dando um passo maior que as pernas, ao fazer uma modificação em algum outro lugar. É muito mais difícil realizar debug e manutenção quando não está claro quais dados a função está modificando. A solução é fazer sempre a função retornar os dados que está afetando, e aí então você pode fazer o que quiser com eles, mas fora da função.
  • 561.
    stings e funçõespersonalizadas T t e S T O R f v e Finalize o script Search do Risky Jobs. Adicione a nova função generate_page_lmks() ao script search.php, certificando-se de adicionar também o código que chama essa função após verificar se existe mais de uma página de resultados. Além disso, crie e inicialize as variáveis usadas como argumentos para a função. E não se esqueça de atualizar o código da consulta para que ela use LIMIT para obter o subconjunto correto de resultados para cada página. Quando estiver tudo pronto, envie o novo script search.php para o seu servidor web, e depois abra a página search.html em um navegador. Experimente fazer algumas buscas, e não se esqueça de procurar por alguns termos que você saiba que vão gerar muitos resultados, para ver as novas funcionalidades de paginação em ação. Para obter o máximo de páginas, faça uma busca sem digitar nenhum termo no formulário. Danger) Your dre*m job 1» out there Do you have the gut* to go find It? RiskyJobs-SearchResults BusiUngdaily farmlooking forpartiisie matadorto VT entertain spirited bull vitb mid castofADO. - SharkTrainer Firefighter Voltage Checker <-1234^> Top celebrity photography firm looking ferseasoned paparazzo U>stalk feniperaiitfiilal lip-syjïCÎEg ?I;P-. CA ft 2 Training shades to do cate tricksforthe audiencesat ournew water theme park. YouT3spend tim... EL ' 2ÛG8-G4-28 The City ofDatavilfe is hiring {kefiglîteis.No experienced reqniiEd- yon wilSbe taiissd. Nog-stck>._ OH 20O8-OS.22 YouH be out ia the field checking ax;, and djc.voltages in the rangeof3 to 250 or more vol's. Y. NC 2008-06-25 Ernesto endohxrou um emprego dom d ^»iidade per+eiía de rîsdo/ Não se esqueça: o código-fonte completo da aplicação Riskyjobs está disponível para download no site da Alta Books: www.altabooks.com.br você está aqui ► 559
  • 562.
    capítulo 9 caixa de ferramentasdo php & mysql L Sua Caixa de Ferramentas do PHP £- MySQL r O script Search do Risky Jobs exigiu uma boa quantidade de novas técnicas de PHP e MySQL. Vamos recapitular algumas das mais importantes.
  • 563.
    10 Expr®ss°es Regulares RégrasPara Substituição As funções string são adoráveis. Mas, ao mesmo tempo, são limitadas. Certamente elas podem realizar tarefas como lhe dizer a extensão da sua string, truncar a string, trocar certos caracteres por outros. Mas às vezes você precisa de liberdade para lidar com manipulações de texto mais complexas. É aqui que as expressões regulares podem ajudar. Elas podem modificar strings de forma precisa, com base em um conjunto de regras, em vez de um só critério. este é um novo capitulo ► 561
  • 564.
    riskyjobs tem dadosruins Risky Jobs permite que os usuários submetam currículos O site riskyjobs.biz cresceu. A empresa agora permite que os usuários digitem os seus currículos e informações de contato em um formulário web, para que os empregadores que usam o Risky Jobs possam encontrá-los mais facilmente. O formulário separece com o seguinte: 0 novo íormulario de registro do Risky Jobs permite ^ue os usuários digite» m-forma^oes pessoais, de modo Alé» das °SPcrk n^*s empregadores possa» . r ~ i -**1 íe*do*tra-!os. m+or^açoes de £ontato normais, o usuário deve digitar o seu e»prego desejado, be» torno o seu durrídJo. As informações dos nossos usuários que estão procurando emprego ficam armazenadas em uma tabela que pode ser consultada por empregadores, recrutadores e headhunters para identificarem potenciais novos contratados. Mas há um problema... os dados digitados no formulário aparentemente não sâo confiáveis! Nome;FourFingers 5°brenom e:M cGraw T p S : f o l í@9regs' ' i s tnet Telefone: 555-098 d e mfacT DeSejad° Ma,aba^ía Nome: Jimmy ?mprengoDeseiado:Ninja Primeiro eu queria contratar um ninja e não consegui, porque o número de telefone dele estava faltando. Agora, o meu email para este malabarista voltou. Estou cheio desses dados inválidos do b an c o de currículos do Risky Jobs. O 0s empregadores pode» ía^ r busôâs no ba»£o de dados do Risky Jobs e ehtao e*trar em dontato tor* as pessoâs para, possivelmente, dontrata-ias... desde < ^ u e as ijvfWmaáoes su-fidichtes de dontato su+idientes tenha» sido digitadas/
  • 565.
    expressões regulares Segue abaixoparte do código do script registration,php, que exibe e processa os dados digitados pelo usuário no formulário para se cadastrar. Escreva o que você acha que há de errado com o código, e como ele poderia ser modificado para resolver o problema dos dados inválidos. <?php if (isset ($_POST ['submit']) ) { $first_name = $_POST[Tfirstname1]; $last_name = $_POST['lastname']; $email = $_POST['email']; $phone = $_POST['phone']; $job - $_POST['job'] ; $resume = $_POST['resume']; $output_form = 'no'; if (empty($first_name)) { //$first_name está em branco echo T<p class="error">Você se esqueceu de digitar seu nome.</p>'; $output_form = 'yes'; } if (empty($last_name)) { . // $last_name está em branco echo ' <p class=”error”>Você se esqueceu de digitar seu sobrenome.</ P>'; $output_form = 'yes'; } if {empty($email)) { // $email está em branco echo '<p class="error">Você se esqueceu de digitar seu endereço de email.</p>'; $output_form = 'yes * ; } if (empty($phone)) { // $phone está em branco echo '<p class="error">Você se esqueceu de digitar seu número de telefone.</p>' ; $output_form = 'yes'; } Coh'tmU’ 3 â validav os dâmpos nâo vazios ire-Pev'Cn^ desejado e 3o t $output_form = 'yes'; } V 2 -Z ÍO &ire-feircnies So Cíttfrej. else { desejado e 3o 1«. ?> } if ($output_form == 'yes’) { yz--------o i’ovmuiario- você está aqui ► 563
  • 566.
    exercício solução ftcício § oluç£k> Segueabaixo parte do código do script registration.php, que exibe e processa os dados digitados pelo usuário no formulário para se cadastrar. Escreva o que você acha que há de errado com o código e como ele poderia ser modificado para resolver o problema dos dados inválidos. <?php if (isset($_POST['submit'])) { $first_name = $_POST[1firstname']; $last_name = $_POST[1lastname']; $email = $_POST[Temail']; Çphone = $_POST['phone']; $job = $_POST[’job'J; $resume - $_POST[1resume']; $output form = 'no'; 0 stript veri-fida se K a dampos em brando no formulário, o <ue e bom, mas alguns dos dampos te** dados mais espedializados < ^ u e predisam adcv-iv a um dctev-*y<inado íormato- if {empty{$first_name)) { // $first_name está em branco echo '<p class="error">Você se esqueceu de digitar seu nome.</p>'; $output_form = 'yes'; r } — N*0 ba muito M âis cjue possamos veri-fidar no <ue diz. respeito a nome e sobrenome, if (empty ($last_jiame) ) { portanto este dódijo esta ok. // $last_name está em branco echo '<p class="error">Você se esqueceu de digitar seu sobrenome</p>'; } $outPut_f = 1yes'; Mmertàe^ c àt ewa-| ^ ^ bastante espedífido, «ue nós devemos if (empty ($email)) { ^ veriíidar antes de adeitar os dados // $email está em branco -fornedidos pelo usuário. echo T<p class="error">Você se esqueceu de digitar seu endereço de email.</p>'; „ $output_form ='yes ' ; rour Finjer Md^raw se es^ueCeu de } dolodar um ponto perto do íinaldo seu endereço de email —o -formulário predisa if (empty {$phone)) { dapturâr esse tipo de erro/ // $phone está em branco echo '<p class="error">Você se esqueceu de digitar seu número de telefone,</p>' ; f c * . a * ■ * ■ j- ' mesma doisa dom o numero de tele-fone —o -formulário nao deve Continua a validar os campos não vazios re-ferehtes ao emprego } desejado e ao durrídulo. $output_form = 'yes’; } ser aterío a não ser <ue tenhamos derteza de <ue o tele-fone esta ho ■formato dorreto- else { $output_form = 'yes'; } if ($output form == 'yes') { Jimmy Swi-ft nao -fornedeu o DDP ?> £*ibe o formulário 0 ^ue nós realmente predisamos c de um a -forma de veri-fidar endereços ____ _ de email e números telefonidos, os -formulário deveria doxtempx do -formulário <ue tem ter e^ido- ** fara os demais dâm posj basta veri-fidar se eles nao estao vazios- dom o seu numero de tele-fone, o ^ue o
  • 567.
    expressões regulares Por quenós não usamos algumas funções string para consertar os dados inválidos? Não poderíamos ter usado str_ replaceQ para adicionar os dados que estão faltando? Você pode consertar alguns dados com funções string, mas elas não ajudam muito quando os dados precisam atender a um padrão bastante específico. As funções stxings são adequadas para operações de localizar-e- substituir simples. Por exemplo, se os usuários estiverem submetendo os seus números telefônicos usando pontos para separar os blocos de dígitos, em vez de hífens, nós poderíamos facilmente escrever algum código com str_replace() para substituir os pontos pelos hífens. Porém, para qualquer coisa que não podemos prever, como por exemplo, o DDD do número deJimmy Swift, precisamos pedir à pessoa que está submetendo o formulário para ser mais clara. E a única maneira que temos de saber que está faltando o DDD é entendendo o padrão exato de um número telefônico. O que nós realmente precisamos é de uma validação mais avançada, para garantir que coisas como números telefônicos e endereços de email sejam digitados da forma correta. Ok, mas aindaassim, não podemos usar funções string para fazer essa validação? As funções string não são realm ente úteis para validação de dados, a não ser que a validação seja muito primitiva. Pense na forma como tentaria validar um endereço de email usando funções string. O PHP tem uma função chamada strlen(),a qual lhe diz quantos caracteres existem em uma string. Mas não existe uma quantidade de caracteres pré-definida para coisas como endereços de email. E claro que essa função poderia ajudar no caso dos números telefônicos, porque eles frequentemente contêm uma quantidade consistente de números, mas você ainda poderá ter de lidar com pontos, hífens e parênteses. Voltando aos endereços de email, o formato deles é simplesmente complexo demais para que as funções strings sejam úteis. O que nós estamos realmente procurando aqui é por padrões específicos de dados, o que requer uma estratégia de validação que possa checar os dados do usuário em relação a um padrão, para ver se os dados são válidos. Modelar padrões para os seus dados é o cerne desse tipo de validação. você está aqui ► 565
  • 568.
    decida como deveráser a aparência dos seus dados Pecida conto deverá ser a aparência dos seus dados O nosso desafio é especificar, clara e exatamente, qual deve ser a aparência de uma determinada informação, nos mínimos detalhes. Considere o número telefônico deJimmy. Ebem óbvio, para um observador humano, que estáfaltando o DDD nesse número. Mas avalidação de formulários não é feita por humanos; ela é executada por código PHP. Isso significa que nós temos de ’’ensinar”o nosso código como procurar por uma string de dados digitados pelo usuário, e determinar se os dados atendem ao padrão estabelecido para os números telefônicos. Elaborar um padrão desses pode ser um desafio, que exige pensar bem sobre a gama de possibilidades para o tipo de informação. Os números telefônicos são relativamente simples, uma vez que eles possuem, nos Estados Unidos, 10 dígitos com delimitadores opcionais. Os endereços de email são outra história, mas iremos nos ocupar deles mais adiante neste capítulo. Por que ninguémestá ligando? P â r à um s e r h u m an o , c -fácil vcr Jimwiy $c es<^tóeu de folotèr o SC* m <3s í»,3o e ião simples âssifft -fazer essa mesma observação ã pariir de Cadimo P H P . First Name: Jimmy Last Name: Swift Email: JS@sim-u-duck.com Phone: 636 4652 Desired Job: Ninja exMem Ainda não sei se entendi por que não posso simplesmente usar isset() e emptyO para a validação do nosso formulário. Essas duas funções lhe dizem se o usuário que submeteu o formulário colocou ou não dados em um campo de texto, mas eles não lhe dizem nada sobre os dados propriamente ditos. No que diz respeito à função empty(), não existe absolutamente nenhuma diferença entre o usuário digitar *{707) 827-700* ou *4FG8SXY12* no campo de telefone do nosso formulário. Isso seria um grande problema para sites como o Risky Jobs, que depende de dados confiáveis para entrar em contato com os candidatos a empregos. Se isset() e empty() não P e r g u n t a s id io t a s - íuncioriam, nao poaernos simplesmente ter alguém para verificar os dados depois de eles serem colocados no banco? Você pode, mas a essa altura frequentementejá é tarde demais para consertar os dados inválidos. Se estiver faltando o DDD em um número telefônico, nós teremos de pedir ao usuário que esclareça as coisas, submetendo novamente os dados desse campo. Se esperar para verificar os dados só depois que elesjá estiverem no banco, talvez você não tenha como contatar o usuário para lhe dizer que alguns dos seus dados estavam inválidos. E uma vez que o usuário provavelmente não vai perceber que cometeu um engano, é possível que elejamais fique sabendo que há algo de errado. Assim, o melhor plano de ação é validar os dados dos usuários imediatamente, quando eles submeterem o formulário. Dessa maneira, você poderá exibir uma mensagem de erro e pedir que eles preencham o formulário novamente. Mas então como decidimos se os dados digitados são válidos ou não? R : Isso depende do tipo dos dados. Diferentes tipos de informações têm diferentes regras que precisam seguir: qual tipo de caracteres elas contém, quantos caracteres, em qual ordem esses caracteres devem estar. Assim, você precisa comunicar essas regras ao seu código PHP. Vamos dar uma olhada com mais detalhes nas regras que governam os números telefônicos...
  • 569.
    - ^j^jottfeseu lápis------------------------------------------------ Escrevaabaixo todas as formas de representar um número telefônico que você conseguir se lembrar. expressões regulares Quais são algumas regras que é razoável esperar que os seus usuários sigam ao preencher o formulário? Por exemplo, números telefônicos não devem conter letras. Eis uma re^ra, tomo exemplo. Mós poderíamos e*<$ir regras domo-' somente dígitos pode» ser usados neste tampo. você está aqui ► 567
  • 570.
    i— f*Aponte seulápis Solupão Escreva abaixo todas as formas de representar um número telefônico que você conseguir se lembrar. Espaços, brados, parênteses, e as vez£s pontos podem apareder t** números te!eíonsdos E possível ate mesmo indluir letras em um número tele-Ponido, mas isso ja estaria perto de ultrapassar os limites do < ^ u e nós devemos donsiderar domo um numero valido- 95<5 Eis uma regra, _ domo exemplo. (<595)^-4*52- ..................... ÇÇ 4*6ÇZ z ÇÇÇfc^&^&ÇZ ÇÇÇ— ^j"^Z 955 ME KIKJA Quais são algumas regras que é razoável esperar que os seus usuários sigam ao preencher o formulário? Por exemplo, números telefônicos não devem conter letras. M os poderíamos exigir regras domo- somente dígitos podem ser usados neste dampo- Nós.poderíamos dividir o número emtres dampos do formulário, um para o .P P P . > ..W. pâr.^.?.s..i*!*? primeiros dígitos, e. um para os quatro últimos dígitos.-. Ou nós poderíamos iníomar às pessoâs ^ue o número de teleíone dçlas deve seguir o -formato . ( f N o s fazemos as regras. 568 Existem tantos padrões possíveis. Como poderemos criar regras para dar conta de todos eles? Existem algumas coisas que sabemos com certeza sobre números telefônicos, e podemos usar essas coisas para criar as regras. Primeiramente, eles não podem começar com 1 (código de interurbano) nem 0 (telefonista).Em segundo lugar, deve haver 10 dígitos. E mesmo que algumas pessoas possam ter maneiras inteligentes de representar os seus números com letras, os números telefônicos são essencialmente números - 10 dígitos quando incluímos o DDD. Canr
  • 571.
    expressões regulares Formule umpadrão para números telefônicos Para ir além da validação básica, como a de empty() e isset(), nós precisamos adotar um padrão para os nossos dados. No caso do número telefônico, isso significa que temos de optar por apenas um formato que esperamos receber do campo telefone de nosso formulário. Uma vezque decidamos por um padrão/formato para o telefone, podemos validar esses dados. Segue o que provavelmente é o formato de telefone mais comum em uso hoje em dia, pelo menos para números dos EUA. Usar este formato significa que, se os dados que os usuários digitarem não se conformarem a ele, o script PHP irá rejeitar o formulário e exibir uma mensagem de erro. Nós optados l àfytos, 1A F Khíícf») hííe* c e*tao os 4" dfyto* -ÇmáiS' 636-46521 * . JK n^UI estaO v — ^«altando dígitos, fcí&hs e o Hííe* * V *e existe parede estar -fora do fcte bate períe«ta»ehte Com o nosso padrao. r e # # # - # # # - # # # # 555-636-46521 . , 7 dígito 3 r»>a»sf| 5556364652 Este hão íffm KtíehS. nãp existem Eu tenho que usar exatamente esse padrão para os números telefônicos? Esse é o que estamos usando para o Risky Jobs porque ele é basicamente o padrão, mas ao elaboraros seus próprios formulários você deve escolher um que faça sentido para você. Apenas tenha em mente que, quanto mais comum o padrãofor, maior a probabilidade de os usuários o seguirem. p e r g u n t a s i d i o t a s - Você poderia fazer isso e seria suficiente se esse fosse o padrão esperado pelos seus usuários. Infelizmente, na realidade esse não é um padrão muito bom, porque a maioria das pessoas não escreve os seus números telefônicos com os números todos juntos desse jeito. É um pouco fora do padrão, o que significa que os usuários não estarão acostumados com ele, e será menos provável que irão segui-lo. r p Nós não poderíamos simplesmente dizeraos usuários para digitarum padrão como e depois usar as funções P:E daí? 0 padrão é meu, eu posso fazer o que quiser; certo? Ok, eu não poderia então usar três campos de texto para o número: um para o DDD, depois três dígitos no segundo, e finalmente os últimos quatro dígitos no terceiro. Aí então eu poderia usar as funções string do PHP. Sim, você poderia, e alguns sites fazem isso. Mas usar os padrões lhe dá mais flexibilidade. E os padrões são úteis para muito mais coisas do que apenas verificar se o usuário digitou o número de telefone corretamente, como você verá mais adiante neste capítulo.. string do PHP para nos certificarmos de que os dados contenham 10 caracteres numéricos? Claro, mas ao mesmo tempo você quer que os seus usuários tenham uma boa experiência. Caso contrário, eles não voltarão ao seu site. você está aqui > 569
  • 572.
    introduzindo expressões regulares Confirapadrões com relapão a expressões regulares O PHP oferece uma maneira poderosa de criar e verificar padrões em um texto. Você pode criai' regras que lhe permitem procurar por padrões em strings de texto. Essas regras são conhecidas como expressões regulares ou simplesmente regex. Uma expressão regular representa ura padrão de caracteres a encontrar. Com a ajuda das expressões regulares, você pode descrever no seu código as regras que deseja impor as suas strings. Como exemplo, eis uma expressão regular que procura por 10 dígitos seguidos. Este padrão só irá coincidir com a uma string que consista de um número com 10 dígitos. Se a string for maior ou menor do que isso, não irá checar. Se a string contiver qualquer coisa que não seja um número, não irá coincidir. Vamos aos detalhes, /Ad d d d d d d d d d $ / Q tirí-unílexo a íAtftar do infcio da d dígito- 0 frimeisre t&ràCÍcr da $trmg ser umdfiÿto— - .„e tèÒA um destes siyú-Çida a mesma eoísar pv-odurar for OM tsro —0 no total- Existe também uma forma mais concisa de escrever esta mesma expressão regular, utilizando chaves. As chaves são usadas para indicar repetição: usadas p a ra c o în c îd îr padrões em uma < ? u 570 fianítsiln ift
  • 573.
    expressões regulares Sim, asexpressões regulares são claríssimas. Claras como lama. É verdade, as expressões regulares são enigmáticas e frequentem ente difíceis de ler... mas são bastante poderosas. O poder frequentemente tem um custo; no caso das expressões regulares, esse custo é aprender a sintaxe enigmáticas que elas usam. Você não vai se tomar um mestre das expressões regulares da noite pro dia, mas a boa notícia é que você não precisa se tomar um. E possível fazer algumas coisas impressionantemente poderosas e úteis com as expressões regulares, principalmente no que diz respeito à validação de campos de formulário, com um conhecimento bastante básico dessas expressões. Além disso, quanto mais você trabalhar com elas e quanto mais prática tiver em analisá-las em detalhes, mais fáceis de entender elas serão. você está aqui ► 571
  • 574.
    metacaracteres regex comuns Criepadrões usando metacaracteres Poder checar dígitos em uma string de texto usando d é bem legal, mas se isso fosse tudo o que as expressões regulares possibilitassem, o seu uso seria tremendamente limitado. Apenas checar dígitos não é suficiente nem para a validação de números telefônicos no Riskyjobs, uma vez que precisaremos checar caracteres como espaços, hífens e até mesmo letras. Felizmente, afuncionalidade regex do PHP lhe permite usar expressões mais especiais, comoVI,parachecaressascoisas. Essas expressões são chamadas de metacaracteres. Vamosdar uma olhada em alguns dos metacaracteres regexusados maisfrequentemente. d Como você viu na página anterior, este metacaracter procura por um dígito. Qualquer número de 0 à 9 - em outras palavras, sevocê quisesse encontrar um número com dois dígitos, teria de usar W oud{2}. s Procura por espaço em branco. Isso não significa apenas o caracter espaço que você obtem na tela ao digitar a barra de espaço* V tambem encontra caracteres tab, ou um' newlme ou caniage return. Novamente, lembre-se que s só encontra um desses ’ caracteres por vez. Se você quiser encontrar exatamente dois caracteres espaços seguidos, precisa usar^V ouV(2}. O metacaracter ponto final encontra qualquer outro caracter, exceto um newline. Encontra letras ou dígitos, assim comow, bem como espaços ou tabs, comoV Os metacaracteres ii9s permitem desci-eVet padrões cíe i e X t ° d e n t r e de uma expressãp regular. w Procura por qualquer caracter alfanumérico ! em outras palavras, ou uma letra ou um numero. Encontra um dos seguintes caracteres: a - z e A- 2 (tanto maiúsculas quanto minúsculas), bem como 0-9 (assim comod) .. Nós também vimos o metacaracter circunflexo na página anterior. Ele procura pelo começo da string, de modo que você pode usá-lo para indicar que precisa haver uma combinação no início de uma string de texto, e não em qualquer lugar da string. Por exemplo, a regex / A d{3}/ encontrará a string "300 cadastros", mas não a string "Nós recebemos 300 cadastros". Procura pelo final de uma string. Você pode usar este metacaracter com Apara marcar o início e o fim da sua string, especificando exatamente onde ela começa e onde termina. Por exemplo / Aw{5Jsd{3}$/ irá encontrar “Nanny 411”, mas não “Nanny 411é ótima’ nem “Ligue para Nanny 411”. Esses metacaracteres são legais, mas e se você quisesse ter um caracter específico na sua regex? Basta usar esse caracter na expressão. Por exemplo, se quisesse encontrar o número de telefone “707-827-7000”exato, você usaria a regex /707-827-7000/. rs /»
  • 575.
    expressões regulares * ’+ WfUlfí.-fSkf # IMi» Ligue cada expressão regular ao número telefônico a que ela corresponde. KegeX // v d{ 3}sd{7}$/ /Ad{3}sd{3}sd{4}$/ /Ad{3}d{3}-d{4}$/ /Ad{3}-d{3}~d{4}$/ /Ad{3}swwsw{5}$/ Sttín^^ue elaencpiitta 5556364652 555 636 4652 555636-4652 555 ME NINJA 555 6364652 555-636-4652 você está aqui ► 573
  • 576.
    quem faz oque solução Ligue cada expressão regular ao número telefônico a que ela corresponde. /Ad{3}sd{7}$/ /~d{3}sd{3}sd{4}$/ /Ad{3}d{3}-d{4}$/ Este e o fâdrâo < ^ u e o Risky Jobs usa pava endontrar numéros de tele-fones no formâto /Ad{3}-d{3}-d{4}$/ /Ad{3}swwsw{5}$/ 5 O s meiatavatteves * neste fadrão endontvarw letras. /Ad{10}$/ Este fadrao e doynpost©totalmente for diÿtos, de modo *^ u e ele só donsegue endontrar um húmero tele-fônido < ^ u e não tenha esfados nem hífens. 5556364652 555 636 4652 555636-4652 555 ME NINJA 555 6364652 555-636-4652 *57A
  • 577.
    expressões regulares S iN T A - S E c o m o u m a E x p r e s s ã o R e g u l a r Suatareía é Interpretai- o papel da expressÈb regular, e aceitar pu rejeitar númerosteleÍPiúcos d°s usuáríos dp RïskyJol->s. Marque ps números ^ue- Vpce considerar Válidps, e deixe 9S demais em brancP. a expressão EsoreVa ppr <jue ps núnieros mvalídps reguiar para o sãp xnV^Jides* ___nwmero lele-fonito - eja ela/ / Ad {3 }-d {3 }-d {4 }$ / □ (555) 935-2659 □ (555)672-0953 Surf pode sev V tm â atividade be» arrisdada> principalmente guando vode trabalha de ista profissional para tubarões/ □ 555-343-8263 555-441-9005 □ 555.903.6386 □ 555-612-8527-8724 você está aqui ► 575
  • 578.
    § ! n1 T A - S E o o r n o u r n a E x p r e s s a 0 R e g u la i: “ S o lu ç ã ? Sua-íareía é Interpretar o papel da expressa? regular, e aceitar Q Urejeitar númerostele-ÇpnicPs cIps usuários d9 RiskyJobs. Marque os nÚmel-9S <jne Voceconsiderar Válidos e deixe çs demais em Wancp. EscreVapet <jue 95 números inválidos sãp inValídps. seja expressão regular solução Esta e a expressão regular para o número tele-fênico - seja ela/ / Ad {3 }-d {3 }-d {4 }$ / Parênteses «ao são permitidos e espaços também n3o-> □ (555) □ (555)672-0953 Sem parenteses, por -Pavor. 555-343-8263 ^s nossas expressões regulares requerem Kífens e nao pontos. Bi, tem quatro números a mais a«^ui. Isso e uma extensão Cmum esáritorio? 555-441-9005 □ 555.903.6386 □ 555-612-8527(-8724 5 7 fi ríanífn/rt <n
  • 579.
    expressões regulares As vezesas pessoas colocam dígitos a mais nos seus números telefônicos, como por exemplo, uma extensão de quatro dígitos no final. Existe alguma maneira de encontrarmos esses padrões também? Sim, mas a chave é especificar esse tipo de padrão como opcional, na sua expressão regular. Se modificássemos a nossa regex para / Ad{3fd{3}-d{4}-d{4}$/, estaríamos exigindo que a nossastring tivesse uma extensão de quatro dígitos no final, e não conseguiríamos mais encontrar números como “555-636-4652”.Mas podemos usar expressões regulares para indicar que partes da string são opcionais. As regexes têm suporte a um recurso chamado quantificadores, que lhe permitem especificar quantas vezes os caracteres ou metacaracteres devem aparecer em um padrão. Na verdade, vocêjá viu os quantificadores em ação, em regexes como esta: W» «V *»* d'2 **- U o dfyto deve / a i X U iO ve^es sendas" Aqui, as chaves agem como quantificador, para dizer quantas vezes o dígito precedente deve aparecer. Vamos dar uma olhada em alguns outros quantificadores frequentemente usados. {min,max} Quando há dois números dentro das chaves, separados por vírgula, issoindicauma faixade possíveisvezesque o caracterou metacaracter deveserrepetido. Aqui, estamos dizendo que ele dc aparecer 2,3 ou 4vezesseguidas.! O caracter ou metacaracter precedente deve aparecer uma ou mais vezes. O caracter ou metacaracter pode aparecer uma ou mais veies... ou não aparecer nenhuma vez. O caracter ou metacaracter precedente ídeve aparecer uma vez [ou então não aparecer inenhuma vez. 0 Assim, se quiséssemos encontrar aqueles dígitos opcionais no final do ôSpôC lílC a número telefônico, poderíamos usar o seguinte padrão: <juíW rfâsVezes / Ad {3}-d {3}-d {4} (-d {4})?$/ ummetacaracter deVe a p re c e i'. Coloque entire parênteses a sedâo à ^«a! o ^uâftti-í-idado*- se aplida. 0 ponto de mterregaçã© faz. dor* ^*e o Sífen e os quatro últimos dígitos seja» opdionâis- você está aqui ► 577
  • 580.
    usando classes decaracteres Você se esqueceu de uma coisa. Os números telefônicos nos EUA não podem começar com 0 nem 1. Você tem toda razão. 0 é o número para chamar uma telefonista e 1 é o código para interurbanos nos EUA. Nós queremos simplesmente o código DDD e o número. Precisamos nos certificar que o primeiro dígito não seja 1 nem 0. E para isso, precisamos de uma classe de caracteres. As classes de caracteres lhe permitem encontrar caracteres a partir de um conjunto específico devalores. Com uma classe de caracteres, você pode procurar por uma faixade dígitos, e pode também procurar por um conjunto de valores. Evocê pode adicionar um circunflexo para procurar por tudo que não esteja no conjunto. Para indicar que alguns caracteres ou metacaracteres pertencem a uma classe de caracteres, tudo o que você precisa fazer é colocá-los entre colchetes, []. Vejamos alguns exemplos de classes de caracteres em ação: [0- 2 ] Isto encontrará uma faixa de números, especificamente 0, 1 ou 2. [A-D] Isto encontrará A, B, C ou D. Uma classe de c a ra c te re s e um conjunto de regrais para se encontrar um c a ra c te r. Em umâ itasse de davâítevcs, o A signilidd [Ab-f] Este circunflexo tem um significado diferente quando usado dentro de uma classe de caracteres. Em vez de dizer "as strings devem começar com...”, o circunflexo significa “encontrar tudo exceto...” Isto encontrará tudo exceto b, c, d, e ou f. Escreva aqui uma expressão regular que encontre números telefônicos internacionais:
  • 581.
    expressões regulares Ajuste ospadrões com classes de caracteres Com a ajuda das classes de caracteres, podemos refinar a nossa expressão regular para números de telefone, de modo tal que ela não encontre combinações inválidas de dígitos. Dessa forma, se alguém acidentalmente digitar um DDD que comece com 0 ou 1, podemos exibir uma mensagem de erro. Eis como seria a nossa nora e melhorada regex: A c f espedVfita» <ue â nossa re^e* deve dobrir / toda a de -fc e ^ fc o «^e es£a**os domparândo- / A[2-9]d {2 }-d {3 }-d {4 }$ / t V V ^ dlasse de darafcteves ...ei^ osestam os diz- ° v 'oSSO j>rodurando por mais dois tavattev- deve ser v & y * * díyt>s ^ue podem ser díyfco á t 2 - i % c^aí^er valor entre 0 e *■ n ã ° e x i s t e m -------------------Fel-gurttaslcllç>tíis ■ seguidos de mais ires dígitos.... Bw o^-b-as palavras, a string pode donter nenbum outro daradter *^ u e na©pertenda ao numero tele-ronido- ....e um h$e* e »ais os ultímOS dtyW p Então as classes de caracteres permitem que você especifique uma faixa de caracteres para comparar com a string de texto? í ^ ! Sim, a classe de caracteres lhe permite especificar, na sua expressão regular, que qualquer membro de umconjunto de caracteres especificado poderá ser usadopara se encontrar a string de texto, em vez deapenas umcaracter. Porexemplo, a classe [aeiou] encontrará uma instância de qualquer vogal minúscula, e aclasse [m-zM-Z] encontrará uma instânciade qualquer letrada segunda metade do alfabeto, seja minúscula ou maiúscula. Eaclasse [0-9] éequivalente ao metacaracterd, que na verdade é apenas umaforma abreviada de dizer a mesma coisa. : Não é preciso colocar espaços ou vírgulas entre os caracteres ou faixas que eu especificar nas classes de caracteres? Não. Se você fizer isso, esses caracteres extras serão interpretados como parte do conjunto de caracteres a serem comparados com a string de texto. Por exemplo, a classe [m-z, M-Z] encontraria não apenas as letras minúsculas e maiúsculas de maté z, mas também uma vírgula ou um espaço, o que provavelmente não é o que você quer. uma vez, com uma classe de caracteres? Por exemplo, uma ou mais vogais consecutivas?. Basteiadicionarumquantificadordepoisdaclassede caracteres.Aexpressão/[aeiouAE10U]+/ encontraráumaoumais vogaisseguidas. ^ - E u pensei que os quantificadores só se aplicassem ao caracter imediatamente antes deles. Geralmente é assim, mas se o quantificador vier logo depois de uma classe de caracteres, ele se aplica à classe inteira. E se você quiser fazer com que o quantificador se aplique a toda uma série de caracteres que não estejam em uma classe, poderá colocar esses caracteres entre parênteses, para indicar que eles devem ficar agrupados. Como exemplo, a expressão regular /(hello)+/ encontrará uma ou mais ocorrências consecutivas da palavra "hello" em uma string de texto. E se eu quisesse encontrar uma palavra escrita de duas formas diferentes, como "ketchup" ou "catsup"? H: Você pode usar a barra vertical (|) nas suas expressões regulares para indicar um conjunto de opções. Assim, a expressão regular/(ketchup|catsup|catchup)/ encontrará qualquer uma das três grafias mais comuns para essa palavra. • P : a» niiicicco encontrar um caracter mais de você está aqui ► 579
  • 582.
    escapando caracteres reservados Sequiser usar caracteres reservados na sua expressão regular, você precisa fazer escape deles. Na sintaxe das expressões regulares, há um pequeno conjunto de caracteres que recebem significados especiais, porque são usados para indicar coisas como metacaracteres, quantificadores e classes de caracteres. Entre eles estão o ponto final {.), o ponto de interrogação (?), o sinal de mais (+), o colchete de abertura ([), os parênteses, o acento circunflexo (A), o cifrão ($), a barra vertical (]), a barra invertida (), a barra normal (/) e o asterisco (*). Se quiser usar esses caracteres na sua expressão regular, com o significado deles, em vez dos metacaracteres ou quantificadores que eles normalmente representam, você precisa "escapá-los", colocando uma barra invertida antes deles. Por exemplo, se quiser encontrar parênteses em um número telefônico, você não poderia fazer só isto: Em vez disso, os parênteses, tanto o de abertura quanto o de fechamento, têm de ser precedidos por barras invertidas para indicar que eles devem ser interpretados realmente como parênteses: £stcs serão si»«^les»e»vte tratadas tomo u» yufo. (555)636-4652 / A<dí3}) dí3}-d{4}$/ Agora o PttP sabe <ue e*t«s sao parênteses literais- (555)636-4652 RAn A r%
  • 583.
    expressões reguläres Crie umastring que bata com cada padrão mostrado abaixo. / A[3-6]{4}/ / A( [A-Z]d){2}$/ Suponha que queiramos aprimoraroesquema de validação do RiskyJobs para números telefônicos, comoobjetivode permitirque os usuários submetam os seus números em mais algunsformatos. Escreva uma única expressão regular que corresponda a TODASas strings de texto abaixo, e que não permita um0ou 1como o primeirodígito. Oseu padrão só deve permitirdígitos, parênteses, espaços e hífens. 555-636-4652 555 636-4652 (555)-636-4652 (555) 636-4652 você está aqui ► 581
  • 584.
    exercício solução Crie umastring que.bata com cada padrão mostrado abaixo. ftcícío SOLUÇÃO A string deve domedar tom. . t repetir essa dlasse de daradteres A string deve tornt^r ^ 3 j ^ â dom... mâiúsdujâ- t um l a V £. ^ <uatrovezes. / a [3-6]{4}/ $ual<^uer string ^ue dome£e tom quatro dígitos na íai*a de 3 d ^ irá dorresponder a esta expressão, lòdds estas strings dorresponderao= *&&> t um numero”. duas ve«s.. e entao adaba-- dítóto... I l C / A([A-Z]d){2}$/ <5ual«uer string «ue domede dom uma letra maiúsdula e depois um dígito, seguido de outra letra maiúsdula, um dígito e só; "Bscr, •fttpz* Suponha que queiramos aprimorar o esquema de validação do Risky Jobs para números telefônicos, com o objetivo de permitir que os usuários submetam os seus números em mais alguns formatos. Escreva uma única expressão regular que corresponda a TODAS as strings de texto abaixo, e que não permita um 0 ou 1 como o primeiro dígito. 0 seu padrão só deve permitir dígitos, parênteses, espaços e hífens. 555-636-4652 555 636-4652 (555)-636-4652 (555) 636-4652 A string deve domedar duas . e uw ' digito, dom... % a % veaes... uw w* espaço- < iA ^ ro 'iez* s - ^ j ^ nríers / ' " i ( ? c i - u d { i } m - « j d { } ) - d { + ) / / T / T '~ r ^ a , e um ftaw .iv.4-j»«* i e entao o p X ti, * & * • — » > • v r â * acsU O ou | vez...
  • 585.
  • 586.
    a função thephp pregjnatchQ Verifique os padrões com preg^matchO Nós não vimos desenvolvendo padrões só porque é divertido. Você pode usar esses padrões com a função preg_match() do PHP. Esta função toma um padrão regex, igual àqueles que vimos construindo, e uma string de texto. Retorna false se não houver uma correspondência, e true se houver. p re g _ m a tc h ($ re g e x , $ m y _ strin g ) Coloque d sua rey* a<ui. A íunçãoy ^ espera redeber uma string o «uc * string ^ue vode esta signi-í-ida <uc a rege* deve -í-idar entre domparando -fida a<ui.. aspas simples- Eis um exemplo da função preg_match() em ação, usando uma regex que procura, em uma string de texto, por um padrão de quatro caracteres de letras maiúsculas e dígitos alternando-se: $wa*do rege*es são passadas para preg_ matdh0, elas dever« ser doiodadas entre aspas preg_m atch(1/Ad{3}-d {2}-d { 4}$/ } , t Retorna um numero inte*»ro; I daso a string bata dom o padrão e 0 daso dontrario. V Vode pode dolodar o padrão dentro da 4ndão desta Wr»a, pas em geral, e melhor armazena ío emuma variável. Podemos tirar proveito da função preg_match() para habilitar uma funcionalidade de validação mais sofisticada nos scripts PHP, colocando uma declaração if em tomo do valor de retomo. ' 5 5 5 - 0 2 - 9 9 8 3 ' ) £sta string bate doma rege*, e a íunção retomará 1. A íunçao preg__matdK0 fida alinhada dentro da dondi^ao, portanto o seu resultado determina «ual dódigo será exedutado- echo ’ Número de seguro social válido'; } else { echo ’ Esse número de seguro social não é válido!’; Se não odorrer dorrespondêndia, pveg__màtdH0 retorna -false, o «ue £32.a dondição avaliar tomo -false- Portanto, este dodigo e e*edutado. Se houver dorrespondendia, preg^matdhO retoma true, o indida para o PffP <ue a dondidao é verdadeira. Portanto, este dódigo e exedutado.
  • 587.
    expressões regulares Reescreva aparte salientada do script PHP do RiskyJobs que verificaos dados de registro abaixo para validarotextodigitado nocampo phone, usando pregjnatch() emvez de emptyQ. Use a regex que você criou anteriormente na função preg_match(). if (empty($phone)) { // $phone está em branco echo ' <p class="error">0 seu número de telefone não é válido.</p>!; $output_form = 'yes'; } você está aqui ► 585
  • 588.
    exercício solução Reescreva aparte salientada do script PHPdo RiskyJobs que verifica os 9 dados de registro abaixo para validar otexto digitado no campo phone, IIClO usando preg_match() em vez de empty(). Use a regexque você criou §0LuÇã0 anteriormente na função pregjnatchQ. if (empty($phone)) { // $phone está em branco echo '<p class=nerror">0 seu número de telefone não é válido. </p>1; $output_form = 'yes’; } fcm vez. de emptyO, nos usamos uma rej^maidh para validar Onumero de tele-fone- Hos £olo£3mos âwtes dela o operador HOT(ftporque queremos exibir um et*o sempre *ue os dados digrèados HhO baterem tom o padrão- A expressão regular ja vimos anteriormente. .«f. sw ffhwc «í».í. valido...................... o um poufio, um a vez. ^ue nao esiêmos apenas verificando se dados '<p £ lj!!= V w > « c wMWo tft UkÇ<**.é.mvál|<io</p> ';............... ^ s< JvkxUx» r .' y o ’ ; * • “ b ^f"£ *"> *p * * - S » *ue estabeiedemos para os Coloíâmos foutput domo yestsim), í^uai antes nuw>eros tele-foniios.
  • 589.
    expressões regulares T tes T O R fv e £ *30 apegas se o usuário di^rbou o nw m C V ol Verifique se os números telefônicos são válidos no script de registro do Risky Jobs. Baixe o script registration.php no site da Alta Books, era www.altabooks.com.br,junto com a folha de estilo do RiskyJobs (style.css) e as imagens (riskyjobs_titie.gife riskyjobs_ fireman.png). Em seguida, modifique o script registration.php para que ele use a função preg_match() para validar os números telefônicos em relação à expressão regular. Certifique-se de ajustar a mensagem de erro para que os usuários saibam que o número telefônico não é válido, e não apenas que está em branco. Envie o script modificado para o seu servidor web e então, abra-o em um navegador. Experimente digitar alguns números telefônicos com diversos formatos, e observe como o script captura os erros. 0 sdvtfl a^ora exibe uma »e^sa^em de erro guando o *ú»ero de 'telefone e m d.©rre-ta»eirrbe> nesttf tâso, tom pontos e»* vez. de hífens. você está aqui ► 587
  • 590.
    a função thephp preg_replace() Hmm. Se a nossa regex usa vários padrões para o número telefônico, o texto não terá vários formatos diferentes no nosso banco de dados? Isso não é bom. Acho que precisamos padronizar isso aí. Só porque você está permitindo que os dados sejam inseridos em vários formatos diferentes, não significa necessariam ente que você queira esses dados armazenados em todos esses formatos. Afortunadamente, existe outra função regex que nos permiürá pegar os números telefônicos válidos submeddos pelos usuários do Riskyjobs e fazê-los todos se conformarem a apenas um padrão consistente, em vez de quatro. A função preg_replace() vai um degrau além de preg_match(), ao fazer a comparação de padrões usando expressões regulares. Além de determinar se um dado padrão bate com uma dada string de texto, ela lhe permite especificar um padrão para ser colocado na string, no lugar do texto encontrado. Funciona de modo bastante semelhante com a função str_replace() quejá usamos, exceto pelo fato de que ela faz a comparação usando uma expressão regular, e não uma string. preg__replace($padrão, $substituição, $minha_string) * / f A string ohde estaImos Kós predisamos e^ontrar ' $uâhdo ehdontrâmos _ esses daradteres tãrêcitr indesejado, Queremos -fôzehd© a operação de mdesejados- * V *e ele seja transformado «isto. ^^^^-c-substitui*^ Eis um exemplo da função preg_replace() em ação: / $ano novo = preg replaceC^OOtO-S]/’, o nsdUio ds -fuBíS. < a nossa string de texto revisâdâ depois de teita a operado de +ica ar»nâicnac(0 fano novo. em Esta re y * diz- a p repiate para produrar uma dorrespondendia «ue seja um numero entre 2 0 0 0 1 100% 2010' t guando uma dorrespondendia t endontrada, ela t substituída por ZOlO. Estamos em 2009.') Cada vez. < ^ u e um ano de ZOOO-ZOO*} ■for endontrado na nossa string, ele será substituído por ZOiO. KQQ íÁ..
  • 591.
    expressões regulares RCÍCÍO Padronize osdados de números telefônicos digitados noformuláriodo Risky Jobs, escrevendo cada umdos seguintes números na coluna phone da tabela abaixo. Certifique-se de usar umformato que armazene o mínimode dados possível para representar cada número de telefone. (555) 935-2659 (555)672-0953 555-343-8263 555-441-9005 555.903.6386 555-612-8527-8724 Dangers You» job is there. Bo you fiaye the guts »«■S*>,,n<1 lt? Risky Jobs-Registration Register wife Sisley Jobs*and pest yooiresume-. você está aqui ► 589
  • 592.
    exercício solução Padronize osdados de números telefônicos digitados noformuláriodo Risky Jobs, escrevendo cada umdos seguintes números na coluna phone da tabela abaixo' Certifique-se de usar umformatoque armazene o mínimode dados .RC|C|0 possível para representar cada número detelefone. goLuçâo (555) 935-2659 (555)672-0953 555-343-8263 555-441-9005 555.903.6386 555-612-8527-8724 A-fo*rr*»3wnàis rápida de armaz**ar ■Wefônido e retirar iudo, exteio os dfyW
  • 593.
    expressões regulares Padronize osdados dos números detelefone Da forma como está. agora, o RiskyJobs está usando a seguinte expressão regular para validar os números telefônicos fornecidos pelos usuários no formulário de registro: Embora esses formatos sejam facilmente interpretados pelas pessoas, eles dificultam o trabalho das consultas SQL, de classificar os resultados da forma como queremos. Os parênteses muito provavelmente irão atrapalhar as nossas tentativas de agrupar os números por DDD, por exemplo, o que poderia ser importante para o RiskyJobs caso nós queiramos analisar quantos dos usuários do site são de uma determinada localização geográfica. Para tomar esses tipos de consultas possíveis, precisamos padronizar os ...para esta. números em um só formato, usando preg 1 “ - -- - J~ INSERT para colocar os dados no banco, livrarmos de todos os caracteres, exceto o simplesmente armazenamos 10 dígitos x ií outro caracter. Queremos que os nossos r desta forma, na tabela: / A ( ? [ 2 - 9 ] d { 2 } ) ? [ - s ] d { 3 } - d { 4 } $ / Isto encontrará números que recaiam em um destes quatros padrões: ###-###-#### (###) ###-#### ### ###.#### Nós queremos transformar nossos dados desta forma... ########## Isto nos deixa com quatro caracteres para localizar e substituir. Nós queremos achar e removerparênteses, espaços e hífens. E queremos encontrar esses caracteres independentemente de onde eles estejam seus dados lie dá melipves resultados em c o n su lta s Sç>L . na string, portanto, não precisamos do circunflexo (A) e nem do cifrão ($). Nós sabemos que estamos procurando por qualquer caracter de um tipo específico, logo, podemos usaruma classe de caracteres. A ordem da busca não importa. Eisa regex que podemos usar: você está aqui ► 591
  • 594.
    removendo caracteres compreg_replace() livre-se dos caracteres indesejados Agora que temos o nosso padrão para encontrar esses caracteres indesejados, podemos aplicá-lo aos números telefônicos para ajustá-los antes de os armazenarmos no banco. Mas como? E aí que a função preg_replace() realmente vem em nosso auxílio. A questão aqui é que não queremos substituir os caracteres indesejados, queremos apenas nos livrar deles. Assim, nós simplesmente enviamos uma string vazia para preg_replace() como o valor de substituição. Eis um exemplo que encontra caracteres indesejados nos números telefônicos e os substitui por strings vazias, na prática eliminando-os: KÓS ârm3Z£ttâmCS OS resultados da ttossà operaçao ioòalizá1 ! e— substituir nesta variável. Realize esta substituição na stHhg de te*fct> de fpkone. 1 $new_phone = preg_replace ('/[()-s]/', '', $phone) ; tndontre estes darafiteres.... — -e os substitua por uma string vazia... ###-###-#### ### ###-#### (###)-###-#### (###)###-#### C. preg replace( ) Tódos os telefones sao padronizados neste -formato, para ^ue todos seja» armazenados «o bando «o mesmo-formato-
  • 595.
    expressões regulares Não seinão, isso parece muito trabalho apenas para termos strings de 10dígitos no nosso banco de dados. Não poderíamos simplesmenteexigir que os usuários digitassem logo desse jeito, noformulário de registro? C ertam ente, mas Isso acabaria causando problem as depois, uma vez que as consultas com números telefônicos não funcionariam como esperado. A maioria dos usuários está acostumada a digitar números telefônicos com alguma combinação de hífens, parênteses e espaços, de modo que tentar forçar o uso de apenas dígitos nos telefones poderia não funcionar como esperado. E muito melhor tentar alcançar algum equilíbrio, dando aos usuários opções razoavelmente flexíveis para a inserção dos dados, ao mesmo tempo nos certificando de que os dados armazenados sejam o mais consistentes possível. Além disso, só é preciso uma chamada a preg_replace() para resolver o problema, o que não é grande coisa. Mas se estivéssemos falando em escrever algum tipo de função personalizada com um monte de código, seria outra história. Mas melhorar a usabilidade e a integridade dos dados com uma única linha de código não tem nenhuma dificuldade!
  • 596.
    — T fe S T O R f v e teste registration.php Ajuste os números de telefone no script de registro. Modifique o script registration.php para ajustar os números de telefone, adicionando as seguintes linhas de código ao script, logo depois da linha que agradece ao usuário por se registrar com o RiskyJobs: $pattern = ’/ [{)-s]/'; $replacement = ''; $new_phone = preg_replace($pattern, $replacement, $phone); echo 'Seu número telefônico foi registrado como 1 . $new_phone . '.</p>'; Envie o script para o seu servidor web e depois abra-o em um navegador. Preencha o formulário, sem se esquecer de colocar um número telefônico com caracteres extra, como por exemplo, (707) 827-7000. Submeta o formulário e verifique os resultados. Experimente colocar algumas outras variantes do número, como: 707- 827-7000, (707)-827-7000, 707 827 7000. Repare em como a expressão regular e preg_ replace() se livram dos caracteres extras. 3 0 hun*cro f ■ fcclc-íwiidoc I reduzido â apenas j dígitos - Voubro târaô-Uy-l
  • 597.
    expressões regulares O emailque mandei para este equilibrista acabou de voltar. Não acredito que esse formulário estúpido está deixando as pessoas digitarem endereços de email que nem funcionam! fir*‘ ”ame;F°ur Fingers Last Name:McGraw Email: four@gregs-|jstnet Phone: 555-098 K Desired Job: Knife JuggST istí faltando ponto no tn d trtto dt email! Da mesma forma que os números telefônicos, os endereços de email têm um formato específico o suficiente para que possamos validá-los, verificando mais do que simplesmente se os usuários os digitaram. Assim como na validação dos números telefônicos, primeiro nós temos de determinar as regras que os endereços de email válidos têm de seguir. Então poderemos formalizá-las como uma expressão regular, e implementá- las no nosso script PHP. Assim, vamos primeiro dar uma olhada do que exatamente se compõe um endereço email. KSs sabemos <weos cnderedos dt emãii devew tontev eskts stf dois daraíteres NomeLocal@Pref±xoDoDomín±o 7SufixoDoDomínio ^ poderá Kavev daradteres ^ jsto geraWnte al+anu^erifios, onde Ko»eLodai te» no se eo^poe dt »miMo .taradter e lWi*oP©!Wni© 3 daradteres te» no mÍm** dois darafiteres. atfa*w**to** Veja se você consegue bolar uma expressão regular flexível o suficiente para encontrar os endereços de email à direita. Escreva-a abaixo: você está aqui ► 595
  • 598.
    Conferir endereços deemail pode ser complicado Parece que deveria ser bem simples encontrar endereços de email porque, à primeira vista, não parece haver tantas restrições sobre os caracteres que você pode usar quanto há para os números telefônicos. Por exemplo, não parece ser grande dificuldade encontrar a parte NomeLocal de um endereço de email (tudo que vem antes do sinal @).Uma vez que ela é composta de caracteres alfanuméricos, deveremos poder usar o seguinte padrão: uma regex para endereços de emall / Aw + / „ ' M mais taratteres Começa dom... alW É rií*- Isso permitiria qualquer caracter alfanumérico no nome local, mas, infelizmente, ele não incluiria caracteres que também são permitidos em endereços de email. Acredite se quiser, mas endereços de email válidos podem conter qualquer um destes caracteres na parte NomeLocal, embora alguns deles não possam ser usados como o primeiro caracter: Todw «te* taraíW poder« aparecer * > a parte HomcL-otat de »„ endweço de <•»»'■ Se quisermos permitir que os usuários registrem endereços de email com esses caracteres, realmente precisamos de uma regex parecida com essa: / A[a-zA-ZO-9][a-zA-Z0-9. -& f?=#]*/ I K f 1 Os dedais daratteres , . 0 wsmÓYo pode» ser «suaisoiuer 2 podemos ter zjsvo ou u ld e « * '* » '^ "’ais delts Isso não encontrará absolutamente todo NomeLocal válido, uma vez que ainda estamos pulando alguns dos caracteres realmente obscuros, mas é bastante prático de usar e, de qualquer forma, ainda deverá encontrar os endereços de email da maioria dos usuários do Riskyjobs.
  • 599.
    expressões regulares Esse negóciodos emails é fácil. Basta usarmos omesmo padrão que usamos para o nome local para validar o nome do domínio... nada demais! Isso funcionaria para uma parte do domínio, o prefixo, mas não para o sufixo. Enquanto o prefixo do domínio pode conter praticamente qualquer combinação de alfanuméricos e alguns caracteres especiais, como o NoméLocal, as restrições sobre os sufixos dos domínios são maiores. A maioria dos endereços de email terminam em algum sufixo de domínio comum: .com, .edu, .org, .gov e assim por diante. Nós precisamos nos certificar de que os endereços de email terminem em um sufixo de domínio válido também. na? existem TWgimtas Idiotas P E se eu quiser permitir absolutamente todos os endereços de email possíveis? Você pode, e se for o ideal para o seu site, certamente deve. Mas às vezes é melhor usar formatos comumente aceitos, e não necessariamente aceitar qualquer variação possível. Você precisa decidir qual será o formato dos emails de 99.9% dos seus usuário, e precisa estar disposto a não validar o .1% restante simplesmente porque isso lhe permitirá escrever um código melhor. Avalidação è, na realidade, um equilíbrio entre o que é permitido e o que é prático aceitar.Se quiser implementar uma validação de emails mais robusta no seu site, você poderá encontrar alguns excelentes códigos PHP open source (ou seja, gratuitos) aqui: http:// code.google.com/p/php-email-address-validation/. * Mas as pessoas não vão ficar irritadas se elas tiverem um endereço de email que eu me recuse a validar? É possível, mas a maioria das pessoas não terá endereços de email malucos. A maioria dos serviços de email online tem as suas próprias restrições que impedem os usuários de criarem endereços de email loucos, embora válidos, como: "_eu sou louco”@gregs~list.net. AV<ll1d^çã°Çte<Jiienternertte e u m e<ju!lít>£iP e n tre 9 < j u e e p e t m i t í c t e e- 9 e p rá tic o ciceltar. você está aqui ► 597
  • 600.
    coincidir sufixos dedomínio Sufixos de domínios estão por toda a parte Além dos ultracomuns sufixosde domínios que vocêvêfrequentemente, como .com e .org, existem muitos, muitos outros sufixosválidos para uso em endereços de email. Outros sufixosreconhecidos como válidos pelo Sistemade Nomes de Domínios (Domain Name System, ou DNS) que você podejá tervisto incluem ,bize .info. Além desses há uma série de sufixos que correspondem aos diferentes países, como .capara o Canadá e .tj para o Tadjiquistão. Eis uma lista com apenas alguns dos sufixos de domínios existentes. Estes não são todos os que existem. jN ÍPtcl Geek Poderíamos fazer isso, e funcionaria. Mas há umjeito mais fácil. Em vez de manter registro de todos os domínios possíveis e ter de modificar nosso código caso um novo domínio seja adicionado, podemos verificar a parte do domínio de um endereço de email usando a função checkdnsrr() do PHP. Esta função se conecta ao DNS e verifica a 0 Sistema de Nomes de Domínios é um serviço de dados distribuído que fornece um diretório mundíai de domínios e os seus endereços IP. Ele torna possível o uso de nomes de domínio. Sem o DNS, teríamos de digitar 208.201.239.36 em vez de oreilly.com.
  • 601.
    Use PHP paraverificar o domínio expressões regulares O PHP fornece a função checkdnsrr() para verificarmos se um domínio é válido ou não. Esse método é ainda melhor do que usar expressões regulares para encontrar o padrão de um endereço email, porque em vez de apenas verificar se uma string de texto poderia ser um domínio válido, essa função na verdade consulta os registros do DNS e descobre se o domínio realmente está registrado. Assim, por exemplo, enquanto que uma expressão regular poderia lhe dizer que gzsdjlkdfsalkjaf.com é válido, checkdnsrr() pode dar um passo adiante e lhe dizer que, na verdade, esse domínio não está registrado, e que nós provavelmente deveríamos rejeitá-lo caso ele seja digitado no nosso formulário de registro. A sintaxe de checkdnsrr() é bem simples: eHetkdvvsrrO espera receber ufeâ s-tr'm< dotvfcendo ur* «orne de doimmio. Esse (nome c h e c k d n s r r ( ' h e a d f i r s t l a b s .c o m ') isto s©e ia» problema se o seu servidor web us^y Windows. Caso esteja usando u*»idoiwputador Se você estiver rodando o PHP em um servidor Windows, esse comando não funcionará para você. u» servidor UN|;</Lmux, eK-fcao nào seva pr©ble**a- Em vez dele, você pode usar este código: te tocando cMt ^arwâ ^ p r ^ r â m a e*U irno, «ç* voda no servider, para function win_checkdnsrr($domain,$recType=1 1 if (iempty($domain) ) { if ($recType— 1' ) $recType="MX"; exec("nslookup -type=$recType $doraain",$output); foreach($output as $line) { if (preg_match. ("/A$domain/”, return true; return false; return false; Server^.fll-M**!W<Wress< autVjori'tsti'1 ®aws'wer- ov*e»lly-toww íail e*cbawyr 2-0 oreilley-í-ow- você está aqui ► 599
  • 602.
    validação do emailem 5 passos Validapão de email: montando o quadro Agora nós sabemos como validar tanto a parte NomeLocal de um endereço de email, usando expressões regulares, quanto a parte de domínio do endereço, usando checkdnsrr(). Vejamos o passo a passo de como podemosjuntar essas duas partes para adicionar uma validação completa de endereços de email ao formulário de registro do RiskyJobs: Rc?âve *ao ba nenbum tiírao no ■ (■ m a l desta re^e*, w»a Use preg_match() para determinar se a parte NomeLocal do nosso vez. ^ue bavera endereço de email contém um padrão de caracteres válido. caracteres apos Podemos usar a seguinte regex para fazer isso: /*■ [a-zA-ZO-9] [a-zA -Z0-9 t?- #] *@ / i l í j n u i í°je'Slr í< > m“*>ísratier Desía <«, ía»>bé»>ím»«k r°* e di«o pode Conter produrar por umsímbolo arroba » > ■^ 3 1 i teres especiais. o endereòo de email fio«te»» " i > - I . . 1 . J ___ esse símbolo ântes do dommio- Se a validação do NomeLocalfalhar, ecoe uma mensagem de erro para o usuário e recarregue o formulário. Se a validação do NomeLocaltiver sucesso, envie a checkdnsrr() parte da string de texto submetida pelo usuário referente ao domínio. Se checkdnsrr () retornar 0, então o domínio não está registrado, portanto, nós ecoamos uma mensagem de erro para o usuário e recarregamos o formulário. Se checkdnsrr () retomar 1, então o domínio está registrado, e podemos ter razoável confiança de que teremos um endereço de email válido. Podemos prosseguir com a validação do restante dos campos do formulário. 6 0 0 Canítnin i fl
  • 603.
    expressões regulares Segue abaixoonovo código PHP para validar os endereços de email dos usuários, mas alguns pedaços desapareceram. Preencha os espaços em branco para completar ocódigo. if {!preg_match( ' .................................... $email)) { // $emaíl é inválido porque NomeLocal é incorreto echo 'Seu endereço de email não é válido.<br />'; $output_form = 'yes'; } else { // Retira tudo do email, exceto o .dominio $domain = preg_replace( ' ..................... ............. ,..... ) ; // Agora verifica se $domain está registrado if {.................. ) { echo 'Seu endereço de email é inválido. <br />'; $output_form = 'yes'; } 1 você está aqui > 601
  • 604.
    exercício soíução Segue abaixoonovo código PHP para validar os endereços de email dos ^ # usuários, mas alguns pedaços desapareceram. Preencha os espaços em ÍRCIClO branco para completar ocódigo. S o L u Ç ã o Esta c a nossa re^e* fava entontv-ar a parte KomcL-oda! do cndcvcço de email; terminando tom y um sinal @ - if (Ipreg match ( ' C a - z ^ i '' $email)) { // $email é inválido porque NomeLocal é incorreto echo 'Seu endereço de email não é válido.<br />'; $output_form - •yes ■; ^ Q NoBeUial e o » W . } #, 3 stnrq vazia í ^to»"« stvi*3 de substituirão- 01S0 { * // Retira tudo do email, exceto o dominio. Çdomain = preg__replace {1/^a-z^-Z^-^Xa-zA-Z^-^ , , femail u ) M j! Agora verifica se ^domain está registrado s ..... Real« a*W rt»í*> no N . valor de fen»ai( echo 'Seu endereçoSáe^email é inválido. <br />'; $output form = 'yes '; ^ estivev usando um servidor H etk ã* ^ > « W * aW «ão « esn«£i rejisbaao- íha»á-loMw. PONTOS DE BALA ■ preg__match () localiza correspondênciasparapadrõesemstrings. ■ preg_replace () modificastrings encontradas.. ■ Quantificadores (Quantifiers) lhepermitem controlarquantasvezes umcaracterou conjuntodecaracteres podeaparecer seguidamente. ■ Vocêpodeespecificar umconjuntode caracteresa serempermitidosnoseu padrão, usandouma classe de caracteres. ■ Noseu padrão, d , w e s significam dígitos, caracteresalfanuméricoseespaço embranco, respectivamente. ■ checkdnsrr () verificaavalidadede nomes dedomínio. fin?
  • 605.
    expressões regulares T b& T O R f V G Adicione validação de emails ao script de registro do Risky Jobs. Use o código da página anterior para adicionar a validação de emails ao script registration.php. Depois envie o script para o seu servidor web, e abra-o em um navegador. Tente submeter um endereço de email inválido, e perceba como o código da nova expressão regular rejeita a submissão do formulário e exibe uma mensagem de erro para explicar o que aconteceu. ^ T Excelente! Eu cumpri a minha cota de contratações para empregos arriscados. Nao preciso fazer mais nada,alémde contar todo *odinheiro queganhei Danger!Yourdreamjob1*out»ere. youSave*h«gutstogotindIt? RiskyJobs-Registration J. Your«asiaíladdressJsimalid. igsterwithRiskyJobs,and postyourresale. DesiredJob: Uma mensagem Idc Oto in-forma p*e o chdercÇo ic Cm âil do av-io não t |alido (ee tcm espaço otide rveria haver »bole @). Com a ajuda da validaçao no -formulário de registro do Risky Jobs, ew-fcrar e» fiontato tom dawfcdatos promissores «ao e mais um problema, e é possível -fazer as Coh-fcratações em -tempo re£orde- você está aqui ► 603
  • 606.
    caixa de ferramentasdo php & mysql Soa Caixa de Ferramentas do PHP S-MySQL C/til
  • 607.
    11 ViSUclllzíUlcIo seusDclclos... e]V[cl!s! Desenhando Gráficos Dinâmicos É claro que todos nós conhecemos o poder de uma boa consulta e O SConsequentes resultados satisfatórios. Mas os resultados de consultas nem sempre falam por si mesmos. As vezes é útil apresentar os dados de uma forma diferente, uma forma mais visual. O PHP possibilita o fornecimento de uma representação gráfica dos dados: gráficos pizza, gráficos em barra, diagramas de Venn, desenhos Rorschach, qualquer coisa. Vale de tudo para ajudar os usuários a compreender os dados que fluem através da sua aplicação. Mas nem todos os gráficos úteis, em aplicações PHP, se originam do seu banco de dados. Por exemplo, você sabia que é possível evitar ataques de spam de preenchimento de formulário robotizado com imagens geradas dinamicamente? este é um novo capítulo ¥ 6 0 5
  • 608.
    yíáque dos robôs (ruitarWars Reloaded: A Vinganpa das Máquinas O futurojá chegou. Os robôs foram soltos no mundo virtual e não há muito que se possa fazer para impedi-los, exceto usar alguma vigilância através de código PHP. Esses robôs são os spam bots, os quais infestam a Web procurando por formulários de input que os permitam publicar anúncios às centenas. Esses robôs são incrivelmente eficientes e não estão nem aí para o que deveria ser o uso legítimo dos formulários que atacam. O seu único objetivo é substituir o seu conteúdo pelo deles, em uma tentativa desenfreada de conseguir receitas publicitárias para os seus mestres. Infelizmente, a aplicação de pontuações do Guitar Wars acabou caindo vítima dos bots. T o clo s Çorniulárfos Webtem o tíscp de ctta^ues cie spam lx>ts Não c nada pessoal; os bots apenas querem â ates^ao dos seus usuários, para aumentar as refiíitas publieífcirias dos seus iwestres. Os bots de spam são excelentes para repetição burra, neste caso preenchendo e submetendo um formulário do Guitar Wars atrás do outro, com dados que na verdade contêm anúncios, em vez de pontuações.
  • 609.
    visualizando seus dados...e mais! Nenhum formulário de input está a salvo Felizmente para o Guitar Wars, os ataques dos bots de spam ficam invisíveis para o usuário final, graças ao recurso de moderação humana adicionado lá no Capítulo 6. No entanto, o moderador agora está completamente soterrado pelo enorme volume de posts dos bots de spam, o que lhe dificulta a tarefa de "peneirar" e aprovar as pontuações legítimas. A moderação humana é um excelente recurso, mas os humanos ficam em desvantagem ao se depararem com um adversário automatizado que nunca se cansa. GuitarWars-HighScoresAdministratfc lis!ofaliGuiiarWarshígh.scorcs.Usete pagetoremove Belowisa needed- Isto é ridículo. Não consigo moderar todos estes posts, a maioria dos quais parecem ser falsos. Eunemsequer sei o que é um frowney! Nauae «rwvr^assbatesxom wwv.ciasshates.coin Date 2008-06-23 2008-06-23 2008-06-23 jtoiroeyceBtrtlxoin 2008-06-231 -trvmírowneyceofcraLwB»2008-06-23 vw ^vw iK rcnitnU «» 20084)6-23 wwJro-WBeyeeatraLcflm 2008-06-23 wwwJieaiilHitlatw^oin K yarwAewitefiateJ<H P wwJwadiastlfito^w •yrvn»Jicadlastlabs-com 2008-06-23 2008-06*23: 2008-06-23 2008-06-23 2008-06-23 Score Aetkm .:44:56 999999999E&gass >âtPSHÊ 45:15999999999Kemovel âggQSíê 45.; :A S > t :46:<X999999999 f Appism ,:46:19 999999999 Ssm m tâ g p S ê .:47:26 999999999 >&$$$£& -.47:42999999999 SêffiSSg! i;47:55 999999999 E m ® í lMAZ999999999M&mt&m&& si 1.52:20 999999999 Regove t AjffflKÊ t‘ 52:32 999999999 í AjaawS 0 nosso destemido moderador do éjuitar V V ârs se enfioK-bra emumd di-fic.il batalha toYikri bots *^ u e Kutóa se £a«sam de postar poht**atões falsas,, < ^ u e v»a verdade sao spam. ) Está claro que a moderação humana dos posts não é o suficiente. O que nós precisamos é de uma forma de evitar que os robôs consigam submeter as pontuações - cortar o acesso logo no início, por assim dizer. Mas para isso será preciso distinguir, de alguma forma, entre um software automatizado e um ser humano com um cérebro real... um problema difícil, mas que pode ser solucionado. Escreva abaixo três perguntas que você poderia fazer para distinguir entre um ser humano real e o cérebro artificial de um robô: você está aqui ► 607
  • 610.
    Precisamos separar oshumanos das máquinas Para descobrir como detectar se há um ser humano real no outro lado da página Adicionar Pontuação do Guitar Wars, você precisa primeiramente avaliar o que exatamente o bot de spam está fazendo quando ele preenche formulário com dados falsos. Para um bot de spam, e a ddsâ mâis ta£ij do mundo bombâtrdMtr ■ uc««:r*s, c âtC mesmo milhares ____ . ^ifítar wass: apenas para humanos 0 banto de dados, do éjuitar W ars esta sendo inundado 6om pontuações mvâlidàs porque os bots estao se aproveitando do -formulário Adicionar Pon^tuaçac 0 formulário Adidionar rontuáiâo nao te* nada para distinguir entre um post de umsev* Humano real e um post teito automaticamente por um robo. 0 formulário AdiCl911at Y ^Iltuaçãí? O problemacom o formulário Adicionar Pontuação é que ele não fríecisa de UUl I1Cm/o '^aznac^a Para impedir submissões automatizadas, significando que 1 ~ qualquer programador habilidoso poderá criar um bot que preencha com anúncios e submeta o formulário repetidas vezes. É claro que esse spam nunca chega à página principal do GuitarWars, graças ao recurso de moderação, mas ele toma a moderação inútil em muitos aspectos, porque o moderador acabaperdendo tempo removendo manualmente centenas de posts falsosque contêm anúncios. campp c[ueexíja a confirmação de c[üeo usuátfe é um ser fcumaxio, antes d e petm íííl: «Jue uma ppntuaçao seja subm etida. O formulário precisa de um novo campo de verificação que precise ser informado com sucesso para que a pontuação seja submetida. E a verificação específica desse campo precisa ser algo fácil para um ser humano real, mas difícil para uma máquina. cno
  • 611.
    visualizando seus dados...e mais! RCÍCIO Seguem abaixo algumas ideias de campos para oformulário que poderiam ser usados para impedirque bots de spam submetam posts. Circuleos campos que acharque poderiam, de forma simples e eficaz, permitirque apenas seres humanos submetam posts, e não se esqueça de escrever porquê. Você é um robô? Q ®im O Não Qual era o prato favorito de Elvis? Scaneamento de retina: Digite as letras mostradas: jkdyqmc Quanto é 7 + 5? Que tipo de animal é este? Digite as letras mostradas: você está aqui ► 609
  • 612.
    exercício solução Seguemabaixoalgumas ideiasdecampos para oformulárioque poderiamser usados para impedirque.bots de spam submetam posts. Circuleos campos que acharque poderiam, deformasimplese eficaz, permitirqueapenas seres humanos submetamposts, e nãose esqueça deescrever porquê. güLuçgo /Vlutio fâdil de adivinhar - »esmo t<m Você é um robô? O O Não sudesso à t ^ O k r A w w base do dhuiomeiro, vode ainda adabaria tendo de apagar toneladas de posts falsos. Qual era o prato favorito de Elvis?? Ceria^enie difídil para os robos, mas poiendiaimenie difídil para alguns seres humanes iambém. Nem iodo mundo sabe < ^ u e Elvis adorava sanduídhes de pasta de amendoim dom banana- Seria também prediso usar um grande bando de dados doniendo as diversas pergunias e respostas. ^__} Scaneamento de retina: Olhe para a suaw * Digite as letras mostradas: Na© e ma ideia, assumindo-se *V * e as ietras a serem digitadas â£3redàm tomo uma imagem, e rào tomo iext©, »as ainda t possível de ser quebrada por bois inteligentes o sufidienie para usarem o redonhedimenio óptido de daradteres (OCR)- Quanto é 7 + 5? Que tipo de animal é este? Lembra-se d > Fang, o tèo foi abduzido por alienígenas no domeço deste livro? Bastan-te efidienie - os bots tem ✓ difiduldade em inierpreiar o donieudo de imagens. /Vias será prediso um bando de dados doniendo as imagens e as respediivas respostas £xdelenie para impedir os bois, ------ m 3s igtnidamenie k d y q m c difídil e daro de implementar. Simples e efidienie, ^ois a môioria dos bois nao e speria o sufidienie para onseguír inierpreiar «jue esta sendo pedido o resultado de uma expressão maiemátída - só temos de iorder para ^ue a maioria dos seres humanos o donsigamf ( S Digite as letras mostradas: tfêo iâo problemátido quanto a verifida^ao de reiina, mas ainda exige hardware e soÇbnâre espediais. ^ ^ Scaneamento de impressão digital: W minieressanie aprimoramento do idador dom leiras aleatórias; a< ^ ui, as leiras sâo obsduredidas dom linhas e pontos, para donfundir os bois <ue ienham OCR.
  • 613.
    visualizando seus dados,,.e mais! Podemos vencer a automapão usando a automação O teste usado para se verificar se a criatura do outro lado do formulário é uma pessoa real é conhecido como CAPTCHA, do termo inglês CompletelyAutomated Public Turing Test to Tell Computers and Humans Apart ("Teste Turing Público Completamente Automatizado para Diferenciar Computadores e Humanos"). Isso é uma forma meio prolixa de se referir a qualquer "teste", em um formulário, em que apenas seres humanos podem passar.Já foram inventados diversos CAPTCHAs interessantes, mas um dos mais populares envolve a geração de uma senha aleatória, que o usuário precisa então digitar. Para ajudar a impedir que bots com reconhecimento óptico de caracteres (OCR) consigam vencer o sistema, as letras da senha são distorcidas ou parcialmente obscurecidas com linhas e pontos aleatórios. vez. <ue Digite as letras exibidas: Urna vet o|ue as irbras da senbâ sa©gradas aleatoriamente, a senka c d iW ie a cada o •W n'utâ'rî© e exibido* Um tampo de test© normal é usado para permitir *w e o usuário digite a senba CAPTCHA- Um CAFTCHA é um programa <Jueprotege um s!te cotxtra autpm atS zadps, u sa n d p alg u m típP deteste. LmKas e foh-èos aleatórios ajudam a ob^urecer ©te*t© apcn3s 0 fara impedir ©redonheCimeni? óptido dc caracteres, mas a©mesmo tempo permitinde seres Hum anos o possam ier. Um campo CAPTCHA é igual a qualquer outro campo do formulário, exceto pelo fato de que o seu propósito é impedir que o formulário seja submetido se o teste não tiver sido completado com sucesso. Assim, ao contrário de outros campos, que geralmente enviam dados ao servidor no momento da submissão, o campo CAPTCHA é verificado e usado para controlar todo o processo de submissão. Uma vez. < u e o boi de spa«« nao t capaz, de identiíidar a Errado! senHa, a unida doisa «ue ele pode íâz«r i tentar adivinhar- ______ _ ^ Digite as letras exibidas: |gwerty? Para um ser Humano real e -fâdil identi-fidar a senha. Digite as letras exibidas: owdysq Correto! É muito importante que a senha CAPTCHA seja exibida no formulário como uma imagem, e não apenas como texto; caso contrário, seria muito mais fácil para os bots identificar as letras. você está aqui ► 611
  • 614.
    não existem perguntasidiotas: edição captcha nsb exSstem p e r g u n ta s Íd!otclS P - Aquele CAPTCHA gráfico com a imagem do cachorro é bem legal. Eu poderia usá-lo em vez deste com senha? J l - Perfeitamente.Apenas tenha em mente que você terá de manter um banco de dados com imagens e descrições do que elas são, porque uma das chaves para o sucesso de qualquer CAPTCHAé a variedade. Um bom CAPTCHAprecisa ter um repositório de conteúdo amplo o suficiente para que o formulário raramente mostre o mesmo teste duas vezes. Esse é o beneficio do CAPTCHAcom senha: uma vez que a senha é gerada a partir de letras aleatórias, é muito improvável que o mesmo teste apareça duas vezes para um mesmo usuário, mesmo com muitas tentativas repetidas. P■ Como o CAPTCHA funciona para os deficientes visuais? E se eles não conseguirem passar no teste visual? R : Os CAPTCHAs visuais obviamente não são a melhor solução para os usuários com deficiência visual. Uma solução ideal poderia induir uma alternativa sonora aos CAPTCHAs visuais. Por exemplo, existe um CAPTCHAde áudio no qual uma série de números é lida em voz alta, após o que o usuário precisa digitá-los para passar no teste. Mas ainda há o problema de bots inteligentes usarem reconhecimento de voz para fraudar o teste, que é o motivo pelo qual algumas dessas soluções usam áudio altamente distorcido, que faz a voz soar um pouco macabra. Os CAPTCHAs de áudio são tecnicamente semelhantes aos visuais, no sentido de requerem um banco de dados com cfipes de áudio e as suas respectivas respostas. Existem serviços que oferecem CAPTCHAs flexíveis, que utilizamtanto vídeo quanto áudio, como por exemplo www.captcha.net. Tais serviços são excelentes para oferecer as tecnologias mais atuais, mas em geral eles não se integram tão bem à sua aplicação web quanto um CAPTCHApersonalizado feito especificamente para ela P'-Mas há também pessoas com pouca acuidade visual, e pessoas com deficiência auditiva. E quanto a elas? R : No fim das contas, você precisará pesara conveniência de impedir os ataques dos bots contra o risco de alienar alguns usuários. De forma semelhante ao que ocorre entre vírus e softwares antivírus, os bots de spam e os CAPTCHAs provavelmente continuarão nessejogo de gato e rato, em que bots são criados para vencer um determinado CAPTCHA, o que fará surgir um CAPTCHAmais sofisticado, e assim por diante. Pegos no fogo cruzado estão os usuários que poderão acabar excluídos por causa da acessibilidade limitada de alguns CAPTCHAs. Fica a cargo de cada desenvolvedor web pesar os riscos de um ataque de bots contra a potencial perda de usuários que poderão não conseguir acessar partes do site. Se servir de consolo, tenha em mente que os bots mais sofisticados geralmente miram nos alvos mais graúdos, onde poderão obter um bom retomo em termos de receita publicitária, o que significa que você poderá não encontrar um bot realmente maléfico até que o seu site cresça ao ponto de se tomar um alvo grande o suficiente para os bots mais poderosos. OK, entoo a senha do CAPTCHA precisa ser exibida como uma imagem, com linhas e pontos aleatórios. Tudo bem, mas como isso pode ser criado com o PHP? O PHP só é capaz de v . _____ _ gerar código HTML, certo? _______ O o O PHP possui capacidades gráficas que podem gerar imagens dinamicamente, as quais você pode então exibir usando código HTML. Comaajudade umabibliotecadegráficoschamadaGD (GraphicsDraw), os nossosscriptsPHPsãocapazesdegerarimagensdinamicamenteemformatos populares, taiscomoGIF,JPEGePNG,e ouretomá-lasaumnavegadorpara seremexibidasouescrevê-lasemumarquivono servidor.EsserecursodoPHP éextremamente importante, porque não existeapossibilidadede se"desenhar" emumapáginawebusandounicamenteHTML. OPHPlhepermite"desenhar" emumaparte dapágina, realizandooperaçõesgráficasemumaimageme depoisexibindoessaimagemnapáginacomafamiliartag<ámg>.
  • 615.
    visualizando seus dados,.,e mais! (rere o texto da senha de CAPTCHA Antes de sequer podermos pensar no aspecto gráfico de um CAPTCHA com senha, precisamos descobrir como gerar a própria senha aleatória, que começa como uma sequência de caracteres de texto. A senha pode ter qualquer número de caracteres, mas algo entre seis e oito caracteres em geral é o suficiente, Podemos usar uma constante para a extensão da senha, o que nos permite modificar facilmente o número de caracteres posteriormente, se for preciso. Umâ senhâ CAPTCHA define (’CAPTCHAJJUMCHARS ', 6 ) ; ^ s c i s provaveUenie é suíitieníe ^ para impedir os b<yb sc'n * atrapalhar os Wma*cs. Então como exatamente nósvamos gerar uma string aleatória de texto com seiscaracteres? É aqui que duas funções internas do PHP entram em cena: rand() e chr(). Afunção rand() retoma um número aleatório na faixa especificadapelos seus dois argumentos, enquanto que chr() converte um código de caracterASCIInumérico em um caracter propriamente dito. O ASCII (American Standard Code for Information Interchange ou Código PadrãoAmericano para Intercâmbio de Informações) é uma codificação de caracteres padrão, que representa os caracteres através de números. Nós sóprecisamos dos códigosASCII na faixa de 97-122, que representam asletras minúsculas a-z. Se gerarmos um código nessafaixa seisvezes, iremos obter uma senha de seis caracteres aleatórios, todos os quais sendo letras minúsculas. // Gera a senha’aleatória $pass_phrase = for ($i = 0; $i < CAPTCHAJxíUMCHARS; $i++) { $pass__phrase .= chr (rand (97, 122)) 1 r ^ — - Alais adiajvfce, este dódijo sera Coletado em um sdript reuiilizivel próprio, fiâp&ha php. $pass_phrase Mmloop para cada taraticr da sertHa. Asenha e tonslrwda um taratier aleâtort© de tada vez. rand( ) Esta função interna retorna um número inteiro aleatório ou dentro de uma faixa especificada ou entre 0 e a constante interna RAND_MAX (dependente do servidor).Para obter um número aleatório dentro de uma determinada faixa, basta enviar os limites inferior e superior da faixa como argumentos para rand(). chr ( ) Esta função interna converte um número no seu caracterASCII equivalente. Como exemplo, o número 97 é o código ASCII para a letra 'a' minúscula. Assim, chamar chr(97) retorna o caracter 'a'. A íunç&>tqndOvetwiaum númetp inteira dentre de umadeterminadafaixa. você está aqui ► 613
  • 616.
    desenhando um captcha Visualizandoa imagem CAPTCHA Pata se deseniaí umaImagem dinâmicaem P H F , é ptcGlSO usar Çunçpes da Criada a senha aleatória, nós podemos passar para a tarefa de gerar uma imagem consistindo do texto da senhajuntamente com linhas e pontos aleatórios, para ajudar a obscurecer o texto. Mas por onde começar? A primeira coisa a fazer é decidir qual será o tamanho da imagem CAPTCHA. Sabendo que essa imagem será exibida em ura formulário, ao lado de um campo de input, faz sentido mantê-la relativamente pequena. Vamos tentar 100x25 e vamos colocar esses valores ein , 1 constantes, para que o tamanho da imagem seja definido em apenas um biblioteca<3D lugar e, portanto, seja fácil de modificar depois, se necessário. 0 -fcam anH o da Wa$em CAPTCHA -fr^a define ( •CAPTCHAJíIDTH 100) ; armax^ado em to»starrUs, para < » tseja define ( 'CAPTCHft_HEIGHT ' , 25) ; ^ ^ a<rcis, a io r ywtiso Para se desenhar a imagem CAPTCHA, é preciso chamar algumas funções da biblioteca GD, todas as quais operam sobre uma imagem carregada na memória. Em outras palavras, você cria uma imagem na memória e então desenha em cima dela; depois, quando tiver terminado, você a envia para o navegador para ser exibida. // Cria a imagem // Define um fundo branco com texto preto . e gráficos cinza $bg_color■= Ímagecolorallocate($img, 255, 255, 255); // branco' $text_color = ímagecolorallocate($img, 0, 0, 0); $graphic_color = Ímagecolorallocate($img, 64, 64, 64); // preto // cinza escuro iodtop) Cria dores para serem usadas por outras TUhÇoes // Preenche o fundo i // Faz output da imagem como PNG, usando um cabeçalho heàçN image SI m M S m s iá s'íihülílíJÁ ||íííífUlí/íí CA A
  • 617.
    visualizando seus dados...e mais! Servidor web As imajensvecém-driadas domeçam domum-hmdopreto vasão. PrediSâmos de um -Çundo Wando onde desenhar os CAPTCHA- FVuneiramente, desenhe algumas linhas aleatórias. Adidione alguns pontos aleatórios pava uma *textura” espedial Desenhe o texto dom uma Cor mais -foV-te, írn dima das linhas e dos pontos. Uma vez. <ue o nave^sdor redebe a ima^e», ele pode exibi-b usando uma ta^ HTML- ^i**3> normal- ^ vt - Finalmente, retorne â imâ^em, na íor»a de PN4 3o navegador Navegador web do cliente você está aqui ► 615
  • 618.
    funções gráficas GD Pordentro das fuwpões gráficas GP A mágica por trás da criação de imagens CAPTCHA é possibilitada pela biblioteca de gráficos GD, que, como vocêjá aprendeu, oferece funções para se desenhar gráficos dinamicamente usando-se código PHP. Vamos examinar algumas dessas funções com mais detalhes e ver como elas se relacionam à geração da imagem CAPTCHA.^ imagecreatetruecolor( ) Esta função cria uma imagem em branco na memória, pronta para ser editada por outras funções GD. Os dois argumentos de im agecreatetruecolor () são a largura e a altura da imagem. A imagem no início é apenas um fundo preto, de modo que geralmente você vai querer preenchê-la com uma cor de fundo, por exemplo, branco, antes de desenhar qualquer coisa. Isso pode ser feito chamando-se a função imagef ille d re c ta n g le (). O valor de retorno de im agecreatetruecolor () é um identificador de imagem, o qual a maioria das funções GD requerem como primeiro argumento para a identificação da imagem que está sendo desenhada. «magens sao driadas inidialmente dom -funcíos pretos. largura altura A largura da nova imagem, em pixels. A áliura da imagem. f $img = imagecreatetruecolor (CAPTCHAJWIDTH, CAPTCHA_HEIGHT) ; ^ dodigo dr»a uma )ma$em tom tamanho A -função retorna um » 100x25, de-Finido r>as nossas donstantes. iden-titodor para a ma$cm, o <ual e referido pelas^outras ^ íundõe* para «ue vode possa usa- las para desenhar a)^0na i^ e - imagecolorallocate{ ) l/erde dlaro- (o, m , O). Use esta função para alocar uma cor a ser usada em Vermelho^ (1$%, 0 , O), outras funções de desenho. O primeiro argumento é o identificador da imagem, seguido de três argumentos representando os três componentes numéricos do código RGB (do inglês Red-Green- Blue, ou ’Vermelho-Verde-Azul”). Cada um desses valores pode ir de 0 a 255. O valor de retomo é um identificador da cor, o qual pode ser usado para identificá-lo em outras funções de desenho, frequentemente como o último argumento. A**l: (0, O, V&>- * i , . , $text color = imagecolorallocate($img 0 valor de retomo é » A ideniiíidador da dor, o ^ualy 0 sdenti&dador y voC e pode usar cm outras 'kn^oes de desenho para deierwiihar a dor a ser usada, tomo por exemplo, a dor do W o CAPTCHA- da imagemna e^ u al a dor ira ser usada- Oi domponentes vermelho, vevde e aaul da dor, neste daso preta-
  • 619.
    visualizando seus dados...e mais! imagesetpixel ( ) q, 0 Lstafunção desenha um único pixel em uma coordenada especificada, dentro da imagem. As coordenadas começam em 0,0 para o canto esquerdo superior da imagem, e vão aumentando até chegar ao canto direito inferior. Como na maioria das funções GD, o pixel é desenhado usando-se a cor que foi passada como o último argumento para a função. £—>0 sistema de toordenadas vara a w>aior‘»adas j thamadas a íunções X#y | 6jf) iorr.Çtâ nO tânto j esquerdo swperior da j imagem, e va*aumentando j nas direções para a direita e pa^a ba‘ «*o- largura, altura imagesetpixel ($img, rand() % CAPTCHA_WIDTH, rand() % CAPTCHAJHEIGHT, $graphic_color) ; A imagem fidenti-Pitador) onde o pixel está sendo desenhado. xvVi , . i L - ^ to c íidenti-fitador) A toordenada yH d« ?»*«> >relativa ao ^ ?ixí( danto esquerdo superior da imagem, *^ue neste tas©ataba sendo uma localí&a^a« aleatória dentro da »magem CAPTCHA- imageline ( ) Chame esta função para desenhar uma linha entre duas coordenadas (xl,yl e x2,y2). As coordenadas são especificadas relativamente ao canto esquerdo superior da imagem, e a linha é desenhada na cor que foi r passada como o último argumento para a função. 2 As Coordenadas x / do inítio da linha, neste taso no tanto esquerdo da imagem CAPTCHA- image1ine{$irag, 0, rand( ) % CAPTCHAJHEIGHT, CAPTCHA_WIDTH, rand() % CAPTCHAJHEIGHT, $graphic_color); 0 ponto íinal XY dâ linha, <ue neste taso, lotaliza- se na borda direita da imâgem CAPTCHA- imagerectangle < ) Desenha um retângulo começando em um ponto (xl,yl) e terminando em outro (x2,y2), com uma cor especificada. Os dois pontos e a cor são fornecidos como argumentos, do segundo até o sexto, para a função, vindo logo após o *2>y2 argumento com o identificador da imagem. A -(-unção x y ^ imaaerettanftleO J I I : =ríí wsa e*atamente os mesmos argumentos «ue i»*age£illedreitangleí)• *2>y imagefilledrectangle( ) Semelhante a im agerectangle (), esta função desenha um retângulo cujo interior é preenchido com a cor especificada. imagefilledrectangle($img, 0, 0, CAPTCHA_WTDTH, CAPTCHA_HEIGHT, $bg_color); As toordenâdâs XY dos pontos initiai e -finai - a«ui, a imagem CAPTCHA inteira é preenthida. você está aqui ► 617
  • 620.
    use funções gráficas:parte dois Continuando as funpões gráficas <rP imageellipse( ) Usada para se desenhar círculos e elipses, esta função aceita um ponto central, uma largura e uma altura. Um círculo perfeito é apenas uma elipse com largura e altura iguais. A cor da elipse ou círculo é passada como o último argumento para a função. largura tlipSCS *30 usâdâs n3 Ím3gem CAPTCMi»* w âmdâ assim cias sa© bastante wte'«!! imagefilledellipse( ) Precisa de uma elipse preenchida? Basta chamar im ag efilled ellip se (), que funciona da mesma forma que im ageellipse () exceto pelo fato de que a cor especificada é usada para se preencher a elipse, em vez de contomã-la. ^ ^ imagefilledellipse($img, ^ 0 ^ 0 ^ 320, 240, $color) ; Tant© imageellipseO quanto imagefilledellipseO aceita» os mesmos argumentos. imagepng( ) A largura c a altura da elipse —defina estes tem o mesmo número para desenhar um círculo perfeito- J ACoordenada XV do Centro da elipse- Quando tiver terminado de desenhar em uma imagem, você pode enviá-la diretamente ao navegador do cliente, ou então, para um arquivo no servidor chamando esta função. De umjeito ou de outro, o resultado final é uma imagem que pode ser usada com a tag HTML <img> para exibição em uma página web. Se preferir gerar uma imagem PNG diretamente na memória (ou seja, sem um arquivo), então você precisará chamar também a função header() para que a imagem seja entregue ao navegador através de um cabeçalho. . imagepng ($img) ; n -run^a© retorna true * ou false dependendo de j se a imanei» foi criada M Com suCesso ou não. A imagem pode ser enviada diretamente para o navegador, ©u entao para um arquivo no servidor. myimage.png 0 identificador de imagem < ^ yc voCe vem usando nas ^ outras funções de desenho- Vote pode passar um nome de arquivo Como um jegundo argumento opcionâl - sem ele, a fundão gera uma imagem na memória < ^ u e pode ser enviada de volta ao navegador, em ur* cabeçalho.
  • 621.
    visualizando seus dados,.,e mais! as suas imagenS « ^ n 3ndo elas nao sao mais neiesssHas é u»a Wa ideia» pav-a impede o desperdid»o de redwrsos do servidor- imagedestròy( ) O trabalho com imagens usando-se a biblioteca GD consome recursos do sistema, e esta função se encarrega de liberá- los depois que você tiver terminado de trabalhar com a imagem. Basta chamá-la depois de fazer o output com imagepngQ. Semelhante a imagepngO, esta fuh£â© retoma true se a operaçao -tiver sudesso, e false, das© dohtvirio. L ib e re s e m p re as im a g e n s da memérïa, depçïs de usa- las, com îmagedesfrpyO imagedestròy ($img) A Ten-te sempre esdrever uma v dhamada a esta fu*çao para dada imagem ^ue vode driar, para <ue todas as imagens sejam destruídas depois de serem wsadas. 0 identifidador da imagem ^ue vode deseja destruir. imagestring ( ) Esta função desenha uma string de texto usando a fonte interna do PHP, na cor especificada. Além do identificador da imagem, você passa à função o tamanho da fonte (na forma de um número de 1a 5)Junto com as coordenadas para o canto esquerdo superior da string, a própria string, e finalmente, a cor. 0 tamanho da fonte a ser usado* na faixa de J a *5 - 0 número «a faixa de I a 5 define o tamanho da fonte usada para se desenhar a string de texto, dom 5 sendo o maior tamanho. x,y*.— -----— — ..... ;Exemplo de texto j f fonte interna e adequada ^ara o desenho de texto basido, mâs e limitada em termos de tamanho- imagestring($img, 3, 75, 75, 'Exemplo de texto', $color); A doordenada XY do danto esquerdo superior da string- 0 texto desenhado Com imagestrmgupO t girado em 10 grâus no sentido anti-horário, para apareder na vertida!- A Esta e a string de texto a ser desenhada- V A dor do texto- im ag estrin g u p () Semelhante a im agestring (), esta função desenha uma string de texto usando a fonte interna, mas o desenha verticalmente, como se ele fosse girado 90 graus no sentido anti-horário. A função é chamada com os mesmos argumentos que im agestring (). você está aqui ► 619
  • 622.
    a função imagettftxtO Pesenhandotexto cow uma fonte A função imagêstrin g () é fácil de usar para desenhos, mas é um tanto limitada em termos do controle que você tem sobre a aparência do texto. Para conseguir uma aparência específica, você precisa usar a sua própria fonte True Type. A imagem com a senha GAPTCHA é um bom exemplo dessa necessidade, uma vez que os caracteres precisam ser desenhados em tamanho razoavelmente grande, e de preferência em negrito. Para conseguir esse look personalizado, você precisa da syuda de mais uma função.GD, que desenha o texto usando uma fonte True Type que você fornece no servidor. pava se desenha** um texto al-UmCttie personalizado, c prediso usav uma fonte True T(pe e a função imagettftextO. i x,y #Exemplo de te x to imagettftext( ) Para desenhar um texto realmente personalizado, coloque uma fonte True Type no seu servidorweb e depois chame esta função. Você não apenas pode usar qualquer fonte que quiser; como também obtém mais flexibilidade quanto ao tamanho da fonte, e mesmo quanto ao ângulo no qual o texto é desenhado. Diferentemente de imagestring (), as coordenadas passadas a esta função especificam o "ponto-base" do primeiro caracter do texto, que é aproximadamente o canto esquerdo inferior do primeiro caracter. Estafunção requer que você coloque um arquivo contendo uma fonte True Type no seu servidor, e depois especifique esse arquivo como o último argumento. Os arquivos de fontes True Type geralmente têm a extensão .ttf. 0 angulo da fonte, espedifidado 0 tawanbo da fonte, « * * » 5raws no sentido antí- geraUente espedifidado horav-io (õ c o texto normal) em wpontosw- ^ imagettftext ($img, 18, 0, 5, CAPTCHA_HEIGHT - 5,1 $text_color, ’ Courier New Bold, ttf’, $pass_phrase) ; 0 ye ts& se*d0 deschKado. f ' Difev-chtcmch-b: dc '»»agestiringO, as doordenadas usadas para se desenhar texto dom imagettftextO apontam para o danto esquerdo inferior do texto. As eoovdenâdas XV do danto es«uevdo infCrioT do texto- í^ o ta G e e k Se quiser tentar criar a sua própria fonte TrueType, para personalizar ainda mais o seu CAPTCHA, dê uma olhada em www. fontstruct.com. Essa é uma comunidade online de criadores de fontes, incluindo uma ferramenta web para que você possa criar fontes personalizadas. Vode pvedisa dolodar a fonte True Type no scu servidor **jeb, para <ue a biblioteda de grafidos possa ^ endontrà~!a- CourierNewBold.ttf Use a îunçâo îmagettfextô para d e s e n ta r urn t & x t v altamente perspnaJizadp, com a sua préprla fonte True Typ< >e.
  • 623.
    A -^ C lflÉ M Ü F — ------------------------------------- imagedoloralloeaieífi^g, J2.8, /ZS, 12.0); Ligue cada bloco de código PHP à imagem gráfica gerada por ele. Assuma que a imagem ($img) e as cores ($black_color, -$w hite_color e $gray_color) já tenham sido criadas. . „ , ■ , ’wageeoiovaiSodâteffs*^ '"'âgcdolovalloíaícífiw^ O, O, O); U & } 2&?>, visualizando seus dados... e mais! image.filledrectangle{$img, .10, 10, 90, 90, $gray_color) ; imagefilledellipse ($img, 50, 5 . 0 , . 60, 60, $white_color) ; imagefílledrectangle ($img, ' 4 0 , 40, 60, 60, $black_color) ; imageline($img,'15, 15, 50, 50,'$black_color) ; imageline. ( $img, 15, • 85,50, 5 . 0 ,$black_color); imageline ($img, 50, 50, 85, 50, $black_color) ; imagefilledellipse($img, 15, 15, 20, 20, $gray_color) ; imagefilledellipse($img, 15, 85, 20, 20, $gray_color); imagefilledéllipse($img, 50, 50, 20, 20, $gray_color); imagefilledellipse- ($img, 85, 50, 20, 20, $gray_color) ; imagefillédrectangle($img, 10, 10, 90, 60, $gray_color); iinagesetpixel ($img, 30, 25, $black_color)-; imagesetpixel ($img,; 70, 25, $black_color); imageline($img, 35, 45, 65, 45, $black_color); imagefÍlledrectangle ($img, 45, 5 . 0 , 55, 90, $gray_color) ; imageellipse($img, 45, 45, 70, 70, $black_color); imagefilledellipse{$img, 75, 75, 30, 30, $gray_color); imagesetpixel ( $img, - 1 0 , '10, $black_color) imagesetpixel( $img, 80, 15, $black_color) imagesetpixel( $img, 20, 15, $black__color) imagesetpixel($img, 90, 60, $black_color) imagesetpixel($img, 20, 80, $black_color) imagesetpixel($img, 45, 90, $black_color) imagefÍlledrectangle( $img, 25, 35, 75, 90, $black_color) imageline($img, 10, 50, 50, 10, $black_color); imageline{$img, 50, 10, 90, 50, $black_color); imagefilledrectangle($img, 45, 65, 55, 90, $white_color) imageline($img, 0, 90, 100, 90, $black_color); você está aqui ► 621
  • 624.
    quem desenha oque solução Ligue cada bloco de código PHP à imagem gráfica gerada por ele. Assuma que a imagem ($img) e as cores ($black_color, $white_ color e $gray_color) já tenham sido criadas. imagefilledrectangle($img, 10, 10, 90, 90, $gray_color); imagefilledellipse($img, 50, 50, 60, 60, $white_color); , imagefilledrectangle($img, 40, 40, . 6 0 , 60, $black_color) imageline($img, 15, 15, 50, 50, $black_color); imageline{$img, 15, 85, 50, 50, $black_color); imageline($img, 50, 50, 85, 50, $black_color); imagefilledellipse ($img, 15, 15, 20, 20 . ,$gray_color) ; imagefilledellipse($img, 15, 85, 20, 20, $gray_color);^ imagefilledellipse ($img, 50, 50, 20, 20, $gray_color.) ; imagefilledellipse($img, 85, 50, 20, 20, $gray color); imagefilledrectangle($img, 10, 10, 90, 60, $gray_color); imagesetpixel($img, 30, 25, $black_color); imagesetpixel($img, 70, 25, $black_color); imageline($img, 35, 45, 65, 45, $black_color); imagefilledrectangle($img, 45, 50, 55, 90, $gray color); imageellipse{$img, 45, 45, 70, 70, $black_color); imagefilledellipse ($img, 75, 75, 30, 30, $gray__color) ; imagesetpixel($img, 10, 10, $black_color); imagesetpixel($img, 80, 15, $black_color); imagesetpixel($img, 20, 15, $black_color); imagesetpixel($img, 90, 60, $black_color); imagesetpixel($img, 20, 80, $black_color); imagesetpixel($img, 45, 90, $black color); imagefilledrectangle($img, 25, 35, 75, 90, $black_color) imageline($img, 10, 50, 50, 10, $black_color); imageline($img, 50, 10, 90, 50, $black_color); imagefilledrectangle( $img, 45, 65, 55, 90, $white_color); imageline($img, 0, 90, 100, 90, $black_color);
  • 625.
    visualizando seus dados...e mais! dompletamente ât{èr>0m0 - vode pode abri-lo no seu râvcgador c ver a imagem <ue ele gera. (rereuma imagem CAPTCHA aleatória Agora, nósjuntamos todo o código CAPTCHAem um script captcha.php, o qual se encarrega de gerar uma senha aleatória e depois retomar uma imagem PNG para o navegador. <?php session start(); Crie Constantes para armazenar o numero de daradteres no CAPTCHA e defina a altura e largura da imagem. // Define algumas constantes importantes define('CAPTCHA_NUMCHARS' , 6); // número de caracteres na senha define(’CAPTCHA_WIDTH’, 100); // largura da imagem define{’CAPTCHA_HEIGHT1, 25); //altura da imagem // Gera a senha aleatória $pass_phrase = for ($i = 0; $i< CAPTCHA_NUMCHARS; $i++) { $pass_phrase .= chr(rand(97, 122)); Embora vode possa armazenar a senha dríptografada no bando de dados, é mais simples dolodi-la apenas em uma variável de sessão —nós predisamos armô2£há~la em algum lugar para ^ue o sdript Adidionar Pontuação possa te r adesso a ela- // Armazena a senha criptografada em uma variável de sessão $_SESSI0N['pass_phrase' ] = shal($pass_phrase); // Cria a imagem $img = imagecreatetruecolor (CAPTCHA__WIDTH, CAPTCHA_HEIGHT); // Define um fundo branco com texto preto e gráficos cinza $bg_color= imagecolorallocate{$img, 255, 255, 255); //branco $text_color= imagecolorallocate($img, 0, 0, 0) ; //preto $graphic_color = imagecolorallocate.($img, 64, 64, 64); // cinza escuro // Preenche o fundo imagefilledrectangle($img, 0, 0, CAPTCHAJWIDTH, CAPTCHA_HE1GHT, $bg_color); // Desenha algumas linhas aleatórias for ($i = 0; $i < 5; $i++) { imageline ($img, 0, rand() % CAPTCHA__HEIGHT, CAPTCHA_WIDTH, rand() % CAPTCHA__HEIGHT, $graphic_color); } // Insere alguns pontos aleatórios for ($i — 0; $i<50; $i++) { imagesetpixel($img, rand() % CAPTCHAJrtIDTH, randO % CAPTCHA_HEIGHT, $graphic_ color); // Desenha a string da senha imagettftext($img, 18, 0, 5, CAPTCHA_HEIGHT - 5, $text_color, $pass_phrase); // Faz output da imagem como PNG, usando um cabeçalho header("Content-type:image/png"); imagepng ($img) //Apaga a imagem imagedestroy($img) ?> 4: éjere uma imagem PNéf dontendo tudo o *^ue foi desenhado A imagem PKéj é enviada ao Courier New Bold.ttf" , ^Algumas versSes da btblioteda 6jZ> Querem *uc useui-»,íarftinHo relaiivo até o arquivo da *oníe, temo "./Courier rmàli^ando, apague a imagem da memória feia ainda e enviada ao navegador, através do dâbedalho). navegador através Ntw Boid-ttf;J . de um dabedalho captcha.php você está aqui ► 623
  • 626.
    teste captcha.php ^ ip p K P TEJST O R fV e ------------------ Crie o script C A P T C H A e teste-o. Crie um arquivo de texto chamado captcha.php, e digite nele o código para o script CAPTCHA mostrado na página anterior (ou baixe o script no site da Alta Books em www.altabooks.com.br). Envie o script para o seu servidor web, e depois abra-o em um navegador. Você verá imediatamente a imagem CAPTCHA com a senha aleatória no navegador. Para gerar uma nova senha, recarregue o navegador. Cada imagem CAPTCHA gerada Consiste de seis caracteres aleatórios, Com algumas jinhas e pontos adicionados para criar ruído de fundow . Recarregar o script CAPTCHA resulta «a gerado de uma nova imagem, Contendo uma nova senha aleatória-
  • 627.
    visualizando seus dados...e mais! Esses robos estão me deixando louco! Preciso de ajuda para pará-los agora! A sanidade retorna ao G-uitar Wars Agora que nósjá trouxemos à tona o seu artista PHP interior, com algumas funções GD e uma imagem CAPTCHA, é hora de usarmos essa imagem para salvar o moderador do Guitar Wars do ataque dos bots. Na verdade, será preciso seguir alguns passos para resolver o problema. Aboa notícia e que já realizamos dois deles: gerar a senha aleatória e desenhar a imagem CAPTCHA. Vamos eliminar os passos restantes para tornar o Guitar Wars oficialmente livre de bots! 0 »oderâdor do Quitar W ars está -tão estressado i^uejá está dow>e$3ndo a tentar bater em robos imaginários ~ ele pretisa de uma solução jaü Feito! Q Gora r uma senha aleatória © Desenho pronto^ Dese nha r uma im agem CAPTCHA.usando a sonha 0 Exibir a imagem CAPTCHA no formulário Adicionar Pontuação do Guitar Wars e pedir ao usuário que digite a senha. 0 Verificar a senha em relação ao input do usuário. Complete o Passo 3do CAPTCHAdo GuitarWars, escrevendo ocódigo HTML para umnovo campo de input de texto chamado Verificação, oqual pedirá # ao usuário para digitara senha do CAPTCHA. Certifique-se de dara esse RCIClO campo umrótulo, e ponha uma tag <img>depois dele para exibira imagem CAPTCHAgerada peloscript captcha.php.
  • 628.
    exercício soiução Complete oPasso 3 do CAPTCHAdo Guitar Wars, escrevendo o código HTML para um novo campo de input de texto chamado Verificação, o qual »|C|0 pedirá ao usuário para digitar a senha do CAPTCHA. Certifique-se de dar O M g a esse campo um rótulo, e ponha uma tag <img> depois dele para exibir a d O L u Ç 3 0 imagem CAPTCHA gerada pelo script captcha.php. Uma tag <labei> t usada para se rotular o novo tampo texto Verificado- £ste de te*to e o»de o wuário ira digitar a senha revelada imagem CAPTCHA- <label f<^^M yçrifyM >yeriftatgoi- </label> y . !^3»e^l'yerifywyalue^'Enter. the.pa^-phrase.” /> ^••^g ?rc^w captchaphpwalt^Veri-Pication .pâss—phrase” /> A >,fofttewda image» e o nome do script PHP <^ue gera dinamicamente à imagem CAPTCHA- Isso fu*Cio*a forque o script captchaphp retorna uma imagem diretamente para o navegador, através de imagepngO e um cabeçalho. f wagem CAPTCHA e e^ibida no formulário, ao lado de um campo de inpvt de te*k>- aKas-sâP! Guitar Wars -AddYourHighácore fW »! Si rfis w. f**« f*-» - ^ - Exibir a imagom CAPTC H A 4t»fermulário Adicionar
  • 629.
    visualizando seus dados...e mais! Adicione CAPTCH Aao script Adicionar Pontuação C°n:T ° nOVOCamP° de * Xto porém, é a nova declaração ifno scodc/wi™ * °-o modlflcaçao mais importante, verifica se a senha d i ^ D e ! ^ t ^ Pontu^ o (Passo 4), que g1 pelo usuário bate com a de CAPTCHA visuaiízanao seus dadt <?php sessionjstart ( ); ?> <html> <head> <title>Guitar Wars - Adicione o seu Recorde</title> clink rel="stylesheet" type=r ’ tex.t/css" href=”style.css" /> </head> <body> <h2>Guitar Wars - Adicione o seu Recorde</h2> <?php require_once{’appvars.php'); require_once(’connectvars-php'); if (isset($_POST[1submit'])) { // Conecta-se ao banco de dados $dbc =mysqli_connect (DB_HOST, DB__USER, DB_PASSWORD, DBJNíAME) ~ Q - Vertfrear 'f«teçã©-ao -input do- -usuário.—— ■ Tudo frontal // Pega os dados em POST Çname = mysqlí_real_escape_string($dbc, trim($_POST[1name'])); $5core = mysqli_real_escape_stri.ng ($dbcftrim ($__POST[ 'score'1)); $screenshot = mysqli_real_escape_string($dbc, trim($_FILES['screenshot’][1name’])); $screenshot_type = $_FILES [’screenshot’]['type1]; 6 ^ 3 senha $s c r e e n s h o t _ s i z e - $_FILES t >s c r e e n s h o t ■] [ ' s i z e ' 1; í l«U *J*& S í/ V e r i f i c a a senha CAPTCfiA ~ ~ vãviâvct ® ^ { $user_passjphrase = shal($_POST['verify']); vara ^ s co u suivto if ( $ SESSION ['pass phrase'] == $user pass phrase) { / verK < . . •••“ 3 else { -- - " echo ’ <p class="error">Por favor, digite o código de verificação exatamente como lostrado </p>'; } ?> <hr /> <form enctype="multipart/form-data" method="post'' action="<?php echo $_SERVER [ 'PHP_ SELF' ]; ?>"> <input type="hidden'' name="MAX_FILE_SIZE" value="<?php echo GW_MAXFILESIZE; ?>" /> <label for=, 'name'I >Nome:</label> <input type="text" id="namenname="name" value="<?php if (! empty ($name) ) echo $name; ?>" /><br /> <label for="score">Pontuapao:</label> <input type="text" id="score" name="score" value="<?php if t! empty ($score)) echo $score; ?>" /><br /> <label for="screenshot">Captura de tela: </label> <input type="file” id=''screenshot" name="screenshot" /><br />■ <label for=’ ’ verify">Verificagao:</label> <input tvpe*=”t e y t - . ” ir j = , * v f > r . - ifv" name="verify" value="Enter the pass-phrase." /> <imCT/€rc="captcha.php^>lt=, f Verification pass-phrasQ.” /> a <hr /> ^ ______________________ £ a<w © s £ * r i p tCrw IUfin <input type="submit" value="Add" name=”submit" /> siviptA d i ô i o n â t " «Swltâ nâ i»*3yw« CA>* sçr e*fotda nâ pâgjnâ- </body> </html> M i m mm addscore.php
  • 630.
    teste drive addscore.phpcom a funcionaiidade captcha T& s t O R tv e Modifique o script Adicionar Pontuação para implementar o suporte a CAPTCHA. Modifique o script addscore .php de modo que ele passe a ter um campo Verificação, bem como a usar o script captcha.php para exibir uma imagem CAPTCHA. Adicione também o código para verificar se o usuário digitou a senha correta antes de adicionar a pontuação. Envie ambos os scripts ao seu servidorweb, e depois, abra addscore .php em um navegador. Tente adicionar uma nova pontuação sem digitar a senha CAPTCHA. Depois tente novamente, agora digitando a senha mostrada na imagem CAPTCHA. 0 «osso moderador humano ■ Çinataen-be-be» ?*** graça* W^a «»ha CAPTCHA nuc se ■Kodiíida £o*sbnW n-fce diiiCui, aos bcts a tav-e-Pa de -í-azer spam no -rormulario do éjuitár W fôrs.
  • 631.
    visualizando seus dados...e mais! nÜ9 existem ■perguntas idiotas [ * Posso usar as funções GD para criar imagens em outros formatos além de PNG? Sim. As funções imagegif () eimagejpegO funcionam de modo bastante semelhante a imagepng ( ) , mas criam imagens GIF e JPEG, respectivamente. y. 1 • As funções de criação de imagens podem criar imagens com transparência? Sim! Existe uma função chamada imagecolortransparent( ) que define uma cor para ser a cor transparente dentro de uma imagem. Essa precisa ser uma cor que você já tenha criado com a função imagecolorallocateQ. Após defini-la como transparente, qualquer coisa desenhada nessa cor será considerada como transparente. Para gerar a imagem com transparência, chame imagegif() ou imagepng (); você nãopodeusar imagejpegO porque as imagens JPEG não têm suporte ao recurso de transparência. T * • Quando usamos im agepng () para enviar uma imagem PNG diretamente ao navegador do cliente, onde o arquivo .png da imagem é armazenado, e qual é o seu nome? Não há nenhum arquivo .png para a imagem, pelo simples motivo que ela não é armazenada em um arquivo. Em vez disso, a função imagepng() gera uma imagem PNG binária na memória, no servidor, e então a envia diretamente ao navegador através de um cabeçalho. Uma vez que os dados da imagem são criados e enviados diretamente para o navegador, não é preciso armazená-la em um arquivo. * É por isso que eu consigo colocar o nome do script CAPTCHA diretamente no atributo src de uma tag <img>? Correto. Referenciar um script PHP no atributo src de uma tag <img>, como fizemos no script captcha.php para o Guitar Wars, resulta na imagem ser entregue diretamente pelo script. Isso é diferente do modo normal como a tag <img> funciona, onde o nome de um arquivo gráfico é especificado no atributo src. Uma vez que o script está enviando a imagem diretamente para o navegador através de um cabeçalho (por meio da função imagepng ()), não se usa um arquivo. E o navegador sabe que deve conectar a imagem do cabeçalho à tag <img> porque o script está especificado no atributo src. ■ Todoformuláriowebcorreoriscodeser atacado porbotsdespam, mastodobotde spam está a mercê de ser combatido por programadores PHPinteligentes, que usam técnicas comoCAPTCHAparaderrotá-los. ■ GDé uma bibliotecadegráficos padrãodo PHP, que lhepermitecriardinamicamente imagensedesenhartodotipodegráficosou textosnelas. ■ AfunçãOGDcreatetruecolorimage ( ) éusadaparasecriarumaimagemembranco. ■ Paraenviaruma imagemPNGaonavegador ouaumarquivonoservidor, chameafunção GDimagepng ( ) . ■ Aoterminardetrabalharcomuma imagem, chame imagedestroyO para apagá~la da memória.
  • 632.
    visualizando dados domismatch Cinco graus de oposipão Uma vez que o Mismatch é uma comunidade de usuários (humanos!) registrados, bots de spam não têm sido problema. Porém, os usuários querem um pouco mais do recurso de encontrar pares im perfeitos do site, principalm ente o conceito de "cinco graus de oposição" de que têm ouvido falar. Os usuários do Mismatch querem mais do que apenas uma lista de tópicos do seu par imperfeito ideal - eles querem algum tipo de contextualização visual de como esses tópicos se relacionam com cada categoria principal de "desencontrabilidade" Euvejo ummonte de tópicos, mas realmente naosei exatamente como nós nos desencontramos nas diferentes categorias. Eu gosto do conceito de "cinco graus de oposição", mas não consigo ver como isso se relaciona ao meu par imperfeito. Eagora? 0 c o n c e it^ d e "c in c o g ra u s d e o p o siç ã o ” d o M ism a tc h enV plV e a aVallaçã» d p s tó p ic o s d e se n c o n tra d o s p o r categ p ria. 0 Beli-b c uma fessoâ 0 visual, t «uer ver o mau do «ue acenas uma lista de -toftèos 0 reíeren^s ao seu fâr ^ '»m ç>eY “£eVfcoideal />r>A
  • 633.
    visualizando seus dados...e mais! Fondo a desencontrabilidade m tabela Como você deve se lembrar, o Mismatch inclui um questionário categorizado, onde os usuários selecionam as opções Adoro ou Odeio para uma série de tópicos. São essas respostas que determinam os tópicos que compõem um par imperfeito ideal. Ao apresentar o par imperfeito ideal para o usuário, o script My Mismatch exibe uma lista de tópicos desencontrados, que ele cria como um array a partir do banco de dados do Mismatch. Mas os usuários agora querem mais do que uma lista de tópicos... eles querem uma representação visual categorizada das suas "desencontrabilidades", talvez em forma de gráfico. Reality TV Horror movies Easy listening music The opera Sushi______ Spicy food Peanut butter & banana sandwiches Martinis Bill Gates Yoga Weightlifting Cube puzzles Karaoke usando os dados do Mismatch, que mostre visualmente os "cincograus de oposição" para Belita e Jason. Escreva oque as informações do gráfico significam. Desenhe umgráfico de barras, FVedisamos ■ fcrâns-ítarmaVf de alj^ummodo, esta lista dc tópidos en. um gtriíido você está aqui ► 631
  • 634.
    gravando dados gráficosno array Desenhe umgráficode barras, usandoosdados do Mismatch, que mostrevisualmenteos "cincograusdeoposição" para Belitae Jason. Escrevaoqueas informaçõesdográficosignificam. e -j, Embora haja muitas W a s diferentes de representar viswaUe^ oS dados do Mismatdb, ur* ojr&to debarras • t . *ão é uma rná opdão, uma vC zl ^ue as dateaorias tem, ta d a j ^ --------^ . â /alores um a> nUero iftual de tépidos. < / de um 3raíido de . ç .--------------- ----------------------------------------- I Cada ba' barras estabelece os valores possíveis para dada barra. Faixa 3 Cada barra representa o wmero de desendontros cm uma dada daíey>ria de tépidos. barra do cyrá-fido -tem um-trtulo e um valor - o valor desta a<ui e 5. altura de uma barra reflete a magnitude do valor para um determinado título. Armazenando dados do gráfico de barras No fim das contas, os dados por trás de ura gráfico de barras são talvez mais importantes do que os gráficos. Sabendo que esse tipo de gráfico na verdade é apenas um conjunto de títulos e valores, podemos visualizar os dados de um gráfico de barras com um array bidimensional, em que o array principal armazena as barras, enquanto que cada sub-array armazena o par título/valor para cada barra. Cada sub-array armazena o título e o valor pârâ um dada barra do gra£»do. / $graph data = array( array! "Heading-'.!”/ ..$vaíue|||, array("Heading 2", $value2), array("Heading 3", $value3) Cada i-tem do array prmdipal dorresponde a uma barra- m i r
  • 635.
    visualizando seus dados...e mais! nap existem P e rg u n ta s Id io ta s 9 } 0 gráfico de barras precisa ser alimentado a partir de um array bidimensional? A: Não, não necessariamente. Mas tenha em mente que cada barra do gráfico geralmente envolve duas informações: um título e um valor. E cada gráfico contém várias barras, de modo que um array bidimensional é uma forma lógica e eficiente de se armazenar dados usados para preencher um gráfico de barras. Como diz o ditado, "se você só consegue ver uma solução, você não entendeu realmente o problema". Neste caso, o problema é achar a melhor forma de armazenar os dados a serem injetados em um gráfico de barras, e uma solução que funciona bem é o array bidimensional. É claro que o desafio ainda é como exatamente criar esse array bidimensional com dados das categorias do Mismatch. 0 primeiro passo é isolar quais dados do banco entram na solução. RCÍClO Oesquema do banco de dados da aplicação Mismatch é mostrado abaixo. Circule todos os dados que precisam ser usados para a geração dinâmica do gráficode barras "cinco graus de oposição”,e não se esqueça de escrever como eles são usados para se criar ográfico 111 user id v —v username password join_date first name last name gender birth date city state picture rateaory_id 0 , name response id topic id 0 'ft response name 1icpr i r i ^ H r _ category id tnpic id ^ você está aqui ► 633
  • 636.
    'exercício solução RCÍCÍO S oLu Ç ao ---- •_id o— username password Uesquema do banco de dados da aplicaçao Mismatch e mostrado abaixo. Circuletodos os dados que precisam ser usados para a geração dinâmica do gráfico de barras "cinco graus de oposição", e não se esqueça de escrevercomo eles são usados para se criaro gráfico.. A doluna user_Jd é usada para sc donsultar respostas do Questionário, para Q ue se A doluna response_id e usada para se possa deíerminar o melhor par dombinar as respostas de dois usuários, •mperteito para um usuário. para determinar se elas esta© definidas dom valores opostos —um desendohtrof. A doluna dategoryjid è usada para se assobiar uma dategoria tom um tépido, o Que leva a uma resposta desendontrada- 0 nome da dategoria e impoirtan-te porque é ele Q ue formede os -tftulos para o jjráfido de barras. join_date first_name iast_name gender birthdate city state picture T ïïÿjïïri ' (^topic id Adoluna topid_id serve domo in-termediário para as dategorias e as respostas, Que t o Que permite a vode desdobrir a dategoria de dada resposta desendon-trada- 0 gráfido de barras reQuer, em úl-tima instândia, uma dontagem de Quantos desendontros existem para dada dâtegoría; a don-tagem é o valor para dada barra, enQuanto Q ^ Co nome da dategoria t o seu -título. C O A
  • 637.
    Gtáflco de BattasExp^stP Na entrevista desta semana: Lendo entre as linhas com o senhor dos gráficos visualizando seus dados... e mais! Use a Cabeça: Então você é o cara que as pessoas chamam quando elas precisam de uma representação visual de alguns dados. E isso mesmo? Gráfico de Barras: Exato. Eu sou expert em todos os tipos de visualização de dados, principalmente no tipo retangular. Use a Cabeça!: Então as suas capacidades de desenho se limitam principalmente a retângulos Gráfico de Barras: Acho que "se limitam" é uma expressão forte neste caso. E uma daquelas situações em que quanto mais simples, melhor - as pessoas simplesmente parecem mais acostumadas com as barras, talvez porque elas estejam acostumadas a ver as coisas medidas dessa forma. E como aquela barrinha nos celulares que lhe diz o quão forte está o sinal. "Está conseguindo me ouvir agora?" Eu adoro isso. Use a Cabeça!: Certo. Mas eujá vi alguns gráficos redondos bem eficientes. Me lembram de coisas boas... como torta de maçã, entende o que eu quero dizer? Gráfico de Barras: Entendi o que você está insinuando, e conheço o Gráfico Torta. Veja, são duas maneiras diferentes de se pensar sobre a mesma coisa. O Gráfico Torta vê o mundo em curvas; eu vejo um pouco mais reto, só isso. Use a Cabeça!: Ma as pessoas não se relacionam inerentemente melhor com uma torta do que com um monte de barras? Gráfico de Barras: Não, a não ser que elas estejam com fome. Veja, o Gráfico Torta é realmente bom para mostrar as partes que compõem o todo, onde os dados compõem algo que realmente importa: 100%, 32 times, 50 estados. São 50 estados nos EUA, certo? Use a Cabeça!: Sim. Bem, assumindo-se que você conte Washington, D.C. como "distrito federal" e lugares como Porto Rico e Guam como "territórios''. Mas, de qualquer forma, entendo o que você está dizendo sobre o Gráfico Torta ser mais adequado para revelar partes de um todo, mas você não faz a mesma coisa? Gráfico de Barras: Sim, mas tenha em mente que eu sou muito mais flexível do que o Gráfico Torta. Você pode me adicionar quantas barras quiser, e eu não terei problema nenhuma para exibi-las. No caso do Gráfico Torta, quanto mais coisas você adiciona, menores as fatias ficam. Chega um ponto em que as partes ficam difíceis de visualizar. No meu caso, tudo o que importa é que as barras têm valores que podem ser mostrados na mesma escala. Use a Cabeça!: O que isso significa? Gráfico de Barras: Bem, eu tenho dificuldades em mostrar coisas que tenham valores altamente diferentes - a não ser, é claro, que você não se importe que as barras sejam altamente diferentes. O meu ponto forte é mostrar a diferença entre valores que estejam dentro da mesma faixa. Por exemplo, talvez você queira que eu mostre o preço da gasolina ao longo de um período de um ano, em cujo caso, todos os valores estariam dentro de uma faixa razoavelmente restrita, por exemplo, com apenas alguns reais de diferença uns para os outros. Use a Cabeça!: Tem certeza disso? Gráfico de Barras: Eu sei, o preço da gasolina parece ser um valor que varia sem limites, mas na verdade não é tão ilimitado assim, dentro do tipo de situações com que eu lido. Use a Cabeça!: Então você está acostumado a ver coisas bem esquisitas, não? Gráfico de Barras: Você não acreditaria. Uma vez, um cara criou uma aplicação web que mantinha registro de quantas milhas ele arrastava o seu mouse por mês. Ele tinha até um blog sobre isso, e me usava para representar as suas "viagens" em forma de gráfico. Bem louco, mas as pessoas adoram esse tipo de coisa. Use a Cabeça!: Então esse é o seu campo de atuação - fornecer representações visuais dos dados das pessoas? Gráfico de Barras: Sim, creio que sim. Sempre que eu posso ser colocado em uma página para fornecer um visual extra para dados que, sem mim, ficariam um pouco chatos e difíceis de entender, considero meu trabalho feito. Use a Cabeça!: Fico feliz de ouvi-lo. Obrigado por conversar conosco, espero que possamos fazer isto novamente. Gráfico de Barras: O prazer foi todo meu. E não se preocupe, você continuará me vendo por aí. você está aqui V 635
  • 638.
    construindo um arraypara categorias Pe uw array para outro Um alias « wado para sc eliminar ' A N a do^TU SâOao referir â dolt*nâ name da iabela mismatdb_d*tegory. Da última vezque vimos o Mismatch, tínhamos uma listade tópicos que correspondiam a desencontros entre dois usuários. Mais especificamente, nós tínhamos naverdade um array de tópicos. O problema é que o gráfico de barras que estamos tentando desenhar não é exatamente sobre os tópicos- é sobre as categorias associadas com os tópicos. Assim, estamos separados em um nível dos dados que realmente precisamos. Parece que precisamos de maisalgumas consultas SQL. Não apenas precisamos do array de tópicos desencontrados, mas precisamos também de um arrayparalelo semelhante, de categorias desencontradas. Umjoin múl-tiplo dohedta a "tabela das $< : íuery = "SELECT mr.response idf mr.topic id, mr .response, dategorias à tabela mt.name as topic_name, f||§|p||f§ das respostas, de "FROM mísmatch_response AS mr " . . modo Q ue o nome d a. T ," JOIN mismatch topic AS mt ^USING (topic id) e ^ d c . ^ w Ojoin adicional nessa consulta faz o nome da categoria correspondente a cada tópico de resposta ser anexado aos dados do resultado, acabando no array $user_responses. Mas lembre-se, nós só precisamos das categorias desencontradas, e não de todas as categorias. Precisamos criar outro array, contendo apenas as categorias desencontradas para as respostas. topiename category^naire Appearance Appearance Appearance Appearance Appearance Entertainment Entertainment Entertainment i~a no Capitule o array bidimensional i lAserjresponses -foi driado e preendbido dom dados de resultade dorrespondenies as respostas do usuário atual- Entertainment Entertainment Food Food Food Nos ainda predisamos de um novo array, dontendo apenas as dategorias desendon-tradas para este par de usuários. A »ova H doluna” de dados de resultado armazena o nome da dategoria de dada resposta- Nos predisamos y, extrair apenas os f nomes das dategorias referen-tes a respostas desendontradas, e doloda-los em um array. Food Food people People People People $user_responses Mas ainda não estamos atingindo o nosso objetivo de criar um array de categorias desencontradas. Para fazer isso, precisamos revisitar o código que cria o array de tópicos desencontrados...
  • 639.
    visualizando seus dados...e mais! T t e S T O R 1 V E Teste a nova consulta para obter tópicos e categorias desencontrados. Usando uma ferramenta MySQL, emita a seguinte consulta para selecionar tópicos e categorias desencontrados para um determinado usuário. Certifique-se de especificar a ID de um usuário que não só exista no banco de dados, mas que tenha também preenchido o questionário do Mismatch: SELECT mr.response_id, mr.topic_id, mr.response, mt. name AS topic_name, me.name AS category_name FROM mísmatch_response AS mr INNER JOIN mismatch_topic AS mt USING (topic_id) INNER JOIN mismatch_category AS me USING (category_id) WHERE mr.user_id = J3; A (D deve str a de w* usuário válido, Q ue respondido o Questiono do q i> c.fc,LECT mr . r esp Q n se _ i'd .,. mr ■ .€ o p í c _ i d , s ir v r a s a q n s e , t .n a m e AS r.cp i c_n arn e, _mc.na.ms AS catéq.cA ry An'ain'e ROM mi sm s r,c r.__re s c c a s e. .AS. mr .. . ' ' NAA.S o rr.isngi:ci'.._tôpr^c.. AS -.mt U SIN Q A ixQ pi'c id ) NNER JOIN :n is n a t:c h _ c a -e ç o .r y AS inc USING ' (C £ t e g o r y _ id ) HERE n r . user'A td.' = .•3-;A. A A ' . A -A.-- A • ■ i a } - r e s p o n s e ■:i ^ c p i c ;.cirri; .. ! .1' 1 T a x t c c s ’ !.. 2 .' ' G o id c h a i: ' i l . 1 E ody- p i e r i : i;' 2 A i i ' C o ^ ' û o v b e i ï L o n g h a ï r ... i. : ■ ; ; R e a ^ it y . T ! i P r q f e s s i o r A A - :: AAi F .o r r c r no-, ! ■c a t e g o r y r.ami .+ ----------------- ------ ■ , A p p e a r a n c e ■ ; A p p e a r a n c e .^jc'ps tri"c < 3 .nc ^ • ! A p p e a r a n c e A p p e a r a n c e a 1..E n t c.r t a i r.me n t i E n ter'iia in .T ien t i E n t e r t a in m e n t ■ i E n t e r t a in m e n t w r e s t i m c s y l i s t e n i n q m u s ic ' Repava Que os resul-fcôdos desta tonsui'fca bâte» to * o av-v-ay ?usev_jrespo*ses da página airrbeviov, Que e o Que *os Queremos. r E sennpv-e u»»a bod ideia testar as donsui-fcas em u»»a -fe^rameh-ta My£$L antes de doioia-las ko dódijo PUP. você está aqui > 637
  • 640.
    Construindo um arrypor tópicos Crie um array detópicos desencontrados Agora nós temos uma consulta que realiza umjoin múltiplo para obter a categoria de cada resposta, além do tópico, que é então colocada no array $user_responses. Lembre-se que outra consulta, parecida com esta, também está obtendo dados para cada outro usuário do banco, para que as comparações de desencontrabilidade possam ser feitas. Assim, $user_ responses armazena os dados de resposta para o usuário logado no Mismatch, enquanto que $mismatch_responses armazena um dos outros usuários do sistema. Isso nos permite fazer um loop através de todos os usuários, e atualizar $mismatch_responses em cada comparação. Nósjá estamos usando esses dois arrays para encontrar pares imperfeitos e para criar um array de tópicos desencontrados. Agora, podemos adicionar uma nova linha de código para construir também um array de categorias desencontradas - este array conterá a categoria de cada tópico desencontrado entre dois usuários. Este i o mesmo dod'150 da versão anterior do Mismâtdh, f e*deto feio + < 3 rfcode Q ue a$ora ele dria um array de y, tate^orías desencontradas, alem do array de tépidos. Çcategories = array{); for ($i = 0; $i < count($user_responses); $i++) { if ($user_responses[$i] [’response 1] + $mismatch_responses[$i] ['response' ] == 3) { ?score - + = 1; array push($topics, $user responses[$i] ['topic_name']); ' , t Este código resulta em um array toniendo apenas as eatejorias desencontradas. Ko íim das dontas, o array /date^ories dontem uma dâtegoria pôra dada desendontro. na° existam perguntas Idiotas Um array de dategorias desendontradas é driado armazenando-se a dategoria assodiada dom dada resposta desendontradâ- Estou um pouco confuso. Qual é adiferença entre um conjunto de resultados do MySQL e um array do PHP? K: Uma grande diferença é 0acesso. Um conjunto de resultados só disponibiliza uma linha de dados de cada vez, enquanto que um array pode armazenar várias "linhas" de dados, graças às múltiplas dimensões. Colocar um conjunto de resultados em um array bidimensional permite que nos movamos através das linhas de dados de forma eficiente, sem termos que ficar voltando ao servidor do banco de dados para obter linhas várias vezes. Isso não funciona com conjuntos enormes de dados, uma vez que para isso você precisaria criar arrays enormes; mas, no caso das respostas do Mismatch, os arrays nunca são maiores do que 0número total de tópicos no sistema. I * Mas nós ainda precisamos contar quantas vezes uma categoria foi desencontrada para podermos gerar 0 gráfico dé barras, certo? Certo. Um array de categorias desencontradas não é suficiente. Lembre-se de que a ideia por trás do gráfico de barras do Mismatch é que cada barra representa uma categoria desencontrada, e que a altura da barra representa quantas vezes a categoria foi desencontrada. Assim, precisamos de uma forma de contar quantas vezes cada categoria foi desencontrada. Mas provavelmente vale a pena dar um passo atrás, para formularmos um plano geral de ataque....
  • 641.
    visualizando seus dados...e mais! Formulando umplano para exeeupãodos gráficos debarras Com um array de categorias desencontradas e um monte de ideias sobre como usá-las para gerar um gráfico de barras para a página My Mismatch, só o que nos falta é um plano. Como veremos logo abaixo, só são necessários três passos para se gerar dinamicamente o gráfico de barras, ejá realizamos um deles. Este passo nos íor»>eCe a lista das categorias desencontradas- ^ ConsnWdr o ba»co~c lrtfaKtoyilo Mismatch cm buocn dos nomps das catogorias desencontradas O Calcular os totais de desencontros para cada categoria. 0 Desenhar o gráfico de barras usando-se os totais das categorias. Para completar o Passo 2 do nosso plano, precisamos de alguma forma de pegar o array de categorias desencontradas e transformá-lo em um conjunto de totais para as categorias, ou seja, uma contagem de quantas vezes cada categoria aparece no array. Como você deve se lembrar, esse é, precisamente, o tipo de dados requeridos para se criar um gráfico de barras, onde as categorias são os títulos e a contagem para cada categoria é o valor de cada barra. Um array bidimensional pode ser usado para se combinar categorias e totais em uma única estrutura de dados. A lista de categorias précisa ser Convertida e» uma lista de totais. Tendo os totais das categorias, m ós podemos passar para ã parte divertida, <ue e desejar o gráíico de barras Com íun^oes 0lKar o »ovo array Appearance I S Entertainment 4 J B Food 4 J p people 2 Activities 5 das categorias por U m angulo diterente revela C or*©de g usado para rn UY os «fedos a© gra+íc© de barras. Este array Contém o nome de cada categoria, uttto Com o total i c * de vezes < ^ u e ela toi desenCofttrada. Os novos dados das Categorias desencontrada s3©cxdtdmente o «ue precisados para o gra-fic© de barras. Uma vez criado esse array de totais, estaremos prontos para seguirmos para o Passo 3, onde usaremos algumas funções GD para gerar o visual do gráfico de barras. você está aqui ► 639
  • 642.
    um pouco dematemática de array Amassando as categorias O desafio agora é totalizar o array de categorias e colocá-lo em um array bidimensional de títulos e valores. Nós temos um array de categorias desencontradas armazenado em ^categories. Precisamos criar um novo array cham ado $ category_totais, que irá conter um a entrada para cada categoria,junto com o número de desencontros para cada uma. Precisamos partir disto.. 0 número -bvhêl de otorremttds de uma da£«govia noasrây fdaiejotries apaveCe Ê O rw ®u m ntoial hOSYYdy f Câtegory^to-tals. ...e chegar a isto! Appearance —s. s j j 4 I Entertainment Food 4 People 2 Activities 5 $category_totais $categories W K R C T R « Como você faria para totalizar as categorias desencontradas no array Scategories, para criar o array bidimensional $category_totals?
  • 643.
    visualizando seus dados...e mais! A matemática das categorias Passar de um array unidimensional de categorias desencontradas para um array bidimensional de totais das categorias pode ser um pouco mais complicado do que você poderia pensar, à primeira vista. Por esse motivo, é útil trabalhar na solução através de pseudocódigo antes de realmente escrever qualquer PHP. O pseudcódigo nos livra dos detalhes sintáticos e nos permite focalizar nas ideias centrais envolvidas em uma determinada solução de codificação. Criar um novo array bidimensional para armazenar os totais das categorias, certificando-se de inicializar o primeiro elemento com a primeira categoria desencontrada e uma contagem 0. Fazer loop através do array de categorias desencontradas. Para cada categoria do array... O último elemento do array contendo os totais é de uma categoria diferente do desencontro atual? ^ S im ! Temos uma nova categoria, portanto vamos adicioná- la ao array com os totais das categorias e inicializar a sua contagem como 0. ^ Não. Esta é apenas uma nova instância da categoria atual, portanto vamos incrementar a contagem do último elemento do array com os totais das categorias. O produto deste código é um array bidimensional de totais, no qual o array principal armazena uma única categoria, enquanto que cada sub- array contém o nome da categoria e o seu valor. Traduza o pseudocódigo para completar ocódigo PHP real que cria oarray bidimensional de dados de categorias do Mismatch, chamado $category_totals. $category_totals = array{array{$mismatch_categories[0], 0)); foreach ($mismatch__categories as $category) { } você está aqui ► 641
  • 644.
    exercício solução Traduza opseudocódigo para completar ocódigo PHP real que cria oarray ibidimensional de dados de categorias do Mismatch, chamado $category_totals. ttr ír ío arrays sao inde*ados a partir do zero, portanto o S o L u ç a o ultimo elemento de um ârray e sempre Count^ «*enos um . $category_totals = array (array ($mismatch_categories [0], 0) ); foreach (Smismatch categories as Scateaorv) l - i-P (fcategory^totaUtcountífcategory^totaU) - 3C03 /—fcategory) { ,^!^.y(í£^kgory) ^ ta e uma nova categoria, j ^ _______ ^ portanto vamos adiciona-la ao ..................................................................................................... array de totais, na -Por»,a de um ejse { sub-array Consistindo do nome .....-• ncn++;.... ' ie ....1.......................................................................................^Tmr.. 0 ofwâdov- de infiremen-t» ^ C++) é aplicado ao segundo elemento do sub-array, <ue e a dontage» das categorias. $category__totals / A variável ?category_totais agora armazena precisamente os dados necessários para se gerar um gra-fico de barras para as categorias desencontradas. Este e o resultado -Pina) deste código- Agora nos podemos riscar este passo da lista, o ^ue nos deixa apenas com a tareia de desenhar o grá£ic© de barras. 0 Calc ular os totais de dese