Mostrando entradas con la etiqueta tutorial. Mostrar todas las entradas
Mostrando entradas con la etiqueta tutorial. Mostrar todas las entradas

Cómo actualizar a Simple Machines Forums 2.0 RC3

Hoy recibí el anuncio desde el foro de SMF sobre la disponibilidad de la nueva RC3.

Incluye 350 entradas en el change log, mayormente bugs.

Por lo tanto se recomienda su actualisación inmediata a usuarios de SMF 2.0 RC2 o inferior.

Ver anuncio de smf

Como actualizar mi versión RC2 a RC3?

Los pasos son muy sencillos, primero que nada vamos a la sección downloads de SMF y elejimos "large update" de la versión 2.0 RC3.

Subimos los archivos al servidor y entramos en update.php, se nos abrirá un panel donde nos pedirá los datos del administrador y podremos configurar un backup (recomendado).

Pasado este punto empezará el backup y luego el upgrade (tanto de DB como de Templates), una vez finalizado seleccionamos borrar update.php y ya tenemos el foro en la versión 2.0 RC3


Introducción a AJAX 2/2 Codigos de ejemplo

Antes de empezar esta segunda parte de la introducción a AJAX donde nos meteremos de lleno en la programación en sí y dejaremos de lado la teoría, querría prevenir a los lectores que en una primera lectura el código y los ejemplos no sean comprensibles, pero se les anima a releerlos e intentar trazarlos para así llegar a una mayor comprensión del algoritmo utilizado.

Funciones comunes

Primero que nada vamos a revisar las 2 funciones que usaremos siempre en nuestro sistema AJAX.
//Funciones comunes
function addEvent(elemento,nomevento,funcion,captura)
{
if (elemento.attachEvent)
{
elemento.attachEvent('on'+nomevento,funcion);
return true;
}
else
if (elemento.addEventListener)
{
elemento.addEventListener(nomevento,funcion,captura);
return true;
}
else
return false;
}

function crearXMLHttpRequest()
{
var xmlHttp=null;
if (window.ActiveXObject)
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
else
if (window.XMLHttpRequest)
xmlHttp = new XMLHttpRequest();
return xmlHttp;
}
La función addEvent se encarga de ejecutar una 'funcion' al suceder un 'evento' sobre un 'elemento' es decir si tenemos el boton1 y queremos que en la acción 'onclick' se ejecute la función 'comprobar()', lo llamaremos de la siguiente forma:
addEvent(boton1, 'click', comprobar, false);
La función crearXMLHttpRequest() es la encargada de crear nuestro módulo AJAX para hacer peticiones de fondo. Básicamente se crea una función gracias al "amado" Internet explorer que usa un ActiveX, el resto de navegadores utilizan windows.XMLHttpRequest como marcan los estándares.

Introducción a AJAX 1/2

¿Qué significa AJAX?

Si bien mucha gente ha escuchado alguna vez en su período como programador web la palabra AJAX pocos saben que significa. Ajax es el acrónimo de Asynchronous Javascript And XML es decir, Javascript asíncrono y XML.

Según la RAE la definición de asíncrono es:
"Se dice del proceso o del efecto que no ocurre en completa correspondencia temporal con otro proceso u otra causa."

Es decir mientras trabajemos con ajax, Javascript no cargará ciertas informaciones cuando se carga la página principal sino cuando sean requeridas (Javascript asíncrono)

Pero, ¿Qué es realmente AJAX?

Como su propio nombre indica AJAX no es una sola tecnología sino que es la unión de muchas tecnologías muy populares que trabajan de forma conjunta logrando un potencial realmente increíble en una página web.

Las tecnologías que intervienen en AJAX son:

  •  Javascript
  • HTML
  • XML
  • CSS
  • PHP
  •  ASP

No todas son necesarias para el desarrollo óptimo de nuestra aplicación con AJAX pero si se recomienda su conocimiento.
Las más utilizadas son: Javascript, HTML, PHP y CSS, para estructuras de datos grandes se usa mucho XML.

¿Cómo funciona?

Quizá podamos simplificar la explicación imaginando iframes. El uso de iframes nació como una buena alternativa (ya prácticamente obsoleta) de mantener una sección de la página estática y solo recargar el resto.
Un ejemplo muy clásico es el menú de una web en un iframe y en otro iframe la web en sí.

Como ya he dicho esta práctica está casi obsoleta, pero AJAX tiene un concepto similar.
Con AJAX tenemos la posibilidad de consultar/mostrar/enviar datos sin necesidad de recargar la página por completo y en "background".

Un ejemplo simple puede ser el envío de un comentario.
En vez de actualizar por completo la página ejecutamos un script que nos envíe "de fondo" el comentario y a la vez lo cargue en nuestra página para su visualización.

Hay ciertas ventajas, así como desventajas.

Entre las ventajas podemos encontrar:

  • Mayor velocidad en la carga de la página: Siguiendo el ejemplo anterior, al no tener que cargar la página por completo al enviar el mensaje el tiempo de carga disminuye bastante.
  • Menos transferencia de datos en el servidor: Por el mismo motivo que nuestra web nos ofrece mayor velocidad, también nos ofrece una transferencia de datos menor a la correspondiente sin dicha tecnología.

Entre las desventajas podemos encontrar:

  • Pérdida del concepto "atras": Con esta tecnología el concepto de atrás se pierde, depende donde apliquemos AJAX ésta no nos afectará.
  • Marcadores indirectos: Ésta se produce en páginas completamente con AJAX como podria ser Gmail. Al crear un marcador, por ejemplo, en el correo 23 y abrir dicho marcador, este nos lleva a la página principal de Gmail y no a dicho mensaje.

¿Quién usa AJAX?

Hay muchas empresas que a día de hoy usan AJAX, algunas de ellas pueden ser:

  • Google (Orkut, Gmail, Google Groups, Google Map, Google Suggest)
  • Flickr (algunas funciones)
  • Amazon (motor de búsqueda)

Introducción a AJAX 2/2 (En redacción)

SyntaxHighlighter formata tus códigos de forma sencilla.

Hace ya mucho me vi en la obligación de crear un pequeño script para formatar correctamente códigos y así poder publicarlos en blogger.

Hace uno o dos días, hablando con yoyahack me explicó que existia una alternativa para "colorear" los códigos en tu blog o web independientemente del cms o la distribución.

Su nombre es SyntaxHighlighter

Su instalación es simple, solo debemos agregar estos códigos js en nuestras cabeceras:

<link href='http://alexgorbatchev.com/pub/sh/current/styles/shCore.css' rel='stylesheet' type='text/css'/>
<link href='http://alexgorbatchev.com/pub/sh/current/styles/shThemeRDark.css' rel='stylesheet' type='text/css'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shCore.js' type='text/javascript'></script>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCpp.js' type='text/javascript'></script>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCSharp.js' type='text/javascript'></script>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCss.js' type='text/javascript'></script>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJava.js' type='text/javascript'></script>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJScript.js' type='text/javascript'></script>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPhp.js' type='text/javascript'></script>

<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPython.js' type='text/javascript'></script>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushRuby.js' type='text/javascript'></script>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushSql.js' type='text/javascript'></script>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushVb.js' type='text/javascript'></script>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushXml.js' type='text/javascript'></script>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPerl.js' type='text/javascript'></script>
<script language='javascript'>
SyntaxHighlighter.config.bloggerMode = true;
SyntaxHighlighter.config.clipboardSwf = 'http://alexgorbatchev.com/pub/sh/current/scripts/clipboard.swf';
SyntaxHighlighter.all();
</script>


y a la hora de redactar encerraremos nuestro códgio entre:
<pre class="brush: js">

</pre>

o

<pre class="brush: php">

</pre>

Hay más lenguajes que estos dos, solo son los que yo uso más... también podemos omitir los scripts js de los lenguajes que no vayamos a utilizar.

El único inconveniente es que aún necesitamos un pequeño script para hacer la función htmlentities() y así no tener problemas con los símbolos < >.

El script que yo uso es:
<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" style="margin-bottom:40px">

<div id="formulario">

<textarea rows="20" cols="80" name="codigo"></textarea> <br />
<input type="submit" name="enviar" value="Formatear" /></div>

</form>

<?php

if (!empty($_POST['codigo'])) {

$codigo = $_POST['codigo'];
$codigo = str_replace("t", " ", $codigo);
$codigo = htmlentities(stripslashes($codigo));

$file = fopen("tmp.txt", "w");
fwrite($file, $codigo);
fclose($file);

$lineas = file('tmp.txt');
unlink('tmp.txt');

for ($i = 0; $i < count($lineas); $i++)
$resultado = $resultado.htmlentities($lineas[$i])."<br />";

echo '<h3> Inserta ste codigo en tu site: </h3>' .$resultado.'</div>';
}

?>

Eso es todo.

nax

Trabajando con Subversion

Este es un articulo que escribí para el Programmers Team, dejo una parte y el link debajo.


Qué es subversión?

Según Wikipedia Subversión es un software de sistema de control de versiones.
Un sistema de control de versiones (RCS) es una implementación de software para el control de versiones que automatiza las tareas de guardar, recuperar, registrar, identificar y mezclar versiones de archivos.
Es decir, con SVN podemos llevar un registro de quien efectuó que cambio a cual archivo y cuando lo efectuó. En definitiva es una herramienta ideal para el trabajo en equipos de desarrollo.

Porqué usar subversión?

Como he dicho, su principal ventaja es que nos proporciona un control absoluto de los cambios que el software ha sufrido, quien los ha realizado y cuando. Aparte de estas características también podemos acceder a cualquier revisión que necesitemos con unos simples clics.
Por ejemplo si desarrollamos un software y descubrimos que a partir de la versión 23 hay un bug que nos obliga a replantearnos completamente la estructura, en dicho caso podemos volver a la versión 23 y seguir desarrollando a partir de esta.

Qué necesito para usar subversión?

Para utilizar repositorios SVN necesitaremos un host:
  • Google code
  • Source Forge
Hay muchos más, pero estos son los que a mí me han gustado.
Un cliente de subversión, a mi parecer el mejor es TortoiseSVN

Estructura de nuestro Repositorio SVN

La estructura de un SVN es completamente libre, pero se suele seguir este modelo:
Repositorio SVN (/):
  • Trunk: El tronco es la carpeta donde se ejecutan todas o casi todas las modificaciones del software, se podría considerar la carpeta de desarrollo.
  • Tags: La etiqueta se utiliza para almacenar una versión estable o con un objetivo importante realizado.
  • Branches: Las ramas se utilizan cuando queremos implementar una característica al proyecto pero no queremos hacerlo en el Trunk dada su magnitud.

Trabajar con nuestro Repositorio

Una vez creado nuestro repositorio e instalado nuestro cliente vamos a aprender a crear, configurar y trabajar con nuestro repositorio.

Crear un repositorio

Para crear el repositorio creamos una carpeta donde queremos tenerlo, en mi caso en mi localhost.
Clicamos el botón derecho y elegimos la opción SVN Checkout
se ve como hacemos un SVN checkout


En la ventana que se nos abrirá ponemos la url de nuestro host SVN agregando /trunk, ya que tomaremos y guardaremos los datos en la carpeta de desarrollo.
Imagen donde configuramos el repositorio

Recibir y enviar archivos

El comando para recibir los archivos se llama “SVN Update” así que en nuestra carpeta hacemos clic derecho y elegimos dicha opción.
Y se nos abrirá un cuadro de texto dándonos un reporte de los archivos que se modificaron, agregaron o borraron y la versión que disponemos.
Imagen donde se ve el update realizado
En mi caso no se habían ejecutado por lo que no hay archivos y solo me indica la versión actual.
Para enviar los archivos usamos la opción “SVN Commit”, así que ejecutamos dicha acción.
La ventana que se nos abrirá contiene 2 secciones. En la primera podemos agregar un mensaje a la nueva versión del repositorio, normalmente se escribe un texto explicando los cambios, o podemos agregar un mensaje anterior con el botón “Recent Message”.
En la segunda sección tenemos una lista con todos los archivos, si no recuerdo mal dispone de 3 status:

Redirecciones 301, una ves ya indexado...

Aveces en nuestro camino por mejorar el SEO descubrimos que las url actuales de las cuales disponemos (.php?var=data&other=something) no son una buena elección para indexar en un buscador y optamos por dar el paso a las url amigables (/data/something)

El principal problema viene cuando estamos indexados y dicha indexación ocupa lugares relativamente buenos en algunos buscadores.

La solución a estos problemas es la redirección 301, lo que hace esta redirección es decirle al buscador "esta url a partir de ahora será esta otra" y el bot indexa y rankea nuestra web de una forma óptima, el desastre que podriamos causar sin redirecciones 301 es inmenso...

.htaccess y la redirección 301:

Nota: Se recomiendan conocimientos previos en el manejo de htaccess


Un primer ejemplo de redirección permanente:

<IfModule mod_rewrite.c>
   RewriteEngine On
   RewriteBase /
   RewriteCond %{HTTP_HOST} !^mysite.com [NC]
   RewriteRule ^(.*)$ http://mysite.com/$1 [L,R=301]
</IfModule>



Lo que estamos haciendo es redirijir http://mysite.com hacia http.//www.mysite.com

PHP y la redirección 301:

En el documento de php colocamos:

<?php
   Header
"HTTP/1.1 301 Moved Permanently" );
   
Header"Location: http://www.mysite.com/newUrl" ); ?>


ASP y redirección 301:

<%
   Response.Status="301 Moved Permanently"
   Response.AddHeader "Location", " http://www.mysite.com/page.asp"
%>


ASP.net y redirección 301:

private void Page_Load(object sender, System.EventArgs e)
{

   Response.Status = "301 Moved Permanently";
   Response.AddHeader("Location","http://www.new-url.com");
}


Existen mas formas de redirijir con otros lenguajes, como por ejemplo HTML

pero la forma de HTML no está bien vista por los bots.

Las variables variables de PHP

Aunque suene un tanto raro existen y quizá cueste un poquito de captar a la primera, así que recomiendo la doble lectura.

En algún momento dado podemos necesitar que el contenido de una variable sea el nombre de la varable.
Ejemplo:
tenemos la variable $boque =  "arbol";
queremos asignarle a una variable $arbol = "verde"; pero no siempre será arbol también podria ser planta.

Entonces, como lo hacemos? Ya que:

<?php

  $bosque 
$arbol "verde"; ?>


solo conseguimos 2 variables con el valor verde, que no es lo que buscamos.
Aquí entran las variables variables.

Asignación de una variable normal:

<?php

  $bosque 
"arbol"; ?>


Ahora una variable variable siguiendo el ejemplo anterior:


<?php

  
$$bosque "verde"; ?>


Y el efecto es asignar la variable $arbol = "verde";

Saludos
Nax

Cambiar mayúsculas y minusculas en la clave de un array

Hoy me vi en el aprieto de hacer una búsqueda de la clave de un array y retornar el valor.

El problema viene generado porque la clave puede estar tanto en mayúsculas como en minúsculas y eso puede afectar negativamente en la búsqueda de la clave probocando un resultado FALSE incorrecto.

Ejemplo: si busco A pero en el array existe a, dará false cuando en realidad es true.

Para hacer la búsqueda opté por una función quizá poco conocida: array_change_key_case()

Funciona de la misma manera que strtolower() y strtoupper() pero en las claves del array.

Un ejemplo de la función:

<?php

$var 
= array("Una" => 1"dOs" => 2);
var_dumparray_change_key_case($var,CASE_LOWER));
// Salida: array(2) { ["una"]=>  int(1) ["dos"]=>  int(2) }
?>


como se puede apreciar las keys ahora son en mínusculas.

Tenemos las dos posibilidades: CASE_LOWER y CASE_UPPER

Ahora podemos hacer búsquedas en arrays sin miedo a dar falsos negativos.

La clase MySQLi

Hoy mismo hablé sobre el uso de mysql_connect pero ahora quiero hablaros de la clase MySQLi que un user de CUH (p3ll3) comentó sobre ella y yo no la habia tenido en mente.

Un código básico de MySQLi:

<?php
$con 
= new MySQLi('host''usuario''pass''db');
$query $con->Query("SELECT algo, otro FROM tabla WHERE id = 1");

while (
$q $query->fetch_object()) {
    echo 
"Hola soy ".$q->algo." y "$q->otro;

}
$query->close(); $con->close();
?>


Como se puede comprobar es bastante sencillo, creamos un objeto con la sentencia new, le decimos que se trata de MySQLi y le pasamos los parámetros de conexión: host, usuario, contraseña y base de datos, aquí ya se nota una mejora por el hecho de no tener que usar mysql_select_db().

Luego para ejecutar una consulta simplemente tomamos el objeto y le indicamos la acción Query seguida de la consulta.

Para accesar a los datos lo hacemos igual que con mysql_query solo que en el while en ves de poner mysql_fetch_array() ponemos la variable y fetch_object().

A la hora de acceder a los datos normalmente lo hariamos como un array $q['algo'] pero con MySQLi se hace así $q->algo.

Eso es todo referente a MySQLi

La Función mysql_connect

No hace mucho publiqué el siguiente artículo en el foro de CUH, el cual se ve que agradó y me solicitaron un poco mas de información, así que os dejo el post completo por si es de ayuda para alguno.

Para establecer una conexión a una base de datos mysql utilizaremos myql_connect().

Esta función se suele almacenar en una variable ya que en futuras acciones debemos decirle cual es la conexion.

Sintaxis:

$variable = mysql_connect([$host],[$usuario],[$password],[$nuevolink],[$flags])

todo es muy simple... un ejemplo de variables sería:

<?php

$host
="localhost"; $usuario="root"; $password=""//sin pass $nuevolink=true; $flags=MYSQL_CLIENT_SSL  
?>


Todos los parámetros de esta función son opcionales... y direis: COMO???, así no hay forma de saber donde conectar...

Bien, hay un detalle que parece ser que mucha gente no usa en cuanto a $host $usuario y $password...

Existe ese maravilloso PHP.ini que tiene unas directivas especialmente para esta función, y en caso de que no se pase un parámetro conectará mediante dichas directiva. Las directivas son:

mysql.default_host =
mysql.default_user =
mysql.default_password =


si les ponemos valores a estas directivas ya no hará falta especificar datos de conexión.

$nuevolink

Por defecto es false y su utilidad en true es que si hacemos otra llamada con los mismos argumentos no establecerá un nuevo link sino que utilizará el que ya se habia creado previamente, por eso no se suele usar..

$flags

Las flags de mysql_connect son:

MYSQL_CLIENT_COMPRESS
Protocolo de compressión

MYSQL_CLIENT_IGNORE_SPACE
Permitir espacios después de nombres de funciones

MYSQL_CLIENT_INTERACTIVE
Permitir los segundos interactive_timeout (en ves de wait_timeout) de inactividad antes de cerrar la conexión

MYSQL_CLIENT_SSL
Encriptación SSL

Eso es todo para mysql_connect() normalmente se usan los 3 primeros parámetros así que si no entendeis el resto no os comais mucho la cabeza

Diferentes formas de usar condicionales if

Hoy vamos a hablar un poco de las diferentes formas de escribir un If().
Resulta, quizá, un tanto extraño hablar de cómo escribir un condicional pero a lo largo de mi etapa como programador en PHP he visto tantas formas que creo es bueno tener una recopilación de, sino todas, la mayoría.

Como ya sabemos If es una condicional que sirve para guiar el flujo de un programa según ciertos parámetros. La estructura más común es:

<?php
if ($condicion) {
   
$acciones1;
}else if (
$otra_condicion) {
   
$acciones2;
} else {
   
$acciones3;
}
?>


Si no se cumple la condición se nos envía al else if y si tampoco se cumple nos redirige al else y si se cumple se ejecutan las primeras.
Cuando contamos con un if para uan sola acción podemos hacerlo de la siguiente forma


<?php if ($condicion)
   
$accion1; $accion2; ?>


En este caso la acción uno se ejecutará solo en caso de que se cumpla la condición, sin embargo la condición dos se ejecuta siempre.
También podemos usar else if y else


<?php
if ($condicion)
   
$accion1;
else if (
$otra)
   
$accion2;
else
   
$accion3; ?>


Esta quizá es la forma más difícil de aprender (así que ya veis lo complicado del tema..) y se utiliza mucho en SMF por lo que si suelen trabajar con su código es bueno conocerla.

<?php
$numero 
3; $variable = ($color == 'Es 3' 'No es 3'); ?>


Como veis es parecido a colocar un if, pero todo mientras damos el valor a la variable, para que quede más claro esta es la equivalencia con un if normal.

<?php
if  ($color == 3)
   
$varoabñe 'Es 3';
else
   
$variable 'No es 3'; ?>

Recuperar el Password MySQL en Linux

El mismo día que comentaba como recuperar el password Root de MySQL en windows, Dragon de DragonJar nos contaba como hacerlo desde linux.

Hoy entonces paso a explicar este proceso.


Primero detenemos el servicio

$ /etc/init.d/mysql stop

una ves que el servicio está apagado reiniciamos el servidor en modo seguro:

$ mysqld_safe --skip-grant-tables --skip-networking

acto seguido abrimos otra consola y entramos como root al servidor:

$ mysql -u root -p mysql

Ahora ya deberiamos tener el acceso a mysql, el siguiente paso es cambiar la contraseña:

$ mysql> UPDATE user SET Password=PASSWORD('unapassowrdnueva') WHERE User='root';
mysql> flush privileges;

El último paso es terminar el proceso mysql-safe y reiniciar el servidor SQL:

$ pkill mysql -safe
$ /etc/init.d/mysql start


Fuente original DragonJar: Como recuperar clave mysql

La mejor forma de administrar las fechas entre PHP y MYSQL

Luego de mucho tiempo trabajando con la función date(), creando campos INT en MySQL y luego usando una función para calcular a partir de ese INT la fecha que almacena (al mas puro estilo SMF) creo haber dado con la fórmula perfecta, al menos para mi, de trabajar con este dato.

El proceso va orientado a una web con sistema de noticias, comentarios, peticiones y demás por lo que es importante tener un registro de fechas y horas.

Empezamos montando la tabla de ejemplo

mysql> DESCRIBE horas;
+-------+-----------+------+-----+-------------------+--------------------------+
| FIELD | Type      | NULL | KEY | DEFAULT           | Extra
   |
+-------+-----------+------+-----+-------------------+--------------------------+
| hora  | timestamp | NO   |     | CURRENT_TIMESTAMP | ON UPDATE CURRENT_TIMESTA
MP |
+-------+-----------+------+-----+-------------------+--------------------------+
 
mysql> SELECT * FROM horas;
+---------------------+
| hora                |
+---------------------+
| 2010-01-28 15:38:26 |
| 2010-01-28 15:38:49 |
| 2010-01-28 15:38:54 |
+---------------------+
3 rows IN SET (0.00 sec)
 
Se puede apreciar claramente que estamos utilizando el tipo timestamp y como valor por defecto CURRENT_TIMESTAMP.
Podemos apreciar que estas funciones guardan los datos en formato EEUU (2010-01-28 15:38:54), cosa que no nos interesa y por la cual normalmente buscariamos otro método, pero aquí viene lo interesante.

La función DATE_FORMAT

Con esta función nos podemos permitir el lujo de formatear las fechas a nuestro anotjo a la hora de hacer las consultas.

Un ejemplo:

mysql> SELECT DATE_FORMAT(hora, '%H:%i:%s %e/%m/%y') AS hora FROM horas;
+-------------------+
| hora              |
+-------------------+
| 15:38:26 28/01/10 |
| 15:38:49 28/01/10 |
| 15:38:54 28/01/10 |
+-------------------+

Como se aprecia en el ejemplo tenemos una hora y fechas perfectamente formatadas.

Tratando las fechas en PHP

Ahora ya solo importa como vayamos a utilizar esta información, para el ejemplo yo voy a comprobar que se haya escrito hace menos de una hora, hoy o ayer, en caso de no ser ninguno de estos casos muestro la fecha mas no la hora.

He agregado un valor y modificado dos para que se produzca cada caso, así que ahora tenemos:


mysql> SELECT DATE_FORMAT(hora, '%H:%i:%s %e/%m/%y') AS hora FROM horas;
+-------------------+
| hora              |
+-------------------+
| 15:38:26 28/01/10 |
| 13:38:49 28/01/10 |
| 22:38:54 27/01/10 |
| 22:38:54 25/01/10 |
+-------------------+
4 rows IN SET (0.01 sec)
 
El código encargado de tratar con las fechas es:

<?php

$con 
mysql_connect('localhost','root','') or die(mysql_error());
mysql_select_db('z_test',$con) or die(mysql_error());

$query mysql_query("SELECT DATE_FORMAT(hora, '%H:%i:%s %e/%m/%y') 

                     AS hora FROM horas;",$con);

while ($list mysql_fetch_array($query)) {
   
$all explode(' '$list['hora']);
   
$data explode('/'$all[1]);
   
$time explode(':'$all[0]);

   echo 
'<br />Publicado: ';
   
   if (
date('H') - $time[0] <= && date('d') == $data[0])
      echo 
'Hace una hora';
   else if (
date('d') == $data[0])
      echo 
'Hoy';
   else if (
date('d') - $data[0] == 1)
      echo 
'Ayer';
   else
      echo 
$all[1];
}

?> 



Y para finalizar la salida de la página:

Publicado: Hace una hora
Publicado: Hoy
Publicado: Ayer
Publicado: 25/01/10

Espero que os sirva para un futuro.

Como convertir un Array en un Objeto de PHP?

La pregunta es clara, quizá en algún momento nos interese o nos sea mas comprensible trabajar con un Array como un Objeto y no como Array.

El código es:

<?php

$hoy 
= array('comida' => 'arros''postre' => 'pastel');

$hoyObjeto = (object)$hoy;

echo 
$hoyObjeto->comida// Salida: arros
echo $hoyObjeto->postre// Salida: pastel


?>


Como se puede apreciar no tiene dificultad ninguna.

Pero como queremos ir siempre mas allá probamos un array numérico:

<?php

$hoy 
= array('comida' => 'arros''postre' => 'pastel'=> 'nada');

$hoyObjeto = (object)$hoy;

echo 
$hoyObjeto->comida// Salida: arros
echo $hoyObjeto->postre// Salida: pastel

/*
echo $hoyObjeto->0;

Esta linea produce el siguiente error:

Parse error: syntax error, unexpected T_LNUMBER, 
expecting T_STRING or T_VARIABLE or '{' or '$' ....
*/

var_dump($hoyObjeto); 
/*
Salida: object(stdClass)#1 (3) { 
   ["comida"]=>  string(5) "arros" 
   ["postre"]=>  string(6) "pastel" 
   [0]=>  string(4) "nada" } 

*/

?>


Como se aprecia en el código hacer un echo del objeto con un índice numérico es imposible, eso lo sabemos gracias al error:

Parse error: syntax error, unexpected T_LNUMBER, expecting T_STRING or T_VARIABLE or '{' or '$' ....

Basandome en ese error he intentado encapsularlo entre {}, meter el numero en una variable, y algunas cosillas mas. El resultado es que no produce un error, pero la variable tampoco se muestra.

Gracias al var_dump() vemos en todo momento que dentro del objeto existe el dato, pero no hay forma de moestrarlo, por lo que podemos decir que las Arrays no pueden tener índices numéricos al pasarlas a objetos, al menos no si queremos mantener los datos.

Aprendamos sobre Expresiones regulares

Hoy toca un poco de expresiones regulares.

Primero deberíamos saber que funciones utilizan dichas expresiones.

Todas las que empiezan por 'preg' como son:

preg_filter
preg_grep
preg_last_error
preg_match_all
preg_match
preg_quote
preg_replace_callback
preg_replace
preg_split

Estas son todas las funciones y podéis encontrar su explicación
En el paper de PCRE de php.net http://es2.php.net/manual/en/book.pcre.php

Cómo funcionan las expresiones regulares?

Bien, básicamente lo que hacemos es dar un Pattern (o patrón) y a partir
de este buscamos coincidencias.

Cabe destacar que cuando damos el patrón 'am' lo que buscamos es cualquier palabra
que contenga 'am' y no la palabra 'am' en sí.
Siendo validos: am, amanecer, mama, entre otros...


Caracteres de las expresiones regulares:

Tenemos varios caracteres con funciones especiales

\ - Carácter de escape. Escapa un carácter especial.
^ - Inicio de cadena. Indica que el patrón especificado a continuación va al inicio
siguiendo el ejemplo anterior '^am' siendo válidos solo: am y amanecer
$ - Fin de cadena. Exactamente lo mismo que el anterior pero al final
. - Representa cualquier carácter, pero solo uno. Con el patrón c.d
podemos pensar como válidos: cad, cod,cud,clda, code pero no caac o ccld por ejemplo
[ - Inicio de definición de clase de caracteres
] - Fin de la definición anterior
| - Operador lógico OR. si tenemos: v|a podemos dar como válidos v o a por ejemplo
* - Cuantificador de cero o más. Con el ejemplo: "a*" podemos pensar en 'a' o 'aa' o 'abb'
+ - Cuantificador de uno o más. Igual que el anterior pero no será válido 'a'
{ - Inicio de valores mínimo máximo
} - Fin de valores mínimo máximo
? - Puede servir de cuantificador, modificador de codicia y para definir clases especiales.


Ahora vamos a tratar de hablar de ellos un poco más a fondo.

Carácter de escape

Si tenemos uno de los caracteres mencionados anterior, por ejemplo ^, pero no queremos
que este ejerza su función sino que sea un carácter más usaremos el carácter de escape.

Ejemplo:

Patrón: "\^Hola!"
Válido: ^Hola!!, C^Hola!, etc
No válido: "Hola!", "^Hol!"

Según e leído (y aún no he comprobado) si PHP encuentra un carácter de escape y su siguiente
no es un carácter de la lista toma el carácter de escape como carácter normal

Por lo que: "\(" y "\\(" Representan lo mismo: "\("

Hay algunos caracteres que no están en la lista anterior y son caracteres de escape:

\n - Salto de línia
\r - Retorno de carro
\t - tabulación
\xhh - Hexadecimal, hh son números en hexadecimal
\ddd - Octal.

También disponemos de otros caracteres de escape dentro de las expresiones regulares:

\d - Cualquier digito decimal, 0-9 y los superíndices
\D - Digitos no decimales (todos los que no son los anteriores)
\s - Caracteres espaciadores: ' ', '\n', '\t', '\r'
\S - Caracteres no espaciadores
\w - Carácter alfanumérico o '_'
\W - Caracteres no alfanuméricos ni '_'
\a - Carácter de inicio de cadena. Equivale a ^
\A - Inicio de línea. Todo carácter que inicia una línea
\z - Carácter de fin de cadena. Equivale a $
\Z - Todo carácter que finaliza una línea

Las clases de caracteres

Para refrescar un poco las clases de caracteres son las que están entre [ y ]

Dentro de estas clases no funcionan todo lo expuesto anteriormente. Estos si funcionan:

\ - Carácter de escape
- - Definir rango de caracteres. Ejemplo: [a-z] define de la a la z
^ - Es un carácter de expulsión, con esto quitamos aquellos que no queremos en la clase
Ejemplo: [a-z^dbg], son todos los caracteres de la a a la z menos dbg.

Nota: Recordamos que esto se rige por los códigos ASCII por lo que no es lo mismo a que A

Para estos tres es necesario escaparlos para usarlos, pero no los de la lista del principio
Por lo que $ o + son perfectamente funcionales sin escaparlos.

La segunda lista proporcionada en "caracteres de escape" es reutilizable en esta
sección, por lo que podemos hacer cosas como: "[\w^_]+"

Subpatrones

Los subpatrones se delimitan con paréntesis y pueden estar concatenados.

Encontramos dos utilidades principales:

- Agrupaciones para usar el OR:

Ejemplo:
Pattern: "per(sona|ro)"
Coincide: tanto con persona como con perro

- Capturar fragmentos que luego utilizaremos

Esta me he planteado no presentarla por lo complicado que puede ser entenderla al
principio, así que si os la queréis saltar no hay problema.

Supongamos que queremos encontrar todo lo que esté encerrado entre ":

Patrón: "\"+\"" (PHP necesita que escapemos las comillas.

Ahora supongamos que también queremos que detecte las comillas simples:

Patrón: "(\"|\')+(\"|\')"
Pero esta expresión no es del todo correcta, puede darse el caso de capturar: " "hola' "

Lo cual no tiene sentido. Entonces podríamos pensar:

Patrón "\"+\"|\'+\'"
Pero imaginemos que también capturamos caracteres entre #, /*, etc...

Entonces lo mejor es:
Patrón "(\"|\'|\#|...)+\1"

Los ... referencian a los demás subpatrones que podríamos agregar.
Destaco el \1 es una "referencia anterior" y hace referencia al primer subpatrón,
el \2 haría referencia al segundo, etc..

De forma vulgar sería como hacer: "(\"|\'|\#|...)+(\"|\'|\#|...)"

solo que no se producen casos como " "Hola' ". Es decir, una maravilla.

Cuantificación

Funciona de la siguiente manera:

"X{min,max}" X representa un carácter, una clase de caracteres o subpatron y min y max
representan el número de veces mínimo y máximo que aparece X.

Ejemplo:
Patrón: "\w{2,4}"
Este patrón nos indicaría palabras de dos a cuatro letras.

Si se omite 'max', se entiende que X se repite 'min' o más veces

Ejemplo:
Patrón: "\w{2,}"
Dos letras o más, NO ONITIR LA COMA!

Si omitimos la coma significa que se repite ese número exacto.

Ejemplo:
Patrón: "\w{10}"
Palabras de 10 letras exactas.

Tenemos a nuestra disposición otros cuantificadores, pero se pueden crear con el método
normal, de todas formas los menciono:

X* equivale a X{0,}
X+ equivale a X{1,}
X? equivale a X{0,1}

Codicia

Usando el ejemplo de los subpatrones "(\"|\')+\1" podremos explicar que significa exactamente
la codicia.

Las expresiones regulares son codiciosas, es decir intentarán coincidir el mayor número posible.

Ejemplo:
Patrón: "(\"|\')+\1"
Cadena: "a href='index.php' target='_self'>"
Coincidirá: "'index.php' target='_self'"

Como podéis notar toma desde la primera comilla simple hasta la última, para evitar
este suceso se puede evitar enredando un poco más la expresión:

Ejemplo:
Patrón "(\"|\')[^\1]+\1"

Con este ejemplo lo que le decimos es que el carácter capturado en el subpatron no puede
estar dentro de la cadena resultado

Por lo que la coincidencia será: 'index.php'


Con esto acabamos una clase básica de expresiones regulares.

Hay algunas cosillas más pero esto es lo más frecuente
No es nada difícil, sino que hay que echarle ganas y repasar dos o tres veces los ejemplos
y crear unos propios.

Basado en la información de:
php-hispano.net
php.net

Curso PHP 5 VI || Aprendamos sobre Formularios

Actividades V

Crea un programa en PHP a forma de calculadora utilizando el mínimo de funciones posible.


<?php 

function calcula($num$oper$num2) { 
    switch (
$oper) { 
     
        case 
'+'
            
$res $num $num2
        break;; 
        case 
'-'
            
$res $num $num2
        break;; 
        case 
'*'
            
$res $num $num2
        break;; 
        case 
'/'
            
$res $num $num2
        break;; 
        case 
'%'
            
$res $num $num2
    } 
    return 
$res


echo 
calcula(2,'+',2); # Resultado: 4 
?> 



Crea un programa en PHP en el que tengas que exponer todo lo aprendido en este apartado
Este ejercicio era bastante libre, y podíais aplicar todo lo aprendido o solo lo de la última clase. Aquí las soluciones son infinitas.


<?php 

$message 
"Este es mi mensaje! saludos, nax"

$fake givetome($message"nax""thief"); 
echo 
$fake

function 
givetome($original$autor$ladron) { 
    
$original explode(' '$original); 
    if (
in_array($autor,$original)) 
        
$original[array_search($autor,$original)] = $ladron;     
    return 
implode(' ',$original); 

?> 


Este ejemplo toma un mensaje original y cambia el autor por el que le indicamos, un ejemplo como cualquier otro que me hayas enviado.

VIII. Introducción a los formularios


Ya hemos dado todos los puntos que me había propuesto para este tutorial/curso, por lo tanto voy a dar una clase práctica de integración con formularios y ya doy por cerrado este curso.

Por supuesto seguiré trayendo cosas tanto en Bl4ck-P0rt4l y CUH como en mi blog. Así que si seguís interesados en el mundo de PHP y sus áreas derivadas no os alejéis mucho.

Empecemos por el principio:

Un formulario web es, a día de hoy, un elemento imprescindible para una página web dinámica, gracias a ellos podemos loguear y registrar usuarios, enviar mensajes, publicar encuestas, comentarios, etc.
Por lo tanto conocer su funcionamiento y proporcionar facilidades a los usuarios es una tarea importante en el desarrollo web.
Hay mucha gente, quizá por comodidad o facilidad, que crea un .html para los formularios y un .php para el código, yo tengo por costumbre hacerlo todo en vista de código y por lo tanto siempre lo hago todo en un .php así que vamos a aprender a hacerlo de esa forma.

Un simple formulario:

Vamos a ver un ejemplo simple.


<?php 

if (isset($_POST['nombre'])) { 
    echo 
"Bienvenido "$_POST['nombre']; 
} else { 
    echo 
'<form action="'.$_SERVER['PHP_SELF'].'" method="post"> 
          Bienvenido desconocido por favor dinos tu nombre: 
          <input name="nombre" type="text" /> 
            <input type="submit" name="Submit" id="button" value="Enviar" /> 
          </form>'


?> 


Este es un ejemplo muy claro, una página que se envía un form a sí mismo.
El if() comprueba que se haya enviado la variable, en caso de ser así es porque se nos ha enviado un nombre para mostrar, sino, mostramos el formulario pidiéndole que nos dé su nombre.

En este ejemplo ya podemos destacar dos cosas, la variable $_SERVER y la variable $_POST, como ya comenté anteriormente la variable $_SERVER es una variable propia del sistema PHP lo mismo pasa con $_POST ambas tienen su función y existen más variables de servidor que explicaremos a continuación.

Variables de Servidor útiles:

La variable $_SERVER contiene un montón de elementos más, pero nos vamos a centrar en aquellos que nos puedan ser de mayor utilidad.

Elemento Ejemplo Descripción
PHP_SELF /pagina.php Nos devuelve la ruta de la página en que se ejecuta
QUERY_STRING id=3&post=4 Es la parte que vemos en la url (store.php?id=3)
PATH_INFO pagina.php?/browse Es parecido a lo anterior pero con directorios
SERVER_NAME http://www.bl4ck-p0rtal.org Nombre del servidor que ejecuta el intérprete
DOCUMENT_ROOT /usr/local/htdocs Ruta local de la carpeta html
REMOTE_ADDR 175.56.23.2 IP del usuario/cliente
REMOTE_HOST pool.cvx.dialup.. Nombre del host del usuario/cliente
HTTP_REFERER foro.el-hacker.com Si se hizo clic para llegar al link esta variable lo contiene
HTTP_USER_AGENT Mozilla/4.0… Información del navegador y sistema operativo.

Os invito a probar el resto estas son, quizá, las más utilizadas.

Procesando y accediendo a los parámetros de los documentos:

Los formularios funcionan con dos métodos POST y GET.
La principal diferencia entre ambos (y las que nos interesa ahora) es que POST se envía en segundo plano y GET se puede ver fácilmente en la barra de direcciones (esto no implica que los POST no se puedan ver, solo que es más ‘dificil’).

Entonces te preguntarás ¿y porqué existe GET si POST es claramente mejor? Bueno, mi profesor de PHP me enseñó en su momento que en PHP si hay 2 formas de hacer las cosas siempre prevalece la mejor y la otra se elimina de el intérprete, pero en el caso de que ambas formas sean útiles en determinados momentos se mantienen ambas. Es decir, un POST es útil con un formulario que, por ejemplo envía una contraseña para que no se vea en la URL, pero sin embargo no podemos enviar datos a otra página (o a la misma) sin usar un formulario y en ese momento es GET el que entra en acción.

Un claro ejemplo de variables GET son los foros SMF todo lo que va detrás de .php? se está enviando vía GET.

Entonces, como conclusión usaremos POST para los formularios y GET para las url. En php accedemos a los métodos con $_POST y $_GET. En los formularios el parámetro name es el que marca el nombre que tendrá en el $_POST o $_GET.

Los elementos de múltiples valores serán enviados como un array:

<?php 

if (isset($_POST['nombre'])) { 
    echo 
"Bienvenido "$_POST['nombre'] . 
    
'<br />Hoy quieres comer: ' $_POST['food'][0] .  

    ' y ' $_POST['food'][1]; 
} else { 
    echo 
'<form action="'.$_SERVER['PHP_SELF'].'" method="post"> 
          Bienvenido desconocido por favor dinos tu nombre: 
          <input name="nombre" type="text" /> <br /> 
            
         <select name="food[]" multiple> 
             <option value="Fideos"> Fideos </option> 
            <option value="carne"> Carne </option> 
            <option value="pescado"> Pescado </option> 
         </select> 
          
         <br /><input type="submit" name="Submit" id="button" 

         value="Enviar" /> 
         </form>'


?> 



Como veis en el form agregamos una lista en la cual al nombre ya le indicamos que será un array con los signos [] y le damos el parámetro múltiple.

En el ejemplo estamos dando por supuesto que se recibirán 2 parámetros, para asegurarnos de ello deberíamos crear una función en JS para asesorarnos que es así.

Comprobar direcciones de correo:

Como este último capitulo pretende ser un repaso muy por encima de los formularios no voy a hablar de validación de datos, pero si os voy a dejar la forma de validar, en parte, un correo electrónico.

Luego, cuando estéis más acostumbrados a PHP se puede verificar que estos correos existan de verdad haciendo consultas whois y cosas por el estilo. Pero con este ejemplo nos aseguraremos de que al menos la sintaxis del correo sea correcta

<?php 

if (! preg_match('/^[^@s]+@([-a-z0-9]+.)+[a-z]{2,}$/i'$_POST['email'])) { 
    
$errores[] = 'Introduce un email valido'
?> 


Valores por defecto:

Al principio hablábamos de dar comodidad al usuario. Una de las formas de hacerlo es recordando los datos que se ingresaron y en caso de haber algún error rellenar los datos que el usuario tiene bien y otra forma es crear valores por defecto a modo de ejemplo.

<?php 

if ($_POST['_check']) { 
    
$defaults $_POST
} else { 
    
$defaults = array( 'nombre' => 'nax'
                        
'edad'  => '20'
                        
'ciudad' => 'Villanax' ); 

?> 


Con este ejemplo tenemos una variable llamada _check que en caso de no existir significa que no se envió un formulario y por lo tanto nombramos nuestros valores por defecto, sino lo que estaríamos haciendo es guardar los valores enviados.

Para establecer valores por defecto es imperativo hacer los form en PHP. Un ejemplo de cómo se cargarán dichos valores es:

<?php 

if ($_POST['_check']) { 
    
$defaults $_POST
} else { 
    
$defaults = array( 'nombre' => 'nax'
                        
'edad'  => '20'
                        
'ciudad' => 'Villanax' ); 

echo 
'<form action="'.$_SERVER['PHP_SELF'].'" method="post">  
          Bienvenido desconocido por favor dinos tu nombre:  
          <input name="nombre" type="text" value="'
. 

          $defaults['nombre'].'" /> <br />  
             
          Edad: <input name="nedad" type="text" value="'
. 

          $defaults['edad'].'" /> <br /> 
           
          Ciudad: <input name="ciudad" type="text" value="'
.

          $defaults['ciudad'].'" /> <br /> 
          <br /><input type="submit" name="Submit" 

          id="button" value="Enviar" /> 
          </form>'

?> 


Con esta buena práctica ahorramos muchos dolores de cabeza a las personas con tendencia a equivocarse en los formularios de registro por ejemplo, y si... lo digo por experiencia propia.


Y bien, con este último capítulo doy por concluido el tutorial de PHP 5. Gracias a todos los que lo han ido siguiendo día a día, a los que enviaron los ejercicios y a los comentarios de crítica (tanto buenos como malos).
Si creen que falta algo o creen que sería bueno ampliar alguna parte del tutorial solo háganmelo saber.

Para:
~ Syntax Error ~
Bl4ck~P0rtal -
http://foro.el-hacker.com

Saludos Nax.


Version .doc:Formularios.doc
Version .pdf: Formularios.pdf

Recuperar el password de MySQL en Windows

La información me llega desde elhacker.net de la mano de ^Tifa^.

Una de las posibles maneras de recuperar una contraseña en MySQL.

Lo vamos a explicar bajo una plataforma Windows.

Necesario:

- Ser administrador o privilegios de administrador.


Proceso:

- Inicio > ejecutar > cmd o win+R cmd

- Detenemos el Proceso de MySQL, esta parte depende de cada uno... si es un Cpanel o nuestro windows.

En windows puede hacerse así por ejemplo:
C:\> net stop mysql

- nos dirijimos a la carpeta de mysql/bin o si tenemos el path para usar mysql desde cualquier dirección (Tutorial aquí), escribimos:

c:\>cd path/to/bin

- ejecutamos la siguiente sentencia:
c:\> mysqld.exe -u root --skip-grant-tables

donde root es el usuario, pero va especialmente orientado a root.

- Ahora abrimos otra cmd y escribimos

c:\> mysql

- ya deberiamos haber logueado sin ningún tipo de problema.

- ahora ejecutamos una query para ver si el usuario existe realmente.
mysql> select user from mysql.user;

- y updateamos el campo password
mysql> update mysql.user set password = password('TU_NUEVA_CONTRASENA') where user = 'root';

- por último
mysql> flush privileges;

- ahora ya cerramos la anterior cmd e iniciamos el proceso mysql

c:\>net start mysql

Usar mySQL desde consola de comandos msdos

Bueno lo haremos con un XAMPP pero la idea es básicamente encontrar donde está el mysql.exe y hacer los mismos pasos.


Paso 1 Buscar myql.exe

Yo uso XAMPP instalado por default así que está aquí:

C:\xampp\mysql\bin
Paso 2: Agregar a variables de entorno

una ves con esta ruta vamos a:

inicio - mipc - propiedades - opciones avanzadas - variables de entorno

seleccionamos PATH y damos a modificar.

agregamos un ; y la ruta anteriormente citada a mi me quedaria así:


C:\Archivos de programa\Nmap;C:\xampp\mysql\bin
Aceptamos todo, y abrimos una cmd.


Paso 3: comandos básicos

Para entrar en MYSQL escribimos:


mysql -u usuario -p
(si no hay password no ponemos -p)

ya estamos en mysql modo consola

voy a listar una serie de comandos básicos de mysql, mas adelante pondré mas.

show databases;
muestra todas las BD


mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| cdcol              |
| main               |
| mydb               |
| mysql              |
| pbxt               |
| phpmyadmin         |
| scam               |
| smf_test           |
| users              |
| website            |
| z_test             |
+--------------------+
12 rows in set (0.00 sec)
use nom_db;
seleccionamos una DB.


mysql> use z_test;
Database changed
show tables;
mostramos todas las tablas.


mysql> show tables;
+------------------+
| Tables_in_z_test |
+------------------+
| monsters         |
| mvp              |
| players          |
+------------------+
3 rows in set (0.00 sec)
describe tabla;
hace una descripción de la tabla


mysql> describe monsters;
+-----------+--------------+------+-----+---------+----------------+
| Field     | Type         | Null | Key | Default | Extra          |
+-----------+--------------+------+-----+---------+----------------+
| id        | int(11)      | NO   | PRI | NULL    | auto_increment |
| monster   | varchar(100) | YES  |     | NULL    |                |
| dead      | int(11)      | YES  |     | NULL    |                |
| id_player | int(11)      | YES  |     | NULL    |                |
+-----------+--------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)
select * from tabla;
vemos todo los datos de la tabla.


mysql> select * from monsters;
+----+-----------+------+-----------+
| id | monster   | dead | id_player |
+----+-----------+------+-----------+
|  1 | monster 1 |    0 |         1 |
|  2 | monster 2 |    5 |         1 |
|  3 | monster 2 |    4 |         2 |
|  4 | monster 1 |    0 |         2 |
+----+-----------+------+-----------+
4 rows in set (0.02 sec)
exit;
salir

mysql> exit
Bye
A partir de aquí simplemente hacemos consultas SQL. Hay algunos comandos interesantes pero lo dejaremos para otra ocasión.

No os olvideis de poner el punto y coma al final de las sentencias.