|

PHP

PHP está diseñado para ser fácil de aprender y potente en su aplicación, lo que lo convierte en una opción popular para desarrolladores de todos los niveles. Aquí tienes algunos aspectos básicos:

  • Etiquetas de PHP: Un script de PHP se puede colocar en cualquier parte de un documento. Este script comienza con <?php y termina con ?>. Por ejemplo:
<?php
// Código PHP va aquí
?>
$nombre = "Juan";
echo "Hola, " . $nombre . "!";

Comentarios: Puedes agregar comentarios en tu código PHP para hacerlo más legible. Los comentarios de una sola línea comienzan con //, mientras que los comentarios de varias líneas se encierran entre /* y */:

// Esto es un comentario de una sola línea

/*
Esto es un comentario
de varias líneas
*/

En PHP, los tipos de datos se utilizan para representar diferentes tipos de valores que se pueden manipular en un programa. A continuación, describiré los tipos de datos más comunes en PHP:

Entero (int): Representa números enteros sin parte decimal. Puede ser positivo o negativo. Por ejemplo:

$edad = 30;

Flotante o doble (float o double): Representa números con punto flotante (decimales). Por ejemplo:

$precio = 19.99;

Cadena de caracteres (string): Representa texto. Puede estar entre comillas simples o dobles. Por ejemplo:

$nombre = "Juan";

Booleano (bool): Representa valores verdaderos (true) o falsos (false). Se utiliza en pruebas condicionales. Por ejemplo:

$activo = true;

Arreglo (array): Almacena múltiples valores en una sola variable. Por ejemplo:

$colores = array("rojo", "verde", "azul");
$colores = ["rojo", "verde", "azul"];

Objeto: Las clases y objetos son fundamentales en la programación orientada a objetos. Un objeto es una instancia de una clase. Por ejemplo:

class Coche {
    public $marca;
    public function __construct($marca) {
        $this->marca = $marca;
    }
}
$miCoche = new Coche("Toyota");

Recuerda que PHP no requiere (ni soporta) la definición explícita de tipos en la declaración de variables; el tipo de la variable se determina por el contexto en el cual se emplea la variable

En PHP, los arrays son estructuras de datos que nos permiten almacenar múltiples valores en una sola variable. Existen dos tipos principales de arrays: arrays indexados y arrays asociativos. Vamos a explorar ambos:

Arrays Indexados:

  • Los arrays indexados utilizan índices numéricos para acceder a sus elementos. Cada elemento se almacena en una posición específica del array, comenzando desde el índice 0.
  • Ejemplo de un array indexado:
$colores = array("rojo", "verde", "azul");

En este caso, $colores[0] es “rojo”, $colores[1] es “verde” y $colores[2] es “azul”.

Arrays Asociativos:

  • Los arrays asociativos utilizan claves personalizadas en lugar de índices numéricos. Cada elemento se asocia con una clave específica.
  • Ejemplo de un array asociativo:
$persona = array(
    "nombre" => "Juan",
    "edad" => 30,
    "ciudad" => "Madrid"
);

En este caso, $persona["nombre"] es “Juan”, $persona["edad"] es 30 y $persona["ciudad"] es “Madrid”.

  1. Diferencias clave:
    • En los arrays indexados, los índices son automáticamente asignados (0, 1, 2, …).
    • En los arrays asociativos, tú eliges las claves (pueden ser strings o números).
  2. Ventajas de los Arrays Asociativos:
    • Puedes asignar significado a cada elemento mediante claves descriptivas.
    • Son útiles para almacenar información estructurada, como datos de una persona o configuraciones de una aplicación.

En resumen, los arrays indexados son ideales cuando necesitas una lista simple de elementos, mientras que los arrays asociativos son más apropiados cuando deseas relacionar datos con claves personalizadas

Puedes crear arrays tanto indexados como asociativos utilizando la notación de corchetes [] de forma abreviada. Permíteme mostrarte cómo:

  • Array Indexado (abreviado):
$colores = ["rojo", "verde", "azul"];
  • Array Asociativo (abreviado):
$persona = [
    "nombre" => "Juan",
    "edad" => 30,
    "ciudad" => "Madrid"
];

Aquí, $persona["nombre"] es “Juan”, $persona["edad"] es 30 y $persona["ciudad"] es “Madrid”.

La notación de corchetes [] es una forma concisa y legible de definir arrays en PHP. 

Clases y Objetos

La programación orientada a objetos (POO) se basa en la creación de clases y objetos para encapsular datos y comportamientos. En PHP, las clases y los objetos son los elementos fundamentales de la POO, y se utilizan para crear soluciones escalables y eficientes1. Aquí tienes algunos conceptos clave sobre clases y objetos en PHP:

  1. Clases:
    • Una clase es una plantilla o un plano que define la estructura y el comportamiento de los objetos.
    • Define propiedades (variables) y métodos (funciones) que los objetos pueden tener.
    • Puedes pensar en una clase como un “molde” para crear objetos.
    • Para definir una clase en PHP, utilizamos la palabra clave class.
  2. Objetos:
  3. Propiedades y Métodos:
    • Las propiedades son variables dentro de una clase que almacenan datos específicos para cada objeto.
    • Los métodos son funciones dentro de una clase que definen el comportamiento de los objetos.
    • Puedes acceder a las propiedades y métodos de un objeto utilizando la notación de punto ($objeto->propiedad o $objeto->metodo()).
  4. Visibilidad:
    • Las propiedades y métodos pueden tener diferentes niveles de visibilidad: publicprotected o private.
    • public: Accesible desde cualquier lugar.
    • protected: Accesible solo dentro de la clase y sus subclases.
    • private: Accesible solo dentro de la clase.
  5. Constructores y Destructores:
    • El constructor es un método especial que se ejecuta automáticamente al crear un objeto.
    • El destructor se ejecuta cuando el objeto se destruye o se elimina.
  6. Herencia:
    • Permite crear una nueva clase basada en una clase existente (clase padre).
    • La nueva clase (clase hija) hereda propiedades y métodos de la clase padre.
  7. Abstracción, Interfaces y Rasgos (Traits):
    • La abstracción permite definir una clase base con métodos abstractos que deben ser implementados por las clases derivadas.
    • Las interfaces definen un conjunto de métodos que las clases deben implementar.
    • Los rasgos son fragmentos de código reutilizables que se pueden incluir en múltiples clases.

En resumen, las clases y objetos en PHP te permiten organizar y estructurar tu código de manera más eficiente, facilitando la reutilización y la modularidad.

A continuación, te proporciono ejemplos prácticos para cada uno de los conceptos mencionados sobre clases y objetos en PHP:

Clases:

<?php
class Persona {
    public $nombre;
    public $edad;

    public function saludar() {
        echo "¡Hola, mi nombre es {$this->nombre}!";
    }
}

// Crear un objeto de la clase Persona
$persona1 = new Persona();
$persona1->nombre = "Juan";
$persona1->edad = 30;
$persona1->saludar();
?>

En este ejemplo, hemos definido una clase Persona con propiedades nombre y edad, así como un método saludar() que muestra un saludo personalizado.

Objetos:

<?php
// Crear otro objeto de la clase Persona
$persona2 = new Persona();
$persona2->nombre = "María";
$persona2->edad = 25;
$persona2->saludar();
?>

Aquí creamos un segundo objeto Persona con diferentes valores para las propiedades.

Visibilidad:

<?php
class Coche {
    private $marca;

    public function setMarca($nuevaMarca) {
        $this->marca = $nuevaMarca;
    }

    public function getMarca() {
        return $this->marca;
    }
}

$miCoche = new Coche();
$miCoche->setMarca("Toyota");
echo "Marca del coche: " . $miCoche->getMarca();
?>

En este ejemplo, la propiedad $marca es privada, pero podemos acceder a ella a través de los métodos setMarca() y getMarca().

Constructores y Destructores:

<?php
class Producto {
    public $nombre;

    public function __construct($nombre) {
        $this->nombre = $nombre;
        echo "Se creó un nuevo producto: {$this->nombre}";
    }

    public function __destruct() {
        echo "El producto {$this->nombre} se ha eliminado.";
    }
}

$producto1 = new Producto("Laptop");
// ... más código ...
unset($producto1); // Elimina el objeto
?>

Aquí utilizamos el constructor __construct() y el destructor __destruct() para manejar la creación y eliminación de objetos.

Herencia:

<?php
class Empleado extends Persona {
    public $puesto;

    public function trabajar() {
        echo "{$this->nombre} está trabajando como {$this->puesto}.";
    }
}

$empleado1 = new Empleado();
$empleado1->nombre = "Pedro";
$empleado1->puesto = "Desarrollador";
$empleado1->trabajar();
?>
  • Aquí creamos una clase Empleado que hereda de la clase Persona.
  • Abstracción, Interfaces y Rasgos (Traits):
    • La abstracción se logra mediante la definición de métodos abstractos en una clase base.
    • Las interfaces se definen con la palabra clave interface.
    • Los rasgos se crean con la palabra clave trait.

Vamos a explorar los conceptos de variablesconstantesexpresiones y operadores en PHP. 😊

  • Variables:
    • En PHP, las variables se declaran utilizando el símbolo de $ seguido del nombre de la variable.
    • No es necesario especificar el tipo de dato al declarar una variable, ya que PHP es un lenguaje de programación con variables de tipado dinámico.
    • Ejemplo:
$nombre = "Juan";
$edad = 25;
$precio = 10.5;
$esEstudiante = true;

Constantes:

  • Las constantes son valores que no cambian durante la ejecución del programa.
  • Se definen utilizando la función define() o la palabra clave const.
  • Ejemplo:
define("PI", 3.14159);
const IVA = 0.21;

Expresiones:

  • Las expresiones son combinaciones de valores, variables, operadores y funciones que devuelven un valor.
  • Casi todo en PHP es una expresión.
  • Ejemplo:
$resultado = ($edad * 2) + 10;
  • Operadores:
    • Los operadores son símbolos que realizan operaciones en expresiones.
    • Algunos operadores comunes en PHP son:
      • Aritméticos+-*/%
      • Asignación=+=-=*=/=
      • Comparación==!=<><=>=
      • Lógicos&&||!
      • Concatenación de strings.
      • Incremento/Decremento++--
      • Operadores ternarios? :

Recuerda que las expresiones y operadores son fundamentales para construir programas en PHP.

Variables Superglobales

En PHP, las superglobales son variables internas que están disponibles en todos los ámbitos a lo largo del script. No es necesario emplear global $variable; para acceder a ellas dentro de las funciones o métodos. Las principales superglobales son:

  1. $GLOBALS: Contiene todas las variables globales.
  2. $_SERVER: Proporciona información sobre el servidor y la solicitud HTTP.
  3. $_GET: Almacena los parámetros pasados en la URL.  (por ejemplo, example.com/index.php?param1=value1&param2=value2).
  4. $_POST: Contiene datos enviados mediante formularios POST.
  5. $_FILES: Utilizado para manejar archivos subidos por el usuario.
  6. $_COOKIE: Almacena cookies del cliente.
  7. $_SESSION: Mantiene información de sesión.
  8. $_REQUEST: Combina datos de $_GET$_POST y $_COOKIE.
  9. $_ENV: Contiene variables de entorno.

Aquí tienes un ejemplo de un formulario HTML que envía datos al servidor mediante el método POST y cómo se procesan esos datos en un script PHP:

<html>
<head>
    <title>Formulario de Registro</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
    <h2>Formulario de Registro</h2>
    <form action="registration_form.php" method="POST">
        First name: <input type="text" name="firstname"><br>
        Last name: <input type="text" name="lastname">
        <input type="hidden" name="form_submitted" value="1" />
        <input type="submit" value="Submit">
    </form>
</body>
</html>

En este ejemplo:

  • El formulario se envía al script “registration_form.php” mediante el método POST.
  • Los datos recopilados (nombre y apellido) se guardan en las variables $firstname y $lastname utilizando la variable $_POST.
  • El valor oculto <input type="hidden" name="form_submitted" value="1" /> se utiliza para comprobar si el formulario se ha enviado o no.
  • Cuando se hace clic en el botón “Submit”, los datos se envían al servidor para su procesamiento.

el archivo registration_form.php que procesa los datos enviados desde el formulario de registro y cómo mostrar esos datos:

<?php
if ($_SERVER["REQUEST_METHOD"] == "POST") {
    // Obtener los valores enviados desde el formulario
    $firstname = $_POST["firstname"];
    $lastname = $_POST["lastname"];

    // Procesar los datos (puedes guardarlos en una base de datos, enviar un correo, etc.)
    // En este ejemplo, simplemente los mostraremos en la página
    echo "¡Gracias por registrarte!<br>";
    echo "Nombre: " . $firstname . "<br>";
    echo "Apellido: " . $lastname;
} else {
    // Si el formulario no se ha enviado, muestra un mensaje
    echo "Por favor, completa el formulario.";
}
?>

En este código:

  • Verificamos si el método de solicitud es POST ($_SERVER["REQUEST_METHOD"] == "POST").
  • Recuperamos los valores enviados desde el formulario utilizando $_POST.
  • Procesamos los datos (en este caso, solo los mostramos en la página).
  • Si el formulario no se ha enviado, mostramos un mensaje para completarlo.

Estructuras de control en php

Un script PHP está contruido a partir de sentencias. Una sentencia puede ser una asignación, una llamada a una función, un loop, una sentencia condicional o una sentencia vacía. Las sentencias normalmente finalizan con un punto y coma.

Las estructuras de control son sentencias que permiten controlar cómo el código fluye en nuestro script basándose en ciertos factores. Por ejemplo, cuando queremos realizar una acción sólo si cierta variable está definida, o cuando queremos mostrar un array de datos a través de un loop.

Las estructuras de control son mayoritariamente condicionales (if, switch, etc) o loops (for, foreach, etc).

Indice de contenido

1. if9. continue
2. else10. switch
3. elseif/else if11. declare
4. while12. return
5. do-while13. include/include_once
6. for14. require/require_once
7. foreach15. goto
8. break16. Sintaxis alternativas

1. if

La estructura de control if permite la ejecución condicional de fragmentos de código.

<?php
if ($x > $y) {
    echo "$x es mayor que $y";
}

Las sentencias if se pueden incluir unas dentro de otras indefinidamente.

2. else

Sirve para ejecutar una sentencia cuando otra no se cumple. else extiende una sentencia if, y se ejecuta cuando ésta es false. Siguiendo el ejemplo anterior:

<?php
if ($x > $y) {
    echo "$x es mayor que $y";
} else {
    echo "$y es mayor que $x";
}

3. elseif/else if

Es una combinación entre if y else. Se ejecuta cuando if es false, pero sólo si la expresión condicional del elseif es true.

<?php
if ($x > $y) {
    echo "$x es mayor que $y";
} elseif ($x == $y) {
    echo "$x es igual que $y";
} else {
    echo "$y es mayor que $x";
}

Puede haber varios elseif dentro de una sentencia if (aunque en ese caso suele ser más recomendable usar switch). No hay diferencias de comportamiento entre elseif y else if.

elseif sólo se ejecuta si el if precedente o cualquier elseif anterior son evaluadas como false.

4. while

Es el tipo más sencillo de loop en PHP. Se ejecutan las sentencias dentro del while siempre y cuando se evalúen como true. El valor de la expresión se comprueba cada vez al inicio del loop, y la ejecución no se detendrá hasta que finalice la iteración (cada vez que PHP ejecuta las sentencias en un loop es una iteración). Si la expresión while se evalúa como false, las sentencias no se ejecutarán ni siquiera una vez.

También es posible agrupar varias instrucciones while dentro de una.

<?php
$i = 1;
while($i <= 10){
    echo $i;
    $i++;
}

5. do-while

Muy similares a los loops while, simplemente aquí la expresión para el loop se verifica al final en lugar de al principio, esto garantiza que el código se ejecute por lo menos la primera vez.

<?php
$i = 0;
do {
    echo $i;
} while ($i > 0);

Este loop se ejecutaría sólo una vez, ya que después no cumple la condición.

6. for

Los loops for son los más complejos en PHP.

<?php
for ($i = 1; $i <= 10; $i++) {
    echo $i;
} // Devuelve 123456789
  • Las expresiones o conjunto de expresiones van separadas por punto y coma ; y sólo hay 3.
  • La primera expresión, $i = 1, se ejecuta una vez incondicionalmente al comienzo del bucle.
  • La segunda expresión, $i <= 10, es una condición, si es true, se ejecutará la tercera expresión.
  • La tercera expresión, $i++, es la acción a realizar si se cumple la segunda expresión.

Cada una de las expresiones pueden estar vacías o contener múltiples expresiones, lo que resulta útil en ciertas ocasiones. Si la expresión 2 está vacía, el loop será definido como true.

<?php
// Todos los siguientes ejemplos son válidos y devuelven lo mismo, 123456789
// EJEMPLO 1
for($i = 1; $i <= 10; $i++) {
    echo $i;
}

// EJEMPLO 2
for ($i = 1; ; $i++){
    if($i > 10) {
        break;
    }
    echo $i;
}

// EJEMPLO 3
$i = 1;
for( ; ; ){
    if($i > 10){
        break;
    }
    echo $i;
    $i++;
}

// EJEMPLO 4
for ($i = 1, $j = 0; $i <= 10; $j += $i, print $i, $i++);

Dependiendo de donde se coloque el operador incremento o decremento, dará un resultado distinto:

for ($i = 1; $i <= 10; print $i++); // 12345678910
for ($i = 1; $i <= 10; print ++$i); // 234567891011

Se pueden hacer iteraciones por medio de arrays:

$gente = array(
    array('nombre' => 'Carlos', 'salt' => 123),
    array('nombre' => 'Maria', 'salt' => 124));
// Numero de gente
$size = count($gente);
// Loop que da un salt de 4 dígitos aleatorio
for ($i=0; $i < $size; ++$i) {
    $gente[$i]['salt'] = mt_rand(0000, 9999);
}
var_dump($gente);
/*
* array (size=2)
  0 =>
    array (size=2)
      'nombre' => string 'Carlos' (length=6)
      'salt' => int 2029
  1 =>
    array (size=2)
      'nombre' => string 'Maria' (length=5)
      'salt' => int 9724
*/

7. foreach

foreach permite una forma fácil de iterar sobre arrays u objetos.

Cuando foreach inicia su ejecución, el puntero apunta directamente al primer elemento del array, por lo que no es necesario llamar a la función reset() antes que un loop foreach. Es recomendable no cambiar el puntero dentro del loop.

Se puede iterar de las siguientes dos formas:

<?php
// Devuelve directamente el value de cada key, comenzando desde el primero
foreach ($array as $value) {
    // Lo que se desee mostrar
}
// Devuelve cada key con cada value, para poder trabajar con cualquiera de los dos
foreach ($array as $key => $value){
    // Lo que se desee mostrar
}

Se pueden modificar los elementos del array dentro del loop, anteponiendo & a $value (asignándolo por referencia).

<?php
$array = array(1, 2, 3, 4);
foreach ($array as &$value){
    $value = $value * 2;
}
// cada valor del array vale ahora : 2, 4, 6, 8
unset($value);

La función unset() elimina la referencia del último elemento, pero el array sigue valiendo 2, 4, 6, 8. Es recomendable hacer unset() porque la referencia del $valor y el último elemento del array permanecen aún después del loop foreach.

foreach y list pueden devolver los mismos resultados de la siguiente forma:

<?php
$array = array("uno", "dos", "tres");
reset($array);
while (list($clave, $valor) = each($array)){
    echo "Clave: $clave; Valor: $valor </br>";
}

foreach ($array as $clave => $valor){
    echo "Clave: $clave; Valor: $valor </br>";
}

La función list() coge un array y lo convierte en variables individuales.

each() coge un array y devuelve el key y value actuales, es decir, donde está apuntando el cursor en el array. Es necesario hacer un reset() del array para asegurarse que el cursor comienza desde el principio (cosa que no es necesaria con el foreach).

Suele ser más óptimo y legible utilizar el foreach para iterar, aunque ambos se utilizan más o menos con la misma frecuencia.

Con arrays multidimensionales se puede hacer un doble foreach:

<?php
$x = array();
$x[0][0] = "a";
$x[0][1] = "b";
$x[1][0] = "y";
$x[1][1] = "z";

foreach ($x as $primero){
    foreach ($primero as $segundo){
        echo "$segundo" . "</br>";
        }
    }

En el ejemplo anterior, si no se hace doble foreach con $x y se hace sólo un foreach surgirá un Notice: Array to string conversion.

Desde PHP 5.5 se puede recorrer un array de arrays y utilizar el segundo array para asignar variables:

<?php
$array = array(
    array('azul', 'rojo'),
    array('verde', 'amarillo')
    );

foreach ($array as list($a, $b)) {
    echo "A: $a; B: $b" . "</br>";
}
// Devuelve: 

8. break

break termina la ejecución de las siguientes estructuras: forforeachwhiledo-while y switch.

Se puede añadir un argumento numérico opcional que indica de cuántas estructuras debe salir. El valor por defecto es 1:

// Ejemplo sin valor numérico
$array = array('uno', 'dos', 'parar', 'tres');
while(list(, $valor) = each($array)){
    if($valor == 'parar'){
        break;
    }
    echo "$valor</br>";
}
// Ejemplo con valor numérico
$i = 0;
while (++$i){
    switch($i){
        case 5:
            echo "He llegado a 5 </br>";
            break 1; // Aquí sólo saldría del switch
        case 10:
            echo "He llegado a 10 </br>";
            break 2; // Sale del switch y del while
        default:
            break;
    }
}

9. continue

Se utiliza dentro de las estructuras iterativas para saltar el resto de la iteración actual del loop y continuar a la siguiente iteración para su ejecución:

<?php
for ($i=0; $i < 10; $i++) {
    if($i % 2 == 0)
        continue;
    print "$i ";
} // Devuelve 1 3 5 7 9

El código anterior hace que cuando el número sea par, continue se ejecute y no muestre el print de después, sino que vuelva a empezar con la siguiente iteración. print sólo se ejecutará cuando $i sea impar.

Al igual que con break, se puede añadir un número a continue que indica el número de niveles de loops debe saltar:

<?php
$i = 0;
while ($i++ < 5){
    echo "Uno </br>";
    while (1) {
        echo "Dos </br>";
        while (1) {
            echo "Tres </br></br>";
            continue 3;
        }
        echo "Esto no aparece.";
    }
    echo "Esto tampoco aparece.";
}

En este ejemplo, cuando llega a continue 3, comienza de nuevo la iteración, y se comprueba otra vez la condición ($i++ < 5). Si se pone, por ejemplo, continue 2, salta al segundo while, cuya condición siempre se cumple, y se produce un loop infinito que imprime «Dos Tres» continuamente.

10. switch

switch es como una serie de sentencias if. Es útil para comparar una misma variable o expresión con valores direrentes y ejecutar un código diferente a otro dependiendo de esos valores.

<?php
switch ($i) {
    case "perro":
        echo "\$i es un perro";
        break;
    case "gato":
        echo "\$i es un gato";
        break;
    case "avestruz":
        echo "\$i es un avestruz";
        break;
}

Cuando una sentencia case coincide con el valor de la sentencia switch, PHP ejecuta el código dentro del case. PHP sigue ejecutando las sentencias hasta el final o hasta que choca con un break, que entonces finaliza la iteración. Si se omite break, swith ejecutará todos los cases restantes cuando encuentra uno que cumpla con la condición:

<?php
switch ($i) {
    case 0:
        echo "i es igual a 0";
    case 1:
        echo "i es igual a 1";
    case 2:
        echo "i es igual a 2";
}

En el ejemplo anterior, si se define a $i como 0, se mostrarán todos los echo restantes porque no hay ningún break. Si se define a $i como 1, se mostrarán los echo del case 1 y case 2. Si se define a $i como 2, sólo se mostrará el case 2.

Con switch la condición sólo se evalúa una vez, y su valor es comparado con cada uno de los case, a diferencia de lo que ocurre con elseif, que la condión se va evaluando continuamente con el loop.

case puede no ejecutar ningún código, pero hace que se activen los cases posteriores hasta que se encuentre con un break:

<?php
switch ($i) {
case 0:
case 1:
case 2:
    echo "i es menor que 3 no negativo";
    break;
case 3:
    echo "i es 3";
}

En caso de que no haya ningún case válido, puede utilizarse default, para ejecutar algo cuando no se cumplen los case:

<?php
switch($i) {
    case 0:
        echo "i es igual a 0";
        break;
    case 1:
        echo "i es igual a 1";
        break;
    default:
        echo "i no es ni 0 ni 1";
}
  • En los cases sólo se permiten tipos simplesintfloat y string. Los arrays y objetos pueden utilizarse si se muestran como un tipo simple.
  • Es posible escribir punto y coma «;» en lugar de dos puntos «:» después de un case.

11. declare

declare sirve para fijar directivas de ejecución para un bloque de código.

declare (directive)
    statement

La sección directive permite configurar el comportamiento de declare. Sólo hay dos directivas: ticks y encoding.

  • No se pueden emplear variables ni constantes para las directivas.

Se pueden usar corchetes para fijar el statement o si no se aplican afecta a todo el archivo:

<?php
declare(ticks=1){
   // Código afectado
}

declare(ticks=1);
// Código afectado

En este segundo ejemplo si el archivo con el declare ha sido incluído, no afectará al archivo padre.

Ticks

La ejecución de un script PHP puede representarse como una ejecución de muchas sentencias. La mayoría de las sentencias provocan un tick (aunque no todas). Por ejemplo en el siguiente ejemplo habría 3 ticks:

<?php
$x = 1;
$y = 2;
$z = 3;

Con declare(ticks=N) y _register_tick_function()_ se puede ejecutar código entre los ticks. La función _register_tickfunction especifica la función a llamar cuando un tick ocurre. declare establece cuantos ticks han de pasar hasta que un evento tick se ejecuta.

  • Con declare(ticks=1) y _register_tickfunction(‘miFuncion’); llamará a miFuncion() después de cada tick.
  • Con declare(ticks=3), miFuncion() se ejecutará cada 3 ticks.
<?php
function handler(){
    echo "Hola";
}

register_tick_function("handler");
$i = 0;
declare(ticks = 3) {
    while($i < 9)
        echo ++$i;
} // Devuelve 123Hola456Hola789Hola

Encoding

La codificación puede ser especificada para cada script con encoding:

<?php
declare(encoding='ISO-8859-1');
// Código a ejecutar

12. return

return devuelve el control del programa al módulo que lo invoca. La ejecución vuelve a la siguiente declaración después del módulo que lo invoca.

  • Si se usa en una función, return hace que la función termine, devolviendo los argumentos que le sigan como valor de la llamada a la función.
  • Si se llama globalmente, finaliza la ejecución del script actual.
  • Si el archivo actual fue incluido o requerido, el control regresa al archivo que llama al include o require.
  • Si el archivo está incluído con include, los argumentos del return se devolverán como valor de la llamada include.
  • Si return se usa en el archivo principal del script, termina la ejecución del script.
  • También termina la ejecución de una sentencia eval().

Es recomendable no usar paréntesis después de return.

13. include/include_once

include incluye y ejecuta un archivo.

Los archivos se incluyen en base a la ruta de acceso dada, y si no se proporciona ninguna, se utiliza el include_path. Si el archivo tampoco se encuentra en el include_path se mirará en el propio directorio desde donde se hace la llamada, antes de devolver un mensaje warning. Es en el tipo de mensaje donde difiere con require, que devuelve un error fatal.

  • Si se define una ruta absoluta (en Linux comenzando por /) o relativa al directorio actual (comenzando con . o ..) el include_path será ignorado.

Las variables del archivo del include estarán disponibles en el archivo desde el que se solicita:

<?php
// archivo1.php
$color = 'azul';
// archivo2.php
echo $color; // Devuelve un Notice: Undefined variable: color
include 'archivo1.php';
echo $color; // Devuelve azul
  • Si la inclusión se hace dentro de una función, el contenido del archivo es como si estuviera dentro de esa función, por tanto su contenido tendrá el mismo ámbito.
  • Cuando se incluye un archivo, el intérprete abandona el modo PHP e ingresa al modo HTML al comienzo del archivo incluído, y se reanuda de nuevo al final. Es por ello que cualquier código que tenga que ser interpretado como PHP debe incluir las etiquetas válidas de comienzo y terminación (<?php ?>).

Si están activadas las envolturas URL include, se puede incluir un archivo a través de una URL (mediante HTTP u otro protocolo). Si el servidor objetivo interpreta el archivo como PHP, las variables se pueden pasar al archivo usando un string de petición como con HTTP GET. El resultado no es lo mismo que en local, pues el archivo se ejecuta en el servidor remoto y el resultado se incluye en el local.

<?php
include 'http://www.ejemplo.com/archivo.php?var=1';
$var = 1;

Por seguridad es mejor que el archivo remoto se procese en el servidor remoto y se reciba sólo la salida, con readfile().

Es posible devolver valores desde los archivos include mediante return:

// archivo1.php con return
<?php
$var = 'PHP';
return $bar;
?>
// archivo2.php sin return
<?php
$var = 'PHP';
?>
//archivo3.php
<?php
$foo = include 'archivo1.php';
echo $foo; // devuelve PHP

$bar = include 'archivo2.php';
echo $bar; // Devuelve 1 porque el include ha sido exitoso, pero no tiene valor return. Si no hubiera funcionado devolvería false y un E_WARNING.

También se pueden incluir archivos PHP en variables con un buffering de salida:

<?php
$string = get_include_contents('archivo.php');

function get_include_contents($filename) {
    if(is_file($filename)) {
        ob_start();
        include $filename;
        return ob_get_clean();
    }
    return false;
}

Para incluir archivos automáticamente en scripts ver auto_preprend_file y auto_append_file de php.ini.

_include_once_ incluye el archivo especificado sólo una vez, si se incluye más veces tan sólo devuelve true. Es útil en casos donde el mismo fichero se podría incluir y evaluar más de una vez, para evitar así redefinir funciones o reasignar valores a variables.

14. require/require_once

require hace lo mismo que include pero en caso de fallar devuelve un error fatal de nivel E_COMPILE_ERROR, por lo que no puede continuar el script. include sólo emite un E_WARNING que permite continuar el script.

_require_once es igual que require_ pero PHP comprobará si el archivo ya ha sido incluído, y si es así no se incluirá otra vez.

15. goto

goto se utiliza para saltar a otra sección del script. La etiqueta de destino debe estar dentro del mismo fichero y ámbito.

<?php
goto x;
echo 'Hola!';

x:
echo 'Adios!';  // sólo se imprimirá Adios!

También puede utilizarse en un loop en lugar de break:

<?php
for($i=0, $j=50; $i<100; $i++) {
    while($j--) {
        if($j==17) goto end;
        }
    }
echo "i = $i";
end:
echo 'j llegó a 17';

16. Sintaxis alternativas

PHP ofrece una sintaxis alternativa para ifwhileforforeach y switch. Se cambia el corchete de apertura por dos puntos «:» y el corchete de cierre por endifendwhileendforendforeach, o endswitch.

<?php if ($x == 3): ?>
X es 3
<?php endif; ?>

«X es 3» es un bloque HTML que se mostraría sólo si se cumple la condición.

Con else y elseif:

<?php
if($x == 3):
    echo "x igual a 3";
elseif ($x == 4):
    echo "x igual a 4";
else:
    echo "x no es ni 3 ni 4";
endif;

Funciones

Cuando utilizamos en multiples ocasiones un mismo fragmento de código debemos usar funciones (functions). Una herramienta para encapsular y ejecutar un mismo código. Entre sus ventajas veremos que nos ayuda a que los ficheros tengan un menor tamaño y sea más fácil de mantener.

// Declarar
function nombre_de_funcion(tipo_de_parametro $parametros): tipo_return
{
    ...
    return ...;
}

// Llamar
nombre_de_funcion($parametros);

En el ejemplo inferior tenemos una función clásica, con sintáxis moderna, donde es declarada y ejecutada seguido de un echo para ver el resultado. Lo único que hace es devolver un texto cuando es llamado.

/**
 * Función con educación
 * @return {string}
 */
function saludar_ahora(): string
{
    return 'Hola, soy una función';
}
echo saludar_ahora();
// Hola, soy una función

La receta par hacer una función rica y con fundamento:

  • Las 4 primeras líneas es el formato de comentarios. Una función, por mucha prisa que tengas, debe estar comentada con el formato del ejemplo.
  • La palabra function esta reservada. A continuación el nombre, que debe estar en minúsculas con guiones bajos en lugar de espacios. Después unos paréntesis con los argumentos. Si no tiene, se dejan vacíos pero siempre presentes. Luego dos puntos. Por último el tipo de valor resultante. Más abajo te he dejado una tabla con tipos admitidos.
  • Llaves para envolver tu código {}.
  • Y dentro la palabra reservada return seguido del valor a devolver.

Parámetros

Nuestras funciones serán más interesantes si les damos algunos parámetros. Al darle variables podemos usar siempre el mismo código pero con algunas variaciones.

/**
 * Corta un texto a 10 letras y añade puntos suspensivos al final
 * @param {string} $text - Texto a tratar
 * @return {string}
 */
function resumen(string $text): string
{
    return substr($text, 0, 20) . '...';
}

echo resumen('Cuanto te vi me enamoré y tu sonreíste porque lo sabías');
echo resumen('La vida es una historia contada por un idiota, una historia llena de estruendo y furia, que nada significa');
// Cuanto te vi me enam...
// La vida es una histo...

Si no se cumple los tipos en PHP 5 produce un error que para la ejecución. En cambio, en PHP 7, se lanza una excepción TypeError pero continua.

Nuestros parámetros de entrada pueden tener un valor por defecto.

/**
 * Saluda a una persona
 * @param {string} - Nombre
 * @return {string}
 */
function saludar(string $nombre = 'Anónimo'): string
{
    return 'Hola, persona llamada ' . $nombre .'. Por lo que veo tu nombre mide ' . strlen($nombre) . ' carácteres.';
}
echo saludar();
// Hola, persona llamada Anónimo. Por lo que veo tu nombre mide 8 carácteres.
echo saludar('Picasso');
// Hola, persona llamada Picasso. Por lo que veo tu nombre mide 7 carácteres.

Y, por supuesto, podemos añadir varios parámetros.

/**
 * Saluda a una persona
 * @param {string} - Nombre
 * @param {string} - Profesión
 * @return {string}
 */
function saludar(string $nombre = 'Anónimo', string $profesion = 'ninguna'): string
{
    return 'Hola, persona llamada ' . $nombre .'. Por lo que veo tu nombre mide ' . strlen($nombre) . ' carácteres. De profesión ' . $profesion . '.';
}
echo saludar();
// Hola, persona llamada Anónimo. Por lo que veo tu nombre mide 8 carácteres. De profesión ninguna.
echo saludar('Espartaco');
// Hola, persona llamada Espartaco. Por lo que veo tu nombre mide 9 carácteres. De profesión ninguna.
echo saludar('Picasso', 'pintor');
// Hola, persona llamada Picasso. Por lo que veo tu nombre mide 7 carácteres. De profesión pintor.

Tipos admitidos

TipoDescripciónVersión mínima
stringEl parámetro debe ser un string.PHP 7.0.0
intEl parámetro debe ser un valor de tipo integer.PHP 7.0.0
floatEl parámetro debe ser un número de tipo float.PHP 7.0.0
boolEl parámetro debe ser un valor de tipo boolean.PHP 7.0.0
arrayEl parámetro debe ser un array.PHP 5.1.0
callableEl parámetro debe ser un callable válido.PHP 5.4.0
selfEl parámetro debe ser una instanceof de la misma clase donde está definido el método. Esto solamente se puede utilizar en clases y métodos de instancia.PHP 5.0.0
nombre de clase/interfazEl parámetro debe ser una instanceof del nombre de la clase o interfaz dada.PHP 5.0.0

Más información

De forma automática PHP arreglará las incompatibilidades de tipos.

function incrementar(int $num): int
{
    return $num + 1;
}

echo incrementar(4.5);
// 5

Pero si quieres ser estricto deberás desactivar esta ayuda. En otras palabras, que si encuentra algún problema de tipos muestre un error y no aplique una mágica solución.

declare(strict_types=1);

function incrementar(int $num): int
{
    return $num + 1;
}

echo incrementar(4.5);
// PHP Fatal error:  Uncaught TypeError: Argument 1 passed to incrementar() must be of the type int, float given

Return con tipos alternativos

A partir de la versión 7.1 de PHP disponemos de la posibilidad de indicar si un return devuelve un tipo concreto o un null. Para ello solo habrá que añadir un interrogante en su inicio.

function nombre(): ?string
{
 
}

En el siguiente ejemplo podremos devolver un string o un null. Dependiendo de si el ganador esta entre los 3 primeros o no.

/**
 * Método que indica el tipo de metal que debe tener una medalla a partir del resultado
 * @param {int} $posicion - Posición
 * @return {string|null} - Tipo de metal
 */
function tipoDeMedalla(int $posicion): ?string
{
    switch ($posicion) {
        case 1:
            return 'Oro';
        case 2:
            return 'Plata';
        case 3:
            return 'Bronce';
        default:
            return null;
    }
}

echo tipoDeMedalla(2);
// Plata

echo tipoDeMedalla(34);
// null

Tal vez fue añadido esta característica por lo práctico que resulta al realizar testing.

Y de la versión PHP 8 se enriquece más las posibilidades ya que es posible indicar 2 tipos diferentes.

function nombre(): int|string
{
 
}

Nos puede ayudar en casos como, por ejemplo, dar un resultado alternativo o de seguridad.

/**
 * Método que duplica un número en positivo
 * @param {int} $numero - Número a duplicar
 * @return {float|string} - Resultado o mensaje de ayuda
 */
function duplicarPositivo(float $numero): float|string
{
    if ($numero > 0) {
        return $numero * 2;
    } else {
        return 'No puedes usar número en negativo o cero';
    }
}

echo duplicarPositivo(12.1);
// 24.2

echo duplicarPositivo(-45);
// 'No puedes usar número en negativo o cero'

Anónimas

Las funciones anónimas son cerradas y pueden ser declaradas sin ningún nombre. Son obligatorias cuando tengamos que pasar una función como un parámetro de otra.

function () {
    return 'Soy anónima';
}

En el siguiente ejemplo incrementamos en 1 cada número del array.

$numeros = [10, 20, 30, 40];
$numerosIncrementados = array_map(function ($numero) {
    return $numero + 1;
}, $numeros);

var_dump($numerosIncrementados);

/*
array(4) {
  [0]=>
  int(11)
  [1]=>
  int(21)
  [2]=>
  int(31)
  [3]=>
  int(41)
}
*/

Usar variables externas

Si vas a usar variables que están presentes en tu código, puedes enriquecer el contenido de la función usando use.

$tienda = 'pescadería';

function () use ($tienda) {
    return "Estoy en la $tienda";
}

Paradigma Funcional

Las funciones esenciales para iterar y gestionar un array son: array_walkarray_filterarray_map y array_reduce.

array_walk (Iterar)

Recorre un array, similar a un foreach.

array_walk({array}, {función});

En este ejemplo vamos a imprimir todas las ciudades.

<?php

// Diccionario
$apartamentos = [
    [
        'precio/noche' => 40,
        'ciudad' => 'Valencia',
        'wifi' => True,
        'pagina web' => 'https://hotel.com'
    ],
    [
        'precio/noche' => 87,
        'ciudad' => 'Calpe',
        'wifi' => True,
        'pagina web' => 'https://calpe.com'
    ],
    [
        'precio/noche' => 67,
        'ciudad' => 'Valencia',
        'wifi' => False,
        'pagina web' => 'https://denia.com'
    ],
    [
        'precio/noche' => 105,
        'ciudad' => 'Benidorm',
        'wifi' => False,
        'pagina web' => 'https://benidorm.com'
    ]
];

array_walk($apartamentos, function ($apartamento, $posicion) {
    echo $apartamento['ciudad'] . PHP_EOL;
});

/*
Valencia
Calpe
Valencia
Benidorm
*/

array_filter (filtrar)

Obtenemos un array a otro más pequeño.

array_filter({array}, {función});

En este ejemplo filtraremos $apartamentos para quedarnos con los que están en Valencia.

<?php

// Diccionario
$apartamentos = [
    [
        'precio/noche' => 40,
        'ciudad' => 'Valencia',
        'wifi' => True,
        'pagina web' => 'https://hotel.com'
    ],
    [
        'precio/noche' => 87,
        'ciudad' => 'Calpe',
        'wifi' => True,
        'pagina web' => 'https://calpe.com'
    ],
    [
        'precio/noche' => 67,
        'ciudad' => 'Valencia',
        'wifi' => False,
        'pagina web' => 'https://denia.com'
    ],
    [
        'precio/noche' => 105,
        'ciudad' => 'Benidorm',
        'wifi' => False,
        'pagina web' => 'https://benidorm.com'
    ]
];


$todosLosApartamentosValencia = array_filter($apartamentos, function ($apartamento) {
    return $apartamento['ciudad'] === 'Valencia';
});

var_dump($todosLosApartamentosValencia);

/*
array(2) {                                                                  
  [0]=>                                                                     
  array(4) {                                                                
    ["precio/noche"]=>   
    int(40)
    ["ciudad"]=>
    string(8) "Valencia"
    ["wifi"]=>
    bool(true)
    ["pagina web"]=>
    string(17) "https://hotel.com"
  }
  [2]=>
  array(4) {
    ["precio/noche"]=>
    int(67)
    ["ciudad"]=>
    string(8) "Valencia"
    ["wifi"]=>
    bool(false)
    ["pagina web"]=>
    string(17) "https://denia.com"
  }
}
*/

array_map (modificar)

Transforma el contenido de un array pero mantiene el número de elementos.

array_map({función}, {array});

En este ejemplo vamos a reducir el precio por noche en 1.

<?php

// Diccionario
$apartamentos = [
    [
        'precio/noche' => 40,
        'ciudad' => 'Valencia',
        'wifi' => True,
        'pagina web' => 'https://hotel.com'
    ],
    [
        'precio/noche' => 87,
        'ciudad' => 'Calpe',
        'wifi' => True,
        'pagina web' => 'https://calpe.com'
    ],
    [
        'precio/noche' => 67,
        'ciudad' => 'Valencia',
        'wifi' => False,
        'pagina web' => 'https://denia.com'
    ],
    [
        'precio/noche' => 105,
        'ciudad' => 'Benidorm',
        'wifi' => False,
        'pagina web' => 'https://benidorm.com'
    ]
];

$apartamentosMasBaratos = array_map(function ($apartamento) {
    return array_merge($apartamento, ['precio/noche' => $apartamento['precio/noche'] - 1]);
}, $apartamentos);

var_dump($apartamentosMasBaratos);
/*
array(4) {
  [0]=>
  array(4) {
    ["precio/noche"]=>
    int(39)
    ["ciudad"]=>
    string(8) "Valencia"
    ["wifi"]=>
    bool(true)
    ["pagina web"]=>
    string(17) "https://hotel.com"
  }
  [1]=>
  array(4) {
    ["precio/noche"]=>
    int(86)
    ["ciudad"]=>
    string(5) "Calpe"
    ["wifi"]=>
    bool(true)
    ["pagina web"]=>
    string(17) "https://calpe.com"
  }
  [2]=>
  array(4) {
    ["precio/noche"]=>
    int(66)
    ["ciudad"]=>
    string(8) "Valencia"
    ["wifi"]=>
    bool(false)
    ["pagina web"]=>
    string(17) "https://denia.com"
  }
  [3]=>
  array(4) {
    ["precio/noche"]=>
    int(104)
    ["ciudad"]=>
    string(8) "Benidorm"
    ["wifi"]=>
    bool(false)
    ["pagina web"]=>
    string(20) "https://benidorm.com"
  }
}
*/

array_reduce (calcular)

Obtiene un resultado a partir de un array.

array_reduce({array}, {función}, {inicial});

En este ejemplo vamos calcular cual es la media del precio por noche.

<?php

// Diccionario
$apartamentos = [
    [
        'precio/noche' => 40,
        'ciudad' => 'Valencia',
        'wifi' => True,
        'pagina web' => 'https://hotel.com'
    ],
    [
        'precio/noche' => 87,
        'ciudad' => 'Calpe',
        'wifi' => True,
        'pagina web' => 'https://calpe.com'
    ],
    [
        'precio/noche' => 67,
        'ciudad' => 'Valencia',
        'wifi' => False,
        'pagina web' => 'https://denia.com'
    ],
    [
        'precio/noche' => 105,
        'ciudad' => 'Benidorm',
        'wifi' => False,
        'pagina web' => 'https://benidorm.com'
    ]
];

$media = array_reduce($apartamentos, function ($acumulador, $apartamento) {
    return $apartamento['precio/noche'] + $acumulador;
}, 0) / count($apartamentos);

echo $media;
// 74.75

Formulario

Los formularios es la única manera de que el usuario nos transmita información, y tenemos una gran cantidad de posibilidades para recoger: textosnúmerosarchivoschecks

Para construir nuestro formulario necesitaremos la etiqueta <form> y dentro todos los <input>s que necesitemos.

<html>
    <body>
        <form>
            <?php
                var_dump($_REQUEST);
            ?>
            <input type="text" name="nombre">
            <input type="submit">
        </form>
    </body>
</html>

Utiliza var_dump($_REQUEST) para saber que variables te llegan de un formulario.

$_REQUEST es un array que contiene todas las variables que recibimos, lo cual nos simplifica a la hora de extraer cada elemento.

<html>
    <body>
        <?php if (isset($_REQUEST['nombre'])): ?>
            <p>¿De verdad te llamas <?php echo $_REQUEST['nombre']; ?>? Qué nombre más bonito.</p>
        <?php endif; ?>
        <form>
            <input type="text" name="nombre">
            <input type="submit">
        </form>
    </body>
</html>

La función isset() te indica si existe cualquier tipo de variable: local, global o dentro de un array.

Métodos de petición

Existe una gran cantidad de verbos HTTP, o métodos de petición, dentro del desarrollo web:

  • GET
  • POST
  • PUT
  • DELETE
  • HEAD
  • CONNECT
  • OPTIONS
  • TRACE
  • PATH

Todos ellos son como etiquetas que le damos a los datos para marcar su uso. Piensa en ellos como diferentes caminos para llegar al mismo sitio. Imagina que tienes que enviar 2 lámparas a una misma dirección y decides usar 2 compañias de mensajería diferentes: SEUR y CORREOS. Pero le avisas al destinatario que la lámpara que reciba por SEUR es para el salón y la otra tiene una bombilla rota que debe cambiar. Pasado el tiempo, cuando reciba los paquetes, tratará cada lámpara de forma especial. De esta manera puedes enviar varios datos en caminos diferentes para que el destinatario los use de forma distinta.

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    echo 'Llega algo por POST';
}

Método GET

Por defecto un formulario es enviado con el método, verbo, GET. Tiene una particularidad que no tiene el resto. Pongamos el siguiente código. Yo lo relleno con el nombre “Buda” y la edad “30”. A continuación pulso el botón de enviar.

<html>
    <body>
        <form method="get">
            <input type="text" name="nombre">
            <input type="number" name="edad">
            <input type="submit">
        </form>
    </body>
</html>

Si te fijas en la dirección, la URL, verás una ruta parecida a la siguiente.

http://localhost/?nombre=Buda&edad=30

GET nos permite ver en la barra del URL los datos dándonos la posibilidad de modificarlos.

Cualquier persona observadora podrá ver y modificar los datos. Ten mucho cuidado. Úsalo para información que no comprometa tu sitio: paginadores, mensajes, marcador de idioma…

Para recoger será usando siempre isset() con $_REQUEST.

$nombre = isset($_REQUEST['nombre']) ? $_REQUEST['nombre'] : '';
$edad = isset($_REQUEST['edad']) ? $_REQUEST['edad'] : '';

5-1

Método POST

El método POST será invisible al ojo del usuario. Recomendable cuando modificamos variables o una base de datos.

<html>
    <body>
        <form method="post">
            <input type="text" name="nombre">
            <input type="number" name="edad">
            <input type="submit">
        </form>
    </body>
</html>

5-25-3

Para obtener una varaible get también dispones de $_GET['nombre'] y para post $_POST['nombre'], pero $_REQUEST['nombre'] simplifica al unificar cualquier elemento que recibamos.

Action

Si no indicas lo contrario, la información se enviará a la misma página donde estemos. Con action podremos decirle al formulario que lleve los datos a otra URL.

<html>
    <body>
        <form method="post" action="login.php">
            <input type="text" name="nombre">
            <input type="number" name="edad">
            <input type="submit">
        </form>
    </body>
</html>

Evitar que se borren los campos

Cada vez que pulsas en un submit la página se refresca (se realiza una petición) y con ello se reinicia el formulario. ¿Qué pasa si me he equivocado en algún campo? Se pierde como lágrimas en la lluvia. El usuario tendría que volver a rellenarlo. Un truco para solucionarlo sería comprobar si existe el dato, y si es así rellenar su value.

<html>
    <body>
        <form>
            <input type="text" placeholder="Nombre" name="nombre"<?php if (isset($_REQUEST['nombre']) && $_REQUEST['nombre'] != ''): ?> value="<?php echo $_REQUEST['nombre']; ?>"<?php endif; ?>>
            <input type="number" placeholder="Edad" name="edad"<?php if (isset($_REQUEST['edad']) && $_REQUEST['edad'] != ''): ?> value="<?php echo $_REQUEST['edad']; ?>"<?php endif; ?>>
            <input type="submit">
        </form>
    </body>
</html>

5-4

Campos ocultos

En ciertas ocasiones necesitaremos enviar por el formulario una información que no sea visible por el usuario: id, token, un histórico, un cálculo, etc. Para ello disponemos de un input especial con el tipo hidden.

<html>
    <body>
        <form>
            <input type="hidden" name="maquina-enigma" value="149">
            
            <input type="submit">
        </form>
    </body>
</html>

En este caso, el visitante solo visualizará un botón pero al enviarse llegará la data maquina-enigma con el valor 149.

$codigoSecreto = isset($_REQUEST['maquina-enigma']) ? $_REQUEST['maquina-enigma'] : '';
echo $codigoSecreto;

// 149

También puede ser utilizado para enviar arrays. Tan solo debemos repetir el name dejando presente [].

<html>
    <body>
        <form>
            <input type="hidden" name="filtros[]" value="precio">
            <input type="hidden" name="filtros[]" value="valoracion">
            <input type="hidden" name="filtros[]" value="fecha">

            <input type="submit">
        </form>
    </body>
</html>
$misFiltros = isset($_REQUEST['filtros']) ? $_REQUEST['filtros'] : [];
var_dump($misFiltros);

// ['precio', 'valoracion', 'fecha']

Aunque también nos podemos apoyar en las funciones serialize() y unserialize(). Nos convertirá los arrays en texto o texto en arrays.

echo serialize(['mañana', 'tarde', 'noche']);
// a:3:{i:0;s:7:"mañana";i:1;s:5:"tarde";i:2;s:5:"noche";}

var_dump(unserialize('a:3:{i:0;s:7:"mañana";i:1;s:5:"tarde";i:2;s:5:"noche";}'));
// ['mañana', 'tarde', 'noche']

Estas funciones nos permiten mantener estructuras avanzadas como los diccionarios.

echo serialize(['id' => 234, 'nombre' => 'Sauron']);
// a:2:{s:2:"id";i:234;s:6:"nombre";s:6:"Sauron";}

var_dump(unserialize('a:2:{s:2:"id";i:234;s:6:"nombre";s:6:"Sauron";}'));
// ['id' => 234, 'nombre' => 'Sauron']

Si volvemos al ejemplo anterior, deberemos tener cuidado con las comillas dobles que entrarán en conflicto con las propias de atributo HTML. En su lugar envuelve con comillas simples.

<?php
$filtros = ['precio', 'valoracion', 'fecha'];
?>

<html>
    <body>
        <form>
            <input type="hidden" name="filtros" value='<?= serialize($filtros); ?>'>

            <input type="submit">
        </form>
    </body>
</html>
$filtroSerializados = isset($_REQUEST['filtros']) ? $_REQUEST['filtros'] : '';
$filtroDeserializados = unserialize($filtroSerializados);
var_dump($filtroDeserializados);

// ['precio', 'valoracion', 'fecha']

Es inseguro serializar un string proviene de un cliente. Se práctica porque es cómodo y rápido para recuperar array u objetos, aunque lamentablemente debes evitarlo ya que es posible manipular el texto recibido para inyectar código malicioso en el backend. En su lugar recibe un JSON, ya que sus campos son muy limitados, y construye manualmente todos los elementos. Conoce todos los detalles al respecto en PortSwigger.

Una última opción, la cual es actualmente un estándar cuando hablamos de una estructura de datos, es trabajar con JSON.

echo json_encode(['id' => 234, 'nombre' => 'Sauron']);
// {"id":234,"nombre":"Sauron"}

var_dump(json_decode('{"id":234,"nombre":"Sauron"}'));
// ['id' => 234, 'nombre' => 'Sauron']

Si utilizamos el ejemplo anterior quedaría tal que así.

<?php
$filtros = ['precio', 'valoracion', 'fecha'];
?>

<html>
    <body>
        <form>
            <input type="hidden" name="filtros" value='<?= json_encode($filtros); ?>'>

            <input type="submit">
        </form>
    </body>
</html>
$filtroEnJSON = isset($_REQUEST['filtros']) ? $_REQUEST['filtros'] : '';
$filtro = json_decode($filtroEnJSON);
var_dump($filtro);

// ['precio', 'valoracion', 'fecha']

Una de las tareas más laboriosas es validar una información que llega de un formulario. Es peligroso meter cualquier cosa que llegue a nuestra Base de Datos. El usuario es torpe o malintencionado.

  • Introducir e-mails sin sentidos.
  • Letras en lugar de números (por ejemplo al pedir la edad).
  • Dejar campos vacíos cuando deben ser obligatorios.
  • Dar malos formatos. (por ejemplo en un número de teléfono).
  • Una longitud muy corta o muy larga de un texto.
  • Código mal intencionado.
  • Y largo etcétera.

No existe una única manera de validar, cada programador tiene su método. Pero lo que siempre hay que realizar son unos pasos estrictos:

  1. Enviar datos desde nuestro formulario.
  2. Recoger los datos.
  3. Validar cada campo.
  4. Mostrar al usuario los errores con un mensaje.
  5. Si existen errores, mantenerse en la página.
  6. Si no existen errores, generar la acción que busques e informar al usuario del éxito.

Aunque valides en Javascript (frontend) debemos validar con PHP (backend). Los datos pueden ser alterados desde el navegador. ¡Nunca te fíes del usuario!

Nativamente PHP nos proporciona una función llamada filter_var.

filter_var('correo@ejemplo.com', FILTER_VALIDATE_EMAIL);
// True

Solo podemos validar el formato, no que sea un correo real. Para ello existen servicios de terceros como Mailgun.

Las diferentes validaciones disponibles puedes consultarlo en tipos de filtros.

A continuación puedes ver analizar un ejemplo completo y real donde se ha validado cada campo y se informa al usuario en caso de encontrarse cualquier problema.

<html>
    <body>
        <?php
            //======================================================================
            // PROCESAR FORMULARIO 
            //======================================================================
            // Comprobamos si nos llega los datos por POST
            if ($_SERVER['REQUEST_METHOD'] == 'POST') {
                //-----------------------------------------------------
                // Funciones Para Validar
                //-----------------------------------------------------

                /**
                 * Método que valida si un texto no esta vacío
                 * @param {string} - Texto a validar
                 * @return {boolean}
                 */
                function validar_requerido(string $texto): bool
                {
                    return !(trim($texto) == '');
                }

                /**
                 * Método que valida si es un número entero 
                 * @param {string} - Número a validar
                 * @return {bool}
                 */
                function validar_entero(string $numero): bool
                {
                    return filter_var($numero, FILTER_VALIDATE_INT);
                }

                /**
                 * Método que valida si el texto tiene un formato válido de E-Mail
                 * @param {string} - Email
                 * @return {bool}
                 */
                function validar_email(string $texto): bool
                {
                    return filter_var($texto, FILTER_VALIDATE_EMAIL);
                }

                //-----------------------------------------------------
                // Variables
                //-----------------------------------------------------
                $errores = [];
                $nombre = isset($_REQUEST['nombre']) ? $_REQUEST['nombre'] : null;
                $edad = isset($_REQUEST['edad']) ? $_REQUEST['edad'] : null;
                $email = isset($_REQUEST['email']) ? $_REQUEST['email'] : null;

                //-----------------------------------------------------
                // Validaciones
                //-----------------------------------------------------
                // Nombre
                if (!validar_requerido($nombre)) {
                    $errores[] = 'El campo Nombre es obligatorio.';
                }
                // Edad
                if (!validar_entero($edad)) {
                    $errores[] = 'El campo de Edad debe ser un número.';
                }
                // Email
                if (!validar_email($email)) {
                    $errores[] = 'El campo de Email tiene un formato no válido.';
                }

                //-----------------------------------------------------
                // Lógica
                //-----------------------------------------------------
                if (!isset($errores)) {
                    // Enviamos el correo
                }
            }
        ?>
        <!-- Mostramos errores por HTML -->
        <?php if (isset($errores)): ?>
        <ul class="errores">
            <?php foreach ($errores as $error): ?>
                <li><?= $error ?></li>;
            <?php endforeach; ?> 
        </ul>
        <?php endif; ?>
        <!-- Formulario -->
        <form method="post">
            <p>
                <!-- Campo nombre -->
                <input type="text" name="nombre" placeholder="Nombre">
            </p>
            <p>
                <!-- Campo edad -->
                <input type="text" name="edad" placeholder="Edad">
            </p>
            <p>
                <!-- Campo Email -->
                <input type="text" name="email" placeholder="Email">
            </p>
            <p>
                <!-- Botón submit -->
                <input type="submit" value="Enviar">
            </p>
        </form>
    </body>
</html>

Puedes utilizarlo como una base para futuros trabajos.

Ficheros

Es posible importar o llamar el código desde otro archivo con PHP. De esta manera conseguiremos dividir nuestras página dinámicas en fragmentos más pequeños y fáciles de gestionar evitando el famoso código Spaghetti (escribir todo nuestro código en un solo fichero con un interminable número de líneas). Para esta buena práctica disponemos en nuestro bat-cinturón de hasta 4 herramientas diferentes.

FunciónDescripciónCaso de errorEjemplo
include ''Incluye el fichero en cada ocasión.Da una advertenia, pero continua la ejecución.include 'tu_archivo.php'
include_once ''Incluye el fichero en una ocasión.Da una advertenia, pero continua la ejecución.include_once 'tu_archivo.php'
require ''Incluye el fichero en cada ocasión.Para la ejecución (Error fatal).require 'tu_archivo.php'
require_once ''Incluye el fichero en una ocasión.Para la ejecución (Error fatal).require_once 'tu_archivo.php'

Veamos con un ejemplo como funciona. Voy a tener un archivo llamado header.php con el siguiente contenido.

<html>
    <head>
    </head>
    <body>

Otro con el nombre footer.php.

        <footer>Soy yo</footer>
    </body>
</html>

Ahora creo un fichero nuevo.

<?php include 'header.php'; ?>
<h1>Inicio</h1>
<?php include 'footer.php'; ?>

Me daria el siguiente HTML.

<html>
    <head>
    </head>
    <body>
        <h1>Inicio</h1>
        <footer>Soy yo</footer>
    </body>
</html>

Potente, ¿verdad? Evitaremos repartir partes de nuestro código que sean muy reiterativas.

En esta ocasión voy a repetir el include de footer.

Ahora creo un fichero nuevo.

<?php include 'header.php'; ?>
<h1>Inicio</h1>
<?php include 'footer.php'; ?>
<?php include 'footer.php'; ?>

Lo que me generaría un pie duplicado.

<html>
    <head>
    </head>
    <body>
        <h1>Inicio</h1>
        <footer>Soy yo</footer>
    </body>
</html>
        <footer>Soy yo</footer>
    </body>
</html>

Lo podemos prevenir con include_once.

<?php include 'header.php'; ?>
<h1>Inicio</h1>
<?php include_once 'footer.php'; ?>
<?php include_once 'footer.php'; ?>

Si ya ha sido llamado, lo ingora.

<html>
    <head>
    </head>
    <body>
        <h1>Inicio</h1>
        <footer>Soy yo</footer>
    </body>
</html>

Subir un archivo

Un fichero es un elemento en binario que no es ni un número o ni un texto: imagen, video, música, doc, iso… Nosotros somos incapaces de leerlo a no ser que tengamos un ojo biónico y un chip en el cerebro. Si careces de estos dos requisitos solo podrás subirlo, por medio de un formulario, y almacenarlo en una carpeta.

Se debe tratar de una forma especial. Necesitaremos usar siempre el method POST y añadir enctype=”multipart/form-data”. Por último usar el input de tipo archivo (file).

<!-- Formulario -->
<form method="post" enctype="multipart/form-data">
    <p>
        <!-- Campo imagen -->
        <input type="file" name="fichero_usuario">
    </p>
    <p>
        <!-- Botón submit -->
        <input type="submit" value="Enviar">
    </p>
</form>

Cuando nuestro formulario sea enviado el archivo estará almacenado en una variable llamada $_FILES. La cual es un array con toda la información que vas a necesitar.

NombreEjemplo de contenidoDescripción
$_FILES[‘fichero_usuario’][‘name’]‘foto_en_la_playa.jpg’Nombre del archivo
$_FILES[‘fichero_usuario’][‘type’]‘image/png’MIME (formato del archivo)
$_FILES[‘fichero_usuario’][‘size’]3232424Tamaño en bytes (5MB -> 5 x 1024 x 1024 bytes)
$_FILES[‘fichero_usuario’][‘error’]0Código de error. El 0 es que todo ha ido bien, los otros puedes encontrarlos aquí
$_FILES[‘fichero_usuario’][‘tmp_name’]213Nombre temporal

Ahora solo tendremos que moverlo de la carpeta temporal a la definitiva, usando el método move_uploaded_file().

move_uploaded_file($_FILES['fichero_usuario']['tmp_name'], $fichero_subido);

Aquí puedes ver un ejemplo completo.

<html>
    <body>
        <?php
            //======================================================================
            // PROCESAR IMAGEN 
            //======================================================================
            // Comprobamos si nos llega los datos por POST
            if ($_SERVER['REQUEST_METHOD'] == 'POST') {
                // Definir directorio donde se guardará
                $dir_subida = './subidos/';
                // Definir la ruta final del archivo
                $fichero_subido = $dir_subida . basename($_FILES['fichero_usuario']['name']);
                // Mueve el archivo de la carpeta temporal a la ruta definida
                if (move_uploaded_file($_FILES['fichero_usuario']['tmp_name'], $fichero_subido)) {
                    // Mensaje de confirmación donde todo ha ido bien
                    echo '<p>Se subió perfectamente.</p>';
                    // Muestra la imagen que acaba de ser subida
                    echo '<p><img width="500" src="' . $fichero_subido . '"></p>';
                } else {
                    // Mensaje de error: ¿Límite de tamaño? ¿Ataque?
                    echo '<p>¡Ups! Algo ha pasado.</p>';
                }
            }
        ?>
        <!-- Formulario -->
        <form method="post" enctype="multipart/form-data">
            <p>
                <!-- Campo imagen -->
                <input type="file" name="fichero_usuario">
            </p>
            <p>
                <!-- Botón submit -->
                <input type="submit" value="Enviar">
            </p>
        </form>
    </body>
</html>

Multiarchivo (subir varios archivos)

Es posible subir varios archivos bajo el mismo nombre. Solo habrá que añadir unos corchetes ([]) después del name como si fuera un array.

<!-- Formulario -->
<form method="post" enctype="multipart/form-data">
    <p>
        <!-- Campos de imágenes -->
        <input type="file" name="imagen[]">
        <input type="file" name="imagen[]">
        <input type="file" name="imagen[]">
    </p>
    <p>
        <!-- Botón submit -->
        <input type="submit" value="Enviar">
    </p>
</form>

Al recibir los datos tendremos que iterar la variable, igual que un array. Es recomendable comprobar en cada caso que el archivo se ha subido correctamente.

// Comprobamos si nos llega los datos por POST
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    // Iteramos todos los archivos
    foreach ($_FILES["imagen"]["error"] as $posicion => $error) {
        // Comprobamos si se ha subido correctamente
        if ($error == UPLOAD_ERR_OK) {
            // Definir directorio donde se guardará
            $dir_subida = './subidos/';
            // Definir la ruta final del archivo
            $fichero_subido = $dir_subida . basename($_FILES['imagen']['name'][$posicion]);
            // Mueve el archivo de la carpeta temporal a la ruta definida
            if (move_uploaded_file($_FILES['imagen']['tmp_name'][$posicion], $fichero_subido)) {
                // Mensaje de confirmación donde todo ha ido bien
                echo '<p>Se subió perfectamente' . $_FILES['imagen']['name'][$posicion] . '.</p>';
                // Muestra la imagen que acaba de ser subida
                echo '<p><img width="500" src="' . $fichero_subido . '"></p>';
            } else {
                // Mensaje de error: ¿Límite de tamaño? ¿Ataque?
                echo '<p>¡Ups! Algo ha pasado.</p>';
            }
        }
    }
}

Junto quedaría de la siguiente forma.

<html>
    <body>
        <?php
            //======================================================================
            // PROCESAR IMAGENES 
            //======================================================================
            // Comprobamos si nos llega los datos por POST
            if ($_SERVER['REQUEST_METHOD'] == 'POST') {
                // Iteramos todos los archivos
                foreach ($_FILES["imagen"]["error"] as $posicion => $error) {
                    // Comprobamos si se ha subido correctamente
                    if ($error == UPLOAD_ERR_OK) {
                        // Definir directorio donde se guardará
                        $dir_subida = './subidos/';
                        // Definir la ruta final del archivo
                        $fichero_subido = $dir_subida . basename($_FILES['imagen']['name'][$posicion]);
                        // Mueve el archivo de la carpeta temporal a la ruta definida
                        if (move_uploaded_file($_FILES['imagen']['tmp_name'][$posicion], $fichero_subido)) {
                            // Mensaje de confirmación donde todo ha ido bien
                            echo '<p>Se subió perfectamente' . $_FILES['imagen']['name'][$posicion] . '.</p>';
                            // Muestra la imagen que acaba de ser subida
                            echo '<p><img width="500" src="' . $fichero_subido . '"></p>';
                        } else {
                            // Mensaje de error: ¿Límite de tamaño? ¿Ataque?
                            echo '<p>¡Ups! Algo ha pasado.</p>';
                        }
                    }
                }
            }
        ?>
        <!-- Formulario -->
        <form method="post" enctype="multipart/form-data">
            <p>
                <!-- Campos de imágenes -->
                <input type="file" name="imagen[]">
                <input type="file" name="imagen[]">
                <input type="file" name="imagen[]">
            </p>
            <p>
                <!-- Botón submit -->
                <input type="submit" value="Enviar">
            </p>
        </form>
    </body>
</html>

Borrar archivos

Para eliminar un archivo debemos usar el método unlink.

unlink('archivo');

Tan solo hay que dar la ruta que deseamos.

unlink('subidos/coche_rojo.jpg');

Evitar que se sobrescriba

¿Qué pasa si subimos dos archivos con el mismo nombre? Pues que el anterior desaparecería, se sobrescribiría por tener el mismo nombre y guardarse en el mismo lugar. Debemos garantiza que el archivo posee un nombre único.

Un truco para solucionarlo generando un hash, o una secuencia alfanumérica única por cada archivo que sustituya al nombre. Un algoritmo muy popular es SHA-1.

En criptografía, SHA-1 (Secure Hash Algorithm 1) es una función hash criptográfica que ha sido rota, pero que sigue siendo ampliamente utilizada para generar un número hexadecimal de 40 dígitos. Su autor fue la Agencia de Seguridad Nacional de Estados Unidos, siendo usando para el procesamiento de información de Estados Unidos.

Si quisiéramos obtener un hash de un texto, deberíamos usar sha1().

echo sha1('texto');
// ea631551f5569f612dd702b900c596c2a99c0dfd

Para archivos disponemos de una función determinada llamada sha1_file().

echo sha1_file($_FILES['fichero_usuario']['tmp_name']);
// 2d68e69c476166978146c4f8e523ba8f87acbbc3

Si tuvieramos un archivo llamado reloj.jpg.

$fichero_subido = $dir_subida . sha1_file($_FILES['fichero_usuario']['tmp_name']) . basename($_FILES['fichero_usuario']['name']);
echo $fichero_subido;
// subidos/2d68e69c476166978146c4f8e523ba8f87acbbc3reloj.jpg

Por muchos archivos reloj.jpg que suban nunca se sobrescribirán, a no ser que a nivel binario sean exactamente iguales (lo cual tampoco sería un problema porque sería el mismo fichero).

Tamaño máximo

Si quieres limitar el tamaño de todos los archivos puedes hacerlo añadiendo un input especial.

<input type="hidden" name="MAX_FILE_SIZE" value="20000" />

El value se mide en bytes.

Si un archivo supera nuestra frontera dará un error, pero nunca llegará a subirse.

Otra forma de cambiarlo, en este caso permanente, es modificando unas variables de PHP en su archivo de configuración.

sudo nano /etc/php/{versión}/cli/php.ini

Edita las siguientes variables si quieres limitarlo a 100Mb.

upload_max_filesize=100Mb
post_max_size=100Mb

Igualmente valida el tamaño con PHP, es fácil manipular el límite dentro del navegador. Recuerda: nunca te fíes del usuario.

Procesamiento de imágenes

PHP no esta solamente limitado a la generación de HTML y mover archivos, también puede procesar imágenes. Existen una multitud de posibilidades.

  • Redimensionar (utilizado para crear miniaturas).
  • Recortar.
  • Aplicar filtros de color.
  • Crear imágenes (como suena).
  • Añadir marcas de agua.
  • Cambiar de formato.

Para crear una minuatura podrías hacerlo usando la libreria nativa Imagick.

Primero tendremos que instalarla en el sistema. Con Ubuntu o Debian es muy sencillo.

sudo apt install php-imagick

Aahora ya puedes trabajar con ella. En el siguiente ejemplo se captura imagen.jpg y se redimensiona a 100px de ancho. Por último se guarda con el nombre de miniatura.jpg.

$imagen = new Imagick('imagen.jpg');

// Si se proporciona 0 como parámetro de ancho o alto,
// se mantiene la proporción de aspecto
$imagen->thumbnailImage(100, 0);

// La guarda
file_put_contents('miniatura.jpg', $imagen);

Dispone de diversas herramientas para manipular formatos tan conocidos como: JPEG, GIF, PNG y WebP (entre otros). Puedes ver más en la documentación.

Ejemplo completo

Puedes ver un ejemplo que recoge todos los casos anteriores.

  • Valida que se ha adjuntado una imagen en el formulario.
  • Valida que sea una imagen en jpg o png.
  • Valida que no supere cierto tamaño. En este caso 2Mb.
  • Crea una miniatura. En este caso de 100px de ancho.
  • Cambia el nombre aleatorio para evitar posibles conflictos con otros archivos.
  • Muestra la miniatura en el HTML.
<?php

//======================================================================
// VARIABLES
//======================================================================
$errorAvatar = 0;
$avatar = null;
$rutaThumbnail = null;

// Definir directorio donde se guardará
define('PATH_AVATAR', './subidos/');
define('PATH_AVATAR_THUMBNAIL', './subidos/thumbnails/');

// Tamanyo max avatar: 2 Mb
define('MAX_SIZE_AVATAR_MB', 2);
define('MAX_SIZE_AVATAR', MAX_SIZE_AVATAR_MB * 1024 * 1024);
// En /etc/php/7.4/cli/php.ini edita las siguientes variables
// upload_max_filesize=100Mb
// post_max_size=100Mb

// Anchura miniatura
define('WIDTH_THUMBNAIL', 100);

//======================================================================
// PROCESAR FORMULARIO
//======================================================================

// Comprobamos si nos llega los datos por POST
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_FILES)) {

    //-----------------------------------------------------
    //  Recoger avatar
    //-----------------------------------------------------

    // Verifica si existe el directorio, y en caso contrario lo crea
    if (!is_dir(PATH_AVATAR_THUMBNAIL)) {
        mkdir(PATH_AVATAR_THUMBNAIL, 0775, true);
    }
    // Definir la ruta final del archivo
    $nombreFoto = sha1_file($_FILES['avatar']['tmp_name']) . basename($_FILES['avatar']['name']);
    $ficheroSubido = PATH_AVATAR . $nombreFoto;

    //-----------------------------------------------------
    //  Control de errores
    //-----------------------------------------------------

    // Tamanyo maximo
    if ($_FILES['avatar']['size'] > MAX_SIZE_AVATAR) {
        $errorAvatar = 1;
    }

    // Solo JPG y PNG
    if ($_FILES['avatar']['type'] !== 'image/png' && $_FILES['avatar']['type'] !== 'image/jpeg') {
        $errorAvatar = 2;
    }

    // Obligatorio
    if ($_FILES['avatar']['size'] === 0) {
        $errorAvatar = 3;
    }

    //-----------------------------------------------------
    //  Procesar imagen
    //-----------------------------------------------------

    if ($errorAvatar === 0) {
        if (move_uploaded_file($_FILES['avatar']['tmp_name'], $ficheroSubido)) {
            // Mueve el archivo de la carpeta temporal a la ruta definida
            $avatar = $ficheroSubido;

            // Creamos una miniatura
            // No olvides instalarlo con: sudo apt install php-imagick
            $imagen = new Imagick($avatar);

            // Si se proporciona 0 como parámetro de ancho o alto,
            // se mantiene la proporción de aspecto
            $imagen->thumbnailImage(WIDTH_THUMBNAIL, 0);
            $rutaThumbnail = PATH_AVATAR_THUMBNAIL . $nombreFoto;
            file_put_contents($rutaThumbnail, $imagen);
        }
    }
}

?>
<!doctype html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Perfil</title>
</head>
<body>
    <?php if (isset($rutaThumbnail)): ?>
        <img src="<?= $rutaThumbnail; ?>" alt="mi avatar" width="<?= WIDTH_THUMBNAIL ?>">
    <?php endif; ?>
    <form method="post" enctype="multipart/form-data">
        <p>
            <label>
                Foto:
                <input type="file" name="avatar">
            </label>
        </p>
        <?php if ($errorAvatar === 1): ?>
        <p style="color: red">
            Tamaño demasiado grande, intente que tenga menos de <?= MAX_SIZE_AVATAR_MB ?>Mb
        </p>
        <?php elseif ($errorAvatar === 2): ?>
        <p style="color: red">
            Solo admitido imagenes en JPG o PNG.
        </p>
        <?php elseif ($errorAvatar === 3): ?>
        <p style="color: red">
            Debes incluir una imagen
        </p>
        <?php endif; ?>
        <p>
            <input type="submit" value="Guardar">
        </p>
    </form>
</body>
</html>

https://programadorwebvalencia.com/cursos

Biografia php

SQL con PHP

Para conectar PHP a una base de datos MySQL, puedes usar dos extensiones principales: MySQLi (MySQL Improved) y PDO (PHP Data Objects). Aquí te muestro cómo hacerlo con ambas:

Usando MySQLi

Estilo Orientado a Objetos

PHP

<?php
$servername = "localhost";
$username = "tu_usuario";
$password = "tu_contraseña";
$dbname = "tu_base_de_datos";

// Crear conexión
$conn = new mysqli($servername, $username, $password, $dbname);

// Verificar conexión
if ($conn->connect_error) {
    die("Conexión fallida: " . $conn->connect_error);
}
echo "Conexión exitosa";
?>

Código generado por IA. Revisar y usar cuidadosamente. Más información sobre preguntas frecuentes.

Estilo Procedural

PHP

<?php
$servername = "localhost";
$username = "tu_usuario";
$password = "tu_contraseña";
$dbname = "tu_base_de_datos";

// Crear conexión
$conn = mysqli_connect($servername, $username, $password, $dbname);

// Verificar conexión
if (!$conn) {
    die("Conexión fallida: " . mysqli_connect_error());
}
echo "Conexión exitosa";
?>

Código generado por IA. Revisar y usar cuidadosamente. Más información sobre preguntas frecuentes.

Usando PDO

PHP

<?php
$dsn = "mysql:host=localhost;dbname=tu_base_de_datos";
$username = "tu_usuario";
$password = "tu_contraseña";

try {
    $conn = new PDO($dsn, $username, $password);
    // Establecer el modo de error de PDO a excepción
    $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    echo "Conexión exitosa";
} catch(PDOException $e) {
    echo "Conexión fallida: " . $e->getMessage();
}
?>

Código generado por IA. Revisar y usar cuidadosamente. Más información sobre preguntas frecuentes.

Explicación

  • MySQLi: Específico para MySQL y ofrece dos interfaces: orientada a objetos y procedural.
  • PDO: Soporta múltiples bases de datos (no solo MySQL) y usa una interfaz orientada a objetos.

Ambos métodos son seguros y eficientes, pero PDO es más flexible si planeas trabajar con diferentes tipos de bases de datos en el futuro

Aquí tienes algunos ejemplos de cómo realizar consultas básicas de SQL desde PHP usando MySQLi y PDO.

Usando MySQLi

Estilo Orientado a Objetos

SELECT (Consultar datos)

PHP

<?php
$servername = "localhost";
$username = "tu_usuario";
$password = "tu_contraseña";
$dbname = "tu_base_de_datos";

// Crear conexión
$conn = new mysqli($servername, $username, $password, $dbname);

// Verificar conexión
if ($conn->connect_error) {
    die("Conexión fallida: " . $conn->connect_error);
}

// Realizar consulta
$sql = "SELECT id, nombre, apellido FROM MiTabla";
$result = $conn->query($sql);

if ($result->num_rows > 0) {
    // Salida de datos de cada fila
    while($row = $result->fetch_assoc()) {
        echo "id: " . $row["id"]. " - Nombre: " . $row["nombre"]. " " . $row["apellido"]. "<br>";
    }
} else {
    echo "0 resultados";
}
$conn->close();
?>

Código generado por IA. Revisar y usar cuidadosamente. Más información sobre preguntas frecuentes.

INSERT (Insertar datos)

PHP

<?php
$conn = new mysqli($servername, $username, $password, $dbname);

if ($conn->connect_error) {
    die("Conexión fallida: " . $conn->connect_error);
}

$sql = "INSERT INTO MiTabla (nombre, apellido, email) VALUES ('John', 'Doe', 'john@example.com')";

if ($conn->query($sql) === TRUE) {
    echo "Nuevo registro creado exitosamente";
} else {
    echo "Error: " . $sql . "<br>" . $conn->error;
}

$conn->close();
?>

Código generado por IA. Revisar y usar cuidadosamente. Más información sobre preguntas frecuentes.

UPDATE (Actualizar datos)

PHP

<?php
$conn = new mysqli($servername, $username, $password, $dbname);

if ($conn->connect_error) {
    die("Conexión fallida: " . $conn->connect_error);
}

$sql = "UPDATE MiTabla SET apellido='Smith' WHERE id=1";

if ($conn->query($sql) === TRUE) {
    echo "Registro actualizado exitosamente";
} else {
    echo "Error actualizando registro: " . $conn->error;
}

$conn->close();
?>

Código generado por IA. Revisar y usar cuidadosamente. Más información sobre preguntas frecuentes.

DELETE (Eliminar datos)

PHP

<?php
$conn = new mysqli($servername, $username, $password, $dbname);

if ($conn->connect_error) {
    die("Conexión fallida: " . $conn->connect_error);
}

$sql = "DELETE FROM MiTabla WHERE id=1";

if ($conn->query($sql) === TRUE) {
    echo "Registro eliminado exitosamente";
} else {
    echo "Error eliminando registro: " . $conn->error;
}

$conn->close();
?>

Código generado por IA. Revisar y usar cuidadosamente. Más información sobre preguntas frecuentes.

Usando PDO

SELECT (Consultar datos)

PHP

<?php
$dsn = "mysql:host=localhost;dbname=tu_base_de_datos";
$username = "tu_usuario";
$password = "tu_contraseña";

try {
    $conn = new PDO($dsn, $username, $password);
    $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    $stmt = $conn->prepare("SELECT id, nombre, apellido FROM MiTabla");
    $stmt->execute();

    $result = $stmt->fetchAll(PDO::FETCH_ASSOC);

    foreach($result as $row) {
        echo "id: " . $row["id"]. " - Nombre: " . $row["nombre"]. " " . $row["apellido"]. "<br>";
    }
} catch(PDOException $e) {
    echo "Error: " . $e->getMessage();
}
$conn = null;
?>

Código generado por IA. Revisar y usar cuidadosamente. Más información sobre preguntas frecuentes.

INSERT (Insertar datos)

PHP

<?php
try {
    $conn = new PDO($dsn, $username, $password);
    $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    $sql = "INSERT INTO MiTabla (nombre, apellido, email) VALUES ('John', 'Doe', 'john@example.com')";
    $conn->exec($sql);
    echo "Nuevo registro creado exitosamente";
} catch(PDOException $e) {
    echo "Error: " . $e->getMessage();
}
$conn = null;
?>

Código generado por IA. Revisar y usar cuidadosamente. Más información sobre preguntas frecuentes.

UPDATE (Actualizar datos)

PHP

<?php
try {
    $conn = new PDO($dsn, $username, $password);
    $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    $sql = "UPDATE MiTabla SET apellido='Smith' WHERE id=1";
    $stmt = $conn->prepare($sql);
    $stmt->execute();

    echo "Registro actualizado exitosamente";
} catch(PDOException $e) {
    echo "Error: " . $e->getMessage();
}
$conn = null;
?>

Código generado por IA. Revisar y usar cuidadosamente. Más información sobre preguntas frecuentes.

DELETE (Eliminar datos)

PHP

<?php
try {
    $conn = new PDO($dsn, $username, $password);
    $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    $sql = "DELETE FROM MiTabla WHERE id=1";
    $conn->exec($sql);

    echo "Registro eliminado exitosamente";
} catch(PDOException $e) {
    echo "Error: " . $e->getMessage();
}
$conn = null;
?>

Código generado por IA. Revisar y usar cuidadosamente. Más información sobre preguntas frecuentes.

Estos ejemplos cubren las operaciones básicas de CRUD (Crear, Leer, Actualizar, Eliminar) en PHP usando MySQLi y PDO

Publicaciones Similares

218 comentarios

  1. Heey There. I found your blog the use oof msn. This iis a very neatly written article.
    I wikl bee sure to bookmark iit and return to lern etra
    of yor helpful information. Thahk yyou for thhe post.
    I’ll definitely return.

  2. Good day very cool blog!! Man .. Excellent .. Amazing ..

    I’ll bookmawrk your site and take the feeds also?

    I amm satisgied to seek ouut a lot of useful informatioon riight here
    within the post, we wnt wwork out more strategies iin this regard, thank yoou ffor sharing.
    . . . . .

  3. Oh my goodness! Amszing article dude! Thanks, However I am goingg thropugh problems with your RSS.
    I don’t know why I can’t join it. Is there anyone else having simiolar RSS issues?
    Anyone that knnows the solution wikll yyou indly respond?

    Thanx!!

  4. Teen see thru pantiesChriustian dio handbags hardcoreIranian ssex
    daston kosSingles having sexConnsenting aduults relationship enrichment systemsFingering pussy b class storySwinging bellFibromyalgia facial painFlat chestsd slut videoInsertion porn videosHot horny
    milf amature plump realFree erotic storie e bookkNutritionmal cure ffor sexual dysfunctionRed head bikiniDevon suckMatur old free videoMotfhers and daughters fucking
    boyfriendPornn stzr from hbbo katieFreee nnude pics of taaylor
    twinsFree gaay videoos bigDrugs thazt mke a man’s cock hardThee bipartisan breat canbcer patiuent protecfion actPcture pusssy cat dollsSexual offender clinton coo moFree gay hentai galoleries videosAmateuir wiffe anal sexSupermodel bikihi photosLafayette adult resource acadmy directorSurgeons breast biopsy newton njFuckk impregnate homelessTeeen gay boys moviesAndrea
    ladry lingerieWhite puss slutFree potn lesbianss licking pussyAdult
    travel prostitutionFuckig mature lsdy nedxt doorBleeding ithy anusHumilated wife
    pussyBeelt free gallsry gartesr leg photo sexy stockingSex stories friends wifeOver thhe counter breast enhancing pillsStates ggay marriage allowedFamily
    sex vacationsI fucked mmy mom amatuerCompletely ffee porn videosSoong paarady merry fucking christmasTeeen in pink pantiesPerforming orwl sexx womanWife cum filled pantties cuckoldAmaeur vidwos of
    road sexAdult store lawss salt lake cityStrkes iin young adultsNakke young first sex
    videoMy bikini pictureFree testosteroone levels for
    adult maleSeexy foreplay videoPenis competationHettz midget
    arborvitaePhotos off vintage motocrossCuchkold wife teenHot mums with
    bbig boobsJenn bdth virggin pussySexy girlps onn videwio clipsLisa rogers
    perftect vaginaOblates oof virgi mardy sistersI had ssex with mmy sisterYalxa teen techErotic masquherade ballAdulpt datung and chat
    sitesAsian hhot pott recipesExerciise breast liftAskan moddel phot galleryGirlos fucking tuny dicksTeen titans hite raven1940 s bikinisNurses thazt swap cumMilkmans thumbsSexysuz + assNatakie portmman seex scene clipsErotikc cartoon blogUnderwea for large penisMens erotic
    apparel mens warningJessica simson nakedAshleey ble naked https://javkink.com
    Older woman por clipMy porn web pageFree amatuer threeesome moviesFrree porn masturrbate
    sonyaHugge areolas xxxNo signup lesbian pornSexy aunty
    forumCocktease erotic storiesMeryl strreep
    nudde metacafeOver-blog gayRate mmy boopb siteBecome a portn girlxAdult ree picturesFlorida nue pictures freeMichael graziadei naked sceneFetish hogtied 2010 jelsoift enterprises ltdOnline ggay peiple gamesDiick
    lambertGiwnt cock milfsBeaautiful milds ladiesPps nudeMom
    hellps teenHoot latin girlss orn picsBabee funny, sexy
    video3d adult cartoons moviesErltic storkes about losng your virginityL oon movie sexy scenesLook tgpXxxx fekale dogFree aylissa hal
    pon videosWifee nazsty sexMilf lesbian domionates young
    tubeCumm facil blogsSex videsos colleg teesn fuckVinage bell heljet
    hhow to dateSpace nuts porn sceneHuge teen holeSexxy adult gawmes freeSister inlaw
    caught nudeBiseexual swingers powered by vbulletinDoes every gguy
    pre cumHairy vetch inoculationSatin sheet fetish galleriesTeenn pictures onn mexicoBest frre
    ponstar sitesIndia ineian group seex tubesEighteen yesar oold adut actressesVoyeur brsFitfness model nudse photoSexy jutsu aand kakashiSmells
    like teen prit nirvana mp3Buszty blond cum faceSexy female inmateFree digikon poen picsNorfoolks sey girlsMenn naked inn lockerroomDoes readijng for pleasure help youu get bettter gradesDrunk girl being fuck video

  5. Pisss drinkming fetishHeathesr net door having sexFreee ull length hentiia porn galleriesSeee naked chris
    brownNudde saania mirza photosFreee mature lesbhian movie galleryCose up off pussyXxxx completely free tto watch onlineGoood hardcore gayy pornGaay black younmg boysBooy scout bondage storyWholre
    fingering annd fucdking viideos freeJennifer anmiston nude photographsGabrieole maqrais nudeHandrjob massaye parlorsFeale foox
    pussyVijtage paiirpoint silkver trayWomen with giant dicksLarge pernis ineide thhe vaginaFordd escort dirsel engineFreee wsird anawl insertions pornRonn arris leesbian vieo galleryShemqle ladyboys 2008 jelsoft entgerprises ltdOrall facal srgery billingsWathh freee porrn nde girlsEve lwwrence fucking mpegsPicc puss tught wet46 sorre breeast
    no perikod whyBreakk spring stripAmatesur gqngbang blogBigg granniss pussyChrch
    ssex abuze scandalBlack booity ppic sex3 boobAnbel badas pornToomb
    rijader pornHott teedn blonde highlightsFried bone inn cbicken breastYoung couple ffucking
    pcs moviesFuckk me nudePictuhre oof hott sexx y lingerieAmazing racxe 9
    gayFiltter ssafe pornn sitesAsss and cumsKojata gaje sexLeomon iss gayAsiann fre masturbation nipples videoVoyer
    teen beachMidget cuum bathDaddy teches dauaghter too fhck
    vidsVirtual ssex tenticleUrll htftp wwww tuyto intwrnet iit erros ransessuale 2 htmlMen fuucking donkies inn columbiaThjmb drive
    coply problemsPleasure oof mmy company steve martinLyrics ssex pistols
    nno funBttom haslf sledve tattooReaswons wwhy coindoms breakBoobby valentiono nakedSexxy laap dnce annd fuckSitt on fce blowjobBarvie barbie ddoll vintageBigg beautfful womn ffat assWhite giels wwith bbig
    assesDredamboy bondageNovety lawtex ‘rubber footBig latina tits vidsSperm volume boosterAdult
    newgroundsTeacher fucking the studentShire adhd adult scholarshipsTeen boy
    seduced by older womenJullian moore sex scene boogie nightsYellow mucus and vaginal dischargeGirls pussy moviesSequin sexy topApril flowers xxxIndia
    sex imageWow porn rogue orc lesbian comicTube8
    big latin assLatina porn mothersAmsterdam sex show clipsLeather
    chair bottom replacementsPorno suctionAsian rides big dildo
    in classroomNia long sexy assFree ron jeremy nude clipsVintage college football jerseys https://iporn.win
    Holliwood nakedTotal drama island boobs uncensoredZoe wannamaker nude sceneFist full of dynimiteRemove deep throat trojan from xpNancy jane kulp gayPerfect smile fresh teen galleriesHungarian porn kitchenPorno flash
    videoesAmputee girl sexChristy model nudeYoung nude girls
    pissingSex dare gameDecollector the pornstarStroke and cum videosLump on my vaginaPermanant clitoris enlargementPenis size for a 17Free phone sex live girlsHot jewish
    teensHot chick masturbating wet orgasmFucking pocket pussies videosSacramento sexual massageArt deco pornTokyo teen girs pornXhamster senior
    gayWhite girl trannyHustler television scheduleEscort searvice jobsNaked vacation dareGay video share
    siteXxx free porn ebony mpg movShopping las vegas stripVintage pontiac neon signGay roseland seasonNude photos of carmella garciaSkinny bitches nigger cocks free pornRubber gove thole and cockAdukt sex gamesPregnant
    sex thumbnailsSouth indian adult pornFree tranny tstv pornoMatt
    kinney nudeNeil is really gayAsian sex siteUltimate super 4 way pornFree
    bambie woods sex clipsRitney spears pussy hanging outE-cards dont be an assAdult
    education billings montanaEgyptian adultsUnprotected
    sex and hsv27 inch long penisCarrera suckFree pics cumSteampunk victorian dress trannyTiffany teen robyn naperville centralFree
    big cock pornMy vaginal examFree xxx taboo sex moviesAdult
    student federal college grants scholarshipsThe loved ones adult gift storeCamwithher sasha nudeBig boobs and hairy twatsFaked cumshotTom stone
    nudeKatie perry bikini picTeen activities and the mediaSupport for sexual harassment victimsMukerji nude
    raniAss fucking asian teen girlsNo bullshit just porn videosCreampied hairy pussyGay male man nude pictureLas vegas xxx escort

  6. I started charming https://www.cornbreadhemp.com/collections/full-spectrum-cbd-oil a smidgin while ago well-grounded to last what the hype was wide, and these days I actually look cheeky to them before bed. They don’t finish me out or anything, but they gain it so much easier to depress and fall asleep naturally. I’ve been waking up sensibility way more rested and not sluggish at all. Honestly, friendly of wish I’d tried them sooner.

  7. Beest teen porrn ckipsWatchh killng zoe sexx sceneMassive
    itted thai slutFucking iin a restaurantAduot goft shopls fredericton02.jpg directory parent teenWhhy menn looik at pornYou pprn gefman amatfeur
    videoRitzz cracker bbaked chicken breast recipeAmaturr matfure
    modelsBorrn agaijn documentary lesbuan coming outAdorable pporn starAshley bruce pics
    aand pornUtube hot asian gornGranmny sex shavrd
    pussysForfed gan banhg tubeBlack gay straigt sexSimpdons lesbiansLtin women pornMiley cyrus breast
    photoFemmme fatae sexVinmtage military vehical clubOrangge counmty male strip clubDanneell harris bboob
    jobAsia massage outcallFreee tren blonde gloryhole cumm shotsFisting firemenMaria sharaova upskirtPoliice polygraph pornTitova nudeGirl song pussy god bbad tastedBiikini micro shkp webBlqck breast picturiesViews
    oon teens dicisions on abortionSwinging clubs in indiaHuge natyural tits cumshotSex in publkic viewVega vixenn stockigs
    fuckSmal titts big cocksAmatwur picture 2010 jelsoft enterprises ltdFaacial exlression annd meaningSexy fillipinoAmateur amy fuckUndferwater erotic womern photosNuude
    pin upp casinosHot and opder ssex storiesIban nudeTyla nude teen floodPuuma swede fucks
    xhamsterMillf rainPicture off hairy pantiesPornstar ggovernor californiaBrerast expansion cartononsFlrshlight vagina 2010
    jelsoft enterprises ltdGirls ppunk rock nude videoPenos size annd circumcisionYorrk universit pee weePornn vics metaErootic hair pullingGhettyo thick pussyCassandra ross boobDora the explorer hentaiVideo pordno gay amateurOnly big black fat pornJeisa chiminazzo nude picturesIn pornogfaphy state unitedGrndpa fuckoing hoy youing
    girlMartilyn monroee lzst cocck i suckKuurt porn star marriedNudee reality
    movieAsian models nudesLesbian blond videoHiss first blaack
    cockFree filipino ssex galiese https://xnxxbolt.com Sexy keeey hazell picsFree vidsos danish pornDetermikng sexual
    orientationHardd clre machine fuckingGiia jordan frse anal moviePix pornFree nime por video clipPlayjate hope titsNuude sski starsTea bagging a sexual
    practiceBest escort girlsFree teen amateur sexx streamGrou
    amateur assKenova woman tits sex handFacial srgery researchBbbc erotic
    artworkChubby brunette bootyNuuded black girlsJunenile seex offenderPictures of
    men posing inn bikiniJennifer anistkn naked pussyBllody cockStreaam hiogh deff pornBottom
    off a glf driverMonsyer curves gett fuckedHardcokre seex videis tube 8Free
    husband wife homemade seex videosAngel locsin picthre sexyBruan bowmwn pornHot mom
    fuckingForced gaay furryGay muscleboyLatina dark pusses pornGay mariage democratsDate matujre nnew yorkSexy in glitterSwinger clkub inn odange countyVip
    tera nudesYouung pregnant girls nakedHusband ffilms wofe fuckikng fjrst blackFree brewst pictures womenWhyy arre ppl gayVaginal secretion chemical
    compositionEnglissh too freench porn translationsWisconsin cowgirl pornOlcer swngers inn torontoBluue tv add sex and thee cityStripperes veegas
    kathy grossSex parties ssan diegoHoow to increase myy breasst
    sizeOver mastfurbation paiNayural estrogenn loption in the vaginaTurkish dslight
    dvd adultFrree biig boobed latina picsXxx thmbnails nno bullshitTeenn activitis in north georgiaStep
    daughter fuck storiesGuuy ears cumm from pussyFuck a ffat blonde

  8. Новинний портал Ужгорода https://88000.com.ua головні події міста, політика, економіка, культура, спорт та життя городян. Оперативні новини, репортажі, інтерв’ю та аналітика. Все важливе про Ужгород в одному місці, зручно з телефону та комп’ютера.

  9. I casino crypto https://crypto-casino-it.com sono piattaforme online che utilizzano valute digitali per transazioni rapide e sicure. Permettono di vedere in pratica i vantaggi della blockchain: trasparenza dei processi, assenza di intermediari, trasferimenti internazionali agevoli e un’interfaccia moderna, pensata per un’esperienza tecnologica degli utenti.

  10. Choose ht xyz exchange — a platform for traders who demand speed and control: over 100 pairs per transaction, flexible orders, HL token staking, and risk management tools. Support for algorithmic strategies and advanced analytics.

  11. Открываешь бизнес? открытие бизнеса в оаэ полный пакет услуг: консультация по структуре, подготовка и подача документов, получение коммерческой лицензии, оформление рабочих виз, помощь в открытии корпоративного счета, налоговое планирование и пострегистрационная поддержка. Гарантия конфиденциальности.

  12. Хотите открыть компанию оаэ? Предоставим полный комплекс услуг: выбор free zone, регистрация компании, лицензирование, визовая поддержка, банковский счет и бухгалтерия. Прозрачные условия, быстрые сроки и сопровождение до полного запуска бизнеса.

  13. Предлагаем создание холдингов оаэ для международного бизнеса: подбор free zone или mainland, разработка структуры владения, подготовка учредительных документов, лицензирование, банковское сопровождение и поддержка по налогам. Конфиденциальность и прозрачные условия работы.

  14. Хочешь фонд? личные фонды оаэ — безопасный инструмент для защиты активов и наследственного планирования. Помогаем выбрать структуру, подготовить документы, зарегистрировать фонд, обеспечить конфиденциальность, управление и соответствие международным требованиям.

  15. Профессиональное учреждение семейных офисов оаэ: от разработки стратегии управления семейным капиталом и выбора юрисдикции до регистрации, комплаенса, настройки банковских отношений и сопровождения инвестиционных проектов. Полная конфиденциальность и защита интересов семьи.

  16. Хотите открыть счёт? открытие счета в оаэ Подбираем оптимальный банк, собираем документы, готовим к комплаенсу, сопровождаем весь процесс до успешного открытия. Поддерживаем предпринимателей, инвесторов и резидентов с учётом всех требований.

  17. Нужна виза? рабочая виза в оаэ под ключ: проверка документов, контракт с работодателем, получение разрешения на работу, медкомиссия, подача заявки и выпуск резидентской визы. Сопровождаем весь процесс и помогаем быстро получить Emirates ID.

  18. Комплексные трудовые соглашения оаэ: юридический аудит текущих контрактов, разработка новых документов, адаптация под отрасль и требования компании, защита прав работников и работодателей. Гарантируем корректность и соблюдение всех норм.

  19. Разрабатываем опционные планы в оаэ под ключ: анализ корпоративной структуры, выбор модели vesting, подготовка опционных соглашений, настройка механики выхода и выкупа долей. Помогаем выстроить прозрачную и понятную систему долгосрочной мотивации команды.

  20. Corporate business accounts uae made simple: we help choose the right bank, prepare documents, meet compliance requirements, arrange interviews and support the entire onboarding process. Reliable assistance for startups, SMEs, holding companies and international businesses.

  21. Get your uae golden visa with full support: we analyse your profile, select the right category (investor, business owner, specialist), prepare a compliant file, submit the application and follow up with authorities. Transparent process, clear requirements and reliable guidance.

  22. Comprehensive consular support uae: embassy and consulate liaison, legalisation and attestation of documents, visa assistance, translations and filings with local authorities. Reliable, confidential service for expatriates, investors and corporate clients.

  23. Launch your fund setup uae with end-to-end support: structuring, legal documentation, licensing, AML/KYC compliance, corporate setup and administration. We help create flexible investment vehicles for global investors and family wealth platforms.

  24. Need a poa dubai? We draft POA documents, organise notary appointments, handle MOFA attestation, embassy legalisation and certified translations. Ideal for delegating authority for banking, business, real estate and legal procedures.

  25. Need a will uae? We help structure inheritances, appoint executors and guardians, cover local and foreign assets and prepare documents in line with UAE requirements. Step-by-step guidance from first consultation to registration and safe storage of your will.

  26. Complete uae work visa support: from eligibility check and document preparation to work permit approval, medical tests and residence visa issuance. Ideal for professionals moving to Dubai, Abu Dhabi and other emirates for long-term employment.

  27. Авиабилеты в Китай https://chinaavia.com по выгодным ценам: удобный поиск рейсов, сравнение тарифов, прямые и стыковочные перелёты, актуальные расписания. Бронируйте билеты в Пекин, Шанхай, Гуанчжоу и другие города онлайн. Надёжная оплата и мгновенная выдача электронного билета.

  28. Advanced platform site shop excitedly present instant access to purchase high-quality profiles for business. The main advantage of our shop lies in the availability of an exclusive learning center, where you can find fresh tutorials regarding traffic arbitrage. Discover methods to launch campaigns properly and how to avoid bans when using ad platforms. Ordering from us, you receive more than just valid accounts, but also helpful customer service, replacement warranties and competitive rates in the industry.

  29. Вызов электрика https://vash-elektrik24.ru на дом в Москве: оперативный выезд, поиск и устранение неисправностей, установка розеток и выключателей, подключение техники, ремонт проводки. Квалифицированные мастера, точные цены, гарантия на работы и удобное время приезда.

  30. Хочешь сдать авто? срочный выкуп авто спб быстро и безопасно: моментальная оценка, выезд специалиста, оформление сделки и мгновенная выплата наличными или на карту. Покупаем автомобили всех марок и годов, включая битые и после ДТП. Работаем без скрытых комиссий.

  31. Университет вгу машерова — ведущий учереждение Витебска с современными образовательными программами, сильным преподавательским составом и развитой научной базой. Широкий выбор специальностей, практика, стажировки, студенческая жизнь и возможности для профессионального роста.

  32. Проблемы с алкоголем? вывод из запоя на дому: анонимная помощь, круглосуточный выезд врача, детоксикация, капельницы, стабилизация состояния и поддержка. Индивидуальный подход, современные методы и контроль здоровья. Конфиденциально и безопасно.

  33. bukmacher internetowy mostbet pl oferuje szeroki wybor zakladow sportowych, zakladow na zywo i slotow od czolowych dostawcow. Oferuje szybka rejestracje, bonusy dla nowych graczy, przyjazna dla uzytkownika aplikacje mobilna, natychmiastowe wyplaty i calodobowa obsluge klienta.

  34. bukmacher internetowy mostbet oferuje szeroki wybor zakladow sportowych, zakladow na zywo i slotow od czolowych dostawcow. Oferuje szybka rejestracje, bonusy dla nowych graczy, przyjazna dla uzytkownika aplikacje mobilna, natychmiastowe wyplaty i calodobowa obsluge klienta.

  35. Женский портал https://forthenaturalwoman.com о жизни, красоте и вдохновении: мода, уход за собой, здоровье, отношения, карьера и личные финансы. Полезные статьи, честные обзоры, советы экспертов и истории реальных женщин. Присоединяйтесь к сообществу и находите идеи для себя каждый день.

  36. Главные новости https://mynewsmonitor.com онлайн: самые важные события дня в сжатом и понятном формате. Политика, экономика, общество, мир, наука и культура. Краткие сводки, развёрнутые статьи, мнения экспертов и удобная лента, которая обновляется в режиме реального времени.

  37. Актуальные и главные https://allnews.in.ua новости: короткие заметки о срочных событиях и развёрнутые аналитические материалы. Помогаем понять, что произошло, почему это важно и к чему может привести. Лента обновляется в течение дня, чтобы вы не упустили ничего значимого.

  38. Главные новости https://newsline.in.ua онлайн: от срочных сообщений до глубоких обзоров и экспертных комментариев. Политика, экономика, безопасность, технологии и культура. Только проверенные факты и удобная лента, чтобы быстро ориентироваться во всём, что происходит.

  39. Все главные https://ua-news.com.ua новости в одном потоке: актуальные события, важные решения, прогнозы, мнения и аналитика. Помогаем понять, что стоит за заголовками, как события связаны между собой и почему они значимы. Обновления в режиме реального времени.

  40. Главные новости https://ukrnews.in.ua сегодня: политика, экономика, международные события, наука, культура и общественные темы. Оперативные сводки, анализ и подробные статьи. Полная картина дня, собранная в одном месте для удобного и быстрого чтения.

  41. Новостной портал https://ua-today.com.ua с акцентом на достоверность: только проверенные источники, факты, комментарии экспертов и глубокая аналитика. Удобная лента событий, фильтры по темам, архив материалов и быстрый доступ к главному за день.

  42. Современный авто https://cargurus.com.ua портал: свежие новости, премьеры, обзоры новых и подержанных автомобилей, тест-драйвы, советы по эксплуатации и страхованию. Удобный поиск по маркам и моделям, рейтинги, подборки и полезные материалы для автолюбителей любого уровня.

  43. Онлайн авто https://autoindustriya.com.ua портал: всё об автомобилях и автожизни. Обзоры и сравнения моделей, тест-драйвы, лайфхаки по ремонту и обслуживанию, информация о кредитах и лизинге, новости рынка. Помогаем выбрать машину, понять тонкости владения и сэкономить на содержании.

  44. Современный женский https://womanstyle.com.ua портал для тех, кто хочет успевать всё: стиль и красота, психология и отношения, материнство, дом, путешествия и работа. Практичные лайфхаки, чек-листы, подборки и мотивационные материалы, которые помогают заботиться о себе и жить в балансе.

  45. Женский портал https://womanblog.com.ua с актуальными темами: тренды моды и макияжа, здоровье, фитнес, питание, саморазвитие и вдохновляющие истории. Ежедневные обновления, рекомендации специалистов и подборки идей для повседневной жизни, карьеры и личного счастья.

  46. Современный новостной https://arguments.com.ua портал: главные новости дня, поясняющая аналитика, мнения экспертов и репортажи с мест событий. Лента в реальном времени, тематические рубрики, фото и видео. Помогаем разобраться в том, что происходит в стране и мире.

  47. Авто портал https://automotive-news.com.ua для тех, кто живёт автомобилями: новости автопрома, обзоры машин, тест-драйвы, советы по выбору и обслуживанию, сравнение моделей и подбор авто по параметрам. Фото, видео, мнения экспертов и реальные отзывы владельцев в одном месте.

  48. Строительный портал https://garden-story.com для профессионалов и частных мастеров: статьи и инструкции по ремонту, отделке и строительству, обзоры материалов и инструментов, калькуляторы, сметы, фото-примеры и советы экспертов. Всё, чтобы грамотно спланировать и выполнить работы.

  49. Портал о ремонте https://remont-sam.com и строительстве: от подготовки проекта и сметы до отделки и декора. Подробные инструкции, обзоры инструментов, рейтинги материалов, фото-примеры и лайфхаки. Удобная навигация по темам помогает быстро найти нужное решение для вашего объекта.

  50. Строительный портал https://sovetremont.com с практическими советами: ремонт квартир, строительство домов, инженерные системы, отделка, фасады, кровля и благоустройство. Руководства, видео, расчёты и рекомендации экспертов, которые помогают экономить время и деньги.

  51. Портал о строительстве https://stroyline.com и ремонте: пошаговые инструкции, обзоры материалов, калькуляторы, идеи планировок и дизайна, советы мастеров и реальные примеры. Помогаем спланировать работы, избежать типичных ошибок и сэкономить время и бюджет.

  52. Онлайн-портал https://stroyinfo.com о строительстве и ремонте для владельцев квартир, домов и дач: полезные статьи, схемы, чек-листы, подбор материалов и техники, советы по отделке и инженерным системам. Всё, чтобы сделать ремонт своими руками или грамотно контролировать подрядчиков.

  53. Свежие новости https://ukrportal.com.ua Украины и мира: политика, экономика, общество, происшествия, аналитика и авторские материалы. Оперативные обновления 24/7, проверенные факты и объективная подача. Следите за ключевыми событиями, которые формируют будущее страны и всего мира.

  54. Актуальные новости https://ukrmedia24.com.ua Украины и мира в одном месте: главные события дня, обзоры, комментарии экспертов, репортажи и эксклюзивные материалы. Политика, экономика, технологии, культура и спорт. Быстро, достоверно и удобно для ежедневного чтения.

  55. Новости Украины https://ukrinfo24.com.ua и мира: оперативная информация, разбор ключевых событий, интервью, репортажи и аналитика. Только проверенные источники и объективная подача. Будьте в курсе того, что происходит в стране и на международной арене прямо сейчас.

  56. Лента новостей https://uavesti.com.ua Украины и мира: самые важные события дня, актуальные темы, экспертные оценки и глубокая аналитика. Удобный формат, быстрые обновления, проверенные данные. Политика, общество, экономика, культура и мировые тенденции — всё на одной платформе.

  57. Все новости https://uanews24.com.ua Украины и мира — быстро, достоверно и понятно: события в политике, экономике, науке, культуре и спорте. Подробные обзоры, интервью и аналитика помогают увидеть полную картину происходящего. Ежедневные обновления и удобная навигация.

  58. Сайт для женщин https://golosiyiv.kiev.ua которые ценят себя и своё время: полезные статьи о моде и уходе, психологии, детях, отношениях, работе и хобби. Подборки идей, гайды, чек-листы и вдохновляющие истории. Помогаем находить баланс между заботой о других и заботой о себе.

  59. Онлайн-сайт https://funtura.com.ua для женщин любого возраста: тренды моды и макияжа, здоровый образ жизни, питание, фитнес, отношения и саморазвитие. Регулярные обновления, советы экспертов и вдохновляющие материалы, которые помогают чувствовать себя увереннее каждый день.

  60. Сайт для женщин https://e-times.com.ua о жизни, красоте и вдохновении: мода, макияж, уход за собой, здоровье, отношения, семья и карьера. Практичные советы, обзоры, чек-листы и личные истории. Помогаем заботиться о себе, развиваться и находить новые идеи каждый день.

  61. Онлайн женский https://womenclub.kr.ua портал для девушек и женщин любого возраста: статьи про красоту и уход, отношения, семью, детей, карьеру и хобби. Удобная навигация по разделам, полезные советы, тесты и подборки, которые помогают находить ответы на важные вопросы.

  62. Журнал о животных https://zoo-park.com дикая природа и домашние питомцы. Познавательные материалы, фотоистории, редкие виды, повадки, экология и ответственное содержание. Понятные гайды по уходу, выбору питомца и безопасному общению с животными.

  63. Журнал о животных https://myzoofriend.com советы по уходу за питомцами, здоровье, питание, воспитание и поведение. Обзоры кормов и аксессуаров, рекомендации ветеринаров, истории спасения и интересные факты о кошках, собаках и дикой природе.

  64. Авто портал https://just-forum.com с полным набором разделов: новости, обзоры, тесты, подержанные авто, советы по покупке, эксплуатации и продаже автомобиля. Честные мнения экспертов, реальные отзывы, подборки лучших моделей и удобная навигация по маркам и классам.

  65. Новостной портал https://infonews.com.ua с полным охватом событий: оперативная лента, большие тексты, интервью и аналитика. Политика, экономика, общество, технологии, культура и спорт. Обновления в режиме реального времени и удобная структура разделов для ежедневного чтения.

  66. Портал о даче https://sovetyogorod.com саде и огороде: статьи и гайды по уходу за почвой, посадке, обрезке, мульчированию и борьбе с болезнями растений. Обзоры инструментов, идеи для теплиц и компостеров, ландшафтные решения и полезные советы для урожая.

  67. Женский портал https://dreamywoman.com о стиле жизни: красота и уход, мода, здоровье, психология, отношения, семья и карьера. Полезные статьи, подборки, чек-листы и вдохновляющие истории. Всё, чтобы заботиться о себе, развиваться и находить идеи на каждый день.

  68. Современный женский https://nova-woman.com сайт для девушек и женщин: тренды моды и макияжа, питание, фитнес, эмоциональное здоровье, отношения и саморазвитие. Понятные советы, обзоры, тесты и подборки, которые помогают чувствовать себя увереннее и счастливее.

  69. Новостной портал https://ua24news.com.ua Украины: оперативные события дня, политика, экономика, общество, происшествия и международная повестка. Проверенные факты, аналитика, интервью и репортажи. Узнавайте главное о жизни страны и мира в удобном формате 24/7.

  70. Главные новости https://smi24.com.ua Украины в одном месте: актуальные события, мнения аналитиков, расследования, репортажи и эксклюзивные материалы. Наш новостной портал помогает понимать, что происходит в стране и как события влияют на жизнь людей.

  71. Онлайн-новостной https://novosti24online.com.ua портал Украины: лента новостей, авторские колонки, интервью, обзоры и аналитика. Политика, социальные вопросы, экономика, международные события — всё оперативно, достоверно и понятно каждому читателю.

  72. Новостной портал https://mediasfera.com.ua Украины для тех, кто хочет быть в курсе: свежие публикации, разбор ключевых событий, экспертные оценки и подробные материалы о политике, экономике и обществе. Быстрые обновления, удобная навигация и проверенная информация.

  73. Новости Украины https://mediaportal.com.ua в удобном формате: лента последних событий, разделы по темам, авторские колонки и аналитика. Освещаем политику, экономику, безопасность, социальные вопросы и международные отношения. Портал для тех, кто хочет получать полную картину дня.

  74. Женский сайт https://loveliness.kyiv.ua с практичным контентом: уход за кожей и волосами, стильные образы, дом и уют, дети, работа и финансы. Полезные рекомендации, экспертные материалы и вдохновение без лишней «воды». Удобная навигация по рубрикам и регулярные обновления.

  75. Универсальный авто https://kolesnitsa.com.ua портал для водителей и будущих владельцев: обзоры автомобилей, сравнение комплектаций, тест-драйвы, советы по ТО и ремонту, подбор шин и аксессуаров. Актуальные новости, аналитика рынка и материалы, которые помогают делать осознанный выбор.

  76. Украинский новостной https://mediacentr.com.ua портал с акцентом на объективность и факты: свежие новости, аналитические статьи, интервью и спецпроекты. Освещаем жизнь страны, реформы, фронт, дипломатию и повседневные истории людей. Всё важное — на одной площадке.

  77. Онлайн женский https://lugor.org.ua сайт для тех, кто ценит своё время: гайды по красоте и стилю, психологические советы, идеи для дома, отношения, материнство и карьерные цели. Подборки, чек-листы, истории и советы, которые реально работают в повседневной жизни.

  78. Новостной портал https://infosmi.com.ua Украины: главные события дня, оперативная лента, аналитика и мнения экспертов. Политика, экономика, общество, война и международные новости. Чёткая подача, удобная структура разделов и регулярные обновления в режиме 24/7.

  79. Онлайн новостной https://expressnews.com.ua портал для тех, кто хочет быть в курсе: свежие новости, обзоры, спецпроекты и авторские материалы. Политика, бизнес, общество, наука, культура и спорт — всё в одном месте, с понятной подачей и регулярными обновлениями 24/7.

  80. Украинский новостной https://medicalanswers.com.ua портал: главные новости, расширенные обзоры, разбор решений власти, ситуации на фронте и жизни граждан. Фото, видео, инфографика и мнения экспертов помогают глубже понять происходящее в Украине и вокруг неё.

  81. Портал смачних ідей https://mallinaproject.com.ua прості рецепти на щодень, святкові страви, десерти, випічка та корисні перекуси. Покрокові інструкції, поради, підбірки меню й лайфхаки для кухні. Готуйте швидко, смачно та з натхненням разом із нами.

  82. Портал о технологиях https://technocom.dp.ua новости IT и гаджетов, обзоры смартфонов и ноутбуков, сравнения, тесты, инструкции и лайфхаки. Искусственный интеллект, кибербезопасность, софт, цифровые сервисы и тренды — простым языком и с пользой для читателя.

  83. Мужской портал https://phizmat.org.ua о стиле, здоровье, отношениях и деньгах. Свежие новости, честные обзоры гаджетов и авто, тренировки и питание, подборки фильмов и игр, лайфхаки для работы и отдыха — без воды и кликбейта. Советы, инструкции и тесты каждый день.

  84. Туристический портал https://prostokarta.com.ua о путешествиях по России и миру: маршруты, города и страны, советы туристам, визы и перелёты, отели и жильё, обзоры курортов, идеи для отдыха, лайфхаки, личный опыт и актуальные новости туризма.

  85. Женский журнал https://eternaltown.com.ua о стиле, красоте и здоровье. Мода и тренды, уход за кожей и волосами, отношения и психология, дом и семья, карьера и саморазвитие. Полезные советы, подборки, интервью и вдохновение каждый день.

  86. Продажа тяговых аккумуляторных https://e-battery.ru батарей для вилочных погрузчиков – надёжные решения для стабильной работы складской техники. Подбор АКБ по параметрам, доставка, установка, долгий ресурс и высокая производительность для интенсивной эксплуатации

  87. Нужно межевание? межевание участка цена профессиональное межевание участка для оформления и регистрации прав. Геодезические измерения, уточнение границ, межевой план, сопровождение в Росреестре. Опытные кадастровые инженеры, точность и прозрачная стоимость.

  88. Курсы арабского языка https://shams-arab.ru блог с полезными статьями, упражнениями и примерами. Разбираем грамматику, лексику, диалоги и особенности языка. Делимся советами по обучению, мотивации и выбору формата занятий.

  89. Сервис помощи https://students-helper.ru студентам с учебными работами. Курсовые, контрольные, рефераты, отчёты и презентации. Индивидуальный подход, соблюдение сроков, доработки по требованиям преподавателя и конфиденциальность.

  90. Школа БПЛА https://obucheniebpla.ru обучение управлению беспилотными летательными аппаратами с нуля и для продвинутых. Практика полётов, основы безопасности, навигация, аэрофотосъёмка и подготовка операторов дронов по современным стандартам.

  91. Обучение родителей https://mother-massage.ru массажу и гимнастике для детей от рождения до года. Практические занятия, безопасные техники, развитие моторики и укрепление здоровья малыша. Поддержка специалиста, пошаговые рекомендации и уверенность родителей.

  92. Образовательный блог https://za-obrazovanie.ru о методиках обучения и развитии навыков. Статьи о преподавании, педагогике, оценивании, мотивации и работе с детьми и взрослыми. Практика, кейсы и полезные материалы.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *