85 Bits - PHP
85 Bits - PHP
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.
?>
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.
$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.
$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
● 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
}
?? 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
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)
fim
Estrutura de Controle (if...else)
<?php
$a = 1; $b = 2; verdadeiro
condição
falso
}
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;
echo $resultado;
Operadores de Incremento/Decremento
Operador Nome
++ Incremento
-- Decremento
$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
falso
condição parar/fim
verdadeiro
código do loop
incrementar/
decrementar
Estrutura de Controle “loop” (for)
Sintaxe:
} 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)
$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;
} $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.
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.
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.
function add($x,$y){
return $x+$y();
}
teste_closure(function($x){
echo($x+10);
});
Função Anônima como parâmetro (com iteração de coleção)
<?php
$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');
//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
];
<?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"];
$array = ["Brasil","Argentina","Bolívia","Venezuela"];
$pessoas = [
["nome" => "João", "cpf" => 123],
["nome" => "Maria", "cpf" => 456]
];
0 1
"João" 0 1 2 "João" 0 1 2
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"];
if (in_array("uva", $frutas)) {
echo "Tem uva !";
}
Checagem de chave no Array (array_key_exists)
<?php
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"];
//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
}
Instanciando (new)
<?php
#1: Pessoa
class Pessoa { nome: null
cpf: null
public $cpf;
public $nome;
} $pessoa
class Pessoa {
public $cpf;
public $nome;
}
$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';
<?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 {
function exemplo() {
return 'olá mundooo!';
}
} + exemplo()
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 {
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;
}
$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.
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;
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()
class Matematica
{
private const PI = 3.14; //disponível a partir do PHP 7.1
function valorDePi() {
echo self::PI . "\n";
}
}
//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;
}
interface Formatador {
<<interface>>
public function formatar(); Fomatador
}
+ formatar()
class Html implements Formatador {
}
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 (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
}
}
<?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.
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
<?php
};
}
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
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..*)
<?php
$livro1 = new Livro();
class Livro { $livro1->titulo = 'Aventuras do PHP';
public $titulo;
public $edicao; $livro2 = new Livro();
} $livro2->titulo = 'A vida';
0 1
Editora1
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
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 {} }
<?php
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 (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";
<?php
require "Modelo\Fruta\Manga.php";
require "Modelo\Literatura\Manga.php";
<?php
spl_autoload_register('meu_autoloader');
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()
+ 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
}
Generator
<?php
function meuGenerator() {
<?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
<?php
Formato
da data Data no
Formato para formato
exibição
(string)
Classe DateTime (modificando data)
Adicionar um dia Segunda Feira desta semana
<?php <?php
<?php
<?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.
<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
atribuição separador de
de valor campos
● 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
<?php
$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;
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)
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;
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"
$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.
● 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
<?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
PDO::ATTR_ERRMODE PDO::ERRMODE_EXCEPTION Lança Exceptions toda vez que uma MySQL, Postgres,
instrução SQL falhar. Sql Server e Oracle
$servidor = "localhost";
$banco = "livraria";
$usuario = "root";
$senha = '';
$porta = 3306;
$dsn = "mysql:host=$servidor;port=$porta;dbname=$banco;charset=utf8";
$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;";
$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";
$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)))";
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
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.
//posicional
$statement = $pdo->prepare('SELECT * FROM funcionario WHERE nome = ? AND cpf = ?');
$statement->execute([$nome, $cpf]);
$funcionario = $statement->fetch();
var_dump($funcionario);
PDO Binding (bindValue)
<?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
include_once “conexao.php”;
<?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
include 'conexao.php';
<?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”;
//recuperando dados
include_once “conexao.php”;
include_once “Livro.php”;
<?php
$statement = $pdo->prepare(
"SELECT * FROM funcionario "
. "LEFT JOIN habilitacao "
. "ON funcionario.id = habilitacao.funcionario_id");
$statement->execute();
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 {
<?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');
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
É 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.
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.
$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 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 " ";
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.
$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)
$fixed[0] = 'A';
$fixed[1] = 'B';
$fixed[2] = 'C'; 0 1 2
head tail
A B C
NULL NULL
SplDoublyLinkedList (iteração, cabeça e cauda)
● Comportamento Last in, first out (última a entrar, primeiro a sair). [Pilha / Stack]
● Exemplos de LIFO:
<?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");
<?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");
$dll->setIteratorMode(\SplDoublyLinkedList::IT_MODE_DELETE);
$queue[] = 1;
1 2 3
$queue[] = 2;
$queue[] = 3;
echo "mínimo:".$minHeap->top();
echo "<br/>";
foreach ($minHeap as $value) {
echo $value."<br/>";
}
MaxHeap (SplMaxHeap)
<?php
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:
● 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->insert('A',1);
$prQueue->insert('B',9);
$prQueue->insert('C',7);
$prQueue->insert('D',5);
$prQueue->insert('E',2);
$prQueue->insert('F',4);
$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.
● 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
● 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;
● 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.
//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';
$string = '2014-02-22';
$regex = '/(\d{4})-(\d{2})-(\d{2})/';
$resultado = preg_replace_callback($regex, 'dataBr', $string);
<?php
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).
//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.
<?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 um à esquerda de ?
$subject = "thiago"; // ou tiago
$pattern = "/th?iago/";
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 ---
//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);
<?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
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 {
<?php
class CareTaker {
}
Memento (utilização)
<?php
$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 {
}
Flyweight (Invariante / Intrínseco)
<?php
class Modelo {
public $nome;
public $fabricante;
public $ano;
}
Flyweight (Fábrica)
<?php
abstract class FlyweightFactory {
}
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();
}
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);
} }
} }
} }
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/