---
language: PHP
contributors:
    - ["Malcolm Fell", "http://emarref.net/"]
    - ["Trismegiste", "https://github.com/Trismegiste"]
translators:
    - ["Mario Pérez", "https://github.com/MarioPerezEsteso"]
lang: es-es
filename: learnphp-es.php
---

Este documento explica el funcionamiento de PHP 5+.

```php
<?php // El código PHP debe estar dentro de etiquetas <?php

// Si tu fichero php solo contiene código php, es una buena práctica
// omitir la etiqueta de cierre php para prevenir salidas acidentales.

// Dos barras comienzan un comentario de una línea.

# También lo hará una almohadilla, pero // es más común

/*
     Escribir texto entre una barra-asterisco y asterisco-barra
     crea un comentario multilínea.
*/

// Utiliza "echo" o "print" para imprimir por pantalla
print('Hola '); // Imprime "Hola " sin salto de línea

// () son opcionales para print y echo
echo "Mundo\n"; // Imprime "Mundo" con un salto de línea
// (todas las sentencias deben finalizar con un punto y coma)

// Cualquier cosa fuera de las etiquetas <?php se imprime automáticamente
?>
¡Hola Mundo de nuevo!
<?php


/************************************
 * Tipos y variables
 */

// Las variables comienzan con el símbolo $.
// Una variable válida comienza con una letra o guión bajo,
// seguida de cualquier cantidad de letras, números o guiones bajos.

// Las variables booleanas no distinguen entre mayúsculas o minúsculas
$boolean = true;  // o TRUE o True
$boolean = false; // o FALSE o False

// Enteros
$int1 = 12;   // => 12
$int2 = -12;  // => -12
$int3 = 012;  // => 10 (un 0 al comienzo declara un número octal)
$int4 = 0x0F; // => 15 (un 0x al comienzo declara un hexadecimal)

// Floats (también conocidos como doubles)
$float = 1.234;
$float = 1.2e3;
$float = 7E-10;

// Eliminar variable
unset($int1);

// Operaciones aritméticas
$suma        = 1 + 1; // 2
$diferencia  = 2 - 1; // 1
$producto    = 2 * 2; // 4
$cociente    = 2 / 1; // 2

// Operaciones aritméticas de escritura rápida
$numero = 0;
$numero += 1;      // Incrementa $numero en 1
echo $numero++;    // Imprime 1 (incremento después la evaluación)
echo ++$numero;    // Imprime 3 (incremento antes de la evaluación)
$numero /= $float; // Divide y asigna el cociente a $numero

// Las cadenas de caracteres deben declararse entre comillas simples
$sgl_quotes = '$String'; // => '$String'

// Evita utilizar comillas dobles excepto para embeber otras variables
$dbl_quotes = "This is a $sgl_quotes."; // => 'This is a $String.'

// Los caracteres especiales solo son válidos entre comillas dobles
$escaped   = "Esto contiene \t un caracter tabulador.";
$unescaped = 'Esto solo contiene una barra y una t: \t';

// Rodea una variable entre corchetes si es necesario
$dinero = "Tengo $${numero} en el banco.";

// Desde PHP 5.3, los nowdocs pueden ser utilizados para multilíneas no interpoladas
$nowdoc = <<<'END'
Multi line
string
END;

// Heredocs interpola cadenas de caracteres
$heredoc = <<<END
Multi line
$sgl_quotes
END;

// La concatenación de cadenas de caracteres se realiza con .
echo 'Esta cadena de caracteres ' . 'está concatenada';

// Las cadenas de caracteres pueden ser pasadas como parámetros en un echo
echo 'Multiples', 'Parametros', 'Validos';  // Devuelve 'MultiplesParametrosValidos'


/********************************
 * Constantes
 */

// Una constante se define utilizando define()
// y nunca puede ser cambiada en tiempo de ejecución

// un nombre válido para una constante debe comenzar con una letra o guión bajo,
// seguido por cualquier número de letras, números o guiones bajos.
define("FOO",     "algo");

// el acceso a una constante se puede realizar llamando a la variable elegida sin un símbolo de $
echo FOO; // Devuelve 'algo'
echo 'Esto imprime '.FOO;  // Devuelve 'Esto imprime algo'



/********************************
 * Arrays
 */

// Todos los arrays en PHP son asociativos (hashmaps),

// Los arrays asociativos son conocidos como hashmaps en algunos lenguajes.

// Funciona con todas las versiones de php
$asociativo = array('Uno' => 1, 'Dos' => 2, 'Tres' => 3);

// PHP 5.4 introdujo una nueva sintaxis
$asociativo = ['Uno' => 1, 'Dos' => 2, 'Tres' => 3];

echo $asociativo['Uno']; // imprime 1

// Lista literales implícitamente asignados con claves enteras
$array = ['Uno', 'Dos', 'Tres'];
echo $array[0]; // => "Uno"

// Añadir un elemento al final de un array
$array[] = 'Cuatro';
// o
array_push($array, 'Cinco');

// Eliminar un elemento de un array
unset($array[3]);

/********************************
 * Salidas por pantalla
 */

echo('¡Hola Mundo!');
// Imprime ¡Hola Mundo! en stdout.
// Stdout es la página web si se está ejecutando en un navegador.

print('!Hola Mundo!'); // Es lo mismo que echo

// No es necesario el paréntesis en echo y print
echo '¡Hola Mundo!';
print '¡Hola Mundo!';

$parrafo = 'parrafo';

echo 100;      // Haz echo de escalares directamente
echo $parrafo; // o de variables

// Si las etiquetas cortas estás configuradas y tu versión de PHP es
// la 5.4.0 o superior, puede utilizar la sintaxis abreviada de echo
?>
<p><?= $parrafo?></p>
<?php

$x = 1;
$y = 2;
$x = $y; // $x ahora contiene el mismo valor que $y
$z = &$y;
// $z contiene ahora una referencia a $y. Un cambio en el valor de
// $z cambiará también el valor de $y, y viceversa.
// $x sin embargo, tendrá el valor original de $y

echo $x; // => 2
echo $z; // => 2
$y = 0;
echo $x; // => 2
echo $z; // => 0

// Dump muestra el tipo y valor de una variable en stdout
var_dump($z); // imprime int(0)

// Para mostrar el valor de una variable en un formato legible para humanos
print_r($array); // imprime: Array ( [0] => Uno [1] => Dos [2] => Tres )

/********************************
 * Lógica
 */
$a = 0;
$b = '0';
$c = '1';
$d = '1';

// assert lanza una advertencia si su argumento no es verdadero

// Estas comparaciones siempre serán verdaderas, incluso si los tipos no son los mismos.
assert($a == $b); // igualdad
assert($c != $a); // desigualdad
assert($c <> $a); // desigualdad alternativa
assert($a < $c);
assert($c > $b);
assert($a <= $b);
assert($c >= $d);

// Los siguiente solo será verdadero si los valores coinciden y son del mismo tipo.
assert($c === $d);
assert($a !== $d);
assert(1 === '1');
assert(1 !== '1');

// Operador 'Spaceship' (desde PHP 7)
// Devuelve 0 si ambos valores son iguales
// Devuelve 1 si el valor de la izquierda es mayor
// Devuelve -1 si el valor de la derecha es mayor

$a = 100;
$b = 1000;

echo $a <=> $a; //  0 porque son iguales
echo $a <=> $b; // -1 porque $a < $b
echo $b <=> $a; //  1 porque $b > $a

// Las variables pueden ser convertidas entre tipos, dependiendo de su uso.

$entero = 1;
echo $entero + $entero; // => 2

$string = '1';
echo $string + $string; // => 2 (los strings son convertidos a enteros)

$string = 'uno';
echo $string + $string; // => 0
// Muestra un 0 porque el operador + no puede convertir la cadena de caracteres 'uno' a un número

// La conversión de tipos puede ser utilizada para tratar a una variable como otro tipo

$boolean = (boolean) 1; // => true

$cero = 0;
$boolean = (boolean) $cero; // => false

// También hay funciones dedicadas a la conversión de tipos
$entero = 5;
$string = strval($entero);

$var = null; // Valor nulo


/********************************
 * Estructuras de control
 */

if (true) {
    print 'He sido imprimido';
}

if (false) {
    print 'Yo no';
} else {
    print 'He sido imprimido';
}

if (false) {
    print 'No se imprime';
} elseif(true) {
    print 'Sí se imprime';
}

// operador ternario
print (false ? 'No se imprime' : 'Sí se imprime');

// atajo para el operador ternario desde PHP 5.3
// equivalente de "$x ? $x : 'Sí'""
$x = false;
print($x ?: 'Sí');

// operador 'no definido' desde php 7
$a = null;
$b = 'Imprime';
echo $a ?? 'a no está definido'; // imprime 'a no está definido'
echo $b ?? 'b no está definido'; // imprime 'Imprime'


$x = 0;
if ($x === '0') {
    print 'No imprime';
} elseif($x == '1') {
    print 'No imprime';
} else {
    print 'Imprime';
}



// Esta sintaxis alternativa se utiliza para plantillas:
?>

<?php if ($x): ?>
Esto se muestra si la evaluación es verdadera.
<?php else: ?>
En otro caso, se muestra esto.
<?php endif; ?>

<?php

// Utiliza el switch para tener algo más de lógica.
switch ($x) {
    case '0':
        print 'Switch does type coercion';
        break; // Debes incluir un break para no seguir con los casos 'Dos' y 'Tres'
    case 'Dos':
    case 'Tres':
        // Hacer algo si la variables es 'Dos' o 'Tres'
        break;
    default:
        // Hacer algo por defecto
}

// Los bucles While, do...while y for te serán familiares
$i = 0;
while ($i < 5) {
    echo $i++;
}; // Imprime "01234"

echo "\n";

$i = 0;
do {
    echo $i++;
} while ($i < 5); // Imprime "01234"

echo "\n";

for ($x = 0; $x < 10; $x++) {
    echo $x;
} // Imprime "0123456789"

echo "\n";

$ruedas = ['bicicleta' => 2, 'coche' => 4];

// Los bucles foreach pueden iterar por arrays
foreach ($ruedas as $numero_ruedas) {
    echo $numero_ruedas;
} // Imprime "24"

echo "\n";

// También se puede iterar sobre las claves, así como sobre los valores
foreach ($ruedas as $vehiculo => $numero_ruedas) {
    echo "Un $vehiculo tiene $numero_ruedas ruedas";
}

echo "\n";

$i = 0;
while ($i < 5) {
    if ($i === 3) {
        break; // Sale fuera del bucle while
    }
    echo $i++;
} // Imprime "012"

for ($i = 0; $i < 5; $i++) {
    if ($i === 3) {
        continue; // Se salta esta iteración del bucle
    }
    echo $i;
} // Imprime "0124"


/********************************
 * Funciones
 */

// Define una función con "function":
function mi_funcion () {
    return 'Hola';
}

echo mi_funcion(); // => "Hola"

// Un nombre válido de función comienza con una letra o guión bajo, seguido de cualquier
// número de letras, números o guiones bajos.

function anadir ($x, $y = 1) { // $y es opcional y por defecto es 1
    $resultado = $x + $y;
    return $resultado;
}

echo anadir(4); // => 5
echo anadir(4, 2); // => 6

// $resultado no es accesible fuera de la función
// print $resultado; // Devuelve una advertencia.

// Desde PHP 5.3 se pueden declarar funciones anónimas
$inc = function ($x) {
    return $x + 1;
};

echo $inc(2); // => 3

function foo ($x, $y, $z) {
    echo "$x - $y - $z";
}

// Las funciones pueden devolver funciones
function bar ($x, $y) {
    // Utiliza 'use' para meter variables de fuera de la función
    return function ($z) use ($x, $y) {
        foo($x, $y, $z);
    };
}

$bar = bar('A', 'B');
$bar('C'); // Imprime "A - B - C"

// Puedes llamar a funciones utilizando cadenas de caracteres
$nombre_funcion = 'add';
echo $nombre_funcion(1, 2); // => 3
// Es útil para determinarl qué función ejecutar.
// O, utiliza call_user_func(callable $callback [, $parameter [, ... ]]);


// Puedes obtener todos los parámetros pasados a una función
function parametros() {
    $numero_argumentos = func_num_args();
    if ($numero_argumentos > 0) {
        echo func_get_arg(0) . ' | ';
    }
    $args_array = func_get_args();
    foreach ($args_array as $key => $arg) {
        echo $key . ' - ' . $arg . ' | ';
    }
}

parametros('Hola', 'Mundo'); // Hola | 0 - Hola | 1 - Mundo |

// Desde PHP 5.6 se puede obtener un número variable de argumentos
function variable($palabra, ...$lista) {
	echo $palabra . " || ";
	foreach ($lista as $item) {
		echo $item . ' | ';
	}
}

variable("Separa", "Hola", "Mundo") // Separa || Hola | Mundo |

/********************************
 * Includes
 */

<?php
// Los ficheros PHP incluidos deben comenzar también con la etiqueta de <?php

include 'mi-fichero.php';
// El código de mi-fichero.php ya está disponible en el entorno actual.
// Si el fichero no puede ser incluido (por ejemplo porque no se ha encontrado),
// se muestra una advertencia.

include_once 'mi-fichero.php';
// Si el código del fichero mi-fichero.php ya ha sido incluido, ya no se
// incluirá de nuevo. Este previene errores por múltiples declaraciones.

require 'mi-fichero.php';
require_once 'mi-fichero.php';
// Es lo mismo que el include(), pero require() causará un error fatal si el archivo
// no ha podido ser incluido.

// Contenido de mi-include.php:
<?php

return 'Cualquier cosa.';
// acabar archivo

// Los include y require también pueden devolver un valor.
$valor = include 'mi-include.php';

// Los archivos son incluidos en función de la ruta data o, si ninguna ruta es
// especificada se utilizará la directiva de configuración de include_path. Si el
// fichero no se encuentra en el include_path, include comprobará la ruta del código
// que lo llama antes de fallar.
/* */

/********************************
 * Clases
 */

// Las clases son definidas con la palabra clave class

class MiClase
{
    const MI_CONSTANTE      = 'valor'; // Una constante

    static $staticVar   = 'static';

    // Las variables estáticas y su visibilidad
    public static $publicStaticVar = 'publicStatic';
    // Accesible solo dentro de su clase
    private static $privateStaticVar = 'privateStatic';
    // Accesible desde la clase y las subclases
    protected static $protectedStaticVar = 'protectedStatic';

    // Las propiedades deben declarar su visibilidad
    public $propiedad    = 'public';
    public $instanceProp;
    protected $prot = 'protected'; // Accesible desde la clase y las subclases
    private $priv   = 'private';   // Accesible solo desde la clase

    // Crear un constructor con __construct
    public function __construct($instanceProp) {
        // Accede a las variables de la instancia con $this
        $this->instanceProp = $instanceProp;
    }

    // Los métodos son declarados como funciones dentro de una clase
    public function miMetodo()
    {
        print 'MiClase';
    }

    // la palabra clave final hará una función no sobreescribible
    final function noMePuedesSobreEscribir()
    {
    }

/*
 * Declarar propiedades de clase o métodos como estáticos los hace accesibles sin
 * necesidad de instanciar la clase. Una propiedad declarada como estática no
 * puede ser accedida mediante una instancia de la clase, pero sí mediante un
 * método estático.
 */

    public static function miMetodoEstatico()
    {
        print 'Soy estático';
    }
}

// Las constantes de una clase siempre pueden ser accedidas estáticamente
echo MiClase::MI_CONSTANTE;    // Muestra 'valor';

echo MiClase::$staticVar;  // Muestra 'static';
MiClase::miMetodoEstatico(); // Muestra 'Soy estático';

// Instancia una clase usando new
$mi_clase = new MiClase('Una instancia');
// Los paréntesis son opcionales si no se pasa ningún argumento.

// Accede a los miembros de una clase utilizando ->
echo $mi_clase->propiedad;     // => "public"
echo $mi_clase->instanceProp; // => "Una instancia"
$mi_clase->miMetodo();        // => "MiClase"


// Extender clases utilizando "extends"
class MiOtraClase extends MiClase
{
    function imprimePropiedadProtegida()
    {
        echo $this->prot;
    }

    // Sobreescribe un método
    function miMetodo()
    {
        parent::miMetodo();
        print ' > MiOtraClase';
    }
}

$mi_otra_clase = new MiOtraClase('Propiedad de instancia');
$mi_otra_clase->imprimePropiedadProtegida(); // => Imprime "protected"
$mi_otra_clase->miMetodo();               // Imprime "MiClase > MiOtraClase"

final class NoMePuedesExtender
{
}

// Puedes utilizar "métodos mágicos" para crear los getters y setters
class MiClaseMapeada
{
    private $propiedad;

    public function __get($key)
    {
        return $this->$key;
    }

    public function __set($key, $value)
    {
        $this->$key = $value;
    }
}

$x = new MiClaseMapeada();
echo $x->propiedad; // Utilizará el método __get()
$x->propiedad = 'Algo'; // Utilizará el método __set()

// Las clases pueden ser abstractas (utilizando la palabra clave abstract) o
// implementando interfaces (utilizando la palabra clave implements).
// Una interfaz puede ser declarada con la palabra clave interface.

interface InterfazUno
{
    public function hazAlgo();
}

interface InterfazDos
{
    public function hazOtraCosa();
}

// las interfaces pueden ser extendidas
interface InterfazTres extends InterfazDos
{
    public function hazCualquierOtraCosa();
}

abstract class MiClaseAbstracta implements InterfazUno
{
    public $x = 'hazAlgo';
}

class MiOtraClase extends MiClaseAbstracta implements InterfazDos
{
    public function hazAlgo()
    {
        echo $x;
    }

    public function hazOtraCosa()
    {
        echo 'hazOtraCosa';
    }
}


// Las clases pueden implementar más de una interfaz
class CualquierOtraClase implements InterfazUno, InterfazDos
{
    public function hazAlgo()
    {
        echo 'hazAlgo';
    }

    public function hazOtraCosa()
    {
        echo 'hazOtraCosa';
    }
}


/********************************
 * Traits
 */

// Los traits están disponibles desde PHP 5.4.0 y son declarados utilizando "trait"

trait MiTrait
{
    public function miMetodoTrait()
    {
        print 'Tengo trait';
    }
}

class MiClaseTrait
{
    use MiTrait;
}

$cls = new MiClaseTrait();
$cls->miMetodoTrait(); // Imprime "Tengo trait"


/********************************
 * Namespaces
 */

// Esta sección está separada porque una declaración de namespace debe
// ser la primera sentencia en un archivo. Vamos a suponer que no es el caso

<?php

// Por defecto, las clases existen en el namespace global y pueden ser llamadas
// explícitamente con una contrabarra.

$cls = new \MiClase();



// Estableder el namespace para un archivo
namespace Mi\Namespace;

class MiClase
{
}

// (de otro archivo)
$cls = new Mi\Namespace\MiClase;

// O de otro namespace.
namespace Mi\Otro\Namespace;

use Mi\Namespace\MiClase;

$cls = new MiClase();

// O se puede asignar un ales al namespace

namespace Mi\Otro\Namespace;

use Mi\Namespace as OtroNamespace;

$cls = new OtroNamespace\MiClase();


/**********************
* Late Static Binding
*
*/

class ClasePadre {
    public static function quien() {
        echo "Soy una " . __CLASS__ . "\n";
    }
    public static function test() {
        // Auto referencia a la clase en la que el método está definido
        self::quien();
        // Referencia estáticamente a la clase donde el método ha sido llamado
        static::quien();
    }
}

ClasePadre::test();
/*
Soy una ClasePadre
Soy una ClasePadre
*/

class ClaseHija extends ClasePadre {
    public static function quien() {
        echo "Pero soy una " . __CLASS__ . "\n";
    }
}

ClaseHija::test();
/*
Soy una ClasePadre
Pero soy una ClaseHija
*/


/**********************
*  Manejo de errores
*  
*/

// Una simple gestión de errores puede ser realizada con un bloque try catch

try {
    // Haz algo
} catch (Exception $e) {
    // Maneja la excepción
}

// Cuando se utilicen bloques try catch en un entorno con namespaces hay que
// usar lo siguiente

try {
    // Haz algo
} catch (\Exception $e) {
    // Maneja la excepción
}

// Excepciones personalizadas

class MiExcepcion extends Exception {}

try {

    $condicion = true;

    if ($condicion) {
        throw new MiExcepcion('Ha pasado algo');
    }

} catch (MiExcepcion $e) {
    // Manejar la excepción
}
```

## Más información

Visita la [documentación oficial de PHP](http://www.php.net/manual/) para más referencias
y apoyo de la comunidad.

Si estás interesado en buenas prácticas, visita
[PHP The Right Way](http://www.phptherightway.com/).

Si vienes de un lenguaje con una buena gestión de paquetes, visita
[Composer](http://getcomposer.org/).

Para estándares comunes, visita el PHP Framework Interoperability Group
[PSR standards](https://github.com/php-fig/fig-standards).