Tutorial: Crear un acortador de URL en PHP y MySQL

cicklow

Admin
Beta
Verificado con documento
Verificación en dos pasos activada
Desde
30 May 2011
Mensajes
57
Crédito(s)
1
Puntos
25.567
Como crear un acortador de url.

Bueno en este tutorial aprenderemos a crear un acortador de url (sin usar scripts de otros ni nada).

Lo primero que aclaro es que no usare CSS ni nada para el diseño, eso corre por cuenta propia del creador.

1- Crearemos la cara del sitio con JQuery pasaremos la url por ajax a save.php
Insertar CODE, HTML o PHP:
	<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
	<script type="text/javascript">

	//Esta funcion es la encargada de ver que sea una url valida.
	function validateUrl(d){
        	matches = d.match(b);
		if (!matches) return null;
		return matches
	}
    	var b = RegExp("((?:(https?|ftp|itms)://)?(?:(?:[^\\s\\!\"\\#\\$\\%\\&\\'\\(\\)\\*\\+\\,\\.\\/\\:\\;\\<\\=\\>\\?\\@\\\\[\\]\\^\\_`\\{\\|\\}\\~]+\\.)+(?:aero|arpa|asia|biz|cat|com|coop|edu|gov|info|int|jobs|mil|mobi|museum|name|net|org|pro|tel|travel|local|example|invalid|test|\u0645\u0635\u0631|\u0440\u0444|\u0627\u0644\u0633\u0639\u0648\u062f\u064a\u0629|\u0627\u0645\u0627\u0631\u0627\u062a|xn--wgbh1c|xn--p1ai|xn--mgberp4a5d4ar|xn--mgbaam7a8h|\u4e2d\u56fd|\u4e2d\u570b|\u9999\u6e2f|\u0627\u0644\u0627\u0631\u062f\u0646|\u0641\u0644\u0633\u0637\u064a\u0646|\u0642\u0637\u0631|\u0dbd\u0d82\u0d9a\u0dcf|\u0b87\u0bb2\u0b99\u0bcd\u0b95\u0bc8|\u53f0\u7063|\u53f0\u6e7e|\u0e44\u0e17\u0e22|\u062a\u0648\u0646\u0633|xn--fiqs8S|xn--fiqz9S|xn--j6w193g|xn--mgbayh7gpa|xn--ygbi2ammx|xn--wgbl6a|xn--fzc2c9e2c|xn--xkc2al3hye2a|xn--kpry57d|xn--kprw13d|xn--o3cw4h|xn--pgbs0dh|\u0625\u062e\u062a\u0628\u0627\u0631|\u0622\u0632\u0645\u0627\u06cc\u0634\u06cc|\u6d4b\u8bd5|\u6e2c\u8a66|\u0438\u0441\u043f\u044b\u0442\u0430\u043d\u0438\u0435|\u092a\u0930\u0940\u0915\u094d\u0937\u093e|\u03b4\u03bf\u03ba\u03b9\u03bc\u03ae|\ud14c\uc2a4\ud2b8|\u05d8\u05e2\u05e1\u05d8|\u30c6\u30b9\u30c8|\u0baa\u0bb0\u0bbf\u0b9f\u0bcd\u0b9a\u0bc8|xn--kgbechtv|xn--hgbk6aj7f53bba|xn--0zwm56d|xn--g6w251d|xn--80akhbyknj4f|xn--11b5bs3a9aj6g|xn--jxalpdlp|xn--9t4b11yi5a|xn--deba0ad|xn--zckzah|xn--hlcj6aya9esc7a|[a-z]{2})(?::[0-9]+)?|(?:[0-9]{1,3}\\.){3}(?:[0-9]{1,3}))(?:\\/?[\\S]+)?)", "gi");

	function Save(){
		//esta funcion es llamada cuando el user hace click en el boton crear
	   if($('#url').val()!=""){ //verificamos que no este vacio el campo
		var _U = $('#url').val();
		if(validateUrl(_U)==_U){ //verificamos que sea una url valida
		//enviamos por ajax la url y save.php nos regresara un texto que la url no es valida o el hash acortador
		$.post("save.php", { url: _U }, 
			function(data){
			 $('#url').val(data);
			});
		}else{
			alert('url no valida!');
		}
	  }
	}
	</script>
	<center>
		<font size="2">Url?</font><br/>
		<textarea id="url"></textarea><br/>
		<a class="back" href="javascript:void(0);" onclick="Save();return false;">Crear</a>
	</center>
2- Ahora crearemos save.php
PHP:
<?php
	//Verificamos que el referer sea de nuestro sitio
	if(stripos($_SERVER['HTTP_REFERER'], 'misitio.td')===false){
		die('url no valida!');
	}
	@set_time_limit();
	//Agregamos db.php para el acceso a la BD
	include('db.php');

	//Verificamos que la url recivida no sea vacia
	if(trim($_REQUEST['url'])=="") die();

	//Esta funcion lo que hace es verificar si ya existe el sitio en nuestra BD, si existe nos regresa el hash, sino llama a la funcion _new para crear uno nuevo
	function _check($U){
		$SQL = @mysql_query("SELECT * FROM `acortador` WHERE url='".$U."'");
		$ROW = @mysql_fetch_array($SQL);

		if($ROW['char']!="") return $ROW['char']; else return _new($U);
	}

	//Esta funcion creara un hash nuevo.
	//Lo que hacemos es codificar en MD5 la url (tenemos un hash unico) y luego obtenemos lugares casi al azar
	//para darle mas aletoriedad al hash
	function _new($U){
		$Z = md5($U);
		$A = substr($Z,0,2); //Obtenemos los primeros 2 caracteres del hash
		$B = substr($Z,16,2); //Obtenemos 2 caracteres a partir del caracter 16
		$C = substr($Z,30,2); //Obtenemos 2 caracteres a partir del caracter 30
		$D = substr($Z,23,1); //Obtenemos 1 caractere a partir del caracter 23
		$zCode = $A.$B.$C.$D; //Juntamos todo

		//Guardamos el codigo, la url, la cantiad de visitas y la IP (por si necesitamos banear IP)
		@mysql_query("INSERT INTO `acortador` VALUES('".$zCode."','".$U."','0','".$_SERVER['REMOTE_ADDR']."');");

		return $zCode;
	}

    //Verificamos que no existe la url de nuestro sitio en la url que quieren acortar (evitamos un anidado de url)
    if(!stristr($_REQUEST['url'],'http://acortador.td/')){
        if(validateURL($_REQUEST['url'])){ echo 'http://acortador.td/'._check(trim($_REQUEST['url'])); }else{ echo 'url no valida!'; }
    }else
        echo $_REQUEST['url']; //Si encontramos nuestra url en la url para acortar, le regresamos la url :)


	//Verificamos que sea una url valida :) (otro chekeo aparte del js)
	function validateURL($url){
		$pattern = "|^http(s)?://[a-z0-9-]+(.[a-z0-9-]+)*(:[0-9]+)?(/.*)?$|i";
		return preg_match($pattern, $url);
	}
?>
3- conecciona a la BD... db.php
PHP:
<?php

	$dbhost = "localhost";
	$dbuser = "root";
	$dbpass = "";
	$dbname = "cosas";

	$dbh = mysql_connect($dbhost,$dbuser, $dbpass);
	mysql_select_db("$dbname") or die ("Could not connect to database");
?>
4- creamos un .htaccess
Insertar CODE, HTML o PHP:
RewriteEngine On
IndexIgnore *
Options -Indexes

RewriteCond %{HTTP_HOST} ^www\.acortador\.td$ [NC]
RewriteRule ^(.*)$ http://acortador.td/$1 [R=301,QSA,L]

RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.* - [L,QSA]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([0-9-a-z-A-Z-_]+)$ go.php?id=$1 [L]

ErrorDocument 400 /e.php
ErrorDocument 401 /e.php
ErrorDocument 403 /e.php
ErrorDocument 404 /e.php
ErrorDocument 405 /e.php
ErrorDocument 500 /e.php
ErrorDocument 501 /e.php
ErrorDocument 502 /e.php
ErrorDocument 503 /e.php
ErrorDocument 504 /e.php
ErrorDocument 505 /e.php
Con este file lo que hacemos es que no permita acceder al sitio con WWW y que lo que mandemos dsp de la / (acortador.td/dwdwded32) sea controlado por go.php
También controlamos los errores y no permitimos listar directorios!

5- creamos go.php, el encardado de redireccionar a la url
PHP:
<?php
	@set_time_limit();
	include('db.php');

	//verificamos si el hash existe en nuestra base de datos
	$SQL = @mysql_query("SELECT * FROM `acortador` WHERE `char`='".trim($_GET['id'])."'");
	$ROW = @mysql_fetch_array($SQL);

	//Si existe redireccionamos
	if($ROW['url']!=""){
		_suma($_GET['id']);
		header ('HTTP/1.1 301 Moved Permanently'); //esta cabecera si queremos la agregamos sino no hay problema :)
		header('location: '.$ROW['url']);
		die();
	}else{
		//sino existe el hash en nuestra BD redireccionamos al index de nuestro sitio
		header('location: http://acortador.td/');
		die();
	}

	//funcion encargada de sumar una visita al hash
	function _suma($U){
		mysql_query("UPDATE `acortador` SET stat=(stat+1) WHERE `char`='".$U."'");
	}
?>
6- la tabla mysql
Insertar CODE, HTML o PHP:
CREATE TABLE `acortador` (
  `char` varchar(7) NOT NULL,
  `url` text NOT NULL,
  `stat` double NOT NULL,
  `ip` varchar(14) NOT NULL,
  UNIQUE KEY `char` (`char`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
7- Creamos e.php el encargado de controlar los errores
PHP:
<?php
	header('location: /');
	die();
?>
Saludos! :)

PD: si queremos eliminar sitios que agregan (por alguna razón) usamos este archivo (admurl.php).
entramos con admurl.php?adm=1
PHP:
<?php
  [MENTION=72080]session[/MENTION]_start();
	if($_GET['adm']=="" && $_SESSION['pepe']!="1"){
		die();
	}else{
		$_SESSION['pepe']=1;
	}

	include('db.php');

	if($_GET['del']!="") mysql_query("DELETE FROM acortador WHERE `char`='".$_GET['del']."'");

	if($_GET['order']==""){
		$SQL = mysql_query("SELECT * FROM acortador WHERE 1");
	}else{
		$SQL = mysql_query("SELECT * FROM acortador WHERE 1 ORDER BY stat DESC");
	}
	echo '<ul>';
	while($ROW = mysql_fetch_array($SQL)){
		echo '<li>['.$ROW['stat'].'] <a href="http://anonym.to/?'.$ROW['url'].'" target="_blank">'.$ROW['url'].'</a> - <a href="?del='.$ROW['char'].'">DEL</a></li>';
	}
?>
PD: Como se menciona el ejemplo no tiene diseño, pero con ingenio pueden dejarlo así.


Ejemplo: http://cicklow.net/acortador/

SON LIBRES DE HACER LO QUE GUSTEN CON EL SCRIPT!

Actualización (para que no rompan las tarlipes):
Para los que no tengan bien configurado su server o un server inseguro usen esta modificación para evitar InjectionSQL.
Crean un archivo noin.php
PHP:
<?php

class secure
{
    function secureSuperGlobalGET(&$value, $key)
    {
        $_GET[$key] = htmlspecialchars(stripslashes($_GET[$key]));
        $_GET[$key] = str_ireplace("script", "blocked", $_GET[$key]);
        $_GET[$key] = mysql_escape_string($_GET[$key]);
        return $_GET[$key];
    }
   
    function secureSuperGlobalPOST(&$value, $key)
    {
        $_POST[$key] = htmlspecialchars(stripslashes($_POST[$key]));
        $_POST[$key] = str_ireplace("script", "blocked", $_POST[$key]);
        $_POST[$key] = mysql_escape_string($_POST[$key]);
        return $_POST[$key];
    }
       
    function secureGlobals()
    {
        array_walk($_GET, array($this, 'secureSuperGlobalGET'));
        array_walk($_POST, array($this, 'secureSuperGlobalPOST'));
    }
}

?>
Luego editan go.php de esta manera:
PHP:
<?php
    @set_time_limit();
    include('db.php');
    include('noin.php');

    $SEC = new secure();
    $SEC->secureGlobals();

    //verificamos si el hash existe en nuestra base de datos
    $SQL = @mysql_query("SELECT * FROM `acortador` WHERE `char`='".trim($_GET['id'])."'");
    $ROW = @mysql_fetch_array($SQL);

    //Si existe redireccionamos
    if($ROW['url']!=""){
        _suma($_GET['id']);
        header ('HTTP/1.1 301 Moved Permanently'); //esta cabecera si queremos la agregamos sino no hay problema :)
        header('location: '.$ROW['url']);
        die();
    }else{
        //sino existe el hash en nuestra BD redireccionamos al index de nuestro sitio
        header('location: http://urlacortador.com/');
        die();
    }

    //funcion encargada de sumar una visita al hash
    function _suma($U){
        mysql_query("UPDATE `acortador` SET stat=(stat+1) WHERE `char`='".$U."'");
    }
?>
 
Última edición:

suenajoven

Baneado
Épsilon
Verificación en dos pasos desactivada
Desde
18 Oct 2011
Mensajes
802
Edad
30
Crédito(s)
0
Puntos
252
simplemente genial =)
lo usare para uno de mis sitios =)
 

Falcon

Zeta
SEO
Verificación en dos pasos desactivada
Verificado por Whatsapp
Desde
29 Dic 2011
Mensajes
1.519
Edad
26
Crédito(s)
0
Puntos
57
Excelente aporte, vamos a probarlo :fatigue:
 

Julcar

Baneado
Mi
Exchanger
Verificación en dos pasos desactivada
Desde
9 Mar 2010
Mensajes
3.193
Edad
29
Crédito(s)
0
Puntos
0
yo en un script similar en ASP habia agregado las funciones de caducidad de url, estadisticas de hits y registro con correo electronico para extender la vida del link acortado.
 

VaMpE

Iota
Domainer
Verificación en dos pasos desactivada
Desde
22 Feb 2011
Mensajes
2.438
Edad
31
Crédito(s)
0
Puntos
531
Genial habria que probarlo seguro que ha de ser sencillo :D gracias por compartir lo implementare lo mas pronto posible :D :encouragement:
 

Kenny Johnson

No recomendado
Redactor
Verificación en dos pasos desactivada
Desde
17 Sep 2011
Mensajes
2.898
Edad
31
Crédito(s)
2
Puntos
390
una consulta amigos y el acortador para que sirve..
 

cicklow

Admin
Beta
Verificado con documento
Verificación en dos pasos activada
Desde
30 May 2011
Mensajes
57
Crédito(s)
1
Puntos
25.567
una consulta amigos y el acortador para que sirve..
funciona acortando una url larga ejemplo:
Insertar CODE, HTML o PHP:
http://forobeta.com/tutoriales/116748-crear-acortador-de-url-php-y-mysql.html#post1130293
quedaria:
Insertar CODE, HTML o PHP:
http://acortador.td/asdfgds
 

lucianoche

Gamma
Verificación en dos pasos desactivada
Desde
17 Ene 2011
Mensajes
402
Crédito(s)
0
Puntos
9
Muchas gracias por compartir, si me dejas agregar algo, respecto a este comentario:

PHP:
    //Esta funcion creara un hash nuevo.
    //Lo que hacemos es codificar en MD5 la url (tenemos un hash unico) y luego obtenemos lugares casi al azar
    //para darle mas aletoriedad al hash
El hash que obtienes con MD5 no es único, puedes tener colisiones, y obtener esos lugares que tu llamas al azar es igual de aleatorio que, por ejemplo, tomar los 7 primeros caracteres del MD5 o tomar los últimos 7, lo que tienes es una "sensacion" de aleatoriedad mayor, pero es sólo eso, una sensacion.

Saludos y gracias de nuevo :)
 

Science

Eta
Verificación en dos pasos desactivada
Desde
24 Ene 2011
Mensajes
1.472
Crédito(s)
0
Puntos
3
Muy buen tutorial. ¿Eso lo ponemos dentro de cualquier espacio libre de alojamiento web?
 

Delmon

Épsilon
Programador
Verificación en dos pasos desactivada
Desde
5 Ago 2008
Mensajes
834
Edad
26
Crédito(s)
2
Puntos
581
Muy interesante tutorial... solo faltó el demo :rolleyes:
 

vsus

Eta
Domainer
Verificación en dos pasos desactivada
Desde
8 Abr 2012
Mensajes
1.317
Crédito(s)
1
Puntos
5
No tiene bugs de inyección sql?

Buen tutorial! :encouragement:
 

Ale Hernandez

Zeta
Verificación en dos pasos activada
Verificado por Whatsapp
Desde
12 Abr 2012
Mensajes
1.641
Crédito(s)
2
Puntos
664
Buen aporte, aunque lo vi como un source, no como un tutorial :witless:
 

cicklow

Admin
Beta
Verificado con documento
Verificación en dos pasos activada
Desde
30 May 2011
Mensajes
57
Crédito(s)
1
Puntos
25.567

vsus

Eta
Domainer
Verificación en dos pasos desactivada
Desde
8 Abr 2012
Mensajes
1.317
Crédito(s)
1
Puntos
5
[MENTION=9679]cicklow[/MENTION] ami cuando creo un enlace y voy a entrar en él, me manda a la pagina de incio... xD
 

cicklow

Admin
Beta
Verificado con documento
Verificación en dos pasos activada
Desde
30 May 2011
Mensajes
57
Crédito(s)
1
Puntos
25.567
[MENTION=9679]cicklow[/MENTION] ami cuando creo un enlace y voy a entrar en él, me manda a la pagina de incio... xD
eso pasa cuando no se guarda en la base de datos. fijate que se este guardando bien, porque sino existe en la BD el hash te redirecciona al inicio
 

Arriba