Crea un acortador de url con cakephp en 10 minutos

Despues de leer este articulo decidi escribir mi propio tutorial, mientras pensaba en como escribir note que en meneame utilizan un acortador de urls con una implementacion similar a la que voy a mostrar.

La idea en si es simple, guardar un link en la base de datos y darle al usuario un string que identifica al link en la base de datos, la funcion para convertir el id (que es un numero) de la link a alfanumerico se llama base_convert.

Manos a la obra

CREATE DATABASE `shortener` ;
CREATE TABLE `shortener`.`links` ( `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`url` VARCHAR( 1024 ) NOT NULL,
`checksum` VARCHAR( 32 ) NOT NULL UNIQUE
) ENGINE = MYISAM ;

Luego de crear la base de datos “horneamos” el nuevo proyecto;

eugenio@eugenio-desktop:/var/www$ cake bake /var/www/shortener

Si hiciste todo bien el proyecto ahora deberia estar creado en /var/www/shortener , puedes usar la ruta que quieras.

Comencemos creando los modelos;
#models/link.php

<?php
class Link extends AppModel{
var $validate = array(
'url' => array(
'rule' => 'url',
'message' => 'La direccion que has enviado no es valida.'
)
);

function getEncodedId($id=null){
$id=($id) ? $id: $this->id;
return base_convert($id,10,36);
}

function getUrlFromEncodedId($encoded_id){
$id=(int)base_convert($encoded_id,36,10);

return ($id>0)? $this->field('url',array('id'=>$id)) : null;
}

function searchOrInsert($url){
$url=$this->getCorrectUrl($url);
$checksum=md5($url);

if($id=$this->field('id',array('checksum'=>$checksum))){
return array('id'=>$id,'url'=>$url);
}

$this->create();
$this->set(array('url'=>$url,'checksum'=>$checksum));
if($this->save()){
return array('id'=>$this->id,'url'=>$url);
}
return false;
}

function getCorrectUrl($url){
if(!ereg('/^https*:\/\//', $url)) $url='http://'.$url;
$pos=strpos($url,'//')+2;
if(!$pos=strpos($url,'/',$pos)) $pos=strlen($url);
$url=strtolower(substr($url,0,$pos)).substr($url,$pos);
return $url;
}
}

Luego creemos el controllador

#controllers/links_controller.php
<?php
class LinksController extends AppController{

function view($encoded_id=null){
if($encoded_id && ($url=$this->Link->getUrlFromEncodedId($encoded_id))){
$this->redirect($url);
}

$this->Session->setFlash(_(‘La url acortada que ingresaste no existe’));
$this->redirect(array(‘action’=>’add’));
}

function add($url=null){
$url=(isset($this->params[‘data’][‘Link’][‘url’])) ? $this->params[‘data’][‘Link’][‘url’] : $url;

if($url){
if($data=$this->Link->searchOrInsert($url)){
$this->set(‘encoded_id’,$this->Link->getEncodedId($data[‘id’]));
$this->set(‘url’,$data[‘url’]);
$this->render(‘urlinfo’);
}
$this->Session->setFlash(_(‘La url que ingresaste no es valida’));

}
}
}

Luego las vistas;

#views/links/add.ctp
<?php
e(
$this->Form->create('Link',array('action'=>'add')).
$this->Form->input('Link.url').
$this->Form->submit(_('Acortar')).
$this->Form->end()
);
?>

#views/links/urlinfo.ctp
<?php
$shorted_url=Router::url(array('controller'=>'links','action'=>'view',$encoded_id),true);

$compress_ratio=floor((strlen($shorted_url)/strlen($url))*100);

?>
<h3>Tu url acortada es:</h3><input type=”text” readonly=”readonly” onclick=”select_text();” onkeyup=”select_text();” onselect=”select_text();” value=”<?=$shorted_url ?>”><br />
Url original: <?=$url ?>
<hr />
<b><?=($compress_ratio<100) ? ‘La url se ha comprimido un ‘.$compress_ratio.’%’ : ‘La url ya era demasiado corta y no pudimos acortarla mas' ?></b>

Por ultimo configuremos las rutas;

#config/routes.php
<?php
Router::connect('/', array('controller' => 'links', 'action' => 'add'));

/**
* …and connect the rest of ‘Pages’ controller’s urls.
*/
Router::connect(‘/pages/*’, array(‘controller’ => ‘pages’, ‘action’ => ‘display’));

Solo quedaria mejorar la configuracion para que conecte /links/view/LINK_ID con algo mas corto como /short/LINK_ID .

Alguien se anima?

Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s