3. Noções básicas do PHP
3.1. A estrutura hierárquica dos scripts

3.2. Configuração do PHP
O PHP vem pré-configurado por um arquivo de texto chamado [php.ini]. Todas essas configurações podem ser alteradas programaticamente. A configuração do PHP influencia significativamente a execução dos scripts. Portanto, é importante conhecê-la. O seguinte script [phpinfo.php] permite isso:
Comentários
- linha 3: a função [phpinfo] exibe a configuração de PHP;
Resultados da execução
A função [phpinfo] exibe aqui mais de 800 linhas de configuração. Não vamos comentá-las, pois a maioria diz respeito a um uso avançado da função PHP. Uma linha importante é a linha 13 acima: ela indica qual arquivo [php.ini] foi usado para configurar o PHP que você utilizará para executar seus scripts. Se você quiser alterar a configuração de execução do PHP, é esse arquivo que você precisa modificar. Há vários comentários nesse arquivo para explicar a função das diferentes configurações.
3.3. Um primeiro exemplo
3.3.1. O código
A seguir, você encontrará um programa [bases-01.php] que apresenta as primeiras características do PHP.
<?php
// este é um comentário
// variável usada sem ter sido declarada
$nom = "dupont";
// uma exibição na tela
print "nom=$nom\n";
// um array com elementos de tipos diferentes
$tableau = array("un", "deux", 3, 4);
// o número de elementos
$n = count($tableau);
// um loop
for ($i = 0; $i < $n; $i++) {
print "tableau[$i]=$tableau[$i]\n";
}
// inicialização de duas variáveis com o conteúdo de uma matriz
list($chaine1, $chaine2) = array("chaine1", "chaine2");
// concatenação das duas cadeias de caracteres
$chaine3 = $chaine1 . $chaine2;
// exibição do resultado
print "[$chaine1,$chaine2,$chaine3]\n";
// uso de função
affiche($chaine1);
// o tipo de uma variável pode ser conhecido
afficheType("n", $n);
afficheType("chaine1", $chaine1);
afficheType("tableau", $tableau);
// o tipo de uma variável pode mudar durante a execução
$n = "a changé";
afficheType("n", $n);
// uma função pode retornar um resultado
$res1 = f1(4);
print "res1=$res1\n";
// uma função pode retornar uma matriz de valores
list($res1, $res2, $res3) = f2();
print "(res1,res2,res3)=[$res1,$res2,$res3]\n";
// esses valores poderiam ter sido recuperados em uma matriz
$t = f2();
for ($i = 0; $i < count($t); $i++) {
print "t[$i]=$t[$i]\n";
}
// testes
for ($i = 0; $i < count($t); $i++) {
// exibe apenas as cadeias de caracteres
if (getType($t[$i]) === "string") {
print "t[$i]=$t[$i]\n";
}
}
// operadores de comparação == e ===
if("2"==2){
print "avec l'opérateur ==, la chaîne 2 est égale à l'entier 2\n";
}else{
print "avec l'opérateur ==, la chaîne 2 n'est pas égale à l'entier 2\n";
}
if("2"===2){
print "avec l'opérateur ===, la chaîne 2 est égale à l'entier 2\n";
}
else{
print "avec l'opérateur ===, la chaîne 2 n'est pas égale à l'entier 2\n";
}
// outros testes
for ($i = 0; $i < count($t); $i++) {
// exibe apenas os inteiros >10
if (getType($t[$i]) === "integer" and $t[$i] > 10) {
print "t[$i]=$t[$i]\n";
}
}
// um loop while
$t = [8, 5, 0, -2, 3, 4];
$i = 0;
$somme = 0;
while ($i < count($t) and $t[$i] > 0) {
print "t[$i]=$t[$i]\n";
$somme += $t[$i]; //$somme=$somme+$t[$i]
$i++; //$i=$i+1
}//enquanto
print "somme=$somme\n";
// fim do programa
exit;
//----------------------------------
function affiche($chaine) {
// exibe $chaine
print "chaine=$chaine\n";
}
//exibe
//----------------------------------
function afficheType($name, $variable) {
// exibe o tipo de $variable
print "type[variable $" . $name . "]=" . getType($variable) . "\n";
}
//afficheType
//----------------------------------
function f1($param) {
// soma 10 a $param
return $param + 10;
}
//----------------------------------
function f2() {
// retorna 3 valores
return array("un", 0, 100);
}
?>
Os resultados:
nom=dupont
tableau[0]=un
tableau[1]=deux
tableau[2]=3
tableau[3]=4
[chaine1,chaine2,chaine1chaine2]
chaine=chaine1
type[variable $n]=integer
type[variable $chaine1]=string
type[variable $tableau]=array
type[variable $n]=string
res1=14
(res1,res2,res3)=[un,0,100]
t[0]=un
t[1]=0
t[2]=100
t[0]=un
avec l'opérateur ==, la chaîne 2 est égale à l'entier 2
avec l'opérateur ===, la chaîne 2 n'est pas égale à l'entier 2
t[2]=100
t[0]=8
t[1]=5
somme=13
Comentários
- linha 5: no PHP, não se declara o tipo das variáveis. Elas têm um tipo dinâmico que pode variar ao longo do tempo. $nom representa a variável com o identificador “nom”;
- linha 7: para exibir na tela, pode-se usar a instrução print ou a instrução echo;
- linha 9: a palavra-chave array permite definir uma matriz. A variável $nom[$i] representa o elemento $i da matriz $tableau;
- linha 11: a função count($tableau) retorna o número de elementos da matriz $tableau;
- linhas 13-15: um loop. Como ele contém apenas uma instrução, as chaves são opcionais. No restante deste documento, colocaremos sistematicamente as chaves, independentemente do número de instruções;
- linha 14: as cadeias de caracteres são delimitadas por aspas " ou apóstrofos '. Dentro das aspas, as variáveis $variable são avaliadas, mas não dentro dos apóstrofos;
- linha 17: a função list permite reunir variáveis em uma lista e atribuir-lhes um valor com uma única operação de atribuição. Aqui, $chaine1="chaine1" e $chaine2="chaine2";
- linha 19: o operador . é o operador de concatenação de cadeias de caracteres;
- linhas 83-86: a palavra-chave function define uma função. Uma função pode ou não retornar valores por meio da instrução return. O código chamador pode ignorar ou recuperar os resultados de uma função. Uma função pode ser definida em qualquer lugar do código.
- linha 92: a função predefinida getType($variable) retorna uma cadeia de caracteres que representa o tipo de $variable. Esse tipo pode mudar ao longo do tempo;
- linha 45: o operador === compara dois elementos de forma estrita: eles precisam ter o mesmo tipo para serem comparados. O operador == é menos estrito: dois elementos podem ser iguais sem serem do mesmo tipo. É o que mostram as instruções das linhas 50 a 60. No caso do operador ==, a comparação é feita após a conversão dos dois elementos comparados para um mesmo tipo. Nesse caso, ocorrem conversões implícitas. É bastante fácil “esquecer” a presença dessas conversões implícitas e, assim, chegar a resultados inesperados, como descobrir que uma condição é verdadeira quando se esperava que fosse falsa. Para evitar essa armadilha, usaremos sistematicamente o operador de comparação ===;
- linha 64: também é possível usar os operadores booleanos or e !;
- linha 69: em vez da notação array(), pode-se usar a notação [] para inicializar um array a partir de PHP7;
- linha 80: a função predefinida exit interrompe a execução do script;
- linha 107: a tag ?> indica o fim do script PHP. Ela não é indispensável. Além disso, em um contexto da web, ela pode causar problemas se for seguida por espaços ou caracteres de fim de linha, difíceis de detectar por não serem visíveis em um editor de texto. Portanto, no restante do documento, omitiremos sistematicamente essa tag;
Observação: neste documento, utilizaremos a palavra-chave [print] para exibir texto no console. Outro método para fazer o mesmo é utilizar a palavra-chave [echo]. Existem diferenças sutis entre essas duas palavras-chave, mas, no contexto deste documento, elas não farão diferença. Portanto, se você preferir usar [echo], fique à vontade.
3.3.2. Uso do NetBeans
O NetBeans exibe vários avisos que vale a pena verificar. Tomemos como exemplo o script [bases-01.php]:

Na linha 5, o NetBeans emite um aviso informando que o arquivo não está em conformidade com a recomendação PSR-1 (Recomendações Padrão PHP n.º 1). As PSR são recomendações para produzir um código padronizado e, assim, facilitar a interoperabilidade e a manutenção de códigos escritos por diferentes pessoas. Pode ser incômodo receber avisos se quisermos deliberadamente descumprir os padrões, por exemplo, porque a equipe do projeto segue outros padrões. O que se deseja verificar ou não com o NetBeans é configurável:

- em [5], encontram-se os elementos que se deseja verificar com o NetBeans;
- em [6], o nível de gravidade atribuído ao erro sinalizado pelo NetBeans;

Vemos em [7] que solicitamos a verificação de que o código segue corretamente as recomendações PSR-0 e PSR-1. Nada disso é obrigatório. Na fase de aprendizado da linguagem, é recomendável verificar o máximo possível de opções oferecidas pelo NetBeans. Assim, aprende-se muito. Posteriormente, essa verificação do NetBeans será adaptada às normas de codificação da equipe de um projeto.
Vejamos as normas de codificação PSR-1 e [8, 9]:
Opção | Verificação |
| As constantes de classe MUST devem ser declaradas em letras maiúsculas, com separadores de sublinhado. Ex.: const TAUX_TVA |
| Os nomes de métodos MUST devem ser declarados em camelCase(). Ex.: public function executeBatchImpots{} |
| Os nomes das propriedades SHOULD devem ser declarados no formato $StudlyCaps, $camelCase ou $under_score (de forma consistente em um escopo) Ex.: public SalaireAnnuel (StudlyCaps), public salaireAnnuel (camelCase), public salaire_annuel (under_score) |
| Um arquivo SHOULD declara novos símbolos e não causa outros efeitos colaterais, ou o SHOULD executa lógica com efeitos colaterais, mas o SHOULD e o NOT fazem as duas coisas. |
| Os nomes de tipos MUST devem ser declarados em StudlyCaps (O código escrito para 5.2.x e versões anteriores a SHOULD utiliza a convenção de pseudonamespacing de prefixos Vendor_ nos nomes de tipos). Cada tipo está em um arquivo próprio e pertence a um namespace de pelo menos um nível: um nome de fornecedor de nível superior. Ex.: class EtudiantBoursier {} |
A recomendação PSR-1 / 4 estabelece que, em um arquivo PHP, deve haver:
- ou a declaração de um tipo (classes, interface);
- ou código executável sem declaração de novos tipos;
Existem outras recomendações PHP não verificadas pelo NetBeans: PSR-3, PSR-4, PSR-6, PSR-7 e PSR-13.
Por uma questão de praticidade, nem todos os exemplos do documento verificam a recomendação PSR-1, pois isso exige que o código das classes e interfaces seja distribuído em arquivos separados, o que é muito trabalhoso para exemplos básicos. Portanto, é mais fácil colocar tudo em um único arquivo. Para o exemplo da aplicação apresentado como fio condutor deste documento, procurou-se seguir ao máximo a recomendação PSR-1.
Alguns avisos do NetBeans indicam um possível erro:

O aviso [Unitialized Variables] indica um erro provável, geralmente um erro de digitação no nome de uma variável. O mesmo se aplica ao aviso [Unused Variables].
Por fim, é recomendável verificar todos os avisos do NetBeans, indicados por um painel na margem esquerda do código e por um traço amarelo na margem direita:


3.4. O escopo das variáveis
3.4.1. Exemplo 1
O script [bases-02.php] é o seguinte:
<?php
// escopo das variáveis
function f1() {
// usa-se a variável global $i
global $i;
$i++;
$j = 10;
print "f1[i,j]=[$i,$j]\n";
}
function f2() {
// usa-se a variável global $i
global $i;
$i++;
$j = 20;
print "f2[i,j]=[$i,$j]\n";
}
function f3() {
// usa-se uma variável local $i
$i = 4;
$j = 30;
print "f3[i,j]=[$i,$j]\n";
}
// testes
$i = 0;
$j = 0; // essas duas variáveis só são conhecidas por uma função f
// a menos que esta as declare explicitamente por meio da instrução global
// que deseja utilizá-las
f1();
f2();
f3();
print "test[i,j]=[$i,$j]\n";
Os resultados:
Comentários
- linhas 29-30: definem duas variáveis, $i e $j, do programa principal. Essas variáveis não são reconhecidas dentro das funções. Assim, na linha 9, a variável $j da função f1 é uma variável local da função f1 e é diferente da variável $j do programa principal. Uma função pode acessar uma variável $variable do programa principal por meio da palavra-chave global;
- na linha 7, a instrução refere-se à variável global $i do programa principal;
3.4.2. Exemplo 3
O script [bases-03.php] é o seguinte:
<?php
// o escopo de uma variável é global aos blocos de código
$i = 0; {
$i = 4;
$i++;
}
print "i=$i\n";
Os resultados:
Comentários
Em algumas linguagens, uma variável definida entre chaves tem o escopo dessas chaves: ela não é reconhecida fora delas. Os resultados acima mostram que isso não ocorre em PHP. A variável $i, definida na linha 5 dentro das chaves, é a mesma utilizada nas linhas 4 e 8 fora delas.
3.5. Mudanças de tipos
As variáveis em PHP não possuem um tipo constante. Esse tipo pode mudar durante a execução, dependendo do valor atribuído à variável. Em operações que envolvem dados de diversos tipos, o interpretador PHP realiza conversões implícitas para unificar os operandos em um tipo comum. Essas conversões implícitas, se não forem conhecidas pelo desenvolvedor, podem ser uma fonte de erros difíceis de identificar. Apresentamos abaixo um script [bases-04.php] que mostra conversões implícitas e explícitas:
<?php
// tipos estritos na passagem de parâmetros
declare(strict_types=1);
// conversões implícitas de tipos
// tipo --> bool
print "Conversion vers un booléen------------------------------\n";
showBool("abcd", "abcd");
showBool("", "");
showBool("[1, 2, 3]", [1, 2, 3]);
showBool("[]", []);
showBool("NULL", NULL);
showBool("0.0", 0.0);
showBool("0", 0);
showBool("4.6", 4.6);
function showBool(string $prefixe, $var) : void {
print "(bool) $prefixe : ";
// a conversão de $var para booleano ocorre automaticamente no teste a seguir
if ($var) {
print "true";
} else {
print "false";
}
print "\n";
}
Comentários
- linha 4: solicita uma verificação rigorosa do tipo dos parâmetros de uma função quando este é especificado;
- linha 18: a função [showBool] tem como objetivo mostrar a transformação implícita (automática) que o interpretador PHP realiza quando um valor de qualquer tipo precisa ser transformado em booleano (linha 21);
- linha 18: o parâmetro $var não tem tipo atribuído. O parâmetro efetivo poderá, portanto, ser de qualquer tipo. O parâmetro $prefixe, por sua vez, deverá ser do tipo string. A função showBool não retorna nenhum valor (void);
- linha 21: na instrução if($var), o valor de $var deve ser convertido em booleano para que if seja avaliado. Surpreendentemente, o interpretador PHP retorna uma resposta para qualquer tipo de valor que lhe seja fornecido;
- linhas 9-16: o valor do parâmetro da função [showBool] será, sucessivamente:
- linha 9: uma string não vazia: resultado TRUE (não importa se está em maiúsculas ou minúsculas, TRUE = verdadeiro);
- linha 10: uma string vazia: resultado FALSE;
- linha 11: um array não vazio: resultado TRUE;
- linha 12: um array vazio: resultado FALSE;
- linha 14: o número real 0: resultado FALSE;
- linha 15: o número inteiro 0: resultado FALSE;
- linha 16: o número real (ou inteiro) diferente de 0: resultado TRUE;
É o que mostram as exibições na tela obtidas:
Conversion vers un booléen------------------------------
(bool) abcd : true
(bool) : false
(bool) [1, 2, 3] : true
(bool) [] : false
(bool) NULL : false
(bool) 0.0 : false
(bool) 0 : false
(bool) 4.6 : true
Vamos continuar com o código do script:
//
// conversões implícitas do tipo string para um tipo numérico
// string --> número
print "Conversion chaîne vers nombre------------------------------\n";
showNumber("12");
showNumber("45.67");
showNumber("abcd");
function showNumber(string $var) : void {
$nombre = $var + 1;
var_dump($nombre);
print "($var): $nombre\n";
}
Comentários
- linha 9: a função [showNumber] aceita um parâmetro do tipo string e não retorna nenhum resultado (void);
- linha 10: esse parâmetro é usado em uma operação aritmética, o que forçará o interpretador PHP a tentar converter $var em um número;
- linha 5: transformará a string “12” no número inteiro 12;
- linha 6: transformará a string “45.67” no número real 45.67;
- linha 7: emitirá um aviso, mas mesmo assim converterá a string “abcd” no número 0;
Aqui estão os resultados da execução:
Vamos continuar com o código do script:
// conversões explícitas de tipo
// para int
showInt("12.45");
showInt(67.8);
showInt(TRUE);
showInt(NULL);
function showInt($var) : void {
print "paramètre : ";
var_dump($var);
print "\n";
print "résultat de la conversion : ";
var_dump((int) $var);
print "\n";
}
Comentários
- linha 21: a função [showInt] recebe um parâmetro de qualquer tipo e não retorna nenhum resultado. Ela tenta converter o parâmetro $var em inteiro na linha 26. De modo geral, para converter uma variável $var em um tipo T, escreve-se (T) $var, onde T pode ser: int, integer, bool, boolean, float, double, real, string, array, object, unset;
- linha 16: converte a string “12.45” em um inteiro 12;
- linha 17: converte o real 67,8 em um inteiro 67;
- linha 18: converte o booleano TRUE no inteiro 1 (o booleano FALSE no inteiro 0);
- linha 19: converte o ponteiro NULL no inteiro 0;
É isso que mostram as exibições na tela:
Continuamos a análise do script com a conversão explícita de valores para o tipo float:
// para float
showFloat("12.45");
showFloat(67);
showFloat(TRUE);
showFloat(NULL);
function showFloat($var) : void {
print "paramètre : ";
var_dump($var);
print "\n";
print "résultat de la conversion : ";
var_dump((float) $var);
print "\n";
}
Comentários
- linha 35: a função [showFloat] recebe um parâmetro de qualquer tipo e não retorna nenhum resultado;
- linha 40: o valor desse parâmetro é explicitamente convertido em float;
- linha 30: a string “12.45” é convertida no número real 12.45;
- linha 31: o inteiro 67 é transformado no número real 67;
- linha 32: o booleano TRUE é transformado no número real 1 (o valor FALSE no número 0);
- linha 33: o ponteiro NULL é convertido no número real 0;
É isso que mostram os resultados na tela:
Continuamos a apresentação do script analisando as conversões para o tipo string:
// para string
showstring(5);
showString(6.7);
showString(FALSE);
showString(NULL);
function showString($var) : void {
print "paramètre : ";
var_dump($var);
print "\n";
print "résultat de la conversion : ";
var_dump((string) $var);
print "\n";
}
- linha 49: a função [showString] recebe um parâmetro de qualquer tipo e não retorna nenhum resultado;
- linha 54: o valor do parâmetro é convertido para o tipo string;
- linha 44: o inteiro 5 será transformado na string “5”;
- linha 45: o número real 6,7 será convertido na string “6,7”;
- linha 46: o booleano FALSE será transformado em uma string vazia;
- linha 47: o ponteiro NULL será convertido em uma string vazia;
Aqui estão os resultados na tela:
3.6. As tabelas
3.6.1. Matrizes clássicas unidimensionais
O script [bases-05.php] é o seguinte:
<?php
// matrizes clássicas
// inicialização
$tab1 = array(0, 1, 2, 3, 4, 5);
// iteração - 1
print "tab1 a " . count($tab1) . " éléments\n";
for ($i = 0; $i < count($tab1); $i++) {
print "tab1[$i]=$tab1[$i]\n";
}
// percorro - 2
print "tab1 a " . count($tab1) . " éléments\n";
reset($tab1);
while (list($clé, $valeur) = each($tab1)) {
print "tab1[$clé]=$valeur\n";
}
// adição de elementos
$tab1[] = $i++;
$tab1[] = $i++;
// navegação - 3
print "tab1 a " . count($tab1) . " éléments\n";
$i = 0;
foreach ($tab1 as $élément) {
print "tab1[$i]=$élément\n";
$i++;
}
// exclusão do último elemento
array_pop($tab1);
// percurso - 4
print "tab1 a " . count($tab1) . " éléments\n";
for ($i = 0; $i < count($tab1); $i++) {
print "tab1[$i]=$tab1[$i]\n";
}
// exclusão do primeiro elemento
array_shift($tab1);
// percurso - 5
print "tab1 a " . count($tab1) . " éléments\n";
for ($i = 0; $i < count($tab1); $i++) {
print "tab1[$i]=$tab1[$i]\n";
}
// adição ao final da tabela
array_push($tab1, -2);
// percurso - 6
print "tab1 a " . count($tab1) . " éléments\n";
for ($i = 0; $i < count($tab1); $i++) {
print "tab1[$i]=$tab1[$i]\n";
}
// adição no início da tabela
array_unshift($tab1, -1);
// percurso - 7
print "tab1 a " . count($tab1) . " éléments\n";
for ($i = 0; $i < count($tab1); $i++) {
print "tab1[$i]=$tab1[$i]\n";
}
Os resultados:
tab1 a 6 éléments
tab1[0]=0
tab1[1]=1
tab1[2]=2
tab1[3]=3
tab1[4]=4
tab1[5]=5
tab1 a 6 éléments
Deprecated: The each() function is deprecated. This message will be suppressed on further calls in C:\Data\st-2019\dev\php7\php5-exemples\exemples\exemple_04.php on line 14
tab1[0]=0
tab1[1]=1
tab1[2]=2
tab1[3]=3
tab1[4]=4
tab1[5]=5
tab1 a 8 éléments
tab1[0]=0
tab1[1]=1
tab1[2]=2
tab1[3]=3
tab1[4]=4
tab1[5]=5
tab1[6]=6
tab1[7]=7
tab1 a 7 éléments
tab1[0]=0
tab1[1]=1
tab1[2]=2
tab1[3]=3
tab1[4]=4
tab1[5]=5
tab1[6]=6
tab1 a 6 éléments
tab1[0]=1
tab1[1]=2
tab1[2]=3
tab1[3]=4
tab1[4]=5
tab1[5]=6
tab1 a 7 éléments
tab1[0]=1
tab1[1]=2
tab1[2]=3
tab1[3]=4
tab1[4]=5
tab1[5]=6
tab1[6]=-2
tab1 a 8 éléments
tab1[0]=-1
tab1[1]=1
tab1[2]=2
tab1[3]=3
tab1[4]=4
tab1[5]=5
tab1[6]=6
tab1[7]=-2
Comentários
O programa acima demonstra operações de manipulação de uma matriz de valores. Existem duas formações para matrizes no PHP:
A tabela 1 é chamada de tabela e a tabela 2, de dicionário ou tabela associativa, na qual os elementos são representados como chave => valor. A notação $contraires["beau"] designa o valor associado à chave “belo”. Portanto, neste caso, trata-se da sequência “feio”. A tabela 1 é apenas uma variante do dicionário e poderia ser representada da seguinte forma:
Assim, temos $tableau[2] = “três”. Por fim, existem apenas dicionários. No caso de uma matriz clássica com n elementos, as chaves são os números inteiros do intervalo [0,n-1].
- linha 14: a função each($tableau) permite percorrer um dicionário. A cada chamada, ela retorna um par (chave, valor) do mesmo. Conforme mostra a linha 10 dos resultados, a função each está agora obsoleta na versão PHP 7;
- linha 13: a função reset($dictionnaire) define a função each no primeiro par (chave, valor) do dicionário.
- linha 14: o loop while é interrompido quando a função each retorna um par vazio no final do dicionário. Trata-se de uma conversão implícita que ocorre aqui: o par vazio é convertido no valor booleano FALSE;
- linha 18: a notação $tableau[]=valor adiciona o elemento valeur como último elemento de $tableau;
- linha 23: o array é percorrido com um foreach. Esse elemento sintático permite percorrer um dicionário, e portanto um array, de acordo com duas sintaxes:
A primeira sintaxe retorna um par (clé,valeur) a cada iteração, enquanto a segunda sintaxe retorna apenas o elemento valeur do dicionário.
- linha 28: a função array_pop($tableau) remove o último elemento de $tableau;
- linha 35: a função array_shift($tableau) exclui o primeiro elemento de $tableau;
- linha 42: a função array_push($tableau,valor) adiciona valeur como último elemento de $tableau;
- linha 49: a função array_unshift($tableau,valor) adiciona valeur como primeiro elemento de $tableau;
3.6.2. O dicionário ou tabela associativa
O script [bases-06.php] é o seguinte:
<?php
// dicionários
$conjoints = ["Pierre" => "Gisèle", "Paul" => "Virginie", "Jacques" => "Lucette", "Jean" => ""];
// percurso - 1
print "Nombre d'éléments du dictionnaire : " . count($conjoints) . "\n";
reset($conjoints);
while (list($clé, $valeur) = each($conjoints)) {
print "conjoints[$clé]=$valeur\n";
}
// classificação do dicionário pela chave
ksort($conjoints);
// percurso - 2
reset($conjoints);
while (list($clé, $valeur) = each($conjoints)) {
print "conjoints[$clé]=$valeur\n";
}
// lista de chaves do dicionário
$clés = array_keys($conjoints);
for ($i = 0; $i < count($clés); $i++) {
print "clés[$i]=$clés[$i]\n";
}
// lista de valores do dicionário
$valeurs = array_values($conjoints);
for ($i = 0; $i < count($valeurs); $i++) {
print "valeurs[$i]=$valeurs[$i]\n";
}
// busca por uma chave
existe($conjoints, "Jacques");
existe($conjoints, "Lucette");
existe($conjoints, "Jean");
// exclusão de uma chave-valor
unset($conjoints["Jean"]);
print "Nombre d'éléments du dictionnaire : " . count($conjoints) . "\n";
foreach ($conjoints as $clé => $valeur) {
print "conjoints[$clé]=$valeur\n";
}
// fim
exit;
function existe($conjoints, $mari) {
// verifica se a chave $mari existe no dicionário $conjoints
if (isset($conjoints[$mari])) {
print "La clé [$mari] existe associée à la valeur [$conjoints[$mari]]\n";
} else {
print "La clé [$mari] n'existe pas\n";
}
}
Os resultados:
Nombre d'éléments du dictionnaire : 4
Deprecated: The each() function is deprecated. This message will be suppressed on further calls in C:\Data\st-2019\dev\php7\php5-exemples\exemples\exemple_05.php on line 8
conjoints[Pierre]=Gisèle
conjoints[Paul]=Virginie
conjoints[Jacques]=Lucette
conjoints[Jean]=
conjoints[Jacques]=Lucette
conjoints[Jean]=
conjoints[Paul]=Virginie
conjoints[Pierre]=Gisèle
clés[0]=Jacques
clés[1]=Jean
clés[2]=Paul
clés[3]=Pierre
valeurs[0]=Lucette
valeurs[1]=
valeurs[2]=Virginie
valeurs[3]=Gisèle
La clé [Jacques] existe associée à la valeur [Lucette]
La clé [Lucette] n'existe pas
La clé [Jean] existe associée à la valeur []
Nombre d'éléments du dictionnaire : 3
conjoints[Jacques]=Lucette
conjoints[Paul]=Virginie
conjoints[Pierre]=Gisèle
Comentários
O código acima aplica a um dicionário o que foi visto anteriormente para uma matriz simples. Comentaremos apenas as novidades:
- linha 12: a função ksort (key sort) permite ordenar um dicionário na ordem natural da chave;
- linha 19: a função array_keys($dictionnaire) retorna a lista de chaves do dicionário na forma de tabela;
- linha 24: a função array_values($dictionnaire) retorna a lista de valores do dicionário na forma de tabela;
- linha 43: a função isset($variable) retorna TRUE se a variável $variable tiver sido definida; caso contrário, retorna FALSE;
- linha 33: a função unset($variable) exclui a variável $variable.
3.6.3. Matrizes multidimensionais
O script [bases-07.php] é o seguinte:
<?php
// tabelas multidimensionais clássicas
// inicialização
$multi = array(array(0, 1, 2), array(10, 11, 12, 13), array(20, 21, 22, 23, 24));
// navegação
for ($i1 = 0; $i1 < count($multi); $i1++) {
for ($i2 = 0; $i2 < count($multi[$i1]); $i2++) {
print "multi[$i1][$i2]=" . $multi[$i1][$i2] . "\n";
}
}
// dicionários multidimensionais
// inicialização
$multi = array("zéro" => array(0, 1, 2), "un" => array(10, 11, 12, 13), "deux" => array(20, 21, 22, 23, 24));
// navegação
foreach ($multi as $clé => $valeur) {
for ($i2 = 0; $i2 < count($valeur); $i2++) {
print "multi[$clé][$i2]=" . $multi[$clé][$i2] . "\n";
}
}
Resultados:
multi[0][0]=0
multi[0][1]=1
multi[0][2]=2
multi[1][0]=10
multi[1][1]=11
multi[1][2]=12
multi[1][3]=13
multi[2][0]=20
multi[2][1]=21
multi[2][2]=22
multi[2][3]=23
multi[2][4]=24
multi[zéro][0]=0
multi[zéro][1]=1
multi[zéro][2]=2
multi[un][0]=10
multi[un][1]=11
multi[un][2]=12
multi[un][3]=13
multi[deux][0]=20
multi[deux][1]=21
multi[deux][2]=22
multi[deux][3]=23
multi[deux][4]=24
Comentários
- linha 5: os elementos da matriz $multi são, por sua vez, matrizes;
- linha 14: a matriz $multi se transforma em um dicionário (clé,valeur), no qual cada valeur é uma matriz;
3.7. As cadeias de caracteres
3.7.1. Notação
O script [bases-08.php] é o seguinte:
<?php
// notação de cadeias
$chaine1 = "un";
$chaine2 = 'un';
print "[$chaine1,$chaine2]\n";
?>
Resultados:
3.7.2. Comparação
O script [bases-09.php] é o seguinte:
<?php
// respeito estrito ao tipo dos parâmetros das funções
declare(strict_types=1);
// função de comparação
function compareModele2Chaine(string $chaine1, string $chaine2): void {
// compara string1 e string2
if ($chaine1 === $chaine2) {
print "[$chaine1] est égal à [$chaine2]\n";
} else {
print "[$chaine1] est différent de [$chaine2]\n";
}
}
// testes de comparação de cadeias de caracteres
compareModele2Chaine("abcd", "abcd");
compareModele2Chaine("", "");
compareModele2Chaine("1", "");
exit;
Resultados:
[abcd] est égal à [abcd]
[] est égal à []
[1] est différent de []
Comentários
- linha 9 do código: poderia ter sido usado o comparador == em vez de ===. Este último operador é mais restritivo, pois exige que os dois operandos sejam do mesmo tipo. Vale ressaltar que, neste caso, ele poderia ter sido substituído pelo operador ==, já que o tipo dos dois parâmetros está definido como string na assinatura da função;
3.7.3. Relações entre strings e matrizes
O script [bases-10.php] é o seguinte:
<?php
// conversão de string em matriz
$chaine = "1:2:3:4";
$tab = explode(":", $chaine);
// iteração pela matriz
print "tab a " . count($tab) . " éléments\n";
for ($i = 0; $i < count($tab); $i++) {
print "tab[$i]=$tab[$i]\n";
}
// de matriz para string
$chaine2 = implode(":", $tab);
print "chaine2=$chaine2\n";
// vamos adicionar um campo vazio
$chaine .= ":";
print "chaîne=$chaine\n";
$tab = explode(":", $chaine);
// iteração pela matriz
print "tab a " . count($tab) . " éléments\n";
for ($i = 0; $i < count($tab); $i++) {
print "tab[$i]=$tab[$i]\n";
} // agora temos 5 elementos, sendo o último vazio
// vamos adicionar novamente um campo vazio
$chaine .= ":";
print "chaîne=$chaine\n";
$tab = explode(":", $chaine);
// percorrer matriz
print "tab a " . count($tab) . " éléments\n";
for ($i = 0; $i < count($tab); $i++) {
print "tab[$i]=$tab[$i]\n";
} // agora temos 6 elementos, sendo que os dois últimos estão vazios
Resultados:
tab a 4 éléments
tab[0]=1
tab[1]=2
tab[2]=3
tab[3]=4
chaine2=1:2:3:4
chaîne=1:2:3:4:
tab a 5 éléments
tab[0]=1
tab[1]=2
tab[2]=3
tab[3]=4
tab[4]=
chaîne=1:2:3:4::
tab a 6 éléments
tab[0]=1
tab[1]=2
tab[2]=3
tab[3]=4
tab[4]=
tab[5]=
Comentários
- linha 5: a função explode($séparateur,$chaine) permite recuperar os campos de $chaine separados por $séparateur. Assim, explode(":",$chaine) permite recuperar, na forma de tabela, os elementos de $chaine que são separados pela sequência de caracteres ":";
- linha 12: a função implode($séparateur,$tableau) realiza a operação inversa à função explode. Ela retorna uma sequência de caracteres formada pelos elementos de $tableau separados por $séparateur;
3.7.4. Expressões regulares
O script [bases-11.php] é o seguinte:
<?php
// tipo estrito para os parâmetros das funções
declare (strict_types=1);
// expressões regulares em PHP
// extrair os diferentes campos de uma string
// o padrão: uma sequência de números entre caracteres quaisquer
// queremos recuperar apenas a sequência de números
$modèle = "/(\d+)/";
// comparamos a string com o padrão
compareModele2Chaine($modèle, "xyz1234abcd");
compareModele2Chaine($modèle, "12 34");
compareModele2Chaine($modèle, "abcd");
// o modelo: uma sequência de números entre caracteres quaisquer
// queremos a sequência de números, bem como os campos que a precedem e a seguem
$modèle = "/^(.*?)(\d+)(.*?)$/";
// comparamos a sequência com o modelo
compareModele2Chaine($modèle, "xyz1234abcd");
compareModele2Chaine($modèle, "12 34");
compareModele2Chaine($modèle, "abcd");
// o modelo: uma data no formato dd/mm/aa
$modèle = "/^\s*(\d\d)\/(\d\d)\/(\d\d)\s*$/";
compareModele2Chaine($modèle, "10/05/97");
compareModele2Chaine($modèle, " 04/04/01 ");
compareModele2Chaine($modèle, "5/1/01");
// o modelo — um número decimal
$modèle = "/^\s*([+|-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*/";
compareModele2Chaine($modèle, "187.8");
compareModele2Chaine($modèle, "-0.6");
compareModele2Chaine($modèle, "4");
compareModele2Chaine($modèle, ".6");
compareModele2Chaine($modèle, "4.");
compareModele2Chaine($modèle, " + 4");
// fim
exit;
// --------------------------------------------------------------------------
function compareModele2Chaine(string $modèle, string $chaîne): void {
// compara a sequência $chaîne com o modelo $modèle
// a string é comparada ao modelo
$champs = [];
$correspond = preg_match($modèle, $chaîne, $champs);
// exibição dos resultados
print "\nRésultats($modèle,$chaîne)\n";
if ($correspond) {
for ($i = 0; $i < count($champs); $i++) {
print "champs[$i]=$champs[$i]\n";
}
} else {
print "La chaîne [$chaîne] ne correspond pas au modèle [$modèle]\n";
}
}
Resultados:
Résultats(/(\d+)/,xyz1234abcd)
champs[0]=1234
champs[1]=1234
Résultats(/(\d+)/,12 34)
champs[0]=12
champs[1]=12
Résultats(/(\d+)/,abcd)
La chaîne [abcd] ne correspond pas au modèle [/(\d+)/]
Résultats(/^(.*?)(\d+)(.*?)$/,xyz1234abcd)
champs[0]=xyz1234abcd
champs[1]=xyz
champs[2]=1234
champs[3]=abcd
Résultats(/^(.*?)(\d+)(.*?)$/,12 34)
champs[0]=12 34
champs[1]=
champs[2]=12
champs[3]= 34
Résultats(/^(.*?)(\d+)(.*?)$/,abcd)
La chaîne [abcd] ne correspond pas au modèle [/^(.*?)(\d+)(.*?)$/]
Résultats(/^\s*(\d\d)\/(\d\d)\/(\d\d)\s*$/,10/05/97)
champs[0]=10/05/97
champs[1]=10
champs[2]=05
champs[3]=97
Résultats(/^\s*(\d\d)\/(\d\d)\/(\d\d)\s*$/, 04/04/01 )
champs[0]= 04/04/01
champs[1]=04
champs[2]=04
champs[3]=01
Résultats(/^\s*(\d\d)\/(\d\d)\/(\d\d)\s*$/,5/1/01)
La chaîne [5/1/01] ne correspond pas au modèle [/^\s*(\d\d)\/(\d\d)\/(\d\d)\s*$/]
Résultats(/^\s*([+|-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*/,187.8)
champs[0]=187.8
champs[1]=
champs[2]=187.8
Résultats(/^\s*([+|-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*/,-0.6)
champs[0]=-0.6
champs[1]=-
champs[2]=0.6
Résultats(/^\s*([+|-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*/,4)
champs[0]=4
champs[1]=
champs[2]=4
Résultats(/^\s*([+|-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*/,.6)
champs[0]=.6
champs[1]=
champs[2]=.6
Résultats(/^\s*([+|-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*/,4.)
champs[0]=4.
champs[1]=
champs[2]=4.
Résultats(/^\s*([+|-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*/, + 4)
champs[0]= + 4
champs[1]=+
champs[2]=4
Comentários
- Aqui, utilizamos expressões regulares para extrair os diversos campos de uma sequência de caracteres. As expressões regulares permitem superar as limitações da função implode. O princípio consiste em comparar uma sequência de caracteres com outra sequência chamada modèle, utilizando a função preg_match:
$correspond = preg_match($modèle, $chaîne, $champs);
A função preg_match retorna um valor booleano TRUE se o modèle puder ser encontrado no chaîne. Se sim, $champs[0] representa a subcadeia correspondente ao modelo. Além disso, se modèle contiver submodelos entre parênteses, $champs[1] é a parte de $chaîne correspondente ao primeiro submodelo, $champs[2] é a parte de $chaîne correspondente ao segundo submodelo, etc…
Consideremos o primeiro exemplo. O modelo é definido na linha 10: ele designa uma sequência de um ou mais (+) dígitos (\d) posicionados em qualquer lugar de uma cadeia. Além disso, o modelo define um submodelo entre parênteses;
- linha 12: o padrão /(\d+)/ (sequência de um ou mais dígitos em qualquer ponto da string) é comparado à string "xyz1234abcd". Percebe-se que a sub-string 1234 corresponde ao padrão. Portanto, teremos $champs[0] igual a “1234”. Além disso, o padrão possui subpadrões entre parênteses. Teremos $champs[1] = “1234”;
- linha 13: o padrão /(\d+)/ é comparado à sequência “12 34”. Vemos que as subsequências 12 e 34 correspondem ao padrão. A comparação é interrompida na primeira subsequência que corresponde ao padrão. Teremos, portanto, $champs[0]=12 e $champs[1]=12;
- linha 14: o padrão /(\d+)/ é comparado à sequência “abcd”. Não é encontrada nenhuma correspondência;
Vamos explicar os padrões utilizados no restante do código:
$modèle = "/^(.*?)(\d+)(.*?)$/";
corresponde ao início da sequência (^), seguido de 0 ou mais (*) caracteres quaisquer (.), depois 1 ou mais (+) dígitos, e novamente 0 ou mais (*) caracteres quaisquer (.). O padrão (.*) designa 0 ou mais caracteres quaisquer. Um padrão desse tipo corresponderá a qualquer sequência de caracteres. Assim, o padrão /^(.*)(\d+)(.*)$/ nunca será encontrado, pois o primeiro subpadrão (.*) absorverá toda a sequência. O padrão (.*?)(\d+) designa 0 ou mais caracteres quaisquer até o subpadrão seguinte (?), neste caso \d+. Portanto, os algarismos agora não são mais absorvidos pelo padrão (.*). O padrão acima corresponde, portanto, a [début de chaîne (^), une suite de caractères quelconques (.*?), une suite d'un ou plusieurs chiffres (\d+), une suite de caractères quelconques (.*?), la fin de la chaîne ($)].
$modèle = "/^\s*(\d\d)\/(\d\d)\/(\d\d)\s*$/";
corresponde a [début de chaîne (^), 2 chiffres (\d\d), le caractère / (\/), 2 chiffres, /, 2 chiffres, une suite de 0 ou plusieurs espaces (\s*), la fin de chaîne ($)].
$modèle = "/^\s*([+|-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*/";
corresponde ao início da sequência (^), 0 ou mais espaços (\s*), um sinal + ou - [+|-] presente 0 ou 1 vez (?), uma sequência de 0 ou mais espaços (\s*), 1 ou mais dígitos seguidos por um ponto decimal seguido por zero ou mais dígitos (\d+\.\d*) ou (|) um ponto decimal (\.) seguido por um ou mais dígitos (\d+) ou (|) um ou mais dígitos (\d+), uma sequência de 0 ou mais espaços (\s*)].
Observação: o termo [espace] nas expressões regulares designa um conjunto de caracteres: espaço em branco, salto de linha \n, tabulação \t, retorno de linha \r, salto de página \f…
3.8. As funções
3.8.1. Modo de passagem dos parâmetros
O script [base-12.php] é o seguinte:
<?php
// modo de passagem de parâmetros de uma função
// respeito estrito ao tipo dos parâmetros
declare(strict_types=1);
function f(int &$i, int $j): void {
// $i será obtido por referência
// $j será obtido por valor
$i++;
$j++;
print "f[i,j]=[$i,$j]\n";
}
// testes
$i = 0;
$j = 0;
// $i e $j são passados para a função f
f($i, $j);
print "test[i,j]=[$i,$j]\n";
Resultados:
Comentários
O código acima mostra os dois modos de passar parâmetros para uma função. Vejamos o seguinte exemplo:
- linha 1: define os parâmetros formais $a e $b da função f. Essa função manipula esses dois parâmetros formais e retorna um resultado;
- linha 7: chamada da função f com dois parâmetros efetivos $i e $j. As relações entre os parâmetros formais ($a, $b) e os parâmetros efetivos ($i, $j) são definidas pelas linhas 1 e 7:
- &$a: o símbolo & indica que o parâmetro formal $a assumirá como valor o endereço do parâmetro efetivo $i. Em outras palavras, $a e $i são duas referências ao mesmo endereço de memória. Manipular o parâmetro formal $a equivale a manipular o parâmetro efetivo $i. É isso que a execução do código demonstra. Esse modo de passagem é adequado para parâmetros de saída e dados volumosos, como tabelas e dicionários. Esse modo de passagem é chamado de passagem por referência.
- $b: o parâmetro formal $b assumirá o valor do parâmetro efetivo $j. Trata-se de uma passagem por valor. Os parâmetros formais e efetivos são duas variáveis diferentes. Manipular o parâmetro formal $b não tem qualquer efeito sobre o parâmetro efetivo $j. É o que mostra a execução do código. Esse modo de passagem é adequado para parâmetros de entrada.
- Considere a função échange, que aceita dois parâmetros formais: $a e $b. A função troca os valores desses dois parâmetros. Assim, durante uma chamada de troca ($i,$j), o código chamador espera que os valores dos dois parâmetros efetivos sejam trocados. Portanto, trata-se de parâmetros de saída (eles são modificados). Assim, escreveremos:
O script a seguir, [base-13.php], mostra outros exemplos:
<?php
// tipos no modo estrito
// declare(strict_types = 1);
// modo de passagem de parâmetros
function f(&$i, $j) {
// $i será obtido por referência
// $j será obtido por valor
$i++;
$j++;
print "f[i,j]=[$i,$j]\n";
}
function g(int &$i, int $j) : void {
// $i será obtido por referência
// $j será obtido por valor
$i++;
$j++;
print "g[i,j]=[$i,$j]\n";
}
// testes
$i = 0;
$j = 0;
// $i e $j são passados para a função f
f($i, $j);
print "test[i,j]=[$i,$j]\n";
// $i e $j são passados para a função g
g($i, $j);
print "test[i,j]=[$i,$j]\n";
// são passados parâmetros incorretos para f
$a=5.3;
$b=6.2;
f($a, $b);
print "test[a,b]=[$a,$b]\n";
// estão sendo passados parâmetros incorretos para f
$a=5.3;
$b=6.2;
g($a, $b);
print "test[a,b]=[$a,$b]\n";
Comentários
- linhas 8-14: a função f analisada no parágrafo anterior, mas sem especificar os tipos dos parâmetros;
- linhas 16-22: a função g faz o mesmo que a função f, mas especifica-se o tipo dos parâmetros esperados – essa é uma novidade PHP 7. Esperam-se dois parâmetros do tipo int. Queremos ver o que acontece quando o parâmetro efetivamente passado para a função não tem o tipo esperado por ela;
- linhas 25-26: $i e $j são dois inteiros;
- linhas 28-29: chamada da função f com parâmetros do tipo esperado;
- linhas 31-32: chamada da função g com parâmetros do tipo esperado;
- linhas 34-35: as variáveis $a e $b são do tipo float;
- linhas 36-37: chamada da função f com parâmetros que não são do tipo esperado;
- linhas 41-42: chamada da função g com parâmetros que não são do tipo esperado;
Resultados
- as linhas 5-6 mostram que a função f aceitou os dois parâmetros do tipo float e trabalhou com eles;
- as linhas 7-8 mostram que a função g aceitou os dois parâmetros do tipo float, mas os converteu para o tipo int (linha 7);
Agora, vamos descomentar a linha 4:
Essa instrução indica que os tipos dos parâmetros formais devem ser respeitados. Caso contrário, é gerado um erro. Os resultados da execução passam a ser:
- linhas 9-10: o interpretador PHP 7 lançou uma exceção para indicar que o primeiro parâmetro passado à função g não tinha o tipo correto. Recomenda-se ser rigoroso quanto aos tipos dos parâmetros, sempre que possível, para detectar erros na chamada de funções;
3.8.2. Resultados retornados por uma função
O script [base-15.php] é o seguinte:
<?php
// tipos no modo estrito
declare(strict_types=1);
// resultados retornados por uma função
// uma função pode retornar vários valores em um array
list($res1, $res2, $res3) = f1(10);
print "[$res1,$res2,$res3]\n";
$res = f1(10);
for ($i = 0; $i < count($res); $i++) {
print "f1 : res[$i]=$res[$i]\n";
}
// uma função pode retornar um objeto
$res = f2(10);
print "f2 : [$res->res1,$res->res2,$res->res3]\n";
// objeto de que tipo?
print "nature de l'objet : ";
var_dump($res);
print "\n";
// fazemos o mesmo com a função f3
$res = f3(10);
print "f3 : [$res->res1,$res->res2,$res->res3]\n";
// Que tipo de objeto?
print "nature de l'objet : ";
var_dump($res);
print "\n";
// fim
exit;
// função f1
function f1(int $valeur): array {
// retorna uma matriz ($valeur+1,$valeur+2,$valeur+3)
return array($valeur + 1, $valeur + 2, $valeur + 3);
}
// função f2
function f2(int $valeur): object {
// retorna um objeto ($valeur+1,$valeur+2,$valeur+3)
$res->res1 = $valeur + 1;
$res->res2 = $valeur + 2;
$res->res3 = $valeur + 3;
// retorna o objeto
return $res;
}
// função f3 — faz o mesmo que a função f2
function f3(int $valeur): object {
// retorna um objeto ($valeur+1,$valeur+2,$valeur+3)
$res = new stdclass();
$res->res1 = $valeur + 1;
$res->res2 = $valeur + 2;
$res->res3 = $valeur + 3;
// retorna o objeto
return $res;
}
Resultados
[11,12,13]
f1 : res[0]=11
f1 : res[1]=12
f1 : res[2]=13
Warning: Creating default object from empty value in C:\Data\st-2019\dev\php7\php5-exemples\exemples\bases\base-15.php on line 43
f2 : [11,12,13]
nature de l'objet : object(stdClass)#1 (3) {
["res1"]=>
int(11)
["res2"]=>
int(12)
["res3"]=>
int(13)
}
f3 : [11,12,13]
nature de l'objet : object(stdClass)#2 (3) {
["res1"]=>
int(11)
["res2"]=>
int(12)
["res3"]=>
int(13)
}
Comentários
- o programa anterior mostra que uma função PHP pode retornar um conjunto de resultados, e não apenas um, na forma de uma matriz ou de um objeto. O conceito de objeto é explicado mais adiante;
- linhas 35-38: a função f1 retorna vários valores na forma de uma matriz (array);
- linhas 41-48: a função f2 retorna vários valores na forma de um objeto (object);
- linhas 51-59: a função f3 é idêntica à função f2, exceto pelo fato de que ela cria explicitamente um objeto, na linha 53;
- a linha 6 dos resultados exibe um aviso (warning) indicando que PHP foi obrigado a criar um objeto por padrão na linha 43 do código, ou seja, ao utilizar a notação [$res→res1]. A função var_dump, na linha 20 do código, permite acessar o tipo do objeto e seu conteúdo. Nos resultados, observa-se que:
- linha 8: o objeto criado por padrão é do tipo stdClass;
- linhas 9-10: a propriedade res1 é do tipo entier e tem o valor 11;
- etc…
- para evitar o aviso da linha 6 dos resultados, criamos explicitamente, na linha 53 da função f3, um objeto do tipo stdClass;
3.9. Os arquivos de texto
O script [bases-16.php] é o seguinte:
<?php
// respeito estrito ao tipo dos parâmetros das funções
declare (strict_types=1);
// processamento sequencial de um arquivo de texto
// este é um conjunto de linhas no formato login:pwd:uid:gid:infos:dir:shell
// cada linha é inserida em um dicionário no formato login => uid:gid:infos:dir:shell
// define-se o nome do arquivo
$INFOS = "infos.txt";
// abrimos o arquivo para criação
if (!$fic = fopen($INFOS, "w")) {
print "Erreur d'ouverture du fichier $INFOS en écriture\n";
exit;
}
// gera-se um conteúdo arbitrário
for ($i = 0; $i < 100; $i++) {
fputs($fic, "login$i:pwd$i:uid$i:gid$i:infos$i:dir$i:shell$i\n");
}
// fecha-se o arquivo
fclose($fic);
// exploramos o arquivo — o `fgets` mantém o marcador de fim de linha
// isso evita que uma string vazia seja recuperada ao ler uma linha em branco
// abre-se o arquivo para leitura
if (!$fic = fopen($INFOS, "r")) {
print "Erreur d'ouverture du fichier $INFOS en lecture\n";
exit;
}
// as linhas têm menos de 1.000 caracteres
// a leitura da linha é interrompida no marcador de fim de linha
// ou no marcador de fim de arquivo
while ($ligne = fgets($fic, 1000)) {
// a marca de fim de linha é removida, se houver
$ligne = cutNewLineChar($ligne);
// colocamos a linha em uma tabela
$infos = explode(":", $ligne);
// recuperamos o login
$login = array_shift($infos);
// ignora-se a senha
array_shift($infos);
// cria-se uma entrada no dicionário
$dico[$login] = $infos;
}
// fechamos o dicionário
fclose($fic);
// análise do dicionário
afficheInfos($dico, "login10");
afficheInfos($dico, "X");
// fim
exit;
// --------------------------------------------------------------------------
function afficheInfos(array $dico, string $clé): void {
// exibe o valor associado à chave no dicionário $dico, caso exista
if (isset($dico[$clé])) {
// valor existe — é uma matriz?
$valeur = $dico[$clé];
if (is_array($valeur)) {
print "[$clé," . join(":", $valeur) . "]\n";
} else {
// $valeur não é uma matriz
print "[$clé,$valeur]\n";
}
} else {
// $clé não é uma chave do dicionário $dico
print "la clé [$clé] n'existe pas\n";
}
}
// --------------------------------------------------------------------------
function cutNewLinechar(string $ligne): string {
// a marca de fim de linha de $ligne é removida, caso exista
$L = strlen($ligne); // comprimento da linha
while (substr($ligne, $L - 1, 1) == "\n" or substr($ligne, $L - 1, 1) == "\r") {
$ligne = substr($ligne, 0, $L - 1);
$L--;
}
// fim
return($ligne);
}
O arquivo infos.txt:
Os resultados:
[login10,uid10:gid10:infos10:dir10:shell10]
la clé [X] n'existe pas
Comentários
- linha 12: fopen(nom_fichier,"w") abre o arquivo nom_fichier para gravação (w=write). Se o arquivo não existir, ele será criado. Se já existir, seu conteúdo será apagado. Se a criação falhar, fopen retornará o valor false. Na instrução if (!$fic = fopen($INFOS, "w")) {…}, há duas operações sucessivas: 1) $fic = fopen(..) 2) if( ! $fic) {…};
- linha 18: fputs($fic, $chaîne) grava chaîne no arquivo $fic. $chaine é gravado com o caractere de fim de linha \n à sua direita;
- linha 21: fclose($fic) fecha o arquivo $fic;
- linha 26: fopen(nom_fichier,"r") abre o arquivo nom_fichier para leitura (r=read). Se a abertura falhar (por exemplo, se o arquivo não existir), fopen retorna o valor false;
- linha 34: fgets($fic, 1000) lê a próxima linha do arquivo, com um limite de 1.000 caracteres. Na operação while ($ligne = fgets($fic, 1000)) {…}, há duas operações sucessivas: 1) $ligne = fgets(…) 2) while ( ! $ligne). Depois que o último caractere do arquivo é lido, a função fgets retorna o valor false e o loop while é encerrado. A função fgets tenta aqui ler no máximo 1.000 caracteres, mas é interrompida assim que encontra um caractere de fim de linha. Como todas as linhas têm menos de 1.000 caracteres, a função [fgets] lê uma linha de texto, incluindo o caractere de fim de linha. A função cutNewLineChar, nas linhas 75 a 84, elimina eventuais caracteres de fim de linha;
- linha 77: a função strlen($chaîne) retorna o número de caracteres de $chaîne;
- linha 78: a função substr($ligne, $position, $taille) retorna $taille caracteres de $ligne, a partir do caractere nº $position, sendo que o primeiro caractere tem o nº 0. Em máquinas Windows, o marcador de fim de linha é “\r\n”. Em máquinas Unix, é a sequência “\n”;
- linha 40: a função array_shift($tableau) remove o primeiro elemento de $tableau e o retorna como resultado. Aqui, desconsidera-se o resultado retornado por array_shift;
- linha 62: a função is_array($variable) retorna true se $variable for uma matriz; caso contrário, retorna false;
- linha 63: a função join faz o mesmo que a função implode já vista;
3.10. Codificação/decodificação jSON

A codificação/decodificação jSON (JavaScript Object Notation) é algo que utilizaremos intensivamente no exercício que serve de fio condutor deste documento. Os scripts [json-01.php, json-02.php, json-03.php] explicam o que é necessário saber para prosseguir.
O script [json-01.php] é o seguinte:
<?php
$array1 = ["nom" => "séléné", "prénom" => "bénédicte", "âge" => 34];
// codificação JSON da matriz array1 com caracteres Unicode escapados
print "encodage json du tableau array1 avec caractères Unicode échappés\n";
$json1 = json_encode($array1);
print "json1=$json1\n";
// codificação JSON da matriz array1 com caracteres Unicode não escapados
print "encodage json du tableau array1 avec caractères Unicode non échappés\n";
$json2 = json_encode($array1, JSON_UNESCAPED_UNICODE);
print "json2=$json2\n";
// decodificação de jSON em tabela associativa
print "décodage jSON de json2 dans tableau associatif\n";
$array2 = json_decode($json2, true);
var_dump($array2);
foreach ($array2 as $key => $value) {
print "$key:$value\n";
}
// decodificação de jSON em objeto
print "décodage jSON de json2 dans objet stdClass\n";
$array2 = json_decode($json2);
var_dump($array2);
print "prénom=$array2->prénom\n";
print "nom=$array2->nom\n";
print "âge=$array2->âge\n";
Resultados
Comentários
- linha 6 do código: a função [json_encode] transforma seu parâmetro na sequência de caracteres jSON;
- linha 2 dos resultados: a sequência de caracteres jSON gerada. Os caracteres Unicode éâ foram substituídos por seus códigos Unicode, que começam com \u;
- linha 10 do código: repetimos o mesmo processo, mas desta vez solicitando que os caracteres Unicode sejam mantidos como estão;
- linha 4 dos resultados: a string resultante jSON. Ela é muito mais legível;
- linhas 14-18 do código: fazemos a operação inversa. Transformamos uma sequência jSON em uma tabela associativa;
- linhas 6 a 13 dos resultados: vemos que recuperamos um array associativo;
- linhas 19-25 do código: transformamos uma string jSON em um objeto do tipo [stdClass];
- linhas 18-25 dos resultados: vemos que foi recuperado um objeto do tipo [stdClass];
- linhas 23-25 do código: o atributo A de um objeto O é denotado como [O→A];
É possível codificar em jSON tabelas com vários níveis, conforme mostra o seguinte script [json-02.php]:
<?php
$array = ["nom" => "séléné", "prénom" => "bénédicte", "âge" => 34,
"mari" => ["nom" => "icariù", "prénom" => "ignacio", "âge" => 35],
"enfants" => [
["prénom" => "angèle", "age" => 8],
["prénom" => "andré", "age" => 2],
]];
// codificação jSON da matriz multinível
print "encodage jSON d'un tableau à plusieurs niveaux\n";
$json = json_encode($array, JSON_UNESCAPED_UNICODE);
print "json=$json\n";
Resultados
encodage jSON d'un tableau à plusieurs niveaux
json={"nom":"séléné","prénom":"bénédicte","âge":34,"mari":{"nom":"icariù","prénom":"ignacio","âge":35},"enfants":[{"prénom":"angèle","age":8},{"prénom":"andré","age":2}]}
Comentários
Na sequência jSON:
- as tabelas não associativas são colocadas entre colchetes [] ;
- as tabelas associativas são colocadas entre chaves {};
O script [json-03.php] mostra como utilizar o arquivo jSON [famille.json] a seguir:
{
"épouse": {
"nom": "séléné",
"prénom": "bénédicte",
"âge": 34
},
"mari": {
"nom": "icariù",
"prénom": "ignacio",
"âge": 35
},
"enfants": [
{
"prénom": "angèle",
"age": 8
},
{
"prénom": "andré",
"age": 2
}
]
}
O script [json-03.php] é o seguinte:
<?php
// leitura do arquivo jSON
$json = file_get_contents("famille.json");
// decodificação de JSON em objeto
$famille1 = json_decode($json);
print "----famille1\n";
var_dump($famille1);
// decodificação de JSON em tabela associativa
print "----famille2\n";
$famille2 = json_decode($json, true);
var_dump($famille2);
Comentários
- linha 4: a função [file_get_contents] lê o conteúdo do arquivo chamado [famille.json] e o armazena na variável [$json];
- a variável é então decodificada em objeto (linhas 5-8) e em tabela associativa (linhas 9-12);
Resultados
----famille1
object(stdClass)#2 (3) {
["épouse"]=>
object(stdClass)#1 (3) {
["nom"]=>
string(9) "séléné"
["prénom"]=>
string(11) "bénédicte"
["âge"]=>
int(34)
}
["mari"]=>
object(stdClass)#3 (3) {
["nom"]=>
string(7) "icariù"
["prénom"]=>
string(7) "ignacio"
["âge"]=>
int(35)
}
["enfants"]=>
array(2) {
[0]=>
object(stdClass)#4 (2) {
["prénom"]=>
string(7) "angèle"
["age"]=>
int(8)
}
[1]=>
object(stdClass)#5 (2) {
["prénom"]=>
string(6) "andré"
["age"]=>
int(2)
}
}
}
----famille2
array(3) {
["épouse"]=>
array(3) {
["nom"]=>
string(9) "séléné"
["prénom"]=>
string(11) "bénédicte"
["âge"]=>
int(34)
}
["mari"]=>
array(3) {
["nom"]=>
string(7) "icariù"
["prénom"]=>
string(7) "ignacio"
["âge"]=>
int(35)
}
["enfants"]=>
array(2) {
[0]=>
array(2) {
["prénom"]=>
string(7) "angèle"
["age"]=>
int(8)
}
[1]=>
array(2) {
["prénom"]=>
string(6) "andré"
["age"]=>
int(2)
}
}
}
Comentários
- linhas 1-38: o objeto resultante da decodificação do arquivo jSON [famille.json];
- linhas 39-76: a tabela associativa resultante da decodificação do arquivo jSON [famille.json];