3. Conceptos básicos de PHP
3.1. La estructura de los scripts

3.2. Configuración de PHP
PHP viene preconfigurado mediante un archivo de texto llamado [php.ini]. Todas estas configuraciones se pueden modificar mediante programación. La configuración de PHP influye en gran medida en la ejecución de los scripts. Por lo tanto, es importante conocerla. El siguiente script [phpinfo.php] lo permite:
Comentarios
- línea 3: la función [phpinfo] muestra la configuración de PHP;
Resultados de la ejecución
La función [phpinfo] muestra aquí más de 800 líneas de configuración. No las comentaremos, ya que la mayoría se refiere a un uso avanzado de PHP. Una línea importante es la línea 13 anterior: indica qué archivo [php.ini] se utilizó para configurar el PHP que vas a utilizar para ejecutar tus scripts. Si quieres modificar la configuración de ejecución de PHP, es este archivo el que debes modificar. En este archivo hay numerosos comentarios que explican la función de las diferentes configuraciones.
3.3. Un primer ejemplo
3.3.1. El código
A continuación, encontrarás un programa [bases-01.php] que presenta las primeras características de PHP.
<?php
// esto es un comentario
// variable utilizada sin haber sido declarada
$nom = "dupont";
// una salida a pantalla
print "nom=$nom\n";
// una matriz con elementos de diferentes tipos
$tableau = array("un", "deux", 3, 4);
// su número de elementos
$n = count($tableau);
// un bucle
for ($i = 0; $i < $n; $i++) {
print "tableau[$i]=$tableau[$i]\n";
}
// inicialización de 2 variables con el contenido de un array
list($chaine1, $chaine2) = array("chaine1", "chaine2");
// concatenación de las dos cadenas
$chaine3 = $chaine1 . $chaine2;
// visualización del resultado
print "[$chaine1,$chaine2,$chaine3]\n";
// uso de una función
affiche($chaine1);
// se puede conocer el tipo de una variable
afficheType("n", $n);
afficheType("chaine1", $chaine1);
afficheType("tableau", $tableau);
// el tipo de una variable puede cambiar durante la ejecución
$n = "a changé";
afficheType("n", $n);
// una función puede devolver un resultado
$res1 = f1(4);
print "res1=$res1\n";
// una función puede devolver una matriz de valores
list($res1, $res2, $res3) = f2();
print "(res1,res2,res3)=[$res1,$res2,$res3]\n";
// se podrían haber recuperado estos valores en una matriz
$t = f2();
for ($i = 0; $i < count($t); $i++) {
print "t[$i]=$t[$i]\n";
}
// pruebas
for ($i = 0; $i < count($t); $i++) {
// solo muestra las cadenas
if (getType($t[$i]) === "string") {
print "t[$i]=$t[$i]\n";
}
}
// operadores de comparación == y ===
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";
}
// otras pruebas
for ($i = 0; $i < count($t); $i++) {
// solo muestra los números enteros >10
if (getType($t[$i]) === "integer" and $t[$i] > 10) {
print "t[$i]=$t[$i]\n";
}
}
// un bucle 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
}//mientras
print "somme=$somme\n";
// fin del programa
exit;
//----------------------------------
function affiche($chaine) {
// muestra $chaine
print "chaine=$chaine\n";
}
//muestra
//----------------------------------
function afficheType($name, $variable) {
// muestra el tipo de $variable
print "type[variable $" . $name . "]=" . getType($variable) . "\n";
}
//afficheType
//----------------------------------
function f1($param) {
// suma 10 a $param
return $param + 10;
}
//----------------------------------
function f2() {
// devuelve 3 valores
return array("un", 0, 100);
}
?>
Los 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
Comentarios
- línea 5: en PHP, no se declara el tipo de las variables. Estas tienen un tipo dinámico que puede variar con el tiempo. $nom representa la variable de identificador «nombre»;
- línea 7: para escribir en pantalla, se puede usar la instrucción print o la instrucción echo;
- línea 9: la palabra clave array permite definir un array. La variable $nom[$i] representa el elemento $i de la matriz $tableau;
- línea 11: la función count($tableau) devuelve el número de elementos de la matriz $tableau;
- líneas 13-15: un bucle. Como este solo tiene una instrucción, las llaves son opcionales. En el resto de este documento, utilizaremos sistemáticamente las llaves, independientemente del número de instrucciones;
- línea 14: las cadenas de caracteres se escriben entre comillas " o apóstrofos '. Dentro de las comillas, las variables $variable se evalúan, pero no así dentro de los apóstrofos;
- línea 17: la función list permite reunir variables en una lista y asignarles un valor con una sola operación de asignación. Aquí, $chaine1="cadena1" y $chaine2="cadena2";
- línea 19: el operador . es el operador de concatenación de cadenas;
- líneas 83-86: la palabra clave function define una función. Una función devuelve o no valores mediante la instrucción return. El código que la invoca puede ignorar o recuperar los resultados de una función. Una función puede definirse en cualquier parte del código.
- línea 92: la función predefinida getType($variable) devuelve una cadena de caracteres que representa el tipo de $variable. Este tipo puede cambiar con el tiempo;
- línea 45: el operador === compara dos elementos de manera estricta: deben ser del mismo tipo para poder compararse. El operador == es menos estricto: dos elementos pueden ser iguales sin ser del mismo tipo. Esto es lo que muestran las instrucciones de las líneas 50 a 60. En el caso del operador ==, la comparación se realiza después de convertir ambos elementos comparados al mismo tipo. En ese momento se producen conversiones implícitas. Es bastante fácil «olvidarse» de la presencia de estas conversiones implícitas y, por lo tanto, obtener resultados imprevistos, como descubrir que una condición es verdadera cuando esperabas que fuera falsa. Para evitar este problema, utilizaremos sistemáticamente el operador de comparación ===;
- línea 64: también se pueden utilizar los operadores booleanos or y !;
- línea 69: en lugar de la notación array(), se puede usar la notación [] para inicializar un array desde PHP7;
- línea 80: la función predefinida exit detiene la ejecución del script;
- línea 107: la etiqueta ?> marca el final del script PHP. No es imprescindible. Además, en un contexto web, puede causar problemas si va seguida de espacios o caracteres de fin de línea, que son difíciles de detectar porque no son visibles en un editor de texto. Por lo tanto, en el resto del documento omitiremos sistemáticamente esta etiqueta;
Nota: en este documento, utilizaremos la palabra clave [print] para mostrar texto en la consola. Otro método para hacer lo mismo es utilizar la palabra clave [echo]. Existen diferencias sutiles entre estas dos palabras clave, pero en el contexto de este documento no habrá ninguna. Así que, si prefieres usar [echo], hazlo.
3.3.2. Uso de NetBeans
NetBeans muestra varias advertencias que conviene revisar. Tomemos como ejemplo el script [bases-01.php]:

En la línea 5, NetBeans emite una advertencia indicando que el archivo no cumple con la recomendación PSR-1 (Recomendaciones estándar n.º 1 de PHP). Las PSR son recomendaciones para generar código estándar y así facilitar la interoperabilidad y el mantenimiento de códigos escritos por diferentes personas. Puede resultar molesto recibir advertencias si se desea incumplir deliberadamente los estándares, por ejemplo, porque el equipo del proyecto tiene otros. Lo que se desea verificar o no con NetBeans es configurable:

- en [5], se encuentran los elementos que se quieren verificar con NetBeans;
- en [6], el nivel de gravedad asignado al error señalado por NetBeans;

En [7] se observa que se ha solicitado verificar que el código cumpla con las recomendaciones PSR-0 y PSR-1. No hay nada obligatorio. Durante la fase de aprendizaje del lenguaje, se recomienda verificar la mayor cantidad posible de opciones que ofrece NetBeans. Así se aprende mucho. Posteriormente, se adaptará esta verificación de NetBeans a las normas de codificación del equipo de un proyecto.
Veamos las normas de codificación PSR-1 y [8, 9]:
Opción | Control |
| Las constantes de clase MUST deben declararse en mayúsculas con separadores de guión bajo. Ej.: const TAUX_TVA |
| Los nombres de los métodos MUST deben declararse en camelCase(). Ejemplo: public function executeBatchImpots{} |
| Los nombres de las propiedades SHOULD deben declararse en el formato $StudlyCaps, $camelCase o $under_score (de manera consistente dentro de un ámbito) Ejemplo: public SalaireAnnuel (StudlyCaps), public salaireAnnuel (camelCase), public salaire_annuel (under_score) |
| Un archivo SHOULD declara nuevos símbolos y no causa otros efectos secundarios, o bien SHOULD ejecuta lógica con efectos secundarios, pero SHOULD NOT hace ambas cosas. |
| Los nombres de tipo MUST deben declararse en StudlyCaps (El código escrito para 5.2.x y versiones anteriores a SHOULD utiliza la convención de espacio de nombres pseudónimo con prefijos de Vendor_ en los nombres de los tipos). Cada tipo se encuentra en un archivo propio y está en un espacio de nombres de al menos un nivel: un nombre de proveedor de nivel superior. Ejemplo: class EtudiantBoursier {} |
La recomendación PSR-1 / 4 establece que en un archivo PHP debe encontrarse:
- o bien la declaración de un tipo (clases, interfaz);
- o bien código ejecutable sin declaración de nuevos tipos;
Existen otras recomendaciones PHP que no son verificadas por NetBeans: PSR-3, PSR-4, PSR-6, PSR-7 y PSR-13.
Por razones de simplicidad, no todos los ejemplos del documento cumplen con la recomendación PSR-1, ya que esto obliga a distribuir el código de las clases e interfaces en archivos separados, lo cual resulta demasiado complicado para ejemplos básicos. Por lo tanto, es más sencillo poner todo en un solo archivo. Para el ejemplo de la aplicación que sirve de hilo conductor de este documento, se ha procurado seguir lo más fielmente posible la recomendación PSR-1.
Algunas advertencias de NetBeans señalan un posible error:

La advertencia [Unitialized Variables] indica un error probable, a menudo un error tipográfico en el nombre de una variable. Lo mismo ocurre con la advertencia [Unused Variables].
Por último, se recomienda revisar todas las advertencias de NetBeans, que se indican mediante un panel en el margen izquierdo del código y un guion amarillo en el margen derecho:


3.4. El alcance de las variables
3.4.1. Ejemplo 1
El script [bases-02.php] es el siguiente:
<?php
// alcance de las variables
function f1() {
// se utiliza la variable global $i
global $i;
$i++;
$j = 10;
print "f1[i,j]=[$i,$j]\n";
}
function f2() {
// se utiliza la variable global $i
global $i;
$i++;
$j = 20;
print "f2[i,j]=[$i,$j]\n";
}
function f3() {
// se utiliza una variable local $i
$i = 4;
$j = 30;
print "f3[i,j]=[$i,$j]\n";
}
// pruebas
$i = 0;
$j = 0; // estas dos variables no son conocidas por una función f
// a menos que esta las declare explícitamente mediante la instrucción global
// que desea utilizarlas
f1();
f2();
f3();
print "test[i,j]=[$i,$j]\n";
Los resultados:
Comentarios
- líneas 29-30: definen dos variables, $i y $j, del programa principal. Estas variables no son reconocidas dentro de las funciones. Así, en la línea 9, la variable $j de la función f1 es una variable local de la función f1 y es diferente de la variable $j del programa principal. Una función puede acceder a una variable $variable del programa principal mediante la palabra clave global;
- en la línea 7, la instrucción hace referencia a la variable global $i del programa principal;
3.4.2. Ejemplo 3
El script [bases-03.php] es el siguiente:
<?php
// el alcance de una variable es global a los bloques de código
$i = 0; {
$i = 4;
$i++;
}
print "i=$i\n";
Los resultados:
Comentarios
En algunos lenguajes, una variable definida dentro de llaves tiene el alcance de estas: no es conocida fuera de ellas. Los resultados anteriores muestran que esto no es así en PHP. La variable $i definida en la línea 5 dentro de las llaves es la misma que la utilizada en las líneas 4 y 8 fuera de ellas.
3.5. Los cambios de tipo
Las variables en PHP no tienen un tipo constante. Este puede cambiar durante la ejecución según el valor asignado a la variable. En operaciones que involucran datos de diversos tipos, el intérprete PHP realiza conversiones implícitas para convertir los operandos a un tipo común. Estas conversiones implícitas, si el desarrollador no las conoce, pueden ser una fuente de errores difíciles de detectar. A continuación se presenta un script [bases-04.php] que muestra conversiones implícitas y explícitas:
<?php
// tipos estrictos en el paso de parámetros
declare(strict_types=1);
// cambios implícitos de tipo
// 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 : ";
// la conversión de $var a booleano se realiza automáticamente en la prueba siguiente
if ($var) {
print "true";
} else {
print "false";
}
print "\n";
}
Comentarios
- línea 4: solicita una verificación estricta del tipo de los parámetros de una función cuando este se especifica;
- línea 18: la función [showBool] tiene como objetivo mostrar la transformación implícita (automática) que realiza el intérprete PHP cuando un valor de cualquier tipo debe transformarse en un valor booleano (línea 21);
- línea 18: al parámetro $var no se le ha asignado ningún tipo. Por lo tanto, el parámetro efectivo podrá ser de cualquier tipo. El parámetro $prefixe, por su parte, deberá ser de tipo cadena. La función showBool no devuelve ningún valor (void);
- línea 21: en la instrucción if($var), el valor de $var debe transformarse en un valor booleano para que se evalúe if. Sorprendentemente, el intérprete PHP tiene una respuesta para cualquier tipo de valor que se le proporcione;
- líneas 9-16: el valor del parámetro de la función [showBool] será sucesivamente:
- línea 9: una cadena no vacía: resultado TRUE (no importa si se escribe en mayúsculas o minúsculas, TRUE = verdadero);
- línea 10: una cadena vacía: resultado FALSE;
- línea 11: un array no vacío: resultado TRUE;
- línea 12: un array vacío: resultado FALSE;
- línea 14: el número real 0: resultado FALSE;
- línea 15: el número entero 0: resultado FALSE;
- línea 16: el número real (o entero) distinto de 0: resultado TRUE;
Esto es lo que muestran las pantallas obtenidas:
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
Continuemos con el código del script:
//
// cambios implícitos de tipo cadena a tipo numérico
// cadena --> 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";
}
Comentarios
- línea 9: la función [showNumber] admite un parámetro de tipo cadena y no devuelve ningún resultado (void);
- línea 10: este parámetro se utiliza en una operación aritmética, lo que obligará al intérprete PHP a intentar convertir $var en un número;
- línea 5: convertirá la cadena «12» en el número entero 12;
- línea 6: convertirá la cadena «45.67» en el número real 45.67;
- línea 7: emitirá una advertencia, pero de todos modos convertirá la cadena «abcd» en el número 0;
Estos son los resultados de la ejecución:
Continuemos con el código del script:
// Cambios explícitos de tipo
// a entero
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";
}
Comentarios
- línea 21: la función [showInt] recibe un parámetro de cualquier tipo y no devuelve ningún resultado. Intenta convertir el parámetro $var en un entero en la línea 26. En general, para convertir una variable $var a un tipo T, se escribe (T) $var, donde T puede ser: int, integer, bool, boolean, float, double, real, string, array, object, unset;
- línea 16: convierte la cadena “12.45” en un entero 12;
- línea 17: convierte el número real 67.8 en el entero 67;
- línea 18: convierte el valor booleano TRUE en el entero 1 (el valor booleano FALSE en el entero 0);
- línea 19: convierte el puntero NULL en el entero 0;
Esto es lo que muestran las pantallas:
Continuamos el análisis del script con la conversión explícita de valores al tipo float:
// a 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";
}
Comentarios
- línea 35: la función [showFloat] recibe un parámetro de cualquier tipo y no devuelve ningún resultado;
- línea 40: el valor de este parámetro se transforma explícitamente en float;
- línea 30: la cadena «12.45» se transforma en el número real 12.45;
- línea 31: el entero 67 se transforma en el número real 67;
- línea 32: el valor booleano TRUE se transforma en el número real 1 (el valor FALSE se transforma en el número 0);
- línea 33: el puntero NULL se transforma en el número real 0;
Esto es lo que muestran los resultados en pantalla:
Continuamos con la presentación del script analizando las conversiones al tipo string:
// a cadena
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";
}
- línea 49: la función [showString] recibe un parámetro de cualquier tipo y no devuelve ningún resultado;
- línea 54: el valor del parámetro se transforma en un tipo de cadena;
- línea 44: el entero 5 se transformará en la cadena «5»;
- línea 45: el número real 6.7 se convertirá en la cadena «6.7»;
- línea 46: el valor booleano FALSE se convertirá en una cadena vacía;
- línea 47: el puntero NULL se convertirá en una cadena vacía;
Estos son los resultados en pantalla:
3.6. Las tablas
3.6.1. Matrices clásicas unidimensionales
El script [bases-05.php] es el siguiente:
<?php
// matrices clásicas
// inicialización
$tab1 = array(0, 1, 2, 3, 4, 5);
// recorrido - 1
print "tab1 a " . count($tab1) . " éléments\n";
for ($i = 0; $i < count($tab1); $i++) {
print "tab1[$i]=$tab1[$i]\n";
}
// recorrido - 2
print "tab1 a " . count($tab1) . " éléments\n";
reset($tab1);
while (list($clé, $valeur) = each($tab1)) {
print "tab1[$clé]=$valeur\n";
}
// agregación de elementos
$tab1[] = $i++;
$tab1[] = $i++;
// recorrido - 3
print "tab1 a " . count($tab1) . " éléments\n";
$i = 0;
foreach ($tab1 as $élément) {
print "tab1[$i]=$élément\n";
$i++;
}
// eliminación del último elemento
array_pop($tab1);
// recorrido - 4
print "tab1 a " . count($tab1) . " éléments\n";
for ($i = 0; $i < count($tab1); $i++) {
print "tab1[$i]=$tab1[$i]\n";
}
// eliminación del primer elemento
array_shift($tab1);
// recorrido - 5
print "tab1 a " . count($tab1) . " éléments\n";
for ($i = 0; $i < count($tab1); $i++) {
print "tab1[$i]=$tab1[$i]\n";
}
// agregar al final de la tabla
array_push($tab1, -2);
// recorrido - 6
print "tab1 a " . count($tab1) . " éléments\n";
for ($i = 0; $i < count($tab1); $i++) {
print "tab1[$i]=$tab1[$i]\n";
}
// agregar al inicio de la tabla
array_unshift($tab1, -1);
// recorrido - 7
print "tab1 a " . count($tab1) . " éléments\n";
for ($i = 0; $i < count($tab1); $i++) {
print "tab1[$i]=$tab1[$i]\n";
}
Los 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
Comentarios
El programa anterior muestra operaciones de manipulación de una tabla de valores. Existen dos formas de escribir las tablas en PHP:
La tabla 1 se denomina tabla y la tabla 2, diccionario o tabla asociativa, donde los elementos se escriben clave => valor. La notación $contraires["beau"] designa el valor asociado a la clave «guapo». En este caso, es la cadena «feo». La tabla 1 no es más que una variante del diccionario y podría escribirse así:
Así, tenemos $tableau[2] = «tres». En definitiva, solo hay diccionarios. En el caso de una matriz clásica de n elementos, las claves son los números enteros del intervalo [0,n-1].
- línea 14: la función each($tableau) permite recorrer un diccionario. En cada llamada, devuelve un par (clave, valor) del mismo. Como se muestra en la línea 10 de los resultados, la función each ya está obsoleta en PHP 7;
- línea 13: la función reset($dictionnaire) establece la función each en el primer par (clave, valor) del diccionario.
- línea 14: el bucle while se detiene cuando la función each devuelve un par vacío al final del diccionario. Aquí se aplica una conversión implícita: el par vacío se convierte en el valor booleano FALSE;
- línea 18: la notación $tableau[]=valor agrega el elemento valeur como último elemento de $tableau;
- línea 23: se recorre el array con un foreach. Este elemento sintáctico permite recorrer un diccionario, y por lo tanto un array, según dos sintaxis:
La primera sintaxis devuelve un par (clé,valeur) en cada iteración, mientras que la segunda sintaxis solo devuelve el elemento valeur del diccionario.
- línea 28: la función array_pop($tableau) elimina el último elemento de $tableau;
- línea 35: la función array_shift($tableau) elimina el primer elemento de $tableau;
- línea 42: la función array_push($tableau,valor) agrega valeur como último elemento de $tableau;
- línea 49: la función array_unshift($tableau,valor) agrega valeur como primer elemento de $tableau;
3.6.2. El diccionario o tabla asociativa
El script [bases-06.php] es el siguiente:
<?php
// diccionarios
$conjoints = ["Pierre" => "Gisèle", "Paul" => "Virginie", "Jacques" => "Lucette", "Jean" => ""];
// recorrido - 1
print "Nombre d'éléments du dictionnaire : " . count($conjoints) . "\n";
reset($conjoints);
while (list($clé, $valeur) = each($conjoints)) {
print "conjoints[$clé]=$valeur\n";
}
// ordenación del diccionario por la clave
ksort($conjoints);
// recorrido - 2
reset($conjoints);
while (list($clé, $valeur) = each($conjoints)) {
print "conjoints[$clé]=$valeur\n";
}
// lista de claves del diccionario
$clés = array_keys($conjoints);
for ($i = 0; $i < count($clés); $i++) {
print "clés[$i]=$clés[$i]\n";
}
// lista de valores del diccionario
$valeurs = array_values($conjoints);
for ($i = 0; $i < count($valeurs); $i++) {
print "valeurs[$i]=$valeurs[$i]\n";
}
// búsqueda de una clave
existe($conjoints, "Jacques");
existe($conjoints, "Lucette");
existe($conjoints, "Jean");
// eliminación de una clave-valor
unset($conjoints["Jean"]);
print "Nombre d'éléments du dictionnaire : " . count($conjoints) . "\n";
foreach ($conjoints as $clé => $valeur) {
print "conjoints[$clé]=$valeur\n";
}
// fin
exit;
function existe($conjoints, $mari) {
// verifica si la clave $mari existe en el diccionario $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";
}
}
Los 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
Comentarios
El código anterior aplica a un diccionario lo que se vio anteriormente para una tabla simple. Solo comentaremos las novedades:
- línea 12: la función ksort (ordenación por clave) permite ordenar un diccionario según el orden natural de la clave;
- línea 19: la función array_keys($dictionnaire) devuelve la lista de claves del diccionario en forma de tabla;
- línea 24: la función array_values($dictionnaire) devuelve la lista de valores del diccionario en forma de tabla;
- línea 43: la función isset($variable) devuelve TRUE si se ha definido la variable $variable; de lo contrario, devuelve FALSE;
- línea 33: la función unset($variable) elimina la variable $variable.
3.6.3. Las tablas multidimensionales
El script [bases-07.php] es el siguiente:
<?php
// tablas multidimensionales clásicas
// inicialización
$multi = array(array(0, 1, 2), array(10, 11, 12, 13), array(20, 21, 22, 23, 24));
// recorrido
for ($i1 = 0; $i1 < count($multi); $i1++) {
for ($i2 = 0; $i2 < count($multi[$i1]); $i2++) {
print "multi[$i1][$i2]=" . $multi[$i1][$i2] . "\n";
}
}
// diccionarios multidimensionales
// inicialización
$multi = array("zéro" => array(0, 1, 2), "un" => array(10, 11, 12, 13), "deux" => array(20, 21, 22, 23, 24));
// recorrido
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
Comentarios
- línea 5: los elementos de la matriz $multi son a su vez matrices;
- línea 14: la tabla $multi se convierte en un diccionario (clé,valeur) donde cada valeur es una tabla;
3.7. Las cadenas de caracteres
3.7.1. Notación
El script [bases-08.php] es el siguiente:
<?php
// notación de cadenas
$chaine1 = "un";
$chaine2 = 'un';
print "[$chaine1,$chaine2]\n";
?>
Resultados:
3.7.2. Comparación
El script [bases-09.php] es el siguiente:
<?php
// cumplimiento estricto del tipo de los parámetros de las funciones
declare(strict_types=1);
// función de comparación
function compareModele2Chaine(string $chaine1, string $chaine2): void {
// compara cadena1 y cadena2
if ($chaine1 === $chaine2) {
print "[$chaine1] est égal à [$chaine2]\n";
} else {
print "[$chaine1] est différent de [$chaine2]\n";
}
}
// pruebas de comparación de cadenas
compareModele2Chaine("abcd", "abcd");
compareModele2Chaine("", "");
compareModele2Chaine("1", "");
exit;
Resultados:
[abcd] est égal à [abcd]
[] est égal à []
[1] est différent de []
Comentarios
- línea 9 del código: se podría haber utilizado el comparador == en lugar de ===. Este último operador es más restrictivo, ya que exige que ambos operandos sean del mismo tipo. Cabe señalar que, en este caso, se podría haber sustituido por el operador ==, ya que el tipo de ambos parámetros está definido como cadena en la firma de la función;
3.7.3. Relaciones entre cadenas y tablas
El script [bases-10.php] es el siguiente:
<?php
// de cadena a matriz
$chaine = "1:2:3:4";
$tab = explode(":", $chaine);
// recorrido por una matriz
print "tab a " . count($tab) . " éléments\n";
for ($i = 0; $i < count($tab); $i++) {
print "tab[$i]=$tab[$i]\n";
}
// de matriz a cadena
$chaine2 = implode(":", $tab);
print "chaine2=$chaine2\n";
// agregamos un campo vacío
$chaine .= ":";
print "chaîne=$chaine\n";
$tab = explode(":", $chaine);
// recorrido por la matriz
print "tab a " . count($tab) . " éléments\n";
for ($i = 0; $i < count($tab); $i++) {
print "tab[$i]=$tab[$i]\n";
} // ahora tenemos 5 elementos, siendo el último vacío
// agregamos nuevamente un campo vacío
$chaine .= ":";
print "chaîne=$chaine\n";
$tab = explode(":", $chaine);
// recorrido por la tabla
print "tab a " . count($tab) . " éléments\n";
for ($i = 0; $i < count($tab); $i++) {
print "tab[$i]=$tab[$i]\n";
} // ahora tenemos 6 elementos, siendo los dos últimos vacíos
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]=
Comentarios
- línea 5: la función explode($séparateur,$chaine) permite recuperar los campos de $chaine separados por $séparateur. Así, explode(":",$chaine) permite recuperar, en forma de matriz, los elementos de $chaine que están separados por la cadena ":";
- línea 12: la función implode($séparateur,$tableau) realiza la operación inversa a la función explode. Devuelve una cadena de caracteres formada por los elementos de $tableau separados por $séparateur;
3.7.4. Las expresiones regulares
El script [bases-11.php] es el siguiente:
<?php
// tipo estricto para los parámetros de las funciones
declare (strict_types=1);
// expresiones regulares en PHP
// extraer los distintos campos de una cadena
// el patrón: una secuencia de dígitos rodeada de cualquier carácter
// solo queremos extraer la secuencia de números
$modèle = "/(\d+)/";
// comparamos la cadena con el patrón
compareModele2Chaine($modèle, "xyz1234abcd");
compareModele2Chaine($modèle, "12 34");
compareModele2Chaine($modèle, "abcd");
// el patrón: una secuencia de números rodeada de caracteres cualquiera
// queremos la secuencia de números, así como los campos que la preceden y la siguen
$modèle = "/^(.*?)(\d+)(.*?)$/";
// se compara la cadena con el patrón
compareModele2Chaine($modèle, "xyz1234abcd");
compareModele2Chaine($modèle, "12 34");
compareModele2Chaine($modèle, "abcd");
// el patrón: una fecha en 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");
// el patrón: un 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");
// fin
exit;
// --------------------------------------------------------------------------
function compareModele2Chaine(string $modèle, string $chaîne): void {
// compara la cadena $chaîne con el patrón $modèle
// se compara la cadena con el patrón
$champs = [];
$correspond = preg_match($modèle, $chaîne, $champs);
// visualización de 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
Comentarios
- Aquí utilizamos expresiones regulares para extraer los distintos campos de una cadena de caracteres. Las expresiones regulares permiten superar las limitaciones de la función implode. El principio consiste en comparar una cadena de caracteres con otra cadena llamada modèle mediante la función preg_match:
$correspond = preg_match($modèle, $chaîne, $champs);
La función preg_match devuelve un valor booleano TRUE si el modèle se puede encontrar en el chaîne. Si es así, $champs[0] representa la subcadena correspondiente a la plantilla. Por otra parte, si modèle contiene submodelos entre paréntesis, $champs[1] es la parte de $chaîne que corresponde al primer submodelo, $champs[2] es la parte de $chaîne que corresponde al segundo submodelo, etc…
Consideremos el primer ejemplo. El patrón se define en la línea 10: designa una secuencia de uno o más (+) dígitos (\d) ubicados en cualquier lugar de una cadena. Además, el patrón define un subpatrón entre paréntesis;
- línea 12: el patrón /(\d+)/ (secuencia de uno o más dígitos en cualquier parte de la cadena) se compara con la cadena "xyz1234abcd". Se observa que la subcadena 1234 coincide con el patrón. Por lo tanto, tendremos que $champs[0] es igual a «1234». Además, el patrón tiene subpatrones entre paréntesis. Tendremos $champs[1] = «1234»;
- línea 13: el patrón /(\d+)/ se compara con la cadena “12 34”. Vemos que las subcadenas 12 y 34 coinciden con el patrón. La comparación se detiene en la primera subcadena que coincide con el patrón. Por lo tanto, tendremos: $champs[0]=12 y $champs[1]=12;
- línea 14: el patrón /(\d+)/ se compara con la cadena «abcd». No se encuentra ninguna coincidencia;
Explicaremos los patrones utilizados en el resto del código:
$modèle = "/^(.*?)(\d+)(.*?)$/";
corresponde al inicio de la cadena (^), seguido de 0 o más (*) caracteres cualquiera (.), luego 1 o más (+) dígitos, y nuevamente 0 o más (*) caracteres cualquiera (.). El patrón (.*) designa 0 o más caracteres cualquiera. Un patrón de este tipo coincidirá con cualquier cadena. Por lo tanto, el patrón /^(.*)(\d+)(.*)$/ nunca se encontrará, ya que el primer subpatrón (.*) absorberá toda la cadena. El patrón (.*?)(\d+) designa 0 o más caracteres cualquiera hasta el subpatrón siguiente (?), en este caso \d+. Por lo tanto, los dígitos ya no son absorbidos por el patrón (.*). El patrón anterior, por lo tanto, coincide con [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 al inicio de la cadena (^), 0 o más espacios (\s*), un signo + o - [+|-] presente 0 o 1 vez (?), una secuencia de 0 o más espacios (\s*), 1 o más dígitos seguidos de un punto decimal y de cero o más dígitos (\d+\.\d*) o (|) un punto decimal (\.) seguido de uno o más dígitos (\d+) o (|) uno o más dígitos (\d+), una secuencia de 0 o más espacios (\s*)].
Nota: el término [espace] en las expresiones regulares se refiere a un conjunto de caracteres: espacio en blanco, salto de línea \n, tabulación \t, retorno de carro \r, salto de página \f…
3.8. Las funciones
3.8.1. Modo de paso de parámetros
El script [base-12.php] es el siguiente:
<?php
// modo de paso de los parámetros de una función
// Cumplimiento estricto del tipo de los parámetros
declare(strict_types=1);
function f(int &$i, int $j): void {
// $i se obtendrá por referencia
// $j se obtendrá por valor
$i++;
$j++;
print "f[i,j]=[$i,$j]\n";
}
// pruebas
$i = 0;
$j = 0;
// $i y $j se pasan a la función f
f($i, $j);
print "test[i,j]=[$i,$j]\n";
Resultados:
Comentarios
El código anterior muestra las dos formas de pasar parámetros a una función. Veamos el siguiente ejemplo:
- línea 1: define los parámetros formales $a y $b de la función f. Esta función procesa estos dos parámetros formales y devuelve un resultado;
- línea 7: llamada a la función f con dos parámetros efectivos $i y $j. Las relaciones entre los parámetros formales ($a, $b) y los parámetros efectivos ($i, $j) se definen en las líneas 1 y 7:
- &$a: el símbolo & indica que el parámetro formal $a tomará como valor la dirección del parámetro efectivo $i. En otras palabras, $a y $i son dos referencias a la misma ubicación de memoria. Manipular el parámetro formal $a equivale a manipular el parámetro efectivo $i. Esto es lo que muestra la ejecución del código. Este modo de paso es adecuado para parámetros de salida y datos de gran tamaño, como tablas y diccionarios. A este modo de paso se le denomina «paso por referencia».
- $b: el parámetro formal $b tomará como valor el del parámetro efectivo $j. Se trata de un paso por valor. Los parámetros formales y efectivos son dos variables diferentes. Manipular el parámetro formal $b no tiene ningún impacto en el parámetro efectivo $j. Esto es lo que muestra la ejecución del código. Este modo de paso es adecuado para los parámetros de entrada.
- Consideremos la función échange, que admite dos parámetros formales: $a y $b. La función intercambia el valor de estos dos parámetros. Así, durante una llamada de intercambio ($i, $j), el código que realiza la llamada espera que se intercambien los valores de los dos parámetros efectivos. Por lo tanto, son parámetros de salida (se modifican). Por lo tanto, se escribirá:
El siguiente script [base-13.php] muestra otros ejemplos:
<?php
// tipos en modo estricto
// declare(strict_types = 1);
// modo de paso de parámetros
function f(&$i, $j) {
// $i se obtendrá por referencia
// $j se obtendrá por referencia
$i++;
$j++;
print "f[i,j]=[$i,$j]\n";
}
function g(int &$i, int $j) : void {
// $i se obtendrá por referencia
// $j se obtendrá por valor
$i++;
$j++;
print "g[i,j]=[$i,$j]\n";
}
// pruebas
$i = 0;
$j = 0;
// $i y $j se pasan a la función f
f($i, $j);
print "test[i,j]=[$i,$j]\n";
// $i y $j se pasan a la función g
g($i, $j);
print "test[i,j]=[$i,$j]\n";
// se pasan parámetros incorrectos a f
$a=5.3;
$b=6.2;
f($a, $b);
print "test[a,b]=[$a,$b]\n";
// se están pasando parámetros incorrectos a f
$a=5.3;
$b=6.2;
g($a, $b);
print "test[a,b]=[$a,$b]\n";
Comentarios
- líneas 8-14: la función f analizada en el párrafo anterior, pero sin especificar los tipos de los parámetros;
- líneas 16-22: la función g hace lo mismo que la función f, pero se especifica el tipo de los parámetros esperados —esta es una novedad PHP 7. Se esperan dos parámetros de tipo int. Queremos ver qué sucede cuando el parámetro real pasado a la función no tiene el tipo esperado por esta;
- líneas 25-26: $i y $j son dos enteros;
- líneas 28-29: llamada a la función f con parámetros del tipo esperado;
- líneas 31-32: llamada a la función g con parámetros del tipo esperado;
- líneas 34-35: las variables $a y $b son de tipo float;
- líneas 36-37: llamada a la función f con parámetros que no son del tipo esperado;
- líneas 41-42: llamada a la función g con parámetros que no son del tipo esperado;
Resultados
- las líneas 5-6 muestran que la función f aceptó los dos parámetros de tipo float y trabajó con ellos;
- las líneas 7-8 muestran que la función g aceptó los dos parámetros de tipo float, pero los convirtió a tipo int (línea 7);
Ahora descomentemos la línea 4:
Esta instrucción indica que se deben respetar los tipos de los parámetros formales. Si no es así, se reporta un error. Los resultados de la ejecución son entonces:
- líneas 9-10: el intérprete PHP 7 lanzó una excepción para indicar que el primer parámetro pasado a la función g no tenía el tipo correcto. Se recomienda ser estricto con los tipos de los parámetros, siempre que sea posible, para detectar errores en las llamadas a funciones;
3.8.2. Resultados devueltos por una función
El script [base-15.php] es el siguiente:
<?php
// tipos en modo estricto
declare(strict_types=1);
// resultados devueltos por una función
// una función puede devolver varios valores en una matriz
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";
}
// una función puede devolver un objeto
$res = f2(10);
print "f2 : [$res->res1,$res->res2,$res->res3]\n";
// ¿De qué tipo es el objeto?
print "nature de l'objet : ";
var_dump($res);
print "\n";
// Hacemos lo mismo con la función f3
$res = f3(10);
print "f3 : [$res->res1,$res->res2,$res->res3]\n";
// ¿De qué tipo es el objeto?
print "nature de l'objet : ";
var_dump($res);
print "\n";
// fin
exit;
// función f1
function f1(int $valeur): array {
// devuelve una matriz ($valeur+1,$valeur+2,$valeur+3)
return array($valeur + 1, $valeur + 2, $valeur + 3);
}
// función f2
function f2(int $valeur): object {
// devuelve un objeto ($valeur+1,$valeur+2,$valeur+3)
$res->res1 = $valeur + 1;
$res->res2 = $valeur + 2;
$res->res3 = $valeur + 3;
// devuelve el objeto
return $res;
}
// función f3: hace lo mismo que la función f2
function f3(int $valeur): object {
// devuelve un objeto ($valeur+1,$valeur+2,$valeur+3)
$res = new stdclass();
$res->res1 = $valeur + 1;
$res->res2 = $valeur + 2;
$res->res3 = $valeur + 3;
// devuelve el 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)
}
Comentarios
- El programa anterior muestra que una función PHP puede devolver un conjunto de resultados y no solo uno, en forma de matriz u objeto. El concepto de objeto se explica con más detalle más adelante;
- líneas 35-38: la función f1 devuelve varios valores en forma de matriz (array);
- líneas 41-48: la función f2 devuelve varios valores en forma de un objeto (object);
- líneas 51-59: la función f3 es idéntica a la función f2, salvo que crea explícitamente un objeto en la línea 53;
- la línea 6 de los resultados emite una advertencia (warning) que indica que PHP se vio obligado a crear un objeto por defecto en la línea 43 del código, es decir, al utilizar la notación [$res→res1]. La función var_dump de la línea 20 del código permite acceder al tipo del objeto y a su contenido. En los resultados, se observa que:
- línea 8: el objeto creado por defecto es de tipo stdClass;
- líneas 9-10: la propiedad res1 es de tipo entier y tiene el valor 11;
- etc…
- Para evitar la advertencia de la línea 6 de los resultados, se crea explícitamente, en la línea 53 de la función f3, un objeto de tipo stdClass;
3.9. Los archivos de texto
El script [bases-16.php] es el siguiente:
<?php
// cumplimiento estricto del tipo de los parámetros de las funciones
declare (strict_types=1);
// procesamiento secuencial de un archivo de texto
// este es un conjunto de líneas con el formato login:pwd:uid:gid:infos:dir:shell
// cada línea se almacena en un diccionario con el formato login => uid:gid:infos:dir:shell
// Se establece el nombre del archivo
$INFOS = "infos.txt";
// se abre en modo de creación
if (!$fic = fopen($INFOS, "w")) {
print "Erreur d'ouverture du fichier $INFOS en écriture\n";
exit;
}
// se genera un contenido arbitrario
for ($i = 0; $i < 100; $i++) {
fputs($fic, "login$i:pwd$i:uid$i:gid$i:infos$i:dir$i:shell$i\n");
}
// se cierra el archivo
fclose($fic);
// se aprovecha la vulnerabilidad: fgets conserva el marcador de fin de línea
// esto evita que se recupere una cadena vacía al leer una línea en blanco
// se abre en modo de lectura
if (!$fic = fopen($INFOS, "r")) {
print "Erreur d'ouverture du fichier $INFOS en lecture\n";
exit;
}
// las líneas tienen menos de 1000 caracteres
// la lectura de la línea se detiene en el marcador de fin de línea
// o en el marcador de fin de archivo
while ($ligne = fgets($fic, 1000)) {
// se elimina el marcador de fin de línea si existe
$ligne = cutNewLineChar($ligne);
// se coloca la línea en una tabla
$infos = explode(":", $ligne);
// se recupera el nombre de usuario
$login = array_shift($infos);
// se omite la contraseña
array_shift($infos);
// se crea una entrada en el diccionario
$dico[$login] = $infos;
}
// se cierra
fclose($fic);
// análisis del diccionario
afficheInfos($dico, "login10");
afficheInfos($dico, "X");
// fin
exit;
// --------------------------------------------------------------------------
function afficheInfos(array $dico, string $clé): void {
// muestra el valor asociado a la clave en el diccionario $dico si existe
if (isset($dico[$clé])) {
// El valor existe: ¿es una matriz?
$valeur = $dico[$clé];
if (is_array($valeur)) {
print "[$clé," . join(":", $valeur) . "]\n";
} else {
// $valeur no es una matriz
print "[$clé,$valeur]\n";
}
} else {
// $clé no es una clave del diccionario $dico
print "la clé [$clé] n'existe pas\n";
}
}
// --------------------------------------------------------------------------
function cutNewLinechar(string $ligne): string {
// se elimina el marcador de fin de línea de $ligne si existe
$L = strlen($ligne); // longitud de la línea
while (substr($ligne, $L - 1, 1) == "\n" or substr($ligne, $L - 1, 1) == "\r") {
$ligne = substr($ligne, 0, $L - 1);
$L--;
}
// fin
return($ligne);
}
El archivo infos.txt:
Los resultados:
[login10,uid10:gid10:infos10:dir10:shell10]
la clé [X] n'existe pas
Comentarios
- línea 12: fopen(nom_fichier,"w") abre el archivo nom_fichier en modo de escritura (w=write). Si el archivo no existe, se crea. Si existe, se vacía. Si falla la creación, fopen devuelve el valor false. En la instrucción if (!$fic = fopen($INFOS, "w")) {…}, hay dos operaciones sucesivas: 1) $fic = fopen(..) 2) if( ! $fic) {…};
- línea 18: fputs($fic, $chaîne) escribe chaîne en el archivo $fic. $chaine se escribe con el carácter de fin de línea \n al final;
- línea 21: fclose($fic) cierra el archivo $fic;
- línea 26: fopen(nom_fichier,"r") abre el archivo nom_fichier en modo de lectura (r=read). Si la apertura falla (por ejemplo, si el archivo no existe), fopen devuelve el valor false;
- línea 34: fgets($fic, 1000) lee la siguiente línea del archivo con un límite de 1000 caracteres. En la operación while ($ligne = fgets($fic, 1000)) {…}, hay dos operaciones sucesivas: 1) $ligne = fgets(…) 2) while ( ! $ligne). Una vez que se ha leído el último carácter del archivo, la función fgets devuelve el valor false y el bucle while se detiene. La función fgets intenta aquí leer un máximo de 1000 caracteres, pero se detiene tan pronto como encuentra un carácter de fin de línea. Como todas las líneas tienen menos de 1000 caracteres, [fgets] lee una línea de texto, incluido el carácter de fin de línea. La función cutNewLineChar de las líneas 75 a 84 elimina los posibles caracteres de fin de línea;
- línea 77: la función strlen($chaîne) devuelve el número de caracteres de $chaîne;
- línea 78: la función substr($ligne, $position, $taille) devuelve $taille caracteres de $ligne, a partir del carácter n.º $position, siendo el primer carácter el n.º 0. En las máquinas con Windows, el marcador de fin de línea es «\r\n». En las máquinas Unix, es la cadena «\n»;
- línea 40: la función array_shift($tableau) elimina el primer elemento de $tableau y lo devuelve como resultado. Aquí se omite el resultado devuelto por array_shift;
- línea 62: la función is_array($variable) devuelve true si $variable es una matriz; de lo contrario, devuelve false;
- línea 63: la función join hace lo mismo que la función implode que ya hemos visto;
3.10. Codificación / decodificación jSON

La codificación / decodificación jSON (JavaScript Notación de objetos) es algo que vamos a utilizar ampliamente en el ejercicio que sirve de hilo conductor del documento. Los scripts [json-01.php, json-02.php, json-03.php] explican lo que hay que saber para continuar.
El script [json-01.php] es el siguiente:
<?php
$array1 = ["nom" => "séléné", "prénom" => "bénédicte", "âge" => 34];
// codificación JSON de la matriz array1 con caracteres Unicode escapados
print "encodage json du tableau array1 avec caractères Unicode échappés\n";
$json1 = json_encode($array1);
print "json1=$json1\n";
// codificación JSON del array array1 con caracteres Unicode sin escapar
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";
// decodificación de jSON en un array asociativo
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";
}
// decodificación de jSON en un 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
Comentarios
- línea 6 del código: la función [json_encode] transforma su parámetro en la cadena de caracteres jSON;
- línea 2 de los resultados: la cadena jSON generada. Los caracteres Unicode éâ han sido reemplazados por su código Unicode, que comienza con \u;
- línea 10 del código: se repite el mismo proceso, pero esta vez se indica que los caracteres Unicode se mantengan tal cual;
- línea 4 de los resultados: la cadena resultante jSON. Es mucho más legible;
- líneas 14-18 del código: se realiza la operación inversa. Se transforma una cadena jSON en un array asociativo;
- líneas 6-13 de los resultados: se observa que se ha obtenido un array asociativo;
- líneas 19-25 del código: convertimos una cadena jSON en un objeto de tipo [stdClass];
- líneas 18-25 de los resultados: se observa que se ha obtenido un objeto de tipo [stdClass];
- líneas 23-25 del código: el atributo A de un objeto O se denota como [O→A];
Se pueden codificar en jSON tablas de varios niveles, como lo muestra el siguiente 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],
]];
// codificación jSON del array de varios niveles
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}]}
Comentarios
En la cadena jSON:
- las tablas no asociativas están entre corchetes [];
- los arreglos asociativos están entre llaves {};
El script [json-03.php] muestra cómo procesar el siguiente archivo jSON [famille.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
}
]
}
El script [json-03.php] es el siguiente:
<?php
// lectura del archivo jSON
$json = file_get_contents("famille.json");
// decodificación de JSON en objeto
$famille1 = json_decode($json);
print "----famille1\n";
var_dump($famille1);
// decodificación de JSON en una tabla asociativa
print "----famille2\n";
$famille2 = json_decode($json, true);
var_dump($famille2);
Comentarios
- línea 4: la función [file_get_contents] lee el contenido del archivo llamado [famille.json] y lo asigna a la variable [$json];
- luego, la variable se decodifica en un objeto (líneas 5-8) y en un array asociativo (líneas 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)
}
}
}
Comentarios
- líneas 1-38: el objeto resultante de la decodificación del archivo jSON [famille.json];
- líneas 39-76: el array asociativo resultante de la decodificación del archivo jSON [famille.json];