Cómo generar URLs amigables en CodeIgniter

Las URLs amigables es una técnica muy común en la optimización del SEO de una web. Las URLs amigables contienen palabras clave relacionadas con el contenido de la página, y ayudan mejorar tu ranking en los distintos motores de búsqueda. Pongamos un ejemplo, esto sería una URL normal y una amigable:

  • URL normal: http://ejemplo.com/post.php?id=1
  • URL amigable: http://ejemplo.com/hola-mundo

El anterior ejemplo refleja claramente que la URL amigable es más legible por humanos que la URL normal. Por eso siempre es buena idea utilizar URLs amigables, sobre todo si quieres que la web esté en los primeros resultados de los motores de búsqueda.

Si tu sitio web está desarrollado con CodeIgniter y quieres integrar URLs amigables para el contenido dinámico (posts, productos, páginas...) de la web, hay una manera sencilla de llevarlo a cabo. En este tutorial veremos cómo generar URLs amigables en CodeIgniter y cómo almacenarlas en base de datos.

En nuestro script de ejemplo implementaremos las distintas funcionalidades:

  • Generar una URL unica para cada título de post
  • Almacenar el slug de la URL en la base de datos para cada post
  • Obtener el slug de la base de datos y especificar la URL dinámica en el listado de posts
  • Mostrar el contenido del posts mediante la URL amigable mediante CodeIgniter Routes

Antes de empezar, vamos a echar un vistazo a la estructura de ficheros de la implementación de las URLs amigables en CodeIgniter.

> codeigniter
>> applicatiom
>>> config
>>>> autoload.php
>>>> routes.php
>>> controllers
>>>> Posts.php
>>> helpers
>>>> common_helper.php
>>> models
>>>> Post.php
>>> views
>>>> posts
>>>>> add.php
>>>>> details.php
>>>>> index.php

Creación de la base de datos

Para almacenar la información de los posts, debes crear una tabla en la base de datos. El siguiente SQL crea una tabla llamada posts con algunos campos básicos, como el campo url_slug, que almacenará la URL amigable de cada post.

CREATE TABLE `posts` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `url_slug` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
 `title` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
 `content` text COLLATE utf8_unicode_ci NOT NULL,
 `created` datetime NOT NULL,
 `modified` datetime NOT NULL,
 `status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '1=Active, 0=Inactive',
 PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

Controller (Posts.php)

El controller Posts comtiene tres métodos, index(), details() y add()

  • index() - Obtiene la información del modelo Post y los envía a la vista del listado
  • details() - Obtiene la información del post basándose en el campo url_slug que viene en la URL y los envía a la vista
  • add() - Genera una URL amigable única (url_slug) y añade el post en la base de datos
    - La url amigable limpia y única se generará a partir del título del post
    - Utilizaremos la función url_title() de CodeIgniter para convertir el título a URL.
    - La función helper isUrlExists() comprueba si existe la URL en la base de datos. En el caso de existir, se agregará la fecha como sufijo de la URL.
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Posts extends CI_Controller {
    
    function __construct() {
        parent::__construct();
        $this->load->model('post');
        $this->load->helper('common');
        $this->load->library('form_validation');
    }
    
    public function index(){
        $data = array();
        
        //get the posts data
        $data['posts'] = $this->post->getRows(array('limit'=>10));
        
        //load the view
        $this->load->view('posts/index', $data);
    }
    
    public function details($url_slug){
        $data = array();
        
        //get the post data
        $data['post'] = $this->post->getRows(array('url_slug'=>$url_slug));
        
        //load the view
        $this->load->view('posts/details', $data);
    }
    
    public function add(){
        $data = array();
        $postData = array();
        if($this->input->post('submitBtn')){
            $this->form_validation->set_rules('title', 'Title', 'required');
            $this->form_validation->set_rules('content', 'Content', 'required');

            $postData = array(
                'title' => strip_tags($this->input->post('title')),
                'content' => strip_tags($this->input->post('content'))
            );

            if($this->form_validation->run() == true) {
                /*
                 * Generate SEO friendly URL
                 */
                $title = strip_tags($this->input->post('title'));
                $titleURL = strtolower(url_title($title));
                if(isUrlExists('posts',$titleURL)){
                   $titleURL = $titleURL.'-'.time(); 
                }
                $postData['url_slug'] = $titleURL;
                
                //Insert post data to database
                $insert = $this->post->insert($postData);
                if($insert){
                    $postData = array();
                    $data['success_msg'] = 'Post data inserted successfully.';
                } else {
                    $data['error_msg'] = 'Some problems occured, please try again.';
                }
            }
        }
        
        $data['post'] = $postData;
        
        //load the view
        $this->load->view('posts/add', $data, false);
    }
}

Model (Post.php)

El modelo Post ayuda a extraer registros de la base de datos y a insertarlos también. Contiene dos métodos, getRows() e insert().

  • getRows() - Extrae información de la tabla post y la devuelve en un array
  • insert() - Inserta registros en la tabla posts y devuelve el ID del registro insertado.
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Post extends CI_Model{
    /*
     * get rows from the posts table
     */
    function getRows($params = array()){
        $this->db->select('*');
        $this->db->from('posts');

        //set start and limit
        if(array_key_exists("start",$params) && array_key_exists("limit",$params)){
            $this->db->limit($params['limit'],$params['start']);
        }elseif(!array_key_exists("start",$params) && array_key_exists("limit",$params)){
            $this->db->limit($params['limit']);
        }
        
        if(array_key_exists("url_slug", $params)){
            $this->db->where('url_slug', $params['url_slug']);
            $query = $this->db->get();
            $result = ($query->num_rows() > 0)?$query->row_array():FALSE;
        }else{
            $query = $this->db->get();
            $result = ($query->num_rows() > 0)?$query->result_array():FALSE;
        }

        //return fetched data
        return $result;
    }
    
    /*
     * Insert post data to table
     */
    public function insert($data = array()) {
        if(!array_key_exists("created", $data)){
            $data['created'] = date("Y-m-d H:i:s");
        }
        if(!array_key_exists("modified", $data)){
            $data['modified'] = date("Y-m-d H:i:s");
        }
        
        //insert data
        $insert = $this->db->insert('posts', $data);
        if($insert){
            return $this->db->insert_id();;
        }else{
            return false;
        }
    }

}

View (posts)

El directorio de las vistas (posts/) contiene tres ficheros: index.php, details.php y add.php.

posts/index.php

Este fichero se carga mediante el método index() del controlador Posts. Se listan todos los posts con su respectivo enlace a la vista detalle. Utilizamos la URL amigable en cada uno de los enlaces del listado.

<!DOCTYPE html>
<html lang="en">  
<head>
    <title>Generate SEO Friendly URL in CodeIgniter</title>
</head>
<body>
<div class="container">
    <h1>Post List</h1>
    <div class="row">
        <ul class="post-list">
            <?php if(!empty($posts)): foreach($posts as $post): ?>
                <li><a href="<?php echo base_url('post/'.$post['url_slug']); ?>"><?php echo $post['title']; ?></a></li>
            <?php endforeach; else: ?>
            <p>Post(s) not available.</p>
            <?php endif; ?>
        </ul>
    </div>
</div>
</body>
</html>

posts/details.php

Este fichero se carga mediante el método details() del controlador Posts. Se muestra la información del post solicitada.

<!DOCTYPE html>
<html lang="en">  
<head>
    <title>Generate SEO Friendly URL in CodeIgniter</title>
</head>
<body>
<div class="container">
    <h1><?php echo $post['title']; ?></h1>
    <p><?php echo $post['content']; ?></p>
</div>
</body>
</html>

posts/add.php

Este fichero se carga mediante el método add() del controlador Posts. Mostraremos un pequeño formulario para que el usuario pueda crear nuevos posts. Una vez se envía el formulario, la información recibida se inserta en la base de datos.

<!DOCTYPE html>
<html lang="en">  
<head>
<title>Generate SEO Friendly URL in CodeIgniter</title>
</head>
<body>
<div class="container">
    <h1>Add Post</h1>
    <div class="row">
        <?php echo !empty($success_msg)?'<p>'.$success_msg.'</p>':''; ?>
        <?php echo !empty($error_msg)?'<p>'.$error_msg.'</p>':''; ?>
        <form method="post">
            <p>Post Title: <input type="text" name="title" value="<?php echo !empty($post['title'])?$post['title']:''; ?>"></p>
            <?php echo form_error('title','<p class="help-block error">','</p>'); ?>

            <p>Post Content: <textarea name="content"><?php echo !empty($post['content'])?$post['content']:''; ?></textarea></p>
            <?php echo form_error('content','<p class="help-block error">','</p>'); ?>
            
            <input type="submit" name="submitBtn" value="Add">
        </form>
    </div>
</div>
</body>
</html>

Helper (common_helper.php)

Aquí es donde se encuentra la función isUrlExists() que hemos mencionado antes. Comprueba si el slug recibido como parámetro existe en la base de datos.

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/*
 * Helper function to check whether the url slug already exists
 */
if(!function_exists('isUrlExists')){
    function isUrlExists($tblName, $urlSlug){
        if(!empty($tblName) && !empty($urlSlug)){
            $ci = & get_instance();
            $ci->db->from($tblName);
            $ci->db->where('url_slug',$urlSlug);
            $rowNum = $ci->db->count_all_results();
            return ($rowNum>0)?true:false;
        }else{
            return true;
        }
    }
}

Config

autoload.php

Para ejecutar nuestro ejemplo, necesitamos ciertas librerías.

/*
| -------------------------------------------------
|  Auto-load Libraries
| -------------------------------------------------
*/
$autoload['libraries'] = array('database');

/*
| -------------------------------------------------
|  Auto-load Drivers
| -------------------------------------------------
*/
$autoload['helper'] = array('url','form');

routes.php

Para cargar el detalle del post basándonos en la URL, necesitamos definir una regla de enrutamiento. De acuerdo con la siguiente regla, si la URL contiene una URL amigable, se cargará el método details() del controlador Posts.

//specify route for post details page
$route['post/(:any)'] = 'posts/details/$1';

Fuente: codexworld.com

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP