3. Os conceitos básicos do PHP
3.1. A estrutura do diretório de scripts

3.2. Configuração do PHP
O PHP vem pré-configurado através de um ficheiro de texto [php.ini]. Todas estas definições podem ser alteradas programaticamente. A configuração do PHP influencia significativamente a execução dos scripts. Por isso, é importante compreendê-la. O seguinte script [phpinfo.php] permite-lhe fazê-lo:
Comentários
- linha 3: a função [phpinfo] exibe a configuração do PHP;
Resultados da execução
A função [phpinfo] apresenta aqui mais de 800 linhas de configuração. Não iremos comentá-las, pois a maioria diz respeito a utilizações avançadas do PHP. Uma linha importante é a linha 13 acima: indica qual o ficheiro [php.ini] que foi utilizado para configurar o PHP que irá utilizar para executar os seus scripts. Se pretender alterar a configuração de tempo de execução do PHP, este é o ficheiro que precisa de editar. Existem muitos comentários neste ficheiro que explicam a função das várias definições.
3.3. Um primeiro exemplo
3.3.1. O código
Abaixo encontra-se um programa [bases-01.php] que demonstra as funcionalidades básicas do PHP.
<?php
// this is a comment
// variable used without being declared
$nom = "dupont";
// a screen display
print "nom=$nom\n";
// an array with elements of different types
$tableau = array("un", "deux", 3, 4);
// its number of elements
$n = count($tableau);
// a loop
for ($i = 0; $i < $n; $i++) {
print "tableau[$i]=$tableau[$i]\n";
}
// initialize 2 variables with the contents of an array
list($chaine1, $chaine2) = array("chaine1", "chaine2");
// concatenation of the 2 strings
$chaine3 = $chaine1 . $chaine2;
// result display
print "[$chaine1,$chaine2,$chaine3]\n";
// use function
affiche($chaine1);
// the type of a variable can be known
afficheType("n", $n);
afficheType("chaine1", $chaine1);
afficheType("tableau", $tableau);
// the type of a variable can change at runtime
$n = "a changé";
afficheType("n", $n);
// a function can return a result
$res1 = f1(4);
print "res1=$res1\n";
// a function can render a table of values
list($res1, $res2, $res3) = f2();
print "(res1,res2,res3)=[$res1,$res2,$res3]\n";
// we could have retrieved these values in a table
$t = f2();
for ($i = 0; $i < count($t); $i++) {
print "t[$i]=$t[$i]\n";
}
// testing
for ($i = 0; $i < count($t); $i++) {
// displays only channels
if (getType($t[$i]) === "string") {
print "t[$i]=$t[$i]\n";
}
}
// == and === comparison operators
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";
}
// other tests
for ($i = 0; $i < count($t); $i++) {
// displays only integers >10
if (getType($t[$i]) === "integer" and $t[$i] > 10) {
print "t[$i]=$t[$i]\n";
}
}
// a while loop
$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
}//while
print "somme=$somme\n";
// end of program
exit;
//----------------------------------
function affiche($chaine) {
// displays $chaine
print "chaine=$chaine\n";
}
//poster
//----------------------------------
function afficheType($name, $variable) {
// displays the type of $variable
print "type[variable $" . $name . "]=" . getType($variable) . "\n";
}
//afficheType
//----------------------------------
function f1($param) {
// adds 10 to $param
return $param + 10;
}
//----------------------------------
function f2() {
// returns 3 values
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: Em PHP, não se declaram tipos de variáveis. As variáveis têm um tipo dinâmico que pode mudar ao longo do tempo. $name representa a variável com o identificador name;
- linha 7: para apresentar o resultado no ecrã, pode utilizar a instrução print ou a instrução echo;
- linha 9: a palavra-chave array é utilizada para definir uma matriz. A variável $name[$i] representa o $i-ésimo elemento da matriz $array;
- linha 11: a função count($tableau) devolve o número de elementos na matriz $tableau;
- linhas 13–15: um loop. Uma vez que este loop contém apenas uma instrução, as chaves são opcionais. No resto deste documento, utilizaremos sempre chaves, independentemente do número de instruções;
- linha 14: as cadeias de caracteres são colocadas entre aspas duplas " ou aspas simples '. Dentro das aspas duplas, as variáveis $variable são avaliadas, mas não dentro das aspas simples;
- linha 17: a função list permite agrupar variáveis numa 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 devolver valores utilizando a instrução `return`. O código de chamada pode ignorar ou recuperar os resultados de uma função. Uma função pode ser definida em qualquer parte do código.
- linha 92: a função predefinida getType($variable) retorna uma string que representa o tipo de $variable. Este tipo pode mudar ao longo do tempo;
- Linha 45: O operador === realiza uma comparação estrita entre dois elementos: estes devem ser do mesmo tipo para serem comparados. O operador == é menos estrito: dois elementos podem ser iguais sem serem do mesmo tipo. Isto é demonstrado pelas instruções nas linhas 50–60. No caso do operador ==, a comparação é realizada após a conversão de ambos os elementos a serem comparados para o mesmo tipo. Ocorrem então conversões implícitas. É bastante fácil «esquecer-se» destas conversões implícitas e, assim, acabar com resultados inesperados, como descobrir que uma condição é verdadeira quando se esperava que fosse falsa. Para evitar esta armadilha, utilizaremos sistematicamente o operador de comparação ===;
- linha 64: também pode usar os operadores booleanos or e !;
- linha 69: em vez da notação array(), pode usar a notação [] para inicializar uma matriz no PHP 7;
- linha 80: a função predefinida exit interrompe a execução do script;
- linha 107: a tag ?> marca o fim do script PHP. Não é essencial. Além disso, num contexto web, pode causar problemas se for seguida de espaços ou quebras de linha, que são difíceis de detetar porque não são visíveis num editor de texto. Por isso, no resto deste documento, omitiremos consistentemente esta tag;
Nota: Neste documento, utilizaremos a palavra-chave [print] para apresentar texto na consola. Outra forma de fazer o mesmo é utilizar a palavra-chave [echo]. Existem diferenças subtis entre estas duas palavras-chave, mas no contexto deste documento, não haverá nenhuma. Portanto, se preferir utilizar [echo], faça-o.
3.3.2. Utilização do NetBeans
O NetBeans emite vários avisos que vale a pena verificar. Tomemos o exemplo do script [bases-01.php]:

Na linha 5, o NetBeans emite um aviso de que o ficheiro não está em conformidade com a recomendação PSR-1 (Recomendações Padrão PHP n.º 1). As PSRs são recomendações para a produção de código padrão, com o objetivo de facilitar a interoperabilidade e a manutenção de código escrito por diferentes pessoas. Pode ser irritante receber avisos se pretender deliberadamente infringir as normas, por exemplo, porque a equipa do projeto tem normas diferentes. O que pretende verificar ou não com o NetBeans é configurável:

- em [5], encontrará os elementos que pretende verificar com o NetBeans;
- em [6], o nível de gravidade atribuído ao erro comunicado pelo NetBeans;

Em [7], pode ver que solicitámos a verificação de que o código segue as recomendações PSR-0 e PSR-1. Nada é obrigatório. Ao aprender a linguagem, é aconselhável verificar o maior número possível de opções oferecidas pelo NetBeans. Aprenderá muito dessa forma. Pode então adaptar estas verificações do NetBeans aos padrões de codificação da sua equipa de projeto.
Vejamos os padrões de codificação PSR-1 [8, 9]:
Opção | Verificação |
| As constantes de classe DEVEM ser declaradas em maiúsculas, com separadores de sublinhado. Ex.: const TAUX_TVA |
| Os nomes dos métodos DEVEM ser declarados em camelCase(). Ex.: public function executeBatchTaxes{} |
| Os nomes das propriedades DEVEM ser declarados nos formatos $StudlyCaps, $camelCase ou $under_score (de forma consistente dentro de um escopo) Ex: public AnnualSalary (StudlyCaps), public annualSalary (camelCase), public annual_salary (underscore) |
| Um ficheiro DEVE declarar novos símbolos e não causar outros efeitos secundários, ou DEVE executar lógica com efeitos secundários, mas NÃO DEVE fazer ambas as coisas. |
| Os nomes dos tipos DEVEM ser declarados em StudlyCaps (o código escrito para a versão 5.2.x e anteriores DEVE usar a convenção de pseudonamespacing com prefixos Vendor_ nos nomes dos tipos). Cada tipo está no seu próprio ficheiro e num namespace de pelo menos um nível: um nome de fornecedor de nível superior. Ex: class ScholarshipStudent {} |
A recomendação PSR-1/4 estabelece que um ficheiro PHP deve conter:
- uma declaração de tipo (classes, interfaces);
- ou código executável sem declarações de novos tipos;
Existem outras recomendações PHP que não são aplicadas pelo NetBeans: PSR-3, PSR-4, PSR-6, PSR-7 e PSR-13.
Por uma questão de simplicidade, nem todos os exemplos neste documento seguem a recomendação PSR-1, uma vez que isso exigiria dividir o código de classes e interfaces em ficheiros separados, o que é demasiado complicado para exemplos básicos. Por isso, é mais fácil colocar tudo num único ficheiro. Para a aplicação de exemplo apresentada como tema central deste documento, esforçámo-nos por seguir a recomendação PSR-1 o mais fielmente possível.
Alguns avisos do NetBeans indicam um erro potencial:

O aviso [Variáveis não inicializadas] indica um erro provável, frequentemente um erro ortográfico no nome de uma variável. O mesmo se aplica ao aviso [Variáveis não utilizadas].
Por fim, recomenda-se que verifique todos os avisos do NetBeans, que são indicados por um banner na margem esquerda do código e por um traço amarelo na margem direita:


3.4. Âmbito da variável
3.4.1. Exemplo 1
O script [bases-02.php] é o seguinte:
<?php
// variable scope
function f1() {
// we use the global variable $i
global $i;
$i++;
$j = 10;
print "f1[i,j]=[$i,$j]\n";
}
function f2() {
// we use the global variable $i
global $i;
$i++;
$j = 20;
print "f2[i,j]=[$i,$j]\n";
}
function f3() {
// we use a local variable $i
$i = 4;
$j = 30;
print "f3[i,j]=[$i,$j]\n";
}
// tests
$i = 0;
$j = 0; // these two variables are known only to a function f
// only if it explicitly declares with the global instruction
// she wants to use them
f1();
f2();
f3();
print "test[i,j]=[$i,$j]\n";
Os resultados:
Comentários
- Linhas 29–30: definem duas variáveis, $i e $j, no programa principal. Estas variáveis não são conhecidas dentro das funções. Assim, na linha 9, a variável $j na função f1 é uma variável local da função f1 e é diferente da variável $j no programa principal. Uma função pode aceder a uma variável $variable no programa principal utilizando a 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
// the scope of a variable is global to code blocks
$i = 0; {
$i = 4;
$i++;
}
print "i=$i\n";
Os resultados:
Comentários
Em algumas linguagens, uma variável definida entre chaves tem o âmbito dessas chaves: não é reconhecida fora delas. Os resultados acima mostram que este não é o caso no PHP. A variável $i definida na linha 5 entre chaves é a mesma que a utilizada nas linhas 4 e 8 fora delas.
3.5. Alterações de tipo
As variáveis em PHP não têm um tipo fixo. O seu tipo pode mudar durante a execução, dependendo do valor atribuído à variável. Em operações que envolvem dados de vários tipos, o interpretador PHP realiza conversões implícitas para unificar os operandos num tipo comum. Estas conversões implícitas, se desconhecidas pelo programador, podem ser uma fonte de erros difíceis de detetar. Abaixo encontra-se um script [bases-04.php] que demonstra conversões implícitas e explícitas:
<?php
// strict types for passing parameters
declare(strict_types=1);
// implicit type changes
// type -->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 : ";
// conversion of $var to Boolean is automatic in the following test
if ($var) {
print "true";
} else {
print "false";
}
print "\n";
}
Comentários
- linha 4: requer verificação rigorosa do tipo dos parâmetros de uma função quando especificado;
- linha 18: a função [showBool] destina-se a demonstrar a conversão implícita (automática) realizada pelo interpretador PHP quando um valor de qualquer tipo deve ser convertido para um booleano (linha 21);
- linha 18: o parâmetro $var não tem nenhum tipo atribuído. O parâmetro real pode, portanto, ser de qualquer tipo. O parâmetro $prefix, por outro lado, deve 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 para um booleano para que o if seja avaliado. Surpreendentemente, o interpretador PHP tem uma solução para qualquer tipo de valor que lhe seja fornecido;
- linhas 9–16: o valor do parâmetro da função [showBool] será, por sua vez:
- linha 9: uma string não vazia: resultado TRUE (as maiúsculas e minúsculas não importam, TRUE=true);
- 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 inteiro 0: resultado FALSE;
- linha 16: um número real (ou inteiro) diferente de 0: resultado TRUE;
Eis o que é exibido no ecrã:
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:
//
// implicit changes from string type to numeric type
// string --> number
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] recebe um parâmetro de tipo string e não retorna nenhum resultado (void);
- linha 10: este parâmetro é utilizado numa operação aritmética, o que obrigará o interpretador PHP a tentar converter $var num número;
- linha 5: converterá a string “12” no inteiro 12;
- linha 6: converterá a string “45.67” no número de ponto flutuante 45.67;
- linha 7: emitirá um aviso, mas continuará a converter a string “abcd” no número 0;
Eis os resultados da execução:
Vamos continuar com o código do script:
// changements explicites de type
// vers 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] aceita um parâmetro de qualquer tipo e não devolve um resultado. Na linha 26, tenta converter o parâmetro $var num inteiro. Geralmente, para converter uma variável $var para o tipo T, escrevemos (T) $var, onde T pode ser: int, integer, bool, boolean, float, double, real, string, array, object, unset;
- linha 16: converte a string “12.45” no inteiro 12;
- linha 17: converte o número real 67,8 no 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;
Eis o que é exibido no ecrã:
Continuamos o nosso estudo do script com a conversão explícita de valores para o tipo float:
// to 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] aceita um parâmetro de qualquer tipo e não retorna um resultado;
- linha 40: o valor deste parâmetro é explicitamente convertido para um float;
- linha 30: a cadeia de caracteres “12.45” é convertida no número de ponto flutuante 12.45;
- linha 31: o inteiro 67 é convertido para o número real 67;
- linha 32: o booleano TRUE é convertido para o número real 1 (o valor FALSE para o número 0);
- linha 33: o ponteiro NULL é convertido para o número real 0;
Isto é demonstrado pela saída no ecrã:
Continuamos a visão geral do script examinando as conversões para o tipo string:
// to 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] aceita um parâmetro de qualquer tipo e não devolve um resultado;
- linha 54: o valor do parâmetro é convertido numa cadeia de caracteres;
- linha 44: o inteiro 5 será convertido na cadeia de caracteres "5";
- linha 45: o número de ponto flutuante 6,7 será convertido na string "6,7";
- linha 46: o valor booleano FALSE será convertido numa string vazia;
- linha 47: o ponteiro NULL é convertido numa string vazia;
Eis os resultados no ecrã:
3.6. Matrizes
3.6.1. Matrizes unidimensionais clássicas
O script [bases-05.php] é o seguinte:
<?php
// classic paintings
// initialization
$tab1 = array(0, 1, 2, 3, 4, 5);
// routes - 1
print "tab1 a " . count($tab1) . " éléments\n";
for ($i = 0; $i < count($tab1); $i++) {
print "tab1[$i]=$tab1[$i]\n";
}
// routes - 2
print "tab1 a " . count($tab1) . " éléments\n";
reset($tab1);
while (list($clé, $valeur) = each($tab1)) {
print "tab1[$clé]=$valeur\n";
}
// add elements
$tab1[] = $i++;
$tab1[] = $i++;
// routes - 3
print "tab1 a " . count($tab1) . " éléments\n";
$i = 0;
foreach ($tab1 as $élément) {
print "tab1[$i]=$élément\n";
$i++;
}
// delete last item
array_pop($tab1);
// routes - 4
print "tab1 a " . count($tab1) . " éléments\n";
for ($i = 0; $i < count($tab1); $i++) {
print "tab1[$i]=$tab1[$i]\n";
}
// delete first element
array_shift($tab1);
// routes - 5
print "tab1 a " . count($tab1) . " éléments\n";
for ($i = 0; $i < count($tab1); $i++) {
print "tab1[$i]=$tab1[$i]\n";
}
// addition at end of table
array_push($tab1, -2);
// routes - 6
print "tab1 a " . count($tab1) . " éléments\n";
for ($i = 0; $i < count($tab1); $i++) {
print "tab1[$i]=$tab1[$i]\n";
}
// addition at the beginning of the table
array_unshift($tab1, -1);
// routes - 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 para manipular uma matriz de valores. Existem duas notações para matrizes em PHP:
A matriz 1 é chamada de matriz, e a matriz 2 é chamada de dicionário ou matriz associativa, onde os elementos são denotados como chave => valor. A notação $opposites["beautiful"] refere-se ao valor associado à chave "beautiful". Aqui, esse valor é a cadeia de caracteres "ugly". A matriz 1 é simplesmente uma variante do dicionário e poderia ser escrita como:
Isto dá-nos $array[2] = "three". Em última análise, todos estes são dicionários. No caso de uma matriz padrão de n elementos, as chaves são os números inteiros no intervalo [0, n-1].
- linha 14: a função each($array) permite iterar sobre um dicionário. Em cada chamada, ela retorna um par (chave, valor) do mesmo. Conforme mostrado na linha 10 dos resultados, a função each está agora obsoleta no PHP 7;
- linha 13: a função reset($dictionary) define a função each para o primeiro par (chave, valor) no dicionário.
- linha 14: o ciclo while termina quando a função each retorna um par vazio no final do dicionário. Uma conversão implícita está em ação aqui: o par vazio é convertido para o booleano FALSE;
- linha 18: a notação $array[]=value adiciona o valor do elemento como o último elemento de $array;
- linha 23: a matriz é iterada utilizando um ciclo foreach. Esta sintaxe permite iterar sobre um dicionário — e, portanto, uma matriz — utilizando duas sintaxes diferentes:
A primeira sintaxe devolve um par (chave, valor) em cada iteração, enquanto a segunda sintaxe devolve apenas o elemento valor do dicionário.
- linha 28: a função array_pop($array) remove o último elemento de $array;
- linha 35: a função array_shift($array) remove o primeiro elemento de $array;
- linha 42: a função array_push($array,value) adiciona value como o último elemento de $array;
- linha 49: a função array_unshift($array,value) adiciona value como o primeiro elemento de $array;
3.6.2. O dicionário ou matriz associativa
O script [bases-06.php] é o seguinte:
<?php
// dictionaries
$conjoints = ["Pierre" => "Gisèle", "Paul" => "Virginie", "Jacques" => "Lucette", "Jean" => ""];
// routes - 1
print "Nombre d'éléments du dictionnaire : " . count($conjoints) . "\n";
reset($conjoints);
while (list($clé, $valeur) = each($conjoints)) {
print "conjoints[$clé]=$valeur\n";
}
// dictionary sorting on key
ksort($conjoints);
// routes - 2
reset($conjoints);
while (list($clé, $valeur) = each($conjoints)) {
print "conjoints[$clé]=$valeur\n";
}
// list of dictionary keys
$clés = array_keys($conjoints);
for ($i = 0; $i < count($clés); $i++) {
print "clés[$i]=$clés[$i]\n";
}
// list of dictionary values
$valeurs = array_values($conjoints);
for ($i = 0; $i < count($valeurs); $i++) {
print "valeurs[$i]=$valeurs[$i]\n";
}
// key search
existe($conjoints, "Jacques");
existe($conjoints, "Lucette");
existe($conjoints, "Jean");
// deleting a key-value
unset($conjoints["Jean"]);
print "Nombre d'éléments du dictionnaire : " . count($conjoints) . "\n";
foreach ($conjoints as $clé => $valeur) {
print "conjoints[$clé]=$valeur\n";
}
// end
exit;
function existe($conjoints, $mari) {
// checks whether the key $mari exists in the dictionary $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 vimos anteriormente para uma matriz simples. Iremos comentar apenas as novas funcionalidades:
- linha 12: a função ksort (ordenação por chave) ordena um dicionário na ordem natural das chaves;
- linha 19: a função array_keys($dictionary) devolve a lista das chaves do dicionário como uma matriz;
- linha 24: a função array_values($dictionary) devolve a lista dos valores do dicionário como uma matriz;
- linha 43: a função isset($variável) retorna TRUE se a $variável tiver sido definida, FALSE caso contrário;
- linha 33: a função unset($variável) elimina a $variável.
3.6.3. Matrizes multidimensionais
O script [bases-07.php] é o seguinte:
<?php
// classic multidimensional tables
// initialization
$multi = array(array(0, 1, 2), array(10, 11, 12, 13), array(20, 21, 22, 23, 24));
// route
for ($i1 = 0; $i1 < count($multi); $i1++) {
for ($i2 = 0; $i2 < count($multi[$i1]); $i2++) {
print "multi[$i1][$i2]=" . $multi[$i1][$i2] . "\n";
}
}
// multidimensional dictionaries
// initialization
$multi = array("zéro" => array(0, 1, 2), "un" => array(10, 11, 12, 13), "deux" => array(20, 21, 22, 23, 24));
// route
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, eles próprios, matrizes;
- linha 14: a matriz $multi torna-se um dicionário (chave, valor) em que cada valor é uma matriz;
3.7. Strings
3.7.1. Notação
O script [bases-08.php] é o seguinte:
<?php
// string notation
$chaine1 = "un";
$chaine2 = 'un';
print "[$chaine1,$chaine2]\n";
?>
Resultados:
3.7.2. Comparação
O script [bases-09.php] é o seguinte:
<?php
// strict adherence to function parameter types
declare(strict_types=1);
// comparison function
function compareModele2Chaine(string $chaine1, string $chaine2): void {
// compare string1 and string2
if ($chaine1 === $chaine2) {
print "[$chaine1] est égal à [$chaine2]\n";
} else {
print "[$chaine1] est différent de [$chaine2]\n";
}
}
// string comparison tests
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: poderíamos ter usado o operador == em vez de ===. Este último operador é mais restritivo, na medida em que exige que ambos os operandos sejam do mesmo tipo. Note-se que, neste caso, poderia ter sido substituído pelo operador ==, uma vez que o tipo de ambos os parâmetros está definido como string na assinatura da função;
3.7.3. Ligações entre cadeias de caracteres e matrizes
O script [bases-10.php] é o seguinte:
<?php
// string to array
$chaine = "1:2:3:4";
$tab = explode(":", $chaine);
// parcours tableau
print "tab a " . count($tab) . " éléments\n";
for ($i = 0; $i < count($tab); $i++) {
print "tab[$i]=$tab[$i]\n";
}
// table to string
$chaine2 = implode(":", $tab);
print "chaine2=$chaine2\n";
// add an empty field
$chaine .= ":";
print "chaîne=$chaine\n";
$tab = explode(":", $chaine);
// parcours tableau
print "tab a " . count($tab) . " éléments\n";
for ($i = 0; $i < count($tab); $i++) {
print "tab[$i]=$tab[$i]\n";
} // we now have 5 elements, the last being empty
// let's add another empty field
$chaine .= ":";
print "chaîne=$chaine\n";
$tab = explode(":", $chaine);
// parcours tableau
print "tab a " . count($tab) . " éléments\n";
for ($i = 0; $i < count($tab); $i++) {
print "tab[$i]=$tab[$i]\n";
} // we now have 6 elements, the last two being empty
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($separator,$string) recupera os campos de $string separados por $separator. Assim, explode(":",$string) devolve os elementos de $string separados pela cadeia ":" sob a forma de um array;
- linha 12: a função implode($separator,$array) realiza a operação inversa da função explode. Ela retorna uma string composta pelos elementos de $array separados por $separator;
3.7.4. Expressões regulares
O script [bases-11.php] é o seguinte:
<?php
// strict type for function parameters
declare (strict_types=1);
// regular expressions in php
// retrieve the various fields of a string
// the model: a sequence of numbers surrounded by any characters
// you only want to retrieve the sequence of digits
$modèle = "/(\d+)/";
// the chain is compared with the model
compareModele2Chaine($modèle, "xyz1234abcd");
compareModele2Chaine($modèle, "12 34");
compareModele2Chaine($modèle, "abcd");
// the model: a sequence of numbers surrounded by any characters
// we want the sequence of digits and the fields that follow and precede them
$modèle = "/^(.*?)(\d+)(.*?)$/";
// the chain is compared with the model
compareModele2Chaine($modèle, "xyz1234abcd");
compareModele2Chaine($modèle, "12 34");
compareModele2Chaine($modèle, "abcd");
// the template - a date in dd/mm/yy format
$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");
// the model - a decimal number
$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");
// end
exit;
// --------------------------------------------------------------------------
function compareModele2Chaine(string $modèle, string $chaîne): void {
// compares the $chaîne string with the $modèle model
// the chain is compared with the
$champs = [];
$correspond = preg_match($modèle, $chaîne, $champs);
// displaying results
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, usamos expressões regulares para extrair vários campos de uma string. As expressões regulares permitem-nos superar as limitações da função implode. O princípio consiste em comparar uma string com outra string, chamada padrão, 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 padrão for encontrado na string. Se for esse o caso, $fields[0] representa a substring que corresponde ao padrão. Além disso, se o padrão contiver subpadrões entre parênteses, $fields[1] é a parte de $string correspondente ao primeiro subpadrão, $fields[2] é a parte de $string correspondente ao segundo subpadrão, e assim por diante…
Considere o primeiro exemplo. O padrão é definido na linha 10: denota uma sequência de um ou mais (+) dígitos (\d) localizados em qualquer parte de uma string. Além disso, o padrão define um subpadrão entre parênteses;
- Linha 12: O padrão /(\d+)/ (uma sequência de um ou mais dígitos em qualquer parte da cadeia) é comparado com a cadeia "xyz1234abcd". Vemos que a subcadeia 1234 corresponde ao padrão. Portanto, $champs[0] será igual a "1234". Além disso, o padrão contém subpadrões entre parênteses. Teremos $champs[1]="1234";
- linha 13: o padrão /(\d+)/ é comparado com a cadeia "12 34". Vemos que as subcadeias 12 e 34 correspondem ao padrão. A comparação pára na primeira subcadeia que corresponde ao padrão. Portanto, $champs[0]=12 e $champs[1]=12;
- linha 14: o padrão /(\d+)/ é comparado com a cadeia "abcd". Não é encontrada nenhuma correspondência;
Vamos explicar os padrões utilizados no resto do código:
$modèle = "/^(.*?)(\d+)(.*?)$/";
corresponde ao início da cadeia (^), seguido de zero ou mais (*) caracteres arbitrários (.), depois um ou mais (+) dígitos, seguidos de zero ou mais (*) caracteres arbitrários (.). O padrão (.*) corresponde a zero ou mais caracteres arbitrários. Um padrão deste tipo corresponderá a qualquer cadeia de caracteres. Assim, o padrão /^(.*)(\d+)(.*)$/ nunca será encontrado porque o primeiro subpadrão (.*) consumirá toda a cadeia de caracteres. O padrão (.*?)(\d+) denota 0 ou mais caracteres arbitrários até ao próximo subpadrão (?), neste caso \d+. Portanto, os dígitos já não são capturados pelo padrão (.*). O padrão acima corresponde, assim, a [início da cadeia (^), uma sequência de quaisquer caracteres (.*?), uma sequência de um ou mais dígitos (\d+), uma sequência de quaisquer caracteres (.*?), fim da cadeia ($)].
$modèle = "/^\s*(\d\d)\/(\d\d)\/(\d\d)\s*$/";
corresponde a [início da cadeia (^), 2 dígitos (\d\d), o caractere / (\/), 2 dígitos, /, 2 dígitos, uma sequência de 0 ou mais espaços (\s*), fim da cadeia ($)].
$modèle = "/^\s*([+|-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*/";
corresponde ao início da cadeia (^), 0 ou mais espaços (\s*), um sinal + ou - [+|-] que ocorre 0 ou 1 vez (?), uma sequência de 0 ou mais espaços (\s*), 1 ou mais dígitos seguidos de um ponto decimal seguido de zero ou mais dígitos (\d+\.\d*) ou (|) um ponto decimal (\.) seguido de um ou mais dígitos (\d+) ou (|) um ou mais dígitos (\d+), uma sequência de 0 ou mais espaços (\s*)].
Nota: O termo [espaço] em expressões regulares refere-se a um conjunto de caracteres: espaço em branco, nova linha \n, tabulação \t, retorno de carro \r, avanço de página \f…
3.8. Funções
3.8.1. Modo de passagem de parâmetros
O script [base-12.php] é o seguinte:
<?php
// function parameter step mode
// strict adherence to parameter type
declare(strict_types=1);
function f(int &$i, int $j): void {
// $i will be obtained by reference
// $j will be obtained by value
$i++;
$j++;
print "f[i,j]=[$i,$j]\n";
}
// tests
$i = 0;
$j = 0;
// $i and $j are passed to function f
f($i, $j);
print "test[i,j]=[$i,$j]\n";
Resultados:
Comentários
O código acima demonstra as duas formas de passar parâmetros a uma função. Considere o seguinte exemplo:
- linha 1: define os parâmetros formais $a e $b da função f. Esta função manipula estes dois parâmetros formais e devolve um resultado;
- linha 7: chama a função f com dois parâmetros reais $i e $j. As relações entre os parâmetros formais ($a, $b) e os parâmetros reais ($i, $j) são definidas pelas linhas 1 e 7:
- &$a: o símbolo & indica que o parâmetro formal $a assumirá o valor do endereço do parâmetro real $i. Por outras palavras, $a e $i são duas referências à mesma localização na memória. Manipular o parâmetro formal $a é equivalente a manipular o parâmetro real $i. Isto é demonstrado pela execução do código. Este modo de passagem é adequado para parâmetros de saída e grandes conjuntos de dados, tais como matrizes e dicionários. Este modo de passagem é chamado de passagem por referência.
- $b: O parâmetro formal $b assumirá o valor do parâmetro real $j. Trata-se de passagem por valor. Os parâmetros formais e reais são duas variáveis diferentes. Manipular o parâmetro formal $b não tem efeito sobre o parâmetro real $j. Isto é demonstrado pela execução do código. Este modo de passagem é adequado para parâmetros de entrada.
- Considere a função swap, que recebe dois parâmetros formais $a e $b. A função troca os valores destes dois parâmetros. Assim, durante uma chamada a swap($i,$j), o código de chamada espera que os valores dos dois parâmetros reais sejam trocados. Estes são, portanto, parâmetros de saída (são modificados). Escreveremos, portanto:
O seguinte script [base-13.php] mostra outros exemplos:
<?php
// types in strict mode
// declare(strict_types = 1);
// parameter switching mode
function f(&$i, $j) {
// $i will be obtained by reference
// $j will be obtained by value
$i++;
$j++;
print "f[i,j]=[$i,$j]\n";
}
function g(int &$i, int $j) : void {
// $i will be obtained by reference
// $j will be obtained by value
$i++;
$j++;
print "g[i,j]=[$i,$j]\n";
}
// tests
$i = 0;
$j = 0;
// $i and $j are passed to function f
f($i, $j);
print "test[i,j]=[$i,$j]\n";
// $i and $j are passed to function g
g($i, $j);
print "test[i,j]=[$i,$j]\n";
// pass incorrect parameters to f
$a=5.3;
$b=6.2;
f($a, $b);
print "test[a,b]=[$a,$b]\n";
// pass incorrect parameters to 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 discutida na secção anterior, mas os parâmetros não são tipados;
- linhas 16–22: a função g faz o mesmo que a função f, mas especificamos o tipo dos parâmetros esperados — esta é uma nova funcionalidade do PHP 7. Esperamos dois parâmetros do tipo int. Queremos ver o que acontece quando o parâmetro real passado para a função não tem o tipo esperado pela função;
- linhas 25–26: $i e $j são dois inteiros;
- linhas 28–29: chamada à função f com parâmetros do tipo esperado;
- linhas 31–32: chamada à 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 à função f com parâmetros que não são do tipo esperado;
- linhas 41-42: chamada à 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 ambos os parâmetros do tipo float e trabalhou com eles;
- As linhas 7–8 mostram que a função `g` aceitou ambos os parâmetros do tipo `float`, mas converteu-os para o tipo `int` (linha 7);
Agora vamos descomentar a linha 4:
Esta instrução especifica que os tipos dos parâmetros formais devem ser respeitados. Se tal não for o caso, é reportado um erro. Os resultados da execução passam então 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` era do tipo errado. Recomenda-se ser rigoroso quanto aos tipos de parâmetros sempre que possível para detetar erros de chamada de função;
3.8.2. Resultados devolvidos por uma função
O script [base-15.php] é o seguinte:
<?php
// types in strict mode
declare(strict_types=1);
// results rendered by a function
// a function can return several values in an 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";
}
// a function can render an object
$res = f2(10);
print "f2 : [$res->res1,$res->res2,$res->res3]\n";
// what kind of object?
print "nature de l'objet : ";
var_dump($res);
print "\n";
// we do the same with the f3 function
$res = f3(10);
print "f3 : [$res->res1,$res->res2,$res->res3]\n";
// what kind of object?
print "nature de l'objet : ";
var_dump($res);
print "\n";
// end
exit;
// function f1
function f1(int $valeur): array {
// returns an array ($valeur+1,$valeur+2,$valeur+3)
return array($valeur + 1, $valeur + 2, $valeur + 3);
}
// function f2
function f2(int $valeur): object {
// renders an object ($valeur+1,$valeur+2,$valeur+3)
$res->res1 = $valeur + 1;
$res->res2 = $valeur + 2;
$res->res3 = $valeur + 3;
// makes the object
return $res;
}
// function f3 - does the same thing as function f2
function f3(int $valeur): object {
// renders an object ($valeur+1,$valeur+2,$valeur+3)
$res = new stdclass();
$res->res1 = $valeur + 1;
$res->res2 = $valeur + 2;
$res->res3 = $valeur + 3;
// makes the object
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 devolver um conjunto de resultados em vez de um único, na forma de uma matriz ou de um objeto. O conceito de objeto é explicado com mais detalhe abaixo;
- linhas 35–38: a função f1 devolve vários valores na forma de um array;
- linhas 41–48: a função f2 devolve vários valores na forma de um objeto;
- linhas 51–59: a função f3 é idêntica à função f2, exceto pelo facto de criar explicitamente um objeto na linha 53;
- A linha 6 dos resultados exibe um aviso indicando que o PHP foi forçado a criar um objeto 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 revela o tipo do objeto e o seu conteúdo. Nos resultados, vemos que:
- linha 8: o objeto padrão é do tipo stdClass;
- linhas 9–10: a propriedade res1 é do tipo inteiro e tem o valor 11;
- etc…
- Para evitar o aviso na linha 6 dos resultados, criamos explicitamente, na linha 53 da função f3, um objeto do tipo stdClass;
3.9. Ficheiros de texto
O script [bases-16.php] é o seguinte:
<?php
// strict adherence to function parameter types
declare (strict_types=1);
// sequential operation of a text file
// this is a set of lines of the form login:pwd:uid:gid:infos:dir:shell
// each line is put into a dictionary in the form login => uid:gid:infos:dir:shell
// set the file name
$INFOS = "infos.txt";
// we open it in creation
if (!$fic = fopen($INFOS, "w")) {
print "Erreur d'ouverture du fichier $INFOS en écriture\n";
exit;
}
// generate arbitrary content
for ($i = 0; $i < 100; $i++) {
fputs($fic, "login$i:pwd$i:uid$i:gid$i:infos$i:dir$i:shell$i\n");
}
// close the file
fclose($fic);
// we use it - fgets keeps the end-of-line marker
// this prevents the retrieval of an empty string when reading a blank line
// open it for reading
if (!$fic = fopen($INFOS, "r")) {
print "Erreur d'ouverture du fichier $INFOS en lecture\n";
exit;
}
// lines are less than 1000 characters long
// line reading stops at the end-of-line mark
// or the end-of-file
while ($ligne = fgets($fic, 1000)) {
// delete the end-of-line marker if it exists
$ligne = cutNewLineChar($ligne);
// put the line in a table
$infos = explode(":", $ligne);
// retrieve login
$login = array_shift($infos);
// we neglect the pwd
array_shift($infos);
// create a dictionary entry
$dico[$login] = $infos;
}
// close it
fclose($fic);
// using the dictionary
afficheInfos($dico, "login10");
afficheInfos($dico, "X");
// end
exit;
// --------------------------------------------------------------------------
function afficheInfos(array $dico, string $clé): void {
// displays the value associated with key in the $dico dictionary if it exists
if (isset($dico[$clé])) {
// value exists - is it a painting?
$valeur = $dico[$clé];
if (is_array($valeur)) {
print "[$clé," . join(":", $valeur) . "]\n";
} else {
// $valeur is not an array
print "[$clé,$valeur]\n";
}
} else {
// $clé is not a key in the $dico dictionary
print "la clé [$clé] n'existe pas\n";
}
}
// --------------------------------------------------------------------------
function cutNewLinechar(string $ligne): string {
// delete the end-of-line mark from $ligne if it exists
$L = strlen($ligne); // line length
while (substr($ligne, $L - 1, 1) == "\n" or substr($ligne, $L - 1, 1) == "\r") {
$ligne = substr($ligne, 0, $L - 1);
$L--;
}
// end
return($ligne);
}
O ficheiro infos.txt:
Os resultados:
[login10,uid10:gid10:infos10:dir10:shell10]
la clé [X] n'existe pas
Comentários
- Linha 12: fopen(filename, "w") abre o ficheiro filename para escrita (w=write). Se o ficheiro não existir, é criado. Se existir, é apagado. Se a criação falhar, fopen devolve false. Na instrução if (!$fic = fopen($INFOS, "w")) {…}, há duas operações sucessivas: 1) $fic=fopen(..) 2) if( ! $fic) {…} ;
- linha 18: fputs($fic,$string) escreve string no ficheiro $fic. $string é escrita com o caractere de nova linha \n no final;
- linha 21: fclose($fic) fecha o ficheiro $fic;
- linha 26: fopen(filename,"r") abre o ficheiro filename para leitura (r=read). Se a abertura falhar (por exemplo, se o ficheiro não existir), fopen retorna false;
- linha 34: fgets($fic,1000) lê a linha seguinte do ficheiro, limitada a 1000 caracteres. No ciclo while ($line = fgets($fic, 1000)) {…}, existem duas operações sucessivas: 1) $line = fgets(…) 2) while ( ! $line). Após a leitura do último caractere do ficheiro, a função fgets retorna false e o ciclo while termina. Aqui, a função fgets tenta ler até 1000 caracteres, mas pára assim que encontra um caractere de fim de linha. Como todas as linhas aqui têm menos de 1000 caracteres, [fgets] lê uma linha de texto, incluindo o caractere de fim de linha. A função cutNewLineChar nas linhas 75–84 remove quaisquer caracteres de fim de linha;
- linha 77: a função strlen($string) retorna o número de caracteres em $string;
- linha 78: a função substr($line, $position, $size) retorna $size caracteres de $line, a partir do caractere #$position, onde o primeiro caractere é #0. Em máquinas Windows, o caractere de fim de linha é "\r\n". Em máquinas Unix, é a string "\n";
- linha 40: a função array_shift($array) remove o primeiro elemento de $array e devolve-o como resultado. Aqui, ignoramos o resultado devolvido por array_shift;
- Linha 62: A função is_array($variable) retorna true se $variable for uma matriz, false caso contrário;
- linha 63: a função join faz o mesmo que a função implode que vimos anteriormente;
3.10. Codificação/Decodificação JSON

A codificação/decodificação JSON (JavaScript Object Notation) é algo que utilizaremos extensivamente no exercício que serve de tema central deste documento. Os scripts [json-01.php, json-02.php, json-03.php] explicam o que precisa de saber para o resto do documento.
O script [json-01.php] é o seguinte:
<?php
$array1 = ["nom" => "séléné", "prénom" => "bénédicte", "âge" => 34];
// json encoding of array1 with escaped Unicode characters
print "encodage json du tableau array1 avec caractères Unicode échappés\n";
$json1 = json_encode($array1);
print "json1=$json1\n";
// json encoding of array1 with unescaped Unicode characters
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";
// decoding jSON in associative array
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";
}
// decoding jSON in object
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] converte o seu parâmetro numa cadeia JSON;
- Linha 2 dos resultados: a cadeia JSON gerada. Os caracteres Unicode éâ foram substituídos pelos seus códigos Unicode, que começam por \u;
- Linha 10 do código: fazemos o mesmo, mas desta vez solicitamos que os caracteres Unicode sejam preservados tal como estão;
- Linha 4 dos resultados: a cadeia JSON resultante. É muito mais legível;
- Linhas 14–18 do código: Realizamos a operação inversa. Convertemos uma string JSON numa matriz associativa;
- linhas 6–13 dos resultados: vemos que recuperámos uma matriz associativa;
- linhas 19–25 do código: convertemos uma string JSON num objeto do tipo [stdClass];
- linhas 18–25 dos resultados: vemos que recuperámos um objeto do tipo [stdClass];
- linhas 23–25 do código: o atributo A de um objeto O é denotado por [O→A];
Podemos codificar matrizes multinível em JSON, conforme ilustrado no 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],
]];
// encoding jSON of the multi-level array
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 cadeia JSON:
- os tabuleros não associativos são colocados entre colchetes [] ;
- os tabuleros associativos são colocados entre chaves {};
O script [json-03.php] mostra como processar o seguinte ficheiro JSON [family.json]:
{
"é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
// reading the jSON file
$json = file_get_contents("famille.json");
// json object decoding
$famille1 = json_decode($json);
print "----famille1\n";
var_dump($famille1);
// json decoding in associative array
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 ficheiro denominado [family.json] e armazena-o na variável [$json];
- A variável é então descodificada num objeto (linhas 5–8) e numa matriz 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 descodificação do ficheiro JSON [family.json];
- linhas 39-76: o array associativo resultante da descodificação do ficheiro JSON [family.json];