PHP es un lenguaje de scripting de servidor utilizado comúnmente para desarrollo web.
El codigo PHP puede estar incrustado dentro del código HTML.
PHP significaba originalmente Personal Home Page, pero ahora solo se le conoce como PHP:Hypertext Preprocessor.
El desarollo de PHP comenzo en 1995 con Rausmus Lerdorf que escribio varias aplicaciones CGI en C que utilizaba para mantener su sitio web a esta implementacion le llamaba "Personal Home Page/Forms Interpreter" o PHP/FI.
En ese mismo año Lerdof libero su PHP/FI bajo el nombre de "Personal Home Page Tools (PHP Tools)".
Zeev Suraski y Andi Gutmans reescribieron el parser en 1997 que seria la base del PHP 3, cambiando el nombre a PHP: Hypertext Preprocessor. Este lenguaje fue liberado oficialmente en 1998.
Debido a que PHP carece de un diseño general, ya que no fue desarrollado pensando en convertirlo en lenguaje de programación, este padece de muchas inconsistencias en los nombramientos de sus funciones y el orden de los parámetros.
Cuando PHP compila un archivo busca los tags de apertura y cierre, los cuales son <?php y ?> los cuales le indican al compilador la región en donde tiene que interpretar el código.
<?php
//La etiqueta de apertura siempre es obligatoria
//En cambio la de cierre solo es necesaria cuando se
//incrusta código PHP dentro de un HTML
?>
Las lineas en PHP se terminan con el símbolo ";".
En PHP se pueden declarar comentarios de 3 diferentes formas:
<?php
/*
Bloque de comentario
*/
//Comentario inline
#Otro inline
Las variables en PHP se declaran con el prefijo $ seguido del nombre de la variable.
El primer carácter debe ser una letra o un guion bajo "_", los siguientes caracteres pueden ser números, letras o mas guion bajo.
Aunque no se necesita asignar un tipo a la variable, estas reciben un tipo dependiendo del valor que se les asigne.
<?php
$variable1;
$mi_variable;
$_otraVariable;
PHP tiene soporte para 8 tipos de datos primitivos.
Guardan cadenas de caracteres como palabras, oraciones, etc.
Se pueden asignar mediante comillas simples (') o comillas dobles (").
<?php
$string1 = "Esto es un string";
$string2 = 'Esto tambien es un string';
$string3 = $string1 . $string2;
//La concatenación se realiza mediante el operador .
Sirven para almacenar números enteros, su capacidad depende de la plataforma en la que se utilice (32 o 64 bits). Los negativos se declaran con el signo (-).
<?php
$a = 1234; // decimal number
$a = -123; // a negative number
$a = 0123; // octal number (equivalent to 83 decimal)
$a = 0x1A; // hexadecimal number (equivalent to 26 decimal)
$a = 0b11111111; // binary number (equivalent to 255 decimal)
$a = -1234; // negative decimal
Sirven para almacenar números que requieran decimales.
<?php
$a = 1.234;
$b = 1.2e3;
$c = 7E-10;
Tipo para indicar condiciones de verdad, solo pueden almacenar los valores verdadero(True) o falso (False).
<?php
$a = True;
$b = true;
$c = False;
$d = false;
Los arreglos en PHP son mapas ordenados. Este tipo de objeto almacena de forma asociativa valores y llaves. Los valores de un arreglo también pueden ser otros arreglos.
<?php
$array = array(
"llave1" => "valor1",
"llave2" => "valor2"
);
$array = [
"llave1" => "valor1",
"llave2" => "valor2"
];
<?php
$array = array(
"llave1" => "valor1",
"llave2" => "valor2",
100 => -100,
-100 => 100
);
<?php
array(4) {
[0] => 1
[1] => "valor1",
["llave1"] => 2,
["llave2"] => "valor2"
};
También se pueden tener llaves de texto y enteras combinadas en un mismo arreglo.
El uso de llaves también es opcional, php en automático toma el ultimo entero utilizado como llave y lo aumenta.
<?php
$array = array(
"llave1" => "valor1",
"llave2" => "valor2",
100 => -100,
-100 => 100
);
echo $array["llave1"];
echo $array[100];
Se puede acceder a los elementos de un arreglo mediante la sintaxis: arreglo[llave]
<?php
class myclase
{
function ejecuta()
{
echo "Texto";
}
}
$a = new myclase;
$a->ejecuta();
Para crear un objeto se necesita crear una nueva instancia de una clase
<?php
$a = NULL;
Representa un objeto sin un valor. La única forma de declarar un null es mediante la constante NULL.
Una variable se considera null si:
Representan una variable especial, guardan una referencia a un recurso externo.
Son creadas apartir de funciones especiales.
Ejemplo de lo que almacena son:
Muestra | Nombre |
---|---|
$a == $b | Comparación |
$a === $b | Comparación exacta |
$a != $b | Diferencia |
$a !== $b | Diferencia exacta |
$a < $b | Menor que |
$a > $b | Mayor que |
$a <= $b | Menor igual que |
$a >= $b | Mayor igual que |
Para asignar constantes en PHP no se utiliza el signo (=), sino que se utiliza la función define('Nombre',valor).
Cuando se quiere utilizar su valor no se agrega el prefijo ($), sino solo se nombre y por convención siempre va todo en mayúsculas.
<?php
define('URL', 'https://www.google.com.mx');
define('PI', 3.14159);
<?php
echo URL;
echo PI;
<?php
if ($a > $b) {
echo "A es mayor que B";
} elseif ($a == $b) {
echo "A es igual a B";
} else {
echo "A es menor que B";
}
<?php
switch ($i){
case 0:
...
break;
case 1;
...
break;
...
default:
...
}
<?php
$i = 1;
while ($i <= 10) {
echo $i++;
}
<?php
for ($i = 1; $i <= 10; $i++) {
echo $i;
}
<?php
$array = array(1,2,3,4)
foreach($array as $value) {
echo $value;
}
//-------------------------------
$array = array("A" => 1, "B" => 2, "C" => 3, "D" => 4);
foreach($array as $key => $value) {
echo $key;
echo $value;
}
<?php
function nombre_funcion(){
print "<h1>Hola</h1>";
}
function nombre_funcion2($text){
print "<h1>$text</h1>";
}
function nombre_funcion3($param="default"){
print "<h1>$param</h1>";
}
En php las funciones no tienen un tipo especifico y tampoco es obligatorio tener return.
En php se puede incluir el código de otro archivo mediante las funciones
Include toma todo el contenido de otro archivo y lo agrega al actual, si hay algún problema con la carga del archivo entonces solo se levanta una advertencia.
Require trabaja de forma similar a include, la diferencia es que si hay problemas con la carga del archivo entonces se genera un error fatal y se detiene la ejecucion del script
También existe una variante para ambas funciones:
La única diferencia es que en estos el archivo que se indica solo puede ser cargado una sola vez.
<a href="http://locahost/index.htm">Home</a> -
<a href="http://locahost/ebxml">ebXML</a> -
<a href="http://locahost/ajax">AJAX</a> -
<a href="http://locahost/perl">PERL</a> <br />
Menu.php
<html>
<body>
<?php include("menu.php"); ?>
<p>This is an example to show how to include PHP file!</p>
</body>
</html>
PDO o Php Data Objects es una interfaz de abstracción de acceso a base de datos.
PDO brinda una interfaz unificada para conectarse a diferentes base de datos, para conectarse a una en especifico solo se debe utilizar su driver.
Como es una capa de abstracción utiliza las mismas funciones para ejecutar querys y obtener datos independientemente de la base de datos.
Los principales beneficios de pdo son:
Links PDO:
clase: https://phpdelusions.net/pdo/pdo_wrapper
comparativa: https://phpdelusions.net/pdo/mysqli_comparison
Para estrablecer una conexión con una base de datos se especifica un string de conexión.
Los datos basicos que utiliza son driver de base de datos(mysql), host, nombre de base de datos y el conjunto de caracteres.
mysql:host=localhost;dbname=test;port=3306;charset=utf8;
$host = '127.0.0.1';
$db = 'test';
$user = 'root';
$pass = '';
$charset = 'utf8';
$dsn = "mysql:host=$host;dbname=$db;charset=$charset";
$opt = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];
$pdo = new PDO($dsn, $user, $pass, $opt);
El usuario y password se indican en el constructor
Notas a tomar en cuenta:
Existen 2 formas de ejecutar querys en PDO.
Si no se van utilizar variables en el query entonces se puede recurrir al metodo PDO::query(). Esta funciona va ejecutar un query y regresa una variable tipo PDOStatement con los resultados del query.
$stmt = $pdo->query('SELECT name FROM users');
while ($row = $stmt->fetch())
{
echo $row['name'] . "\n";
}
La inyección de sql es un exploit que utiliza querys que no están formateados de forma correcta.
Este surge de la combinación de código con los datos que se utilizan para crear los querys dinámicos.
Por ejemplo si tenemos el siguiente código:
$name = "Bobby';DROP TABLE users; -- ";
$query = "SELECT * FROM users WHERE name='$name'";
Esto se compilaria de la siguiente forma:
SELECT * FROM users WHERE name='Bobby';DROP TABLE users; -- '
Si se hubiera formateado de forma correcta tendriamos el siguiente query:
SELECT * FROM users WHERE name='Bobby\';DROP TABLE users; -- '
Para evitarnos este problema utilizamos la función PDO::prepare($query), ademas se debe llamar la función execute().
En lugar de utilizar las variables se utiliza en posición el simbolo (?) o mediante nombre (:nombre).
$sql = 'SELECT * FROM users WHERE email = ? AND status=?';
//o
$sql = 'SELECT * FROM users WHERE email = :email AND status=:status';
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = ?
AND status=?');
$stmt->execute([$email, $status]);
$user = $stmt->fetch();
// or
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = :email AND
status=:status');
$stmt->execute(['email' => $email, 'status' => $status]);
$user = $stmt->fetch();
Cuando se usa de esta forma todos los parámetros se envían como string por default, si se necesita enviar un tipo especifico entonces se usan las funciones bindValue() o bindParam().
<?php
/* Execute a prepared statement by binding PHP variables */
$calories = 150;
$colour = 'red';
$sth = $dbh->prepare('SELECT name, colour, calories
FROM fruit
WHERE calories < :calories AND colour = :colour');
$sth->bindValue(':calories', $calories, PDO::PARAM_INT);
$sth->bindValue(':colour', $colour, PDO::PARAM_STR);
$sth->execute();
?>
<?php
/* Execute a prepared statement by binding PHP variables */
$calories = 150;
$colour = 'red';
$sth = $dbh->prepare('SELECT name, colour, calories
FROM fruit
WHERE calories < :calories AND colour = :colour');
$sth->bindValue(':calories', $calories, PDO::PARAM_INT);
$sth->bindValue(':colour', $colour, PDO::PARAM_STR);
$sth->execute();
?>
La función bindParam es muy similar, solo que tiene el añadido que es la única forma de utilizar los parámetros OUT e INOUT de los stored procedures.
<?php
/* Call a stored procedure with an INOUT parameter */
$colour = 'red';
$sth = $dbh->prepare('CALL puree_fruit(?)');
$sth->bindParam(1, $colour, PDO::PARAM_STR|PDO::PARAM_INPUT_OUTPUT, 12);
$sth->execute();
print("After pureeing fruit, the colour is: $colour");
?>
Cuando se quiere obtener la cantidad de registros modificados por un DELETE o UPDATE o cuando se busca obtener solo un registro se utiliza la función fetchColumn()
$stmt = $pdo->prepare("DELETE FROM goods WHERE category = ?");
$stmt->execute([$cat]);
$deleted = $stmt->fetchColumn();
$stmt = $pdo->prepare("SELECT name FROM table WHERE id=?");
$stmt->execute([$id]);
$name = $stmt->fetchColumn();
$count = $pdo->query("SELECT count(*) FROM table")->fetchColumn();
Cuando se quiere obtener multiples filas es facil obtener resultados mediante un foreach, utilizando cada fila como arreglo asociativo.
$stmt = $pdo->query('SELECT name FROM users');
foreach ($stmt as $row)
{
echo $row['name'] . "\n";
}
La función fetch nos regresa una fila a la vez, mientras que avanza el puntero a la siguiente fila en los resultados, por lo cual se recomienda utilizar el foreach.
Esta función tiene distintas formas de devolver los resultados, lo cual se configura mediante una variable.
Otra opción del fetch es PDO::FETCH_CLASS el cual va crear objetos apartir de una clase en particular.
$news = $pdo->query('SELECT * FROM news')->setFetchMode(PDO::FETCH_CLASS,'News');
$news->fetch();
Hay que considerar que:
Si se quieren obtener todos los resultados se utiliza la función fetchAll.
Algunas aspectos a considerar con esta función:
Por default la funcion fetchAll regresa arreglos enumerados que consisten de todas las filas obtenidas.
El formato de estas filas puede ser cambiado mediante las propiedades PDO::FETCH_NUM, PDO::FETCH_ASSOC, PDO::FETCH_OBJ, etc.
$data = $pdo->query('SELECT name FROM users')->fetchAll();
var_export($data);
/*
array (
0 => array('name' => 'John'),
1 => array('name' => 'Mike'),
2 => array('name' => 'Mary'),
3 => array('name' => 'Kathy'),
)*/
Cuando solo se va obtener una sola columna por fila entonces es muy practico utilizar PDO::FETCH_COLUMN para obtener textos planos en lugar de arreglos
$data = $pdo->query('SELECT name FROM users')->fetchAll(PDO:
:FETCH_COLUMN);
/* array (
0 => 'John',
1 => 'Mike',
2 => 'Mary',
3 => 'Kathy',
)*/
Cuando se quieren obtener arreglos enumerados por otra columna de la fila se utiliza PDO::FETCH_KEY_PAIR, para obtenerlos en la forma llave=>valor
$data = $pdo->query('SELECT id, name FROM users')->fetchAll(PDO:
:FETCH_KEY_PAIR);
/* array (
104 => 'John',
110 => 'Mike',
120 => 'Mary',
121 => 'Kathy',
)*/
Cuando tambien se quieren obtener los resultados enumerados por una columna, pero obtener toda la fila en lugar de un solo valor se utiliza PDO::FETCH_UNIQUE
$data = $pdo->query('SELECT * FROM users')->fetchAll(PDO::FETCH_UNIQUE);
/* array (
104 => array (
'name' => 'John',
'car' => 'Toyota',
),
110 => array (
'name' => 'Mike',
'car' => 'Ford',
),
120 => array (
'name' => 'Mary',
'car' => 'Mazda',
),
121 => array (
'name' => 'Kathy',
'car' => 'Mazda',
),
)*/
La primer columna que seleccione el query deberá ser única, en este caso se asume que la primera sera un id.
Otra opcion muy poderosa es PDO::FETCH_GROUP la cual nos agrupa los resultados en arreglos anidados en base a una columna
$data = $pdo->query('SELECT sex, name, car FROM users')->fetchAll(PDO::FETCH_GROUP);
/* array (
'male' => array (
0 => array (
'name' => 'John',
'car' => 'Toyota',
),
1 => array (
'name' => 'Mike',
'car' => 'Ford',
),
),
'female' => array (
0 => array (
'name' => 'Mary',
'car' => 'Mazda',
),
1 => array (
'name' => 'Kathy',
'car' => 'Mazda',
),
),
)*/
La primer columna seleccionada en el query sera la que se utilice como agrupador.
Cuando se utilizan id's en secuencia o con la opción 'auto_increment' se puede obtener el ultimo id insertado mediante la función PDO::lastInsertId.
Un detalle que surge cuando se ejecutan stored procedures es que siempre regresa un conjunto de resultados extra, es decir, si el SP solo ejecuta un select entonces pdo recibirá dos grupos de resultados: Uno que contiene el resultado del query y otro vació.
Por lo tanto si después de ejecutar un SP se trata de ejecutar otro query entonces recibiremos un error a menos que se ejecute la función nextRowset.
$stmt = $pdo->prepare("CALL bar()");
$stmt->execute();
$data = $stmt->fetchAll();
$stmt->nextRowset();
/* Despues de esto ya se puede ejecutar otro query
si el sp no regresaba mas de un grupo de resultados */
Si no estamos seguros si el siguiente grupo de resultados esta vació, entonces se puede utilizar la función columnCount para determinar si en verdad esta vació.
PHP tiene 2 arreglos asociativos para manejar las llamadas http get y post.
Reciben las peticiones que les corresponden, la principal diferencia es que $_GET no soporta datos binarios, por lo tanto no se puede utilizar para subir archivos al servidor.
<?php
if( $_GET["name"] || $_GET["age"] ) {
echo "Welcome ". $_GET['name']. "<br />";
echo "You are ". $_GET['age']. " years old.";
exit();
}
?>
<html>
<body>
<form action = "<?php $_PHP_SELF ?>" method = "GET">
Name: <input type = "text" name = "name" />
Age: <input type = "text" name = "age" />
<input type = "submit" />
</form>
</body>
</html>
<?php
if( $_POST["name"] || $_POST["age"] ) {
echo "Welcome ". $_POST['name']. "<br />";
echo "You are ". $_POST['age']. " years old.";
exit();
}
?>
<html>
<body>
<form action = "<?php $_PHP_SELF ?>" method = "POST">
Name: <input type = "text" name = "name" />
Age: <input type = "text" name = "age" />
<input type = "submit" />
</form>
</body>
</html>
Una de las formas para mantener datos accesibles a distintas paginas de un mismo sitio es mediante el uso de una sesión.
Las sesiones son almacenadas en un archivo en un directorio temporal la cual puede ser cambiada en el archivo de configuración de php (php.ini).
Cuando una sesión es creada ocurre lo siguiente:
Para iniciar la sesión se utiliza la función session_start().
Esta función revisa si ya hay una sesión iniciada, sino entonces inicia una nueva.
Todas las variables de sesión se almacenan en el arreglo asociativo $_SESSION. Estas variables estarán disponibles durante el tiempo de duración de la sesión.
<?php
session_start();
if( isset( $_SESSION['counter'] ) ) {
$_SESSION['counter'] += 1;
}else {
$_SESSION['counter'] = 1;
}
$msg = "You have visited this page ". $_SESSION['counter'];
$msg .= "in this session.";
?>
<html>
<head>
<title>Setting up a PHP session</title>
</head>
<body>
<?php echo ( $msg ); ?>
</body>
</html>
Si se desea destruir la sesión entonces se utiliza la funcion session_destroy().
Esta función elimina todas las variables que están almacenadas en la sesión, si solo se quiere eliminar una variable en especifico entonces se utiliza la función unset().
<?php
unset($_SESSION['counter']);
session_destroy();
Una de las formas para proteger datos importantes como las contraseñas de los usuarios en un sistema es mediante el uso de funciones hash.
La ventaja y desventaja a la vez de estas funciones es que una vez que un dato se pasa por una función hash este ya no se puede recuperar.
Una de las opciones que tiene php para realizar esto es mediante la función password_hash.
Esta función utiliza por default el algoritmo "bcrypt", pero esta diseñado a cambiar a futuro.
<?php
echo password_hash("mipasswordsuperseguro", PASSWORD_DEFAULT)."\n";
Como esta función agrega un "salt" al texto que se le envía, para la validación de estos se debe utilizar la función password_verify.
La ventaja de esta función es que no se necesita almacenar de forma separada el valor "salt" para su validación.
<?php
$hash = '$2y$10$oxYQcg7vXgCE8v/iDgchzepDXJ5B1rUX12Mfj/WM0UO76C7KAecRi';
if (password_verify("mipasswordsuperseguro", $hash)) {
echo "Password correcto!";
} else {
echo "Password equivocado";
}
Cuando se desea enviar los header HTTP de forma manual se utiliza la función header de php.
Es importante mencionar que para esta función tenga efecto debe llamarse antes de devolver cualquier contenido, ya sea que se imprima algo con php o directamente un elemento html.
Devolver códigos http
<?php
header("HTTP/1.0 404 Not Found");
<?php
header("Location: http://www.example.com/");
exit();
Realizar redireccionamiento
<?php
header('Content-Type: application/pdf');
header('Content-Disposition: attachment; filename="downloaded.pdf"');
readfile('original.pdf');
Descarga de archivos
Cuando se enviar archivo al servidor de php este los almacena en un directorio temporal.
Para realizar esta carga se debe crear una forma en html que utilice el método post ademas de especificar el enctype "multipart/form-data".
<form action="" method="POST" enctype="multipart/form-data">
<input type="file" name="image" />
<input type="submit"/>
</form>
Estos archivos son recibidos en la variable global $_FILES la cual funciona como arreglo asociativo.
Esta almacena nombre, tamaño, nombre temporal y tipo por cada imagen.
$_FILES['image']['name'] => MyFile.jpg
$_FILES['image']['type'] => image/jpeg
$_FILES['image']['tmp_name'] => /tmp/php/php6hst32
$_FILES['image']['error'] => UPLOAD_ERR_OK
$_FILES['image']['size'] => 98174 (bytes)
Una vez que se han ejecutado todas las validaciones necesarias el archivo debe ser copiado a una ubicación que no sea temporal, para eso se utiliza la función move_uploaded_file.
move_uploaded_file($filename, $destination)
Antes de realizar dicha acción es recomendable validar el origen del archivo a mover mediante la función is_uploaded_file, esta se encarga de validar que el archivo haya sido recibido mediante un HTTP POST.
Si lo que se desea es almacenar la imagen dentro de la base de datos(blob) se utiliza la función file_get_contents.
Esta función lee todo el contenido de la imagen y lo almacena en un string el cual almacenamos directamente en la columna blob de la base de datos.
Nota: Siempre que se almacene un blob también se debe guardar su MIME type
Para desplegar la imagen obtenida de un blob primero se debe convertir a base64 en php mediante la función base64_encode, esta nos devolverá un string que utilizaremos de la siguiente manera:
<img src="data:mime_type;base64[texto_base64]"/>
El MIME type es un identificador de dos partes, el formato del archivo y el formato de los contenidos. Por ejemplo: text/html o image/jpeg.