====== 02 - PHP II: Variables y constantes ====== En PHP las variables se representan con un signo de dólar seguido por el nombre de la variable. El nombre de la variable **es sensible a mayúsculas y minúsculas**. Como hemos dicho antes, no hace falta declarar el tipo de variable (ni siquiera definirla): El anterior código no daría ningún error (aunque no hemos definido antes //$var1//), como mucho nos mostraría un //warning//, dependiendo de como tengamos configurado PHP. Incluso podemos cambiar el tipo de variable en un momento dado, sin que nos muestre ningún tipo de error: "; echo $var1; $var1 = 5; echo $var1; No es necesario tampoco inicializar las variables, sin embargo la mayoría de veces es aconsejable. Las variables no inicializadas tienen un valor predeterminado de acuerdo a su tipo dependiendo del contexto en el que son usadas. De forma predeterminada, las variables en PHP siempre se asignan por valor. Si queremos cambiar asignar por referencia debemos utilizar **&**. ===== Ámbito de las variables ===== El ámbito de una variable es el contexto dentro del que la variable está definida. La mayor parte de las variables PHP sólo tienen un ámbito simple. Este ámbito simple también abarca los ficheros incluidos y los requeridos. Por ejemplo: Aquí, la variable //$a// estará disponible en el interior del //script// incluido //archivo2.php//. Sin embargo, en el interior de las funciones definidas por el usuario se introduce un ámbito local a la función. Cualquier variable usada dentro de una función está, por omisión, limitada al ámbito local de la función. Por ejemplo: {{ :clase:daw:dws:1eval:php09.png?400 |}} Tenemos varias formas de poder acceder a la variable //$a// del anterior ejemplo. Podemos usar la palabra reservada **global** para indicarle a la función que la variable //$a// es una variable global. {{ :clase:daw:dws:1eval:php10.png?200 |}} Otra forma sería utilizar la variable predefinida [[https://www.php.net/manual/es/reserved.variables.globals|$GLOBALS]] para acceder a //$a//. $a = 5; function test() { echo "El valor de a es " . $GLOBALS["a"]; } test(); ===== Tipos de datos ===== PHP admite diez tipos primitivos. Cuatro tipos escalares: * **boolean** * **integer** * **float** (número de punto flotante, también conocido como double) * **string** Cuatro tipos compuestos: * **array** * **object** * **callable** * **iterable** Y finalmente dos tipos especiales: * **resource** * **NULL** Vamos a comentar algunas particularidades de algunos de los anteriores tipos de datos. ==== boolean ==== Este es el tipo más simple. Un **boolean** expresa un valor que indica verdad. Puede ser //TRUE// (verdadero) o //FALSE// (falso). Se puede convertir explícitamente un valor al tipo //boolean// mediante el forzamiento de tipo **(bool)** o **(boolean)**. $var1 = 5; echo (bool)$var1; Sin embargo, en la mayoría de casos es innecesario, ya que un valor será convertido automáticamente a boolean según las siguiente regla: * los siguientes valores se consideran //FALSE//: * el //boolean FALSE// mismo * el //integer// 0 y -0 (cero) * //float// 0.0 y -0.0 (cero) * el valor //string// vacío, y el //string// "0" * un //array// con cero elementos * el tipo especial //NULL// (incluidas variables no establecidas) * objetos //SimpleXML// creados desde etiquetas vacías Todos los demás valores se consideran TRUE. ==== integer ==== Los //integer// pueden especificarse mediante notación decimal (base 10), hexadecimal (base 16), octal (base 8) o binaria (base 2), opcionalmente precedidos por un signo (- o +). Para utilizar la notación octal, se antepone al número un 0 (cero). Para utilizar la notación hexadecimal, se antepone al número 0x. Para utilizar la notación binaria, se antepone al número 0b. $num1 = 5; #número decimal $num2 = -5; #número negativo $num3 = 0123; #número octal $num4 = 0x1B3; #número hexadecimal $num5 = 0b11010; #número binario Si mostramos el valor de las variables anteriores en un navegador mediante //echo//, nos mostrará su valor en decimal. El tamaño máximo de un entero depende de la plataforma, aunque el valor usual es aproximadamente 2.000 millones. Para convertir explícitamente un valor al tipo //integer// se puede usar //(int)// o //(integer)//. $cadena1 = "5"; $numero1 = (int) $cadena1; ==== float ==== Los float se pueden especificar usando cualquiera de las siguientes sintaxis: $a = 1.234; $b = 1.2e3; $c = 7E-10; $d = 1_234.567; // a partir de PHP 7.4.0 El tamaño de un //float// depende de la plataforma, aunque un valor común consiste en un máximo de aproximadamente 1.8e308 con una precisión cercana a los 14 dígitos decimales (el formato de 64 bit del IEEE). Para convertir explícitamente un valor al tipo //float// se puede usar //(float)//. $cadena1 = "5.345LOI"; echo (float)$cadena1; # imprimirá 5.345 ==== string ==== Un //string// es una serie de caracteres donde cada carácter ocupa un byte. Por esa razón, PHP sólo admite cadenas de 256 caracteres, y no ofrece soporte nativo para Unicode. Para especificar un valor de tipo string podemos utilizar, como hemos visto antes, las comillas dobles o sencillas. Para escapar caracteres, debemos emplear la barra invertida \. Además, existen otras dos representaciones adicionales: **herodoc** y **nowdoc**. La sintaxis //herodoc// permite especificar cadenas de caracteres en varias líneas mediante el operador <<<. Después de este operador, se deberá proporcionar un identificador y justo después una nueva línea. A continuación va el propio //string//, y para cerrar la notación se pone el mismo identificador. $cadena = << El texto //heredoc// se comporta como un //string// entre comillas dobles, lo que significa, entre otras cosas, que podemos usar variables dentro del texto sin necesidad concatenar cadenas. //Nowdoc// es a los //string// con comillas simples lo mismo que //heredoc// lo es a los //string// con comillas dobles. Un //nowdoc// se especifica de forma análoga a un //heredoc//, pero no se realiza ningún análisis dentro del //nowdoc//. Un //nowdoc// se identifica con la misma secuencia empleada para //heredoc//, <<<, pero el identificador que le sigue está delimitado con comillas simples. $cadena = <<<'EOS' Hola, soy una cadena de texto que ocupa varias líneas. La cadena no terminará hasta que aparezca el identificador de fin de cadena EOS; echo $cadena; La principal diferencia entre //herodoc// y //nowdoc// es la misma que entre las comillas dobles y sencillas. Dentro de un texto //herodoc// PHP cambiará el valor de una variable por su correspondiente valor, mientras que con //nowdoc// mostrará el nombre de la variable. $palabra = 'Mundo'; $cadena1 = << Es muy importante señalar que la línea con el identificador de cierre no debe contener ningún otro carácter, excepto un punto y coma (;). Esto, en especial, significa que el identificador no debe estar sangrado, y que no debe existir ningún espacio ni tabulación antes o después del punto y coma. ==== Variables predefinidas ==== PHP proporciona una gran cantidad de variables predefinidas para todos los //scripts//. Algunos ejemplos son: * **$GLOBALS**: Hace referencia a todas las variables disponibles en el ámbito global * **$_SERVER**: Información del entorno del servidor y de ejecución * **$_GET**: Variables HTTP GET * **$_POST**: Variables HTTP POST * **$_FILES**: Variables de subida de ficheros HTTP * **$_REQUEST**: Variables HTTP Request * **$_SESSION**: Variables de sesión * **$_ENV**: Variables de entorno * **$_COOKIE**: Cookies HTTP A lo largo del curso aprenderemos a utilizar varias de ellas para crear nuestras aplicaciones. ==== isset y unset ==== Para comprobar si una variable está definida y no es //null// podemos utilizar la función [[https://www.php.net/manual/es/function.isset.php|isset]], que devolverá TRUE si la variable existe y no es nula. if (isset($a)) { # codigo... } else { # codigo... } Es bastante habitual utilizar //isset// para comprobar si hemos recibido el parámetro por //$_GET// o //$_POST// (por ejemplo a la hora de recibir datos de un formulario). Si queremos eliminar una variable utilizaremos [[https://www.php.net/manual/es/function.unset.php|unset]]. unset($a) ===== Constantes ===== Podemos definir constantes usando la función [[https://www.php.net/manual/es/function.define.php|define]] o con la palabra reservada **const**. Si usamos la función //define()// debemos pasar como primer parámetro el nombre de la constante y el valor como segundo. Antes de PHP 5.6, al emplear la palabra reservada //const//, solamente los datos escalares (//boolean//, //integer//, //float// y //string//) podían estar contenidos en constante. Desde PHP 5.6 en adelante, también es posible definir un //array// constante. define('FRASE', 'Hola mundo'); const PI = 3.1416; Igual que con las variables, PHP ofrece un gran número de constantes predefinidas a cualquier //script// en ejecución. Algunas de ellas son: * **PHP_VERSION**, versión de PHP instalada * **PHP_EOL**, símbolo de fin de línea de la plataforma en uso * **PHP_INT_MAX**, número entero más grande admitido * **PHP_INT_MIN**, número entero más pequeño admitido * **E_ERROR**, constante de informe de error ===== Operadores ===== ^ Operadores aritméticos ^^ | \$a + \$b | Suma de \$a y \$b | | \$a - \$b | Resta de \$a y \$b | | \$a * \$b | Multiplicación de \$a y \$b | | \$a / \$b | División de \$a entre \$b | | \$a % \$b | Módulo de \$a dividido por \$b | | \$a %%**%% \$b | Elevar \$a a la potencia \$bésima | ^ Operadores de comparación ^^ | \$a == \$b | //TRUE// si \$a es igual a \$b | | \$a === \$b | //TRUE// si \$a es igual a \$b, **y son del mismo tipo** | | \$a != \$b o \$a <> \$b | //TRUE// si \$a no es igual a \$b | | \$a !== \$b | //TRUE// si \$a no es igual a \$b, **o no son del mismo tipo** | | \$a < \$b | //TRUE// si \$a es menor que \$b | | \$a > \$b | //TRUE// si \$a es mayor que \$b | | \$a <= \$b | //TRUE// si \$a es menor o igual que \$b | | \$a >= \$b | //TRUE// si \$a es mayor o igual que \$b | ^ Operadores para //string// ^^ | \$a . \$b | Concatenación de \$a y \$b | ^ Operadores de asignación ^^ | \$a = valor |\ $a se define como valor | | \$a += número | Equivalente a \$a = \$a + número | | \$a .= “texto” | Equivalente a \$a = \$a . “Texto” | ^ Operadores para arrays ^^ | \$a + \$b | Unión de \$a y $b | | \$a == \$b | TRUE si \$a y \$b tienen las mismas parejas clave/valor | | \$a === \$b | TRUE si \$a y \$b tienen las mismas parejas clave/valor **en el mismo orden y de los mismos tipos** | | \$a != \$b o \$a <> \$b | //TRUE// si \$a no es igual a \$b | | \$a !== \$b | //TRUE// si \$a no es idéntico a \$b | ==== Operador ternario ==== Otro operador condicional es el operador ternario (//?//). $nombre = isset($_POST['nombre']) ? $_POST['nombre'] : 'Pepe'; echo $nombre; La expresión //(expr1) ? (expr2) : (expr3)// evalúa a //expr2// si //expr1// se evalúa como //TRUE// y a //expr3// si //expr1// se evalúa como //FALSE//. En el ejemplo anterior si existe //$_POST[‘nombre]//, //$nombre// toma el valor //$_POST[‘nombre’]//. Si no, valdrá ‘Pepe’. Es equivalente a la siguiente sentencia: if (isset($_POST['nombre'])) { $nombre = $_POST['nombre']; } else { $nombre = 'Pepe'; } A partir de PHP 5.3, es posible dejar de lado la parte media del operador ternario. La expresión //expr1 ?: expr3// retorna //expr1// si //expr1// se evalúa como TRUE y //expr3// si es de otra manera. ==== Operadores nave espacial y fusión de null ==== A partir de PHP 7 existen dos operadores adicionales de comparación, el operador **nave espacial** y el operador **fusión de null**. El operador //nave espacial// (**<=>**) se emplea para comparar dos expresiones. Devuelve -1, 0 o 1 cuando \$a es respectivamente menor, igual, o mayor que \$b. // Numeros enteros echo 1 <=> 1; // 0 echo 1 <=> 2; // -1 echo 2 <=> 1; // 1 // Numeros decimales echo 1.5 <=> 1.5; // 0 echo 1.5 <=> 2.5; // -1 echo 2.5 <=> 1.5; // 1 // Cadenas de caracteres echo "a" <=> "a"; // 0 echo "a" <=> "b"; // -1 echo "b" <=> "a"; // 1 Por su parte, el operador //fusión de null// (**??**) se ha añadido como aliciente sintáctico para el caso común de la necesidad de utilizar un operador ternario junto con //isset()//. Devuelve su primer operando si existe y no es //null//; de lo contrario devuelve su segundo operando. // Obtener el valor de $_GET['usuario'] y devolver 'nadie' si no existe. $nombre = $_GET['usuario'] ?? 'nadie'; // Esto equivale a: $nombre = isset($_GET['usuario']) ? $_GET['usuario'] : 'nadie'; // La fusión se puede encadenar: esto devolverá el primer valor definido de $_GET['usuario'], $_POST['usuario'], y 'nadie'. $nombre = $_GET['usuario'] ?? $_POST['usuario'] ?? 'nadie';