Posted on 02-11-2007
Filed Under (Programación) by galifate

Aquí tenéis otro artículo traducidos sobre introducción a programación. En este caso, no se trata de nada de Java, sino de PHP y MySQL. Creo que es un buen articulito de ejemplo para meterse por primera vez en este tema. Bueno, es otra de mis traducciones, así que recomiendo mirar el original, escrito por Alejandro Gervasio en Devshed.

Construir un motor de búsqueda con MySQL y PHP 5

Si mantienes un sitio web de tamaño medio en crecimiento, puedes llegar a la conclusión de que necesitas un buscador interno para mejorar la experiencia del visitante de la web. Este artículo, el primero de tres partes, te introducirá en la elaboración de un buscador usando PHP y MySQL.

Introducción

Siendo uno de los lenguajes de programación más populares de la web actualmente, PHP da a los desarrolladores web las herramientas para hacer un vasto arsenal de aplicaciones que no podían ser creadas hace unos años. Sitios web database-driven, carritos de compra, sistemas de paginación y mecanismos de validación de formularios son sólo unos cuantos ejemplos de lo que se puede hacer con es lenguaje de scripting. PHP ha evolucionado significativamente y ahora muestra un maduro modelo orientado a objetos.

Sin embargo, hay que notar que aparte de la abundancia de aplicaciones web que pueden ser creadas fácilmente con PHP, hay una en particular que se está volviendo muy popular en muchos de los sitios web modernos a medida que crecen. En este caso, nos referimos al desarrollo de un motor de búsqueda interno para cualquier sitio web, usando las capacidades suministradas por el potente tandem MySQL/PHP5.

Los motores de búsqueda basados en web han existido durante mucho tiempo y han evolucionado constantemente, principalmente debido a los continuos avances de grandes compañías como Yahoo y Google entre otras.

Sin embargo, ahora no se trata de ser tan ambicioso como para abordar un proyecto tan complejo. En cambio, enfocaremos nuestra atención en una situación concreta que algunos desarrolladores de PHP tienen que afrontar frecuentemente. Deben tratar un sitio web de tamaño medio que requiere la implementación de un buscador interno, de modo que los usuarios puedan encontrar los contenidos que buscan de un modo más directo y fácil, sin la necesidad de navegar a través de un montón de páginas irrelevantes.

Desde un punto de vista teórico, hacer este tipo de aplicaciones puede parecer un proceso bastante simple que puede ser llevado a cabo sin más problemas. Pero en realidad, desarrollar un motor de búsqueda eficiente con PHP 5 y MySQL puede ser un reto, especialmente si eres un desarrollador de PHP que da sus primeros pasos en el área del desarrollo web.

Considerando que más y más sitios web están añadiendo buscadores propietarios a sus estructuras, en estos artículos, tres tutoriales, se va a enseñar como crear una aplicación de búsqueda web que puede ser adaptada fácilmente a tus necesidades personales. Pro supuesto, como habrás podido adivinar, se van a usar algunas tablas básicas de una base de datos MySQL para guardar los contenidos de un hipotético sitio web, pero esta condición puede se modificada rápidamente para trabajar con otro servidor de base de datos diferente.

Una vez presentado el objetivo de esta serie de artículos, es el momento de empezar a aprender cómo desarrollar un motor de búsqueda extensible usando la potente combinación MySQL/PHP5.


Creando el Front End

Un punto de inicio lógico para hacer este buscador con MySQL es crear un front-end básico. Éste estará formado por un simple formulario web donde los usuarios podrán introducir los diferentes términos de búsqueda. Naturalmente, estos términos de búsqueda se introducirán en una consulta “SELECT”, y se usará para devolver al cliente los correspondientes resultados de la base de datos, asumiendo que la búsqueda haya tenido éxito.

Así, teniendo en cuenta este requerimiento, más abajo se muestra la signatura de un fichero (X)HTML simple, llamado “form.htm.”. Éste simplemente muestra el formulario de búsqueda.

Aquí está la definición de este nuevo fichero:

(definición del fichero “form.htm”)

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-
8859-1" />

<title>MySQL-based Search Engine</title>
<link href="default.css" rel="stylesheet" type="text/css" media="screen" />
<script language="javascript" type="text/javascript">
window.onload=function(){
if(document.getElementById&&document.
getElementsByTagName&&document.createElement){

var sfield=document.getElementsByTagName('form')[0].elements[0];

if(!sfield){return};

sfield.onfocus=function(){this.value=''};

sfield.onblur=function(){

if(!this.value){this.value='Enter your search term here'};

}
}
}
</script>
</head>
<body>
<h1>MySQL-based Search Engine</h1>
<div class="maincontainer">
<form method="get" action="processform.php">
<input type="text" name="searchterm" title="Enter your search
term here" value="Enter your search term here"
class="searchbox" />

<input type="submit" name="search" title="Search Now!
"value="Search" class="searchbutton" />

</form>
</div>

</body>
</html>

Como se puede ver, el anterior HTML muestra un típico text input que permite a los usuarios introducir los términos de búsqueda. Estos términos serán procesados apropiadamente por MySQL para devolver algunos registros de la base de datos. Además se le ha dado algo más al formulario con JavaScript para hacerlo un poco más interactivo.

Ahora que se sabe como se ha creado la estructura básica, veremos el fichero de estilos “default.css”, cuya función es mejorar el look and feel del formulario.

(definición del fichero “default.css”)

body{
background: #ccc;
margin: 0;
padding: 0;
}
h1{
width: 375px;
padding: 10px;
margin-left: auto;
margin-right: auto;
background: #339;
font: normal 18px Arial, Helvetica, sans-serif;
color: #fff;
border: 1px solid #000;
text-align: center;
}
h2{
font: bold 18px Arial, Helvetica, sans-serif;
color: #339;
}
p{
font: normal 10pt Arial, Helvetica, sans-serif;
color: #000;
}
a:link,a:visited{
font: normal 10pt Arial, Helvetica, sans-serif;
color: #00f;
text-decoration: none;
}
a:hover{
color: #f00;
text-decoration: underline;
}
.maincontainer{
width: 375px;
padding: 10px;
margin-left: auto;
margin-right: auto;
background: #f0f0f0;
border: 1px solid #000;
}
.rowcontainer{
padding: 10px;
margin-bottom: 10px;
background: #ccf;
}
.searchbox{
width: 200px;
font: normal 12px Arial, Helvetica, sans-serif;
color: #000;
}
.searchbutton{
width: 80px;
font: bold 12px Arial, Helvetica, sans-serif;
color: #000;
}

El CSS anterior declara algunos estilos básicos que son bastante útiles para darle al formulario un aspecto visual decente. Después de aplicar el CSS, el formulario se ve como en la imagen siguiente:

img1.gif

Así, en este momento ya tenemos un front-end para introducir los términos de búsqueda. Estos términos se introducirán en una consulta SELECT y se procesarán por MySQL para devolver al cliente los resultados de la búsqueda.

En este caso, el proceso de búsqueda se efecutará en el servidor web con la ayuda de algunas clases PHP. En la siguiente sección se mostrarán estas clases.


Haciendo búsquedas con MySQL y PHP 5

Como se puede suponer, desarrollar la lógica de negocio que maneja esta aplicación de búsqueda basada en MySQL se reduce a definir un par de clases PHP. Estas clases serán responsables de efectuar algunas tareas cruciales como conectar con MySQL y ejecutar una sentencia SELECT, así como devolver al navegador los correspondientes resultados de la base de datos de acuerdo con la búsqueda realizada por el usuario mediante el formulario web.

Para efectuar todas las tareas mencionadas, se han definido dos clases PHP. Probablemente las encontrarás un poco familiares, puesto que ya han sido utilizadas en otros artículos del autor en Developer Shed Network.

Las clases en cuestión se han puesto en un único fichero, llamado “mysql.php”:

(definición del fichero “mysql.php”)

<?php
// define 'MySQL' class
class MySQL{
private $conId;
private $host;
private $user;
private $password;
private $database;
private $result;
const OPTIONS=4;

public function __construct($options=array()){
if(count($options)!=self::OPTIONS){
throw new Exception('Invalid number of connection parameters');
}
foreach($options as $parameter=>$value){
if(!$value){
throw new Exception('Invalid parameter '.$parameter);
}
$this->{$parameter}=$value;
}
$this->connectDB();
}
// connect to MySQL
private function connectDB(){
if(!$this->conId=mysql_connect($this->host,$this->user,$this->password)){
throw new Exception('Error connecting to the server');
}
if(!mysql_select_db($this->database,$this->conId)){
throw new Exception('Error selecting database');
}
}
// run query
public function query($query){
if(!$this->result=mysql_query($query,$this->conId)){
throw new Exception('Error performing query '.$query);
}
return new Result($this,$this->result);
}
public function escapeString($value){
return mysql_escape_string($value);
}
}
// define 'Result' class
class Result {
private $mysql;
private $result;
public function __construct(&$mysql,$result){
$this->mysql=&$mysql;
$this->result=$result;
}
// fetch row
public function fetchRow(){
return mysql_fetch_assoc($this->result);
}
// count rows
public function countRows(){
if(!$rows=mysql_num_rows($this->result)){
return false;
}
return $rows;
}
// count affected rows
public function countAffectedRows(){
if(!$rows=mysql_affected_rows($this->mysql->conId)){
throw new Exception('Error counting affected rows');
}
return $rows;
}
// get ID form last-inserted row
public function getInsertID(){
if(!$id=mysql_insert_id($this->mysql->conId)){
throw new Exception('Error getting ID');
}
return $id;
}
// seek row
public function seekRow($row=0){
if(!is_int($row)||$row<0){
throw new Exception('Invalid result set offset');
}
if(!mysql_data_seek($this->result,$row)){
throw new Exception('Error seeking data');
}
}
}
?>

Como se muestra arriba, el anterior fichero PHP usa un par de clases de proceso de MySQL para hacer un proceso de búsqueda contra una o más bases de datos. Además, nótese que la versátil y extensible estructura ofrecida por las clases PHP hace realmente fácil implementar un motor de búsqueda interno en cualquier sitio web existente.

En este punto has comprendido la lógica de negocio que hay detrás de este motor de búsqueda, puesto que sólo requiere unas cuantas clases PHP simple para hacer las correspondientes búsquedas en el servidor de MySQL. ¿Cual es el siguiente paso?

Bien, asumiendo que puede que quieras ver como los ficheros anteriores se pueden enlazar entre ellos para implementar una aplicación de búsqueda completamente funcional, en la siguiente sección se va a desarrollar un ejemplo ilustrativo para mostrar como poner este motor de búsqueda a trabajar rápidamente.

Ensamblando los módulos de búsqueda

Implementar este motor de búsqueda en MySQL es cuestión de recoger los términos de búsqueda introducidos en el formulario web, y entonces meterlos dentro de una consulta SELECT, y finalmente ejecutar la consulta en cuestión contra una o más bases de datos.

Lógicamente, el último paso del proceso es mostrar los resultados correspondiente (asumiendo que la consulta ha tenido éxito) en el navegador.

Basándonos en cómo debe funcionar la aplicación de búsqueda, más abajo se lista la definición de un nuevo fichero PHP. Se llama “processform.php” y está destinado, primero, a ejecutar el proceso de búsqueda contra una tabla de ejemplo “USERS”, y después mostrar el resultado al usuario final.

(definición del fichero “processform.php”)

<?php

// include MySQL-processing classes

require_once 'mysql.php';

try{

// connect to MySQL

$db=new MySQL(array
('host'=>'host','user'=>'user','password'=>'password',
'database'=>'database'));

$searchterm=$db->escapeString($_GET['searchterm']);

$result=$db->query("SELECT firstname, lastname,comments FROM
users WHERE MATCH(firstname,lastname,comments) AGAINST
('$searchterm')");

if(!$result->countRows()){

echo '<div class="maincontainer"><h2>No results were found. Go
back and try a new search.</h2></div>'."n";

}

else{

// display search results

echo '<div class="maincontainer"><h2>Your search criteria
returned '.$result->countRows().' results.</h2>'."n";

while($row=$result->fetchRow()){

echo '<div class="rowcontainer"><p><strong>First Name:
</strong>'.$row['firstname'].'<p><p><strong>Last Name:
</strong>'.$row['lastname'].'</p><p><strong>Comments:
</strong>'.$row['comments'].'</p></div>'."n";

}

}

echo '</div>';

}

catch(Exception $e){

echo $e->getMessage();

exit();

}

?>

Como puede ver, el fichero PHP anterior usa las dos clases de proceso de MySQL para realizar el pertinente proceso de búsqueda contra la tabla “USERS”. En este caso, el autor creó la consulta de búsqueda usando las clausulas “MATCH” y “AGAINST” para aprovecharse de las capacidades de tratamiento de texto que ofrece las versiones más recientes de MySQL, pero puede que quieras usar la sentencia “LIKE” más típica, particularmente si tus consultas son bastante primitivas.

Y finalmente, asumiendo que la mencionada tabla “USERS” ha sido rellenada anteriormente con los siguientes datos:

Id nombre apellido email comentario

1 Alejandro Gervasio alejandro@domain.com MySQL is great for building a search engine
2 John Williams john@domain.com PHP is a server side scripting language
3 Susan Norton sue@domain.com JavaScript is good to manipulate documents
4 Julie Wilson julie@domain.com MySQL is the best open source database server

Por favor, echa un vistazo a las siguientes capturas. Muestran los resultados de la base de datos devueltos por el buscador MySQL cuando se han usado los términos de búsqueda “Alejandro,” “Alejandro+Susan” y finalmente “Alejandro+Susan+John”:

img2.gif

img3.gif

img4.gif

Como se ha demostrado claramente con las imágenes anteriores, construir una aplicación de búsqueda extensible usando la potente combinación MySQL/PHP 5 e, en efecto, un proceso poco complicado que puede ser llevado a cabo con mínimos esfuerzos. Siéntete libre de usar todos los ficheros fuentes mostrados aquí para implementar el motor de búsqueda en tu propio sitio web, de modo que puedas suministrar a los usuarios la posibilidad de buscar sobre los contenidos de tu web.

Reflexión final

En esta primera parte de la serie de artículos, se espera que hayas aprendido como crear una aplicación de búsqueda extensibles usando las capacidades ofrecidas por MySQL y PHP5. Sin embargo, este instructivo viaje aun no ha acabado, puesto que la aplicación carece de características importante, como la implementación de búsquedas booleanas reales y paginación de los resultados.

Todas estas mejoras se presentaran en la siguiente parte de esta serie de artículos.

Vía DevShed.

Discutir en el foro (0)

    Read More   

Comments

[…] el Blog del Galifate hay otro tutorial de programación, el cual es otra traducción de un artículo de DevShed. Se trata de la primera […]


pavel on 6 Diciembre, 2007 at 11:43 pm #

que tal, creo que tiene un error este ejemplo, la verdad es que no sé donde está ni si es por las versiones de PHP pero el mensaje que arroja al hacer la consulta es: Error performing query SELECT firstname, lastname,comments FROM users WHERE MATCH(firstname,lastname,comments) AGAINST (’xxx’)

Si alguien sabe de qué se trata esto les agradeceria respuesta.
Saludos


Miguel Herrero on 26 Diciembre, 2007 at 10:12 am #

El error está en el motor de la base de datos:ha de ser MyISAM, y luego hay que crear los índices FULLTEXT con “ALTER TABLE users ADD FULLTEXT(firstname, lastname, comments);”.


Fab on 15 Febrero, 2008 at 1:15 pm #

Hola, gracias por la información esta muy interesante.
¿En donde encuentro la 2da y 3era parte de este artículo?


Post a Comment
Name:
Email:
Website:
Comments: