Advertisement
Guest User

Generador De Consulta MySQL FullText

a guest
Oct 29th, 2011
106
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 13.46 KB | None | 0 0
  1. <?php
  2. /**
  3.  * Clase BuscadorFullText.
  4.  * Es responsable de entregarnos el codigo de una consulta para la Base de datos
  5.  * MySQL con motor MyIsam, basandose en los Indices FullText.
  6.  * Ver http://dev.mysql.com/doc/refman/5.0/es/fulltext-search.html
  7.  * Ver http://dev.mysql.com/doc/refman/5.0/es/fulltext-fine-tuning.html
  8.  * Ver http://dev.mysql.com/doc/refman/5.0/es/information-functions.html
  9.  *
  10.  * @package     varias creado en el projecto opet
  11.  * @copyright   2011 - ObjetivoPHP
  12.  * @license     Gratuito (Free) http://www.opensource.org/licenses/gpl-license.html
  13.  * @author      Marcelo Castro (ObjetivoPHP)
  14.  * @link        objetivophp@gmail.com
  15.  * @version     2.3.0 (27/12/2009 - 15/05/2011)
  16.  * @since       ver uso de str_word_count( $_POST['buscar'], 1, '+-~<>');
  17.  *              para proxima version
  18.  * @since       Continua  serie BuscadorGenerico 4.4.6 del 21/05/2007.
  19.  */
  20. class BuscadorFullText
  21. {
  22.     /**
  23.      * Contiene la cadena de busqueda, generalmente su contenido se correlaciona
  24.      * con un campo en el formulario de busqueda.
  25.      * @var string
  26.      */
  27.     private $_textoDeBusqueda;
  28.  
  29.     /**
  30.      * Contiene la tabla de la base en la cual se realizara la consulta.
  31.      * @var string
  32.      */
  33.     private $_tablaMysql;
  34.  
  35.     /**
  36.      * Coleccion de campos que se retornaran como resultado.
  37.      * @var array
  38.      */
  39.     private $_colCamposResultado = array();
  40.  
  41.     /**
  42.      * Coleccion de campos que se utilizan para la busqueda de tipo fulltext.
  43.      * @var array
  44.      */
  45.     private $_colCamposFullText = array();
  46.  
  47.     /**
  48.      * Coleccion de parametros adiccionales a incluirle a la consulta.
  49.      * Todos se añaden con tipo AND.
  50.      * @var array
  51.      */
  52.     private $_colParametros = array();
  53.  
  54.     /**
  55.      * Contiene el tipo de consulta que se realizo.
  56.      * @var string
  57.      */
  58.     private $_tipoConsulta = 'FULLTEXT';
  59.  
  60.     /**
  61.      * Configura si utiliza SQL_CALC_FOUND_ROWS en la consulta mysql para luego extraer la
  62.      * cantidad de resultados con limit.
  63.      * @var boolean
  64.      */
  65.     private $_SQL_CALC_FOUND_ROWS = true;
  66.  
  67.     /**
  68.      * Contiene el metodo de envio del Formulario.
  69.      * Utilizado en los metodos getValue y addParametros.
  70.      * @var string
  71.      */
  72.     private $_metodoEnvio = 'POST';
  73.  
  74.     /**
  75.      * Contiene los operadores para parametros variables permitidos.
  76.      * @var array
  77.      */
  78.     private static $_operadores = array('=', '<=>', '<>', '!=', '<=', '<',
  79.                                         '>', 'IS', 'IS NOT', 'IS NULL',
  80.                                         'IS NOT NULL');
  81.  
  82.     /**
  83.      * Configura si la palabra se toma en cuenta una vez, o cada vez que aparece.
  84.      * Por defecto cada vez que aparece se toma en cuenta.
  85.      * @var boolean
  86.      */
  87.     private $_sumarUnaVez = false;
  88.  
  89.    
  90.     private $_filtrarPalabras = array();
  91.    
  92.     /**
  93.      * Metodo __construct.
  94.      * Crea un objeto BuscadorFullText
  95.      * @param   string  $buscar Cadena de busqueda puede contener +-~><
  96.      * @param   string  $tabla  Nombre de la Tabla MySQL a usar en la consulta.
  97.      * @return  void
  98.      */
  99.     public function  __construct($buscar, $tabla)
  100.     {
  101.         $this->_textoDeBusqueda = addslashes($buscar);
  102.         $this->_tablaMysql      = addslashes($tabla);
  103.     }
  104.  
  105.     /**
  106.      * Metodo addCamposResultado.
  107.      * Ingresa los campos que se usaran como resultado de la consulta.
  108.      * @param   string/array  $campo Contiene el o los nombres de los campos.
  109.      * @return  void
  110.      */
  111.     public function addCamposResultado($campo)
  112.     {
  113.         if (is_string($campo)) {
  114.             $campo  = explode(',', $campo);
  115.         }
  116.         if (is_array($campo)) {
  117.             foreach ($campo as $valor) {
  118.                 $this->_colCamposResultado[] = $valor;
  119.             }
  120.         }
  121.     }
  122.    
  123.     /**
  124.      * Metodo addFiltro.
  125.      * Agrega palabras que seran eliminados de la consulta de busqueda.
  126.      * @param   array   Contiene las palabras a eliminar.
  127.      * @return  void
  128.      */
  129.     public function addFiltro(array $filtrar)
  130.     {
  131.         if (!is_array($filtrar)) {
  132.             return false;
  133.         }
  134.         // Si es un arreglo lo dejo preparado.
  135.         foreach($filtrar as $palabra) {
  136.             $palabra    = '/[\w]*(\s' . $palabra . '\*)[\w]*/';
  137.             $this->_filtrarPalabras[] = $palabra;
  138.         }
  139.     }
  140.  
  141.     /**
  142.      * Metodo limitarLargo.
  143.      * Limita el largo de un campo a un determinado numero de caracteres.
  144.      * @version 2.1.0 (21/11/2010)
  145.      * @param   string  $campo      nombre de campo.
  146.      * @param   integer $caracteres Cantidad de caracteres que retornara la consulta.
  147.      * @return  void
  148.      */
  149.     public function limitarLargo($campo, $caracteres)
  150.     {
  151.         $clave  = array_search($campo, $this->_colCamposResultado);
  152.         if ($clave !== false) {
  153.             $caracteres = ($caracteres > 0)? $caracteres : 250;
  154.             $this->_colCamposResultado[$clave] = 'LEFT(`' . $campo . '`, ' .$caracteres . ') as ' . $campo;
  155.         }
  156.     }
  157.  
  158.     /**
  159.      * Metodo addCamposFullText.
  160.      * Ingresa los campos que se usaran para la consulta.
  161.      * @param   string/array  $campo Contiene el o los nombres de los campos.
  162.      * @return  void
  163.      */
  164.     public function addCamposFullText($campo)
  165.     {
  166.         if (is_string($campo)) {
  167.             $campo  = explode(',', $campo);
  168.         }
  169.         if (is_array($campo)) {
  170.             foreach ($campo as $valor) {
  171.                 $this->_colCamposFullText[] = $valor;
  172.             }
  173.         }
  174.     }
  175.  
  176.     /**
  177.      * Metodo addParametrosVariables.
  178.      * Inserta un parametro a la consulta.
  179.      * @param   string  $campo      Nombre del campo en el formulario de consulta, debe
  180.      *                              coincidir con el de la base de datos.
  181.      * @param   string  $operador   operador de consulta = > < etc.
  182.      * @return  void
  183.      */
  184.     public function addParametrosVariables($campo, $operador)
  185.     {
  186.         $valor      = ($this->_metodoEnvio == 'POST')? $_POST[$campo] : $_GET[$campo];
  187.         if (!in_array($operador, self::$_operadores)) {
  188.             trigger_error('Operador de Consulta no valido en Metodo ' . __METHOD__, E_USER_ERROR);
  189.         }
  190.         $parametro  = $campo . ' ' . $operador . " '" . addslashes($valor) . "'";
  191.         $this->_colParametros[] = $parametro;
  192.     }
  193.  
  194.     /**
  195.      * Metodo addParametrosFijos.
  196.      * Agrega parametros fijos en la consulta.
  197.      * @param   string  $parametros parametro tipo campo='valor'
  198.      * @return  void
  199.      */
  200.     public function addParametrosFijos($parametros)
  201.     {
  202.         $this->_colParametros[] = $parametros;
  203.     }
  204.  
  205.     /**
  206.      * Metodo setSqlCalcFoundRows.
  207.      * Configura si debe ponerse en la consulta MySQL la clausula SQL_CALC_FOUND_ROWS.
  208.      * @param   boolean $boolean    true por si, false por no.
  209.      * @return  void
  210.      */
  211.     public function setSqlCalcFoundRows($boolean)
  212.     {
  213.         $this->_SQL_CALC_FOUND_ROWS = ($boolean)? true:false;
  214.     }
  215.  
  216.     /**
  217.      * Metodo setMetodoEnvio.
  218.      * Configura por que metodo se envia el formulario (GET, POST).
  219.      * @param   string  $metodo Metodo a utilizarce para levantar las variables
  220.      *                          del formulario.
  221.      * @return  void
  222.      */
  223.     public function setMetodoEnvio($metodo = 'POST')
  224.     {
  225.         ($metodo == 'GET')? $this->_metodoEnvio = 'GET' : $this->_metodoEnvio = 'POST';
  226.     }
  227.  
  228.     /**
  229.      * Metodo getValue.
  230.      * Retorna una cadena que se puede colocar dentro del value de un campo
  231.      * de busqueda.
  232.      * @param   string  $campo  Nombre del campo que se debe levantar.
  233.      * @param   string  $metodo metodo POST o GET. Por defecto POST.
  234.      * @return  string  Cadena tipo value.
  235.      */
  236.     public function getValue($campo)
  237.     {
  238.         $valor  = ($this->_metodoEnvio == 'POST')? $_POST[$campo] : $_GET[$campo];
  239.         return stripslashes(str_replace('"', "'", $valor));
  240.     }
  241.  
  242.     /**
  243.      * Configura si se desea tomar una palabra con incidencia igual 1 por mas que
  244.      * se repita (true), o si la palabra incide cada vez que aparece (false)
  245.      * @param boolean $cont
  246.      */
  247.     public function setContarUnaVez($cont = false)
  248.     {
  249.         $this->_sumarUnaVez = $cont ? true : false;
  250.     }
  251.  
  252.     /**
  253.      * Metodo getConsultaMysql.
  254.      * Genera una consulta MySQL, para un buscador dependiendo de el largo de la
  255.      * cadena utiliza like o modo fulltext.
  256.      * @param   string  $texto
  257.      * @return  string  Consulta MySQL para busqueda.
  258.      */
  259.     public function getConsultaMysql($texto='')
  260.     {
  261.         // Veo si cambia el texto de busqueda o si lo mantiene.
  262.         $this->_textoDeBusqueda = ($texto)? addslashes($texto) : $this->_textoDeBusqueda;
  263.         // Comienzo a generar la consulta MySql
  264.         $mySqlQuery             = (strlen($this->_textoDeBusqueda) < 4)?
  265.                                 $this->_getConsultaLike($this->_textoDeBusqueda) :
  266.                                 $this->_getConsultaFullText($this->_textoDeBusqueda);
  267.         // Agregamos los Parametros a la consulta
  268.         if ($this->_colParametros) {
  269.             $mySqlQuery        .= ' && (' . implode(' && ', $this->_colParametros) . ' ) ';
  270.         }
  271.         // Cerramos la consulta
  272.         $mySqlQuery             = ($this->_tipoConsulta == 'FULLTEXT')? $mySqlQuery . " ORDER BY puntuacion DESC" : $mySqlQuery;
  273.         $mySqlQuery             = $mySqlQuery . ' LIMIT %d, %d';
  274.         return $mySqlQuery;
  275.     }
  276.  
  277.     /**
  278.      * Genera la consulta tipo Like.
  279.      * @param   string      $texto  Texto de busqueda.
  280.      * @return  string      Cadena para consulta MySQL con LIKE.
  281.      */
  282.     private function _getConsultaLike($texto)
  283.     {   $this->_tipoConsulta= 'LIKE';
  284.         $inicio             = ($this->_SQL_CALC_FOUND_ROWS)? 'SELECT SQL_CALC_FOUND_ROWS ':'SELECT ';
  285.         $camposResultados   = (count($this->_colCamposResultado))? implode(', ', $this->_colCamposResultado) : '*';
  286.         $consulta           = $inicio . $camposResultados . " FROM " . $this->_tablaMysql . " WHERE ( ";
  287.  
  288.         foreach($this->_colCamposFullText as $campo)
  289.         {
  290.             $consulta       = $consulta . " " . $campo . " LIKE '%%" . $texto . "%%' OR ";
  291.         }
  292.         $consulta           = substr($consulta,0,strlen($consulta)-3) ." ) ";
  293.         return $consulta;
  294.     }
  295.  
  296.     /**
  297.      * Genera la consulta fulltext.
  298.      * @param   string      $texto  Texto de busqueda
  299.      * @return  string      Cadena para consulta MySQL tipo FULLTEXT.
  300.      */
  301.     private function _getConsultaFullText($texto)
  302.     {
  303.         $this->_tipoConsulta= 'FULLTEXT';
  304.  
  305.         $camposFullText     = implode(', ', $this->_colCamposFullText);
  306.         $parsearTexto       = $this->_cadenaFullText($texto);
  307.         $inicio             = ($this->_SQL_CALC_FOUND_ROWS)? 'SELECT SQL_CALC_FOUND_ROWS ':'SELECT ';
  308.         $camposResultados   = (count($this->_colCamposResultado))? implode(', ', $this->_colCamposResultado) : '*';
  309.         $consulta           = $inicio . " " . $camposResultados . ", MATCH( $camposFullText ) AGAINST ('$parsearTexto' ";
  310.         $consulta          .= ($this->_sumarUnaVez)? 'IN BOOLEAN MODE )' : ')';
  311.         $consulta          .= " AS puntuacion FROM $this->_tablaMysql "
  312.                             . " WHERE MATCH( $camposFullText ) AGAINST ('$parsearTexto' IN BOOLEAN MODE)";
  313.         return  $consulta;
  314.     }
  315.  
  316.     /**
  317.      * Metodo cadenaFullText.
  318.      * Genera la cadena que ira en la parte  AGAINST, de la consulta MySQL.
  319.      * @param   string  $texto  Texto digitado por el usuario.
  320.      * @return  string
  321.      */
  322.     private function _cadenaFullText($texto)
  323.     {
  324.         $patron     = array('/\s\s+/',                      // Quito espacios en blanco de mas
  325.                             '/\'/',                         // Cambio comillas simples por dobles
  326.                             '/([\+\-\~\<\>])(\s)/',         // junto los simbolos con las palabras de busqueda
  327.                             '/([\w]*)([\+\-\~\<\>\)])/',    // Separo los simbolos de las palabras que los anteceden);
  328.                             '/\*/',
  329.                             '/\s\s+/');                     // Vuelvo a sacar espacios en blanco por las dudas
  330.         $remplazo   = array(' ', '"','\1', '\1 \2', '', ' ');
  331.         $texto      = preg_replace($patron, $remplazo, $texto);
  332.  
  333.         // Separamos las cadenas entre comillas.
  334.         $datos      = explode('"', str_replace('\\', '', $texto));
  335.  
  336.         $cantidad   = count($datos);
  337.         for ($index = 0; $index < $cantidad; $index++) {
  338.             if(($index % 2) == 0 && $datos[$index] ) {
  339.                 $partes         = explode(' ', trim($datos[$index]));
  340.                 $datos[$index]  = implode('* ', $partes) . '* ';
  341.             } elseif ($datos[$index]) {
  342.                 // Ordeno en caso que sea una cadena entrecomillada
  343.                 $simbolo    = substr($datos[$index - 1], strlen($datos[$index - 1])-3,1);
  344.                 $datos[$index]  = '"' . $datos[$index] .'"';
  345.                 if (strpos("+-~<>", $simbolo) !== false) {
  346.                     $datos[$index]  = $simbolo . $datos[$index];
  347.                     $datos[$index-1]= substr($datos[$index-1], 0, strlen($datos[$index - 1])-3);
  348.                 }
  349.             }
  350.         }
  351.         $texto  = implode(' ', $datos);
  352.  
  353.         // Correcciones Finales
  354.         $patron     = array('/\(\*/', '/\)\*/', '/[\+\-\~\<\>]\*/','(á)','(é)','(í)','(ó)','(ú)','(Á)','(É)','(Í)','(Ó)','(Ú)');
  355.         $remplazo   = array('(', ')', '','a','e','i','o','u','A','E','I','O','U');
  356.         $texto      = preg_replace($patron, $remplazo, $texto);
  357.         // Filtrado final
  358.         if (count($this->_filtrarPalabras)) {
  359.             $texto  = preg_replace($this->_filtrarPalabras, '', $texto);
  360.         }
  361.         return $texto;
  362.     }
  363. }
  364.  
  365.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement