Código PHP - Referência Rápida
Esta página inclui exemplos de sintaxe de PHP básicas e como usar FastSitePHP. Assume-se que algum conhecimento em programação como o que é uma expressão [if] ou [loop]; no entanto você não tem que saber PHP para utilizar esta ferramenta.
Os exemplos são projetados de forma que basta simplesmente copiar e colar o que você precisa. Como os exemplos de código aqui estão em PHP padrão, esta página pode ser útil como uma referencia geral de PHP se você não estiver utilizando o FastSitePHP.
Mostrando 62 Seções de Código de Exemplo
Sintaxe do PHP - Visão Geral
<?php
// A sintaxe PHP é similar a sintaxe C so blocos [if], loops [for] e [while],
// [funções], [comentários] e mais são também similares a outras linguagens
// amplamente utilizadas como: JavaScript, C# e Java. Se você tiver alguma
// experiência com JavaScript é muito fácil começar a usar o PHP.
// Scripts PHP começam com [<?php] e linhas individuais devem ser finalizadas com
// um ponto e vírgula [;]. O comando [echo] exibe/imprime na tela um conteúdo.
// Salvando este exemplo em um arquivo e executando-o, simplesmente exibirá
// 'Olá Mundo!'.
echo 'Olá Mundo!';
Sintaxe PHP - Variáveis
// Em PHP todas as variáveis começam com um cifrão [$] seguido de um nome.
// A criação de variáveis em seu primeiro uso Variáveis não precisam ser
// declaradas com antecedência e são criadas em seu primeiro uso
$value = 'Teste';
// A tipagem de variáveis acontece dinamicamente no PHP; tipo de dados é
// determinado pelo valor da variável e o tipo pode ser mudado.
$value = (10 * 20); //valor
$string = 'String'; //cadeia de texto
$number = 123; //número
$decimal = 123.456;
$bool = true; //booleano
$null = null; //nulo
// Arrays podem ser definidos utilizando os caracteres [] como JavaScript
// e outras linguagens quando em qualquer versão recente do PHP. Se estiver
// utilizando versões anteriores (5.3 ou anterior) Arrays precisam ser
// definidos utilizando a função [array()].
$cities = ['Tóquio', 'São Paulo', 'Jacarta', 'Seul', 'Manila', 'Nova York']; //cidades
// Uma vírgula extra pode ser inserida depois do último item
$numbers = array(123, 456, 789,); //números
// Os arrays PHP é na verdade um mapa ordenado (map) então eles são muitas
// vezes utilizados como Dicionários, Hashes ou Arrays Associativos de outras
// linguagens.
$dias_do_mes = [
'Janeiro' => 31,
'Fevereiro' => 28,
'Março' => 31,
'Abril' => 30,
];
// Objetos podem ser dinamicamente criados em PHP utilizando a classe
// integrada [stdClass].
$objeto = new \stdClass;
$objeto->nome = 'FastSitePHP';
$objeto->tipo = 'PHP Framework';
// Objetos também podem ser criados dinamicamente fazendo casting de um array.
$objeto2 = (object)[
'nome' => 'FastSitePHP',
'tipo' => 'PHP Framework',
];
// Para verificar foi definida utilize a função [isset()]
$definida1 = isset($objeto); // true
$definida2 = isset($objeto3); // false
// Tipos adicionais incluem recursos como um arquivo e funções de callback.
Sintaxe PHP - Strings
// Similar a outras linguagens como JavaScript, Python e Ruby,
// strings em PHP pode ser cercados por aspas simples ou aspas duplas
$value = 'String em Aspas Simples';
$value = "String em Aspas Duplas";
// Para combinar ou concatenar strings utilize o caractere ponto [.]:
$saudacao = 'Olá ' . 'Mundo';
// Espaços não são obrigatórios entre o ponto [.] e as outras variáveis:
$saudacao = 'Olá '.'Mundo';
// Você pode adicionar algo a uma string utilizando o operador [.=]:
$saudacao = 'Olá';
$saudacao .= ' Mundo';
// Similar ao Python e Ruby, aspas duplas expandem variáveis para
// interpolação de texto (string). Isto imprime 'Olá Mundo':
$nome = 'Mundo';
$saudacao = "Olá ${name}";
// Strings the múltiplas linhas utilizam [<<<] seguido por um
// identificador definido pelo programador e finaliza a string com o
// mesmo identificador iniciando em uma nova linha seguido de um [;].
// Neste exemplo o identificador foi nomeado de [FDD] para Fim-Dos-Dados.
// Strings multi linha utilizando esta sintaxe suportam interpolação
// de strings.
$multilinha1 = <<<FDD
Multi linha
Texto
${nome}
FDD;
// Quando utiliza-se os caracteres ['] é similar a utilizar strings em
// aspas simples então não há interpolação de string. O exemplo acima
// imprime 'Mundo' ao invés de '${nome}' enquanto esta versão imprime
// '${nome}'
$multilinha2 = <<<'FDD'
Multi linha
Texto
${nome}
FDD;
// Funções de String comuns utilizando esta string:
$value = ' abcdefgh ';
// Comprimento (length) de String e Trim
$len = strlen($value); // 10
$len2 = strlen(trim($value)); // 8
// Busca de String, frequentemente funções PHP retornam tipos de dados
// diferentes. [strpos()] e [stripos()] são bons exemplos disso.
// Se a string for encontrada, um número inteiro com a posição será retornado,
// caso contrário, retornará um valor booleano falso.
$pos = stripos($value, 'DEF'); // Sem diferenciação de maiúsculas e minúsculas = 4
$pos2 = strpos($value, 'DEF'); // Cem diferenciação de maiúsculas e minúsculas = false
// Dividir para um Array e unir um Array a uma String.
// Ao invés de utilizar [split()/join()] PHP utiliza [explode/implode()].
$value = '123,456,789';
$array = explode(',', $value);
$string = implode('_', $array);
// Replace
$texto = 'Azul e Vermelho';
$busca = 'Vermelho';
$substituir = 'Verde';
$novo_valor = str_replace($busca, $substituir, $texto);
// Internamente no PHP strings são implementadas como um array de bytes
// então se você trabalha com arquivos ou dados binários você usa o
// tipo de dado string. Isto pode apresentar um problem no entanto se
// você precisa calcular o comprimento de uma string Unicode para um
// usuário, encontrar a posição do caractere etc. To support codificações
// diferentes o PHP inclui Funções de String Multibyte. Em termos gerais
// elas tem os mesmos nomes e parâmetros que as outras funções de string
// têm mas com o prefixo [mb_].
$unicode = '测试';
$ulen = strlen($unicode); // 6
$ulen2 = mb_strlen($unicode); // 2
Sintaxe PHP - Declaração Lógica
// Este exemplo gera dados para o cliente assim que validados:
// var_dump() = Função PHP que imprime uma variável e tipo de dado.
// echo "\n" = Gera uma nova lina para formatação.
$numero = 5;
// Declaração [if] Básica
// Imprime: '[Número equivale a 5]'
if ($numero === 5) {
echo '[Número equivale a 5]';
} else {
echo '[Número não equivale a 5]';
}
// [if ... else]. O exemplo também mostrado utilizando o operador de
// negação [!].
// Imprime: '[Número é positivo]'
if (!is_int($numero)) {
echo '[Número não é inteiro]';
} elseif ($numero < 0) {
echo '[Número é negativo]';
} else {
echo '[Número é positivo]';
}
// Expressão Ternária: (expressão ? true : false)
// Prints: [Número é par: não]
$is_even = ($numero % 2 === 0 ? 'sim' : 'não');
echo "[Número é par: ${is_even}]";
// A declaração [if] pode ser utilizada para avaliar valores "verdade" para
// outros tipos de dados. As três declarações abaixo avaliam para falso por
// que os valores são vazios ou zero.
$empty_array = array();
if ($empty_array) {
echo '[Array tem dados]';
} else {
echo '[Array está vazio]';
}
$empty_string = '';
if ($empty_array) {
echo '[String tem dados]';
} else {
echo '[String está vazia]';
}
$zero = 0;
if ($zero) {
echo '[Número não é zero]';
} else {
echo '[Número é zero]';
}
// É possível excluir a expressão do meio ao utilizar o operador ternário '?:'
// (expressão ?: padrão). Isso é conhecido como o operador Elvis e retorna
// o resultado da primeira expressão se for avaliada como uma "verdade" ou
// a segunda expressão (valor padrão).
// Imprime:
// [Operador Elvis: Padrão]
$value = ($empty_string ?: 'Padrão');
echo "[Operador Elvis: ${value}]";
// Imprime:
// [Elvis Operator: 3]
$value = ((1 + 2) ?: 'Entre um Valor');
echo "[Operador Elvis: ${value}]";
// Igual [==] vs. Idêntico (modo estrito) [===]
// O PHP é similar ao JavaScript em comparações de tipos de dados
// Essas expressões avaliam como verdadeiro [true] por que o tipo de dados
// não tem de corresponder exatamente.
echo "\n";
var_dump(1 == true);
var_dump(0 == '');
var_dump(0 == 'a');
var_dump('1' == '01');
// Essas expressões avaliam como falso [false] por que o tipo de dados tem
// que corresponder exatamente.
echo "\n";
var_dump(1 === true);
var_dump(0 === '');
var_dump(0 === 'a');
var_dump('1' === '01');
// Não Igual [!=] vs. Não Idêntico [!==]:
echo "\n";
var_dump(0 != ''); // false
var_dump(0 !== ''); // true
// Operadores Lógicos:
echo "\n";
var_dump(true && true); // true
var_dump(false && false); // false
var_dump(false || true); // true
// Arrays podem ser facilmente comparados em PHP
echo "\n";
$array1 = [1, 2, 3];
$array2 = [1, 2, 3];
$array3 = [1, 2, 3, 4];
var_dump($array1 === $array2); // true
var_dump($array1 === $array3); // false
// Declaração Switch
// Assim como a declaração [if] a sintaxe para [switch] é similar às
// linguagens baseadas no estilo C, como a própria C e JavaScript, então
// as mesmas regras podem ser aplicadas.
//
// Este exemplo imprime o nome da estação à partir do calendário de 4
// estações no hemisfério norte baseando-se no mês atual.
echo "\n";
$month = date('F');
switch ($month) {
case 'Março':
case 'Abril':
case 'Maio':
echo 'Primavera';
break;
case 'Junho':
case 'Julho':
case 'Agosto':
echo 'Verão';
break;
case 'Setembro':
case 'Outubro':
case 'Novembro':
echo 'Outono';
break;
case 'Dezembro':
case 'Janeiro':
case 'Fevereiro':
echo 'Inverno';
break;
default:
echo 'Erro';
}
Sintaxe PHP - Loops
// Just like the logic demo this example also outputs data as it is evaluated.
// Assim como a demonstração de lógica, este exemplo também gera dados assim
// que validados.
// Define arrays com as maiores cidades no mundo (por área urbana)
$cities = [
"Tóquio", "São Paulo", "Jacarta", "Seul", "Manila",
"Nova York", "Xangai", "Cairo", "Délhi"
];
$cities_populacao = [
'Tóquio' => '36,923,000',
'São Paulo' => '36,842,102',
'Jacarta' => '30,075,310',
'Seul' => '25,520,000',
'Manila' => '24,123,000',
'Nova York' => '23,689,255',
'Xangai' => '23,416,000',
'Cairo' => '22,439,541',
'Délhi' => '21,753,486',
];
echo 'Maiores Cidades no Mundo' . "\n";
echo str_repeat('-', 40) . "\n";
// Fazer um Loop pelas listas de cidades utilizando [foreach].
// foreach (array as item)
foreach ($cities as $city) {
echo $city;
echo "\n";
}
echo "\n";
// Fazer um Loop por um Dicionário ou Array Associativo utilizando [foreach]
// foreach (array as key => value)
foreach ($cities_populacao as $city => $populacao) {
echo $city . ' = ' . $populacao;
echo "\n";
}
echo "\n";
// Loop [for] utilizando estilo de sintaxe C, isto imprime 0...9 em linhas
// separadas
for ($n = 0; $n < 10; $n++) {
echo $n;
echo "\n";
}
echo "\n";
// Loops [while] e [do-while] também utilizam estilo de sintaxe C, então são
// familiares para desenvolvedores JavaScript. [continue] e [break]
// também funcionam como esperado.
// Imprime números pares entre 0 e 8
$n = 0;
while ($n < 10) {
if ($n % 2 !== 0) {
$n++;
continue;
}
echo $n;
echo "\n";
$n++;
}
echo "\n";
// Imprime 0...4
$n = 0;
do {
if ($n === 5) {
break;
}
echo $n;
echo "\n";
$n++;
} while ($n < 10);
Sintaxe PHP - Funções
// Definir e chamar funções em PHP é similar a outras linguagens estilo C.
// Enquanto funções são facilmente definidas em PHP com muita taxa
// frameworks populares e projetos PHP definem classes ao invés de funções.
// PHP no entanto, tem muitas funções integradas que são utilizadas em
// desenvolvimento
function add($x, $y) {
return $x + $y;
}
// Parâmetros opcionais podem ser especificados atribuindo um valor para
// a variável.
function increment($x, $y = 1) {
return $x += $y;
}
// Funções Callback pode ser definidas e atribuídas para uma variável da
// mesma forma que seria em JavaScript.
$subtract = function($x, $y) {
return $x - $y;
};
// Este código chama as funções acima e imprime "2"
$x = 1;
$y = 2;
$z = add($x, $y); // returns 3
$z = increment($z); // returns 4
$z = increment($z, 2); // returns 6
$z = $subtract($z, 4); // returns 2
echo $z;
echo '<br>';
// Diferente do JavaScript as funções PHP não tem acesso a variáveis
// fora de seu escopo (escopo pai/escopo superior). A palavra chave
// [use] pode ser utilizada para passar variáveis fora do escopo da
// função. Ao utilizar essa sintaxe e ao definir [$x] na função
// chamada, [$x] não é definida à partir do escopo superior então
// este código imprime "1".
$scope_test = function() use ($x) {
$x = 123;
};
$scope_test();
echo $x;
echo '<br>';
// Esta versão é similar a versão acima no entanto a variável [$x] é
// passada por referência utilizando o operador [&]. Esta versão
// imprimirá "123" por que [$x] é modificada.
$scope_test = function() use (&$x) {
$x = 123;
};
$scope_test();
echo $x;
echo '<br>';
Sintaxe PHP - Classes e Objetos
// Como definir e utilizar classes em detalhe, foge do escopo desta
// página de referência rápida entretanto, a sintaxe básica é mostrada
// abaixo o que pode ajudar a começar.
class Math
{
// Define uma Variável Membro
public $value = 0;
// Define um construtor de Classe com um parâmetro opcional.
// Definir um construtor [__construct] é opcional.
public function __construct($numero = 0)
{
$this->value = $numero;
echo 'Classe criada como valor: ' . $numero . '<br>';
}
// Definir um destruidor de Classe
public function __destruct()
{
echo 'Classed Destroyed<br><br>';
}
// Função pública que retorna a instância do objeto [$this]
public function add($numero) {
$this->value += $numero;
return $this;
}
// Função sem parâmetro ou valor de retorno
public function show()
{
echo 'Value: ' . $this->value . '<br>';
}
}
// Imprime:
/*
Classe criada com o valor: 0
Valor: 3
Classe destruída
*/
$math = new Math();
$math->add(1)->add(2)->show();
$math = null;
// Imprime:
/*
Classe criada como valor: 10
Valor: 15
...
*/
$math = new Math(10);
$math->add(5)->show();
// Ler de uma variável associada:
$value = $math->value;
echo $value . '<br>';
Sintaxe PHP - Codificação - JSON, Base64, Base64-URL
// Criar um objeto e um array básicos para codificar
$object = new \stdClass;
$object->string = 'Test';
$object->number = 123;
$object->bool = true;
$array = [
'string' => 'Test',
'number' => 123,
'bool' => true,
];
// -------------------------------------------
// Codificar e Decodificar JSON
// -------------------------------------------
// Desde que o array PHP seja utilizado como um Dicionário ou Hash,
// ambos exemplos imprimem:
// {"string":"Test","number":123,"bool":true}
$json = json_encode($object);
echo $json;
echo "\n";
$json = json_encode($array);
echo $json;
echo "\n\n";
// Utilize o segundo parâmetro para JSON formatado
$json = json_encode($object, JSON_PRETTY_PRINT);
echo $json;
echo "\n";
// Decodifique e imprima o objeto com detalhes utilizando [print_r()]:
$decoded = json_decode($json);
print_r($decoded);
echo "\n";
// Por padrão objetos são decodificados como objetos da [stdClass].
// Para retornar um array ao invés de um objeto passe [true] como o
// segundo parâmetro.
$decoded = json_decode($json, true);
print_r($decoded);
echo "\n";
// Se houver um erro ao decodificar dados JSON será retornado [null].
// Se você precisar Se você precisar lidar com um JSON inválido, você pode
// fazer dessa forma:
if ($decoded === null && json_last_error() !== JSON_ERROR_NONE) {
throw new \Exception('Erro decodificando Dados JSON: ' . json_last_error_msg());
}
// O FastSitePHP inclui uma classe auxiliar JSON que lança excessẽs em erros
// JSON ao invés de utilizar o comportamento padrão de retornar [false] ou
// [null].
$json = \FastSitePHP\Encoding\Json::encode($object);
$decoded = \FastSitePHP\Encoding\Json::decode($json);
/* Muitas vezes no entanto, na maioria dos códigos, simplesmente chamar
[json_encode()] ou [json_decode()] será suficiente. Por padrão o PHP
decodifica números grandes como ponto flutuante. Se você quer uma
decodificação mais estrita para que venham em string, então você pode
utilizar opções adicionais. É assim que a classe JSON do FastSitePHP
decodifica quando é utilizada nas classes JWT, Encryptione SignedData.
[JSON_BIGINT_AS_STRING] não está disponível no PHP 5.3 então o
FastSitePHP utiliza código compatível. */
$decoded = json_decode($json, true, 512, JSON_BIGINT_AS_STRING);
// -------------------------------------------
// Codifique e Decodifique Base64
// -------------------------------------------
// Imprime: "VGhpcyBpcyBhIHRlc3Q="
$data = 'Isto é um teste';
$base64 = base64_encode($data);
echo $base64;
echo "\n";
// Ao decodificar, se houver um erro então [false] é retornado
$decoded = base64_decode($base64);
print_r($decoded);
echo "\n\n";
// ---------------------------------------------
// Codifique e Decodifique o Formato Base64-URL
// ---------------------------------------------
/* O PHP não tem funções internas para o formato Base64-URL então o
FastSitePHP inclui uma classe auxiliar com métodos estáticos. Eles se
comportam de forma similar às funções integradas [base64_encode()] e
[base64_decode()], então, se houver um erro, será retornado [false]. */
$base64url = \FastSitePHP\Encoding\Base64Url::encode($data);
echo $base64;
echo "\n";
$decoded = \FastSitePHP\Encoding\Base64Url::decode($base64url);
print_r($decoded);
echo "\n";
Sintaxe PHP - Erros e Exceções
// PHP usa ambos Erros, que são provocados, e Exceções que são lançadas.
// PHP lida com erros de forma diferente de muitas linguagens. Por exemplo
// linguagens um erro "divisão por zero" tanto lançaria uma Exceção ou seria
// fatal e interromperia o programa e, em linguagens compiladas uma variável
// indefinida não permitiria que o programa rodasse. Entretanto ao utilizar
// PHP, a não ser que o relatório de erros esteja definido, ambos os erros
// seriam simplesmente ignorados e o script continuaria com resultados
// inesperados. Isso pode tornar programar em PHP difícil no início se você
// estiver vindo de outra linguagem. FastSitePHP torna as coisas fáceis, por This can make programming
// que roda o código em modo estrito e converte erros para exceções assim
// que [app->setup()] é chamada.
// Para controlar todos os erros e exceções de forma global em PHP, quatro
// funções diferentes tem de ser definidas primeiro. Essas são controladas
// automaticamente à partir de [app->setup()]:
// error_reporting()
// set_exception_handler()
// set_error_handler()
// register_shutdown_function()
// Em PHP, a lógica de [try...catch], é similar a muitas linguagens como
// JavaScript:
try {
throw new \Exception('Test');
} catch (\Exception $e) {
echo $e->getMessage();
echo '<br>';
}
// A existência de variáveis pode ser verificada.
// Eeste código funciona e nenhum erro é desencadeado.
if (isset($x) === false) {
echo 'A variável [$x] não foi definida<br>';
}
// Descomentando as linhas abaixo desencadeará tipos diferentes de erros.
// Ao utilizar os parâmetros padrão de desenvolvimento PHP os erros, muitas
// vezes causarão uma mensagem de erro no meio do código e o código posterior
// ainda será executado.
//
// echo $x; // [E_NOTICE] = "Variável indefinida: x"
// echo 1 / 0; // [E_WARNING] = "Divisão por zero"
// FastSitePHP converte Erros em Exceções para que eles possam ser capturados
try {
echo $x;
} catch (\Exception $e) {
echo $e->getMessage();
echo '<br>';
}
try {
echo 1 / 0;
} catch (\Exception $e) {
echo $e->getMessage();
echo '<br>';
}
Olá Mundo com FastSitePHP
<?php
// Somente dois arquivos são necessários para rodar o FastSitePHP e eles podem
// estar no mesmo diretório que o [index.php] ou seus conteúdos podem ser
// integrados na página principal PHP.
require 'Application.php';
require 'Route.php';
// Crie o Objeto Application e opcionalmente configure controle de Erro e
// Fuso um horário.
$app = new FastSitePHP\Application();
$app->setup('UTC');
// Defina a rota padrão do 'Olá Mundo'
$app->get('/', function() {
return 'Olá Mundo!';
});
// Retorne uma resposta JSON como um Objeto ou um Array
$app->get('/json', function() {
return ['Olá' => 'Mundo'];
});
// Para todas as outras requisições, retorne a URL como resposta em texto puro.
// A palavra chave [use] torna a variável [$app] disponível para a função.
$app->get('/*', function() use ($app) {
$app->header('Content-Type', 'text/plain');
return $app->requestedPath();
});
// Rode a App
$app->run();
Objeto Application - Definindo Rotas Básicas
// O Objeto Application é o objeto chave no FastSitePHP. É utilizado para
// definir rotas, fornecer informações e requisição, renderizar modelos,
// enviar a resposta e mais. Se você estiver utilizando uma cópia deste
// site ou um site inicial o Objeto Application estará disponível como a
// variável [$app] e rotas são definidas na página [app.php].
// Rota Básica
// Envie uma Reposta HTML quando quando '/about' ou '/about/' for requisitado
$app->get('/about', function() {
return '<h1>Página About</h1>';
});
// Por padrão URLs diferenciam maiúsculas de minúsculas, entretanto, isso
// pode ser desativado e '/ABOUT' corresponderia à rota acima.
$app->case_sensitive_urls = false;
// Se o mode estrito de URL estiver definido, então, a URL acima apenas
// corresponderia a '/about' e '/about/' teria que ser definida
// explicitamente.
$app->strict_url_mode = true;
$app->get('/about/', function() {
return '<h1>Diretório About</h1>';
});
// A chamada de about utilizando [get()] corresponde somente a requisições
// 'GET'. Se você gostaria de controlar ambos 'GET' e 'POST' ou outros
// métodos com a mesma rota, você pode definir a rota utilizando a função
// de rota [route()] e verificar se há dados enviados com a requisição
// como mostrado abaixo. A função [route()] aceitará todos os métodos de
// requisição.
$app->route('/form', function() {
if ($_POST) {
// Controle dados postados de formulário
}
// Controle requisições GET, retorne o modelo renderizado etc
});
// Em acréscimo às Requisições GET, você pode manipular requisições
// [POST, PUT, PATCH, and DELETE] utilizando funções nomeadas.
$app->get('/method', function() { return 'get()'; });
$app->post('/method', function() { return 'post()'; });
$app->put('/method', function() { return 'put()'; });
$app->patch('/method', function() { return 'patch()'; });
$app->delete('/method', function() { return 'delete()'; });
// A mesma URL ode ser definida múltiplas vezes e a primeira resposta
// correspondente impedirá rotas adicionais de serem avaliadas. Neste
// exemplo a rota '/example' retornará o texto 'Exemplo 2'.
$app->get('/example', function() { return null; });
$app->get('/example', function() { return 'Exemplo 2'; });
$app->get('/example', function() { return 'Exemplo 3'; });
// Além de retornar uma resposta, você pode também simplesmente exibir uma
// resposta utilizando [echo] ou outras funções.
$app->get('/echo-response', function() {
echo 'Output';
});
Define uma Rota com um Parâmetro
// Envie uma resposta 'Olá FastSitePHP!' para a URL '/hello/FastSitePHP'.
// O texto ':name' no modelo de rota define um parâmetro para a rota
// por que inicia-se com o caractere ':'.
$app->get('/hello/:name', function($name) {
return 'Olá ' . $name;
});
Define uma Rota com um Parâmetro Opcional
// Envie uma resposta 'Olá Mundo!' para a URL '/hello' ou no caso da variável
// opcional [name] escapa e retorna uma mensagem como nome. A palavra chave
// [use] faz a variável [$app] ficar disponível para a função e o ponto de
// interrogação no modelo da URL ':name?' torna a variável opcional.
$app->get('/hello/:name?', function($name = 'Mundo') use ($app) {
return 'Olá ' . $app->escape($name) . '!';
});
// Além os parâmetros opcionais um caractere curinga '*' pode ser utilizado
// no final da URL para manipular todas as requisições que correspondem ao
// início da URL. Neste exemplo as seguintes URLs seria ambas correspondidas.
// '/hello/world'
// '/hello/page1/page2/page3'
$app->get('/hello/*', function() use ($app) {
$app->header('Content-Type', 'text/plain');
return $app->requestedPath();
});
Defina a Rota que mapeia para uma Classe de Controle
// Definindo rotas com uma funções callback, permite prototipagem rápida
// e funciona bem ao utilizar lógica mínima. Com o crescimento do código,
// isso pode ser organizado em classes controller.
// Opcionalmente especifique o Namespace raiz da classe controller. Ao usar
// este arquivo se uma classe 'Exemplos' for criada, então, isso será
// mapeado como 'App\Controllers\Examples'.
$app->controller_root = 'App\Controllers';
// Semelhante a [controller_root], [middleware_root] a qual se aplica às
// funções [Route->filter()] e [$app->mount()].
$app->middleware_root = 'App\Middleware';
// As duas opções de formato são 'class' e 'class.method'. Ao utilizar só
// nome de classe, a funções de rota [route(), get(), post(), put(), etc]
// serão utilizadas para o nome do método do controller correspondente.
$app->get('/:lang/examples', 'Exemplos');
$app->get('/:lang/examples/:page', 'Exemplo.getExample');
// Exemplo de Classe de Controle
class Exemplos
{
public function get(Application $app, $lang) { }
public function getExample(Application $app, $lang, $page) { }
}
// Além de organizar o código em classes de controle, você pode também
// separar rotas em arquivos diferentes utilizando a função [mount()]. A
// função [mount()] carregará um arquivo no mesmo diretório somente se a
// parte inicial da URL requisitada corresponder à URL de Mount. Um terceiro
// parâmetro opcional aceita uma função callback ou string de 'Class.method'
// e se o retorno for false, o arquivo não será carregado.
$app->mount('/data/', 'routes-data.php');
$app->mount('/secure/', 'routes-secure.php', function() {
// Lógica ...
return false;
});
$app->mount('/sysinfo/', 'routes-secure.php', 'Env.isLocalhost');
Validação de Parâmetro de Rota
// O Objeto da Aplicação tem uma função [param()] que pode ser utilizado para
// validar e converter os parâmetros da URL para um formato específico como
// um número.
// A função é definida como:
// param($name, $validation, $converter = null)
// Parâmetros:
// Validation = ['any', 'int', 'float', 'bool'], uma expressão regular
// válida ou uma função Closure/Callback. Ao utilizar
// 'int|float|bool' o tipo de dado será automaticamente convertido.
// Convertor = ['int', 'float', 'bool'] ou uma função Closure/Callback.
// Exemplo Básico
// '/product/123' = Corresponde e [$product_id] será um número inteiro
// '/product/abc' = 404 Página não encontrada
$app->param(':product_id', 'int');
$app->get('/product/:product_id', function($product_id) {
var_dump($product_id);
});
// Exemplos adicionais de Definição de Regras de Parâmetros. Para mais veja
// a documentação completa e outros exemplos.
$range_param = function($value) {
$num = (int)$value;
if ($num >= 5 && $num <= 10) {
return true;
} else {
return false;
}
};
$app
->param(':range1', $range_param)
->param(':range2', $range_param, 'int')
->param(':range3', $range_param, function($value) {
return (int)$value;
});
$app->param(':float', 'float');
$app->param(':bool', 'any', 'bool');
$app->param(':regex1', '/^\d+$/');
$app->param(':regex2', '/^[a-zA-Z]*$/');
Utilize Filtros de Rota
// Rotas podem ter funções filtro personalizadas atribuídas a elas para
// rodar códigos específicos se uma rota for correspondida, realizar
// validação ou outra tarefa requisitada pelo seu site. Funções Filtro rodam
// somente se a rota corresponder a URL requisitada.
// Definir algumas funções callback/closure
$text_response = function() use ($app) {
$app->header('Content-Type', 'text/plain');
};
$is_authenticated = function() {
// Verificar Permissões de Usuário ...
return true;
};
// Quando rotas são criadas [get(), route(), post(), etc], a rota criada é
// retornada para que você possa chamar [filter()] depois de definir a rota.
// Esta página será retornada como Texto Puro por que a função filtro define
// o Cabeçalho de Resposta e não retorna valor.
$app->get('/text-page', function($name) {
return 'Olá';
})->filter($text_response);
// Uma rota pode ter múltiplos filtros e para clareza você pode colocar
// funções filtro em linhas separadas. Esta página será somente chamada se
// [$is_authenticated] retornar [true] e isso for também uma resposta em
// texto.
$app->get('/secure-text-page', function($name) {
return 'Olá ' . $name;
})
->filter($is_authenticated)
->filter($text_response);
// A função [filter()] também aceita uma string representando uma classe e
// método no formato de 'Classe.método'.
$app->get('/phpinfo', function($name) {
phpinfo();
})
->filter('Env.isLocalhost');
// Quando usar filtros de string, você pode especificar um namespace raiz
// para as classes utilizando a propriedade de App [middleware_root].
$app->middleware_root = 'App\Middleware';
Objeto de Aplicação - Informação de Básicas de Requisição
// Muitos frameworks requerem valores especiais de configurações para que
// possam manipular requisições. O FastSitePHP descobre isso automaticamente
// e fornece algumas funções no Objeto Application para retornar
// informações básicas de requisição.
// Se seu site não usa um servidor proxy como balanceador de carga essas
// funções pode ser utilizadas para criar URLs ou outras necessidades do app.
//Se seu site utiliza um balanceador de cargas com cabeçalhos personalizados
// para o host, então você utilizaria o objeto da requisição para obter a
// URL raiz.
// URL raiz ou base para o site. Isso é frequentemente necessário para
// construir URL com caminhos completos em páginas web.
//
// Exemplos:
// # [index.php] especificado no URL
// Request: https://www.example.com/index.php/page
// https://www.example.com/index.php/page/page2
// Returns: https://www.example.com/index.php/
//
// # [index.php] Localizado na pasta raiz
// Request: https://www.example.com/page
// https://www.example.com/page/page2
// Returns: https://www.example.com/
//
// # [index.php] Localizado sob [site1]
// Request: https://www.example.com/site1/page
// https://www.example.com/site1/page/page2
// Returns: https://www.example.com/site1/
//
$root_url = $app->rootUrl();
// Diretório raiz para o site. Geralmente necessário para construir URLs para
// recursos estáticos como arquivos CSS ou JavaScript.
//
// Request: https://www.example.com/index.php/page
// https://www.example.com/index.php/page/page2
// https://www.example.com/page
// Returns: https://www.example.com/
//
$root_dir = $app->rootDir();
// Obtém a URL requisitada que exite depois da URL raiz. Isso será baseado
// em onde o [index.php] ou entrada no arquivo PHP estiver localizada.
//
// Request: https://www.example.com/index.php/test/test?test=test
// https://www.example.com/index.php/test/test
// https://www.example.com/test/test/
// https://www.example.com/test/test
// https://www.example.com/site1/index.php/test/test
// Returns: '/test/test'
//
// No exemplo acima ambos '/test/test/' e '/test/test' retornam '/test/test'
// quando utiliza-se a propriedade padrão [$app->strict_url_mode = false]
// caso contrário a URL exata será retornada.
//
$requested_path = $app->requestedPath();
// Exemplo de utilização para construção de URL:
$site_css = $app->rootDir() . 'css/site.css';
$docs_link = $app->rootUrl() . '/documents';
//
// <link href="{{ $site_css }}" rel="stylesheet" />
// <a href="{{ $docs_link }}">Documentos</a>
Funçẽs Dinâmicas e Propriedades Lazy Loading
// FastSitePHP permite que o objeto da aplicação tenha funções dinamicamente
// atribuídas e propriedades lazy loading. Isso permite que funções
// personalizadas e recursos compartilhados por muitas rotas serem organizados
// sob um objeto global e pode permitir uma injeção simples e clara de
// de dependência.
// Exemplo JavaScript - Isto funciona para adicionar uma função dinamicamente
// a um objeto:
//
// var obj = {};
// obj.test = function() { alert('test'); };
// obj.test();
// Exemplo PHP - A função pode ser atribuída a uma propriedade, entretanto,
// se chamada um erro é acionado - 'Call to undefined method ...'.
$obj = new \stdClass;
$obj->test = function() { echo 'teste'; };
// $obj->test();
// Ao utilizar o objeto aplicação do FastSitePHP você pode simplesmente
// atribuir e usar funções como em JavaScript ou Ruby.
$app->test = function() { echo 'test'; };
$app->test();
// A função nativa de PHP [method_exists()] não funcionará para funções
// personalizadas, então para verificar se exite um método integrado ou
// personalizado do App use isso.
$exists = $app->methodExists('test');
// A função [lazyLoad()] aceita um nome de propriedade e função de callbback.
// Isso cria o objeto como uma propriedade do app somente se utilizada. Isso
// é ideal para trabalhar com sites onde algumas páginas usam um recurso e
// outras não.
$app->lazyLoad('db', function() {
return $pdo = new \PDO('sqlite::memory:');
});
// [$app->db] é definida aqui no primeiro uso.
$sql = 'CREATE TABLE test (id INTEGER PRIMARY KEY, test)';
$app->db->query($sql);
// [$app->db] agora funciona como uma propriedade padrão já que ela foi
// previamente chamada.
$sql = 'SELECT * FROM sqlite_master';
$records = $app->db->query($sql)->fetchAll(\PDO::FETCH_ASSOC);
Eventos da Aplicação
<?php
// Da mesma for que na demonstração Hello World, este código pode ser copiado
// para um [index.php] separado ou outro arquivo e então testado.
// Existem 5 eventos callback da Aplicação:
// before(), beforeSend(), after(), notFound(), and error()
// Eles podem ser usados para manipular lógica personalizada enquanto a aplicação
// está rodando.
// Carregue Arquivos
require 'Application.php';
require 'Route.php';
// Ou utilize um Autoloader:
// require '../../vendor/autoload.php';
// Cria e Configura o objeto App
$app = new FastSitePHP\Application();
$app->setup('UTC');
// ------------------------------------------------------------------
// Defina Eventos
// ------------------------------------------------------------------
// Eventos [Before] serão chamados da função [run()] antes que qualquer rota seja
// correspondida. Todas funções de evento podem ser chamadas múltiplas vezes e
// rodarão na ordem que foram definidas.
$app->before(function() use ($app) {
$app->content = '[before1]';
});
$app->before(function() use ($app) {
$app->content .= '[before2]'; // Append
});
// Eventos [Before Send] serão chamados da função [run()] depois que uma rota
// corresponder ao recurso requisitado. Funções passadas para a função
// [beforeSend()] devem ser definidas como [function($content)] e elas devem
// retornar uma resposta caso contrário uma resposta 404 'Não encontrada' será
// enviada para o cliente.
$app->beforeSend(function($content) {
return $content . '[beforeSend]';
});
// Eventos [Not Found] serão chamados da função [run()] depois que todas as rotas
// forem verificadas e não houverem rotas que correspondam ao recurso requisitado.
// Funções passadas para a função [notFound()] não recebem parâmetros e, se elas
// retornam uma resposta, são tratadas como uma rota padrão e chamará quaisquer
// funções definidas [beforeSend()] após.
$app->notFound(function() use ($app) {
return $app->content . '[notFound]';
});
// Eventos [Error] serão acionados se uma exceção não manipulada for lançada, um
// erro for acionado ou uma rota não corresponder e acionar uma resposta 404 ou
// 405. Esta função pode ser utilizada para fazer log de erros ou manipular a
// resposta com um erro personalizado. if [exit()] não for chamada, então o
// modelo de erro especificado ou padrão do FastSitePHP será renderizado.
$app->error(function($response_code, $e) use ($app) {
// $response_code = [null, 404, 405, or 500]
// $e = [null, Exception, or Throwable]
if ($app->requestedPath() === '/error-test-1') {
echo $app->content . '[Custom Error]';
exit();
}
});
// Eventos [After] serão chamados da função [run()] depois que a resposta estiver
// sido enviada para o cliente. Funções passadas para a função [after()] devem
// ser definidas como [function($content)]; o parâmetro [$content] definido
// na callback é o conteúdo da resposta que foi enviada para o cliente e não
// pode ser modificado à partir daqui. A única forma que funções [after()] não
// serão chamadas é se seus scripts terminarem por uma declaração PHP [exit()]
// ou se a manipulação de erros não estiver configurada e algum erro ocorrer.
$app->after(function($content) {
echo '[after]';
});
// ------------------------------------------------------------------
// Define Rotas
// ------------------------------------------------------------------
// Esta resposta resultará no seguinte:
// [before1][before2][page][beforeSend][after]
$app->get('/', function() use ($app) {
return $app->content . '[page]';
});
// Chame a URL '/test' e veja o seguinte:
// [before1][before2][notFound][beforeSend][after]
// Esta resposta resultará no seguinte:
// [before1][before2][Custom Error]
$app->get('/error-test-1', function() {
throw new \Exception('Teste de Erro 1');
});
// Mostra a Página de Erro Padrão com [after] sendo mostrado na parte inferior
$app->get('/error-test-2', function() {
throw new \Exception('Teste de Erro 2');
});
// ------------------------------------------------------------------
// ROda a App
// ------------------------------------------------------------------
$app->run();
Modelo PHP de Exemplo
<!--
// Estes são os conteúdos do arquivo [template.php] que é mostrado como um exemplo
// nesta página. Ao chamar [render()] o Objeto Application é passado como [$app]
// o que permite que [escape()] e outras funções sejam utilizadas. Alé da sintaxe
// padrão [if (expression) { code }] o PHP provê uma sintaxe alternativa para
// controlar estruturas ao utilizar modelos [if (expr): (code) endif].
//
// Os modelos PHP são de alto desempenho e usam pouquíssima memória, entretanto,
// a sintaxe pode ser considerada mais verbosa que muitos formatos de modelos
// modernos. Se você preferir utilizar um formato de modelo diferente, existem
// muitos mecanismos de modelos para PHP amplamente utilizados e de alta
// qualidade que podem ser integrados ao FastSitePHP.
-->
<h1><?= $app->escape($page_title) ?></h1>
<?php if (count($list) === 0): ?>
<p>Não Foram Encontrados Registros</p>
<?php else: ?>
<ol>
<?php foreach ($list as $item): ?>
<li><?= $app->escape($item) ?></li>
<?php endforeach ?>
</ol>
<?php endif ?>
<p><?= $app->escape($year) ?></p>
Aplicação - Renderiza Arquivos de Modelo Server-Side
// Define o Diretório Modelo Raiz e Arquivos Principais Específicos
$app->template_dir = __DIR__ . '/views/';
// $app->header_templates = '_header.php';
// $app->footer_templates = '_footer.php';
// $app->error_template = 'error.php'; // Para respostas 500
// $app->not_found_template = '404.php'; // Para respostas 404 e 405
// De forma opcional mostre erros detalhados ao utilizar o modelo de erro
// padrão e defina mensagens de erro. Com o modelo padrão, erros detalhados
// serão exibidos quando rodar como localhost.
$app->show_detailed_errors = true;
// $app->error_page_title = 'Página de Erro Personalizada';
// $app->error_page_message = 'Mensagem de Erro Personalizada';
// $app->not_found_page_title = 'Página 404 Personalizada';
// $app->not_found_page_message = 'Mensagem 404 Personalizada';
// $app->method_not_allowed_title = 'Página 405 Personalizada';
// $app->method_not_allowed_message = 'Mensagem 405 Personalizada';
// Defina Dados para o Modelo. Variáveis pode ser definidas na propriedade
// [locals] da App e elas podem ser passadas na função de renderização.
$app->locals['year'] = date('Y');
$data = [
'page_title' => 'Modelo PHP de Exemplo',
'list' => ['Item 1', 'Item 2', 'Item 3', 'Item 4'],
];
// Renderiza o Modelo PHP e retorna uma string.
// O código fonte do modelo é mostrado na seção de código do exemplo acima.
$html = $app->render('template.php', $data);
Aplicativo - Renderiza com um Mecanismo de Modelo Personalizado
// Defina um Mecanismo de Modelo Personalizado que utiliza o popular sistema
// de Modelos Mustache.
$app->engine(function($file, array $data = null) {
$dir = __DIR__ . '/views/';
$options = [
'cache' => dirname(__FILE__).'/tmp/cache/mustache',
'loader' => new Mustache_Loader_FilesystemLoader($dir, ['extension' => '.htm']),
];
$mustache = new Mustache_Engine($options);
$tmpl = $mustache->loadTemplate($file);
$html = $tmpl->render($data);
return $html;
});
// Defina os Dados para o Modelo
$app->locals['year'] = date('Y');
$data = [
'page_title' => 'Exemplo de Modelo Mustache',
'list' => ['Item 1', 'Item 2', 'Item 3', 'Item 4'],
'has_list' => true,
];
// Renderiza o Modelo
$html = $app->render('template.mustache', $data);
// Ao utilizar Modelos Personalizados, você pode definir Páginas de Erro e
// Não Encontradas Personalizadas:
// $app->error_template = 'error'; // Para Respostas 500
// $app->not_found_template = '404'; // Para Respostas 404 e 405
Objeto HTTP Request - Lendo Strings de Consulta, Campos de Formulários e Cookies
// O objeto Request pode ser utilizado obtendo informações do cliente
// para uma requisição HTTP. Isso inclui strings de consulta, campos de formulários
// cookies, cabeçalhos e mais. O objeto Request contém funções para
// limpar e de, forma segura, ler informações do cliente.
// Sem utilizar um framework, strings de consulta, variáveis de formulário,
// e outras entradas de usuário, podem ser lidas através de superglobais PHP
// Without using a Framework, Query Strings, Form Variables and other
// [$_GET, $_POST, etc].
// Exemplo, leia o campo da string de consulta [number]:
$numero = $_GET['number'];
// Se a string de consulta [type] não existe, então o código acima lançaria
// uma exceção e, para obter de forma segura o valor, você poderia
// primeiro verificar se foi definida.
$numero = (isset($_GET['number']) ? $_GET['number'] : null);
// Uma linha de código PHP adicional pode ser utilizada para forçar um valor
// numérico:
$numero = (int)$numero;
// A requisição pode ser utilizada então para, seguramente, ler os valores,
// converter tipos de dados etc. Para usar o objeto Requisição, simplesmente
// crie um:
$req = new \FastSitePHP\Web\Request();
// Você pode então ler strings de consultas por nome sem incluir lógica segura:
$numero = $req->queryString('number');
// Um segundo parâmetro opcional pode ser utilizado para converter para um
// tipo de dados específico. Neste exemplo o valor será convertido para um
// número inteiro se for válido, caso contrário, [null] será retornado.
$numero = $req->queryString('number', 'int?');
// Além de [queryString()] as funções [form()] e [cookie()] podem ser
// utilizadas da mesma maneira.
$value = $req->form('field');
$cookie = $req->cookie('name');
// O objeto Request, também contém uma função auxiliar para manipular entradas
// de usuário e objetos onde um valor pode ou não existir. Isso pode ser
// utilizado para prevenir erros quando objetos JSON complexos são lidos e
// para limpar dados de qualquer objeto ou array.
//
// Definição de Função:
// value($data, $key, $format = 'value?', $max_length = null)
//
// Dados de Exemplo:
// $_POST['input1'] = 'test';
// $_POST['input2'] = '123.456';
// $_POST['checkbox1'] = 'on';
// $json = [
// 'app' => 'FastSitePHP',
// 'strProp' => 'abc',
// 'numProp' => '123',
// 'items' => [ ['name' => 'item1'], ['name' => 'item2'] ],'
// ];
//
// Funções de Exemplo:
// 'test' = $req->value($_POST, 'input1');
// // Truncar a string para dois caracteres:
// 'te' = $req->value($_POST, 'input1', 'string', 2);
// 123.456 = $req->value($_POST, 'input2', 'float');
// '' = $req->value($_POST, 'missing', 'string'); // Faltando
// 1 = $req->value($_POST, 'checkbox1', 'checkbox');
// 0 = $req->value($_POST, 'checkbox2', 'checkbox'); // Faltando
// true = $req->value($_POST, 'checkbox1', 'bool');
// 'FastSitePHP' = $req->value($json, 'app');
// 'abc' = $req->value($json, 'strProp', 'string?');
// 0 = $req->value($json, 'strProp', 'int'); // Int Inválido
// null = $req->value($json, 'strProp', 'int?'); // Int Inválido
// 123 = $req->value($json, 'numProp', 'int');
// 'item1' = $req->value($json, ['items', 0, 'name']);
// 'item2' = $req->value($json, ['items', 1, 'name']);
// null = $req->value($json, ['items', 2, 'name']); // Faltando
//
// Veja a documentação completa para mais. Se você precisa de validação
// completa ao invés de limpeza de dados veja a classe [\FastSitePHP\Data\Validator].
Objeto HTTP Request - Requisite JSON e Conteúdo
// Create the Request Object
$req = new \FastSitePHP\Web\Request();
// Obtenha o tipo do conteúdo da requisição. Isso é um campo auxiliar que
// retorna um valor simples baseado no cabeçalho 'Content-Type':
// 'json' = 'application/json'
// 'form' = 'application/x-www-form-urlencoded'
// 'xml' = 'text/xml' or 'application/xml'
// 'text' = 'text/plain'
// 'form-data' = 'multipart/form-data'
// Se diferente, o valor puro do cabeçalho será retornado e se o cabeçalho
// nao estiver definido, então [null] será retornado.
$type = $req->contentType();
// O corpo/conteúdo da requisição pode ser lido à partir de [content()]. Se
// o tipo da requisição for JSON, então o objeto será analisado e um
// objeto/array será retornado. Se [contentType() === 'form'] então um array
// será retornado, caso contrário, o corpo/conteúdo é retornado como uma
// string. No PHP uma string pode também ser utilizada para dados binários
// por que uma string é simplesmente um array de bytes.
$body = $req->content();
// A função [value()] pode ser utilizada para, de forma segura, ler valores
// aninhados de um objeto JSON enviado. Veja outros exemplos e documentos
// para mais sobre o uso da função [value().
$value = $req->value($body, ['items', 0, 'name']);
Objeto HTTP Request - Campos de Cabeçalho
// Crie o Objeto Request
$req = new \FastSitePHP\Web\Request();
// Lendo Campos Comuns de Cabeçalho pode ser feito através de funções:
$origin = $req->origin();
$userAgent = $req->userAgent();
$referrer = $req->referrer();
$client_ip = $req->clientIp();
$protocol = $req->protocol();
$host = $req->host();
$port = $req->port();
// Ao utilizar funções com cabeçalhos 'Accept' um array de dados é retornado
// e um parâmetro opcional pode ser passado para retornar [true] ou [false]
$accept_encoding = $req->acceptEncoding();
$accept_language = $req->acceptLanguage();
// Exemplo:
// Valor do Cabeçalho 'Accept-Language' = 'ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4'
// Retorna:
// [
// ['value' => 'ru-RU', 'quality' => null],
// ['value' => 'ru', 'quality' => 0.8],
// ['value' => 'en-US', 'quality' => 0.6],
// ['value' => 'en', 'quality' => 0.4],
// ];
$accept_en = $req->acceptLanguage('en'); // true
$accept_de = $req->acceptLanguage('de'); // false
// Qualquer cabeçalho pode ser lido ao utilizar a função [header()]:
$content_type = $req->header('Content-Type');
$user_agent = $req->header('User-Agent');
// Chaves de Cabeçalho ignoram diferenciação de maiúsculas e minúsculas, então
// todas as seguintes retornam o mesmo valor:
$content_type = $req->header('content-type');
$content_type = $req->header('CONTENT-TYPE');
$content_type = $req->header('Content-Type');
// Todos os cabeçalhos pode ser lidos à partir da função [headers()]:
$headers = $req->headers();
Objeto HTTP Request - Campos de Cabeçalho de Proxy
// Cria o Objeto da Request
$req = new \FastSitePHP\Web\Request();
// Cabeçalhos da Request de Proxy são usados por campos chave como IP do
// cliente quando um servidor web está atrás de um servidor "proxy" em
// uma rede local, por exemplo um balanceador de carga. Ler os valores
// corretamente é importante para segurança, entretanto, em geral com qualquer
// linguagem de programação ou framework, ler cabeçalhos de proxy é difícil
// requer configuração extra. O FastSitePHP torna essa tarefa fácil sem a
// necessidade de configuração.
// Por exemplo, simplesmente ler o IP do cliente da requisição pode ser
// feito lendo o valor de REMOTE_ADDR.
$client_ip = $_SERVER['REMOTE_ADDR'];
// Se o balanceador de carga estiver configurado para fornecer o IP do
// Cliente, isso será normalmente um dos seguintes cabeçalhos de requisição:
// [X-Forwarded-For, Client-Ip ou Forwarded]. Entretanto, desde que o usuário
// final possa enviar dados com o cabeçalho de requisição, isso deve ser
// lido corretamente. O cabeçalho padronizado [Forwarded] tem um formato
// como este:
// 'for=192.0.2.43, for="[2001:db8:cafe::17]";proto=http;by=203.0.113.43'
// Enquanto cabeçalhos não padronizados mas amplamente utilizados tal como
// [X-Forwarded-For], utilizam este formato:
// 'client-ip1, client-ip2, proxy1, proxy2'
// O FastSitePHP lida com ambos os formatos.
// Por exemplo, assumamos que o balanceador de carga esteja em '10.0.0.1',
// '10.0.0.2' é utilizado para filtragem adicional de conteúdo e
// [X-Forwarded-For] entrou com o seguinte valor:
// [REMOTE_ADDR] = '10.0.0.1'
// [X-Forwarded-For] = "' OR '1'='1 --, 127.0.0.1, 54.231.1.5, 10.0.0.2"
// Neste exemplo, o seguinte foi enviado:
// - Client - A SQL Injection String of "' OR '1'='1 --"
// - Client - A localhost IP [127.0.0.1]
// - Client - Actual IP [54.231.1.5]
// - Server - 10.0.0.2
// Ao simplesmente ler o IP do cliente sem parâmetros, o IP do balanceador
// de carga é retornado, que para esta exemplificação é '10.0.0.1'.
$client_ip = $req->clientIp();
// Então ao utilizar a configuração padrão 'from proxy', o correto IP do
// usuário é retornado '54.231.1.5' is returned. Se nenhum servidor de proxy
// for utilizado, então é seguro chamar as configurações padrão de
// 'from proxy'.
$user_ip = $req->clientIp('from proxy');
// Ao utilizar proxies, um segundo parâmetro opcional de [$trusted_proxies]
// está disponível. Este tem sua string definida por padrão como 'trust
// local', entretanto um array de um IP específico ou de faixas de IP
// (format CIDR) pode ser utilizado para uma filtragem mais específica. Além
// disso o primeiro parâmetro [$option], pode também ser modificado para ler
// de Cabeçalhos de Requisição diferentes.
$user_ip = $req->clientIp('from proxy', 'trust local');
// Além do IP de Cliente, valores de proxy também podem ser lidos para
// [Protocol, Host, and Port]:
$portocal = $req->protocol('from proxy'); // 'http' or 'https'
$host = $req->host('from proxy');
$port = $req->port('from proxy');
Objeto Request - Informação do Servidor
// O Objeto Request pode retornar o IP do Servidor e tem uma função auxiliar
// [isLocal()] que retorna true somente se ambos, o cliente requerente e o servidor,
// estiverem no localhost ['127.0.0.1' ou '::1']. Em certas apps você pode
// querer ativar certas funcionalidades para desenvolvimento ou operação
// local e estas funções ajudam nisso.
$req = new \FastSitePHP\Web\Request();
$server_ip = $req->serverIp();
$is_local = $req->isLocal();
// NOTA - o IP do servidor web é frequentemente diferente do verdadeiro IP
// da rede. Para obter o IP da rede (localização do servidor), utilize o
// Objeto Networking Config como alternativa:
$config = new \FastSitePHP\Net\Config();
$net_ip = $config->networkIp();
Resposta - Conteúdo, Códigos de Status, Cabeçalhos, Cookies e Arquivos
// Por padrão, quando uma string é retornada em uma rota, o servidor retorna
// uma resposta HTML. Sem criar um Objeto Response, o Objeto Application
// pode ser utilizado para especificar um cabeçalho 'Content-Type' diferente
// que é o que os Navegadores e Clientes HTTP utilizam para determinar como
// lidar com a resposta.
$app->get('/app-text-response', function() use ($app) {
$app->header('Content-Type', 'text/plain');
return 'Resposta utilizando o Objeto Application';
});
// Ao utilizar o Objeto Response [contentType()] e [content()] são as
// principais funções para especificar diferentes tipos de conteúdo.
$app->get('/text-response', function() {
$res = new \FastSitePHP\Web\Response();
return $res->contentType('text')->content('Resposta em Texto');
});
// Ao utilizar o Objeto Response, propriedades são definidas através de
// funções getter/setter e são encadeáveis para que possam ser utilizadas
// em uma linha como mostrado acima ou separadas em múltiplas linhas como
// é mostrado aqui.
$app->get('/text-response2', function() {
return (new \FastSitePHP\Web\Response())
->contentType('text')
->content('Resposta em Texto 2');
});
// Utilizando o Objeto Response
$res = new \FastSitePHP\Web\Response();
// Defina o Cabeçalho 'Content-Type'.
// Todas as seguintes 3 chamadas de função, definem o mesmo valor. A
// diferença é que [contentType()] é uma função auxiliar que permite
// valores abreviados de [html, json, jsonp, text, css, javascript, xml].
$res->contentType('text');
$res->contentType('text/plain');
$res->header('Content-Type', 'text/plain');
// Definir Conteúdo
// Para a maioria dos tipos de conteúdo, utilize uma string ao definir [content()].
$res->content('<h1>FastSitePHP</h1>');
// Para Conteúdo JSON ambos, Objetos e Arrays, são utilizados
$object = [
'título' => 'Demonstração',
'número' => '123',
];
$res
->contentType('json')
->content($object);
// A função auxiliar [json()] define ambos, [contentType()] e [content()]
$res->json($object);
// Para JSON formatado, defina a opções [JSON_PRETTY_PRINT] antes de enviar
// a resposta. POr padrão [JSON_UNESCAPED_UNICODE] é utilizada e o JSON é
// minificado. Qualquer constante utilizada por [json_encode()] pode ser
// definida aqui.
$app->json_options = (JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
$res->jsonOptions(JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
// Códigos de Status
// [$app] somente suporta [200, 201, 202, 204, 205, 404 e 500] e o Objeto
// Response permite e trata respostas 304 juntamente com qualquer outro
// código de status válido ou personalizado.
$app->statusCode(201);
$res->statusCode(500);
// Uma função auxiliar [pageNotFound()] existe no Objeto Aplicação que pode
// ser utilizada para enviar uma resposta 404 juntamente com a página 404
// padrão ou personalizada.
$app->get('/document/:name', function($name) use ($app) {
if ($name !== 'test') {
return $app->pageNotFound();
}
return 'Teste';
});
// Especifique um arquivo ou a resposta; o arquivo especificado será
// transmitido para o cliente e enviado de uma maneira eficiente para a
// memória, para que esta função seja chamada em arquivos muito grandes
// impactando minimamente o servidor.
$file_path = __FILE__;
$res->file($file_path);
// Incluir Mime-Type específico com Cabeçalhos para Armazenamento em Cache.
// Outro tópico nesta página cobre armazenamento em cache em mais detalhe.
$res->file($file_path, 'text', 'etag:md5', 'private');
// Exemplo de Uso de Arquivo
$app->get('/view-source-code', function() {
$file_path = __FILE__;
$res = new \FastSitePHP\Web\Response();
return $res->file($file_path, 'download');
});
// Converter o nome ou tipo de um arquivo para um mime-type.
//
// Extensões de arquivo que mapeiam para um tipo MIME com a função são:
// Texto: htm, html, txt, css, csv, md, markdown, jsx
// Imagem: jpg, jpeg, png, gif, webp, svg, ico
// Aplicação: js, json, xml, pdf, woff
// Vídeo: mp4, webm, ogv, flv
// Áudio: mp3, weba, ogg, m4a, aac
//
// Se um tipo de arquivo não estiver associado com um mime-type, então um
// tipo de arquivo de download 'application/octet-stream' será retornado.
$mime_type = $res->fileTypeToMimeType('video.mp4');
$mime_type = $res->fileTypeToMimeType('mp4');
// Definir Cabeçalhos de Resposta e Cookies
// Utilizando o Objeto Application
$app->header('X-API-Key', 'App_1234');
$app->cookie('X-API-Key', 'App_1234');
// Ou utilizando o Objeto Response
$res->header('X-API-Key', 'Res_1234');
$res->cookie('X-API-Key', 'Res_1234');
// Ao criar um Objeto Response o Objeto Aplicação pode ser passado e todas
// as definições do App de [statusCode(), cors(), noCache(), headers(),
// cookies() e [json_options] serão passadas para o Objeto Response.
$res = new \FastSitePHP\Web\Response($app);
Redirecionamentos HTTP
// Requisições HTTP pode ser redirecionadas utilizando o objeto App ou o
// Response.
// Ao utilizar o Objeto Ap e chamar [redirect()], o script PHP finaliza-se
// imediatamente, entretanto, quaisquer eventos definidos por [after()] serão
// chamados. Se seu site utiliza Server-side Unit Testing, você pode querer
// utilizar o objeto resposta que comporta-se como uma rota regular e não
// finaliza a execução do script.
// O usuário faz esta requisição
$app->get('/page1', function() use ($app) {
$app->redirect('page3');
});
// Ou o usuário faz esta requisição
$app->get('/page2', function() {
$res = new \FastSitePHP\Web\Response();
return $res->redirect('page3');
});
// O usuário verá então esta URL resposta
$app->get('/page3', function() {
return 'page3';
});
// O Código de Status de Resposta Padrão é [302 'Found'] (Temporary Redirect),
// e um segundo parâmetro opcional para ambos App e Response permite códigos
// de status de redirecionamento adicionais:
// 301 Moved Permanently
// 302 Found
// 303 See Other
// 307 Temporary Redirect
// 308 Permanent Redirect
$app->get('/old-page', function() use ($app) {
$app->redirect('new-page', 301);
});
Resposta - Cabeçalhos de Cache e Cache do Lado do Cliente
// Exemplos abaixo mostram como utilizar Cabeçalhos Response para controlar
// como um Navegador ou Cliente HTTP armazena uma Página ou Recurso em cache.
// Evitar que um Navegador ou Cliente Armazene um Arquivo ou Página em Cache.
// Ambos os Objetos, Application e Response, têm uma função [noCache()].
// Chamando essas funções enviará 3 Cabeçalhos Response para o cliente:
// Cache-Control: no-cache, no-store, must-revalidate
// Pragma: no-cache
// Expires: -1
$app->noCache();
$res = new \FastSitePHP\Web\Response();
$res->noCache();
// Se ao utilizar certos Cabeçalhos Response o Objeto Response enviará uma
// resposta 304 "Not Modified" dependendo dos cabeçalhos da requisição.
// Respostas 304 são utilizadas por Navegadores e outros Clientes pare
// reutilizar recursos previamente obtidos de suas cópias armazenadas em
// cache. Isto permite que o usuário veja recursos estáticos mais
// rapidamente e reduz a quantidade de tráfego enviado do servidor.
// Cabeçalho de resposta 'Cache-Control'. Este cabeçalho tem opções
// diferentes para informar clientes de como eles podem armazenar uma
// página em cache. Neste exemplo, somente usuários finais e não servidores
// proxy podem armazenar em cache a reposta e eles devem revalidar isso
// a cada vez.
$res->cacheControl('private, must-revalidate'); // privado, deve revalidar
// Cabeçalho de resposta 'Expires'. Este cabeçalho é utilizado para informar
// o cliente de por quanto tempo o conteúdo é valido, entretanto dependendo
// das opções de 'Cache-Control' este valor pode ser ignorado. Embora,
// definindo esse valor não aciona uma resposta 304 e cabe ao navegador ou
// cliente como lidar com isso.
$res->expires('+1 month'); // mais um mês
// Cabeçalho de Resposta 'ETag' (ETag é uma abreviação para Entity Tag). Uma
// ETag representa um valor para o conteúdo (geralmente utilizando uma Hash).
// Navegadores e Clientes enviarão um Cabeçalho de Requisição 'If-None-Match'
// com a versão que eles tem armazenada e se corresponder, então o Objeto
// Response enviará uma resposta 304 sem o conteúdo já que o navegador pode
// utilizar a cópia local.
$res->etag('hash:md5');
// A função [etag()] também aceita a própria hash ou uma função de fechamento.
$res->etag('0132456789abcdef');
$res->etag(function($content) {
return sha256($content);
});
// O segundo parâmetro opcional aceita as ETag do tipo 'strong' ou 'weak'.
// O padrão é 'weak' e este é o recomendado para evitar erros complexos de
// de armazenamento em cache. Se você precisa utilizar ETags 'strong',
// provavelmente você deveria fazer testes extra.
$res->etag('hash:sha256', 'weak');
// Cabeçalho de Resposta 'Last-Modified'. Se estiver definido e o cliente
// envia de volta um cabeçalho de requisição 'If-Modified-Since' que
// corresponde, então uma resposta 304 é enviada. Ao definir o valor
// utilize um Timestamp Unix ou uma String que pode ser analisada pela
// função PHP [strtotime()].
$res->lastModified('2019-01-01 13:01:30');
// Cabeçalho de Resposta 'Vary'. O cabeçalho de resposta 'Vary' pode ser
// utilizado para especificar regras para armazenamento HTTP em cache e
// também prover dicas de conteúdo para Google e outros Mecanismos de
// Busca.
$res->vary('User-Agent, Referer');
// Ao enviar um arquivo coo a resposta, você pode especificar parâmetros
// opcionais [$cache_type e $cache_control]. Cache Type tem 3 opções válidas
// mostradas abaixo e Cache Control defini a função [cacheControl()].
$file_path = __FILE__;
$content_type = 'text'; // texto
$res->file($file_path, $content_type, 'etag:md5');
$res->file($file_path, $content_type, 'etag:sha1', 'private'); // privado
$res->file($file_path, $content_type, 'last-modified', 'public');// público
// Ao enviar etags com [file()] e utilizando uma das duas 'etag:md5' ou
// 'etag:sha1' a hash é calculada a cada vez. Se você utiliza ETags e tem
// arquivo grandes ou frequentemente acessados, isso seria uma boa ideia
// para salvar a hash quando o arquivo for criado pela primeira vez
// definí-la através da função [etag()].
$saved_hash = '0132456789abcdef';
$res->file($file_path)->etag($saved_hash);
Cross-Origin Resource Sharing (CORS) - Compartilhamento de recursos entre origens
// CORS é comumente utilizado em APIs web para compartilhar dados de um site
// ou domínio com outro domínio (recursos entre origens). Para incluir o
// cabeçalho 'Access-Control-Allow-Origin' em sua resposta, utilize a função
// [cors()]. Primeiro, certifique-se de definir os cabeçalhos CORS à partir
// do Objeto do App.
$app->cors('*');
// Se você estiver utilizando o Objeto Response você pode passar o Objeto App para a
// resposta em sua criação ou para sua função [cors()].
$res = new \FastSitePHP\Web\Response($app);
$res->cors($app);
// Ao passar uma string o 'Access-Control-Allow-Origin' é validado e definido,
// entretanto se você precisar passar CORS adicionais, utilize um array com
// cabeçalhos nomeados.
$app->cors([
'Access-Control-Allow-Origin' => 'https://www.example.com',
'Access-Control-Allow-Headers' => 'Authorization, Content-Type',
'Access-Control-Allow-Credentials' => 'true',
'Access-Control-Max-Age' => 86400,
]);
// Se estiver chamando um POST, PUT, DELETE ou outro Método de Requisição
// você provavelmente precisa tratar requisições OPTIONS. Ao utilizar CORS e
// uma requisição OPTIONS é processada, FastSItePHP definirá automaticamente
// o cabeçalho 'Access-Control-Allow-Methods' baseando-se em como rotas são
// definidas.
// Para ter certeza que requisições OPTIONS sejam tratadas, primeiro crie
// uma função que defina o valor CORS.
$cors = function () use ($app) {
$app->cors('*');
};
// Atribua a Função Filtro para as rotas que utilizam CORS:
$app->post('/api-data', function() {
return [ 'exemplo' => 'POST' ];
})
->filter($cors);
$app->put('/api-data', function() {
return [ 'exemplo' => 'PUT' ];
})
->filter($cors);
// Se você não quer permitir que o FastSitePHP manipule requisições OPTIONS,
// você pode desativar isso utilizando esta opção:
$app->allow_options_requests = false;
Cookies Seguros
// O FastSitePHP permite fácil manipulação de Cookies Seguros (Encrypted,
// Signed ou JWT). Para utilizar, gere uma chave segura e salve-a com os
// valores de configuração da app. Para mais sobre configuração e definições
// de criptografia, veja outros documentos neste site. Chaves robustas são
// importantes para segurança e são requeridas por padrão.
// $app->config['ENCRYPTION_KEY'] = 'eada343fc415625494bfd1b065ba...';
// $app->config['SIGNING_KEY'] = 'ab2403a36467b59b20cc314bb211e18...';
// $app->config['JWT_KEY'] = 'fkeVxeElykoCBzRTIUjxwTD9MIg71nXxOEQ...';
// O objeto Request tem três funções que utilizam as chaves de configuração
// para ler e verificar os cookies seguros. Se os cookies não existirem,
// forem inválidos, estiverem expirados etc [null] será retornado.
$req = new \FastSitePHP\Web\Request();
$decrypted = $req->decryptedCookie('encrypted');
$verified = $req->verifiedCookie('signed');
$jwt = $req->jwtCookie('jwt');
// Dados criptografados e assinados podem ser de qualquer tipo básico
// [Strings, Números, Objetos etc], enquanto while JWT requer um Objeto ou
// um Array/Dicionário.
$text = 'Momento da Requisição: ' . date(DATE_RFC2822);
$user = new \stdClass;
$user->id = 123;
$user->name = 'Admin';
$user->role = 'Admin';
// Para enviar com a Response, passe os dados para o método de resposta
// correspondente. Um terceiro parâmetro opcional de expiração exite para
// ambas [signedCookie()] e [jwtCookie()], que tem como valor padrão 1 hora.
// Isto aplica-se para os dados assinados ou JWT e não para o cookie.
$res = new \FastSitePHP\Web\Response();
$res->encryptedCookie('encrypted', $text);
$res->signedCookie('signed', $user, '+20 minutes');
$res->jwtCookie('jwt', $user, '+20 minutes');
Conecte a um Banco de Dados e rode Consultas SQL
// O FastSitePHP fornece um classe Database que é uma fina camada que
// envolve o PDO, reduzindo a quantidade de código necessária ao consultar
// um banco de dados. Um exemplo adicional nesta página, mostra como
// utilizar PDO.
// Conecte a um Bando de Dados. Este exemplo utiliza SQLite com um bd
// temporário na memória.
$dsn = 'sqlite::memory:';
$db = new \FastSitePHP\Data\Database($dsn);
// Dependendo da conexão, quatro parâmetros adicionais podem também serem
// utilizados:
/*
$user = null;
$password = null;
$persistent = false;
$options = [];
$db = new Database($dsn, $user, $password, $persistent, $options);
*/
// Cria tabelas e registros de teste. A função [execute()] é utilizada para
// consulta de ação (INSERT, UPDATE, DELETE, CREATE etc) e retorna o número
// de linhas afetadas.
$db->execute('CREATE TABLE page_types (id INTEGER PRIMARY KEY, page_type)');
$sql = 'CREATE TABLE pages (id INTEGER PRIMARY KEY AUTOINCREMENT,';
$sql .= ' type_id, title, content)';
$db->execute($sql);
// Este exemplo utiliza áspas duplas para a string ["] por que strings SQL
// incluem o caractere áspas simples ['] para texto.
$sql = "INSERT INTO page_types (id, page_type) VALUES (1, 'text/plain')";
$rows_added = $db->execute($sql);
// Um segundo parâmetro opcional pode ser utilizado. Isto é recomendado
// para prevenir ataques de SQL Injection via entradas de usuário. O ponto
// de interrogação [?] é um caractere que representa um espaço reservado
// a ser utilizado pela expressão SQL.
$sql = 'INSERT INTO page_types (id, page_type) VALUES (?, ?)';
$params = [2, 'text/html'];
$rows_added += $db->execute($sql, $params);
// Múltiplos registros pode ser adicionados (ou atualizados etc) ao
// utilizar [executeMany()]
$sql = 'INSERT INTO pages (type_id, title, content) VALUES (?, ?, ?)';
$records = [
[1, 'Página de Teste em Texto', 'Isto é um teste.'],
[2, 'Página de Teste em HTML', '<h1>Teste<h1><p>Isto é um teste.</p>'],
];
$rows_added += $db->executeMany($sql, $records);
// Além de utilizar [?], você também pode utilizar parâmetros nomeados no
// formato ":name". Parâmetros nomeados pode fazer com que o código seja
// mais fácil de ler.
$sql = 'INSERT INTO pages (type_id, title, content)';
$sql .= ' VALUES (:type_id, :title, :content)';
$params = [
'type_id' => 1,
'title' => 'Parâmetros Nomeados',
'content' => 'Teste com Parâmetros Nomeados.',
];
$rows_added += $db->execute($sql, $params);
// Obtenha a ID da última linha ou valor sequencial inserido
$last_id = $db->lastInsertId();
// Consulte Múltiplos Registros
// Retorna um Array de Registros (Array Associativo para cada Registro).
$sql = 'SELECT * FROM pages';
$records = $db->query($sql);
// Consulta um registro. Retorna um Array Associativo ou [null] se não
// encontrado. Ambas [query()] e [queryOne()] suportam parâmetros opcionais
// ao consultar.
$sql = 'SELECT * FROM pages WHERE id = ?';
$params = [1];
$record = $db->queryOne($sql, $params);
// A classe [Database] também contém funções adicionais tal como
// [queryValue(), queryList() e querySets()] para simplificar e reduzir a
// quantidade de código necessária ao trabalhar com bancos de dados.
Conecte a um Banco de Dados e rode Consultas SQL utilizando PDO
// Conecte a um Banco de Dados utilizando PHP Data Objects (PDO). Este
// exemplo utiliza SQLite com um bd temporário em memória.
$dsn = 'sqlite::memory:';
$user = null;
$password = null;
$options = [
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
];
$pdo = new \PDO($dsn, $user, $password, $options);
// Crie tabelas e registros test.
$pdo->query('CREATE TABLE page_types (id INTEGER PRIMARY KEY, page_type)');
$sql = 'CREATE TABLE pages (id INTEGER PRIMARY KEY AUTOINCREMENT,';
$sql .= ' type_id, title, content)';
$pdo->query($sql);
// Este exemplo utiliza áspas duplas para a string ["] por que strings SQL
// incluem o caractere áspas simples ['] para texto.
$sql = "INSERT INTO page_types (id, page_type) VALUES (1, 'text/plain')";
$stmt = $pdo->query($sql);
$rows_added = $stmt->rowCount();
// Este exemplo utiliza um prepared statement com um array de parâmetros.
// Isto é recomendado quando houver uma entrada por usuário para prevenir
// ataques de SQL Injection. O ponto e interrogação [?] é um caractere que
// representa um espaço reservado a ser utilizado na expressão SQL.
$sql = 'INSERT INTO page_types (id, page_type) VALUES (?, ?)';
$params = [2, 'text/html'];
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
$rows_added += $stmt->rowCount();
// Múltiplos registros podem ser adicionados (ou atualizados etc) em um loop
// utilizando um prepared statement.
$sql = 'INSERT INTO pages (type_id, title, content) VALUES (?, ?, ?)';
$records = [
[1, 'Página de Teste em Texto', 'Isto é um teste.'],
[2, 'Página de Teste em HTML', '<h1>Teste<h1><p>Isto é um teste.</p>'],
];
$stmt = $pdo->prepare($sql);
foreach ($records as $record) {
$stmt->execute($record);
$rows_added += $stmt->rowCount();
}
// Além de utilizar [?], você também pode utilizar parâmetros nomeados no
// formato ":name". Parâmetros nomeados pode fazer com que o código seja
// mais fácil de ler.
$sql = 'INSERT INTO pages (type_id, title, content)';
$sql .= ' VALUES (:type_id, :title, :content)';
$params = [
'type_id' => 1,
'title' => 'Parâmetros Nomeados',
'content' => 'Teste com Parâmetros Nomeados.',
];
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
$rows_added += $stmt->rowCount();
// Obtenha a ID da última linha ou valor sequencial inserido
$last_id = $pdo->lastInsertId();
// Consulte Múltiplos Registros
// Retorna um Array de Registros (Array Associativo para cada Registro).
$sql = 'SELECT * FROM pages';
$stmt = $pdo->query($sql);
$records = $stmt->fetchAll(\PDO::FETCH_ASSOC);
// Consulta um registro utilizando parâmetros. Retorna um Array Associativo
// ou [false] se não for encontrado.
$sql = 'SELECT * FROM pages WHERE id = ?';
$params = [1];
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
$record = $stmt->fetch(\PDO::FETCH_ASSOC);
// As funções [fetchAll()] e [fetch()] também suportam um número de
// opções para o valor retornado incluindo Indexed-Arrays utilizando
// [PDO::FETCH_NUM], Objetos Anônimos utilizando [PDO::FETCH_OBJ] e
// classes personalizadas utilizando [PDO::FETCH_CLASS].
COnectar a um Banco de Dados
// A classe Database do FastSitePHP ou a classe PHP integrada PDO,
// pode conectar a bancos de dados diferentes. A classe Database do
// FastSitePHP fornece um classe Database que é uma fina camada que
// envolve o PDO, reduzindo a quantidade de código necessária ao consultar
// um banco de dados.
// O exemplos abaixo mostram coo construir strings de conexão e rodar
// uma query para um número diferente bancos de dados. Se você baixar
// este site, o código abaixo pode ser modificado e testado para seu
// ambiente; or simplesmente copie o que você precisa para seu site
// ou app.
// Ao especificar o hostname (Nome do Server), muitas vezes você pode
// somente especificar o nome do servidor (exemplo: 'db-server') ou
// o nome de domínio totalmente qualificado (FQDN) (example
// 'db-server.example.com') baseado-se em como sua rede é configurada.
// Por exemplo em uma rede interna, simplesmente utilizando o nome
// de servidor funcionará, mas através de uma VPN é geralmente
// necessário utilizar o FDQN.
// ----------------------------------------------------------------------------
// MySQL
// Format Básico:
// "mysql:host={hostname};dbname={database}";
//
// Este exemplo também mostra o uso da opção [MYSQL_ATTR_INIT_COMMAND]
// para definir o fuso horário para UTC quando a conexão é criada.
//
// Se você tem um site ou aplicação que tem usuários em múltiplos
// fuso horários ou países, um modelo de aplicação que funciona bem
// é o de salvar todas as datas e horários em UTC e daí formatar
// baseando-se no fuso horário selecionado pelo usuário.
//
$dsn = 'mysql:host=localhost;dbname=wordpress;charset=utf8';
$user = 'root';
$password = 'wordpress';
$options = [
\PDO::MYSQL_ATTR_INIT_COMMAND => "SET time_zone = '+00:00'",
];
$sql = 'SELECT table_schema, table_name';
$sql .= ' FROM information_schema.tables';
$sql .= " WHERE table_type = 'BASE TABLE'";
// ----------------------------------------------------------------------------
// Oracle
// Formato:
// "oci:dbname=//{hostname}:{port-number}/{database}"
$dsn = 'oci:dbname=//server:1521/hr';
$user = 'sys';
$password = 'password';
$options = [];
$sql = 'SELECT OWNER, TABLE_NAME FROM ALL_TABLES ORDER BY OWNER, TABLE_NAME';
// Além do formato padrão, você pode também especificar uma string TNS
// completa
$tns = '(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)';
$tns .= '(HOST=server.example.com)(PORT=1521)))';
$tns .= '(CONNECT_DATA=(SERVICE_NAME=dbname)))';
$dsn = 'oci:dbname=' . $tns;
// ----------------------------------------------------------------------------
// SQL Server
$dsn = 'sqlsrv:Server=db-server;Database=DbName';
$user = 'sa';
$password = 'password';
$options = [];
$sql = 'SELECT SCHEMA_NAME(schema_id) AS schema_name, name FROM sys.tables';
// SQL Server (utilizando ODBC)
// Se o driver PDO nativo de SQL Server não estiver instalado e o
// Driver PDO para ODBC estiver e a Conexão ODBC estiver definida,
// você poderia utilizar isso:
$dsn = 'odbc:DRIVER={SQL Server};SERVER=db-server;DATABASE=DbName;';
// ----------------------------------------------------------------------------
// IBM (utilizando ODBC)
// Este exemplo mostra uma conexão a um IBM DB2 ou AS/400 através do
// iSeries.
// Opções ODBC variarão com base no driver instalado ou utilizado.
$dsn = 'odbc:DRIVER={iSeries Access ODBC Driver};';
$dsn .= 'HOSTNAME=AS400.EXAMPLE.COM;';
$dsn .= 'PORT=56789;';
$dsn .= 'SYSTEM=SYSTEM;';
$dsn .= 'PROTOCOL=TCPIP;';
$dsn .= 'UID=USER;';
$dsn .= 'PWD=PASSWORD;';
$user = null;
$password = null;
$options = [];
$sql = 'SELECT SYSTEM_TABLE_SCHEMA, TABLE_NAME, TABLE_TEXT';
$sql .= ' FROM QSYS2.SYSTABLES';
$sql .= " WHERE SYSTEM_TABLE_SCHEMA IN 'QSYS'";
$sql .= ' ORDER BY SYSTEM_TABLE_SCHEMA, TABLE_NAME';
$sql .= ' FETCH FIRST 100 ROWS ONLY';
// ----------------------------------------------------------------------------
// PostgreSQL
$dsn = 'pgsql:host=localhost;port=5432;dbname=dbname;';
$user = 'postgres';
$password = 'password';
$options = [];
$sql = 'SELECT table_schema, table_name';
$sql .= ' FROM information_schema.tables';
$sql .= " WHERE table_type = 'BASE TABLE'";
// ----------------------------------------------------------------------------
// SQLite
// Exemplo utilizando um caminho de arquivo:
// 'sqlite:/var/www/app_data/db.sqlite'
// 'sqlite:C:\inetpub\wwwroot\db.sqlite'
// Banco de Dados em Memória:
// 'sqlite::memory:'
$dsn = 'sqlite:' . $file_path;
$user = null;
$password = null;
$options = [];
$sql = 'SELECT * FROM sqlite_master';
// ----------------------------------------------------------------------------
// Opção e Conexão Persistente
//
// Muitos drivers de Bancos de Dados PHP suportam conexões persistentes
// o que permite um melhor desempenho.
$persistent = false;
// ============================================================================
// Conecte utilizando PHP Data Objects (PDO)
$options[\PDO::ATTR_ERRMODE] = \PDO::ERRMODE_EXCEPTION;
if ($persistent) {
$options[\PDO::ATTR_PERSISTENT] = true;
}
$pdo = new \PDO($dsn, $user, $password, $options);
// Consulte utilizando PDO
$stmt = $pdo->query($sql);
$records = $stmt->fetchAll(\PDO::FETCH_ASSOC);
// =================================================================================
// Conecte e Consulte utilizando a classe Database do FastSitePHP.
// Somente o DSN (Data Source Name/Nome da Fonte de Dados) é um parâmetro necessário.
$db = new \FastSitePHP\Data\Database($dsn, $user, $password, $persistent, $options);
$records = $db->query($sql);
// =================================================================================
// Além da classe Database do FastSitePHP, [OdbcDatabase] e [Db2Database] também
// podem ser utilizadas para suportar ambientes, e especialmente Bancos de Dados IBM.
//
// Ao utilizar a classe [OdbcDatabase] o DSN será o mesmo que o do PDO excluindo
// o prefixo 'odbc:'.
/*
$odbc = new OdbcDatabase($dsn, $user, $password, $persistent, $options);
$db2 = new Db2Database($dsn, $user, $password, $persistent, $options);
*/
// ============================================================================
// Lazy Loading com FastSitePHP
//
// O objeto Application do FastSitePHP tem uma função [lazyLoad()] que aceita
// um nome de propriedade e função callback. Isso cria o objeto como uma
// propriedade da app somente se utilizada. Isto é ideal para trabalhar com
// sites onde algumas páginas conectam a um banco de dados e algumas não, ou
// se você tem um site que conecta-se à múltiplos bacos de dados mas nem todas
// as páginas utilizam à cada um.
$app->lazyLoad('db', function() use ($dsn, $user, $password) {
return new \FastSitePHP\Data\Database($dsn, $user, $password);
});
// Consulta para registros. O banco de dados é conectado aqui somente quando usado pela primeira vez.
$records = $app->db->query($sql);
// ============================================================================
// Para obter uma lista dos drivers disponíveis no computador chame
// [phpinfo()] e veja o resultado ou chame a seguinte função para obter uma
// array de nomes de drivers. Uma lista completa de drivers PDO pode ser
// encontrada em:
// http://php.net/manual/en/pdo.drivers.php
// Se você precisar de um driver que não estiver disponível ou ativado em
// seu servidor, eles geralmente são fáceis de serem instalados e ativados.
$drivers = \PDO::getAvailableDrivers();
Valiando Entradas de Usuário
// Para muitos apps validação client side (webpage ou app) fornece retorno
// imediato para usuários e limita a necessidade de requisição web extra,
// porém usuários podem iludir a validação utilizando DevTools ou outros
// métodos, então para os dados que precisam ser validados utilizar
// validação server-side é importante.
// O FastSitePHP provê uma classe que permite que várias regras sejam
// facilmente definidas e rodem contra um objeto (ou Array
// Associativo/Dicionário).
// Regras comuns podem ser copiadas de forma simples de controles Input HTML.
// HTML Exemplo:
/*
<input name="nome" title="Nome" required>
<input name="idade" title="Idade" required min="13" max="99">
<input name="telefone" title="Telefone" pattern="[0-9]{3}-[0-9]{3}-[0-9]{4}">
*/
// O Código do FastSitePHP Code para Validar Postagem de Formulário
// utilizando o HTML acima.
// Campos de Postagem de Formulários vem na array PHP Superglobal [$_POST]
// e isso pode ser simplesmente passado para a classe [Validator].
$v = new \FastSitePHP\Data\Validator();
$v->addRules([
// Campo, Título, Regras
['nome', 'Nome', 'required'],
['idade', 'Idade', 'required min="13" max="99"'],
['telefone', 'Telefone', 'pattern="[0-9]{3}-[0-9]{3}-[0-9]{4}"'],
]);
list($errors, $fields) = $v->validate($_POST);
if ($errors) {
// Lógica de Erros
// [$errors] retorna uma array de mensagens de erro para o usuário final
// [$fields] retorna uma array de campos únicos que tiveram um erro em
// conjunto com uma array de mensagens de erro para cada campo.
// Campos pode ser utilizados pelo app cliente para evidenciar campos de
// formulário, etc.
}
// Além da utilização de strings para as regras você pode também utilizar
// arrays. Isso pode conceder melhor desempenho se você tiver um site de
// alto tráfego, contudo, isso roda de forma muito rápida de qualquer forma.
$v = new \FastSitePHP\Data\Validator();
$v->addRules([
['nomes', 'Nome', ['required' => true]],
['idade', 'Idade', [
'required' => true,
'min' => '13',
'max' => '99',
]],
['telefone', 'Telefone', ['pattern' => '[0-9]{3}-[0-9]{3}-[0-9]{4}']],
]);
// A classe Validator suporta um número de regras HTML5 juntamente com
// algumas regras personalizadas:
// 'exists', 'required', 'type', 'minlength', 'maxlength',
// 'length', 'min', 'max', 'pattern', 'list',
// A regra [type] suporta vários tipos de dados HTML5, junto com muitos
// tipos de dados personalizados:
// 'text', 'password', 'tel', 'number', 'range', 'date',
// 'time', 'datetime', 'datetime-local', 'email', 'url',
// 'unicode-email', 'int', 'float', 'json', 'base64',
// 'base64url', 'xml', 'bool', 'timezone', 'ip', 'ipv4',
// 'ipv6', 'cidr', 'cidr-ipv4', 'cidr-ipv6',
// Além das regras padrão, regras personalizadas pode ser definidas
// utilizando funções callback que retornam true/false ou uma string de
// mensagem personalizada de erro
$v = new \FastSitePHP\Data\Validator();
$v
->addRules([
['site_user', 'Site User', 'check-user required'],
['site_password', 'Password', 'check-password required'],
])
->customRule('check-user', function($value) {
return ($value === 'admin');
})
->customRule('check-password', function($value) {
return ($value === 'secret' ? true : 'Senha Inválida');
});
list($errors, $fields) = $v->validate($_POST);
Utilizando o Cliente HTTP
// HttpClient pode ser utilizado para simplificar a comunicação com
// outros serviços web, APIs HTTP e funciona muito bem para chamar
// e retornar o resultado de serviços locais - por exemplo um serviço
// AI/ML (Artificial Intelligence / Machine Learning) escrito em
// Python com TensorFlow ou scikit-learn.
// Faça um requisição HTTP GET simples e verifique o resultado
$res = \FastSitePHP\Net\HttpClient::get($url);
if ($res->error) {
// Um erro seria retornado em uma eventual falha grave como tempo limite
// atingido ou um erro de certificado SSL. Uma resposta 404 ou 500 do
// servidor seria tratada verificando o [status_code].
$error = $res->error;
} else {
$status_code = $res->status_code; // 200, 404, 500 etc
$headers = $res->headers; // Array de Cabeçalhos de Resposta
$content = $res->content; // Conteúdo da Resposta como uma String - HTML, Texto etc
$info = $res->info; // Array de Informações como Estatísticas de Tempo
}
// Realize uma Requisição HTTP GET e leia o Resultado JSON. Se o Content-Type
// da Resposta for 'application/json' então [$res->json] conterá um array
// caso contrário, conterá null. Cabeçalhos de Requisição podem receber um
// parâmetro opcional.
$headers = [
'X-API-Key' => 'ab82050cf5907934fa1d0f6f66284642a01d1ba2280656870c',
'X-Custom-Header' => 'Teste',
];
$res_json = \FastSitePHP\Net\HttpClient::get($url, $headers);
$json = $res->json;
$text = $res->content;
// Envie uma Requisição HTTP POST como JSON e também como um Form.
// Dados podem ser um Array ou um Objeto e Cabeçalhos são opcionais.
$data = [
'text' => 'teste',
'num' => 123,
];
$res_post = \FastSitePHP\Net\HttpClient::postJson($url, $data, $headers);
$res_form = \FastSitePHP\Net\HttpClient::postForm($url, $data);
// Ao utilizar PHP 5.5 ou mais recente, 'multipart/form-data' Form Posts são
// suportados com a classe integrada [CURLFile]:
/*
$data = [
'field1' => 'teste',
'file' => new \CURLFile($file_path),
];
*/
// Salve o Conteúdo da Resposta como um Download de Arquivo
// Assim como [postJson ()] e [postForm ()] Request Headers são opcionais.
$res_file = \FastSitePHP\Net\HttpClient::downloadFile($url, $save_path, $headers);
$saved_path = $res_file->content;
// O código de demonstração acima mostra as quatro funções estáticas
// auxiliares [get(), postJson(), postForm() e downloadFile()]. Opções
// adicionais estão disponíveis quando utilizar a HttpClient como um
// objeto com o mesmo método [request()].
// Envie uma Requisição PUT com um arquivo como o Corpo de Requisição
$http = new \FastSitePHP\Net\HttpClient();
$res_put = $http->request($url, [
'method' => 'PUT',
'headers' => $headers,
'send_file' => $file_path,
]);
Serviço GraphQL utilizando HttpClient
// GraphQL é uma tecnologia popular para desenvolver APIs. Ela foi portada para
// muitas linguagens incluindo PHP, contudo, a implementação referencial, a versão
// mais comumente utilizada e também de alto desempenho é a GraphQL com NodeJS e
// Express. Esta rota pode ser copiada ou modificada para permitir utilizar
// GraphQL à partir do PHP utilizando qualquer serviço GraphQL no localhost ou
// de outra URL.
$app->route('/graphql', function() {
try {
$url = 'http://localhost:4000/graphql';
// Se um Cabeçalho de Requisição 'Authorization' foi enviado, então,
// passe-o para o Serviço GraphQL.
$req = new \FastSitePHP\Web\Request();
$auth = $req->header('Authorization');
$headers = ($auth === null ? null : ['Authorization' => $auth]);
// Submit GraphQL Request
if ($req->method() === 'GET') {
$url .= '?query=' . urlencode($req->queryString('query'));
$url .= '&variables=' . urlencode($req->queryString('variables'));
$url .= '&operationName=' . urlencode($req->queryString('operationName'));
$res = \FastSitePHP\Net\HttpClient::get($url, $headers);
} else {
$res = \FastSitePHP\Net\HttpClient::postJson(
$url,
$req->content(),
$headers
);
}
// Verifique a Resposta, um erro tipicamente ocorreria não para erros
// de dados, mas sim para erros HTTP (i.e.: Se o serviço estiver caído).
if ($res->error) {
throw new \Exception($res->error);
}
// Retorne Objeto para uma Resposta JSON
return $res->json;
} catch (\Exception $e) {
// Retorne erro inesperado como uma resposta 200 utilizando o formato
// de erro padrão usado pelo GraphQL.
return [
'errors' => [
['message' => $e->getMessage()]
],
];
}
})->filter(function() use ($app) {
// Utilize CORS para permitir que páginas web acessem este serviço de
// qualquer host (URL)
if (isset($_SERVER['HTTP_ORIGIN']) && $_SERVER['HTTP_ORIGIN'] !== 'null') {
$app->cors([
'Access-Control-Allow-Origin' => $_SERVER['HTTP_ORIGIN'],
'Access-Control-Allow-Headers' => 'Authorization, Content-Type',
'Access-Control-Allow-Credentials' => 'true',
]);
} else {
$app->cors('*');
}
});
Envia um E-mail via um Servidor SMTP
// Defina as Configurações de E-mail
$from = 'noreply@example.com';
$to = 'user.name@example.com';
$subject = 'E-mail de Teste de FastSitePHP em ' . date(DATE_RFC2822);
$body = '<h1>Título do E-mail</h1><p style="color:blue;">Isto é um teste.</p>';
// Cria um Objeto E-mail
$email = new \FastSitePHP\Net\Email($from, $to, $subject, $body);
// A Classe Email também tem várias definições adicionais e pode ser criada
// sem especificar quaisquer parâmetros. Ao definir os endereços de e-mail
// de [From] ou [Reply-To], um os seguintes formatos pode ser utilizado:
// String: 'Email Address'
// Array: ['Email', 'Name']
// E quando especificar para quem enviar o e-mail para qualquer um dos
// formatos, pode utilizar:
// String 'Endereço de E-mail'
// Array: ['E-mail', 'Nome']
// Array: ['Endereço de E-mail 1', 'Endereço de E-mail 2', '...']
/*
$email = new \FastSitePHP\Net\Email();
$email
->from(['noreply@example.com', 'No Reply'])
->replyTo('test@example.com')
->to(['email1@example.com', 'email2@example.com'])
->cc('email3@example.com')
->bcc('email4@example.com')
->priority('High')
->header('X-Transaction-ID', '123abc');
*/
// Arquivos anexos também são suportados:
//
// $email->attachFile($file_path);
// Servidores SMTP que suportam E-mails Unicode pode utilizar
// [allowUnicodeEmails(true)]. Quando utilizado, O Cliente SMTP envia uma
// opção SMTPUTF8 se o servidor suportá-la.
//
// $email->allowUnicodeEmails(true)->from('无回复@example.com');
// Configurações SMTP
$host = 'smtp.example.com';
$port = 25;
$auth_user = null;
$auth_pass = null;
// Cria Cliente SMTP e Envia E-mail.
// Uma vez que a variável para o Client SMTP não estiver mais em uso ou
// definida como null, então, um comando 'QUIT' é automaticamente enviado
// para o Servidor SMTP e a conexão é fechada.
$smtp = new \FastSitePHP\Net\SmtpClient($host, $port);
if ($auth_user !== null) {
$smtp->auth($auth_user, $auth_pass);
}
$smtp->send($email);
$smtp = null;
// Opções adicionais podem ser especificadas, em segundos, para timeout e
// para logging
$timeout = 2;
$debug_callback = function($message) {
echo '[' . date('H:i:s') . '] ' . trim($message) . "\n";
};
// A Classe [SmtpClient] também suporta uma API de fácil utilização para
// comunicar com Servidores SMTP. Neste exemplo Gmail é utilizado e diversos
// comandos são realizados. Mensagens são logadas para a função
// [$debug_callback].
$host = 'smtp.gmail.com';
$port = 587;
$smtp2 = new \FastSitePHP\Net\SmtpClient($host, $port, $timeout, $debug_callback);
$smtp2->help();
$smtp2->noop();
$smtp2->quit();
$smtp2->close();
// Um ou mais e-mails pode também ser enviados utilizando Valores de
// Configuração de App ou Variáveis de Ambiente do Sistema. Este tipo de
// configuração pode ser utilizada para prevenir que dados de autenticação
// sensíveis sejam salvos com o código lógico principal.
/*
$app->config['SMTP_HOST'] = $host;
$app->config['SMTP_PORT'] = $port;
$app->config['SMTP_TIMEOUT'] = $timeout;
$app->config['SMTP_USER'] = $auth_user;
$app->config['SMTP_PASSWORD'] = $auth_pass;
\FastSitePHP\Net\SmtpClient::sendEmails([$email]);
*/
Busque por Arquivos e Diretórios (Pastas)
// Crie um Objeto Search do Sistema de Arquivos
$search = new \FastSitePHP\FileSystem\Search();
// Para utilização básica, especifique um diretório raiz com o comando
// [dir()] e então chame [files()] ou [dirs()]. Um array the nomes correspondentes
// será retornado.
$files = $search->dir($dir_path)->files();
// Funções são encadeáveis então quebrá-las em uma por linha pode tornar o
// código mais fácil de ler.
$dirs = $search
->dir($dir_path)
->dirs();
// [all()] can be used to return both directories and files
list($dirs, $files) = $search->dir($dir_path)->all();
// URL lists can also be generated from matching files.
$url_root = 'http://www.example.com/';
$urls = $search
->dir($dir_path)
->urlFiles($url_root);
// Existem várias funções com critérios diferentes e podem ser utilizadas
// para filtrar os resultados. Neste exemplo uma busca recursiva é utilizada
// para encontrar arquivos PHP que contenham o texto 'FileSystem'. Quando
// uma busca recursiva é utilizada, o caminho completo dos arquivos é
// retornado a não ser que [includeRoot(false)] esteja definida.
// Veja a documentação e exemplos para todas as funções.
$files = $search
->dir($dir_path)
->recursive(true)
->fileTypes(['php'])
->includeText(['FileSystem'])
->files();
Converta Markdown para HTML utilizando PHP
// O FastSitePHP inclui a biblioteca de alto desempenho Parsedown para
// converter o formato Markdown para HTML.
// Certifique-se de carrear o autoloader do fornecedor
require '../../../vendor/autoload.php';
// Crie o Objeto Parsedown
$Parsedown = new Parsedown();
// Converta para HTML de uma String de Texto
$html = $Parsedown->text('Olá **FastSitePHP**!');
// Leia um Arquivo e converta para HTML
$file_path = __DIR__ . '/views/example.md';
$md = file_get_contents($file_path);
$html = $Parsedown->text($md);
Logging
// O FastSitePHP inclui duas classes de logging que implementam a amplamente
// utilizada Interface [Psr\Log].
// Cria um arquivo logger. Mensagens de log são adicionadas e o arquivo é
// criado quando a primeira mensagem é adicionada.
$file = __DIR__ . '/log.txt';
$file_logger = new \FastSitePHP\Data\Log\FileLogger($file);
// Crie um Logger HTML
// Esta classe pode ser utilizada para logs temporários de desenvolvimento
// porque isto gera uma tabela HTML das mensagens registradas depois que a
// resposta é enviada ou, dependendo das opções, pode ser utilizada para
// substituir a resposta original. O parâmetro [$replace_response] é opcional.
$replace_response = false;
$html_logger = new \FastSitePHP\Data\Log\HtmlLogger($app, $replace_response);
// Registre mensagens utilizando uma das seguintes funções:
// emergency(), alert(), critical(), error(),
// warning(), notice(), info(), debug()
$file_logger->info('Isto é um teste.');
$html_logger->error('Aplicação de Teste');
// Dados adicionais podem ser passados para a mensagem através de espaços
// reservados
$html_logger->info('Usuário {name} criado', [
'name' => 'Admin'
]);
// O formato de data pode ser qualquer valor válido para a função [date()] do PHP.
// O padrão é [\DateTime::ISO8601].
$file_logger->date_format = 'Y-m-d H:i:s';
// Para o arquivo de registro o formato gerado pode ser controlado pelas
// propriedades.
//
// Formato Padrão:
// '{date} {level} - {message}{line_break}';
//
// Quebras de Linha padrão baseando-se no Sistema Operacional (SO):
// "\r\n" - Windows
// "\n" - Outros SOs
$file_logger->log_format = '[{level}] {message}{line_break}';
$file_logger->line_break = '^^';
// Você pode também personalizar o HTML Logger com seu próprio modelo:
// $html_logger->template_file = 'SEU_MODELO.php';
Obtenha Informações de Rede e do Servidor
// Crie um Objeto de Configuração de Rede
$config = new \FastSitePHP\Net\Config();
// Obtenha um (fqdn) 'fully-qualified domain name' para o servidor ['servidor.example.com']
$host = $config->fqdn();
// Obtenha o endereço IPv4 da Rede para o computador ou servidor
$ip = $config->networkIp();
// Obtenha uma lista de todos os endereços IPv4 para o computador ou servidor
$ip_list = $config->networkIpList();
// Obtenha um string de texto de informações do servidor utilizando um
// dos seguintes comandos:
// - Linux / Unix = [ip addr] ou [ifconfig]
// - Mac = [ifconfig]
// - Windows = [ipconfig]
$info = $config->networkInfo();
// Converte a String de Informações de Rede em um Objeto
$info = $config->parseNetworkInfo($info);
Obtém Informações de Ambiente e Sistema
// Cria um Objeto do Sistema de Ambiente
$sys = new \FastSitePHP\Environment\System();
// Obtém um array de informações básicas relacionadas ao Sistema Operacional
// [ 'OS Type', 'Version Info', 'Release Version', 'Host Name', 'CPU Type' ]
$os_info = $sys->osVersionInfo();
// Obtém uma string de texto de informações detalhadas do sistema utilizando
// um dos seguintes comandos:
// - Linux = File: '/etc/os-release'
// - FreeBSD = uname -mrs
// - IBM AIX = uname -a
// - Mac = system_profiler SPSoftwareDataType SPHardwareDataType
// - Windows = ver
$info = $sys->systemInfo();
// Obtém um array de informações relacionado espaço livre, usado e total
// para um drive do sistema de arquivos ou partição do disco. Esta função
// permite que drives específicos ou partições sejam especificadas.
// - *nix = $sys->diskSpace('/dev/disk0')
// - Windows = $sys->diskSpace('C:')
$disk_space = $sys->diskSpace();
// Função somente de Windows que retorna um array de letras de unidades
// mapeadas para o servidor. Retorna um array vazio para outros SOs.
$mapped_drives = $sys->mappedDrives();
Utilize um arquivo [.env]
// Carrega variáveis de ambiente de um arquivo [.env] para dentro de
// [getenv()] e [$_ENV]. O FastSitePHP DotEnv é um porte do pacote Node
// [dotenv] então a mesma sintaxe utilizada por projetos Node é suportada.
$vars = \FastSitePHP\Environment\DotEnv::load($dir);
// Utilize variáveis de um arquivo depois de lê-lo. Variáveis são somente
// definidas de um arquivo se elas ainda não existirem.
$value = getenv('DB_CONNECTION');
$value = $_ENV['DB_CONNECTION'];
// Carregue um arquivo utilizando o formato [.env]. O caminho completo do
// arquivo é especificado de forma que possa receber qualquer nome.
$vars = \FastSitePHP\Environment\DotEnv::loadFile($file_path);
// Opcionalmente, exija que hajam chaves no arquivo.
$required_vars = ['DB_ORACLE', 'DB_SQL_SERVER'];
$vars = \FastSitePHP\Environment\DotEnv::load($dir, $required_vars);
Segurança - Criptografe e Descriptografe Dados
// Gere uma Chave para Criptografia.
// A chave é uma longa string hexadecimal de bytes aleatórios seguros.
// A chave seria tipicamente salva com seu app ou nas configurações.
$crypto = new \FastSitePHP\Security\Crypto\Encryption();
$key = $crypto->generateKey();
// Criptografe e Descriptografe utilizando a classe auxiliar Cypto com
// definições de configuração.
// Dados de diferentes tipos de dados pode ser criptografados e retornados
// no mesmo formato (string, int, objeto etc).
$app->config['ENCRYPTION_KEY'] = $key;
$encrypted_text = \FastSitePHP\Security\Crypto::encrypt($data);
$decrypted_data = \FastSitePHP\Security\Crypto::decrypt($encrypted_text);
// Criptografe e Descriptografe utilizando a classe Encryption. Esta classe
// fornece muitas opções adicionais que não estão na classe auxiliar.
$encrypted_text = $crypto->encrypt($data, $key);
$decrypted_data = $crypto->decrypt($encrypted_text, $key);
Segurança - Criptografe e Descriptografe um Arquivo
// O FastSitePHP permite uma autenticação de criptografia rápida de qualquer
// tamanho de arquivo(mesmo grandes arquivos que estão nos gigabytes de
// tamanho). O código utilizado para a criptografia é compatível com comandos
// de shell e um script Bash [encrypt.sh] que funciona em Computadores
// Linux e Unix. O script Bash pode ser baixado deste site e funcionará na
// maioria dos sistemas Linux sem que nada seja instalado.
// Gere uma Chave para Criptografia
$crypto = new \FastSitePHP\Security\Crypto\FileEncryption();
$key = $crypto->generateKey();
// Construa caminhos de arquivos para salvar, baseando-se no nome original
$enc_file = $file_path . '.enc';
$output_file = $enc_file . '.decrypted';
// Criptografe e Descriptografe utilizando a classe auxiliar Crypto com
// definições de configuração. Uma classe [FileEncryption] também existe com
// opções adicionais.
$app->config['ENCRYPTION_KEY'] = $key;
\FastSitePHP\Security\Crypto::encryptFile($file_path, $enc_file);
\FastSitePHP\Security\Crypto::decryptFile($enc_file, $output_file);
Segurança - Codifique e Decodifique um Token JSON Web (JWT)
// A carga do JWT pode ser um Objeto ou um Array (Dicionário).
$payload = [
'User' => 'John Doe',
'Roles' => ['Admin', 'SQL Editor']
];
// Gere um Chave para Codificação (Assinando).
// A chave é uma longa string hexadecimal de bytes aleatórios seguros.
// A chave seria tipicamente salva com seu app ou nas configurações.
$jwt = new \FastSitePHP\Security\Crypto\JWT();
$key = $jwt->generateKey();
// Codifique e Decodifique o JWT com a Classe Auxiliar Crypto e Definições
// de Configuração.
// Ao utilizar os parâmetros padrão com ao classe auxiliar, os dados tem
// validade de uma hora.
$app->config['JWT_KEY'] = $key;
$token = \FastSitePHP\Security\Crypto::encodeJWT($payload);
$data = \FastSitePHP\Security\Crypto::decodeJWT($token);
// Codifique (Assine) e Decodifique (Verifique) utilizando a classe JWT. Ao
// utilizar as definições padrão com a classe JWT, nenhuma expiração é
// especificada, todas as reivindicações são validadas e uma chave é
// necessária.
$token = $jwt->encode($payload, $key);
$data = $jwt->decode($token, $key);
// Adicione Reivindicações à Carga Válida e utilize uma Chave Insegura para
// Compatibilidade com ouros sits (Geralmente demonstrações online de JWT
// são mostradas utilizando senhas simples para a chave). Por padrão, chaves
// necessitam ser seguras, com comprimento apropriado e no formato Base64 ou
// Hexadecimal.
$payload = $jwt->addClaim($payload, 'exp', '+10 minutes');
$payload = $jwt->addClaim($payload, 'iss', 'example.com');
$jwt
->useInsecureKey(true)
->allowedIssuers(['example.com']);
$insecure_key = 'password123';
$token = $jwt->encode($payload, $insecure_key);
$data = $jwt->decode($token, $insecure_key);
Segurança - Codifique e Decodifique o JWT utilizado RSA
// A carga do JWT pode ser um Objeto ou um Array (Dicionário)
$payload = new \stdClass;
$payload->User = 'John Doe';
$payload->Roles = ['Admin', 'SQL Editor'];
// Crie uma Classe JWT, especifique o Algorítmo 'RS256 e gere um Par de Chaves
$jwt = new \FastSitePHP\Security\Crypto\JWT();
$jwt
->algo('RS256')
->allowedAlgos(['RS256']);
list($private_key, $public_key) = $jwt->generateKey();
// Encode (Sign) and Decode (Verify)
$token = $jwt->encode($payload, $private_key);
$data = $jwt->decode($token, $public_key);
Segurança - Sign and Verify Data
// Utilizar [SignedData] tem um conceito parecido ao de utilizar JWT.
// Um cliente pode ler os dados mas não modificá-los.
// Gere uma Chave para Assinar.
// A chave é uma longa string hexadecimal de bytes aleatórios seguros.
// A chave seria tipicamente salva com seu app ou nas configurações.
$csd = new \FastSitePHP\Security\Crypto\SignedData();
$key = $csd->generateKey();
// Assine e Verifique utilizando a Classe Auxiliar Cypto com Definições de
// Configuração. Ao utilizar os parâmetros padrão com a classe auxiliar, os
// dados expiram em uma hora. Dados para diferentes tipos de dados podem
// ser assinados e verificados em seu format original (string, int, object,
// etc).
$app->config['SIGNING_KEY'] = $key;
$signed_text = \FastSitePHP\Security\Crypto::sign($data);
$verified_data = \FastSitePHP\Security\Crypto::verify($signed_text);
// Assina e Verifica utilizando a Classe SignedData Class. A Classe
// SignedData permite opções adicionais e não utiliza definições de
// configuração. O parâmetro [$expire_time] é opcional.
$expire_time = '+20 minutes';
$signed_text = $csd->sign($data, $key, $expire_time);
$verified_data = $csd->verify($signed_text, $key);
Segurança - Hash e Verifique Senhas
// Salvando Senhas de Usuário utilizando uma função hash unidirecional é
// importante para segurar aplicações. A classe Password do FastSitePHP
// provê suporte para bcypt (padrão) e Argon2.
// Exemplo de uma Senha de Usuário. Este valor não deveria ser gravado em
// um banco de dados
$password = 'Password123';
// Crie um Objeto Password
$pw = new \FastSitePHP\Security\Password();
// Hash de Senha. Isto criará uma hash textual que parece que isso:
// '$2y$10$cDpu8TnONBhpBFPEKTTccu/mYhSppqNLDNCfOYLfBWI3K/FzFgC2y'
// O valor mudará toda vez e é seguro gravá-lo em um banco de dados.
$hash = $pw->hash($password);
// Verifique a Senha - retorna [true] ou [false]
$verified = $pw->verify($password, $hash);
// Cria uma senha aleatoriamente gerada que tem 12 caracteres de
// comprimento e contém o seguinte:
// 4 Letras Maiúsculas (A - Z)
// 4 Letras Minúsculas (a - z)
// 2 Dígitos (0 - 9)
// 2 Caracteres Especiais (~, !, @, #, $, %, ^, &, *, ?, -, _)
$strong_password = $pw->generate();
// Especifique um custo BCrypt de 12 ao invés do valor padrão 10
$pw->cost(12);
$hash2 = $pw->hash($password);
$verified2 = $pw->verify($password, $hash2);
// Ao utilizar PHP 7.2 ou mais recente, Argon2 pode ser utilizada
if (PHP_VERSION_ID >= 70200) {
$pw->algo('Argon2');
$argon_hash = $pw->hash($password);
$argon_verified = $pw->verify($password, $argon_hash);
}
Segurança - Gere um novo Par de Chaves RSA
// Gere um novo Par de Chaves RSA
$key_pair = \FastSitePHP\Security\Crypto\PublicKey::generateRsaKeyPair();
list($private_key, $public_key) = $key_pair;
// Gere uma nova chave RSA 3072-Bit
$bits = 3072;
$key_pair = \FastSitePHP\Security\Crypto\PublicKey::generateRsaKeyPair($bits);
list($private_key2, $public_key2) = $key_pair;
Gere uma string de bytes aleatórios
// Gere bytes pseudo-aleatórios criptograficamente seguros, adequados para
// uso criptográfico e aplicativos seguros.
$bytes = \FastSitePHP\Security\Crypto\Random::bytes(32);
// Converte os bytes para outro formato:
$hex_bytes = bin2hex($bytes);
$base64_bytes = base64_encode($bytes);
// Ao utilizar PHP 7 ou mais recente, você pode simplesmente chamar
// [random_bytes()]
$bytes = random_bytes(32);
Segurança - CSRF utilizando Session
// Uma chamada para um função estática cria um token em Requisições GET e
// valida isso com Requisições POST, PUT, DELETE etc. Se não há erro com o
// token, então um exceção é lançada, o que causará uma resposta 500 com a
// página de erro.
\FastSitePHP\Security\Web\CsrfSession::setup($app);
// O token recebe um valor locals no Objeto da Aplicação
$token = $app->locals['csrf_token'];
// Isto permite que seja utilizado com código de modelo. Tokens são
// validados à partir por [setup()] mas não automaticamente adicionado a
// formulários, então eles devem ser adicionados através de modelos ou por
// código.
//
// <meta name="X-CSRF-Token" content="{{ $csrf_token }}">
// <input name="X-CSRF-Token" value="{{ $csrf_token }}">
// Um bom lugar para chamar esta função é nos filtros de rota das páginas
// que utilizam autenticação. Exemplo:
// Crie uma função filtro para atribuir para múltiplas rotas
$csrf_session = function() use ($app) {
\FastSitePHP\Security\Web\CsrfSession::setup($app);
};
// Utilize a função quando definir uma rotaUse the function when defining a route
$app->get('/form', function() use ($app) {
return $app->render('form.php');
})
->filter($csrf_session);
Segurança - Stateless CSRF
// Tokens Stateless CSRF não são armazenados em Sessão, mas ao invés disso
// utilizam um código de autenticação de mensagem criptografada com hash
// (HMAC) para criar e verificar o token.
// Uma chave segura secreta é requerida.
// A chave seria tipicamente salva com seu app ou nas configurações.
$key = \FastSitePHP\Security\Web\CsrfStateless::generateKey();
// Para utilizar a Chave, essa deve ser salva em um valor de configuração ou
// em uma variável de ambiente antes de chamar [setup()].
$app->config['CSRF_KEY'] = $key;
// putenv("CSRF_KEY=${key}");
// Um identificador único para o usuário é também necessário. Isto não tem de
// ser um segredo e pode ser simplesmente um campo numérico em um banco de
// dados.
$user_id = 1;
// Configura e valida token stateless CSRF
\FastSitePHP\Security\Web\CsrfStateless::setup($app, $user_id);
// Opcionalmente adicione um tempo de expiração, este token CSRF expirará depois de 5 minutos
$expire_time = '+5 minutes';
\FastSitePHP\Security\Web\CsrfStateless::setup($app, $user_id, $expire_time);
// A mesma lógica é utilizada ao usar a classe [CsrfSession], então o token
// é atribuído um valor locals no Objeto da Aplicação permitindo que seja
// utilizado com código de modelo.
$token = $app->locals['csrf_token'];
//
// <meta name="X-CSRF-Token" content="{{ $csrf_token }}">
// <input name="X-CSRF-Token" value="{{ $csrf_token }}">
// Também da mesma forma que [CsrfSession] um bom lugar para chamar
// [setup()] é nas funções filtro de rota.
$csrf = function() use ($app, $user_id) {
\FastSitePHP\Security\Web\CsrfStateless::setup($app, $user_id);
};
$app->get('/form', function() use ($app) {
return $app->render('form.php');
})
->filter($csrf);
Endereços IP e Validações
// Com o FastSitePHP você pode facilmente comparar um endereço de IP a uma
// reconhecida faixa de IPs utilizando Notação CIDR. Notação CIDR
// (Classless Inter-Domain Routing) é uma representação compacta de endereços
// de IP e os prefixos de suas rotas associadas. Isto é utilizado regularmente
// ao trabalhar com redes digitais e frequentemente necessário para websites
// quando lidando com endereços de IP por segurança.
// Verifique se o endereço de IP '10.10.120.12' está na faixa '10.0.0.0/8'
// Retorna [true]
$matches = \FastSitePHP\Net\IP::cidr('10.0.0.0/8', '10.10.120.12');
// Check if IP Address '10.10.120.12' is in the '172.16.0.0/12' range
// Retorna [false]
$matches2 = \FastSitePHP\Net\IP::cidr('172.16.0.0/12', '10.10.120.12');
// IPv6 também é suportado
$matches3 = \FastSitePHP\Net\IP::cidr('fe80::/10', 'fe80::b091:1117:497a:9dc1');
// Obtém um array de Endereços de Rede Privados em Notação CIDR
// [
// '127.0.0.0/8', // IPv4 localhost
// '10.0.0.0/8', // IPv4 Private Network, RFC1918 24-bit block
// '172.16.0.0/12', // IPv4 Private Network, RFC1918 20-bit block
// '192.168.0.0/16', // IPv4 Private Network, RFC1918 16-bit block
// '169.254.0.0/16', // IPv4 local-link
// '::1/128', // IPv6 localhost
// 'fc00::/7', // IPv6 Unique local address (Private Network)
// 'fe80::/10', // IPv6 local-link
// ]
$private_addr = \FastSitePHP\Net\IP::privateNetworkAddresses();
// O array de [privateNetworkAddresses()] pode ser utilizado com a função
// [cidr()] para verificar se um endereço de IP é de uma rede privada ou de
// da internet pública. A função [cidr()] aceita o Parâmetro CIDR como um
// array ou uma string.
$matches4 = \FastSitePHP\Net\IP::cidr($private_addr, '10.10.120.12');
// Obtém informações sobre a sting CIDR ao chamar [cidr()] com somente 1
// parâmetro.
// Este exemplo retorna o seguinte:
// [
// 'CIDR_Notation' => '10.63.5.183/24',
// 'Address_Type' => 'IPv4',
// 'IP_Address' => '10.63.5.183',
// 'Subnet_Mask' => '255.255.255.0',
// 'Subnet_Mask_Bits' => 24,
// 'Cisco_Wildcard' => '0.0.0.255',
// 'Network_Address' => '10.63.5.0',
// 'Broadcast' => '10.63.5.255',
// 'Network_Range_First_IP' => '10.63.5.0',
// 'Network_Range_Last_IP' => '10.63.5.255',
// 'Usable_Range_First_IP' => '10.63.5.1',
// 'Usable_Range_Last_IP' => '10.63.5.254',
// 'Addresses_in_Network' => 256,
// 'Usable_Addresses_in_Network' => 254,
// ]
$info = \FastSitePHP\Net\IP::cidr('10.63.5.183/24');
// Exemplo de informações CIDR quando utiliza IPv6:
// [
// 'CIDR_Notation' => 'fe80::b091:1117:497a:9dc1/48',
// 'Address_Type' => 'IPv6',
// 'IP_Address' => 'fe80::b091:1117:497a:9dc1',
// 'Subnet_Mask' => 'ffff:ffff:ffff::',
// 'Subnet_Mask_Bits' => 48,
// 'Network_Address' => 'fe80::',
// 'Network_Range_First_IP' => 'fe80::',
// 'Network_Range_Last_IP' => 'fe80::ffff:ffff:ffff:ffff:ffff',
// 'Addresses_in_Network' => '1208925819614629174706176',
// ]
$info_ip6 = \FastSitePHP\Net\IP::cidr('fe80::b091:1117:497a:9dc1/48');
Segurança de Sistema de Arquivos
// A Classe FileSystem Security contém funções para validar arquivos.
// Previna ataques Path Traversal verificando se um nome de arquivo existe
// em um diretório específico. Ataque Path Transversal podem ocorrer se um
// usuário tem concedida a permissão de especificar um arquivo em um
// sistema de arquivos através e input e usa um padrão como '/../' para
// obter arquivos de outro diretório.
// Exemplos:
// Assuma que ambos os arquivos existem e retornariam [true] da função
// integrada [is_file()]. [false] seria retornado para o segundo arquivo
// ao utilizar [Security::dirContainsFile()].
$file1 = 'user_image.jpg';
$file2 = '../../index.php';
$file_exists_1 = \FastSitePHP\FileSystem\Security::dirContainsFile($dir, $file1);
$file_exists_2 = \FastSitePHP\FileSystem\Security::dirContainsFile($dir, $file2);
// A função [dirContainsFile()] só permite que arquivos diretamente sob a
// pasta raiz então outra função existe para procurar subdiretórios a
// [dirContainsPath()].
$path1 = 'icons/clipboard.svg'; // Retorna [true]
$path2 = '../../app/index.php'; // Retorna [false]
$path_exists_1 = \FastSitePHP\FileSystem\Security::dirContainsPath($dir, $path1);
$path_exists_2 = \FastSitePHP\FileSystem\Security::dirContainsPath($dir, $path2);
// [dirContainsPath()] contains an optional 3rd parameter [$type] which defaults
// to 'file' and allows for one of the following options ['file', 'dir', 'all'].
$path3 = 'icons';
$exists = \FastSitePHP\FileSystem\Security::dirContainsPath($dir, $path3, 'dir');
// [dirContainsDir()] pode ser utilizada para verificar diretórios/pastas.
$dir1 = 'icons';
$dir2 = '../../app';
$dir_exists_1 = \FastSitePHP\FileSystem\Security::dirContainsDir($dir, $file1);
$dir_exists_2 = \FastSitePHP\FileSystem\Security::dirContainsDir($dir, $file2);
// Valide Arquivos de Imagem
// A função [fileIsValidImage()] pode ser utilizada para verificar se
// arquivos de imagem criados de outro input de usuário, são válidos. Por
// exemplo um usuário malicioso pode tentar renomear um script PHP ou
// arquivo executável como se fosse uma imagem e enviá-lo para um site.
// Retorna [true] se um arquivo de imagem [jpg, gif, png, webp, svg] for
// válido e a extensão do arquivo corresponder ao tipo de imagem.
$is_image = \FastSitePHP\FileSystem\Security::fileIsValidImage($image_file);
Segurança - Limitação de Frequência
// Classe de Limitação de Frequência
$rate_limit = new \FastSitePHP\Security\Web\RateLimit();
// Utilizando a classe RateLimit requer uma instância de [\FastSitePHP\Data
// \KeyValue\StorageInterface].
// Neste exemplo SQLite é utilizado. Quando múltiplos servidores são
// usados atrás de um balanceador de carga, um bd de cache em memória como
// o Redis pode ser utilizado.
$file_path = sys_get_temp_dir() . '/ratelimit-cache.sqlite';
$storage = new \FastSitePHP\Data\KeyValue\SqliteStorage($file_path);
// Há duas opções obrigatórias [storage] e [id]. [id] representa o usuário -
// Endereço de IP, ID de Usuário etc.
//
// [max_allowed] e [duration] serão comumente utilizadas e representam a
// taxa na qual o evento é permitido. Se não especificado, então, um
// padrão de 1 é usado o qual permite 1 requisição por segundo.
$options = [
'max_allowed' => 1, // Requisições, Eventos etc
'duration' => 1, // Em segundos
'storage' => $storage,
'id' => $_SERVER['REMOTE_ADDR'],
];
// Verifique a Requisição
list($allowed, $headers) = $rate_limit->allow($options);
// $allowed = bool
// $headers = Array de cabeçalhos pode ser utilizado para lógica ou
// ou enviado com a resposta
// Uma coisa para estar ciente ao filtrar por IP é que vários usuários podem
// estar como o mesmo IP se eles estiverem acessando seu site de um mesmo
// escritório ou localização.
// Exemplos de opções:
// Limitar a 10 requisições a cada 20 segundos
$options = [ 'max_allowed' => 10, 'duration' => 20, ];
// Limitar a 2 requisições por minuto
$options = [ 'max_allowed' => 2, 'duration' => 60, ];
// Limitar a 2 requisições por dia
$options = [ 'max_allowed' => 10, 'duration' => (60 * 60 * 24), ];
// Se estiver utilizando a classe [RateLimit] para múltiplas utilizações,
// então, você precisa especificar uma chave opcional.
$options = [ 'key' => 'messages-sent' ];
$options = [ 'key' => 'accounts-created' ];
// A classe [RateLimit] permite diferentes algorítimos de limitação de
// taxa; o padrão é 'fixed-window-counter' o qual coloca uma quantidade
// fixa no número de requisições para a duração dada, mas permite rajadas.
// O 'token-bucket' permite limitar a taxa por uma taxa
// cronometrada, entretanto, isso pode permitir um número maior de requisições
// do que o especificado [max_allowed].
//
// Para utilização básica com um número pequeno de [max_allowed] tal como
// "1 requisição por segundo", ele comportarão-se da mesma forma, no
// entanto, se especificar um número maior como "10 requisições por 20
// segundos", então, haverá um diferença, assim se você estiver utilizando
// limitação de taxa para requisições web com um número grande você
// pode querer comparar as diferenças utilizando código exemplo e ver links
// relacionados nos documentos da API.
//
$options = [ 'algo' => 'fixed-window-counter' ];
$options = [ 'algo' => 'token-bucket' ];
// A função [filterRequest()] pode ser utilizada para filtrar a requisição.
// Ao ser utilizada, se a limitação de taxa do usuário é atingida,
// então, uma resposta 409 [Too Many Requests] é enviada e [exit()] é
// chamada para parar a execução do script.
$filter_request = function() use ($app, $storage) {
// Obtém o IP de Usuário (exemplo se estiver utilizando um balanceador
// de carga)
$req = new \FastSitePHP\Web\Request();
$user_ip = $req->clientIp('from proxy');
// Check rate
$rate_limit = new \FastSitePHP\Security\Web\RateLimit();
$rate_limit->filterRequest($app, [
'storage' => $storage,
'id' => $user_ip,
]);
};
$app->get('/api', function() {})->filter($filter_request);
// Quando utilizar [filterRequest()] os seguintes Cabeçalhos de Response
// podem ser enviados para o cliente dependendo de quais opções são
// utilizadas
// Retry-After Cabeçalho Padrão
// X-RateLimit-Limit Descrição legível por humanos do limite da taxa
// X-RateLimit-Remaining Requisições permitidas para o período de tempo dado
// X-RateLimit-Reset Registro de data e hora Unix para o limite redefinir
Abra e Edite Arquivos de Imagens
// Utilize a Classe Media Image para abrir uma imagem. Se a imagem for
// inválida ou a extensão do arquivo não corresponder ao tipo de arquivo,
// então, uma exceção será lançada. Extensões de arquivos suportadas =
// [jpg, jpeg, gif, png, webp]
$img = new \FastSitePHP\Media\Image();
$img->open($file_path);
// Gera uma Miniatura ou Redimensiona a Imagem para um máximo especificado
// de largura e altura.
//
// Quando ambas largura e altura são especificadas, a imagem será
// redimensionada para o menor dos dois valores para que ela se ajuste. Se
// somente a largura ou somente a altura for especificada, então, a imagem
// será dimensionada proporcionalmente para o valor.
$max_width = 200; // Pixels
$max_height = 200;
$img->resize($max_width, $max_height);
// Imagens pode também serem cortadas para uma dimensão especificada.
// Isto pode ser utilizado com JavaScript ou bibliotecas de corte para Apps
// para permitir que usuários gerem miniaturas de uma imagem completa enviada.
// Por exemplo, permita o usuário cortar uma imagem enviada para uma
// miniatura de perfil.
$left = 50;
$top = 40;
$width = 120;
$height = 80;
$target_width = $width * 2; // Opcional
$target_height = $height * 2; // Opcional
$img->crop($left, $top, $width, $height, $target_width, $target_height);
// Imagens podem ser rotacionadas o que é útil para sites que permitem
// usuários enviar imagens, por que imagens podem, geralmente, ser enviadas
// com a rotação incorreta dependendo do dispositivo móvel ou um usuário
// pode simplesmente querer modificar a rotação.
$degrees = 180;
$img->rotateLeft();
$img->rotateRight();
$img->rotate($degrees);
// Qualidade de Salvamento (0 to 100) pode ser especificada quando for
// salvar imagen JPG ou WEBP. E Nível de Compressão (0 to 9) pode ser
// especificado ao salvar arquivos PNG.
$img->saveQuality(90); // Qualidade Padrão
$img->pngCompression(6); // Nível de Compressão Padrão
// Sobrescreva uma imagem existente simplesmente chamando [save()] sem um
// caminho ou salve para um novo arquivo especificando um caminho completo
// de arquivo.
$img->save($save_path);
// Opcionalmente feche a imagem para liberar memória quando terminar de
// trabalhar com ela. Isto acontece automaticamente quando a variável não é
// mais utilizada.
$img->close();
Manipule Traduções de Idiomas para um Site ou Aplicação
// O FastSitePHP provê uma API de Internacionalização (i18n) de fácil
// utilização para sites e apps que precisam suportar múltiplos idiomas.
// O código é estruturado mas mínimo em seu tamanho, assim se você tem
// necessidades diferentes de tradução, você pode simplesmente copiar e
// modificar a classe.
// Traduções são salvas como arquivos JSON no mesmo diretório utilizando o
// formato de nome “{nome}.{idioma}.json”. Um arquivo principal opcional
// nomeado “_.{idioma}.json” se encontrado será lido primeiro. O arquivo
// principal "_" é útil para armazenar traduções chave tal como menus,
// cabeçalho de página, rodapés de páginas etc.
// Um idioma de fallback opcional pode ser especificado assim traduções
// não encontradas são obtidas de outro idioma. Isto permite que sites
// parcialmente traduzidos utilizem esta API.
// Já que a API é simples e fácil de utilizar, existem somente duas funções
// para chamar:
// [langFile()] e [textFile()].
// Arquivos de Exemplo:
// _.en.json
// _.es.json
// header.en.json
// header.es.json
// about.en.json
// Utilizando este código, os aquivos acima serão carregados na ordem listada.
$app->config['I18N_DIR'] = __DIR__ . '/i18n';
$app->config['I18N_FALLBACK_LANG'] = 'en';
\FastSitePHP\Lang\I18N::langFile('header', 'es');
\FastSitePHP\Lang\I18N::langFile('about', 'es');
// Uso típico é permitido para um app carregar um arquivo de idioma
// baseando-se na URL Requisitada:
$app->get('/:lang/about', function($lang) {
\FastSitePHP\Lang\I18N::langFile('about', $lang);
});
// [setup()] pode ser chamada por cada requisição para ter certeza que o
// arquivo de idioma seja sempre carregado para a renderização de um modelo
// quando [$app->render()] é chamada.
//
// Isto é útil se seu site utiliza PHP ou outros modelos para renderizar e
// espera que o arquivo [i18n] padrão sempre esteja disponível. Por exemplo
// um erro inesperado ou chamada de [$app->pageNotFound()] pode acionar um
// modelo para que seja renderizado.
\FastSitePHP\Lang\I18N::setup($app);
// Traduções carregadas são definidas na propriedade da app
// ($app->locals['i18n']), de forma que elas podem ser utilizadas com
// renderização de modelo e chamada de página.
// Ao utilizar um formato de URL [https://www.example.com/{lang}/{pages}]
// e um idioma fallback, o usuário será redirecionado para a mesma página
// com o idioma fallback se o idioma especificado não existir.
// Quando [langFile()] é chamada e o idioma é verificado como válido, isto é
// definido na propriedade do app ($app->lang).
// A outra função I18N [textFile()] simplesmente recebe um caminho completo
// de arquivo contento o texto '{lang}' juntamente com o idioma selecionado
// e então carrega o arquivo ou, se este não existir, o arquivo que
// corresponde ao idioma de fallback.
$file_path = $app->config['I18N_DIR'] . '/test-{lang}.txt';
$content = \FastSitePHP\Lang\I18N::textFile($file_path, $app->lang);
Formatando Datas, Horas e Números
// O FastSitePHP provê uma API de Localização (l10n) de fácil utilização
// para permitir formatação de datas e números com a linguagem local do
// usuário e configurações regionais.
// Cria um novo Objeto Lang L10N
$l10n = new \FastSitePHP\Lang\L10N();
// Definições são passadas de forma opcional quando a classe é criada
/*
$locale = 'pt-BR';
$timezone = 'America/Sao_Paulo';
$l10n = new \FastSitePHP\Lang\L10N($locale, $timezone);
*/
// Utiliza a função [timezone()] para obter ou definir o fuso horário que
// será utilizado ao formatar datas e horários.
//
// Se você tem um site ou aplicação que tenha usuários em múltiplos fusos
// horários our países, um design de aplicação que funciona bem é salvar
// todas as datas e horários em UTC e daí formatá-los baseando-se no fuso
// horário escolhido pelo usuário.
//
// Este exemplo imprime:
/*
UTC = 2030-01-01 00:00
Asia/Tokyo = 2030-01-01 09:00
America/Los_Angeles = 2029-12-31 16:00
*/
$date_time = '2030-01-01 00:00:00';
$timezones = ['UTC', 'Asia/Tokyo', 'America/Los_Angeles'];
foreach ($timezones as $timezone) {
// Mude o Fuso Horário
$l10n->timezone($timezone);
// Imprime a data e horário formatados
echo $l10n->timezone();
echo ' = ';
echo $l10n->formatDateTime($date_time);
echo '<br>';
}
echo '<br>';
// Mude o Fuso Horário de volta para UTC para os próximos exemplos
$l10n->timezone('UTC');
// O parâmetro [$date_time] para as funções [formatDateTime(), formatDate()
// e formatTime()] é um carimbo de data/hora Unix (int) ou uma string no
// formato de 'YYYY-MM-DD HH:MM:SS' ou 'YYYY-MM-DD'
$date_time = 1896181200;
$date_time = '2030-02-01 13:00:00';
// Imprima Data e Hora com localizações diferentes utilizando as funções
// [locale()] e [formatDateTime()]. Este exemplo imprime:
/*
ko = 2030. 2. 1. 오후 1:00
bn = ১/২/২০৩০ ১:০০ PM
en-US = 2/1/2030, 1:00 PM
de-CH = 01.02.2030, 13:00
ar = ١/٢/٢٠٣٠ ١:٠٠ م
*/
$locales = ['ko-KR', 'bn-BD', 'en-US', 'de-CH', 'ar'];
foreach ($locales as $locale) {
// Mude a Localização
$l10n->locale($locale);
// Imprima a data e hora formatados
echo $l10n->locale();
echo ' = ';
echo $l10n->formatDateTime($date_time);
echo '<br>';
}
echo '<br>';
// Além de [formatDateTime()] as funções [formatDate()] e [formatTime()]
// podem ser utilizadas para mostrar somente uma data ou hora. Imprime:
/*
01/02/2030
13:00:00
*/
$l10n->locale('fr-FR');
echo $l10n->formatDate($date_time);
echo '<br>';
echo $l10n->formatTime($date_time);
echo '<br>';
echo '<br>';
// Imprima um Número formatado com diferentes localizações utilizando as
// funções [locale()] e [formatNumber()]. Posições decimais são opcionais
// e seu padrão é 0. Este exemplo imprime:
/*
en-US = 1,234,567,890.12345
en-IN = 1,23,45,67,890.12345
fr = 1 234 567 890,12345
fa = ۱٬۲۳۴٬۵۶۷٬۸۹۰٫۱۲۳۴۵
*/
$numero = 1234567890.12345;
$decimals = 5;
$locales = ['en-US', 'en-IN', 'fr', 'fa'];
foreach ($locales as $locale) {
// [locale()] é uma função getter e setter encadeável assim ela pode ser
// definida e lida de uma mesma linha.
echo $l10n->locale($locale)->locale();
echo ' = ';
echo $l10n->formatNumber($numero, $decimals);
echo '<br>';
}
// Obtenha Localizações, Idiomas e Fusos Horários suportados
$locales = $l10n->supportedLocales();
$languages = $l10n->supportedLanguages();
$timezones = $l10n->supportedTimezones();
Starter Site Middleware
// The FastSitePHP Starter Site inclui várias páginas de exemplos e fornece uma
// estrutura básica de diretório / arquivo. O site foi projetado para fornecer
// estrutura para conteúdo básico (JavaScript, CSS etc.), mantendo um tamanho
// pequeno, para facilitar a remoção de arquivos desnecessários e a
// personalização para o seu site.
//
// https://github.com/fastsitephp/starter-site
//
// As classes de Middleware são fornecidas e podem ser modificadas para
// o seu site.
//
// Para utilizá-las especifique 'Class.method' nas funções filtro da rota
// ou quando montando arquivos adicionais.
// Exige que um usuário esteja logado para utilizar uma página
$app->get('/secure-page', 'SecureController')->filter('Auth.hasAccess');
// Exige um usuário autenticado e utilize CORS
$app
->get('/api/:record_type', 'ApiController.getData')
->filter('Cors.acceptAuth')
->filter('Auth.hasAccess');
// Somente rode uma rota de localhost
$app->get('/server-info', function() {
phpinfo();
})
->filter('Env.isLocalhost');
// Somente carregue um arquivo se estiver rodando à partir de localhost
$app->mount('/sysinfo/', 'routes-sysinfo.php', 'Env.isLocalhost');