Thanks to visit codestin.com
Credit goes to pt.scribd.com

0% acharam este documento útil (0 voto)
2K visualizações402 páginas

85 Bits - PHP

Este documento fornece informações sobre um curso de PHP 7 ministrado por Celso Araujo Fontes. O curso aborda tópicos como PHP básico, funções, arrays, orientação a objetos, formulários, banco de dados e padrões de projeto. O curso é oferecido em vídeo aulas disponíveis no YouTube.

Enviado por

Danilo Henrique
Direitos autorais
© © All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
0% acharam este documento útil (0 voto)
2K visualizações402 páginas

85 Bits - PHP

Este documento fornece informações sobre um curso de PHP 7 ministrado por Celso Araujo Fontes. O curso aborda tópicos como PHP básico, funções, arrays, orientação a objetos, formulários, banco de dados e padrões de projeto. O curso é oferecido em vídeo aulas disponíveis no YouTube.

Enviado por

Danilo Henrique
Direitos autorais
© © All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
Você está na página 1/ 402

CURSO DE PHP 7

Versão Vídeo Aula disponível em:

https://www.youtube.com/channel/UC0aGMws3O0PEhxng-CxwLFg
Sobre o Professor (Abril 2019)
● Celso Araujo Fontes
● Mestre em Sistemas e Computação (IME-RJ)
● Coordenador de Projetos Estratégicos na PGE RJ
● Professor na graduação do Instituto Infnet

linkedin: https://www.linkedin.com/in/celsowm/
email: [email protected]
Tópicos do Curso
1. PHP Básico (sintaxe, variáveis, estruturas de controle...)
2. PHP Funções
3. PHP Arrays
4. PHP Orientado a Objetos (classe, herança, interface...)
5. PHP Entrada de Dados e Formulários
6. Serialização
7. Tratamento de Exceções
8. Estruturas de Dados com SPL (pilha, fila...)
9. PHP e Banco de Dados (pdo)
10. Design Patterns
PHP Básico
● Introdução ao PHP
● Sintaxe Básica
● Variáveis
● Operadores (string, aritméticos, comparação, lógicos,
incremento/decremento)
● Estruturas de Controle (if, switch, for, while)
● Função
● Constante
PHP
● Criado por Rasmus Lerdorf in 1994
● Originalmente Personal Home Page hoje PHP: Hypertext
Preprocessor
● Linguagem script (server-side)
● Tipagem dinâmica
● Multiparadigma (procedural, reflexiva, orientada a objetos,
funcional, imperativa)
● Influenciada por Perl, C, C++, Java e Tcl.
● Cross-platform (Windows, Linux, Mac OSX…)
PHP
Ferramentas (sugestões)
● Ferramentas Web:
○ http://ideone.com/
○ https://3v4l.org/
○ http://phpfiddle.org/
○ http://phptester.net/

● Ferramentas desktop:
○ http://www.wampserver.com/
○ https://notepad-plus-plus.org/
○ https://netbeans.org/
Exemplo de Arquitetura com PHP
Web Server

request
(exemplo.php)

os
response dad
sql
Arquitetura PHP
● Executável que interpreta e executa scripts PHP
● Suporta extensões escritas em C
○ Projetos PECL (PHP Extension Community Library) outros
● Pode utilizar bibliotecas de terceiros escritas em PHP
○ Projeto PEAR PHP Extension and Application Repository) e outros
● Precisa, normalmente, de um serviço HTTP para responder requisições Web
Sintaxe básica (HTML5 + PHP)
<!DOCTYPE html> O objetivo final da maioria dos
documentos web PHP será exibir
<html>
dinamicamente algum conteúdo HTML,
<head> pois esta é a linguagem de marcação
utilizada pelos navegadores para
<title>PHP Test</title>
exibição e formatação dos elementos de
</head> uma página web.
<body>
Este é um exemplo de uma página web
<?php echo '<p>Hello World</p>'; ?> em HTML5 com um trecho de instruções
para interpretação do PHP.
</body>
</html> O cliente não terá acesso ao código
PHP, apenas ao conteúdo final escrito
pelo mesmo.
Separação de instruções (; ?> )
Basicamente um código PHP
<?php começa com o símbolo de menor
seguido de um sinal de interrogação
echo 'Isto é um teste'; e o termo PHP.

?> Cada instrução é separada pelo


caractere ponto e vírgula.

Para fechar um bloco de códigos


<?php echo 'Isto é um teste' ?> PHP utilizamos o símbolo de
interrogação e o sinal de menor.

É válido salientar que a instrução de


<?php echo 'Nós omitimos a última fechamento do PHP é opcional
tag de fechamento'; quando não existe nenhum outro
tipo de código após o bloco de
instruções
Comentários ( //, /* */, #)
<?php

echo 'Isto é um teste'; // Estilo de

comentário de uma linha em c++ Assim como outras linguagens, o


PHP permite a escrita de
/* Este é um comentário de múltiplas linhas comentários, que permitem ao
desenvolvedor escrever textos que
ainda outra linha de comentário */ possam explicar a outros
desenvolvedores o que significa
echo 'Isto é ainda outro teste';
aquele código ou até documentar
echo 'Um teste final'; # Este é um comentário de forma estruturada elementos da
aplicação através do PHPdoc.
de uma linha no estilo shell

?>
require_once & include
● funcionam com caminhos
○ absolutos:
■ “c:\\apache24\\htdocs\\aula\\teste.php”
○ relativos:
■ “teste.php” “..\aula2\teste2.php”
● quando o arquivo não existe:
○ include: gera erro mas o script continua
○ require: erro fatal e o script é encerrado
● require_once:
○ A instrução require_once () é idêntica a require (), exceto que o PHP verificará se o arquivo já
foi incluído e, em caso afirmativo, não incluirá (require) novamente.
Variáveis e Tipos “básicos” O elemento básico de qualquer linguagem de
programação é variável.

<?php Variáveis são basicamente locais onde as


informações são definidas ou referenciadas.
No PHP as variáveis começam com o símbolo
$minha_var; // null do cifrão ($) seguido pelo nome da variável.

$texto = "Ola Mundo !"; // string Se nenhum valor é definido para esta variável,
ela começa automaticamente com o valor NULL
$x = 5; // integer ou nulo.
$y = 10.5; // float ou double
Para definir um valor basta utilizar o símbolo de
$verdadeiro = true; // bollean igual seguido do valor que pode ser um destes
tipos primitivos ou também um array ou uma
$nulo = null; // null referência a um objeto.

Como o PHP é uma linguagem de tipagem


dinâmica, não é necessário que o
desenvolvedor defina um tipo para a variável,
pois a mesma poderá ter seu tipo alterado de
acordo com o valores a serem definidos na
execução do código.
Variáveis (diferença entre caixas)
<?php
É válido salientar que os
nomes de variáveis no PHP
fazem distinção entre letras
//duas variáveis diferentes maiúsculas e minúsculas
$verdadeiro = true; (caixas alta e baixa).

$Verdadeiro = false; Portanto, neste exemplo,


existem duas variáveis
distintas pois uma possua uma
letra em caixa diferente da
outra.
Echo e Print
<?php Outro recurso fundamental de qualquer
echo("Olá Mundo!"); ambiente de desenvolvimento é a saída
padrão, isto é, uma forma para se exibir
echo "Olá Mundo !"; conteúdo para o usuário. No PHP
echo "Olá ", "Mundo!"; podemos utilizar tanto o echo e como o
print. Como nenhum deles é exatamente
uma função PHP, o uso do parêntese é
opcional.
<?php
print("Olá Mundo!"); As diferenças entre eles são que o echo
print "Olá Mundo!"; é ligeiramente mais rápido e pode
aceitar mais de um parâmetro enquanto
$ret = print "Hello World"; o print tem valor de retorno 1 e pode ser
print("Olá mundo! ".$ret); usado como uma função.
Strings (‘Single quoted’ e “Double quoted”)
<?php Para definir uma string ou texto, o PHP
permite utilizar dois diferentes tipos de
caracteres delimitadores, o apóstrofo ou
$versao = 7; as aspas.

Quando uma string é delimitada por


echo 'PHP versão $versao'; apóstrofos, nomes de variáveis serão
considerados partes integrantes do texto.
//saída: PHP versão $versao
Já com o uso das aspas, nomes de
variáveis serão interpretados e seus
echo "PHP versão $versao"; valores e não seus nomes é que serão
//saída: PHP versão 7 considerados para integrar a string.
‘NOWDOC’ e HEREDOC
<?php NOWDOC são para cadeias de
caracteres com aspas simples o que
$versao = '7'; HEREDOC são para cadeias de
caracteres com aspas duplas.
$nowdoc = <<<'NOW'
PHP versão $versao! Um NOWDOC é especificado de forma
NOW; semelhante a um HEREDOC, mas
nenhuma análise é feita dentro de um
$herec = <<<HERE NOWDOC.
PHP versão $versao!
HERE; A construção é ideal para incorporar
código PHP ou outros grandes blocos
echo $nowdoc; de texto sem a necessidade de usar
echo $herec; “escape” (escapar).
Operadores de String (concatenação “.” e ”.=”)

<?php Um importante recurso para a manipulação


de duas ou mais strings é o operador de
$a = "Olá "; concatenação.

$b = $a . "Mundo!"; O sinal de ponto no PHP é utilizado com este


propósito: permitir a união de uma ou mais
strings.

$a = "Hello "; Ele também pode ser utilizado com o símbolo


de igual para permitir que o PHP faça a
$a .= "World!"; concatenação do conteúdo já presente na
variável à esquerda do ponto com o conteúdo
a direita do sinal de igual.
Operadores Aritméticos
Operador Nome Exemplo Resultado

+ Adição $x = 2 + 2; 4 Outro conjunto de operadores


comumente disponível nas
- Subtração/Negação $x = 4 - 2; 2 linguagens de programação são os
operadores aritméticos.
* Multiplicação $x = 2 * 10; 20 Ressaltando que além das quatro
operações básicas da aritmética,
/ Divisão $x = 15 / 5 3
no PHP, existe também o operador
% Módulo (sobra da $x = 5 % 2 1 de módulo, que permite obter o
divisão) valor da sobra de uma divisão e o
operador de exponencial.
** Exponencial $x = 4 ** 4; 256
Ordem de precedência
<?php
//PHP usa a ordem de precedência
conhecida como BODMAS

$x = 1 + 2 * 3;
$y = (1 + 2) * 3;
echo $x; //7
echo $y; //9

fonte:http://www.famousarticlesolutionz.com/2015/03/what-is-bodmas-rule.html
unset()
<?php

$a = 1; O unset() destrói variáveis previamente


$b = $a; especificadas.
unset($a);
O comportamento de unset() dentro de
echo $a; //Notice: Undefined variable: a
uma função pode variar dependendo do
echo $b;
tipo de variável que você está tentando
destruir.
Estrutura de Controle (If)
● Como toda linguagem de alto nível, PHP possui um conjunto
estruturas de controle que permite à aplicação reagir a diferentes
ações ou resultados.
● A primeira e mais importante é o IF (se).
● O if permite testar uma ou mais condições e definir quais serão os
códigos para executar caso a condição seja verdadeira ou falsa.
● Neste pequeno exemplo testamos se uma determinada variável
possui o conteúdo igual a string “85 bits”, se a condição for
verdadeira o código do bloco “então” será executado.
Estrutura de Controle (If)

● Sintaxe básica:
then/então falso
condição
if (condição) {
verdadeiro
//código para executar se a
condição for verdadeira;
código condicional
}

fim do código condicional


fim
Estrutura de Controle (If)

Neste pequeno exemplo testamos se uma determinada variável possui o


conteúdo igual a string “85 bits”, se a condição for verdadeira o código.
Estrutura de Controle (If)
● Exemplo:
falso
condição
<?php
verdadeiro

if ($nome == "85 bits") { código condicional

echo "Nome correto !";


}
fim
Operadores de comparação
Exemplo ($a =
Operador Nome
5; $b = 3;)
Resultado Nesta tabela é descrito os
operadores de comparação
== Igual if ($a == $b) false
disponíveis no PHP.
=== Idêntico if ($a === $b) false
Apesar da tipagem
!= Diferente if ($a != $b) true
dinâmica do PHP é
<> Diferente if ($a <> $b) true possível fazer uma
!== Não if ($a !== $b) true comparação mais criteriosa
idêntico utilizando os comparadores
> Maior if ($a > $b) true
idêntico e não idênticos
que onde não apenas os
valores são comparados
< Menor if ($a < $b) false
que mas o tipo também.
Operadores de comparação

Operador Nome Exemplo ($a = 5; $b = 3; $c = 0) Resultados

>= Maior ou Igual if ($a >= $b) true

<= Menor ou Igual if ($a <= $b) false

<=> Spaceship if ($a <=> $b) 1

?? Diferente (Null $a ?? $b ?? $c 5
coalescing)

Spaceship: Retornar 0 se os valores de ambos os lados são iguais. Retornar 1 se o valor à esquerda é
maior. Retornar -1 se o valor da direita é maior.
Já o operador diferente ou Null Coalescing funciona avaliando as variáveis da esquerda para a direita, e o
primeiro valor não nulo será o resultado da comparação.
Operadores Lógicos

Operador Nome Exemplo ($a = 5; $b = 3; $c = 0;) Resultados

&& E if ($a && $b) true

II OU if ($a || $b) true

xor Xor “ou exclusivo” if ($a xor $b) 1

and E if ($a > $b AND $c < $a) true

or OU if ($a > $b OR $a < $c) true

! Not if(!($a > $b)) false


Operadores Lógicos (“>” maior, igual “==” e “&&”)
Exemplo:

<?php Outro conjunto de operadores


do PHP são os operadores
$compra = 500; lógicos, estes operadores são
$saldo = 300; utilizados para combinar e
$tem_cheque_especial = false; testar mais de uma condição.

if( $compra >= $saldo && $tem_cheque_especial == false ) { Neste exemplo utilizamos o
print 'compra negada'; operador lógico E,
} representado pelos símbolos
duplos de e comercial para
testar se ambas as condições
são verdadeiras.
Operadores Lógicos (ou “II” e “>=” maior ou igual)
Exemplo 2:

<?php
Neste exemplo utilizamos o operador
$tempo_trabalho = 24; lógico OU, representado pelos
$idade = 66; símbolos duplos de pipe para testar
se uma das condições são
if( $idade > 65 || $tempo_trabalho >= 25 ) { verdadeiras.
echo 'Aposentadoria !';
}
Operadores Lógicos (diferente “!=” )
Exemplo 3:

<?php
Neste exemplo utilizamos o operador
$convite = 'econômico'; lógico de diferente, representado
pelos símbolos de exclamação e igual
para testar se uma variável ou
if($convite != 'VIP'){ expressão é diferente do valor testado
echo 'Acesso negado!'; à direita.
}
Operadores Lógicos (igual “==” e idêntico “===” )
Exemplo 4:
<?php
<?php
$x = '300.00'; $x = '';
$y = null;
$y = 300.00;
$z = 0;
$z = 300.00;
if($x == $y){
if($x == $y){ echo 'iguais'; //são idênticos
echo 'iguais'; //são idênticos }
if($x === $y){
}
echo 'idênticos'; //não são idênticos
if($x === $y){ }
echo 'idênticos'; //não são idênticos if($y === $z){
} echo 'idênticos'; //não são idênticos
if($y === $z){ }
echo 'idênticos'; //são idênticos
}
Estrutura de Controle (if...else)

verdadeiro falso
Na estrutura de controle IF também condição
é possível definir qual conjunto de
códigos será executado se as
código código
condições do if não forem condicional condicional
verdadeiras, para isto, podemos (verdadeiro) (falso)

utilizar a cláusula “else”.

fim
Estrutura de Controle (if...else)
<?php
$a = 1; $b = 2; verdadeiro
condição
falso

if ($a > $b) { THEN/ENTÃO


código código
echo "A é maior que B"; condicional condicional
(verdadeiro) (falso)
} else {
echo "A não é maior do que B";
}
fim
Estrutura de Controle (if...elseif)
<?php
Também podemos
if ($a > $b) { combinar mais uma
echo "a é maior que b"; estrutura de controle if
utilizando a cláusula elseif.
} elseif ($a == $b) {
echo "a é igual a b"; Neste exemplo utilizamos
apenas um elseif mas
} else { diversos elseif podem ser
echo "a não é maior do que b"; usados.

}
Operador Ternário (?:)
Outra forma de escrita do if no PHP é o operador ternário. Nesta forma simplificada utilizamos o sinal de
<?php interrogação para definir bloco do então e o sinal de dois pontos para o else.
O valor de resultado da operação pode ser impresso ou armazenado em uma variável, conforme fizemos neste
exemplo.

$a = 40;
then/então else/senão
$b = 50;

$resultado = ($a >= $b ? 'maior ou igual a b' : 'menor que b');

echo $resultado;
Operadores de Incremento/Decremento

Operador Nome

++ Incremento

-- Decremento

Incremento e decremento são operadores que as linguagens oferecem para que


o desenvolvedor possa manipular o valor de uma variável de forma rápida,
permitindo que o seu valor acrescido ou subtraído em 1.
Pré Incremento e Decremento
<?php

$x = 10;
$y = 10;

//pré incremento
echo "valor de x:".++$x; //11 - Incrementa $x mais 1 e então retorna $x
echo "valor de x:".$x; //11

//pré decremento
echo "valor de x:".--$y; //9 - Decrementa $y menos 1 e então retorna $y
echo "valor de x:".$y; //9
Pós Incremento e Decremento
<?php

$x = 10;
$y = 10;

//pós incremento
echo "valor de x:".$x++; //10 - Retorna $x e então incrementa $x mais 1
echo "valor de x:".$x; //11

//pós decremento
echo "valor de x:".$y--; //10 - Retorna $y e então decrementa $y menos 1
echo "valor de x:".$y; //9
Estrutura de Controle (switch)
expressão
Apesar das facilidades do if muitas vezes nos
deparamos com um número grande de possibilidades
V
para uma determinada variável, então podemos usar condição
código do case n0
uma outra estrutura de controle chamada de switch. n0

Nela podemos definir um conjunto de rotinas para cada F


resultado e até um conjunto para se caso nenhum dos condição V
n1
código do case n1
resultados for alcançado.
F
É válido ressaltar a importância do uso do break no final
de cada bloco pois se não utilizarmos esta cláusula o código do default
PHP continuará testando as outras condições inclusive a
default.
fim
Estrutura de Controle (switch)
<?php expressão
switch ($i) {
V
case 0: condição
código do case n0
ATENÇÃO ! n0
echo "i igual a 0";
F
break;
condição V
código do case n1
case 1: n1

echo "i igual a 1"; F


break; código do default
default:
echo "i não é igual nem a 0 ou 1";
fim
}
Estrutura de Controle “loop
Durante o desenvolvimento de uma aplicação é comum trabalhar com instruções
repetitivas, e na maioria das vezes para trabalhar com um conjunto de dados.

Para otimizar este tipo de tarefa utilizamos estruturas de controle conhecidas


popularmente como “laço” ou loop.

Este fluxograma representa um exemplo de loop onde o primeiro passo é a


inicialização, onde muitas vezes uma variável é usada para o controle do loop.
Em seguida, uma condição é testada, e enquanto esta condição for verdadeira
todo o bloco do código será executado.
Quando a condição não é mais atendida, o laço é interrompido e as instruções
posteriores serão executadas.
Estrutura de Controle “loop”
Inicialização

falso
condição parar/fim

verdadeiro

código do loop

incrementar/
decrementar
Estrutura de Controle “loop” (for)
Sintaxe:

Uma das estruturas de


for (inicialização; condição; incremento) { controle de laço do PHP é
o FOR.
//código
Esta é sintaxe para sua
} //fim utilização de forma mais
básica.
Estrutura de Controle “loop” (for)
<?php
O número é: 0
O número é: 1
O número é: 2
for ($x = 0; $x <= 10; $x++) { O número é: 3
O número é: 4
echo "O número é: $x <br />"; O número é: 5

} O número é: 6
O número é: 7
O número é: 8
O número é: 9
O número é: 10

* substituir o </ br> por \r\n se vc estiver usando o ideone ou php cli.
Estrutura de Controle “loop” (while)

Outra estrutura de laço é o while


falso
(enquanto), ele permite que um condição
conjunto de instruções sejam repetidas
inúmeras vezes “enquanto” uma verdadeiro

condição for verdadeira.


código do loop
Por isso, é comum utilizar alguma
variável de controle que será
modificada dentro do escopo do while
para limitar o número de repetições.
parar/fim
Estrutura de Controle “loop” (while)
<?php
falso
condição

$i = 1;
verdadeiro
while ($i <= 10) {
código do loop
echo $i++;

parar/fim
Estrutura de Controle “loop” (do...while)
<?php DO

$x = 1;
código do loop
do {
echo "O número é: $x </ br>";
$x++;
verdadeiro
} while ($x <= 5); condição

falso

parar/fim
While (sintaxe alternativa)
<?php <?php

$i = 1; $i = 1;

while ($i <= 10) { while ($i <= 10):

echo $i++; echo $i;

} $i++;

endwhile;
Função
Sintaxe básica:
Uma função é
<?php basicamente um bloco
de instruções que
podem ser utilizados
function nomeDaFuncao() {
repetidamente num
//código
programa.
}
Função
<?php Diferente das outras
function escreverMensagem() { instruções básicas, uma
função nunca será
echo "Olá Mundo!"; executada imediatamente
} quando uma página ou
script é carregado.

escreverMensagem(); Uma função só será


// executar/chamar a função executada apenas quando
é feito uma chamada pela
mesma.
Função (argumentos/parâmetros)
<?php
function imprimeNome($nome) { Uma informação pode ser
echo "Meu nome é $nome !"; passada para as funções por
meio de argumentos. Um
}
argumento é como uma variável
(inclusive utilizamos o $ antes do
imprimeNome("João"); nome).
imprimeNome("Maria");
Argumentos são especificados
após o nome da função, dentro
dos parênteses.
Função (argumentos)
<?php
function imprimeNome($nome, $sobrenome) {
Podemos adicionar
echo "Meu nome é $nome $sobrenome !";
}
quantos argumentos
quisermos, basta
separá-los com uma
imprimeNome("João","Oliveira"); vírgula.
imprimeNome("Maria","das Lurdes");
Função (argumentos com valor padrão “opcional”)
<?php
Muitos vezes é necessários que
function imprimeNome($nome = "Fulano") { alguns parâmetros de nossa função
echo "Meu nome é $nome !"; sejam opcionais.
}
Para isso, podemos definir valores
padrões para os parâmetros que
imprimeNome(); desejamos que se tornem opcionais.
imprimeNome("João"); Esta atribuição é feita através de
imprimeNome("Maria"); forma muito similar a atribuição de
um valor para uma variável usando o
sinal de igual seguido do valor
desejado.
Lista de argumentos variável (Splat Operator “...”)
<?php A partir do PHP 5.6 tornou-se
function soma(...$numeros) { possível incluir o token reticências
para indicar uma lista de
echo array_sum($numeros); argumentos e assim informar que
a função aceita um número
} variável de argumentos.

Os argumentos serão passados


soma(1, 2, 3, 4); na forma de um array e por isso,
neste exemplo, utilizamos uma
função do php chamada
array_sum para somar os valores
dentro deste array.
Argument Unpacking (Splat Operator “...”)
<?php
function soma($a, $b, $c) {
O splat operator também
echo $a + $b + $c; pode ser utilizado para
} “desempacotar” um um
coleção em argumentos
separados.
$args = array(2, 3);
soma(1, ...$args);
Função (return)
<?php
function soma($x, $y) { O return permite que uma
função possa retornar
$z = $x + $y; algum valor.
return $z;
} O return retorna o controle
do programa para o trecho
que executou a chamada.
echo "5 + 10 = " . soma(5, 10)
;
Função Recursiva
● É basicamente uma função que chama a si mesma.

● Neste exemplo utilizaremos o resultado de cada iteração para multiplicar este


resultado vezes ele mesmo menos 1 em uma cadeia de recursividade que
será controlada por um “if” que irá garantir que a recursividade não seja
eterna.

● Atenção: Chamadas de função / método recursivas com mais de 100 a 200


níveis de recursão podem estourar a pilha e causar o encerramento do script
atual.

● A recursão infinita é considerada um erro de programação.


Função Recursiva
<?php

function fatorial($numero) {
=4*3
echo 'Numero atual'.$numero.' ';
= 4 * (3 * 2)
if ($numero < 2) { = 4 * (3 * (2 * 1))
return 1; = 4 * (3 * 2)
} else {
return ($numero * fatorial($numero-1)); =4*6
} = 24
}

echo 'Resultado:'.fatorial(4);
Type Hint
<?php

Tipos usados no
function soma(int $a, int $b) { TypeHint:
return $a + $b; ● bool
} ● float (php >=7)
● int (php >=7)
● string (php >=7)
echo soma(1,2); ● Classe/Interface
● callable
● self
● array
Type Hint + Splat Operator (...)
<?php
function soma(int ...$numeros) {
echo array_sum($numeros); O type hint ainda pode ser
usado em conjunto com o
} Splat Operator para especificar
qual será o tipo dos valores de
um determinado conjunto.
soma(1, 2, 3, 4);

soma(1, 2, 3, 4, 5, 6, 7);
Função (declaração de tipo de retorno “:”)
<?php
function soma($a, $b): int { A partir do PHP 7 também se tornou
possível definir o tipo do valor do retorno
return $a + $b; de uma função.

} Para utilizar este recurso, basta definir


tipo da saída (retorno) antecedido pelo
símbolo de dois pontos.

echo soma(1, 2.5);


declare (strict_types=1)
<?php
No PHP também é possível
controlar o nível de restrição do
declare(strict_types=1);
Type Hint, isto é, definir se a
restrição estará ligada “1” ou
function soma(int $a, int $b) {
desligada “0”.
return $a + $b;
}
Vale a pena salientar que o
strict_types precisar ser a primeira
echo soma(1,2); instrução no script
echo soma(1,2.5); //se o strict_types
// for 1 teremos um "TypeError"
Nullable types (php 7.1 >=) “?”
<?php

function soma(int $x, ?int $y): ?string Com o advento do PHP 7, foi
{ possível determinar uma nova
condição de valor para o tipo de
return $x+$y;
parâmetro (ou retorno de função),
} usando o “nullable type”.
O Nullable Type permite que além
echo soma(2,2).PHP_EOL; de um valor com o tipo solicitado,
echo soma(2,null).PHP_EOL; o parâmetro também seja capaz
echo soma(2).PHP_EOL; /*Too few de receber null (ou um retorno
arguments to function soma() */ null).
Passagem por referência “&”
<?php
function somar(&$var) {
$var++; Com o uso do e comercial,
é possível determinar que
}
um parâmetro possa
modificar uma variável
$x=5; “mantendo a referência”
somar($x); para a mesma dentro do
escopo da variável.
echo $x;
Função Anônima (Closure)
<?php Funções anônimas, também
conhecidas como closures,
permitem a criação de funções que
$x = function ($txt) { não tem o nome especificado.

echo("Hello $txt !"); Elas são mais úteis como o valor de


}; parâmetros callback, mas podem
tem vários outros usos.

Vale apenas salientar que toda


$x('World');
função anônima atribuída a uma
$x('PHP'); variável termina com ponto e
vírgula.
Função Anônima (“use”)
<?php

$total = 40; O termo “use” permite


a utilização de
$soma = function ($x) use ($total) { variáveis externas
echo $x+$total;
};
dentro do escopo de
uma closure.
$soma(50);
Função Anônima como parâmetro
<?php

function add($x,$y){
return $x+$y();
}

echo add (3, function(){return 5;} );


Função Anônima como parâmetro
<?php

function teste_closure(callable $a) {


$b = 20;
return $a($b);
}

teste_closure(function($x){
echo($x+10);
});
Função Anônima como parâmetro (com iteração de coleção)
<?php

function calculaImposto(callable $formula){


$impostos = [10,22,34,46,58];

for($i = 0; $i < count($impostos); $i++){


$impostos[$i] = $formula($impostos[$i]);
}
return $impostos;
}

$resultado = calculaImposto(function($valor){
return $valor * 0.1;
});
Constantes
<?php Diferente das variáveis, o valor de um
constante nunca muda e acessamos seu
valor sem o uso do cifrão.
define("MINHA_CONSTANTE", "nunca vai mudar");
Para definir uma constante utilizamos a
define("OUTRA_CONSTANTE", "não importa o case", true); função define, onde o primeiro parâmetro
define("PI", 3.141592); será um string com o nome da constante,
o segundo parâmetro será o valor da
constante e por último podemos definir
echo MINHA_CONSTANTE; se a constante será insensível ao case,
echo outra_constante; isto é, se a constante pode ser chamada
através de letras maiúsculas ou
echo PI; minúsculas independente de como foi
definido.
Date e time
<?php
//definindo TimeZone
date_default_timezone_set('America/Sao_Paulo');

//data Função date permite recuperar data (e hora) em


diversos formatos.
echo date("d");
echo date("d/m/y");

//hora
echo date("h:i:s");
echo date("d/m/y h:i:s"); //combinando data e hora
PHP Array
● Um array em PHP é na verdade um mapa ordenado. Um mapa é um tipo
que associa valores a chaves.
● Esse tipo é otimizado para vários usos diferentes; ele pode ser tratado como
uma matriz, lista (vetor), tabela de hash (uma implementação de um mapa),
dicionário, coleção, pilha, fila e provavelmente mais.
● Como os valores de array podem ser outros arrays, árvores e arrays
multidimensionais também são possíveis.
● Pode crescer dinamicamente e ser iterado em diferentes direções.
Array (sintaxe básica)
<?php
//No primeiro exemplo é feito utilizando a sintaxe tradicional do php até 5.3
$array = array("maria", "joão", 2, 3.5);
/*A partir do php 5.4 é possível utilizar esta sintaxe simplificada conforme o
segundo exemplo*/
$array = ["maria", "joão", 2, 3.5 ];

0 1 2 3

"maria" "joão" 2 3.5


Array (chaves)
<?php

//definindo manualmente as chaves


$array = [ 1=>"maria", 2=>"joão", 'valor'=>2 , null => 3.5 ];

echo $array[1]; 1 2 'valor' null


echo $array[2];
echo $array['valor'];
echo $array[null]; "maria" "joão" 2 3.5

//sem definição das chaves


$array2 = [ 'maria', 'joao' ]; 0 1

echo $array2[0]; "maria" "joão"


echo $array2[1];
Arrays Multidimensionais
<?php
0 1 2
$shop = [
["camisa", 9.25 , 15],
["short", 19.75 , 25], 0 1 2 0 1 2 0 1 2

["tênis", 89.15 , 7] camisa 9.25 15 short 19.75 25 tênis 89.15 7

];

<?php
echo $shop[0][0]." custa".$shop[0][1]." e existem ".$shop[0][2]." em estoque";
echo $shop[1][0]." custa ".$shop[1][1]." e existem ".$shop[1][2]."em estoque";
Arrays (Multidimensionais e Associativos)
<?php
$shop = [
[ 0 1 2
"Produto" => "camisa",
"Preco" => 9.25,
"Quantidade" => 15 Produto Preco Qua Produto Preco Qua Produto Preco Qua
], ntida ntida ntid
de de ade
[
"Produto" => "short", camisa 9.25 15 short 19.75 25 tênis 89.15 7
"Preco" => 19.75,
"Quantidade" => 25,
],
[
"Produto" => "tênis",
"Preco" => 89.15,
"Quantidade" => 7
] echo $shop[0]['Produto'];
];
Iteração/loop de Arrays (for)
<?php

$array = ["Brasil","Argentina","Bolívia","Venezuela"];

for ($i = 0; $i < count($array); $i++) {


print $array[$i];
}
Iteração de Arrays (foreach)
<?php

$array = ["Brasil","Argentina","Bolívia","Venezuela"];

foreach ($array as $pais) {


print $pais;
}
Iteração de Array (foreach chave - valor)
<?php

$array = [ 10 => "Brasil", 20 => "Argentina", 30 => "Bolívia", 99 => "Venezuela"];

foreach ($array as $key => $pais) {


print "$key - $pais";
}
Iteração de Arrays Multidimensionais
<?php

$pessoas = [
["nome" => "João", "cpf" => 123],
["nome" => "Maria", "cpf" => 456]
];

foreach ($pessoas as $pessoa) {


print "nome: ".$pessoa["nome"];
}
Iteração de Arrays Multidimensionais
<?php
$turmas = [
["nome" => "PHP", "alunos" => [
"João", "Maria", "Lucas"]],
["nome" => "BD", "alunos" => [
"Pedro", "Thiago", "João"]]
];

0 1

nome alunos nome alunos

"João" 0 1 2 "João" 0 1 2

"João" "Maria" "Lucas" "João" "Maria" "Lucas"


Iteração de Arrays Multidimensionais
<?php

foreach ($turmas as $turma) {


print "nome: ". $turma["nome"]."</ br>";
print "alunos:";
foreach($turma["alunos"] as $aluno){
print $aluno."</ br>";
}
}
Debug (print_r, var_dump, var_export)
<?php

$var1 = [ '', false, 42, ['42'] ];

print_r($var1);

var_dump($var1);

var_export($var1);
print_r, var_dump, var_export
print_r() var_dump() var_export()
Array array(4) { array (
( [0]=> 0 => '',
[0] => string(0) "" 1 => false,
[1] => [1]=> 2 => 42,
[2] => 42 bool(false) 3 =>
[3] => Array [2]=> array (
( int(42) 0 => '42',
[0] => 42 [3]=> ),
) array(1) { )
[0]=>
) string(2) "42"
}
}
Ordenação de Arrays
$carros = ["Chevete", "BMW", "Ferrari"];

● Ordem crescente (sort):


sort($carros);

● Ordem descrecente (rsort):


rsort($carros);
Ordenação de Arrays Associativos
$pessoas = ["Mateus"=>"35", "Marcos"=>"37", "Lucas"=>"43"];

● Ordem crescente “valor” (sort):


asort($pessoas);

● Ordem descrecente “valor” (rsort):


arsort($pessoas);
Ordenação de Arrays Associativos
$pessoas = ["Mateus"=>"35", "Marcos"=>"37", "Lucas"=>"43"];

● Ordem crescente “chave” (sort):


ksort($pessoas);

● Ordem descrecente “chave” (rsort):


krsort($pessoas);
Array para String (implode)
<?php

$array = ['uva', 'pera', 'abacate'];


$texto = implode(",", $array);

echo $texto; // uva,pera,abacate


String para Array (explode)
<?php

$texto = "uva pera abacate";


$array = explode(" ", $texto);

echo $array[0]; // uva


echo $array[1]; // pera
Checagem de valor no Array (in_array)
<?php

$frutas = ["uva", "pera", "abacaxi", "laranja"];

if (in_array("uva", $frutas)) {
echo "Tem uva !";
}
Checagem de chave no Array (array_key_exists)
<?php

$frutas = ["uva" => 10.99, "manga" => 4.00];

if (array_key_exists("uva", $frutas)) {
echo "a chave uva se encontra no array !";
}
Executar uma função em cada elemento (array_map)
<?php
$array = [
'PHP',
'Arrays',
$y = array_map(function ($x){
'Funções',
return "#".$x;
];
}, $array);
function hashtag($x){
return "#".$x; print_r($y);
}

print_r(array_map('hashtag', $array));
Filtrar elementos do array por condição (array_filter)

<?php

$alunos = [
['nome' => 'João', 'nota' => 8],
['nome' => 'Maria', 'nota' => 4.5],
['nome' => 'Thiago', 'nota' => 7]
];
$alunosAprovados = array_filter($alunos, function($aluno) {
return $aluno['nota'] >= 7;
});
var_dump($alunosAprovados);
Variáveis para array (compact)
<?php

$nome = "João";
$cpf = "123";
$rg = "8888";
$filhos = ["Maria", "Thiago"];

$result = compact("nome", "cpf", "rg", "filhos");


print_r($result);
Array para variáveis (list)
<?php

$info = ['Camiseta', 'Azul', 30.65];

// Listando todas as variáveis


list($produto, $modelo, $preco) = $info;

echo "A $produto $modelo custa $preco.\n";


Array collumn (recuperar dados por key)
<?php
$nomes = array_column($pessoas, 'nome');
$pessoas = [
print_r($nomes);
[
'id' => 1,
'nome' => 'João',
'idade' => 34,
],
[ 0 1 2
'id' => 2,
'nome' => 'Maria', “João” “Maria” “Lucas”
'idade' => 22,
],
[
'id' => 3,
'nome' => 'Lucas',
'idade' => 60,
]
];
Array collumn (recuperar dados por key com index)
<?php
$pessoas = [ $nomes = array_column($pessoas, 'nome', ‘id’);
[
'id' => 6789,
print_r($nomes);
'nome' => 'João',
'idade' => 34,
],
[ 6789 7089 3000
'id' => 7089,
'nome' => 'Maria', “João” “Maria” “Lucas”
'idade' => 22,
],
[
'id' => 3000,
'nome' => 'Lucas',
'idade' => 60,
]
];
Array como Pilha (array_push & array_pop)
//2
//3
<?php

$alunos = ["Maria", "João"]; //1


Lucas Lucas
X
array_push($alunos,"Carlos", "Lucas"); //2
print_r($alunos); //1
Carlos Carlos
array_pop($alunos); //3
print_r($alunos);
João João João

Maria Maria Maria


Array como Fila (array_shift)
<?php

//1
$alunos = ["Maria", "João"];
Maria João

array_push($alunos,"Carlos", "Lucas");
print_r($alunos);
//2
array_shift($alunos); Maria João Carlos Lucas
print_r($alunos);

//3
Maria João Carlos Lucas
PHP OO
● A programação orientada a objetos (POO) é um paradigma baseado no
conceito de "objetos", que podem conter dados, na forma de campos
(atributos/propriedades) e instruções de código, na forma de funções
(métodos).
● Consolidado no PHP 5, os recursos de Orientação a Objetos suportados pela
linguagem estão a inclusão de visibilidade, classes e métodos abstratos e
final, métodos mágicos, interfaces, clonagem e type hint.
● O PHP trata objetos da mesma maneira que referências ou manipuladores,
onde cada variável contém uma referência a um objeto ao invés de uma
cópia de todo o objeto.
Classe
● nome Pessoa

● atributos
● métodos
+ nome
+ sobrenome
+ dataNascimento
+ cpf

+ nomeCompleto()
+ idade()
Classe PHP
<?php Pessoa
class Pessoa {

public $nome;
+ nome
public $sobrenome; + sobrenome
public $dataNascimento; + dataNascimento
public $cpf; + cpf

public function nomeCompleto(){

return $this->nome." ".$this->sobrenome; + nomeCompleto()

}
Instanciando (new)
<?php
#1: Pessoa
class Pessoa { nome: null
cpf: null
public $cpf;
public $nome;

} $pessoa

$pessoa = new Pessoa();


Object Operator (arrow) “->”
<?php

class Pessoa {

public $cpf;
public $nome;
}

$pessoa = new Pessoa();

$pessoa->nome = 'maria';
$pessoa->cpf = '123';
Objetos (Instâncias)
#2: Pessoa
<?php
class Pessoa { #1: Pessoa nome: joão
public $cpf; cpf: 567
public $nome; nome: maria
} cpf: 123

$x = new Pessoa();
$y = new Pessoa();
$y
$x->nome = 'maria'; $x $z
$x->cpf = '123';

$y->nome = 'joão'; var_dump($x);


$y->cpf = '345'; var_dump($y);
var_dump($z);
$z = $y;
$z->cpf = '567';
clone

<?php

class Aluno {
$b = clone $a;
public $nome;
$b->nome = 'Juliana';
public $turma;
}
var_dump($a);
$a = new Aluno() ;
var_dump($b);
$a->nome = 'Maria';
$a->turma = 'PHP';
Métodos
<?php Pessoa

class Pessoa {

public $cpf; + cpf


public $nome; + nome

function exemplo() {
return 'olá mundooo!';
}
} + exemplo()

$pessoa = new Pessoa();

echo $pessoa->exemplo();
Referência ao Objeto ($this)
<?php

class Pessoa {
$pessoa = new Pessoa();
$pessoa->nome = 'João';
public $cpf;
$pessoa->sobreNome = 'da Silva';
public $nome;
public $sobreNome;
echo $pessoa->nomeCompleto();
function nomeCompleto(){
return $this->nome." ".$this->sobreNome;
}
}
Método Construtor (__construct)
<?php
class Pessoa {

public $cpf; $pessoa = new Pessoa();


public $nome; $pessoa->nome = 'maria';
$pessoa->cpf = '123';
function __construct() { print $pessoa->nome;
echo "nova pessoa";
}
}
Método Construtor com parâmetros (__construct)
<?php

class Pessoa {

public $cpf;
$pessoa = new Pessoa('123','João');
public $nome;
echo $pessoa->cpf;
function __construct($cpf, $nome){ echo $pessoa->nome;
$this->cpf = $cpf;
$this->nome = $nome;
}
}
Método Destrutor (__destruct)
<?php
class Pessoa {

public $cpf;
public $nome; $pessoa = new Pessoa();
$pessoa->nome = 'maria';
function __construct() { $pessoa->cpf = '123';
echo "nova pessoa";
}
print $pessoa->nome;

function __destruct() {
echo "objeto removido";
}
}
Herança (extends)
Pessoa
<?php
class Pessoa { + nome
public $nome;
}

class PessoaFisica extends Pessoa {


public $cpf;
} PessoaFisica
+ cpf

$a = new PessoaFisica() ;
$a->nome = 'Maria';
$a->cpf = 123;

var_dump($a);
Method Overriding e Parent
<?php A substituição de métodos (method overriding), em é
class Pai { um recurso que permite que uma subclasse ou classe
filha forneça uma implementação específica de um
public function falar() {
método que já é fornecido por uma de suas
echo 'sou seu pai! ';
} superclasses ou classes pai.

} A implementação na subclasse substitui (override) a


class Filho extends Pai{
implementação da superclasse, fornecendo um método
public function falar() { que possui o mesmo nome, mesmos parâmetros ou
parent::falar(); assinatura, e o mesmo tipo de retorno que o método na
echo 'nãooooooooo'; classe pai.
}

} Apesar do recurso de overriding, ainda é possível que


a classe filha “execute” um método da classe pai
$filho1 = new Filho(); através do recurso parent.
echo $filho1->falar();
PHP OO (visibilidade)
public: torna uma variável / método disponível
de qualquer lugar, outras classes e instâncias
do objeto.

protected: escopo quando você quiser fazer o


seu / função variável visível em todas as
classes que estendem a classe atual, incluindo
a classe pai.

private: escopo quando você quer que seu /


função variável a ser visível apenas em sua
própria classe.

http://stackoverflow.com/questions/4361553/php-public-private-protected
Public (Visibilidade)
● Mesma classe que foi declarada
<?php ● Classes que herdam
class Pai {
public $publico; ● As classes que herdam a classe
protected $protegido; declarada acima.
private $privado;
} ● Quaisquer elementos estrangeiros
fora dessa classe também podem
class Filho extends Pai {}
acessar estes elementos
$pai = new Pai();
$filho = new Filho();
$pai->publico = 'abc';
$filho->publico = 123;

var_dump($pai);
var_dump($filho);
Protected (Visibilidade)
<?php
class Pai {
public $publico;
Quando você declara um método
protected $protegido; (função) ou uma propriedade (atributo)
private $privado;
} como protegido, esses métodos e
class Filho extends Pai { propriedades podem ser acessados por
public function alteraProtegido($valor){ a mesma classe que declarou isso.
$this->protegido = $valor;
}
} As classes que herdam a classe
$pai = new Pai(); declarada acima. Os membros de
$filho = new Filho();
outsiders não podem acessar essas
//$pai->protegido = 'xyz'; //Erro !
//$filho->protegido = 456; //Erro !
variáveis. "Outsiders" no sentido de que
eles não são instâncias de objetos da
$filho->alteraProtegido(456);
própria classe declarada.
var_dump($filho);
Private (Visibilidade)
<?php
class Pai {
public $publico;
protected $protegido;
private $privado;

public function exibePrivado(){ Quando você declara um método


return $this->privado;
} (função) ou uma propriedade (variável)
public function alteraPrivado($valor){ como privada, esses métodos e
$this->privado = $valor;
} propriedades podem ser acessados por
} a mesma classe que declarou isso.
class Filho extends Pai {}

$filho = new Filho();


$filho->alteraPrivado(789);

echo $filho->exibePrivado();
Atributos Estáticos
<?php Teste
class Teste {
+ status
+ nome
public static $status = 'online';
public $nome;
}
Na programação orientada a objetos, atributo estático
é conhecido como "variável de classe". Um atributo
$t1 = new Teste(); estático de uma determinada classe tem seus valores
$t1->nome = 'Teste 1'; compartilhados em todas as instâncias (objetos) ou
Teste::$status = 'offline'; diretamente na classe utilizando o operador ::

var_dump($t1);
var_dump(Teste::$status);
Métodos Estáticos
<?php Util

class Util {
+ hoje()

public static function hoje() {


De maneira similar, um método estático é
return date('d/m/y'); “procedimento da classe”. Um método estático de uma
} determinada classe pode ser acessado em todas as
} instâncias (objetos) ou diretamente na classe
utilizando o operador ::

É válido salientar que é proibido utilizar o $this dentro


echo Util::hoje(); (no contexto) de um método estático.
$util = new Util();
echo $util->hoje();
Class Constants
<?php

class Matematica echo Matematica::PI . "\n";


{
const PI = 3.14; $mat = new Matematica();
$mat->valorDePi();
function valorDePi() {
echo self::PI . "\n"; Similar as constantes usando o define(), o
} valor de uma constante nunca pode ser
alterado.
} O acesso é similar aos atributos estáticos,
utilizando o :: porém sem o $.
Class Constants (visibilidade)
<?php

class Matematica
{
private const PI = 3.14; //disponível a partir do PHP 7.1

function valorDePi() {
echo self::PI . "\n";
}
}

//echo Matematica::PI . "\n"; erro !

$mat = new Matematica();


$mat->valorDePi();
Final Method
<?php
class ClasseBase {
public function teste() {
echo "teste";
O PHP 5 introduziu a palavra-chave
} final, que previne que classes filhas
final public function maisTeste() { sobrescrevam um método que esteja
echo "teste"; prefixado em sua definição com a
} palavra final.
}

class ClasseFilha extends ClasseBase {

//erro:
public function maisTeste() {
echo "mais teste";
}
Final Class
<?php

class Pessoa {
public $nome;
}
Se a própria classe estiver
final class Professor extends Pessoa { definida como final, ela
public $matricula; não pode ser estendida.
}

//erro:
class ProfessorSubstituto extends Professor {}
Classe Abstrata
Pessoa
<?php
abstract class Pessoa { + nome
public $nome;
}

class PessoaFisica extends Pessoa {


public $cpf;
}
PessoaFisica PessoaJuridica
class PessoaJuridica extends Pessoa { + cpf + cnpj
public $cnpj;
}

$pf = new PessoaFisica();


$pj = new PessoaJuridica();
//$p = new Pessoa(); //erro !
Método Abstrato
<?php

abstract class Pessoa{


public $nome;
abstract function exibirDocumento(); $pf = new PessoaFisica();
} $pf->cpf = 123;
echo $pf->exibirDocumento();
class PessoaFisica extends Pessoa {
public $cpf;

//Métodos abstratos precisam ser implementados nas classes filhas


public function exibirDocumento(){
Métodos abstratos precisam ser
return $this->cpf; implementados nas classes filhas.
}
}
Interface
● Interfaces permitem a criação de códigos que especificam quais métodos
uma classe deve implementar, sem definir como esses métodos serão
tratados.
● Interfaces permitem também que classes de diferentes hierarquias possam
ter comportamentos similares.
● Interfaces são definidas da mesma forma que classes, mas com a
palavra-chave interface substituindo class e com nenhum dos métodos
tendo seu conteúdo definido.
● Todos os métodos declarados em uma interface devem ser públicos, essa é a
natureza de uma interface.
● Interfaces PHP suportam herança múltipla e constantes
Interface
<?php

interface Formatador {
<<interface>>
public function formatar(); Fomatador

}
+ formatar()
class Html implements Formatador {

//erro: é obrigatório implementar o método formatar !


//obs.: exceção se a classe Html fosse abstrata

}
Interface (herança múltipla)

<?php

interface Paginador{
public function paginar();
class TabelaPessoa implements ArvorePaginavel
}
{
//deverá implementar dois métodos
interface Arvore{ }
public function getNoRaiz();
}

interface ArvorePaginavel extends Paginador, Arvore {

}
Interface (usando typehint)
<?php

interface Sepultavel {
public function calcularValorDoCaixao(float $valor): float;
} Neste exemplo, classes de
class Felino implements Sepultavel { diferentes Taxonomias
public $peso; implementam uma mesma
public function calcularValorDoCaixao(float $valor): float{
return $valor * ($this->peso * 0.3); Interface
}
}

class Pessoa implements Sepultavel {


public $altura;
public $peso;
public $circunferenciaAbdominal;
public function calcularValorDoCaixao(float $valor): float{
return $valor * (($this->altura * $this->peso) / 2 +
$this->circunferenciaAbdominal);
}
}
Interface (usando typehint - parte 2)

<?php
Um método de uma classe (ou uma
class Sepultamento { função) pode usar o type int com o
nome de uma interface para que
public $cotacao = '4.05'; seja garantido que os
comportamentos de um objeto (que
public function enterrar(Sepultavel $sepultavel): float{ implementam esta interface)
return possam ser evocados.
$sepultavel->calcularValorDoCaixao($this->cotacao);
}

}
$gato = new Felino();
$gato->peso = 3.4;
$s = new Sepultamento();
echo $s->enterrar($gato);
Trait
● Traits são mecanismos para reutilização de código em linguagens de
herança únicas, como PHP.

● Uma Trait destina-se a reduzir algumas limitações de herança única,


permitindo que um desenvolvedor reutilizar conjuntos de métodos livremente
em várias classes independentes que podem viver em diferentes taxonomias
de classes.

● Não é possível instanciar um Trait por conta própria.

● É uma adição à herança tradicional e permite a composição horizontal do


comportamento, isto é, a aplicação de membros de classe sem exigir
herança.
Trait
<?php
trait MinhaTrait {
public $nome = 'trait';
public function ola() { $x = new Teste();
return 'ola '.$this->nome."!!!"; echo $x->nome;
} echo $x->ola();
}
$y = new MinhaTrait(); //Erro! Não é possível instanciar uma Trait
class Teste {
use MinhaTrait;
}
Trait - (múltiplo uso)
<?php
class Smartphone {
trait Telefone { use Telefone, Camera;
public function ligar() { public function videoChamada() {
echo 'alo…'; echo $this->filmar().$this->ligar();
} }
} }

trait Camera { $o = new Smartphone();


public function filmar() { $o->ligar();
echo 'gravando…'; $o->filmar();
} $o->videoChamada();
}
Trait (precedência/instead of)
<?php

trait Video {
public function tag() {
class Media {
echo '<video> ';
}
use Audio, Video {
}
Video::tag insteadof Audio;
} //sem esta resolução ocorrerá um Fatal Error.
}
trait Audio {
public function tag() {
$media = new Media();
echo '<audio>';
$media->tag(); //resultado: <video>
}
}
Trait (alias “as”)
<?php

trait Video { class Media {


public function tag() { use Audio, Video {
echo '<video> '; Video::tag insteadof Audio;
} Audio::tag as tagAudio;
}
}
}
trait Audio {
public function tag() { $media = new Media();
echo '<audio>';
}
$media->tag();
}
$media->tagAudio();
Trait (sintaxe para resolução de conflitos)
● Precedência:
○ ClasseA::metodo insteadof ClasseB
● Alias:
○ ClasseA::metodo as metodoN2
Classe Anônima
<?php

$pessoa = new class {


var_dump($pessoa);
public $nome = 'Maria';
echo $pessoa->nome;
public $cpf = '754';
echo $pessoa->cpf;
echo $pessoa->getNome();
public function getNome(){
return strtoupper($this->nome);
}
};
Classe Anônima (novas instâncias)

<?php

$pessoa = new class{


echo $pessoa->oi();
public $nome = 'Fulano'; $p1 = new $pessoa();
$p1->nome = 'Maria';
public function oi(){ echo $p1->oi();
return "Oi {$this->nome} !";
}
};
Classe Anônima (via function)
<?php

function pessoa_oo() { $pessoa = pessoa_oo();


echo $pessoa->nome;
return new class {
public $nome = 'Maria'; echo $pessoa->cpf;
public $cpf = '754'; echo $pessoa->getNome();
public function getNome(){
return strtoupper($this->nome);
}

};
}
Associação entre objetos
Na programação orientada a objetos, a associação define um relacionamento entre classes de objetos
que permite que uma instância de objeto faça com que outra execute uma ação em seu nome. Essa
relação é estrutural, porque especifica que objetos de um tipo estão conectados a objetos de outro e não
representam comportamento.

Pessoa Veiculo

possui 0..1 + placa


+ nome
+ modelo
Associação entre objetos
<?php
$p1 = new Pessoa();
$p1->nome = 'Maria';
class Pessoa { $p1->veiculo = new Veiculo();
public $nome;
public $veiculo;
} $p1->veiculo->placa = 'ABC123';
$p1->veiculo->modelo = 'Tesla X1';
class Veiculo{
public $placa; var_dump($p1);
public $modelo;
}
Composição
● Composição é um tipo de associação onde o objeto composto é o único
responsável pela disposição das partes componentes.
● O relacionamento entre o composto e o componente é um relacionamento
forte "tem um", pois o objeto composto apropria-se do componente.
● Isso significa que o composto é responsável pela criação e destruição das
partes componentes. Um objeto só pode fazer parte de um composto. Se o
objeto composto for destruído, todas as partes componentes devem ser
destruídas.
● A composição impõe o encapsulamento, pois as partes do componente
geralmente são membros do objeto composto.
● A composição é caracterizada na UML pelo uso do losango preenchido.
Composição
<?php
class Assunto {
public $texto;
}
class Corpo {
public $texto;
public $formato;
}
class Destinatario {
public $nome;
}
class Email {
private $assunto;
private $corpo;
private $destinatario;
public function __construct() {
$this->assunto = new Assunto();
$this->corpo = new Corpo();
$this->destinatario = new Destinatario();
}
}
Composição (Versão com classes anônimas)
<?php

class Email {
private $assunto;
private $corpo;
private $destinatario; public function setAssunto($texto){
$this->assunto->texto = $texto;
public function __construct() {
}
$this->assunto = new class {
public $texto; //implementar os próximos getters & setters
}; }
$this->corpo = new class {
public $texto; $email = new Email();
public $formato; $email->setAssunto('Curso de PHP');
};
$this->destinatario = new class {
public $nome;
};
}
Agregação
● Agregação é um tipo de associação que especifica um relacionamento
de todo / parte entre a parte agregada (todo) e o componente.
● Esse relacionamento entre o agregado e o componente é um
relacionamento "tem-um" fraco, pois o componente pode sobreviver ao
objeto agregado.
● O objeto componente pode ser acessado através de outros objetos
sem passar pelo objeto agregado. O objeto agregado não participa do
ciclo de vida do objeto de componente, o que significa que o objeto de
componente pode sobreviver ao objeto agregado. O estado do objeto
componente ainda faz parte do objeto agregado.
● A agregação é caracterizada na UML pelo uso do losango sem vazio.
Agregação Motor

<?php
abstract class Motor {}
class MotorV8 extends Motor { MotorV8

}
class Carro {
private $motor;
public function __construct(Motor $motor) {
$this->motor = $motor;
}
} Carro
$motorV8 = new MotorV8();
$carro1 = new Carro($motorV8);
Associação (1..*)

Uma associação um-para-muitos


(ou têm muitos) é um tipo de
associação que estabelece uma
vinculação onde uma instância da Editora Livro
classe do lado esquerdo tem zero publicacoes
ou mais instâncias de outra classe. + nome 1..* + titulo
+ website + edicao
Para representar esta
multiplicidade, podemos utilizar
uma coleção (ex.: array) para
“armazenar” / “intermediar” esta
relação.
Associação (1..*)

<?php
$livro1 = new Livro();
class Livro { $livro1->titulo = 'Aventuras do PHP';
public $titulo;
public $edicao; $livro2 = new Livro();
} $livro2->titulo = 'A vida';

class Editora { $editora1 = new Editora();


public $nome; $editora1->nome = 'Editora XPTO';
public $website; $editora1->publicacoes[] = $livro1;
public $publicacoes = []; $editora1->publicacoes[] = $livro2;
}
Associação (1..*)

0 1

Editora1

nome: Editora XPTO


website: null Livro1 Livro2
publicacoes:
titulo: Aventuras d.. titulo: A vida
edicao: null edicao: null
Classe Associativa
Uma classe associativa é uma classe que faz parte de um
relacionamento de associação entre duas outras classes.

É possível “anexar” uma classe associativa a um


relacionamento para fornecer informações adicionais
sobre o relacionamento. Uma classe de associação é
idêntica a outras classes e pode conter operações,
atributos e outras associações.

Por exemplo, um Ator pode atuar em muitos Filmes e um


Filme pode contar com a atuação de vários Atores. Em
cada Filme, o Ator pode atuar com um papel distinto. Por
isso, neste caso, uma classe associativa chamada
Atuação pode definir melhor esta associação fornecendo
informação adicional do papel que o Ator desempenhou
em um determinado Filme.

Como a figura a seguir ilustra, uma classe de associação é


conectada a uma associação por uma linha pontilhada.
Classe Associativa
<?php

class Ator {
public $nome;
public $atuacoes = []; $ator1 = new Ator();
} $ator1->nome = 'José da Silva';
class Atuacao {
public $ator; $ator2 = new Ator();
public $filme; $ator2->nome = 'Maria das Dores';
public $papel;
$filme1 = new Filme();
public function __construct(Ator $ator, Filme $filme, string $papel){ $filme1->titulo = 'Aventuras do barulho';
$this->ator = $ator;
$this->filme = $filme;
$this->papel = $papel; $filme1->atuacoes[] =
} new Atuacao($ator1, $filme1, 'Protagonista');
} $filme1->atuacoes[] =
new Atuacao($ator2, $filme1, 'Coadjuvante');
class Filme {
public $titulo;
public $atuacoes = [];
}
Autoload (Carregamento automático de Classes)
● Quando trabalhamos com mais de uma Classe, Interface e/ou Trait, é
interessante utilizar algum recurso que possibilite o carregamento
dinâmico/automático das estruturas em seus respectivos arquivos *.php.
● O PHP possui duas funções de registro automático: o __autoload() e o
spl_autoload_register()
● O __autoload() foi depreciado à partir do PHP 7.2.
● O spl_autoload_register() permite que vários carregadores automáticos sejam
registrados, que serão executados por sua vez até que uma classe, interface ou
trait correspondente seja localizada e carregada, ou até que todas as opções de
carregamento automático tenham sido esgotadas. Isso significa que, se você
estiver usando algum framework ou outras bibliotecas que implementam seus
próprios carregadores automáticos, não é necessário se preocupar com a
possibilidade de conflitos.
Autoload (spl_autoload_register)

classes\Pessoa.php exemplo.php
<?php <?php

class Pessoa { function meu_autoloader($class) {


public $nome; include 'classes/' . $class . '.php';
} }

spl_autoload_register('meu_autoloader');
classes\Veiculo.php
<?php $pessoa1 = new Pessoa();
$veiculo1 = new Veiculo();
class Veiculo {
public $placa;
}
Reflection
● Permite introspecção no código Orientado a objeto.
● O Reflection auxilia os desenvolvedores a criar bibliotecas genéricas de
software para exibir dados, processar diferentes formatos de dados, realizar
serialização, agrupar dados e muito mais.
● O Reflection pode ser usado para observar e modificar a execução do
programa em tempo de execução.
● Em linguagens de programação orientada a objeto, como PHP, o Reflection
permite a inspeção de classes, interfaces, campos e métodos em tempo de
execução sem conhecer os nomes das interfaces, campos, métodos em
tempo de execução.
● Também permite a instanciação de novos objetos e a invocação de métodos
de forma dinâmica.
Reflection (class)
<?php

<?php
class Aluno {
public $nome;
class Animal {} protected $endereco;
class Felino extends Animal {} private $telefone;
class Gato extends Felino {} }

$aluno1 = new Aluno();


$class = new ReflectionClass(Gato::class);
$reflect = new ReflectionClass($aluno1);
$props = $reflect->getProperties(ReflectionProperty::IS_PUBLIC |
while ($parent = $class->getParentClass()) { ReflectionProperty::IS_PROTECTED);
$parents[] = $parent->getName();
$class = $parent; foreach ($props as $prop) {
print $prop->getName() . "\n";
}
}

echo "Parents: " . implode(", ", $parents); var_dump($props);


Reflection (alterando visibilidade)
<?php
class Teste {
private $propriedade = 'ola'; Com o uso do Reflection é possível
“modificar” a visibilidade de um atributo
private function dizSegredo(){ ou método em tempo de execução
echo $this->propriedade.'! 1234'; através do setAcessible(true);
}
}
$class = new ReflectionClass("Teste"); Entretanto, o acesso aos
$property = $class->getProperty("propriedade"); valores/retornos precisam ser feitos
$property->setAccessible(true); através dos métodos getValue() ou
invoke().
$teste1 = new Teste();
//echo $teste1->propriedade; // Não funciona aqui No caso dos atributos é possível utilizar o
echo $property->getValue($teste1); setValue() para modificar o valor de um
$property->setValue($teste1, 'legal'); atributo também.
$method = new ReflectionMethod("Teste", 'dizSegredo');
$method->setAccessible(true);
echo $method->invoke($teste1);
Reflection (gerar instâncias e invocar métodos)

<?php

class Pessoa { //com reflection


$reflector = new ReflectionClass('Pessoa');
public function digaOi(){ $instancia = $reflector->newInstance();
return 'oi!'; $metodo = $reflector->getMethod('digaOi');
} echo $metodo->invoke($instancia);
}
Reflection (recuperar comentários)
<?php
/**
* Esta é uma classe de exemplo
*/
class Exemplo {
/**
* Esta é uma função de exemplo Com Reflection também é possível recuperar
*/ comentários das classes e métodos através do
public function fazNada(){} getDocComment().
}

$reflector = new ReflectionClass(Exemplo::class);

echo $reflector->getDocComment();
echo
$reflector->getMethod('fazNada')->getDocComment();
Namespace
● Os namespaces são basicamente uma maneira de organizar suas classes
PHP e evitar conflitos de código.
● Usamos a palavra reservada namespace
● Namespace não estão relacionados diretamente com a estrutura de
diretórios.
● Namespace usam “backslash” (\) como separador
● É possível referenciar a classe usando o use para evitar escrever o
namespace completo novamente
● Apelidos e Conflitos podem ser resolvidos com o uso do as
Namespace
Pessoa.php exemplo.php

<?php <?php

namespace Modelo; require "Pessoa.php";

class Pessoa {} // não funciona !


//$pessoa1 = new Pessoa();
$pessoa1 = new Modelo\Pessoa();
Namespace (modelos homônimos)
\Modelo\Literatura\Manga.php
<?php

namespace Modelo\Literatura; exemplo.php


class Manga { <?php
public $autor;
public $editora;
} require "Modelo\Fruta\Manga.php";
\Modelo\Fruta\Manga.php
require "Modelo\Literatura\Manga.php";
<?php
$manga1 = new Modelo\Literatura\Manga();
namespace Modelo\Fruta;
$manga2 = new Modelo\Fruta\Manga();
class Manga {

public $vitaminas = ['A','C'];

}
Namespace (use)

<?php

require "Modelo\Fruta\Manga.php";
Com a palavra reservada use, é
possível invocar o nome completo de
use Modelo\Fruta\Manga; uma classe para que a mesma possa
ser utilizada sem a necessidade do
namespace após o use.
$manga2 = new Manga();
Namespace (use + as)

<?php

require "Modelo\Fruta\Manga.php";

use Modelo\Fruta\Manga as FrutaManga;

$manga2 = new FrutaManga();


Namespace (resolução de conflitos)

<?php

require "Modelo\Fruta\Manga.php";
require "Modelo\Literatura\Manga.php";

use Modelo\Fruta\Manga as FrutaManga;


use Modelo\Literatura\Manga;

$manga1 = new Manga();


$manga2 = new FrutaManga();
Namespace + Autoloader
<?php

use classes\Pessoa; O nome do namespace (e consonância


use classes\Veiculo; com o nome dos diretórios) pode ser
utilizado para incluir automaticamente as
function meu_autoloader($class) { classes no código.
include_once $class . '.php';
} Isto não exime o desenvolvedor de utilizar
o use ou nome completo da classe (FQN -
spl_autoload_register('meu_autoloader'); Fully Qualified Name).

$pessoa1 = new Pessoa();


$veiculo1 = new Veiculo();
Namespace (Group use PHP >= 7.0)

<?php

use classes\{Pessoa, Veiculo};

function meu_autoloader($class) { A partir do PHP 7, tornou-se possível agrupar


include_once $class . '.php'; classes de um mesmo namespace utilizando a
} sintaxe de group use.

spl_autoload_register('meu_autoloader');

$pessoa1 = new Pessoa();


$veiculo1 = new Veiculo();
Iteração de atributos do Objeto
<?php

class Pessoa {
public $nome = 'Maria da Silva'; //Aqui só é possível iterar os atributos públicos
private $cpf = '123456'; foreach($pessoa as $key => $value) {
protected $idade = 30; print "$key => $value\n";
}
function iterar() { echo "\n";
foreach ($this as $key => $value) {
print "$key => $value\n"; //no método usando o $this é possível iterar todos
} os valores
} $pessoa->iterar();
}
$pessoa = new Pessoa();
Interface Iterator

<<interface>>
● Interface Iterator possui um conjunto abstrato de Iterator
métodos para iteradores externos ou objetos que
podem ser iterados internamente.
+ current ()
+ key()
+ next()
● Quando uma nova classe implementa esta esta + rewind
Interface, suas instâncias tornam-se iteráveis, + valid()

similar ao uso de um array.


<<interface>>
Interface Iterator Iterator

+ current ()
public function next() {
<?php $novo_atual = $this->atual;
+ key()
$this->atual += $this->anterior; + next()
class Fibonacci implements Iterator { $this->anterior = $novo_atual; + rewind
private $anterior = 1; $this->key++; + valid()
private $atual = 0; }
private $key = 0;
public function rewind() {
public function __construct (int $max = 100) { $this->anterior = 1;
$this->max = $max; $this->atual = 0;
} $this->key = 0;
}
public function current() {
return $this->atual; public function valid() {
} if($this->atual > $this->max) Fibonacci
return false;
public function key() { return true;
return $this->key; }
} }
Interface Iterator

$seq = new Fibonacci();


Quando um objeto implementa o Iterator, o
mesmo torna-se passível de ser “iterado”
foreach ($seq as $f) { de forma transparente, similar a um array,
por uma estrutura de laço dinâmica como o
“foreach”, graças aos métodos que
“garantem” o processo da iteração.
echo $f.PHP_EOL;

}
Generator
<?php

function meuGenerator() {

echo "Um".PHP_EOL; Quando uma função contém a palavra reservada


yield 1; yield, o PHP automaticamente interpreta a mesma
echo "Dois".PHP_EOL; como um objeto do tipo Generator.
yield 2;
echo "Três".PHP_EOL; Similar ao uso do Iterator, um generator permite que
yield 3; o objeto possa ser iterado.
}
Além disso, o yield “pausa” o fluxo natural do código
$iterator = meuGenerator(); da função e permite retorna um valor similar ao
return.
$value = $iterator->current();
$value = $iterator->next();
$value = $iterator->next();
Generator (yield from)
<?php function oito() {
yield 8;
function contar10() { }
yield 1;
yield 2; foreach (contar10() as $num) {
yield from [3, 4]; echo "$num ";
yield from new ArrayIterator([5, 6]); }
yield from sete_oito();
yield 9;
yield 10;
}
Com o uso yield from é possível
recuperar os valores de outros
function sete_oito() {
generators, iteradores ou arrays.
yield 7;
yield from oito();
}
Iterator to Array

<?php

$iterator = meuGenerator();
$seq = new Fibonacci();
Com o uso da função
$array_fibonnaci = iterator_to_array($seq); iterator_to_array é possível
$array_generator = iterator_to_array($iterator); converter um objeto iterável para
array.
var_dump($array_fibonnaci);
var_dump($array_generator);
Classe DateTime

<?php Classe DateTime é uma alternativa


O.O. à função date().
$dateTime = new DateTime('2016-12-31'); Ela possui um conjunto de métodos
echo $dateTime->format('Y-m-d H:i:s'); que permitem realizar operações
complexas com datas e horários.
$dateTimeAgora = new DateTime(); Além disso, por sua natureza de
echo $dateTimeAgora->format('Y-m-d H:i:s'); Classe, é possível estender a
mesma e criar classes customizadas
de Data e Hora.
DateTimeZone (Fuso Horário)

<?php

date_default_timezone_set('America/Sao_Paulo'); É possível setar o fuso horário no


PHP através da função
$dateTimeAgora = new DateTime(); date_default_timezone_set()
passando como valor o fuso horário
echo $dateTimeAgora->format('d/m/Y H:i:s'); desejado.

Também é possível determinar o fuso


$dateTime = new DateTime('2016-12-31 12:03:00', horário individualmente no momento
new DateTimeZone('America/Sao_Paulo')); da criação do objeto DateTime
passando uma instância de
echo $dateTime->format('d/m/Y H:i:s'); DateTimeZone
Classe DateTime (createFromFormat)

<?php

$dateBr = DateTime::createFromFormat('d/m/Y', '31/12/2003');


echo $dateBr->format('d/m/Y');

Formato
da data Data no
Formato para formato
exibição
(string)
Classe DateTime (modificando data)
Adicionar um dia Segunda Feira desta semana
<?php <?php

$dateTime = new DateTime('2018-01-31'); $dateTime = new DateTime();


$dateTime->modify('+1 day'); $dateTime->modify('monday this week');
echo $dateTime->format('d/m/Y'); echo $dateTime->format('d/m/Y');

Adicionar dez dias úteis Adicionar um mês e “menos três dias”


<?php <?php

$dateTime = new DateTime(); $dateTime = new DateTime();


$dateTime->modify('+10 weekdays'); $dateTime->modify('+1 month -3 days');
echo $dateTime->format('d/m/Y'); echo $dateTime->format('d/m/Y');
Classe DateTime (diferença entre datas)

<?php

$date1 = new DateTime('2018-08-11 05:02:00');


$date2 = new DateTime('2018-10-13 10:12:34');
$interval = $date1->diff($date2);

echo "Meses: {$interval->m} dias: {$interval->d} horas: {$interval->h} minutos:


{$interval->i} segundos: {$interval->s}";
DateTime (comparação)

<?php

$hoje = new DateTime('today');


$ontem = new DateTime('yesterday'); É possível usar operadores de comparação
var_dump($hoje > $ontem); para comparar datas.
var_dump($hoje < $ontem);
var_dump($hoje == $ontem);
Typed Properties (PHP 7.4 >=)
<?php

class Veiculo {
public string $placa;
public string $modelo; Com o advento das typed properties no PHP 7.4,
} é possível especificar os tipos dos atributos de
uma classe e restringir os valores dos mesmos.
class Pessoa {
public string $nome; O comportamento é similar ao type hint em
public Veiculo $veiculo; parâmetros de métodos (funções) e ambos são
} afetados pelo nível do “strict_types” onde, o PHP
poderá (ou não) converter determinados tipos dos
$pessoa1 = new Pessoa(); valores em tempo de execução para o tipo
$pessoa1->nome = "Maria da Silva"; determinado na declaração na classe.
$veiculo1 = new Veiculo();
$veiculo1->placa = "ABC 123";
$pessoa1->veiculo = 1; //erro !
$pessoa1->veiculo = $veiculo;
StdClass e Type Cast
<?php
//convertendo array para objeto
$array = ['nome'=>'José', 'idade'=>34];
$objeto = (object) $array; A classe nativa do PHP StdClass
var_dump($objeto); (Standard Class) tem o propósito de ser
uma classe para objetos frutos de
//convertendo json para objeto coerções.
$json = '{"nome":"Maria", "idade":45}';
$objeto2 = json_decode($json); Também permite que objetos genéricos
var_dump($objeto2); possam ser criados.

//criando um objeto genérico


$objeto3 = new StdClass();
$objeto3->nome = 'Legal';
$objeto3->vivo = true;
var_dump($objeto3);
Entrada de dados

● Para que um aplicação seja dinâmica, faz-se necessário permitir que os


usuários possam interagir com a mesma através de algum método de input
(entrada) de dados.

● Antes do surgimento dos sistemas operacionais gráficos (GUI), a entrada de


dados era feita através de interface de linha de comando (CLI).

● Com o surgimento da web, os dados são, em sua maioria, imputados através


de formulários HTML.
Entrada de dados (CLI)
cli.php
<?php

echo "Qual é o seu nome? " . PHP_EOL;


$input = fgets(STDIN);
echo "Seja bem vindo(a), $input";
Entrada de Dados (web)
formulario.htm cadastrar.php

<html>
<form action='cadastrar.php'>
<label>Nome:</label>
<input type="text" name="nome"/>
<?php
<label>Email:</label>
var_dump($_REQUEST);
<input type="email" name="email"/>
<input type="submit" value="Cadastrar"/>
</form>
</html>
Formulários e Requisições (Variáveis)
● $_POST: é um array de variáveis com os valores enviados via HTTP POST
como, por exemplo, o utilizado por formulários HTML.
● $_GET: é um array de variáveis com os parâmetros da URL, também
conhecido como “query string”.
● $_REQUEST: por default possui o conteúdo de $_GET, $_POST (e
$_COOKIE também).
● $_FILES: um array com as informações de arquivos enviados via HTTP
POST (utilizar o “multipart/form-data” no enctype do formulário)
Entrada de Dados (GET)
http://localhost/curso/get/index.php?nome=Maria&idade=33

URL campo valor

atribuição separador de
de valor campos

Separador de URL e Query String


Formulário (Array como parâmetro)
sanduba_formulario.php
<!DOCTYPE html>
<html>
<head>
<title>Formulário</title><meta charset="utf-8" /> sanduba.php
</head> <?php
<body>
<form action="sanduba.php" method="post"> foreach($_REQUEST['adicionais'] as $adicional){
echo $adicional."<br/>";
Quais adicionais você deseja?<br />
}
<input type="checkbox" name="adicionais[]" value="queijo" />Queijo<br />
<input type="checkbox" name="adicionais[]" value="bacon" />Bacon<br />
<input type="checkbox" name="adicionais[]" value="ovo" />Ovo<br />
<input type="submit"/>
</form>
</body>
</html>
Formulários (upload - $_FILES e multipart/form-data)
email_com_anexo.php
<!DOCTYPE html>
<html> <?php
<head>
$diretorio = "tmp".DIRECTORY_SEPARATOR;
<title>Formulário com upload</title>
<meta charset="utf-8" /> foreach($_FILES as $arquivo){
</head> $nome = $arquivo['name'];
<body> $conteudo = file_get_contents($arquivo['tmp_name']);
//salvando no disco
<form action="email_com_anexo.php"
file_put_contents($diretorio.$nome, $conteudo);
method="post" enctype="multipart/form-data"> }
Name: <input type="text" name="nome"><br>
E-mail: <input type="email" name="email"><br>
Anexo: <input type="file" name="anexo"><br>
<input type="submit"/>
</form>
</body>
</html>
Cookie
<!DOCTYPE html> Um cookie é um pequeno arquivo que o servidor
<?php incorpora no computador (navegador) do usuário.
$cookie_name = "usuario";
Cada vez que o mesmo computador solicita uma
$cookie_value = "João da Silva";
setcookie($cookie_name, $cookie_value, mktime(24), "/"); página com um navegador, ele também enviará o
?> cookie.
<html>
<body>
Com o PHP, é possível criar e recuperar valores de
<?php
if (!isset($_COOKIE[$cookie_name])) { cookie. O nome do cookie é automaticamente
echo "Cookie (" . $cookie_name . ") sem valor"; atribuído a uma variável com o mesmo nome.
} else {
echo "Cookie '" . $cookie_name . "' com valor!<br>"; A função setcookie() cria o cookie enquanto a
echo "valor atual é: " . $_COOKIE[$cookie_name];
} variável global $_COOKIE acessa os valores.
?>
</body> O cookie pode ser substituído por soluções mais
</html> modernas como o localstorage do Javascript.
Session
<?php session_start(); ?> Session (sessão) é uma maneira de
<!DOCTYPE html>
<html>
armazenar informações temporariamente
<body> que podem ser utilizadas em várias
<?php páginas da aplicação;
$_SESSION["usuario"] = "admin";
$_SESSION["senha"] = "1234"; Ao contrário de um cookie, as
?>
</body> informações não são armazenadas no
</html> computador do usuário e sim no servidor.

Apesar da informação (dado) estar no


<?php servidor, um pequeno cookie é criado no
session_start();
navegador do usuário para vincular a este
if(isset($_SESSION['usuario'])){ dado(s) na sessão.
echo "Seja bem vindo ! {$_SESSION['usuario']} !";
}else{ É possível destruir a sessão utilizando a
header("Location: index.php");
função: session_destroy();
}
PHP Assíncrono (PHP + Javascript)
● Com o fluxo tradicional “síncrono” do HTTP, faz-se necessário “atualizar/carregar” a
página toda vez que um informação é enviada do cliente para o servidor (ou o inverso),
o que, em muitas situações, pode prejudicar a interação do usuário com a aplicação.

● Com o advento do Ajax em 1999, os apps web tornaram-se capaz de enviar e


recuperar dados do servidor de forma assíncrona (em segundo plano) sem interferir na
exibição e no comportamento da página existente. Ao separar a camada de troca de
dados da camada de apresentação, o Ajax permite que uma página web possa alterar
seu conteúdo dinamicamente sem a necessidade de recarregar a página inteira.

● A partir de 2017, uma nova alternativa surgiu ao Ajax: o fetch, que permite que
requisições assíncronas possam ser feitas usando o conceito de promisses.
PHP Assíncrono (Ajax - XMLHttpRequest)
index.php
Com o uso do XMLHttpRequest do Javascript é
<!DOCTYPE html>
possível recuperar enviar dados e receber
<html lang="pt-BR">
<head> conteúdos de documentos web de forma
<title>Teste de Ajax</title> assíncrona.
<script src="curso.js"></script>
</head> curso.js
<body>
function meuAjax() {
<div id="mensagem"></div>
var xhr = new XMLHttpRequest();
<button onclick="meuAjax()">Ver mensagem</button>
xhr.open('GET', 'meu_ajax.php?nome=Maria');
</body>
xhr.onload = function () {
</html>
if (xhr.status === 200) {
document.getElementById('mensagem')
.innerHTML = xhr.responseText;
meu_ajax.php
} else {
<?php alert('Erro! Status: ' + xhr.status);
}
echo "Meu nome é ".$_REQUEST['nome']; };
echo " ".(new DateTime())->format('h:i:s'); xhr.send();
}
PHP Assíncrono (Fetch JS)
index.php
<!DOCTYPE html> A partir de 2017, o fetch permite que requisições
<html lang="pt-BR">
assíncronas possam ser feitas usando o conceito
<head>
<title>Teste de Ajax</title> de promisses.
<script src="curso.js"></script>
</head>
<body> curso.js
<div id="mensagem"></div> function meuFetch() {
<button onclick="meuFetch()">Ver mensagem</button>
</body> window.fetch("meu_fetch.php?nome=Maria")
</html> .then(response => response.text())
.then(data => {
document.getElementById('mensagem')
meu_fetch.php .innerHTML = data;
})
<?php
.catch(error => alert('Erro!' + error));
echo "Meu nome é ".$_REQUEST['nome']; }
echo " ".(new DateTime())->format('h:i:s');
PHP Assíncrono (FormData + Fetch JS)
index.php curso.js

<!DOCTYPE html> function meuFormData(event) {


<html lang="pt-BR"> event.preventDefault();
<head> const formData = new FormData(this);
<title>Formulário Assíncrono</title> window.fetch(this.getAttribute("action"), {
<script src="curso.js"></script> method: 'post',
</head> body: formData
<body> }).then(function (response) {
<form id="meu_form" action="meu_form_data.php"> return response.text();
<label>Nome:</label> }).then(function (text) {
<input type="text" name="nome"/> document.getElementById('mensagem')
<label>Email:</label> .innerHTML = text;
<input type="email" name="email"/> });
<input type="submit" value="Cadastrar"/> }
</form>
<div id="mensagem"></div>
<script> meu_form_data.php
const form = document.getElementById('meu_form');
form.addEventListener('submit', meuFormData); <?php
</script>
</body> echo "Email {$_REQUEST['email']} cadastrado com
</html> sucesso !";
PHP Assíncrono (Upload Múltiplo com Fetch)
index.php curso.js
<!DOCTYPE html> function meuFormData(event) {
<html lang="pt-BR"> event.preventDefault();
<head> <title>Formulário Assíncrono</title> const formData = new FormData(this);
<script src="curso.js"></script> </head>
<body> var fileInput = document.querySelector('input[type="file"]');
<form id="meu_form" action="meu_form_data.php" formData.delete('anexo');
enctype="multipart/form-data"> for (var i=0; i < fileInput.files.length; i++){
<label>Nome:</label> formData.append('anexo'+i, fileInput.files.item(i));
<input type="text" name="nome"/> }
<label>Email:</label>
<input type="email" name="email"/> window.fetch(this.getAttribute("action"), {
<input type="file" name="anexo" multiple="multiple"/> method: 'post',
<input type="submit" value="Cadastrar"/> body: formData
</form> }).then(function (response) {
<div id="mensagem"></div> return response.text();
<script> }).then(function (text) {
const form = document.getElementById('meu_form'); document.getElementById('mensagem')
form.addEventListener('submit', meuFormData); .innerHTML = text;
</script> });
</body> }
</html>
PHP Assíncrono (Upload Múltiplo com Fetch)
meu_form_data.php

<?php

echo "Email {$_REQUEST['email']} cadastrado com sucesso ! <br/>";

$diretorio = "anexos".DIRECTORY_SEPARATOR;

foreach($_FILES as $arquivo){
$nome = $arquivo['name'];
$conteudo = file_get_contents($arquivo['tmp_name']);
file_put_contents($diretorio.$nome, $conteudo);
if(file_exists($diretorio.$nome))
echo "Arquivo {$arquivo['name']} salvo com sucesso ! <br/>";
}
PHP Assíncrono (JSON + <select>)
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<title>Formulário Assíncrono</title> <script src="curso.js"></script>
</head>
<body>
<form>
<label>Região:</label>
<select id="regioes">
index.php
<option value="">Selecione...</option>
<option value="centro-oeste">Centro Oeste</option>
<option value="sul">Sul</option>
</select>
<label>Estado:</label>
<select id="estados"></select>
</form>
<script>
const select = document.getElementById('regioes');
select.addEventListener('change', selectEstados.bind(this,'regioes', 'estados'), false);
</script>
</body>
</html>
PHP Assíncrono (JSON + <select>)
function selectEstados(fonte_id, alvo_id) {

fonte = document.getElementById(fonte_id);
alvo = document.getElementById(alvo_id);
alvo.length = 0;

let regiao_selecionada = fonte.options[fonte.selectedIndex].value;


if (regiao_selecionada == '') curso.js
return;
window.fetch("estados.php?regiao_selecionada=" + regiao_selecionada)
.then(response => response.json())
.then(data => {
for (var i = 0; i < data.length; i++) {
var option = document.createElement("option");
option.innerHTML = data[i].nome;
option.value = data[i].id;
alvo.options.add(option);
}
})
.catch(error => alert('Erro!' + error));
}
PHP Assíncrono (JSON + <select>)
<?php

header('Content-Type: application/json');

$regiao_selecionada = $_REQUEST['regiao_selecionada'];
$estados = [
'centro-oeste' => [
['id'=>'DF', 'nome' => 'Distrito Federal'],
estados.php
['id'=>'GO', 'nome' => 'Goiás'],
['id'=>'MT', 'nome' => 'Mato Grosso'],
['id'=>'MS', 'nome' => 'Mato Grosso do Sul']
],
'sul' => [
['id'=>'PR', 'nome'=> 'Paraná'],
['id'=>'RS', 'nome'=> 'Rio Grande do Sul'],
['id'=>'SC', 'nome'=> 'Santa Catarina']
]
];

echo json_encode($estados[$regiao_selecionada]);
Tratamento de Exceções/Erros
● O tratamento de exceção é usada para alterar o fluxo normal da execução de
código se ocorrer uma condição de erro específico (excepcional). Essa
condição é chamada de exceção.
● No PHP 7>= existem dois principais tipos de erros: os throwables e o não
throwables.
● Os throwables podem ser lançados via throw e tratados via try/catch. Nesta
categoria existem dois sub tipos: Exceptions e Errors.
● Os não throwables podem, em alguns casos, ser suprimidos via @,
error_reporting ou tratados utilizando o set_error_handler()
Taxonomia de Erros e Exceções (throwables)

Com o advento do PHP 7, foi


definido uma Interface
chamada Throwable, que se
tornou a interface base para
qualquer objeto “lançável”,
isto é, objetos passíveis de
serem disparados via throw
e/ou capturados via catch.

FONTE:
http://asika.windspeaker.co/post/3503-php-exceptions
Manipulação de Throwables
Bloco de código em
<?php TRY

try { código
Bloco Sim lança
// código aqui uma
CATCH Exceção/
} Error ?
catch (\Throwable $t) {
Não
echo $t->getMessage();
} Bloco FINALLY
Throwable
<?php Utilizando a Interface base como
// "capturando" exceptions typehint do catch, é possível capturar
try {
tanto as Exceptions como os Errors.
throw new Exception('exception');
} catch (Exception $e) {
echo('capturando exception: '.$e->getMessage().PHP_EOL);
}
// capturando errors (PHP 7>=)
try {
$obj = new \StdClass();
$obj->not_a_method();
} catch (Error $e) {
echo('capturando error: '. $e->getMessage().PHP_EOL);
}
// ambos (Exception e Error)
try {
throw new Exception('exception');
} catch (Throwable $e) {
echo('capturando Throwable: '. $e->getMessage().PHP_EOL);
}
Tratamento de Throwables (Finally [PHP 5.5>=])
<?php
try {
print "bloco de código";
Com o advento do PHP 5.5, tornou-se
possível colocar uma condição final que
} catch (\Throwable $t) { será executada tanto no caso da ocorrência
de uma Exception/Error quanto no caso de
print "Erro!"; sucesso das instruções do bloco try.

} finally {
print "Terminou!";
}
Lançamento de Throwables (throw new)
<?php Com o uso do operador throw seguido de
uma instância de Throwable é possível
function escolhaMcOferta (int $opcao) : ?string { “lançar” uma exceção/erro para que o
usuário de uma função/método possa
receber as informações necessárias do
$ofertas = ['bic mac', 'mc cheddar', erro e tratá-lo da melhor maneira possível;
'quarteirão', 'mc fish', 'mc chicken'];
Se o desenvolvedor tentar usar uma
if (!in_array($opcao, range(1,5))) { instância de um objeto que não
implementa throwable ocorrerá um erro
throw new OutOfRangeException("Oferta inválida");
fatal do tipo “Uncaught Error” descrevendo
} que o objeto não implementa a interface;
return $ofertas[--$opcao];
}

echo escolhaMcOferta(6);
Tratamento de Throwables (múltiplos)

<?php

function teste($x):int{
return $x;
}

try {
É possível especificar diferentes
intdiv(10,0);
tratamentos de Exceptions/Errors
teste('ss');
através do aninhamento de catchs
}
catch(DivisionByZeroError $e){
echo "não pode fazer essa divisão";
}
catch(TypeError $e){
echo "Erro de tipo!";
}
Tratamento de Throwables (grupo com pipe)

<?php

function teste($x):int{
return $x;
}
Com o advento do PHP 7.1 é possível
especificar um único tratamento para
try { um grupo de diferentes tratamentos de
intdiv(10,0); Exceptions/Errors utilizando o operador
pipe “I”;
teste('ss');
}
catch(DivisionByZeroError | TypeError $e){
echo "Erro de divisão ou de tipo";
}
Criando Exceções/Erros customizados (extends Exception)

<?php
class MeuException extends Exception {
public function __construct($message = null, $code = 0){
parent::__construct($message, $code);
file_put_contents('/tmp/log.txt',
$this->getTraceAsString().PHP_EOL ,
FILE_APPEND | LOCK_EX); É possível criar um Throwable customizado
} com uma especialização de Exception ou
}
Error. (Pois não é possível implementar a
function legal($x){ interface Throwable).
if($x == 0){
throw new MeuException();
}
}

try{
legal(0);
}catch(Exception $e){
print('erro');
}
Principais Tipos de Erros (não Throwable)
Tipo Constante Significado Interrompe a Pode ser Tempo
execução do suprimido de:
script? com @?

NOTICE E_NOTICE Aviso para indica que o script encontrou alguma NÃO SIM Execução
coisa que pode indicar um erro;

WARNING E_WARNING Erro não fatal; NÃO SIM Execução

DEPRECATED E_DEPRECATED Aviso de um recurso depreciado e será NÃO SIM Execução


futuramente removido nas próximas versões do
PHP.

ERROR E_ERROR Erro fatal em tempo de execução. Estes indicam SIM NÃO Execução
erros que não podem ser recuperados.

PARSER E_PARSER Erros gerados pelo interpretador devido a erro SIM NÃO Compilação
ERROR de sintaxe no script
Operador de controle de erro (supressão @)
<?php
O PHP suporta um operador de controle
echo @(10 / 0);
// suprimiu "Warning: Division by zero" de erro: o sinal 'arroba' (@).
$c = @$_POST["nome"] . @$_POST["sobrenome"];
// suprimiu "Notice: Undefined index: nome" Com uso do @ é possível suprimir um
// suprimiu "Notice: Undefined index: sobrenome"
@$newfunc = create_function('$a', 'return;');
notice ou um erro não fatal.
// suprimiu "Deprecated: Function create_function() is
deprecated"
@ $i / 0;
// suprimiu "Notice: Undefined variable: i"
// não suprimiu o "Warning: Division by zero"

$c = @funcaoNaoExiste(); //não suprimiu erro fatal


echo 'fim';
Controle de nível de erros não throwables
<?php Com o uso da função error_reporting()
podemos controlar, em tempo de
// Desligando todos os avisos de erros
execução quais avisos de erros o PHP
error_reporting(0);
poderá imprimir na tela.
// Ligando apenas para warning
error_reporting(E_WARNING); Essas mesmas constantes podem ser
setadas de uma maneira global no
// com o uso do pipe | é possível criar uma lista php.ini.
// fixa de avisos para erros
error_reporting(E_ERROR | E_WARNING | E_PARSE);

// E_ALL é o equivalente a todos os tipos


error_reporting(E_ALL);

// Com o uso do ^ (not) é possível remover


// um item da lista (todos menos notice)
error_reporting(E_ALL ^ E_NOTICE);
set_error_handler() e restore_error_handler()
<?php Com o uso do set_error_handler() é possível
set_error_handler("manipuladorCustomizadoDeErros"); criar um manipulador customizado de erros
não throwables.
function manipuladorCustomizadoDeErros
($severity, $mensagem, $arquivo, $linha) {
if (error_reporting() & $severity) { É possível, inclusive, lançar uma exceção
throw new Exception($mensagem, 0); dentro de um manipulador customizado
} permitindo assim que erro possa ser tratado
} com um throwable, podendo ser capturado
via catch.
$array = ['maria','josé'];

try { O ideal é sempre no final do bloco de


$b = $array[2]; instruções restaurar o manipulador original
} catch (Exception $e) { do programa com o restore_error_handler().
echo "Posição não encontrada !";
} finally {
restore_error_handler();
}
Serialização
● É o processo de traduzir estruturas de dados ou estado de objeto em um
formato que pode ser armazenado (por exemplo, em um arquivo ou buffer de
memória) ou transmitido e reconstruído posteriormente (possivelmente em
um ambiente de computador diferente).
● Quando a série resultante de bits é relida de acordo com o formato de
serialização, ela pode ser usada para criar um clone semanticamente idêntico
do objeto original.
● Esse processo de serializar um objeto também é chamado de marshalling
(empacotamento de um objeto).
● A operação oposta, extraindo uma estrutura de dados de uma série de bytes,
é a desserialização (também chamada de unmarshalling).
Serialização (serialization)
Aluno.php Turma.php
<?php <?php

class Aluno { class Turma {

public $nome; public $nome;


public $matricula; public $data;
public $alunos;
public function __construct(string
$nome, int $matricula) { public function __construct(string
$this->nome = $nome; $nome, \DateTime $data, array $alunos = []) {
$this->matricula = $matricula; $this->nome = $nome;
} $this->data = $data;
} $this->alunos = $alunos;
}
}
Serialização (escrita)
<?php
include_once 'Turma.php';
include_once 'Aluno.php';
A função serialize converte toda estrutura
$turmas = [];
de arrays e objetos em uma string utilizando
$aluno1 = new Aluno('José', 123);
$aluno2 = new Aluno('Maria', 456);
um formato passível de recuperação pelo
$aluno3 = new Aluno('Thiago', 789); próprio PHP.

$turmas[] = new Turma('PHP', Já a função file_put_contents persiste


new \DateTime('today'), [$aluno1, $aluno2]); uma string em um arquivo texto.
$turmas[] = new Turma('CakePHP',
new \DateTime('-2 days'), [$aluno1, $aluno2, $aluno3]); Se as classes não forem carregadas o PHP
$turmas[] = new Turma('MySQL', irá gerar instâncias de
new \DateTime('yesterday'), [$aluno1, $aluno3]); __PHP_Incomplete_Class.

$serializacao = serialize($turmas);
file_put_contents('dados.db', $serializacao);
Desserialização (leitura)
<?php
include 'Turma.php';
include 'Aluno.php';

$serializacao = file_get_contents('dados.db');
$turmas = unserialize($serializacao); A função file_get_contents recupera o
conteúdo de um arquivo texto em uma
echo "<table border>"; string.
foreach ($turmas as $turma) {
echo "<tr>"; A função unserialize interpreta o conteúdo
echo "<td> {$turma->nome} </td>"; serializado em uma string e reconstrói os
echo "<td> {$turma->data->format('d/m/Y')} </td>"; objetos e arrays.
echo "<td>". implode(", ",
array_column($turma->alunos, 'nome'))."</td>";
echo "</tr>";
}
echo "</table>";
PHP e Bancos de Dados Relacionais
● Até o PHP 5.0, era necessário utilizar extensões PECL com conjuntos diferentes de funções
para cada acessar cada banco de dados (ex.: mysql_connect, mssql_connect etc…).

● Com o advento do PHP 5.1 surgiu o PDO (PHP Data Objects): uma camada de abstração de
acesso a banco de dados (DBAL). Uma DBAL (Database abstraction layer) é uma API que visa
unificar a comunicação entre um aplicações e bancos de dados.

● As DBALs reduzem a quantidade de trabalho para acessar diferentes bancos de dados


fornecendo uma API consistente ao desenvolvedor ocultando o máximo possível as
especificidades do banco de dados por trás dessa interface.

● O PDO fornece uma DBAL, o que significa que, independentemente de qual banco de dados, o
desenvolvedor utiliza as mesmas funções para emitir consultas e buscar dados. O PDO não
fornece uma abstração de SQL e nem emula os recursos ausentes de um banco de
dados.
Modelo Relacional
● O modelo relacional é uma abordagem para gerenciar dados usando uma
estrutura e linguagem consistente com lógica de predicados de primeira ordem,
descrita pela primeira vez em 1969 pelo cientista inglês Edgar F. Codd, onde os
dados são representados em termos de tuplas (linhas), agrupadas em relações
(tabelas).
● Um banco de dados organizado em termos do modelo relacional é um banco de
dados relacional.
● A maioria dos bancos de dados relacionais utiliza o SQL para definição de dados
e a linguagem de consulta; esses sistemas implementam o que pode ser
considerado como uma aproximação de engenharia ao modelo relacional.
● Além disso, os banco de dados permitem também criar relacionamento entre as
tabelas (entidades) através de chaves estrangeiras.
Modelo Relacional: Tabela, colunas, tipos e chave primária

● Uma tabela é composta de colunas (campos).


● Cada coluna possui um nome e um tipo de dado, ex.:
VARCHAR (string), INT, DOUBLE etc.
● É possível definir também se um campo poderá permitir
valores nulos ou não.
● Para garantir o unicidade de cada tupla (registro) é
possível utilizar o recurso da chave primária onde o
SGBD garante que aquele valor não possa ser repetido
Relacionamentos e restrições de integridade
● Um relacionamento, no contexto de bancos de dados relacionais, é uma situação que
existe entre duas tabelas quando uma possui uma chave estrangeira que faz
referência à chave primária da outra tabela. Os relacionamentos permitem que bancos
de dados relacionais dividam e armazenem dados em diferentes tabelas, enquanto
ligam itens de dados distintos.

● Existem os seguintes tipos de relacionamentos entre tabelas:


○ 1..1 (um para um): onde uma das duas tabelas faz referência para a outra.
○ 1..N (um para muitos): onde o lado N recebe faz referência para o lado um.
○ N..N (muitos para muitos): onde uma terceira tabela (associativa) precisa ser
criada para permitir que está faça referência para as duas tabelas da relação.
○ Auto relacionamento: onde uma tabela faz referência para ela mesma.
Drive PDO
● Um drive/extensão PDO define uma interface leve e consistente para acessar
bancos de dados no PHP. Cada driver de banco de dados que implementa a
interface do PDO pode expor recursos específicos do banco de dados como
funções de extensão regulares.

● Os drivers PDO também são extensões PECL e podem ser habilitadas no


php.ini, caso as mesmas estejam disponíveis em forma de *.dll ou *.so no
diretório de extensões do PHP.
PDO (getAvailableDrivers())

<?php

print_r(PDO::getAvailableDrivers());
O método estático getAvailableDrivers permite
verificar quais os drivers de PDO estão instalados no
PHP.
PDO Drivers

Banco (SGBD) Drive (.dll ou .so) Incluído no pacote PHP Download


Windows? adicional

MySQL php_pdo_mysql SIM -

Postgres php_pdo_pgsql SIM -

SQL Server php_pdo_sqlsrv NÃO Drive ODBC

Oracle php_pdo_oci SIM Instant Client


Classe PDO (instanciando)
<?php

$pdo = new PDO($dsn, $usuario, $senha, $opcoes);

● dsn: conexão com a fonte de banco de dados


● usuario: usuário do banco de dados
● senha: senha deste usuário
● opções: conjunto de opções em forma de chave e valores utilizando um
conjunto de constantes, alguns comuns entre os drivers e outros
específicos de cada um.
PDO Options (opções recomendadas)
Opção Valor Recomendado Resultado Suportado pelos
Drivers

PDO::ATTR_ERRMODE PDO::ERRMODE_EXCEPTION Lança Exceptions toda vez que uma MySQL, Postgres,
instrução SQL falhar. Sql Server e Oracle

PDO::ATTR_EMULATE_PRE false O motor do banco de dados fará o MySQL, Postgres e


PARES prepared statement ao em vez do Oracle
PDO e assim, consulta e os dados
reais são enviados separadamente,
aumentando a segurança.

PDO::ATTR_DEFAULT_FETC PDO :: FETCH_ASSOC É conveniente configurá-lo de forma MySQL, Postgres,


H_MODE global e depois omiti-lo em buscas Sql Server e Oracle
específicas.
DSN (Data Source Name)
● DSN ou data source name (nome de fonte de dados, algumas vezes conhecido como
nome de fonte de banco de dados, apesar de fontes de dados não serem limitadas a
bancos de dados), é uma estrutura de dados usada para descrever uma conexão a
uma fonte de dados.
● Cada Driver possui seu conjunto específico de parâmetros. Exemplos:
○ MYSQL: mysql:host=localhost;dbname=livraria;port=3306;charset=utf8mb4
○ POSTGRES: pgsql:host=localhost;port=5432;dbname=livraria;
○ SQL SERVER: sqlsrv:Server=localhost;Database=livraria
○ ORACLE:
oci:dbname=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521))(CONNECT
_DATA=(SERVICE_NAME=LIVRARIA)))
PDO (Conexão MySQL)
conexao.php
<?php
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false, //para funcionar bind no limit
];

$servidor = "localhost";
$banco = "livraria";
$usuario = "root";
$senha = '';
$porta = 3306;
$dsn = "mysql:host=$servidor;port=$porta;dbname=$banco;charset=utf8";

$pdo = new PDO($dsn, $usuario, $senha, $options);


PDO (Conexão Postgres)
conexao_postgres.php
<?php

$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];

$servidor = "localhost";
$banco = "livraria";
$usuario = "postgres";
$senha = "admin";
$porta = 5432;
$dsn = "pgsql:host=$servidor;port=$porta;dbname=$banco;";

$pdo = new PDO($dsn, $usuario, $senha, $options);


PDO (Conexão SQL Server)
conexao_sqlserver.php
<?php

$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, //ver erros de query
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
];

$servidor = "localhost";
$banco = "livraria";
$usuario = "85bits";
$senha = "admin";
$dsn = "sqlsrv:Server=$server;Database=$banco";

$pdo = new PDO($dsn, $usuario, $senha, $options);


PDO (Conexão Oracle)
conexao_oracle.php
<?php
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_CASE => PDO::CASE_LOWER
];

$servidor = "localhost";
$usuario = "php";
$senha = "admin";
$service_name = "XE";
$sid = "XE";
$port = 1521;
$dbtns = "(DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = $servidor)(PORT = $port)) (CONNECT_DATA =
(SERVICE_NAME = $service_name) (SID = $sid)))";

$pdo = new PDO("oci:dbname=" . $dbtns . ";charset=utf8", $usuario, $senha, $options);


Modelo de Banco de Dados Livraria
● Para os exemplos deste curso utilizaremos um banco de dados do domínio de uma Livraria.
O banco está disponível para 4 SGBDS diferentes e já conta com um número considerável de
registros nas tabelas.

● Além disso, este banco possui todos os tipos de associações:


a. (1..1): Funcionário tem uma Habilitação.
b. (1..N): Editora tem muitos Livros.
c. (N..1): Livros pertencem a uma Editora.
d. (N..N): Livros têm muitos Autores e Autores têm muitos Livros.
● E algumas Associações especiais:
a. Auto relacionamento: Funcionário tem gerente Gerente (Funcionário).
b. N..N com dados associativos: Pedido tem muitos Livros (através de ItemPedido e seus
dados).
c. Árvore: Gênero tem nós filhos, irmãos e pais.
Modelo de Exemplo (livraria)
SQL (livraria v0.2 - DUMP do Banco de Dados)
Disponível em:

https://gist.github.com/celsowm/5a3723b58775900db7d010653e5f82e0

https://gist.github.com/celsowm/067fe51dfa612697895c8ec3b5cb436d

https://gist.github.com/celsowm/b139713d65d6c42df084269b3f150a2d

https://gist.github.com/celsowm/219c130a18289b9378fa7642508c473b
PDO Query (PDO->query() e PDOStatement->fetch())

<?php O método query permite


submeter uma query SQL para o
include_once “conexao.php”; SGBD e retorna um objeto do tipo
PDOStatement.
$statement = $pdo->query("SELECT nome FROM funcionario");
$funcionario = $statement->fetch(); Para recuperar (a
próxima/primeira) linha do
echo $funcionario['nome']; resultado da query podemos
utilizar o método fetch(), que, no
caso do fetch padrão associativo,
retorna um array onde as chaves
são as colunas e os valores de
cada linha os valores do array.
PDO Query (PDO->query() e PDOStatement->fetch())

<?php Podemos iterar o resultado de


uma query invocando o método
include_once “conexao.php”; fetch até o mesmo retornar nulo,
isto é, até esgotar o número de
$statement = $pdo->query("SELECT nome FROM funcionario"); registros.
while($funcionario = $statement->fetch()){
echo $funcionario['nome']."</br>";
}
PDO Query (Transversable)

<?php
A classe PDOStatement
include_once “conexao.php”; implementa Traversable, o
que permite que objetos
$statement = $pdo->query('SELECT nome FROM funcionario'); desta classe possam ser
foreach ($statement as $linha){ iterados de forma
echo $linha['nome'] . "<br>"; transparente.
}
SQL Injection
"SQL Injection" é um subconjunto da vulnerabilidade de entrada do usuário não Exemplo:
verificada / não-tratada cujo a propósito é forçar o aplicativo a executar um código ' or '1'='1
SQL que não foi planejado.

<!DOCTYPE html> <?php


<html> include_once '../conexao.php';
<head>
<title>Login</title> $login = $_REQUEST['login'];
<meta charset="UTF-8"> $senha = $_REQUEST['senha'];
</head>
<body> $query = "SELECT * FROM usuario WHERE login = '$login' AND senha =
<form action="logar.php"> '$senha'";
<label>login:</label> //var_dump($query);
<input type="text" name="login" />
<label>senha:</label> $statement = $pdo->query($query);
<input type="password" name="senha" /> $usuario = $statement->fetch();
<input type="submit" value="logar" /> if($usuario){
</form> echo "Usuário {$usuario['login']} logado com sucesso !";
</body> }
</html>
Prepared Statements
● Para evitar SQL Injection podemos utilizar o recurso de prepared statement
(declaração/instrução preparada/parametrizada).
● Os prepared statements são resilientes à SQL injections porque os valores que
são transmitidos posteriormente usando um protocolo diferente e não são
compilados/interpretados com o código SQL original.
● Para utilizar este recurso com o PDO devemos utilizar o método prepare() com a
query desejada substituindo os valores por placeholders (caracteres substitutos).
● Antes de recuperar os dados (fetch) faz-se necessário vincular os valores aos
seus respectivos placeholders e executar (execute).
● Os Drivers PDO podem utilizar prepared statements de forma nativa (quando
suportado) ou emulados pelo PDO (PDO::ATTR_EMULATE_PREPARES)
PDO Binding (usando parâmetros no SQL)
include_once “conexao.php”;

$nome = 'Edson Wander';


$cpf = '54698715324';

//posicional
$statement = $pdo->prepare('SELECT * FROM funcionario WHERE nome = ? AND cpf = ?');
$statement->execute([$nome, $cpf]);
$funcionario = $statement->fetch();

//usando key e value


$statement = $pdo->prepare('SELECT * FROM funcionario WHERE email = :email AND status=:status');
$statement->execute([nome => $nome, 'cpf' => $cpf]);
$funcionario = $statement->fetch();
Prepared Statement (evitando SQL Injection)
<!DOCTYPE html> <?php
<html> include_once '../conexao.php';
<head>
<title>Login</title> $login = $_REQUEST['login'];
<meta charset="UTF-8"> $senha = $_REQUEST['senha'];
</head>
<body> $query = "SELECT * FROM usuario WHERE login = ? AND
<form action="logar_prepared.php"> senha = ? ";
<label>login:</label> //var_dump($query);
<input type="text" name="login" />
<label>senha:</label> $statement = $pdo->prepare($query);
<input type="password" $statement->execute([$login, $senha]);
name="senha" /> $usuario = $statement->fetch();
<input type="submit" value="logar" /> if($usuario){
</form> echo "Usuário {$usuario['login']} logado com sucesso !";
</body> }
</html>
PDO Binding (bindParam)
<?php Podemos utilizar o
método bindParam para
include 'conexao.php'; passar por referência o
valor de variáveis para
$nome = 'Edson Wander'; uma prepared statement.
$cpf = '54698715324';
No primeiro parâmetro
especificamos o nome ou
$stmt = $pdo->prepare('SELECT * FROM funcionario WHERE nome = ? AND
posição do placeholder;
cpf = ?'); no segundo, a variável
$stmt->bindParam(1, $nome,PDO::PARAM_STR); de referência e no
$stmt->bindParam(2, $cpf,PDO::PARAM_STR); terceiro o tipo desejado
$stmt->execute(); do valor (usando
$funcionario = $stmt->fetch(); constantes do PDO).

var_dump($funcionario);
PDO Binding (bindValue)

<?php Podemos utilizar o


método bindValue para
include 'conexao.php'; passar por um valor de
variáveis para uma
$stmt2 = $pdo->prepare('SELECT * FROM funcionario WHERE nome = ? AND prepared statement.
cpf = ?');
No primeiro parâmetro
$stmt2->bindValue(1, 'Edson Wander',PDO::PARAM_STR);
especificamos o nome ou
$stmt2->bindValue(2, '54698715324',PDO::PARAM_STR);
posição do placeholder;
$stmt2->execute(); no segundo, a variável
$funcionario2 = $stmt2->fetch(); de referência e no
terceiro o tipo desejado
var_dump($funcionario2); do valor (usando
constantes do PDO).
PDO (bindColumn)

<?php Com o uso do bindColumn é possível


passar por referência o valor de uma
include 'conexao.php'; coluna para uma variável para cada fetch
realizado.
$query = "SELECT id, nome, cpf FROM funcionario";
$statement = $pdo->query($query); A indicação da coluna pode ser feita de
$statement->bindColumn(1, $id); maneira posicional ou pelo nome da
$statement->bindColumn(2, $nome); coluna.
$statement->bindColumn('cpf', $cpf);
O ideal é utilizar sempre o estilo
while ($row = $statement->fetch(PDO::FETCH_BOUND)) { PDO::FETCH_BOUND que permite que o
echo "$id:" . $nome . " " . $cpf . "</br>"; PDO possa designar valores para
} variáveis que foram “vinculadas”
anteriormente usando bindColumn.
PDO Prepared Statement (com SQL like)

<?php O operador like do SQL, que permite


procurar por um determinado “padrão” em
include 'conexao.php'; um texto, pode ser utilizado também como
prepared statement.
$sql = "SELECT * FROM livro WHERE titulo LIKE ?";
$statement = $pdo->prepare($sql); Só é válido salientar que os operadores
$statement->execute(['%do%']); curingas precisam ser utilizados “fora” da
foreach($statement as $livro){ query, isto é, precisam ser enviados como
echo $livro['titulo']."</br>"; valores para os binds.
}
PDO Prepared Statement (com SQL IN() “literal” )
<?php Infelizmente o uso de
include 'conexao.php'; array como placeholders
não é suportado
$filtro = ["preco_minimo" => "1.98"];
nativamente no PDO,
$edicoes = [1,2,10];
então, faz-se necessário
$edicoes = array_combine( “replicar” um conjunto de
array_map(function($i){ return ':id'.$i; }, array_keys($edicoes)), placeholders que possa
$edicoes representar cada valor do
); conjunto do IN().
$in_placeholders = implode(',', array_keys($edicoes));
$sql = "SELECT * FROM livro WHERE preco >= :preco_minimo AND edicao IN É válido salientar que
($in_placeholders)";
muitos SGBDs possuem
$statement = $pdo->prepare($sql);
limitação no número de
$statement->execute(array_merge($filtro,$edicoes));
foreach($statement as $livro){ valores literais em um IN.
echo $livro['titulo']."</br>";
}
PDO (fetchCollumn)

<?php

include_once “conexao.php”;

//PDO fetchColumn
$statement = $pdo->query("SELECT id, titulo FROM livro"); O método fetchCollumn retorna uma
var_dump($statement->fetchColumn()); única coluna da próxima linha de um
var_dump($statement->fetchColumn(1)); conjunto de resultados ou FALSE se
não houver mais linhas.
PDO getColumnData (Introspecção)

<?php O método getColumnData permite


que recuperar os metadados dos
include 'conexao.php'; campos (colunas) de uma query
(inclusive campos virtuais).
$statement = $pdo->query('SELECT titulo, preco FROM livro');
$metadados = $statement->getColumnMeta(0); O parâmetro do método é a
posição da coluna em relação do
echo "<pre>"; descrito na query.
var_dump($metadados);
echo "</pre>"; Infelizmente o drive do Oracle
(pdo_oci) não suporta/implementa
este método.
PDO FetchAll
● PDOStatement::fetchAll() retorna um array contendo todas as linhas
restantes no conjunto de resultados. O array representa cada linha como
uma matriz de valores de coluna ou um objeto com propriedades
correspondentes a cada nome de coluna.
● Uma array vazio é retornado se houver zero resultados a serem obtidos ou
retorna FALSE em caso de falha.
● Usar esse método para buscar conjuntos de resultados grandes resultará em
uma grande demanda no sistema e possivelmente nos recursos da rede. Em
vez de recuperar todos os dados e manipulá-los no PHP, considere o uso do
servidor de banco de dados para manipular os conjuntos de resultados. Por
exemplo, use as cláusulas WHERE ou Paginação no SQL para restringir os
resultados antes de recuperá-los e processá-los com o PHP.
FetchAll (exemplo)

<?php

include_once “conexao.php”;

$statement = $pdo->query('SELECT * FROM funcionario');


$funcionarios = $statement->fetchAll();
foreach ($funcionarios as $funcionario) { O resultado do fetchAll() é um
echo $funcionario['nome']."</br>"; array com o resultado da query.
}
Fetch & Fetch All (estilos)
● Ao utilizar os métodos fetch ou fetchAll de um PDOStatement é possível
determinar qual o “formato” dos dados resultantes da query.

● Alguns estilos possuem argumentos (similar a uma função). E os


valores destes argumentos influenciam na formatação dos dados.

● O estilo dos fetchs podem ser determinados das seguintes maneiras :


○ De maneira global no options do PDO (PDO::ATTR_DEFAULT_FETCH_MODE)
○ Através do segundo parâmetro dos métodos fetch e fetchAll do PDOStatement
○ Utilizando o método setFetchMode() em cada PDOStatement antes do
fetch/fetch/execute.
PDO::FETCH_ASSOC

<?php

include 'conexao.php';
PDO::FETCH_ASSOC:
$statement = $pdo->query('SELECT nome FROM funcionario'); retorna um array indexado
$funcionarios = $statement->fetchAll(PDO::FETCH_ASSOC);
foreach ($funcionarios as $funcionario) { pelo nome da coluna
echo $funcionario['nome']."</br>"; conforme o retorno da
}
query.
$statement = $pdo->query('SELECT nome FROM funcionario');
$funcionario = $statement->fetch(PDO::FETCH_ASSOC);
echo $funcionario['nome']."</br>";
PDO::FETCH_NUM

<?php
PDO::FETCH_NUM:
include 'conexao.php'; retorna um array 2D
$statement = $pdo->query("SELECT nome, id FROM funcionario");
onde as chaves
//$statement = $pdo->query("SELECT titulo, id FROM livro"); assumem as posições
$dados = $statement->fetchAll(PDO::FETCH_NUM);
foreach ($dados as $dado) {
das colunas e os
echo "nome: $dado[0] | id: $dado[1] <br/>"; valores são os dados
}
de cada registro nesta
coluna.
PDO::FETCH_BOTH

<?php
PDO::FETCH_BOTH:
include 'conexao.php'; retorna um array indexado
$statement = $pdo->query('SELECT * FROM funcionario'); duplicando o número
$funcionario = $statement->fetch(PDO::FETCH_BOTH); colunas onde permitindo
var_dump($funcionario);
que os dados sejam
acessados tanto pelo nome
da coluna como pelo índice
(número) da mesma.
PDO::FETCH_KEY_PAIR

<?php PDO::FETCH_KEY_PAIR:
retorna um array 2D onde
include_once "conexao.php";
as chaves assumem os
valores da primeira coluna
$statement = $pdo->query("SELECT id, nome FROM funcionario");
$dados = $statement->fetchAll(PDO::FETCH_KEY_PAIR); e os valores são os dados
echo "<select>"; da segunda.
foreach($dados as $key => $dado){
echo "<option value='$key'>$dado</option>"; Se uma terceira coluna for
} colocada na projeção, o
echo "</select>"; PDO lançará uma exceção
PDO::FETCH_UNIQUE

<?php
PDO::FETCH_UNIQUE:
include_once “conexao.php”; retorna um array de
arrays onde as chaves
$statement = $pdo->query('SELECT id,nome,cpf FROM funcionario'); assumem os valores da
$funcionarios = $statement->fetchAll(PDO::FETCH_UNIQUE); primeira coluna e os
foreach ($funcionarios as $id => $funcionario) {
valores (com colunas em
echo $id.":".$funcionario['nome']."</br>";
} keys) em subarrays.
PDO::FETCH_NAMED
<?php
PDO::FETCH_NAMED:
retorna um array
$statement = $pdo->query('
SELECT * FROM editora
multidimensional onde campos
LEFT JOIN livro ON livro.editora_id = editora.id'); com nomes repetidos são
$registros = $statement->fetchAll(PDO::FETCH_NAMED);
colocados dentro de um
mesmo array onde, a ordem
foreach ($registros as $registro) {
echo "editora id {$registro['id'][0]} e
dos mesmos é referente a
livro {$registro['id'][1]} <br/>"; ordem de suas respectivas
}
tabelas na própria query.
JOIN SQL
LEFT JOIN: junção de A B, INNER JOIN: junção de A B, RIGHT JOIN: junção de A B,
porém, recupere tudo de A porém recupere apenas se porém, recupere tudo B
mesmo se não houver uma houver registro A e B com mesmo se não houver uma
referência em B (ficando referências. referência em A (ficando
nulo valores para B sem nulo valores para A sem
referência para A). referência para B).
A B A B A B

SELECT * FROM funcionario SELECT * FROM pedido SELECT * FROM livro


LEFT JOIN habilitacao ON INNER JOIN cliente ON RIGHT JOIN editora ON editora.id
funcionario.id = cliente.id = pedido.cliente_id = livro.editora_id
habilitacao.funcionario_id
PDO::FETCH_GROUP
<?php

include 'conexao.php';

$statement = $pdo->query("SELECT edicao, id, titulo PDO::FETCH_GROUP:


FROM livro order by edicao");
retorna os registros
$livrosPorEdicao = $statement->fetchAll(PDO::FETCH_GROUP); agrupados pela primeira
foreach ($livrosPorEdicao as $key => $livros) { coluna da query em arrays
echo "Livros na $key ª edição: </br>"; multidimensionais.
foreach ($livros as $livro) {
echo "-- {$livro['titulo']} </br>";
}
echo "<br/>";
}
PDO::FETCH_LAZY

<?php PDO::FETCH_LAZY: Faz um busca


tardia/lenta/por demanda e retornar a
include_once “conexao.php”; próxima linha como um objeto anônimo com
nomes de colunas como atributos. O
$statement = $pdo->query('SELECT * FROM livro'); desempenho costuma ser notável ao
$livro = $statement->fetch(PDO::FETCH_LAZY); recuperar uma grande massa de dados
echo "ISBN: {$livro['isbn']} : {$livro->titulo} </br>"; (linhas).

Devido à própria natureza de


busca “tardia” (e por demanda)
dos registros do banco de dados,
o FETCH_LAZY não funciona
com o fetchAll().
PDO::FETCH_BOUND

<?php

include 'conexao.php';
PDO::FETCH_BOUND:
$query = "SELECT id, nome, cpf FROM funcionario"; Permite que o PDO possa
$statement = $pdo->query($query); designar valores para variáveis
$statement->bindColumn(1, $id); que foram “vinculadas”
$statement->bindColumn(2, $nome);
anteriormente usando
$statement->bindColumn('cpf', $cpf);
bindColumn.
while ($row = $statement->fetch(PDO::FETCH_BOUND)) {
echo "$id:" . $nome . " " . $cpf . "</br>";
}
PDO::FETCH_COLUMN (Estilos com argumentos)

<?php PDO::FETCH_COLUMN:
include_once "conexao.php";
retorna um array 2D onde
$statement = $pdo->query('SELECT nome, id FROM funcionario'); os valores são os dados de
$nomes = $statement->fetchAll(PDO::FETCH_COLUMN);
uma única coluna e uma
foreach ($nomes as $nome) {
echo $nome."</br>"; chave sequencial.
}
Seu parâmetro é similar o
$statement = $pdo->query('SELECT id, nome, cpf FROM funcionario');
fetchColumn, onde um
$cpfs = $statement->fetchAll(PDO::FETCH_COLUMN, 2);
foreach ($cpfs as $cpf) { inteiro é utilizado para
echo $cpf."</br>"; indicar a coluna desejada.
}
PDO::FETCH_FUNC (Estilos com argumentos)
<?php

include_once “conexao.php”;

$statement = $pdo->query('SELECT preco, titulo FROM livro'); PDO::FETCH_FUNC:


$livros = $statement->fetchAll(PDO::FETCH_FUNC, function($preco, $titulo){ Permite que uma
$preco_no_cartao = round($preco + ($preco * 0.1),2);
return "$titulo: R$ {$preco} à vista e no cartão R$ {$preco_no_cartao}";
função/closure receberá
}); em forma de parâmetros
as colunas da query.
foreach ($livros as $preco) {
echo $preco."</br>";
}
PDO e ORM (Object Relational Mapper)
● Alguns estilos do PDO permitem um mapeamento primitivo entre registros de
uma tabela (modelo relacional) e o instâncias/objetos de uma classe (modelo
orientado a objetos).

● As maiores limitações começam a surgir quando é necessário


representar/mapear relacionamentos entre objetos.

● Para tarefas mais complexas de mapeamento é recomendável utilizar


bibliotecas ORM de terceiros.
PDO (Fetch Class)
Livro.php
<?php O comportamento padrão do
class Livro { FETCH_CLASS é chamar o construtor
public $id; depois de colocar os valores nos atributos.
public $titulo;
private $edicao; }

//recuperando dados
include_once “conexao.php”;
include_once “Livro.php”;

$sth = $pdo->prepare("SELECT * FROM livro");


$sth->execute();

$result = $sth->fetchAll(\PDO::FETCH_CLASS, 'Livro');


print_r($result);
PDO FETCH_CLASS + FETCH_CLASSTYPE

<?php

include_once “conexao.php”; PDO::FETCH_CLASSTYPE:


Combinado com FETCH_CLASS permite
class Autor {} que a primeira coluna da query seja
class Funcionario {}
utilizada para definir qual classe utilizar
$statement = $pdo->query( para instância o registro.
"SELECT 'Autor', nome FROM autor
UNION Pode ser muito útil para o caso de
SELECT 'Funcionario', nome FROM funcionario"); associações polimórficas com simulação
$objeto = $statement->fetchAll(PDO::FETCH_CLASS | de herança no modelo relacional.
PDO::FETCH_CLASSTYPE);
print_r($objeto);
PDO::FETCH_CLASS + PDO::FETCH_PROPS_LATE
<?php <?php
class Funcionario {
class Habilitacao {
public $id;
public $nome;
public $numero;
public $habilitacao;
public $categoria;
public function __construct() {
$this->habilitacao = new Habilitacao(); }
}

public function __set($name, $value) { Podemos utilizar a flag


if (array_key_exists($name, get_object_vars($this->habilitacao))) { FETCH_PROPS_LATE para que o
$this->habilitacao->$name = $value; PDO comece a “colocar” os valores
} else { do objeto após a chamada do método
$this->$name = $value; construtor.
} Com isso podemos decorar nosso
} objeto e mapear um relacionamento
1..1, como neste exemplo.
}
PDO::FETCH_CLASS + PDO::FETCH_PROPS_LATE
include 'conexao.php';
include ‘Funcionario.php’;
include ‘Habilitacao.php’;

$statement = $pdo->prepare(
"SELECT * FROM funcionario "
. "LEFT JOIN habilitacao "
. "ON funcionario.id = habilitacao.funcionario_id");
$statement->execute();

$funcionarios = $statement->fetchAll(\PDO::FETCH_CLASS | \PDO::FETCH_PROPS_LATE,


Funcionario::class);

foreach ($funcionarios as $funcionario) {


echo "{$funcionario->nome} com Habilitação nº {$funcionario->habilitacao->numero} <br/>";
}
PDO::FETCH_OBJ
<?php

include_once "conexao.php";
PDO::FETCH_OBJ:
Retorna os registros em
$statement = $pdo->query('SELECT * FROM livro');
forma de objetos
$livros = $statement->fetchAll(PDO::FETCH_OBJ);
genéricos (instâncias de
foreach ($livros as $livro) {
StdClass).
echo "instância de ".get_class($livro).":";
echo $livro->titulo."</br>";
}
fetchObject
<?php Vale a pena salientar que o fetchObject
cria a instância e seta os valores antes
include 'conexao.php'; mesmo do método construtor ser
executado.
class Livro {

public function __construct($etiqueta = null) {


$this->etiqueta = $etiqueta;
}

$statement = $pdo->query("SELECT * FROM livro");


$livro = $statement->fetchObject(Livro::class, [123456]);
var_dump($livro);
PDO:FETCH_INTO
<?php
class Livro { PDO::FETCH_INTO:
public $titulo; Permite atualizar uma instância existente da
public $preco; classe solicitada, mapeando as colunas do
public $isbn; conjunto da query para os atributos nomeadas
public $edicao;
public $ano_publicacao; na classe.
}

$livro = new Livro();

$statement = $pdo->query('SELECT * FROM livro'); Atenção: Diferente do


$statement->setFetchMode(PDO::FETCH_INTO, $livro); FETCH_CLASS, o FETCH_INTO
$statement->fetch(); não é capaz de modificar valores de
atributos privados ou protegidos
var_dump($livro);
PDO::FETCH_CLASS + PDO::FETCH_SERIALIZE
<?php $statement = $pdo->query('SELECT dados FROM log');
$statement->setFetchMode(PDO::FETCH_CLASS|PDO::FETCH_SERIALIZE,
include 'conexao.php'; Log::class);
$logs = $statement->fetchAll();
class Log implements \Serializable { foreach ($logs as $log) {
public $id; echo "id: $log->id | ";
public $dados; echo "dados: " . var_export($log->dados, true);
echo "<br/>";
public function serialize() { }
return serialize((array) $this);
}
public function unserialize($serialized): void {
foreach (unserialize($serialized) as $p => $v) { PDO::FETCH_SERIALIZE: Tem efeito similar ao
$this->{$p} = $v;
} FETCH_INTO porém é utiliza os
}
}
comportamentos da serialização (interface) nos
objetos.
PDO (operações com cursor)
● Quando um cursor é criado para uma consulta, é possível iterar sobre o
conjunto de linhas sem obter o resultado inteiro da mesma de uma só vez.
● Com um cursor não rolável (forward-only) é possível efetuar FETCH em cada
linha no máximo uma vez, e o cursor se move automaticamente para a linha
seguinte.
● Já os cursores roláveis (scrollable) permitem iterar o resultado em diversas
direções, inclusive para trás e por isso podem acessar a mesma linha no
conjunto do resultados várias vezes. Assim, modificações de dados (inserir,
atualizar, excluir operações) de outras transações podem ter um impacto no
conjunto de resultados.
PDO Cursores (Exemplo Pedidos)
<?php
include_once '../conexao_postgres.php'; //sqlserver, oracle e postgres
$query = "select * from pedido order by id";
$statement = $pdo->prepare($query, [PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL]);
Em SGBDs que
$statement->execute(); suportam o recurso
de cursor scroll, é
$pedido = $statement->fetch(PDO::FETCH_LAZY, PDO::FETCH_ORI_FIRST); possível, no momento
print "Primeiro pedido (id:{$pedido['id']}) ocorreu em : {$pedido['data']}<br/>"; do método fetch(),
posicionar o cursor
$pedido = $statement->fetch(PDO::FETCH_LAZY, PDO::FETCH_ORI_NEXT);
print "Próximo pedido (id:{$pedido['id']}) ocorreu em : {$pedido['data']}<br/>";
em diferentes pontos
do resultado, bem
$pedido = $statement->fetch(PDO::FETCH_LAZY, PDO::FETCH_ORI_LAST); como movimentá-lo
print "Último pedido (id:{$pedido['id']}) ocorreu em: {$pedido['data']}<br/>"; para frente ou para
trás.
$pedido = $statement->fetch(PDO::FETCH_LAZY, PDO::FETCH_ORI_PRIOR);
print "Penúltimo pedido (id:{$pedido['id']}) ocorreu em: {$pedido['data']}<br/>";
No SQL Server o ABS
$pedido = $statement->fetch(PDO::FETCH_LAZY, PDO::FETCH_ORI_ABS, 3); começa com zero.
print "Terceiro pedido (id:{$pedido['id']}) em: {$pedido['data']}<br/>";
PDO Exception

<?php
O PDO também faz parte da Taxonomia de
include_once 'conexao.php'; Throwable e possui uma Exception com
informações diretamente específicas do
try{ SGBD que podem auxiliar no tratamento do
erro.
$pdo->query('SELECT * FROM nao_existe');

} catch (\PDOException $t) {

echo "mensagem:".$t->getMessage()."<br/>". Atenção: Para que o PDO lance


"código:".$t->getCode(); exceções, é necessário utilizar o
} atributo de conexão
PDO::ATTR_ERRMODE com o valor
PDO::ERRMODE_EXCEPTION.
SQL DML: Inserção, Atualização e Remoção
● Os recursos da linguagem SQL são normalmente divididos em conjuntos
onde cada um destes possui um propósito específico.

● Um destes conjuntos é chamado de DML (Data Manipulation Language /


Linguagem de Manipulação de Dados).

● O DML é composto pelas seguintes instruções (statements): INSERT,


UPDATE e DELETE.

● É fortemente recomendado utilizar prepared statement ao executar qualquer


instrução DML no PDO.
PDO (Inserção)
<?php

include_once “conexao.php”;

try { A instrução
$statement = $pdo->prepare("INSERT INTO funcionario (nome, cpf)” (statement) INSERT
. “VALUES (?,?)"); SQL permite adicionar
$statement>execute([$nome, $cpf]); um ou mais registros
a qualquer tabela
} catch (\PDOException $t) { única em um banco
de dados relacional.
echo "mensagem:".$t->getMessage()."<br/>".
"código:".$t->getCode();
}
PDO (Atualização)
<?php

include_once “conexao.php”; A instrução


(statement) UPDATE
try { SQL permite alterar
os dados de um ou
$stmt = $pdo->prepare("UPDATE livro SET preco += 1 WHERE id= :id "); mais registros em
$stmt->execute([‘id’=>$id]); uma tabela. Todas as
linhas podem ser
} catch (\PDOException $t) { atualizadas ou um
subconjunto pode ser
echo "mensagem:".$t->getMessage()."<br/>". escolhido usando
"código:".$t->getCode(); uma condição
} (WHERE).
PDO (Remoção)
<?php A instrução (statement)
DELETE SQL permite
include_once “conexao.php”; remover um ou mais
registros de uma tabela.
Um subconjunto pode
try { ser definido para
$stmt = $pdo->prepare("DELETE FROM livro WHERE id= :id "); exclusão usando uma
$stmt->execute([‘id’=>$id]); condição (WHERE),
caso contrário, todos os
} catch (\PDOException $t) { registros serão
removidos. Alguns
echo "mensagem:".$t->getMessage()."<br/>". SGBDs, como o MySQL,
"código:".$t->getCode(); permitem a exclusão de
} linhas de várias tabelas
com uma instrução
DELETE (multi-table
delete)
Conjunto de DMLs (sem transação)
UPDATE conta_corrente SET saldo = saldo - 200 WHERE cliente_id = 1;
select sleep(30); -- se durante este tempo o SGBD cair, a próxima instrução nunca ocorrerá
UPDATE conta_corrente SET saldo = saldo + 200 WHERE cliente_id = 2;

É muito comum a utilização de duas ou mais instruções SQL DML de forma sequencial para
cumprir a lógica de um caso de uso da aplicação.
Um exemplo seria o caso de uso: “transferência bancária”
Neste exemplo, R$ 200 serão “transferidos” da conta do cliente 1 para o cliente 2.
PDO x Transação
● Uma transação, no contexto de um banco de dados, é uma unidade lógica que é executada de
forma independente para recuperação ou atualização de dados.
● No SQL ANSI uma transação começa com BEGIN TRANSACTION e, após a mesma, todas as
instruções serão parte desta transação.
● Para “confirmar” a transação, faz-se necessário utilizar a instrução COMMIT
● Para “cancelar” todas as instruções da transação e retornar o banco ao estado original, faz-se
necessário utilizar o comando ROLLBACK
● Em bancos de dados relacionais, as transações do banco de dados devem ser atômicas,
consistentes, isoladas e duráveis - resumidas como o acrônimo ACID.
● Alguns SGBDs como o MySQL, utiliza outra sintaxe (START ao invés de BEGIN). Utilizando o PDO
estas diferenças são suprimidas pois o mesmo possui um método único para todos.
Transação ACID
● Atomicidade: Atomicidade garante que cada transação seja tratada de forma "unitária" e, se alguma das
instruções que constituem uma transação não for concluída, a transação inteira falhará e o banco de dados
permanecerá inalterado;

● Consistência: A consistência garante que uma transação só pode trazer o banco de dados de um estado
válido para outro, mantendo as regras do banco: quaisquer dados gravados no banco de dados devem ser
válidos de acordo com todas as regras definidas, incluindo restrições, triggers e qualquer combinação dos
mesmos. Isso evita corrupção do banco de dados por uma transação ilegal, mas não garante que uma
transação esteja correta;

● Isolamento: As transações geralmente são executadas simultaneamente (por exemplo, ler e gravar em
várias tabelas ao mesmo tempo). O isolamento garante que a execução simultânea de transações deixe o
banco de dados no mesmo estado que teria sido obtido se as transações fossem executadas
sequencialmente. O isolamento é o principal objetivo do controle de concorrência;

● Durabilidade: A durabilidade garante que uma vez que uma transação tenha sido confirmada, ela
permanecerá comprometida mesmo no caso de uma falha no sistema (por exemplo, falta de energia ou
falha). Isso geralmente significa que as transações concluídas (ou seus efeitos) são registradas na
memória não volátil.
PDO Transaction (Inserção)
<?php Neste exemplo, dois
inserts são
include_once “conexao.php”; executados dentro de
uma transação,
try { porém, apenas com a
$pdo->beginTransaction(); confirmação feita com
$stmt = $pdo->prepare("INSERT INTO funcionario (nome) VALUES (?)"); o commit, é que as
foreach (['José da Silva','Maria das Dores'] as $name){ mesmas serão de
$stmt->execute([$name]); facto executadas.
}
$pdo->commit(); Para que a transação
}catch (Exception $e){ não fique aberta em
$pdo->rollback(); caso de erro,
throw $e; utilizaremos o rollback
} dentro do catch
PDO Transaction (Atualização)
<?php

include_once “conexao.php”;

try {
$pdo->beginTransaction();
$stmt = $pdo->prepare("UPDATE livro SET preco += 1 WHERE id= :id ");
$stmt->execute([‘id’=>$id]);
$pdo->commit();
}catch (Exception $e){
$pdo->rollback();
throw $e;
}
PDO Transaction (Remoção)
<?php

include_once “conexao.php”;

try {
$pdo->beginTransaction();
$stmt = $pdo->prepare("DELETE FROM livro WHERE id= :id ");
$stmt->execute([‘id’=>$id]);
$pdo->commit();
}catch (Exception $e){
$pdo->rollback();
throw $e;
}
PDO::lastInsertId
● Muitas vezes, na lógica da aplicação, faz-se necessário persistir
mais de uma entidade e manter o relacionamento entre elas.

● Para isso, é preciso recuperar a chave primária da entidade forte e


utilizar como chave estrangeira na entidade fraca.

● O PDO possui um método chamado lastInsertId() que permite


recuperar a última chave primária persistida no banco. Infelizmente
nem todos os bancos/drivers suportam esse recurso e faz-se
necessário utilizar algum recurso proprietário dos mesmos.
PDO::lastInsertId
<?php if($pdo->getAttribute(PDO::ATTR_DRIVER_NAME) != 'oci'){
include 'conexao.php'; $funcionario_id = $pdo->lastInsertId();
try {
}
$pdo->beginTransaction();
$sql = "INSERT INTO funcionario (nome, cpf) VALUES(:nome,:cpf) "; $sql2 = "INSERT INTO habilitacao (numero, categoria,
if($pdo->getAttribute(PDO::ATTR_DRIVER_NAME) == 'oci'){
funcionario_id) VALUES(:numero,:categoria,:funcionario_id) ";
$sql .= 'RETURNING id INTO :last_id';
} $statement2 = $pdo->prepare($sql2);
$statement2->execute(['95685512398','B',$funcionario_id]);
$statement = $pdo->prepare($sql);
$pdo->commit();
$statement->bindValue('nome','Jaqueline');
$statement->bindValue('cpf','12269736044');
} catch (PDOExecption $e) {
if($pdo->getAttribute(PDO::ATTR_DRIVER_NAME) == 'oci'){ $dbh->rollback();
$statement->bindParam('last_id', $funcionario_id,
print "Error!: " . $e->getMessage() . "</br>";
PDO::PARAM_INT, 8);
} }
$statement->execute();
PDO x BLOB
● A maioria dos SGDS tem suporte ao armazenamento de BLOBs
● Um Binary Large Object (BLOB) é uma coleção de dados binários armazenados como uma
entidade única em um sistema de gerenciamento de banco de dados. Os blobs são tipicamente
imagens, áudio ou outros objetos multimídia, embora às vezes o código executável binário seja
armazenado como um blob.
● Com o PDO o bind (vinculação) de um valor BLOB é feito utilizando a tipagem como LOB através
do PARAM_LOB
● Alguns bancos como o SQL Server exigem o uso de um constante proprietária para indicar
corretamente ao Drive ODBC o uso recurso.
● Outros bancos como o Oracle exigem a necessidade da criação de um BLOB vazio via SGBD e,
através de um ponteiro virtual de arquivo (resource) a “persistência” dos dados.
PDO: Inserção de Binário (formulário)
<!DOCTYPE html>
<html>
<head>
<title>Incluir Nova Foto</title>
<meta charset="utf-8"/>
</head>
<body>
<form action="blob_action.php" method="post" enctype="multipart/form-data">
Funcionário: <select name="funcionario_id">
<?php include 'conexao.php'; Neste exemplo, será submetido via
$funcionarios = $pdo->query('SELECT id, nome FROM funcionario') formulário o id do funcionário e uma
->fetchAll(PDO::FETCH_KEY_PAIR); imagem que será persistida na tabela
foreach($funcionarios as $key => $value){ foto.
echo "<option value='$key'>$value</option>";
}
?>
</select>
Foto: <input type="file" name="foto" accept="image/*"><br>
<input type="submit" value="cadastrar"/>
</form>
</body>
</html>
PDO: Inserção de Binário (action - parte 1)
<?php

include 'conexao.php';

try {
$pdo->beginTransaction();

$funcionario_id = $_REQUEST['funcionario_id'];
Devido às peculiaridades do Oracle,
$arquivo = $_FILES['foto']['tmp_name']; faz-se necessário particularizar o bind
$binario = file_get_contents($arquivo); dos parâmetros, primeiramente,
$mimetype = $_FILES['foto']['type']; criando um BLOB vazio com a função
Oracle EMPTY_BLOB() e recuperar o
$sql = "INSERT INTO foto (binario, mimetype, funcionario_id) "; resource do mesmo no placeholder
$sql_values = " VALUES (:binario, :mimetype, :funcionario_id)"; :binario

$driver = $pdo->getAttribute(PDO::ATTR_DRIVER_NAME);
if ($drive == 'oci') {
$sql_values = " VALUES (EMPTY_BLOB(), :mimetype, :funcionario_id)"
. " RETURNING binario INTO :binario";
}
PDO: Inserção de Binário (action - parte 2)
$statement = $pdo->prepare($sql . $sql_values);
switch ($driver) {
case 'sqlsrv':
$statement->bindParam('binario', $binario, PDO::PARAM_LOB, 0, PDO::SQLSRV_ENCODING_BINARY);
break;
case 'oci':
$statement->bindParam('binario', $binario_resource, PDO::PARAM_LOB);
$binario_resource = fopen($arquivo, 'rb');
break;
default:
$statement->bindParam('binario', $binario, PDO::PARAM_LOB);
break;
}
$statement->bindValue('mimetype', $mimetype, PDO::PARAM_STR);
$statement->bindValue('funcionario_id', $funcionario_id, PDO::PARAM_INT);
$statement->execute();
$pdo->commit();
} catch (\PDOException $ex) {
$pdo->rollback();
echo $ex->getMessage();
}
Tipo Resource
● Um resource é uma variável especial, mantendo uma referência a um
recurso externo. Recursos são criados e usados por funções especiais.
● Resources normalmente funcionam como identificadores (referências)
especiais para arquivos abertos, conexões de banco de dados, áreas de tela
de imagem e semelhantes.
● Devido a natureza dos resources, a conversão dos mesmos não é possível.
Recuperação de binários do Banco (blob/varbinary)
<!DOCTYPE html> <?php
<html lang="pt-BR"> include 'conexao.php';
<head>
<title>Foto de BLOB</title> $id = $_REQUEST['funcionario_id'];
<meta charset="UTF-8">
try {
</head>
$statement = $pdo->prepare("SELECT * FROM
<body>
<img src="carrega_foto.php?funcionario_id=7" alt="foto do funcionário" /> foto WHERE funcionario_id = ? ");
</body> $statement->execute([$id]);
</html> $foto = $statement->fetch(PDO::FETCH_ASSOC);
} catch (Exception $exc) {
echo $exc->getTraceAsString();
}
Neste exemplo recuperamos uma imagem armazenada no banco. Alguns
drivers utilizam um link em forma de resource (recurso) para acessar o binário
ob_clean();
de forma otimizada. Para estes casos, utilizamos o stream_get_contents()
header("Content-type: {$foto['mimetype']}");
para recuperar o conteúdo binário.
if (is_resource($foto['binario'])) {
echo stream_get_contents($foto['binario']);
ob_clean() é uma função do PHP para ajudar a limpar o “output buffer” e evitar
} else {
algum caráter indesejável na composição do echo do binário, o que poderia
echo ($foto['binario']);
corromper o mesmo
}
PDO - Formatação de datas (dd/mm/YYYY)
<?php
include 'conexao.php';
switch ($pdo->getAttribute(PDO::ATTR_DRIVER_NAME)) {
case 'mysql': Normalmente, os SGBDs armazenam as
$data = "DATE_FORMAT(data, '%d/%m/%Y')"; datas utilizando o padrão YYYY-MM-DD.
break;
case 'sqlsrv': //>= 2012 Existem diferentes maneiras para
$data = "FORMAT(data, 'd', 'pt-BR')"; recuperar datas no formato brasileiro,
break; dentre elas, podemos utilizar funções
case 'pgsql':
case 'oci':
específicas de SQL de cada SGBD (t-sql,
$data = "TO_CHAR(data, 'dd/mm/yyyy') as"; plsql etc.) para já recuperar, diretamente
break; da query, a data formatada.
}
$statement = $pdo->query("SELECT $data data FROM pedido"); Lembrando que esta formatação também
$pedidos = $statement->fetchAll(); pode ser feita utilizando o format() da
classe Date conforme demonstrado aqui.
foreach ($pedidos as $pedido) {
echo $pedido['data']."<br/>";
}
PDO (paginação)
● O recurso/técnica de paginação em repositórios de dados permite que
uma parte dos dados seja carregada por demanda do usuário.

● Com a paginação do lado do servidor, o número de registros de uma


consulta também será limitada pelo limite estabelecido na paginação.

● O número e o tamanho das páginas digitais em um documento são


limitados pela quantidade de dados no repositório de dados, não pelos
dispositivos de vídeo ou pela quantidade de “papel”.
PDO paginação (parte 1)
<?php
include_once 'conexao.php';

$pagina = (isset($_REQUEST['pagina'])) ? $_REQUEST['pagina'] : 1;


$limit = 5;
$inicio = $pagina * $limit;
$offset = ($pagina - 1) * $limit;

$query = "SELECT id, titulo, preco, isbn, edicao, ano_publicacao FROM livro ";
$query_total = $pdo->query("SELECT COUNT(*) FROM ($query) q");
$total = $query_total->fetchColumn();
$statement = limit($pdo, $query, $limit, $offset);
$livros = $statement->execute();
PDO (paginação parte 2)
function limit($pdo, string $query, int $limit, int $offset, string $order = 'id') : \PDOStatement{

$query_limit = "";
switch ($pdo->getAttribute(PDO::ATTR_DRIVER_NAME)) {
case 'sqlsrv': //>= 2012
case 'oci': //>= 12c
$query_limit = "$query ORDER BY $order OFFSET :offset ROWS FETCH NEXT :limit ROWS ONLY";
break;
default: //mysql e postgres
$query_limit = "$query ORDER BY $order LIMIT :limit OFFSET :offset";
break;
}
$statement = $pdo->prepare($query_limit);
$statement->bindValue(':offset', (int) $offset, PDO::PARAM_INT);
$statement->bindValue(':limit', (int) $limit, PDO::PARAM_INT);
return $statement;

}
PDO paginação (parte 3)

function montaLinha(array $row, $tag = 'td'){


return "<tr>".implode('',array_map(function($row) use ($tag){
return "<$tag>" . $row . "</$tag>";
}, $row))."</tr>";
}

echo "<table border>";


echo montaLinha(['ID','Título','Preço','ISBN','Edição','Ano'], 'th');
while ($row = $statement->fetch()){
echo montaLinha($row);
}
echo "</table>";

echo (($pagina-1) > 0) ? "<a href='index.php?pagina=".($pagina-1)."'>Anterior</a>" : "Anterior";


echo "&nbsp";
echo (($pagina)*$limit < $total) ? "<a href='index.php?pagina=".($pagina+1)."'>Próximo</a>" : "Próximo";
PDO - Paginação com Filtro
● Muitas vezes é necessário permitir que o usuário possa recuperar um
subconjunto específico dos dados persistidos pelo sistema
● Com o recurso do formulário é possível permitir que o usuário possa escolher
e/ou digitar determinados valores que, aplicados à query, afetará o resultado
final exibido na lista/tabela
● Utilizando paginação síncrona, faz-se necessário persistir o filtro nos links da
paginação permitindo que, via get, os valores possam ser reutilizados na
próxima página pela query.
PDO Paginação com Filtro (parte 1)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"> Neste formulário,
<title></title> usaremos o PHP
</head> para recuperar os
<body>
<form> valores dos campos
<label>Nome:</label> de pesquisa, caso
<input name="nome" value="<?php echo isset($_REQUEST['nome']) ? $_REQUEST['nome'] : '';?>"/> os mesmos tenham
<label>CPF:</label> sido usados (e
<input name="cpf" value="<?php echo isset($_REQUEST['cpf']) ? $_REQUEST['cpf'] : '';?>"/>
<input type="submit" value="filtrar" />
repassados pelos
</form> links da paginação
e/ou submissão do
próprio formulário).
PDO Paginação com Filtro (parte 2)
<?php
// put your code here
include 'conexao_oracle.php';

function limit(\PDO $pdo, string $query, int $limit, int $offset, string $order = 'id'): \PDOStatement {
$query_limit = "";
switch ($pdo->getAttribute(PDO::ATTR_DRIVER_NAME)) {
case 'sqlsrv':
case 'oci':
$query_limit = "$query ORDER BY $order OFFSET :offset ROWS FETCH NEXT :limit ROWS ONLY";
break;
default:
$query_limit = "$query ORDER BY $order LIMIT :limit OFFSET :offset";
break;
}
$statement = $pdo->prepare($query_limit);
$statement->bindValue('offset', (int) $offset, PDO::PARAM_INT);
$statement->bindValue('limit', (int) $limit, PDO::PARAM_INT);
return $statement;
}
PDO Paginação com Filtro (parte 3)
$pagina = (isset($_REQUEST['pagina'])) ? $_REQUEST['pagina'] : 1;
unset($_REQUEST['pagina']);
$parametros = [];
$nome = "";
$cpf = "";
$limit = 5;
$inicio = $pagina * $limit;
$offset = ($pagina - 1) * $limit;
$query = "SELECT * FROM funcionario WHERE 1=1 ";
if(!empty($_REQUEST['nome'])){
$nome = $_REQUEST['nome'];
$parametros['nome'] = $nome;
$query .= " AND nome LIKE :nome";
}
if(!empty($_REQUEST['cpf'])){
$cpf = $_REQUEST['cpf'];
$parametros['nome'] = $cpf;
$query .= " AND cpf LIKE :cpf";
}
PDO Paginação com Filtro (parte 4)
$query_total = $pdo->prepare("SELECT COUNT(*) FROM ($query) q");
$query_total->execute($parametros);
$total = $query_total->fetchColumn();
$statement = limit($pdo, $query, $limit, $offset);
(!$nome) ?: $statement->bindValue('nome', "%$nome%");
(!$cpf) ?: $statement->bindValue('cpf', "%$cpf%");
$funcionarios = $statement->execute();
echo "<table border>";
echo "<tr><th>Nome</th><th>CPF</th></tr>";
while($funcionario = $statement->fetch()){
echo "<tr>";
echo "<td>{$funcionario['nome']}</td>";
echo "<td>{$funcionario['cpf']}</td>";
echo "</tr>";
}
echo "</table>";
$parametrosUrl = http_build_query($_REQUEST);
echo (($pagina - 1) > 0 ) ? "<a href='paginacao_1.php?pagina=" . ($pagina-1) . "&$parametrosUrl'>Anterior</a>" : "Anterior";
echo "&nbsp";
echo (($pagina) * $limit < $total) ? "<a href='paginacao_1.php?pagina=". ($pagina+1) . "&$parametrosUrl'>Próximo</a>" :
"Próximo";
?>
</body>
</html>
PDO e Information Schema
● Com o Information Schema é possível fazer uma introspecção nas tabelas do
SGBD.

● Informações de metadados como campos obrigatórios, tipos e ou até limites


de tamanho podem ser obtidos para, por exemplo, validar entrada dos
usuários de forma dinâmica.

● Tal recurso é primordial para tornar dinâmico algumas tarefas repetitivas


como validação de campos e essencial na construção de uma biblioteca
ORM.
PDO e Information Schema
<?php
include 'conexao_oracle.php';

$driver = $pdo->getAttribute(\PDO::ATTR_DRIVER_NAME);
Neste exemplo será
recuperado os
$table = 'editora'; metadados de cada
$colunas = 'COLUMN_NAME, IS_NULLABLE, DATA_TYPE, coluna da tabela
CHARACTER_MAXIMUM_LENGTH'; editora.
$from = 'information_schema.COLUMNS';
if($driver == 'oci'){
Como o Oracle não
$table = strtoupper($table);
$from = 'all_tab_columns'; suporta o Information
$colunas = 'column_name, nullable as IS_NULLABLE, data_type, data_length as Schema ANSI, faz-se
CHARACTER_MAXIMUM_LENGTH'; necessário uma
} adaptação para
$query = "SELECT $colunas " utilizar seu
. " FROM $from WHERE table_name = ?";
equivalente.
$statement = $pdo->prepare($query);
$statement->execute([$table]);
$schema = $statement->fetchAll();
PDO e Information Schema
echo "<table>";
echo "<tr><th>name</th><th>is null?</th><th>type</th><th>size</th></tr>";
foreach($schema as $coluna_schema){
$coluna_schema = array_change_key_case($coluna_schema, Para compatibilizar a
CASE_UPPER); caixa utilizada por
echo "<tr>"; alguns SGBDs, o
echo "<td>{$coluna_schema['COLUMN_NAME']}</td>"; array_change_key_c
echo "<td>{$coluna_schema['IS_NULLABLE']}</td>"; ase com a constante
echo "<td>{$coluna_schema['DATA_TYPE']}</td>"; CASE_UPPER
echo "<td>{$coluna_schema['CHARACTER_MAXIMUM_LENGTH']}</td>"; manterá todos os
echo "</tr>"; índices do resultado
} do fetchAll() em caixa
echo "</table>"; alta (padrão ansi do
information schema)
Estruturas de Dados com Classes SPL (Standard PHP Library)

● A Biblioteca Padrão do PHP (SPL) é uma coleção de interfaces e classes que


se destinam a solucionar problemas comuns.
● Nenhuma biblioteca externa é necessária para construir essa extensão e está
disponível e compilada por padrão desde o PHP 5.0.
● A SPL fornece um conjunto de:
○ Estrutura de dados (array, pilha, fila etc.)
○ Iteradores para percorrer objetos,
○ Interfaces,
○ Exceptions
SplFixedArray
● A classe SplFixedArray fornece as principais funcionalidades do array. A
principal diferença entre um SplFixedArray e um array PHP normal é que o
SplFixedArray é de tamanho fixo e permite apenas inteiros como valores para
os índices.

● Notoriamente o SplFixedArray consome um número menor de memória RAM


e, muitas vezes, também é mais rápido quando comparado ao array
“tradicional” do PHP.
SplFixedArray
<?php
0 1 2
$fixed = new SplFixedArray(3);

$fixed[0] = 'A';
$fixed[1] = 'B';
$fixed[2] = 'C'; 0 1 2

foreach ($fixed as $item) { A B C


echo $item, PHP_EOL;
}
0 1
$fixed->setSize(2); //diminuindo o array
A B
foreach ($fixed as $item) {
echo $item, PHP_EOL;
}
SplDoublyLinkedList (Lista Duplamente Encadeada)
● Classe genérica que representa a estrutura de uma fila duplamente encadeada.
● Permite a iteração bidirecional da lista e implementa as mesmas interfaces que o SplFixedArray.
● Ela também serve como a classe base para as classes SplStack e SplQueue, que também
implementam as estruturas de dados de pilha e fila.
● Através do método setIteratorMode, o Lista encadeada pode ser organizada usando FIFO ou LIFO.
● Esta implementação não é circular, por isso, não existe uma referência entre os elementos das
extremidades.

head tail

A B C
NULL NULL
SplDoublyLinkedList (iteração, cabeça e cauda)

<?php $prev = null;


$dll = new \SplDoublyLinkedList(); $dll->rewind(); //rebobinando

$dll->push("laranja"); while ($dll->valid()) {


$dll->push("banana"); $current = $dll->current();
$dll->push("limão"); echo 'Anterior: '.$prev, "<br/>";
$dll->push("maçã"); echo 'Atual: '.$current, "<br/>";
$dll->push("uva"); $prev = $current;
$dll->push("abacaxi"); $dll->next();
$next = $dll->current();
head echo "Cabeça: ". $dll->bottom(). "<br/>"; echo 'Próximo: '.$next. "<br/>"; tail
echo "Cauda: ". $dll->top(). "<br/>"; echo "<br/>";
}

laranja banana limão maça uva abacaxi


NULL
NULL
SplDoublyLinkedList (métodos)
<?php function imprimir(\SplDoublyLinkedList &$dll) {
$dll = new \SplDoublyLinkedList();
$dll->unshift(200); //no início $dll->rewind();
imprimir($dll); $values = [];
$dll->unshift(100); //no início while ($dll->valid()) {
imprimir($dll); $values[] = $dll->current();
$dll->push(34); //no fim $dll->next();
imprimir($dll); }
$dll->push(35); //no fim echo "[ " . implode(' , ', $values) . " ] </br>";
imprimir($dll); }
$dll->add(2, 3); //posição específica
imprimir($dll);
$dll->unshift(670); //no início
imprimir($dll);
$dll->add(3, 450); //posição específica
imprimir($dll);
$dll->pop(); //remove o último
imprimir($dll);
$dll->shift(); //remove o primeiro
imprimir($dll);
$dll->offsetUnset(1); //remove de posição específica (2ª)
imprimir($dll);
FIFO e LIFO
● FIFO: Comportamento First in, first out (primeiro a entrar, primeiro a sair) [Fila / Queue];
● Exemplos de FIFO:

○ Scheduling de CPU e Disco.


○ Fila da impressora: os trabalhos enviados para a impressora são impressos na ordem de chegada.
○ Transferindo dados de maneira assíncrona entre dois processos (E / S de Arquivo, Pipes, buffers de E / S,
etc.)
○ App de gerenciamento fila em bilheteiras, hospitais etc.

● Comportamento Last in, first out (última a entrar, primeiro a sair). [Pilha / Stack]
● Exemplos de LIFO:

○ Mecanismo Desfazer / Refazer em editores de texto e outras aplicações (CTRL+Z);


○ Verificação de sintaxe do compilador para chaves correspondentes
○ Uma pilha de pratos ou livros ou cadeiras.
○ Backtracking: Este é um processo quando você precisa acessar o elemento de dados mais recente em uma
série de elementos.
○ Inverter uma palavra
SplDoublyLinkedList (Modo FIFO)

<?php

//FIFO
$fifo = new \SplDoublyLinkedList();

$fifo->setIteratorMode(\SplDoublyLinkedList::IT_MODE_FIFO);

$fifo->push("laranja");
$fifo->push("banana");
$fifo->push("limão");
$fifo->push("maçã");
$fifo->push("uva");
$fifo->push("abacaxi");

foreach ($fifo as $value) {


echo $value."<br/>";
}
SplDoublyLinkedList (Modo LIFO)

<?php

//FIFO
$fifo = new \SplDoublyLinkedList();

$fifo->setIteratorMode(\SplDoublyLinkedList::IT_MODE_LIFO);

$fifo->push("laranja");
$fifo->push("banana");
$fifo->push("limão");
$fifo->push("maçã");
$fifo->push("uva");
$fifo->push("abacaxi");

foreach ($fifo as $value) {


echo $value."<br/>";
}
SplDoublyLinkedList (Modo Delete)
<?php
$dll = new \SplDoublyLinkedList();

$dll->setIteratorMode(\SplDoublyLinkedList::IT_MODE_DELETE);

$dll->push("laranja"); Com o modo de Iteração Delete, os


$dll->push("banana"); item são removidos da lista
$dll->push("limão");
$dll->push("maçã");
duplamente encadeadas, conforme
$dll->push("uva"); os mesmos são iterados.
$dll->push("abacaxi");

foreach ($dll as $value) { O modo default é KEEP, que


echo $value."<br/>"; mantém os itens na lista.
echo "Tamanho atual: ".$dll->count();
}
echo "Tamanho atual: ".$dll->count();
Pilha (SplStack) / LIFO
<?php

$stack = new SplStack();


3
$stack[] = 1;
$stack[] = 2;
2
$stack[] = 3;

foreach ($stack as $item) {


1
echo $item, PHP_EOL;
}
Fila (SplQueue) / FIFO
<?php

$queue = new SplQueue();

$queue[] = 1;
1 2 3
$queue[] = 2;
$queue[] = 3;

foreach ($queue as $item) {


echo $item, PHP_EOL;
}
SplHeap
● Heap é uma estrutura de dados baseada em árvore especializada que é
essencialmente uma árvore quase completa que satisfaz a propriedade heap: em P
um heap máximo, para qualquer nó dado C, se P é um nó pai de C, então a chave (o
valor) de P é maior que ou igual à chave de C. Em uma pilha mínima (MinHeap), a
chave de P é menor ou igual à chave de C. C
● O nó no "topo" do heap (sem pais) é chamado de nó raiz.
● O heap é uma implementação maximamente eficiente de um tipo de dados abstrato chamado de
fila de prioridade e, na verdade, as filas de prioridade são geralmente chamadas de "heaps",
independentemente de como elas podem ser implementadas. Em um heap, o elemento de
prioridade mais alto (ou mais baixo) é sempre armazenado na raiz.
● No entanto, um heap não é uma estrutura classificada; pode ser considerado parcialmente
ordenado.
● Um heap é uma estrutura de dados útil quando é necessário remover repetidamente o objeto/item
com a prioridade mais alta (ou mais baixa).
Spl Heap (Exemplo)
<?php $heap = new CampeonatoBrasileiro();
class CampeonatoBrasileiro extends SplHeap { $heap->insert(['nome' => 'Remo', 'pontuacao' => 22, 'vitorias' => 6]);
$heap->insert(['nome' => 'Santa Cruz', 'pontuacao' => 28, 'vitorias' => 7]);
protected function compare($value1, $value2): int { $heap->insert(['nome' => 'Atlético AC’, 'pontuacao' => 30, 'vitorias' => 9]);
$heap->insert(['nome' => 'Botafogo PB', 'pontuacao' => 26, 'vitorias' => 6]);
if ($value1['pontuacao'] == $value2["pontuacao"]) { $heap->insert(['nome' => 'Náutico', 'pontuacao' => 31, 'vitorias' => 9]);
return $value1['vitorias'] <=> $value2['vitorias']; $heap->insert(['nome' => 'Confiança', 'pontuacao' => 23, 'vitorias' => 5]);
} $heap->insert(['nome' => 'Globo', 'pontuacao' => 22, 'vitorias' => 4]);
return $value1['pontuacao'] <=> $value2['pontuacao'];
} //Campeão:
echo "Campeão da Série C 2018: {$heap->top()['nome']} <br/>";
} //Resultados
$total = $heap->count();
foreach ($heap as $key => $time) {
echo ($total - $key) . " º {$time['nome']} <br/>";
}
MinHeap (SplMinHeap)
<?php

$minHeap = new \SplMinHeap();


$minHeap->insert(30);
$minHeap->insert(50);
$minHeap->insert(10);
$minHeap->insert(105);
$minHeap->insert(99);
$minHeap->insert(88);

echo "mínimo:".$minHeap->top();
echo "<br/>";
foreach ($minHeap as $value) {
echo $value."<br/>";
}
MaxHeap (SplMaxHeap)
<?php

$maxHeap = new \SplMaxHeap();


$maxHeap->insert(30);
$maxHeap->insert(50);
$maxHeap->insert(10);
$maxHeap->insert(105);
$maxHeap->insert(99);
$maxHeap->insert(88);

echo "max:".$maxHeap->top();
echo "<br/>";
foreach ($maxHeap as $value) {
echo $value."<br/>";
}
SplPriorityQueue (Fila de Prioridade)
● Fila de prioridade é uma extensão da fila com as seguintes características:

○ Cada item tem uma prioridade associada a ele.


○ Um elemento com alta prioridade é retirado da fila antes de um elemento com baixa
prioridade.
○ Se dois elementos tiverem a mesma prioridade, eles serão atendidos de acordo com sua
ordem na fila.

● Filas de prioridade são estruturas de dados úteis em simulações, particularmente para manter um
conjunto de eventos futuros ordenados pelo tempo, para que possamos recuperar rapidamente o
que acontecerá. Eles são chamados filas de prioridade porque permitem recuperar itens não pelo
tempo de inserção (como em uma pilha ou fila), nem por uma correspondência de chave (como em
um dicionário), mas por qual item tem a prioridade mais alta de recuperação.
SplPriorityQueue
<?php

$prQueue = new SplPriorityQueue();

$prQueue->insert('A',1);
$prQueue->insert('B',9);
$prQueue->insert('C',7);
$prQueue->insert('D',5);
$prQueue->insert('E',2);
$prQueue->insert('F',4);

foreach ($prQueue as $item) {


echo $item, <br/>;
}
SplPriorityQueue (Flags)
<?php <?php
//flags //flags
$prQueue = new SplPriorityQueue(); $prQueue = new SplPriorityQueue();
$prQueue->insert('A',1); $prQueue->insert('A',1);
$prQueue->insert('B',9); $prQueue->insert('B',9);
$prQueue->insert('C',7); $prQueue->insert('C',7);
$prQueue->insert('D',5); $prQueue->insert('D',5);
$prQueue->insert('E',2); $prQueue->insert('E',2);
$prQueue->insert('F',4); $prQueue->insert('F',4);
$prQueue->insert('G',5); $prQueue->insert('G',5);

$prQueue->setExtractFlags(SplPriorityQueue::EXTR_PRIORITY); $prQueue->setExtractFlags(SplPriorityQueue::EXTR_BOTH);
foreach ($prQueue as $item) { foreach ($prQueue as $item) {
echo $item."<br/>"; echo "prioridade: {$item['priority']} ; dado:{$item['data']}<br/>";
} }

Com o uso do método setExtractFlags é possível determinar qual será o resultado extraído ao recuperar os
dados de um SplPriorityQueue. Seja com os dados (default), apenas o valor da priorização (priority) ou
ambos (both).
SplStorageObject
● A classe SplObjectStorage fornece um mapa de objetos para dados ou, ignorando dados, um
conjunto de objetos. Esse duplo propósito pode ser útil em muitos casos, envolvendo a
necessidade de identificar objetos de forma exclusiva.

● Diferente de um hashmap, o SplObjectStorage não atua como um armazenamento de chave-valor,


mas apenas um conjunto de objetos. Algo está no set ou não, mas sua posição não é importante.

● A "chave" de um elemento no SplObjectStorage é, na verdade, o hash do objeto. Isso faz com que
não seja possível adicionar várias cópias da mesma instância de objeto a um SplObjectStorage,
para que você não precise verificar se já existe uma cópia antes de adicionar.

● A principal vantagem do SplObjectStorage é o fato de que você ganha muitos métodos para lidar e
interagir com diferentes conjuntos (contains(), removeAll(), removeAllExcept () etc).
SplObjectStorage

<?php $storage->attach($o1);
$storage->attach($o2);
class Pessoa { $storage->attach($o3);
public $nome; $storage->attach($o1); //já existe, mesmo hash
} $storage->attach($o4); //estados iguais, objetos diferentes
$storage = new SplObjectStorage(); $storage->detach($o3); //removendo

$o1 = new Pessoa(); //var_dump($storage[0]); //nulo !


$o2 = new Pessoa(); echo "contém o1? ".var_export($storage->contains($o1), true)."</br>";
$o3 = new Pessoa(); foreach($storage as $key => $o){
$o4 = new Pessoa(); var_dump($o);//aqui funciona!
}
$o1->nome = 'João';
$o2->nome = 'Maria';
$o3->nome = 'Thiago';
$o4->nome = 'Maria';
SPLEnum (Conjunto finito de identificadores)
<?php
class MesesDoAno extends SplEnum {

const __default = self::Janeiro; Enum é um tipo de dado definido pelo usuário


const Janeiro = 1; const Fevereiro = 2; que consiste em um conjunto de constantes
const Marco = 3; const Abril = 4; nomeadas chamadas enumeradores.
const Maio = 5; const Junho = 6;
const Julho = 7; const Agosto = 8;
const Setembro = 9; const Outubro = 10;
const Novembro = 11; const Dezembro = 12;
}

echo new MesesDoAno(MesesDoAno::Junho) . "<br/>";


echo MesesDoAno::Novembro . "<br/>"; O SPLEnum faz parte de uma extensão PECL
print_r((new MesesDoAno())->getConstList(true)); chamada SPLTypes. Infelizmente esta
extensão não é mais compatível com PHP 7
try { >=, por isso, faz-se necessário utilizar algum
new MesesDoAno(13); fork (e compilar) ou um polyfill como por
} catch (UnexpectedValueException $uve) {
exemplo o duck-projects.
echo $uve->getMessage() . PHP_EOL;
}
Manipulação de String
● Na maioria das aplicações existe a necessidade de editar, manipular e/ou
comparar textos;

● O PHP fornece muitas funções internas para manipular strings, como calcular
o tamanho de uma string, encontrar substrings ou caracteres, substituir parte
de uma string por caracteres diferentes, separar uma string e muitos outros;

● Além disso, o PHP também possui implementações nativas de algoritmos


avançados de comparação/métrica de string como, por exemplo, o
Levenshtein;
Caixa Baixa e Alta - (Manipulação de String)
<?php
$nome = "José da Silva";
echo "caixa baixa:".mb_strtolower($nome);
O PHP possui um conjunto
echo "caixa alta:".mb_strtoupper($nome);
de funções que permite
echo "caixa alta 1º char :".ucfirst($nome); alterar as caixa (case) de
echo "caixa baixa 1º char :".lcfirst($nome); uma string, seja em sua
totalidade ou em partes dela.
echo "caixa alta 1º char de cada palavra :".ucwords($nome);
Posição e Tamanho de string
<?php

$nome = "José da Silva Silveira";


echo "tamanho:".strlen($nome); strlen: retorna o tamanho de uma string
strrpos: encontra a posição da última ocorrência
echo "existe:".strstr($nome, "s"); de um caractere em uma string
echo "existe:".stristr($nome, "silva"); strripos: o mesmo do strrpos, porém, insensível à
echo "encontrar:".strrpos($nome, "s"); caixa.
strspn: encontra o comprimento do segmento
echo "encontrar:".strripos($nome, "O");
inicial combinando com a máscara.
$digitos = '0123456789'; strrchr: Encontra a última ocorrência de um
$telefone = '02199999999a'; caractere em uma string
if (strlen($telefone) != strspn($telefone,$digitos)){
echo "telefone inválido";
}
Substring
<?php
Uma substring é uma seqüência
$string = "85 bits"; contígua de caracteres dentro de
uma string. Por exemplo, "o melhor
$frase = "o sabiá sabia assobiar"; dos" é uma substring de "Foi o
$path = '/www/public_html/index.html'; melhor dos tempos".

substr: Retorna uma parte de uma


echo substr($string, 1)."\n"; // 5 bits string
echo substr($string, 0, 2)."\n"; // 85 substr_count: Conta o número de
echo substr($string, -4, 4). "\n"; // bits ocorrências de uma substring
strrpos: retorna a posição da ultima
echo substr_count($frase, 'bi'); // 3
ocorrência de uma substring
$arquivo = substr($path, strrpos($path, '/') + 1);
echo $arquivo;
Substituição de String
<?php

$noticias = str_replace("aberto", "fechado", "Hoje o comércio está aberto !");


$vogais = array("a", "e", "i", "o", "u");
$titulo = str_replace($vogais, "", "Olá Seja Bem Vindo ao PHP !");
$conselho = "Você deveria comer frutas, vegetais e fibra todos os dias.";
$saudavel = array("frutas", "vegetais", "fibra");
$gorduroso = array("pizza", "bacon", "sorvete");
$novo_conselho = str_replace($saudavel, $gorduroso, $conselho);
$var = 'ola chuva !';
echo substr_replace($var, 'guarda', 4) . "<br />\n";
echo substr_replace($var, 'guarda-', 4, 0) . "<br />\n";
Funções para Strings com HTML
<?php htmlentities: converte
todos os caracteres
$original = "Eu <i>gosto</i> de estudar <b>PHP</b> !"; aplicáveis em entidades
$original = "Muito &lt;b&gt;bom!&lt;/b&gt;"; html.
html_entity_decode: é o
echo htmlspecialchars($original); oposto da função
echo htmlspecialchars_decode($str); htmlentities() no que
echo htmlspecialchars_decode($str, ENT_NOQUOTES); converte todas as
$a = htmlentities($original); entidades HTML para os
$b = html_entity_decode($a); seus caracteres de string.
echo $a."<br>";
echo $b;
$str = '<p>this -&gt; &quot;</p>';
echo nl2br("Vamos quebrar\n linhas !");
$html = '<p>Um parágrafo</p><!-- Comentário --> <a href="#">Link</a>';
echo strip_tags($html) . "<br>";
echo strip_tags($html, '<p><a>');
Formatação e limpeza
<?php wordwrap: permite “quebrar” string
limitando o número de caracteres em
$string = "Uma palavra enorme em português: inconstitucionalissimamente";
echo wordwrap($string,20,"<br>\n")."<br>\n"; grupos, comumente linhas, através de
$string_com_espacos = " olá "; um separador.
echo ltrim($string_com_espacos)."<br>\n"; ltrim: remove os espaços à esquerda
echo rtrim($string_com_espacos)."<br>\n"; rtrim: remove os espaços à direita
echo trim($string_com_espacos)."<br>\n"; trim: remove os espaços à esquerda e
à direita
Formatação de String
● "Printf" é o nome de uma das principais funções de saída da linguagem C e
significa "impressão formatada".
● O PHP, assim como outras linguagens de programação, também possui uma
implementação do printf, mantendo uma compatibilidade razoável com printf
do C.
● Essa função utiliza o conceito de um parâmetro de “formato”, que é composto
de um conjunto de um ou mais especificadores que começam com um
caractere “%”, indicando o local e o método para converter os dados de
entrada no formato desejado de saída em uma string.
● Importante reforçar que incompatibilidades entre os especificadores de
formato e o tipo de dados podem causar falhas e outras vulnerabilidades.
Formatação (printf)
especificador Tratado como Resultado
e notação científica em caixa baixa
notação científica
E notação científica em caixa alta
f número de ponto flutuante (reconhecimento de localidade)
float
F número de ponto flutuante (sem reconhecimento de localidade)
s string string
u decimal sem sinal
x hexadecimal (caixa baixa)
X hexadecimal (caixa alta)
b Inteiro binário
c caractere ASCII correspondente
d decimal com sinal de positivo ou negativo
o número octal
Printf (Exemplo)
printf (preenchimento)
<?php

printf( "%04d", 12 ); // Resultado: "0012"


printf( "%04d", 1234 ); // Resultado: "1234"
printf( "%04d", 12345 ); // Resultado: "12345"
printf( "% 10s", "Hello" ); // Resultado: " Hello"
printf( "%10s", "Hello" ); // Resultado: " Hello"
printf( "%'*10s", "Hello" ); // Resultado: "*****Hello"
printf( "%'*-10s", "Hello" ); // Resultado: "Hello*****"
Troca de argumento
<?php
//ordem natural:
printf('Existe uma diferença entre o %s and %s', 'bem', 'mal');
//informando posição usando % e a formatação com $:
printf( 'O Brasil possui %2$d regiões e %1$d estados', 27, 5 );
//retornando uma string (e não printando diretamente no output)
$string = sprintf('%3$02d/%2$02d/%1$04d', 1998, 2, 1);
print($string);
Comparação Avançada de Strings

<?php levenshthein: calcula a “distância”


entre duas strings. Esta distância é
$nome1 = "tiago da silva"; definida como o mínimo de caracteres
$nome2 = "thyago da silva"; (passos) necessários para transformar
echo "distâncias: ".levenshtein($nome1, $nome2)."<br/>"; a string1 na string2. Sua
echo "comparação fonética 1:" complexidade é O (m*n);
.soundex($nome1), "&nbsp", soundex($nome2)."<br/>"; soundex: calcula a “chave sonora” de
echo "comparação fonética 2:" uma string.
.metaphone($nome1), "&nbsp", metaphone($nome2)."<br/>"; metaphone: similar ao soundex,
similar_text($nome1, $nome2, $porcentagem); porém mais precisa pois utiliza os
echo "similaridade de textos: " principios básicos da pronuncia de
. $porcentagem." % <br/>"; palavras em inglês.
similar_text: calcula a distância entre
as duas strings, utilizando o algoritmo
de Oliver. Sua complexidade é
O(n**3).
Expressões Regulares
● Comumente conhecidas como "regex" ou "RegExp", expressões regulares
são sequências de caracteres especialmente formatadas para encontrar
padrões em textos.
● Expressões regulares são uma das ferramentas mais poderosas disponíveis
atualmente para processamento e manipulação de textos eficazes e
eficientes.
● Podem ser usadas, por ex., para verificar se o formato dos dados, ou seja,
nome, email, número de telefone etc. digitado pelo usuário estava correto ou
não, localizar ou substituir a sequência correspondente no conteúdo de texto.
● Com o advento do PHP 5.3, a linguagem passou a dar suporte a expressões
regulares no estilo Perl através de sua família preg_ de funções.
Regex no PHP
● O PHP possui um conjunto de funções que trabalham com expressões
regulares, todas com o prefixo “preg”

● PREG é um mnemônico para Perl REGular expression.

● A sintaxe dos padrões usados nessas funções se parece muito com o Perl. A
expressão deve estar entre os delimitadores, uma barra (/), por exemplo.

● O suporte a expressões regulares utilizando a sintaxe POSIX com funções de


prefixo “ereg” foram depreciadas no PHP 7.
Regex (Delimitadores)
Os delimitadores podem ser qualquer caractere
<?php ASCII não alfanumérico e sem espaço em
branco, exceto a barra invertida (\) e o byte
nulo. Se o caractere delimitador precisar ser
$regex_valido = "/a/"; usado na própria expressão, ele precisará ser
$regex_valido = "%a%"; escapado por uma barra invertida.
$regex_valido = "*a*"; Delimitadores correspondentes ao estilo Perl (), {},
$regex_valido = "!a!"; [] e <> também podem ser usados.
Funções de Regex no PHP
<?php

//busca
● preg_match($pattern, $subject, $matches);
● preg_match_all($pattern, $subject, $matches);
● preg_grep($pattern, $input);
● preg_split($pattern, $subject, $limit, $flags);

//substituição
● preg_filter($pattern, $replacement, $subject);
● preg_replace_callback($pattern, $callback, $subject);
● preg_replace_callback_array($patterns_and_callbacks, $subject);

//auxiliares
● preg_last_error();
● preg_quote($str, $delimiter);
Regex: preg_match
<?php
preg_match: busca um padrão ($pattern)
$regex = "/85/"; específico em uma string ($subject) e,
$subject = "Bem vindo ao 85 bits developer"; quando o padrão é encontrado pela
$matches = []; primeira vez, ele para de procurá-lo. Ele é
capaz de preencher um array por
if (preg_match($regex, $subject)) {
echo "encontrado"; referência (&$matches), onde
} else { $matches[0] conterá o texto que
echo "não encontrado"; corresponde ao padrão completo,
} $matches[1] terá o texto que
correspondeu ao primeiro sub-padrão
//passando array por referência
preg_match($regex, $subject, $matches); capturado entre parênteses, e assim por
var_dump($matches); diante.
Regex: preg_match_all
<?php

$regex = "/\w+(ala)/";
$subject = "uma mala com uma bala jogada em uma cala";
$matches = [];
preg_match_all: busca todas
preg_match_all($regex, $subject, $matches); as correspondências em uma
var_dump($matches);
string e as produz em um array
multidimensional ($matches)
ordenado de acordo com as
sinalizações ($flags).
Regex: preg_grep
<?php

$regex = "/Silva/i";
$array = [
'Maria da Silva', 'Luiz Oliveira',
'José da Silva', 'Thiago Silva'
]; preg_grep: retorna os itens do
var_dump(preg_grep($regex, $array));
array que combinaram com o regex.
Regex: preg_split

<?php

$regex = "/\./";
$string = "pudim.com.br";
var_dump(preg_split($regex, $string)); preg_split: divide a string em substrings
dentro de um array utilizando uma
expressão regular.
Regex: preg_replace
<?php
$regex = '/[aeiou]/';
$replacement = 'e';
$string = "O sapo não lava o pé, não lava porque não quer";
var_dump(preg_replace($regex, $replacement, $string)); preg_replace: realiza uma
pesquisa por uma
expressão regular e a
substitui.
Regex: preg_filter
<?php

$regex = '/a/';
$replacement = 'o';
$subject = 'luiz';

var_dump(preg_filter($regex, $replacement, $subject)); preg_filter: é idêntico a preg_replace(),


var_dump(preg_replace($regex, $replacement, $subject));
exceto que apenas retorna o $subject
(possivelmente transformado) onde
houve uma correspondência.
Regex: preg_replace_callback
<?php

$string = '2014-02-22';
$regex = '/(\d{4})-(\d{2})-(\d{2})/';
$resultado = preg_replace_callback($regex, 'dataBr', $string);

function dataBr ($matches) { O comportamento desta função é


return $matches[3].'/'.$matches[2].'/'.$matches[1]; similar ao da preg_replace(), exceto
}
pelo fato que ao invés do parâmetro
echo $resultado; $replacement, é utilizado uma função
ou closure com a responsabilidade de
executar a transformação/substituição.
Regex: preg_quote

<?php

$regex = 'etc… / legal';


$regex = preg_quote($regex, '/');
echo $regex;
Regex: preg_last_error()
PREG_PATTERN_ORDER: 1

PREG_SET_ORDER: 2

PREG_OFFSET_CAPTURE: 256

PREG_SPLIT_NO_EMPTY: 1

PREG_SPLIT_DELIM_CAPTURE: 2

PREG_SPLIT_OFFSET_CAPTURE: 4

PREG_NO_ERROR: 0

PREG_INTERNAL_ERROR: 1
PCRE
● O motor de expressões regulares do PHP é a implementação da biblioteca
PCRE (Perl Compatible Regular Expressions).

● A biblioteca PCRE possui um conjunto de recursos que implementam a


correspondência de padrões de expressão regular usando uma mesma
sintaxe e semântica que o Perl 5, com apenas algumas poucas diferenças.

● Este conjunto de recursos é em sua vasta maioria representado por


caracteres especiais (tokens) que, em caso de necessidade de utilizá-los
como parte integrante da string de busca, as mesmas deverão ser
“escapadas”.
Regex (âncoras)
<?php
//^ começa com...
$subject = "eles gostam de PHP";
$pattern = "/^ele/"; //começa com
Âncoras ou asserções atômicas de
var_dump(preg_match($pattern, $subject));
largura zero, especificam uma
posição na cadeia de caracteres em
que uma correspondência deve
//$ termina com... ocorrer.
$subject = "Eu gosto de estudar";
$pattern = "/estudar$/";
var_dump(preg_match($pattern, $subject)); Quando utilizamos âncora em uma
expressão de pesquisa, o
mecanismo de expressões regulares
não avança pela cadeia de
//começa e termina com...
$subject = "PHP"; caracteres ou consome caracteres,
$pattern = "/^PHP$/"; ele procura uma correspondência
var_dump(preg_match($pattern, $subject)); apenas na posição especificada.
Regex (modificador multi linha)
<?php
//multi linha
$regex = '/^ele/m'; $matches = [];
$string = "eles disseram:\nele gosta sim !";
preg_match_all($regex, $string, $matches);
var_dump($matches);

//apenas inicio da string (mesmo multi linha) Com o uso o modificador m (após
$regex = '/\Aele/m'; $matches = []; os delimitadores da regex), é
$string = "eles disseram:\nele gosta sim !"; possível usar âncoras e outros
preg_match_all($regex, $string, $matches); tokens mesmo quando existir
var_dump($matches); quebra de linhas na string.

//termina com (multi linha)


$regex = '/sim$/m'; $matches = [];
$string = "gosto sim\n gosto disso sim";
preg_match_all($regex, $string, $matches);
var_dump($matches);
Regex (modificador multi linha)
//\z string termina com (mesmo multi linha)
$regex = '/sim\z/m';
$string = "gosto sim\n gosto disso sim";
$matches = [];
preg_match_all($regex, $string, $matches);
var_dump($matches);

Com o uso o modificador m (após os


delimitadores da regex), é possível
usar âncoras e outros tokens mesmo
quando existir quebra de linhas na
string.
Regex (grupos de captura/ subpattern)

<?php

//sem grupos
$string = 'comi muita uva';
preg_match('/uva/', $string, $matches); Ao colocar parte de uma expressão regular
var_dump($matches); entre parênteses, é possível agrupar essa
//com grupos
parte da expressão regular. Isso permite
preg_match('/(u)(v)(a)/', $string, $matches); aplicar um quantificador a todo o grupo ou
var_dump($matches); restringir a alternância a parte da regex.
//grupo "nomeado"
Também é possível nomear/identificar um
$string = 'havia 2 homens e 4 crianças no local';
$regex = '/(?P<numeros>\d)/'; grupo através do uso do
preg_match_all($regex, $string, $matches); ?P<nome_do_grupo>.
var_dump($matches['numeros']);
Regex (quantificadores)
<?php

// * zero ou mais do caracter à esquerda de *


$subject = "goal"; //ou gol
$pattern = "/goa*l/";
var_dump(preg_match($pattern, $subject));

// + um ou mais do caracter à esquerda de +


$subject = "gooooool";
$pattern = "/go+l/";
var_dump(preg_match($pattern, $subject));

// ? zero ou um à esquerda de ?
$subject = "thiago"; // ou tiago
$pattern = "/th?iago/";
var_dump(preg_match($pattern, $subject));

// {n} N repetições do caracter à esquerda


$subject = "golll";
$pattern = "/gol{3}/";
var_dump(preg_match($pattern, $subject));
Regex (quantificadores)
// {nx, ny} mínimo nx e máximo ny repetições do caracter à esquerda
$subject = "goll";
$pattern = "/gol{1,3}/"; //começa com
var_dump(preg_match($pattern, $subject));

// {nx, } mínimo nx de repetições do caracter à esquerda


$subject = "golllllllllllllllllllllllllll";
$pattern = "/gol{1,}/"; //começa com
var_dump(preg_match($pattern, $subject));

// * zero ou mais repetições da string dentro dos parênteses


$subject = "muhahahahahaha";
$pattern = "/mu(ha)*/"; //começa com
var_dump(preg_match($pattern, $subject));

// * zero ou mais repetições da string dentro dos parênteses


$subject = "muhahaha";
$pattern = "/mu(ha){1,3}$/";
var_dump(preg_match($pattern, $subject));
Greedy vs Lazy
<?php Um quantificador greedy (ganancioso)
tenta corresponder a um elemento tantas
$html = '<b>Eu sou bold</b> <i>Eu sou itálico</i> <b>Eu também sou bold</b>';
vezes quanto possível.

//greedy Um quantificador não greedy/ Lazy (lento)


preg_match_all('#<b>(.+)</b>#', $html, $bolds); tenta corresponder a um elemento o
print_r($bolds[1]);
menor número de vezes possível.
//lazy
preg_match_all('#<b>(.+?)</b>#', $html, $bolds); É possível transformar um quantificador
print_r($bolds[1]); greedy em um quantificador lazy
simplesmente adicionando um token ? ou
//lazy com modificador U
preg_match_all('#<b>(.+)</b>#U', $html, $bolds); utilizar o modificador U depois do
print_r($bolds[1]); delimitador final.

A busca lazy é bastante útil ao tentar


executar uma análise simplista de HTML.
Regex (Operador “ou”)
<?php O operador “ou” permite criar
a alternância de matches.
// | seguido pela string a ou b
$string = "ele"; Com uso do operador pipe é
$regex = "/el(e|a)/"; //começa com possível alternar entre
var_dump(preg_match($pattern, $string)); caracteres dentro de um
grupo.

Sem o uso do pipe, basta


// mesmo que o anterior porém sem grupo colocar os caracteres de
$string = "ela"; forma contígua dentro de
$regex = "/el[ea]/"; brackets
var_dump(preg_match($regex, $string));
Regex (classe de caractere)
<?php
// \d dígito (mesmo que [0-9]))
$subject = "tem numero 1 aqui";
$pattern = "/\d/"; //começa com
var_dump(preg_match($pattern, $subject));

// \w caractere alfanumérico + underscore (mesmo que [a-zA-Z0-9_])


$subject = "número ou letra ou underscore 1_";
$pattern = "/\w/"; //começa com
var_dump(preg_match($pattern, $subject));

// \s caractere de espaço (incluindo tab e quebra de linha)


$subject = "tem espaço aqui";
$pattern = "/\s/"; //começa com
var_dump(preg_match($pattern, $subject));

// . qualquer caractere
$subject = "oi1 _";
$pattern = "/./"; //começa com
var_dump(preg_match($pattern, $subject));
Regex (classe de caractere [negação])
//--- Negação ---

// \D precisa ter um não dígito


$subject = "precisa ter um 'não' dígito aqui 123";
$pattern = "/\D/"; //começa com
var_dump(preg_match($pattern, $subject));

// \W precisa ter um não alfa


$subject = "precisa ter um 'não' alfa aqui 123";
$pattern = "/\W/"; //começa com
var_dump(preg_match($pattern, $subject));

// \W precisa ter um não espaço


$subject = "precisa ter um 'não' espaço aqui";
$pattern = "/\S/"; //começa com
var_dump(preg_match($pattern, $subject));

// \W precisa ter um não espaço


$subject = "precisa ter um 'não' espaço aqui";
$pattern = "/\S/"; //começa com
var_dump(preg_match($pattern, $subject));
Regex (ranges “-”)
<?php
//range para verificar se contém números 0 à 9 (todos os números) //range para letras acentuadas independente da caixa
$string = "3 quartos, 2 banheiros, 4 tvs e 18 copos"; $string = "Último açaí às 18 horas";
$regex = "/[0-9]/"; $regex = "/[À-ú]/u";
var_dump(preg_match($regex, $string)); preg_match_all($regex, $string, $matches);
var_dump($matches);
//range para verificar se contém números de 0 à 3
$regex = "/[0-3]/";
var_dump(preg_match($regex, $string));

//range para verificar se contém letras (caixa baixa e não acentuadas)


$regex = "/[a-z]/";
var_dump(preg_match($regex, $string));

//range para verificar se contém letras (caixa alta e não acentuadas)


$regex = "/[A-Z]/";
var_dump(preg_match($regex, $string));
Regex Unicode
<?php //Símbolo de pontuação "outros"
//categorias em https://www.fileformat.info/info/unicode/category/index.htm $string = "Ele gritou: – Você fez isso ?!? ";
//Símbolo de moeda $regex = "/\p{Po}/u";
$string = "Sua dívida era de R$ 40,78 e £ 200,00"; preg_match_all($regex, $string, $matches);
$regex = "/\p{Sc}/u"; var_dump($matches);
preg_match_all($regex, $string, $matches);
var_dump($matches);

//Símbolo matemático
$string = "solidão + auto-estima ÷ zombaria ÷ condenação × culpa ...";
$regex = "/\p{Sm}/u";
preg_match_all($regex, $string, $matches);
var_dump($matches);

//Símbolos de pontuação de abertura (Ps) e fechamento (Pe)


$string = 'tem coisas (muitas) e outras também [1] e assim {bom demais}';
$regex = "/(\p{Ps}.*?\p{Pe})/u";
preg_match_all($regex, $string, $matches);
var_dump($matches);
Regex \b (word bondaury)

<?php

$regex = '/\bflor\b/';
$string = "uma flor na janela";
$string2 = "hoje visitei uma floricultura";
var_dump(preg_match($regex, $string)); //1
var_dump(preg_match($regex, $string2)); //0
Conditional Subpattern

<?php

$regex = "/(fato)?(?(1) é verdadeiro| é falso)/";


$string = "este fato é verdadeiro";
$matches = [];
preg_match_all($regex, $string, $matches);
var_dump($matches);
Biblioteca GD (Manipulação de Imagem)
● Nas aplicações modernas, muitas vezes, faz-se
necessário manipular imagens.
● Para
● GD: Graphical Draw
GD (Rotação de imagem)
GD (Ampliação e Redução de imagem)
GD (Recorte de Imagem)
GD (Virar imagem)
GD (Filtros)
FFI
Designer Patterns
Factory
<?php class ProdutoFisico implements Produto {
interface Produto { private $valor;
public function calcularValor(): float;
private $frete;
}

class ProdutoDigital implements Produto { public function __construct(float $valor, float $frete) {
private $valor; $this->valor = $valor;
public function __construct(float $valor) { $this->frete = $frete;
$this->valor = $valor; }
}
public function calcularValor(): float {
public function calcularValor(): float {
return $this->valor;
} return ($this->valor + $this->frete);
} }
}
Factory
class ProdutoFactory {
const FRETE_ATUAL = 20.00;
static public function test() {
return 0;
}
static public function criarProduto(string $tipo, float $valor) {
switch($tipo){
$produto = ProdutoFactory::criarProduto('Físico', 98.99);
case 'Digital':
echo $produto->calcularValor();
return new ProdutoDigital($valor);
break;
default:
case 'Fisico':
return new ProdutoFisico($valor, self::FRETE_ATUAL);
break;
}
}
}
Decorator
● O padrão Decorator permite que um usuário adicione novas funcionalidades
a um objeto existente sem alterar sua estrutura.
● Esse padrão cria uma classe “decoradora” que envolve a classe original e
fornece funcionalidades adicionais mantendo a assinatura de métodos de
classe intacta.
Decorator (interface e decorator abstrato)

<?php
<?php
interface Sanduiche { abstract class SanduicheDecorator implements Sanduiche {
public function calcularPreco(): float; protected $sanduiche;
public function getDescricao(): string; public function __construct(Sanduiche $sanduiche){
} $this->sanduiche = $sanduiche;
}
}
Decorator class QueijoExtra extends SanduicheDecorator {

private const PRECO = 4.00;


public function calcularPreco(): float {
return $this->sanduiche->calcularPreco() + self::PRECO;
<?php }
public function getDescricao(): string {
class RecheioRosbife implements Sanduiche { return $this->sanduiche->getDescricao() . ' com queijo extra';
public function calcularPreco(): float{ }
return 7.00; }
}
public function getDescricao(): string{ class Bacon extends SanduicheDecorator {
return 'recheio de rosbife';
} private const PRECO = 3.50;
} public function calcularPreco(): float {
return $this->sanduiche->calcularPreco() + self::PRECO;
}
public function getDescricao(): string {
return $this->sanduiche->getDescricao() . ' e bacon';
}
}
Decorator (utilização)

$sanduiche = new RecheioRosbife();


$sanduiche = new Bacon($sanduiche);
$sanduiche = new QueijoExtra($sanduiche);
echo $sanduiche->getDescricao(). ‘ ‘.
$sanduiche->calcularPreco();
Singleton
<?php
class Conexao {
$obj1 = Conexao::getConexao();
private static $obj; $obj2 = Conexao::getConexao();

private final function __construct() { var_dump($obj1 == $obj2);


echo __CLASS__ . " inicializa uma vez só <br>";
}

public static function getConexao() {


if(!isset(self::$obj)) {
self::$obj = new static();
}
return self::$obj;
}
}
Fluent Interface
<?php
class Cafe {
private $acucar = 0;
private $leite = 0; $cafe = new Cafe();
echo $cafe->addAcucar(2)
public function addAcucar(int $colheres){ ->addLeite(20)
$this->acucar += $colheres; ->addAcucar(1)
return $this;
}
->preparar();

public function addLeite(int $mililitros){


$this->leite += $mililitros;
return $this;
}

public function preparar(){


return "Café com {$this->acucar} colheres de
açucar e {$this->leite} ml de leite";
}
}
Memento (Memento e Originator)
<?php <?php
class Originator {
class Memento {
private $state;
private $state;
public function setState($state) {
public function __construct($state) { $this->state = $state;
$this->state = serialize($state); }
}
public function getState() { public function getState() {
return unserialize($this->state); return $this->state;
} }
}
public function saveStateToMemento() {
return new Memento($this->state);
}

public function getStateFromMemento(Memento $memento) {


$this->state = $memento->getState();
}
}
Memento (Carekater e Classe de Domínio)

<?php

class CareTaker {

private $mementoList = [];


<?php
public function add(Memento $state) {
$this->mementoList[] = $state; class Pedido {
} public $valor = 0;
}
public function get(int $index): Memento {
return $this->mementoList[$index];
}

}
Memento (utilização)
<?php

$originator = new Originator();


$careTaker = new CareTaker();

$pedido = new Pedido();


$pedido->valor = 90.00;
$originator->setState($pedido);
$careTaker->add($originator->saveStateToMemento());
$pedido->valor = 99.00;
$originator->setState($pedido);
$careTaker->add($originator->saveStateToMemento());
$pedido->valor = 120.00;
$originator->setState($pedido);
$careTaker->add($originator->saveStateToMemento());

$originator->getStateFromMemento($careTaker->get(0));
echo("Valor original: " . $originator->getState()->valor . "<br>");
Flyweight
● Devido à própria natureza de “script” do PHP, onde normalmente, apenas
parte dos dados de aplicação é carregada, esse padrão não é muito “comum”
em aplicações PHP (ou tecnologias similares).
● É muito importante que os objetos flyweight sejam imutáveis: qualquer
operação no estado de um objeto deve ser executada pela fábrica.
● CSV deste exemplo disponível em:
○ https://gist.github.com/celsowm/2258b0d078b799e911e5029bebe74338
Flyweight (Variante / Extrínseco)
public function encontrar(array $query): bool {

foreach ($query as $key => $value) {


<?php
if (property_exists($this, $key)) {
class Veiculo {
if ($this->$key != $value) {
return false;
public $placa;
}
private $variante;
} elseif (property_exists($this->variante, $key)) {
if ($this->variante->$key != $value) {
public function __construct(string $placa, Modelo $variante) {
return false;
$this->placa = $placa;
}
$this->variante = $variante;
} else {
}
return false;
}
public function imprimir() {
}
$this->variante->imprimirPerfil($this);
}
return true;
}

}
Flyweight (Invariante / Intrínseco)
<?php
class Modelo {

public $nome;
public $fabricante;
public $ano;

public function __construct(string $nome, string $fabricante, int $ano) {


$this->nome = $nome;
$this->fabricante = $fabricante;
$this->ano = $ano;
}

public function imprimirPerfil(Veiculo $carro) {


echo "Placa: $carro->placa <br>";
echo "Modelo: $this->nome <br>";
echo "Ano: $this->ano <br>";
echo "Fabricante: $this->fabricante <br>";
}

}
Flyweight (Fábrica)

<?php
abstract class FlyweightFactory {

protected $flyweights = [];


protected $invariantes = [];

protected function getKey(array $data): string {


return md5(implode("_", $data));
}

}
Flyweight (Fábrica Concreta)
<?php public function addVeiculo(string $placa, string $modelo, int $ano,string $fabricante)
class VeiculoBD extends FlyweightFactory { {
$invariante = $this->getInvariante($modelo, $ano, $fabricante);
public function __construct() { $this->flyweights[] = new Veiculo($placa, $invariante);
$file = new SplFileObject("carros.csv"); }
$colunas = []; public function getInvariante(string $modelo, int $ano, string $fabricante): Modelo {
$key = $this->getKey(get_defined_vars());
while (!$file->eof()) { if (!isset($this->invariantes[$key])) {
$linha = trim($file->fgets()); $this->invariantes[$key] = new Modelo($fabricante, $modelo, $ano);
if(empty($colunas)){ }
$colunas = array_flip(explode(',', $linha)); return $this->invariantes[$key];
}else{ }
$array = explode(',', $linha); public function findVeiculo(array $query) {
$this->addVeiculo( foreach ($this->flyweights as $carro) {
$array[$colunas['placa']], if ($carro->encontrar($query)) {
$array[$colunas['modelo']], return $carro;
$array[$colunas['ano']], }
$array[$colunas['fabricante']]); }
} echo "Sem resultados";
} }
$file = null; }
}
Flyweight (utilização)
<?php
$bd = new VeiculoBD();
$v1 = $bd->findVeiculo(['placa' => "LVG-5389"]);
if ($v1) {
$v1->imprimir();
}

$v2 = $bd->findVeiculo(['placa' => "QZM-0867"]);


if ($v2) {
$v2->imprimir();
}
Chain of Responsability
● A Chain of Responsibility é um design pattern que permite a passar uma
requisição ao longo da cadeia de possíveis manipuladores até que um deles
trate a solicitação.
Chain of Responsability
<?php

//source: https://dzone.com/articles/simple-example-illustrates protected function podeInterpretarArquivo(string $fileName,


class Interpretador { string $format): bool {

private $sucessor; $spl = new SplFileInfo($fileName);


return ($fileName == null) || ($spl->getExtension() == $format);
public function __construct(Interpretador $sucessor) {
$this->setSucessor($sucessor); }
}
public function getSucessor(): ?Interpretador {
public function interpretar(string $fileName): void { return $this->sucessor;
if ($this->getSucessor() != null) { }
$this->getSucessor()->interpretar($fileName);
} else { public function setSucessor(Interpretador $sucessor): void {
echo "Não é possível encontrar o interpretador correto $this->sucessor = $sucessor;
para o arquivo: " . $fileName . "<br>"; }
}
} }
Chain of Responsability (manipuladores)
class TextoInterpretador extends Interpretador { class JsonInterpretador extends Interpretador {

public function interpretar(string $fileName): void { public function interpretar(string $fileName): void {
if ($this->podeInterpretarArquivo($fileName, "txt")) { if ($this->podeInterpretarArquivo($fileName, "json")) {
echo("O Interpretador Texto está manipulando o echo("O Interpretador JSON está manipulando o arquivo: " .
arquivo: " . $fileName . "<br>"); $fileName . "<br>");
} else { } else {
parent::interpretar($fileName); parent::interpretar($fileName);
} }
} }
} }

class CSVInterpretador extends Interpretador { class XMLInterpretador extends Interpretador {

public function interpretar(string $fileName): void { public function __construct() {return;}


if ($this->podeInterpretarArquivo($fileName, "csv")) { public function interpretar(string $fileName): void {
echo("O Interpretador CSV está manipulando o if ($this->podeInterpretarArquivo($fileName, "xml")) {
arquivo: " . $fileName . "<br>"); echo("O Interpretador XML está manipulando o arquivo: " .
} else { $fileName . "<br>");
parent::interpretar($fileName); } else {
} parent::interpretar($fileName); }}}
}}
Chain of Responsability (criando a cadeia)

$listaArquivos = ["legal.txt", "bacana.json", "maneiro.xml", "supinpa.csv", "ruim.doc"];

$xmlInterpretador = new XmlInterpretador();


$csvInterpretador = new CsvInterpretador($xmlInterpretador);
$jsonInterpretador = new JsonInterpretador($csvInterpretador);
$textInterpretador = new TextoInterpretador($jsonInterpretador);

foreach ($listaArquivos as $key => $fileName) {


$textInterpretador->interpretar($fileName);
}
Observer
https://www.php.net/manual/en/class.splobserver.php
Referências
http://pt.slideshare.net/patrick.allaert/php-data-structures-and-the-impact-of-php-7-
on-them-php-days-2015
https://docstore.mik.ua/orelly/webprog/pcook/ch13_05
.htm
https://docs.microsoft.com/pt-br/dotnet/standard/base-types/anchors-in-regular-ex
pressions

https://pt.slideshare.net/felipernb/spl-datastructures

https://digitalfortress.tech/tricks/top-15-commonly-used-regex/

https://marcobaccaro.wordpress.com/2011/11/22/specification-pattern/
https://refactoring.guru/design-patte
rns/flyweight/php/example
https://www.geeksforgeeks.org/priority-queue-set-1-introduction/

Você também pode gostar