filtrar contenido con jquery

Iniciado por gAb1, 16 Noviembre 2015, 06:11 AM

0 Miembros y 2 Visitantes están viendo este tema.

gAb1

#10
Pues ahora que lo dices, al principio se imprimia el \n, pero porque se me olvido cambiar las comillas normales '\n' a dobles "\n". Ahora imprime el salto de linea, ¿eso no debe dar ningún error no? Si se ponen saltos de linea sin variables y no pasa nada. (Lo he quitado y nada, el mismo error sin saltos de linea)

Acaba de encontrar un supuesto error:

Código (sql) [Seleccionar]
SELECT t1.id, t2.*
FROM for_sale t1
INNER JOIN property t2 ON t2.id = t1.id
WHERE t2.use = 1
AND t2.type = 2
OR t2.type = 3
NULL
NULL
NULL
NULL
LIMIT ?, ?


Podria ser por las variables que se imprimen como NULL, sin embargo le acaba de poner else unset() a los IFs y sigue tirando el mismo error. Ya no sé que más probar...

Código (php) [Seleccionar]
if ($filter_type != NULL) {
   foreach ($filter_type as $type=>$value) {
       if ($type === 0) {
           $type_cond = 'AND t2.type = ' . $value;
       } else {
           $type_cond .= $type_cond . "\n OR t2.type = " . $value;
       }
   }
} else unset($filter_status); // Ya no imprime NULL dentro del prepare()


EDITO: Que extraño, al marcar 3 checkboxes se repite el primero... Puede ser el foreach (que lo dudo) o el array...

Código (sql) [Seleccionar]
MySQLi failed: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 't2.type = 1
OR t2.type = 2AND t2.type = 1AND t2.type = 1
OR t2.type = 2
OR t2' at line 5<br><br />


Esos dos AND despues del primer OR están de más... ¿Como es posible que se este imprimiendo asi?

Al parecer lo del NULL no tiene nada que ver, no se llega a imprimir, asi que esos unset() están de más.

MinusFour

#11
Esto ya se vuelve un problema de PHP y MySQL:

Tienes que usar los paréntesis y USE y TYPE son palabras reservadas. Por eso la etiqueta code te resalta en rojo esas palabras:

Código (mysql) [Seleccionar]

SELECT t1.id, t2.*
FROM for_sale t1
INNER JOIN property t2 ON t2.id = t1.id
WHERE t2.`USE` = 1
AND (t2.`TYPE` = 2 OR t2.`TYPE` = 1 OR t2.`TYPE` = 3)
AND (t2.`STATUS` = 0 OR t2.`STATUS` = 1 OR t2.`STATUS` = 2)
AND (t2.bhk = 3 OR t2.bhk = 1 OR t2.bhk = 2)


Está es una forma de hacerlo con PHP:

Código (php) [Seleccionar]

<?php
function agregaCondicionCompuesta($campo$valores){
    
$red = function($acc$valor) use ($campo){
  
$condicion "$campo = $valor";
  
if($acc){
  
return $acc ' OR ' $condicion;
  
} else {
    
return $condicion
  
}
};
    
$reduced array_reduce($valores$red);
    return 
count($valores) > "($reduced)" $reduced;
}


O una manera más sencilla de verla sin el reduce:

Código (php) [Seleccionar]

function agregaCondicionCompuesta($campo, $valores){
 $query = '';
 foreach($valores as $index => $valor){
   $condicion = "$campo = $valor";
   if($index == 0){
     $query .= $condicion;
   } else {
     $query .= ' OR ' . $condicion;
   }
 }
 return count($valores) > 1 ? "($query)" : $query;
}


Después simplemente agregas las condiciones compuestas:

Código (php) [Seleccionar]

$filtros = [0, 1];
$use = [1];
echo agregaCondicionCompuesta('t2.`USE`', $use) . ' AND ' . agregaCondicionCompuesta('t2.`TYPE`', $filtros);
//t2.`USE` = 1 AND (t2.`TYPE` = 0 OR t2.`TYPE` = 1)


Claro que esto deja mucho que desear porque te pueden hacer SQL Injection. Puedes usar '?' en lugar de $valor si vas a usar prepared statements:

Código (php) [Seleccionar]

$condicion = "$campo = ?";


Luego simplemente haces el bind de las variables con un for. Ojo que los parámetros van en orden, y si tienes otros parámetros antes estos tienen que ser puestos primero.

Ultimadamente creo que sería mejor que en lugar de usar múltiples ORs usaras la función IN de MySQL:

Código (mysql) [Seleccionar]

   SELECT t1.id, t2.*
   FROM for_sale t1
   INNER JOIN property t2 ON t2.id = t1.id
   WHERE t2.`USE` = 1
   AND t2.`TYPE` IN(1, 2, 3);
   AND t2.`STATUS` IN(0, 1, 2)
   AND t2.bhk IN(1, 2, 3)


Estoy seguro que te puedes imaginar formas de como agregar los valores tu solo a lo que hay dentro de el IN.

gAb1

#12
Tienes razón, debería escapar las palabras reservadas (aunque ese no fuera el problema). El problema estaba en la primera condición, que no dejaba un espacio o un salto de linea y se juntaba "use = 1AND t2.type".

Gracias por las funciones, tenia pensado hacer una cuando funcionara bien. Sobre lo del SQL Injection dudo mucho que se pueda hacer usando enteros  ;D Aunque sería mejor practica usar el bind_param es más trabajo.

Voy a adaptar la función que usa el reduce para usar el IN, yo tambien creo que mejor. Aunque aún estoy pensando en como hacerlo...  :rolleyes: Primero usar IN en lugar de ORs y lo del bind_param... En cuanto lo tenga edito.

Por mi se puede mover al subforo de PHP, donde podrá ser visto por todos.

Gracias!

EDITO: Al final no me hizo falta el array_reduce()

Código (php) [Seleccionar]
function addQueryCond($col, $values) {

   $red = function($acc, $values) use ($col) {

       $condition = '';
       $count = count($values);

       foreach ($values as $key=>$value) {
           if ($key === 0) {
               $condition = "\nAND ". $col . ' IN(?';
               if ($count === 1) {
                   $condition .= . $condition . ')';
               }
           } else if ($key < $count) {
               $condition .= $condition . ', ?';
           } else {
               $condition .= $condition . ', ?)';
           }
       }
   };

   return array($condition, $count); // count para el bind_param
}


Luego para hacer el bind_param()... No lo tengo claro aun xD

EDITO 2: A ver no se me ocurre como reducir esto...

Código (php) [Seleccionar]
if ($filter_type != NULL) {
   $data = addQueryCond('t2.`type`', $filter_type);
   $type_cond = $data[0];
   $type_count = $data[1];
}

if ($filter_status != NULL) {
   $data = addQueryCond('t2.`status`', $filter_status);
   $status_cond = $data[0];
   $status_count = $data[1];
}

if ($filter_bhk != NULL) {
   $data = addQueryCond('t2.bhk', $filter_bhk);
   $bhk_cond = $data[0];
   $bhk_count = $data[1];
}

if (isset($type_count)) {
   foreach($type_count as $count) {
       $var = 'type' . $count;
       foreach($filter_type as $filter) {
           $$var = $filter;
       }
   }
}
if (isset($status_count)) {
   foreach($status_count as $count) {
       $var = 'status' . $count;
       foreach($filter_status as $filter) {
           $$var = $filter;
       }
   }
}
if (isset($bhk_count)) {
   foreach($bhk_count as $count) {
       $var = 'bhk' . $count;
       foreach($filter_bhk as $filter) {
           $$var = $filter;
       }
   }
}


Al parecer con PDO se puede hacer mucho más facilmente lo que quiero, voy a mirar como funciona.