PHP

Sintaxe PHP 8
Voltar

Base


VARIÁVEIS:
As variáveis em PHP começam com $
Não é preciso declarar o tipo da variável: o PHP automaticamente converte o tipo dependendo do valor atribuído à variável (coerção).
Ex:
<?php
$var1 = 999;
echo $var1;
$var3 = "Testando";
echo $var3.$var1; //concatenação feita com o ponto (.)
?>

<?php
$var1 = 999;
echo $var1."<br>";
echo "Olá <br>";
?>

CONSTANTES:
A constante é similar a uma variável, porém o seu valor não pode ser modificado. São nomeadas com letras maiúsculas.
Sintaxe: define(nome,valor);
Ex:
<?php
define("PI",3.1415);
echo PI;
?>


OPERADORES DE ATRIBUIÇÃO:
● Atribuição por concatenação:
$b = "Bom ";
$b .= "Dia!"; //define $b para "Bom Dia!", como em $b = $b."Dia!";
● Atribuição por referência:
$a = 3;
$b = &$a; // $b é uma referência de $a
print "$b"; // imprime 3
$a = 4;
print "$b\n"; //imprime 4 tbm, pois se mudar o valor de uma, a outra também será alterada

VARIÁVEIS DE VARIÁVEIS: (variáveis variantes)
$nome = "matt";
$$nome = "santos"; //cria variável de nome "matt", com o valor "santos"

OPERADOR TERNÁRIO:
ex: $maior = ($a>$b) ? $a : $b;

ECHO:
Através do comando echo, podemos testar diferentes situações resultantes da ação de operadores sobre variáveis.
Ex:
$i = 10;
echo "Numero $i<br>"; (ocorre interpolação entre string e variável)
echo 'Numero $i<br>'; (diferente do Javascript, ele encarará tudo como String)
$j = 20;
echo "Soma $i+$j<br>"; (interpola, mas não soma, pois encara o + como string)
echo "Soma ".$i+$j."<br>"; (se informar a concatenação, aí aceitará)
$var = 666;
echo "Numero $var <br>";
echo "Numero \"$var\" <br>"; // mostrar aspas no código
echo "Meu \ntexto \nquebrado \naqui"; //quebra de linhas
echo "\tTabulacao"; // tabulação
echo "\tTabulacao"; (tabulação = espaço do tab)

COMENTÁRIOS:
<?php
//linha
/* multiplas */
?>

FUNÇÕES NATIVAS STRING:
● printf: imprimir formatado
ex:
$p = "Leite"; $pr = 4.5;
printf("O %s custa %.2f",$p,$pr);
// %s - string | %.2f - float com 2 casas decimais
// %d - decimal | %u - decimal sem sinal | %f - real | %s - string

● explode / implode
<?php
// explode — divide uma string em substrings
// Usamos o espaco em branco " " como separador
$todos = "Maria Jose Lucia Carlos Julia Roberto";
$nome = explode(" ",$todos);
echo $nome[0]."<br>\n";
echo $nome[1]."<br>\n";
echo $nome[3]."<br>\n";
echo "<br>\n";
// implode — une varias substrings em uma unica string
// Usamos um hifen com espacos " - " como separador
$todosNovamente = implode(" - ",$nome);
echo $todosNovamente."<br>";
?>

● strtoupper / strtolower / ucwords
<?php
$nome = "joaquim jose da silva xavier";
echo "Nome antes do strtoupper => $nome <br>\n";
$nome = strtoupper($nome);
echo "Nome depois do strtoupper => $nome <br>\n";
$nome = strtolower($nome);
echo "Nome depois do strtolower => $nome <br>\n";
$nome = "joaquim jose da silva xavier";
echo "Nome depois do ucwords => ".ucwords($nome)."<br>\n";
?>

● ucfirst: colocar primeira letra maiúscula
<?php
$nome = "mateus mchwede";
print("Seu nome é".ucfirst($nome));
print("Nome: ".strtolower(ucfirst($nome)));
?>

● ucwords: primeira letra maiúscula em cada palavra
<?php
$nome = "mateus schwede";
print("O nome é ".ucwords($nome));
?>

● stripos: mesmo que strpos, ignorando maiúsculas e minúsculas
<?php
$frase = "Eu aprendo PHP";
$pos = stripos($frase,"PHP");
?>

● substr: determinado pedaço da String, com posição inicial e final
<?php
$site = "MatBytes blog";
$sub = substr($site,0,5);
$sub = substr($site,5); //pega a partir da 5ª letra
$sub = substr($site,0,-5); //pega as 5 últimas letras
$sub = substr($site,0,-5,2); //pegas, das 5 últimas letras, as 2 primeiras delas
?>

● str_repeat: repetir a string x vezes
<?php
$txt = str_repeat("PHP",5);
print($txt);
?>

● str_replace: altera a palavra x pela y na string
<?php
$frase = "Eu estudo PHP";
$novaFrase = str_replace("PHP","Java", $frase);
print($novaFrase);
?>

● ltrim / rtrim / trim
<?php
// rtrim e ltrim removem os espacos em branco na direita e esquerda das strings.
// trim remove de ambos lados
$var = " IFRS ";
echo "String original com espacos em branco:<br>";
echo "=".$var."=<br>";
echo "Sem espaco em branco do lado direito:<br>";
echo "=".rtrim($var)."=<br>";
echo "Sem espaco em branco do lado esquerdo:<br>";
echo "=".ltrim($var)."=<br>";
echo "Sem espaco em branco de ambos lados:<br>";
echo "=".lrim($var)."=<br>\n";
?>

● str_split: mostrar cada letra em um índice do vetor
ex:
$nome = "Maria";
$vetor = str_split($nome);

● md5
<?php
$senha = "MinhaSenha";
echo md5($senha);
?>

● ord: mostra o código da letra informada
ex:
$letra = "C";
$cod = ord($letra);

FUNÇÕES PARA ORDENAR ARRAYS:
● De forma comum
– asort // Ordem crescente
– arsort // Ordem decrescente - reversa
- array_reverse // Ordem decrescente - reversa (array_reverse($lista))

● Com índices (keys)
– ksort // Ordem crescente
– krsort // Ordem decrescente - reversa

● Outras
– count // Conta o numero de elementos
– sizeof // Igual ao count
– shuffle // Embaralha um array
- array_rand // Escolhe x elementos alteatórios (array_rand($lista,2))

ESTRUTURA DE CONDIÇÃO IF:
<?php
$valor = -10;
if($valor == 0) {
    echo "Zero!";
} elseif($valor > 0) {
    echo "Positivo!";
} else {
    echo "Negativo!";
}
?>

ESTRUTURA DE CONDIÇÃO SWITCH:
<?php
$valor = 1;
// Entra em um dos cases dependendo de $valor
switch($valor) {
    case 0:
        echo "Zero";
        break;
    case 1:

    case 2:

    case 3:
        echo "Um, dois, tres";
        break;
    default:
        echo "Outro";
}
?>
Se remover tdos os breaks, ele segue rodando as condições abaixo até o fim...

ESTRUTURA DE CONDIÇÃO SEGUIDA DE REPETIÇÃO WHILE:
<?php
$c = 0;
while($c < 10) {
    echo $c."<br>";
    $c++;
}

while ($c <= 1000) {
    #codigo
    break; // termina o loop
    #codigo
    continue; // encerra o loop e volta ao topo da condição
}
?>

ESTRUTURA DE REPETIÇÃO SEGUIDA DE CONDIÇÃO:
<?php
$d = 10;
do {
    echo $d."<br>";
    $d++;
} while($d < 20);
?>

ESTRUTURA DE REPETIÇÃO FOR:
<?php
for ($i = 0; $i <= 10; $i++) {
    echo $i."<br>";
}
?>

EMPTY:
A função empty determina se uma variável é vazia ou não (retorna true ou false).
Uma variável é considerada empty se ela:
– recebeu "" (string vazia)
– recebeu 0 (zero como um valor inteiro)
– recebeu "0"(zero como uma string)
– null
– false
Ex:
<?php
$v1 = "";
if(empty($v1)) echo "Vazio! ";
?>
Obs: o false, somente false empty, na realidade será verdadeiro!

Ex2 (variável atribuída de form post):
<form action="atividade.php" method="post">
    Salário: <input type="number" name="salario" step="0.01">
    <input type="submit" value="Calcular">
</form>
<?php
if (!empty($_POST['salario'])) {
    $salario = $_POST['salario'];
    echo "O salário é $salario";
    } else {
    echo "Salário não informado";
    }
?>

ISSET:
A função isset determina se uma variável foi iniciada ou não (retorna true ou false).
Esta função retorna false se a variável:
– não foi iniciada
– recebeu null
– foi removida com a função unset
Ex modelo de excessão em forms:
$nome = isset($_GET['nome'])?$_GET['nome']:"Nome não informado";
Ex do mesmo no php 7:
$nome = $_GET['nome'] ?? "Nome não informado";
Ex:
<?php
$v1 = "";
if(isset($v1)) echo "Existe sim! "; else echo "Nao! ";
?>

FORMULÁRIOS:
receber valores de informados em formulários
<form action="atividade.php" method="post">
    Salário: <input type="number" name="salario" step="0.01">
    <input type="submit" value="Calcular">
</form>
<?php
if (!empty($_POST['salario'])) {
    $salario = $_POST['salario'];
    echo "O salário é $salario";
    } else {
    echo "Salário não informado";
    }
?>

Receber valores radio:
<form action="exemplo_slide_05.php">
    <input type="radio" name="resp" value="sim" checked> Sim <br>
    <input type="radio" name="resp" value="nao"> Não <br>
    <input type="radio" name="resp" value="talvez"> Talvez <br>
    <input type="submit" value="Enviar">
</form>
<?php
if (!empty($_GET)) {
    if (!empty($_GET['resp'])) {
        $resposta = $_GET['resp'];
        echo "Resposta: ".$resposta;
    }
}
?>

Receber valores checkbox:
<form action="exemplo_slide_06.php">
    <input type="checkbox" name="bebida1" value="vodka" checked>Vodka<br>
    <input type="checkbox" name="bebida2" value="whisky">Whisky<br>
    <input type="checkbox" name="bebida3" value="cerveja">Cerveja<br>
    <input type="submit">
</form>
<?php
if (!empty($_GET)) {
    if (!empty($_GET['bebida1'])) {
        $bebida1 = $_GET['bebida1'];
        echo $bebida1."<br>";
    }
    if (!empty($_GET['bebida2'])) {
        $bebida2 = $_GET['bebida2'];
        echo $bebida2."<br>";
    }
// Segue codigo aqui
}
?>

Receber valores de password:
<form action="exemplo_slide_07.php" method="post">
    Senha:<input type="password" name="senha"><br>
    <input type="submit" value="Enviar">
</form>
<?php
if (!empty($_POST)) {
    if (!empty($_POST['senha'])) {
        $senha = $_POST['senha'];
        echo "Senha: ".$senha;
    }
}
?>

Receber dados de textarea:
<form action="exemplo_slide_08.php">
    <textarea name="mensagem" rows="10" cols="30"></textarea>
    <input type="submit">
</form>
<?php
if (!empty($_GET)) {
    if (!empty($_GET['mensagem'])) {
        $mensagem = $_GET['mensagem'];
        echo "</p>".$mensagem."</p>";
    }
}
?>

Receber dados select box:
<form action="exemplo_slide_09.php">
    <select name="carro">
        <option value="volvo">Volvo</option>
        <option value="chevrolet">Chevrolet</option>
        <option value="fiat">Fiat</option>
        <option value="porsche">Porsche</option>
    </select>
    <input type="submit">
</form>
<?php
if (!empty($_GET)) {
    if (!empty($_GET['carro'])) {
        $carro = $_GET['carro'];
        echo "Carro: ".$carro."<br>";
    }
}
?>

Campos Multivalorados checkbox:
<form action="exemplo-check.php" method="post">
    <input type="checkbox" name="letras[]" value="letraA"> A<br>
    <input type="checkbox" name="letras[]" value="letraB"> B<br>
    <input type="checkbox" name="letras[]" value="letraC"> C<br>
    <input type="submit"/>
</form>
<?php
if(!empty($_POST['letras'])) {
    foreach($_POST['letras'] as $letra) {
        echo $letra.'<br>';
    }
}
?>

Campos Multivalorados select:
<form action="exemplo-select.php" method="post">
    <select name="partidos[]" size="4" multiple="multiple">
        <option value="PSDB">PSDB</option>
        <option value="PMDB">PMDB</option>
        <option value="PT">PT</option>
        <option value="PP">PP</option>
    </select>
    <input type="submit"/>
</form>
<?php
if(!empty($_POST['partidos'])) {
    foreach($_POST['partidos'] as $part) {
        echo $part.'<br>';
    }
}
?>

ARRAYS: 
Um array em PHP serve para relacionar índices e valores, sendo que estes índices não são necessariamente números.
<?php
$array2 = [4,6,20,200,88,33];
var_dump($array2);

//array key string
$listaDiferente = ["foo" => "bar", "bar" => "foo"];

//array key diversas
$lista = [1 => "a", "1" => "b", 1.5 => "c", true => "d"];

//array key referenciadas
$lista2 = array("foo" => "bar", "bar" => "foo", 100 => -100, -100 => 100);

//array key em alguns termos
$lista3 = array("a", "b", 6 => "c", "d");

//arrays multidimencionais
$list4 = array( "foo" => "bar", 42 => 24, "multi" => array("dimensional" => array("array" => "foo")));
$listaBidimencional = array(array(1,2,3), array(4,5,6), array(7,8,9));
//cada elemento do listaBidimencional tbm é array
echo $listaBidimencional[0][1]."<br>";
echo $listaBidimencional[1][1]."<br>";
echo $listaBidimencional[2][1];

//atribuindo valores internos
$listaBidimencional[2][0] = $listaBidimencional[1][1];

//criando array com range:
$c = range(5,20,5); //array inicia no 5, termina no 20, e pula de 5 em 5

//Detalhado Array recursivos e multidimencionais:
$fruits = array(
    "frutas" => array(
    "a" => "laranja","b" => "banana","c" => "maçã"),
    "numeros" => array(1,2,3,4,5,6),
    "buracos" => array("primeiro",5 => "segundo","terceiro",)
);

// Alguns exemplo de enderecos dos valores do array acima
echo $fruits["buracos"][5]; // prints "segundo"
echo $fruits["frutas"]["a"]; // prints "laranja"
unset($fruits["buracos"][0]); // remove "primeiro"

// Criando um novo array multidimensional
$sucos["maca"]["verde"] = "bom";

// Array de CONST com define:
define('ANIMALS', ['dog','cat','bird']);
echo ANIMALS[1]; // imprime "cat"
?>

Adicionar Elementos de Array:
$lista[] = 666;
$arr["x"] = 42;
$foo['bar'] = 'Inimigo';

Acessar Elementos de Array:
echo $lista[0];
var_dump($list4["multi"]["dimensional"]["array"]);

Remover Elementos de Array:
unset($list4['foo']);
unset($list4); //remove todo array
Obs: Isso modificarão as keys do array

Indexando numericamente elementos do array:
$array1 = array(10,20,30,40,50);
$array2 = array_values($array1);

FOREACH: (percorrer array)
$array1 = array("Feliz","Bom Principio","Tupandi");
foreach ($array1 as $indice => $conteudo) {
    echo $indice." - ".$conteudo."<br>";
}

//percorrer array bidimencional
foreach($array1 as $i1 => $array2) {
    foreach($array2 as $i2 => $numero) {
        echo $numero." ";
    }
echo "<br>";
}

Comparando Arrays: array_diff()
array_diff ( array $array1 , array $array2 [, array $ ... ] ) : array
/*
array1 deve ser comparado
array2 para comparar
retorna um array contendo tudo de array1 que não se encontra em array2
*/
ex:
$array1 = array("a" => "verde", "vermelho", "azul", "vermelho");
$array2 = array("b" => "verde", "amarelo", "vermelho");
$result = array_diff($array1, $array2);
print_r($result);

Preenchendo Array:
$handle = opendir('.');
while (false !== ($file = readdir($handle))) {
    $files[] = $file;
}
closedir($handle);

Ordenando Array por valores:
//coloca valores do array em ordem crescente
//altera keys conforme ordenamento
sort($lista);
print_r($lista);
rsort($lista); //em ordem decrescente

Ordenação Associativa:
//coloca valores em ordem, mas mantém as keys
asort($lista);
arsort($lista); //em ordem decrescente

Ordenação por Keys:
//coloca keys em ordem crescente
ksort($lista);
krsort($lista); //em ordem decrescente

Contando itens Array:
echo count($list4);

Gerenciar últimos elementos Array:
//LIFO (Left in first out)
array_push($lista,7); //insere valor 7 no final $lista
array_pop($lista); //remove último elemento

Gerenciar primeiros elementos Array:
array_unshift($lista,7); //insere valor 7 no início $lista
array_shift($lista); //remove primeiro elemento

FUNÇÕES:
Uma função é uma parte de um programa com um objetivo específico, encapsulado sob uma estrutura única que recebe um conjunto de parâmetros e retorna um dado ou faz uma operação. Uma função é declarada apenas uma vez, mas pode ser chamada diversas vezes.
ex:
<?php
function quadrado($valor) {
    return $valor * $valor;
}
echo quadrado(4);

//função sem retorno
function escreve($frase) {
    echo $frase;
}
$retorno = escreve("Nada a declarar");

//com parâmetros
function incrementa($variavel,$valor) {
    $variavel += $valor;
}
$a = 10;
incrementa($a,20);
echo $a;

//parâmetros referenciados (altera externamente tbm)
function incrementa(&$variavel,$valor) {
    $variavel += $valor;
}
$a = 10; //no caso o $a será modificado tbm externamente
incrementa($a,20);
echo $a;

//PHP 7: tipagem em parâmetros e retorno da função
function sum(int $a, int $b): int {
    return $a + $b;
}
echo sum(5,10);

//número variável de argumentos:
function sum(int ...$numbers): int {
    $acc = 0;
    foreach ($numbers as $n) {
        $acc += $n;
    }
    return $acc;
}
echo sum(1, 2, 3, 4);

//fornecer argumentos:
function add($a, $b) {
    return $a + $b;
}
echo add(...[1, 2])."\n";
$a = [1, 2];
echo add(...$a);

//retornar referência de uma função:
function &retorna_referencia() {
    return $alguma_referencia;
}
$nova_referencia =& retorna_referencia();

//funções anônimas:
$greet = function($name) {
    printf("Hello %s\r\n", $name);
};
$greet('World');
$greet('PHP');

//função com parâmetros dinâmicos
function soma() {
    $p = func_get_arg();
    $t = func_num_args(); //5 nºs
    for($i = 0; $i < $tot; $i++) {
        $s += $p[$i];
    }
    return $s;
}
$res = soma(3,4,8,1,2); //cada nº possui sua key

//funções em outros arquivos:
> arquivo 'funcoes.php', recebe funções de outros 2 arquivos
> arq 'script1.php': include "funcoes.php";
> arq 'script2.php': include "funcoes.php";
?>

TRY_CATCH excessões com funções:
<?php
declare(strict_types=1);
function sum(int $a, int $b) {
    return $a + $b;
}

try {
    var_dump(sum(1, 2));
    var_dump(sum(1.5, 2.5));
} catch (TypeError $e) {
    echo 'Error: '.$e->getMessage();
}
?>

INCLUDE:
A instrução include inclui e avalia o arquivo informado. Esse arquivo (um código com variáveis, estruturas, comandos, etc.) é incluído no escopo do programa, tornando-se disponível a partir da linha que que ocorre a inclusão. Se o arquivo não existir produzirá uma mensagem de advertência (warning), exceto se estiver desabilitado na configuração do PHP.
ex:
<?php
include "vars.php";
include "fat.php";
echo fatorial($a)."<br>\n";
echo fatorial($b);

//condicinal de conexão
if (include('vars.php') == TRUE) {
    echo 'OK';
}
?>

REQUIRE:
<?php
require 'somefile.php';
?>

INCLUDE vs REQUIRE:
Ambos incluem arquivos com códigos externos. Caso o outro arquivo não inacessível, o include ñ incluirá e continuará o código. O require vai dar erro.
Include: incluir (opcional, qntas vezes quiser)
Require: requerir (obrigatório, qntas vezes quiser)
include_once: inclui somente se ñ fora já incluido (inclui 1 vez só)
require_once: requere somente se ñ fora já requerido (requere 1 vez só)

ARQUIVOS REMOTOS:
//pegando titulo de página remota
<?php
$file = fopen ("http://www.example.com/", "r");
if (!$file) {
    echo "<p>Incapaz de abrir arquivo remoto.\n";
    exit;
}

while (!feof ($file)) {
    $line = fgets ($file, 1024);
    /* Isso só funciona se o título e suas tags estiverem na mesma linha */
    if (eregi ("<title>(.*)</title>", $line, $out)) {
        $title = $out[1];
        break;
    }
}
fclose($file);
?>

//guardando informações em servidor remoto
<?php
$file = fopen ("ftp://ftp.example.com/incoming/outputfile", "w");
if (!$file) {
    echo "<p>Incapaz de abrir arquivo remoto para escrita.\n";
    exit;
}
/* Escreva informação aqui. */
fwrite ($file, $_SERVER['HTTP_USER_AGENT'] . "\n");
fclose ($file);
?>

REDIRECIONAMENTO COM HEADER:
<?php
header("Location:exemplo_slide_12B.php");
// O codigo que vem após não sera executado
?>

COOKIES & SESSÕES:
● Problema: O protocolo HTTP não armazena informações de estado, ou seja, ele trata de forma independente cada requisição de pagina recebida.
● Solução: Usar cookies e sessões, que servem para manter informações sobre os usuarios enquanto eles navegam no site.
– Cookies são arquivos texto armazenados no computador do usuario, que podem ser recuperados posteriormente pelo servidor.
– Sessões são recursos que podemos usar para manter uma conexão com o usuario enquanto ele navega no site.
● Algumas utilidades de cookies e sessões:
– Manter usuarios autenticados
– Carrinhos de compras
– Exibição de anúncios
– Personalização de conteúdo e layouts

COOKIES:
● Um cookie é formado por um par nome/valor: possui um nome pelo qual é referenciado e um valor associado.
● Permitem compartilhar dados entre diferentes paginas e diferentes acessos (dias e horarios distintos).
● Cookies podem ser mantidos na maquina do usuario por varios dias, diferente de sessões!
● Um cookie é enviado junto com o header, logo você deve criar ele antes de gerar qualquer conteúdo da pagina.
ex:
<?php
setcookie("pais","Spain",time()+15); //nome,valor,validade
?>
<p>Os cookies foram criados.</p>
<p><a href="exemplo_slide_18.php">Clique ... </a></p>

Apagar Cookie:
setcookie("pais"); //cookie somente com o nome
Ex:
<p>
<?php
if($_COOKIE["pais"] == null) {
    echo "pais == null<br>";
} else {
    echo $_COOKIE["pais"]."<br>";
}
?>
</p>

SESSÃO:
● Uma sessão é um período de tempo no qual o usuário navega em um site.
● Em uma sessão podemos registrar diversas variáveis, que ficarão gravadas em arquivo no servidor e poderão ser acessadas enquanto o site estiver aberto. Para criar uma sessão no PHP devemos chamar a função session_start(). Para criar variáveis na sessão devemos inserir valores no array $_SESSION.
<?php
session_start();
if(!isset($_SESSION['contador'])) {
    $_SESSION['contador'] = 1;
} else {
    $_SESSION['contador']++;
}
echo $_SESSION['contador'];
?>

Apagando variáveis da sessão:
<?php
session_start();
$_SESSION['contador'] = 1000;
unset($_SESSION['contador']);
if($_SESSION['contador'] == null) {
    echo "Contador nulo!";
}
?>

Destruindo sessão:
session_destroy();

SESSÕES MÚLTIPLAS (ARRAYS):
<?php
session_start(['cache_limiter' => 'private','read_and_close' => true,]);
?>
Ex:
<?php
session_start();
if(!isset($_SESSION['contador'])) {
    $_SESSION['contador'] = 1;
} else {
    $_SESSION['contador']++;
}
?>

OOP


CLASSE BASE EM PHP:

-- CLASSE PRODUTO.CLASS.PHP --
<?php
    class Produto {
        //atributos
        private $codigo;
        private $descricao;
        //Construtor
        function Produto($c,$d) {
            $this->codigo = $c;
            $this->descricao = $d;
        }
        //Construtor 2
        function __construct() {
            $this->setCodigo(0);
            $this->setDescricao("Bola");
        }
        //Get
        function getCodigo() {return $this->codigo;}
        //Set
        function setCodigo($c) {$this->codigo = $c;
        }
    }
?>

-- INDEX.PHP --
<?php
    require_once 'Produto.class.php';
    $p1 = new Produto(33,"Vassoura");
    $p1->setCodigo(03);
    $p1->codigo = 4; //se visibilidade for public
    $p1->getCodigo();
    print_r($p1);
    echo "O produto {$p1->getCodigo()} é um {$p1->getDescricao()}!";
?>

Obs1: O que vier após o return(nos métodos), nunca será executado!
Obs2: Caso não seja definido um Construtor na classe, todas as propriedades da mesma serão inicializadas com null!
Obs3: Crie uma pasta, para armazenar as classes com a extensão .class.php
ex: require_once 'classes/Produto.class.php';


COMPARAÇÃO DE OBJETOS:

-- Objetos iguais:
(mesmos atributos e valores, e instâncias da mesma classe)
<?php
    $prod1 = new Produto();
    $prod2 = new Produto();
    $prod1->setCodigo(200);
    $prod2->setCodigo(200);
    if($prod1 == $prod2) {echo "Iguais"}
    else {echo "Diferentes"};
?>

-- Objetos idênticos:
(variáveis idênticas e se referirem ao mesmo objeto, da mesma classe)
<?php
    $prod1 = new Produto();
    $prod2 = new Produto();
    $prod1->setCodigo(200);
    $prod2->setCodigo(200);
    if($prod1 === $prod2) {echo "Identicos"}
    else {echo "Diferentes"};
?>


INDUÇÃO DE TIPOS:
Para induzir um tipo no método, inserimos o nome da classe na frente da variável
(para registrar um país no continente, preciso já ter um país criado)

-- Class Continente.class.php
<?php
    class Continente() {
        function __construct() {$this->paises = array();}
        function registrar(Pais $_pais) {$this->paises[] = $_pais;}
        function imprimirPaises() {
            foreach($this->paises as $p) {echo $p->nome."<br>";}
        }
    }
?>

-- Classe Pais.class.php
<?php
    class Pais() {
        public $nome;
        function __construct($n) {$this->nome = $n;}
    }
?>

-- Index.php
<?php
    require_once 'Continente.class.php';
    require_once 'Pais.class.php';

    $c1 = new Continente();
    $p1 = new Pais("Brasil");
    $c1->registrar($p1);
    $p2 = new Pais("Alemanha");
    $c1->registrar($p2);
    $c1->registrar("Argentina"); //erro, pois só aceita objetos Pais
    $c1->imprimirPaises();
?>


ENCAPSULAMENTO (Interface):

-- INTERFACE Controlador.class.php --
<?php
    interface Controlador {
        abstract function ligar();
        abstract function desigar();
    }
?>

-- CLASSE Controle.class.php --
<?php
    require_once 'Controlador.class.php';
    class Controle implements Controlador {
        //atributos
        private $ligado, $desligado;

        //Construtor
        function __construct() {
            $this->ligado = false;
            $this->desligado = true;
        }

        //Gets & Sets

        //Métodos Abstratos implementados
        function ligar() {
            $this->setLigado(true);
        }
        function desigar() {
            $this->setDesligado(true);
        }
    }
?>

-- INDEX.PHP --
<?php
    require_once 'Controle.class.php';
    $c = new Controle();
    $c->ligar();
    $c->getLigado();
?>


AGREGAÇÃO (tem um...) & OBJETOS COMPOSTOS (array):

-- CLASSE Lutador.class.php --
<?php
    class Lutador {
        private $nome, $vitorias, $empates, $derrotas;

        function __construct($n,$v,$e,$d) {
            $this->nome = $n;
            $this->vitorias = $v;
            $this->empates = $e;
            $this->derrotas = $d;
        }

        //gets e sets

        function ganharLuta() {
            $this->setVitorias($this->getVitorias()++);
        }
        function perderLuta() {
            $this->setDerrotas($this->getDerrotas()++);
        }
        function empatarLuta() {
            $this->setEmpates($this->getEmpates()++);
        }
    }
?>

-- CLASSE Luta.class.php --
<?php
    require_once 'Lutador.class.php';
    class Luta {
        private $desafiado, $desafiante;

        //gets e sets de Lutador

        function lutar($l1,$l2) {
            $this->desafiado = $l1;
            $this->desafiante = $l2;
            $vencedor = rand(0,2);
            switch($vencedor) {
                case 0:
                    $this->desafiado->empatarLuta();
                    $this->desafiante->empatarLuta();
                break;
                case 1:
                    $this->desafiado->ganharLuta();
                    $this->desafiante->perderLuta();
                break;
                case 2:
                    $this->desafiado->perderLuta();
                    $this->desafiante->ganharLuta();
                break;
            }
        }
    }
?>

-- INDEX.PHP --
<?php
    require_once 'Luta.class.php';
    require_once 'Lutador.class.php';

    // agregação: luta 1 <-> 2 lutadores
    $l = array();
    $l[0] = new Lutador("Max",11,2,1);
    $l[1] = new Lutador("Marc",8,2,3);

    $ufc01 = new Luta($l[0],$l[1]);
    $ufc01->lutar();
?>


HERANÇA (extends):

-- CLASSE ABSTRATA Pessoa.class.php --
<?php
    //abstração - classe/métodos abstratos (final)
    abstract class Pessoa {
        private $nome;
        private $idade;
        final function fazerAniver() {
            $this->idade++;
        }
        //gets e sets de Pessoa
    }
?>

-- CLASSE FILHA Aluno.class.php --
<?php
    require_once 'Pessoa.class.php';
    class Aluno extends Pessoa {
        private $matricula;
        private $curso;
        function pgtoMensal() {
            echo "pago!";
        }
        //gets e sets de Aluno
    }
?>

-- CLASSE FILHA Bolsista.class.php --
<?php
    require_once 'Aluno.class.php';
    class Bolsista extends Aluno { //herança
        private $bolsa;
        //sobreposição (polimorfismo)
        function ptgoMensal() {
            echo "pago com desconto!";
        }
        //gets e sets de Bolsista
    }
?>

-- INDEX.PHP --
<?php
    require_once 'Pessoa.class.php';
    require_once 'Aluno.class.php';
    require_once 'Bolsista.class.php';

    $a1 = new Aluno();
    $a1->setNome("Pedro");
    $b1 = new Bolsista();
    $b1->setNome("João");
    $b1->pgtoMensal();
?>


POLIMORFISMO1 (Sobreposição-Sobrescrita):
"Métodos com mesmo nome e lista de parâmetros, conteúdo interno diferente na subclasse"

-- CLASSE ABSTRATA Animal.class.php --
<?php
    abstract class Animal {
        protected $peso;
        protected $idade;
        protected $membros;
        //método abstrato:
        abstract function locomover();
        //gets e sets de Animal
    }
?>

-- CLASSE FILHA Mamifero.class.php --
<?php
    require_once 'Animal.class.php';
    class Mamifero extends Animal {
        private $corPele;
        function locomover() {
            echo "correndo";
        }
        //gets e sets de Mamifero
    }
?>

-- CLASSE FILHA Peixe.class.php --
<?php
    require_once 'Animal.class.php';
    class Peixe extends Animal {
        private $corEscama;
        //sobrescrita no método:
        function locomover() {
            echo "nadando";
        }
        //gets e sets de Peixe
    }
?>

-- INDEX.PHP --
<?php
    require_once 'Mamifero.class.php';
    require_once 'Peixe.class.php';

    $m1 = new Mamifero();
    $m1->locomover();
    $p1 = new Peixe();
    p1->locomover(); //mesmo método, resultado diferente (polimorfismo)!
?>


POLIMORFISMO2 (Sobrecarga):
"Métodos com mesmo nome, lista de parâmetros diferentes (geralmente na mesma classe)"
O php não tem suporte pra Sobrecarga, mas há soluções alternativas!
=> Solução: métodos similares de conteúdo, com nomes diferentes (emitirSom1(),emitirSom2())

-- CLASSE ABSTRATA Animal.class.php --
<?php
    abstract class Animal {
        protected $peso;
        function emitirSom();
        //gets e sets de Animal
    }
?>

-- CLASSE FILHA Mamifero.class.php --
<?php
    require_once 'Animal.class.php';
    class Mamifero extends Animal {
        function emitirSom() {
            echo "Som de mamífero";
        }
    }
?>

-- CLASSE FILHA Lobo.class.php --
<?php
    require_once 'Mamifero.class.php';
    class Lobo extends Mamifero {
        function emitirSom() {
            echo "Auuu!";
        }
    }
?>

-- CLASSE FILHA Cachorro.class.php --
<?php
    require_once 'Lobo.class.php';
    class Cachorro extends Lobo {
        function emitirSom() {
            echo "Au Au Au!";
        }
    }
?>

-- INDEX.PHP --
<?php
    require_once 'Mamifero.class.php';
    require_once 'Lobo.class.php';
    require_once 'Cachorro.class.php';

    $l1 = new Lobo();
    $l1->emitirSom();
    $c1 = new Cachorro();
    $c1->emitirSom();
?>

PDO


-- BANCO DE DADOS (Mysql) --
CREATE DATABASE aula;
CREATE TABLE Pessoa (
    id INTEGER AUTO_INCREMENT PRIMARY KEY,
    nome VARCHAR(20) NOT NULL,
    sobrenome VARCHAR(20) NOT NULL
);
INSERT INTO Pessoa (nome,sobrenome) VALUES ('Carlos','Garcia'), ('Maria','Antunes'), ('Cassio','Silva');


CONEXÃO PHP COM MYSQL:
<?php
    $db = new PDO('mysql:host=localhost;dbname=aula;charset=utf8','root','');
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
?>


SELECT MODO 1: pouco usado, requer o dobro de memória
<?php
    //código conexão com bd aqui
    $resultado = $db->query('SELECT * FROM Pessoa');
    foreach($resultado as $linha) {
        echo $linha['nome'].' '.$linha['sobrenome']."<br>";
    }
?>

SELECT MODO 2: pouco usado, requer o dobro de memória
<?php
    //código conexão com bd aqui
    $resultado = $db->query('SELECT * FROM Pessoa');
    foreach($resultado as $linha) {
        echo $linha[0].' '.$linha[1].' '.$linha[2]."<br>";
    }
?>

SELECT MODO 3: Ideal, indexação única de array, não gasta muita memória
<?php
    //código conexão com bd aqui
    $resultado = $db->query('SELECT * FROM Pessoa');
    // $linhas = $resultado->fetchAll(PDO::FETCH_NUM);
    // $linhas = $resultado->fetchAll(PDO::FETCH_BOTH);
    $linhas = $resultado->fetchAll(PDO::FETCH_ASSOC);
    print_r($linhas);
?>

Indexação de Array no Select:
(parâmetros do fetchAll)
● PDO::FETCH_ASSOC: (ideal) Retorna linhas do BD como array associativo indexado com nomes de colunas do BD.
● PDO::FETCH_NUM: Retorna linhas do BD como array indexado de modo numérico, onde 0 é o índice da primeira coluna, 1 é o índice da segunda coluna, etc...
● PDO::FETCH_BOTH: Duplica dados, retornando linhas tanto como um array associativo como um array numérico. Ocupa dobro da memória.


CONTANDO LINHAS:
(Usado para retornar se há resultados no Select, linhas > 0)
<?php
    //conexão com bd aqui...
    $resultado = $db->query('SELECT * FROM Pessoa');
    $numeroLinhas = $resultado->rowCount();
    echo $numeroLinhas.' linhas foram selecionadas!';
?>


INSERT DIRETO: (sem variáveis)
<?php
    //conexão com bd aqui...
    $numeroLinhasInseridas = $db->exec("INSERT INTO Pessoa (nome,sobrenome) VALUES ('Maria','Silva')");
    echo $numeroLinhasInseridas." linha foi inserida.";
?>


UPDATE DIRETO: (sem variáveis)
<?php
    //conexão com bd aqui...
    $numeroLinhasAtualizadas = $db->exec("UPDATE Pessoa SET nome='Mike' WHERE sobrenome='Silva'");
    echo $numeroLinhasAtualizadas." linhas foram atualizadas.";
?>


DELETE DIRETO: (sem variáveis)
<?php
    //conexão com bd aqui...
    $numeroLinhasApagadas = $db->exec("DELETE FROM Pessoa WHERE sobrenome='Silva'");
    echo $numeroLinhasApagadas." linhas foram apagadas.";
?>


ERROS EM PDO:
PDO::ERRMODE_SILENT: Não exibe nenhuma mensagem de erro, você deve chamar o método $db->errorInfo() para obter informações sobre os erros ocorridos.
PDO::ERRMODE_WARNING: Apenas exibe warnings na tela, mas segue execução.
PDO::ERRMODE_EXCEPTION: Lança uma PDOException – é o modo que você vai querer usar pois permite que os erros sejam tratados.

<?php
    try {
        // Código que pode vir a gerar um erro
    } catch (PDOException $exception) {
        // Código para tratar erro caso aconteça
    }
?>

Exemplo:
<?php
    //conexão com bd aqui...
    try {
        $db->query('THUNDERCAT');
    } catch (PDOException $exception) {
        echo "<p><b> Occorreu um erro! </b></p>";
        echo "<b>Mensagem</b>: ".$exception->getMessage();
    }
    echo "Programa segue normalmente depois do erro.";
?>

PREPARED STATEMENTS:
Realizar queries com variáveis de forms

Modelo 1:
<?php
    //código conexão com bd
    $r = $db->prepare('SELECT * FROM Pessoa WHERE id=? OR nome=?');
    $id = 1;
    $nome = 'Maria';
    $r->execute(array($id, $nome));
    $linhas = $r->fetchAll(PDO::FETCH_ASSOC);
    foreach($linhas as $linha) {
        echo $linha['id'].' '.$linha['nome'].' '.$linha['sobrenome']."<br>";
    }
?>

Modelo 2: (mais usado)
<?php
    //código conexão com bd
    $r = $db->prepare( 'SELECT * FROM Pessoa WHERE id=:id OR nome=:nome');
    $id = 2;
    $nome = 'Marcela';
    $r->execute(array(':id' => $id, ':nome' => $nome));
    $linhas = $r->fetchAll(PDO::FETCH_ASSOC);
    foreach($linhas as $linha) {
        echo $linha['nome'].' '.$linha['sobrenome']."<br>";
    }
?>

Além dos arrays, podemos usar o método bindValue para especificar valores a serem inseridos na consulta. Qndo usamos o bindValue, temos que especificar o tipo de dado para o argumento ? ou :arg. Os possíveis tipos de dados são:
● PDO::PARAM_INT
● PDO::PARAM_STR
● PDO::PARAM_BOOL
Ex:
<?php
    //código conexão com bd
    $r = $db->prepare('SELECT * FROM Pessoa WHERE id=? OR nome=?');
    $id = 1;
    $nome = 'Maria';
    $r->bindValue(1, $id, PDO::PARAM_INT);
    $r->bindValue(2, $nome, PDO::PARAM_STR);
    $r->execute();
    $linhas = $r->fetchAll(PDO::FETCH_ASSOC);
    foreach($linhas as $linha) {
        echo $linha['nome'].' '.$linha['sobrenome']."<br>";
    }
?>

<?php
    //código conexão com bd
    $r = $db->prepare('SELECT * FROM Pessoa WHERE id=:id OR nome=:nome');
    $id = 2;
    $nome = 'Marcela';
    $r->bindValue(':id', $id, PDO::PARAM_INT);
    $r->bindValue(':nome',$nome, PDO::PARAM_STR);
    $r->execute();
    $linhas = $r->fetchAll(PDO::FETCH_ASSOC);
?>


INSERT COM VARIÁVEIS:
<?php
    //código conexão com bd
    $nome = 'Jair';
    $sobrenome = 'Kobe';
    $r = $db->prepare('INSERT INTO Pessoa(nome,sobrenome) VALUES (:nome,:sobrenome)');
    $r->execute(array(':nome'=>$nome,':sobrenome'=>$sobrenome));
    if($r->rowCount() > 0) {
        echo 'Linha inserida!';
    }
?>


UPDATE COM VARIÁVEIS:
<?php
    //código conexão com bd
    $id = 4;
    $nome = 'Charlie';
    $r = $db->prepare('UPDATE Pessoa SET nome=? WHERE id>?');
    $r->execute(array($nome, $id));
    $numeroLinhas = $r->rowCount();
    echo $numeroLinhas.' linhas atualizadas!';
?>


DELETE COM VARIÁVEIS:
<?php
    //código conexão com bd
    $id = 4;
    $r = $db->prepare('DELETE FROM Pessoa WHERE id>?');
    $r->execute(array($id));
    $numeroLinhas = $r->rowCount();
    echo $numeroLinhas.' linhas removidas!';
?>

PDO OOP


-- COM 1 CLASSE --

//Banco modelo:
CREATE DATABASE aula16;
USE aula16;
CREATE TABLE Pessoa (
    id INTEGER AUTO_INCREMENT PRIMARY KEY,
    nome VARCHAR(20) NOT NULL,
    sobrenome VARCHAR(20) NOT NULL
);
INSERT INTO Pessoa (nome,sobrenome) VALUES ('Carlos','Garcia'),('Maria','Antunes'),('Cassio','Silva'),('Marcela','Moraes');

//Classe Pessoa.class.php
<?php
    class Pessoa {
        private $id;
        private $nome;
        private $sobrenome;

        public function info() {
            $r = '#'.$this->id;
            $r .= ':'.$this->nome;
            $r .= ' '.$this->sobrenome;
            return $r;
        }
    }
?>
O nome dos atributos da classe deve coincidir com o nome dos campos da tabela!

<?php
    $db = new PDO('mysql:host=localhost;dbname=aula16;charset=utf8','root','');
    $query = "SELECT id, nome, sobrenome FROM Pessoa";
    $r = $db->query($query);
    $r->setFetchMode(PDO::FETCH_CLASS,'Pessoa');
    while($pessoa = $r->fetch()) {echo $pessoa->info()."<br>\n";}
?>


-- COM 2 CLASSES --

//Banco modelo:
create database aula18;
use aula18;
create table equipe (
    id integer not null primary key,
    nome varchar(30) not null,
    cidade varchar(30) not null
);
create table atleta (
    id integer not null primary key,
    nome varchar(30) not null,
    sobrenome varchar(30) not null,
    posicao varchar(30) not null,
    equipe_id integer not null,
    constraint equipe_fk foreign key (equipe_id) references equipe(id)
);

//Classe Equipe.class.php
<?php
    class Equipe {
        private $id, $nome, $cidade, $atletas;
        public function getId() {return $this->id;}
        public function getNome() {return $this->nome;}
        public function getCidade() {return $this->cidade;}
        public function getAtletas() {return $this->atletas;}
        public function addAtleta(Atleta $atleta) {$this->atletas[] = $atleta;}
    }
?>
//$atletas: Atributo array para manter com a tabela 'atletas'

//Classe Atleta.class.php
<?php
    class Atleta {
        private $id, $nome, $sobrenome, $posicao, $equipe_id;
        public function getId() {return $this ->id;}
        public function getNome() {return $this ->nome;}
        public function getSobrenome() {return $this ->sobrenome;}
        public function getPosicao() {return $this ->posicao;}
        public function getEquipeID() {return $this ->equipe_id;}
    }
?>

//index.php
<?php
    $equipes = array();
    $db = new PDO('mysql:host=localhost;dbname=aula18','root','');
    $select1 = 'SELECT id, nome, cidade FROM Equipe';
    $r1 = $db->query($select1);
    $r1->setFetchMode(PDO::FETCH_CLASS,'Equipe');
    $select2 = 'SELECT id, nome, sobrenome, posicao FROM Atleta WHERE equipe_id = :id';
    $r2 = $db->prepare($select2);
    while ($equipe = $r1->fetch()) {
        $r2->bindValue(':id',$equipe->getId(),PDO::PARAM_INT);
        $r2->execute();
        $r2->setFetchMode(PDO::FETCH_CLASS,'Atleta');
        while ($atleta = $r2->fetch()) {$equipe->addAtleta($atleta);}
        $equipes[] = $equipe;
    }
?>

MVC


--- INDEX ---
<?php
    include '/mvcexemplo/Controller/Controller.php';
    include '/mvcexemplo/View/View.php';
    include '/mvcexemplo/Model/Model.php';

    $acao = $_GET['acao'];

    if(isset($acao) && $acao == 'login'){
        $controller = new Controller();
        $controller->login();
    } else {
        $view = new View();
        $view->login(); 
    }
?>


--- VIEW ---
<?php
    class View {
        public function login($validacao) { 
            if(!isset($validacao)) {
                echo ' 
                    <h3>Login</h3>
                    <form action='index.php' method ='post'>
                        <input type='text' placeholder='Usuário' name='usuario'>
                        <input type='password' placeholder='Senha' name='senha'>
                        <input type='submit' value='Entrar'>
                    </form>
                ';
            } else {echo '<h3>'.$validacao.'</h3>';}
        }
    }
?>


--- CONTROLLER ---
<?php
    include '/../Model/Model.php';
    class Controller {
        public function login() {
            $user = $_POST['usuario'];
            $pass = $_POST['senha'];
            $model = new Model();
            $validacao = $model->validaDados($user,$pass);
            $view = new View();
            $view->login($validacao); 
        }
    }
?>


--- MODEL ---
<?php
    class Model {
        public function validaDados($user,$pass) {
            if(($user!="admin") and ($pass!="adm")) {return 'Login incorreto'; }
            else {return 'Logado com sucesso';}
        }
    }
?>

PHP 8


--- Construct Promotion ---
Criar __construct passando atributos e relacionando-os diretamente dentro do método

-- Antes:
class Carro {
    private string $marca;
    private string $modelo;
    private float $motor;

    public function __construct($marca,$modelo,$motor=1.4) {
        $this->marca = $marca;
        $this->modelo = $modelo;
        $this->motor = $motor;
    }
}

-- Depois:
class carro {
    public fuction __construct(private string $marca, private string $modelo, private float motor=1.4){}
}


--- Named Arguments ---
Somente argumentos necessários são informados, em qualquer ordem, inclusive à funções nativas.

-- Antes:
function desconto ($idCliente, $pSaude=false, $vRefeicao=false, vTransporte=false){}

$descCli1 = desconto(1,false,true);
$descCli2 = desconto(2,false,false,true);

-- Depois:
function desconto ($idCliente, $pSaude=false, $vRefeicao=false, vTransporte=false){}

$descCli1 = desconto(idCliente:1, vRefeicao:true);
$descCli2 = desconto(idCliente:2, vTransporte:true);
$setcookie(name:'testing', expires:time()+60*60*10); //Argumento value não foi informado


--- Union Types ----
União de tipos especificada previamente pela linguagem

-- Antes:
class Numero {
    /** @var int|float */
    private $num;
    /** @param float|int $num */
    public function __construct($num) {
        $this->num = $num;
    }
}
new Numero('NaN'); //Ok

-- Depois:
class Numero {
    public function __construct(private int|float $num){}
}
new Numero('NaN'); //TypeError


--- Mixed Types ---
Engloba todos os tipos possíveis de Union Types para a passagem de argumentos e retorno de funções.

-- Antes:
function addValor($val){}

-- Depois:
//Union Types
function addValor(array|bool|callable|int|float|null|object|resource|string $val){}

//Mixed Types
function addValor(mixed $val){}


--- Atributes ---
Substitui o phpDoc por referência nativa na linguagem para routes, validações e propriedades de tableBD

-- Antes:
class UserController {
    /**
    * @Route("/usuarios/{id}", methods={"GET"})
    */
    public function get($id){}
}

-- Depois:
class UserController {
    #[Route("usuarios/{id}", methods:["GET"])] //Métadados estruturados
    public function get($id){}
}


--- Operador NullSafe ---
Verificação de objetos nulos de forma simplificada.

-- Antes:
if($sessao !== null) {
    $user = $sessao->user;
    if($user !== null) {
        $pais = $user->getPais();
        if($pais !== null) {
            $estado = $pais->getEstado();
        }
    }
}

-- Depois:
$estado = $sessao?->user?->getPais()?->getEstado();


--- Match Expressions ---
-- Antes:
switch($status) {
    case 200:
    case 300:
        $msg = null;
        break;
    case 400:
        $msg = 'Não encontrado ou não permitido';
        break;
    case 500:
        $msg = 'Erro de servidor';
        break;
    default:
        $msg = 'Erro desconhecido';
        break;
}

-- Depois:
$msg = match($status) {
    200,300 => null,
    400 => 'Não encontrado ou não permitido',
    500 => 'Erro de servidor',
    default => 'Erro desconhecido',
};


--- Comparação entre strings e números ---
-- Antes: 0 == 'zero' //true
-- Depois: 0 == 'zero' //false


--- Funções ---
- str_contains(string $v1, string $v2):bool //buscas dentro de string, verica se v2 encontra-se em v1
- str_starts_with(string $v1, string $v2):bool //Se v1 inicia com v2
- str_ends_with(string $v1, string $v2):bool //Se v1 finaliza com v2
- get_debug_type() //Similar à gettype(), retorna tipo de var, mais ágil
- fdiv(4.5,2.8) //Divisão por float com resultado decimal preciso


--- Arrays com índices negativos ---
$carros = array_fill(-5,7,"Ferrari");


--- Exception sem variável catch ---
-- Antes:
try {
    multicar(2,3);
} catch(Exception $error) {
    echo "Erro na multiplicação";
}

-- Depois:
try {
    multiplicar(2,3);
} catch(Exception) {
    echo "Erro na multiplicação";
}


--- Throw Exception em Operador Ternário ---
$show_error = fn($error) => throw new Exception($error);
$show_error("Erro no PHP!!!");

$result = call_api();
return $result ?? throw new Exception("Erro na chamada da API");


--- Concatenações ---
Não há mais erro de concatenações de valores numéricos com strings.
$n1 = 10;
$n2 = 15;
echo "Resultado: ".($n1+$n2);


--- Métodos com retorno Static ---
class First {
    public static function class_name() {
        return __CLASS__;
    }
    public static function show() {
        return self::class_name(); //Ao trocar 'self' por 'static', a resposta se tornará 'Second'
    }
}

class Second extends First {
    public static function class_name() {
        return __CLASS__;
    }
}
echo Second::show(); //Exibirá 'first'


--- Classe WeakMaps ---
Cria referência ao objeto, e ao removê-lo será também removida sua referência.
$anos = new WeakMap;
$k = (object)"ano";
$anos[$k] = 1969;
var_dump($anos);
echo "<br>";
unset($k);
var_dump($anos);


--- ::class em objetos ---
Para saber o nome da classe referente.
class Company {
    public function index() {
        return 'UB Social';
    }
}
$res = new Company();

-- Antes: var_dump(get_class($res));
-- Depois: var_dump($res::class);


--- Vírgula no último parâmetro ---
new Address("Avenida Paulista", 260, "São Paulo", "SP", "Brasil",);


--- Outras ---
- Operador @ não silencia mais os erros fatais


--- Herança de Métodos Privados ---
class A {
    function callYourPrivate() {
        $this->myPrivate();
    }
    function notOverriden_callYourPrivate() {
        $this->myPrivate();
    }
    final private function myPrivate() {
        echo __METHOD__ . PHP_EOL;
    }
}
class B extends A {
    function callYourPrivate() {
        $this->myPrivate();
    } 
    private function myPrivate() {
        echo __METHOD__ . PHP_EOL;
    }
}

$a = new A();
$a->callYourPrivate();
$a->notOverriden_callYourPrivate();
$b = new B();
$b->callYourPrivate();
$b->notOverriden_callYourPrivate();


--- Sintaxes de variáveis ---
- Array: $foo[$bar], $foo{$bar}
- Object: $foo->bar, $foo->bar()
- Static: Foo::$bar, Foo::bar(), Foo::BAR
- Call: foo()


--- Interface Stringable ---
interface Stringable {
    public function __toString(): string;
}

Elaborado por Mateus Schwede
ubsocial.github.io