2010-12-08 11 views
7

Actualmente, tengo el siguiente código:

if(isset($_GET['mid']) && !empty($_GET['mid'])) { 
    $mid = $_GET['mid']; 

    if(is_numeric($mid) && $mid > 0) { 
     if(isset($_GET['op']) && !empty($_GET['op'])) { 
      $op = $_GET['op']; 

      if($op == 'info') { 
      } 

      if($op == 'cast') { 
      } 
     } 
    } 
} 

Pero creo que es demasiado "complejo" con sentencias if dentro de si las declaraciones, etc ...

manejaría de manera diferente? ¿Cómo lo harías más simple?

[EDIT] respuesta aceptado:

Bueno, he aprendido algunos detalles pequeños y nuevas funciones de PHP que no era consciente. No creo que haya exactamente una forma de hacer lo que solicité. Claramente estaba usando algunas funciones de PHP de una manera incorrecta y lo arreglaré.

Me parece que una entrada como esta debe validarse/desinfectarse con funciones de filtro de PHP y, por lo tanto, marcó como respuesta de Arkh aceptada.

Sin embargo, para un proyecto universitario específico (que el código PHP es completamente irrelevante) voy a utilizar una combinación de su respuesta con Tatu función de ayuda idea. Pero para un proyecto diferente, usaré una combinación de su respuesta con idea de clase de Ignacio porque se ve mejor y más organizada.

+2

En primer lugar, hacer que su código sólo sensata. 'if (is_numeric ($ mid) && $ mid> 0) {' => 'if (is_numeric ($ mid))', 'if (isset ($ _ GET ['mid']) &&! empty ($ _ GET [' mid '])) '=>' if (! empty ($ _ GET [' mid '])) 'y así sucesivamente. Ver http://php.net/empty –

+0

No sabía 'is_numeric()' devolvió falso para '0'. El otro tampoco lo sabía. –

+2

No es así. ['is_numeric()'] (http://php.net/is_numeric) devuelve 'TRUE' en' 0'. Sin embargo, puede colapsar 'isset()' en '! Empty()'. –

Respuesta

11

me gustaría utilizar filter_input con el filtro para mediados FILTER_SANITIZE_NUMBER_FLOAT. Algo así:

$mid = filter_input(INPUT_GET, 'mid', FILTER_SANITIZE_NUMBER_FLOAT); 
$op = filter_input(INPUT_GET, 'op'); 
if($mid > 0){ 
    switch($op){ 
    case 'info': 
     // Some code 
     break; 
    case 'cast': 
     // Some more code 
     break; 
    default: 
     break; 
    } 
} 
+0

Esto tiene un problema: si '$ _GET ['op']' contiene la cadena 'info', su bloque de conmutadores ejecutará todo el código de todos los casos. Deberías agregar descansos. – Stephen

+0

@Stephen lo suficientemente fácil como para editar la respuesta para agregarlos. –

+0

@Mark ehh ... No pensé en eso. – Stephen

5

Escribiría una función que tomaría el nombre del índice, y devolvería el valor dentro de $_GET o lanzaría una excepción.

Eso, o encapsular en una clase similar a la siguiente:

#$_GET = array('name' => 'Ignacio', 'foo' => '42'); 

class Get 
{ 
    public static function string($name) 
    { 
    if (isset($_GET[$name])) 
    { 
     return $_GET[$name]; 
    } 
    else 
    { 
     throw new Exception(sprintf('Unknown GET parameter "%s"', $name)); 
    } 
    } 

    public static function int($name) 
    { 
    $val = Get::string($name); 
    $ret = filter_var($val, FILTER_VALIDATE_INT); 
    if ($ret != $val) 
    { 
     throw new Exception(sprintf('Invalid int GET parameter "%s"', $name)); 
    } 
    return $ret; 
    } 
} 

echo Get::string('name') . "\n"; 
echo Get::int('foo') . "\n"; 
#echo Get::int('name') . "\n"; 
#echo Get::int('age') . "\n"; 
+0

¿Podría dar un ejemplo sobre ese enfoque de clase? –

+0

Claro, solo dame unos minutos para escribirlo ... –

+0

Me gusta este :) – Nigel

2

se puede hacer una función auxiliar:

function getvar($var) { 
    return isset($_GET[$var]) && !empty($_GET[$var]) ? $_GET[$var] : false; 
} 

$mid = getvar('mid'); 
$op = getvar('op'); 

if(is_numeric($mid) && $mid > 0) { 
    if($op == 'info') { 
    } 

    if($op == 'cast') { 
    } 
} 

Eso haría que su código un poco más limpia, pero el código sí mismo está bien.

+3

Comprobando si una variable 'isset' y/o' empty' es redundante. 'empty' ya verifica si está configurado. – Stephen

-1

No hay nada de malo en esto. Anidado si las declaraciones son absolutamente correctas. Aunque puede usar filter.

+0

Sí, la pregunta era más sobre "complejidad del código" en términos de cómo se ve. Normalmente tiendo a tener líneas de hasta 80 caracteres y con muchas declaraciones if anidadas, el "código real" tendrá poco espacio para respirar. –

+1

Hay muchos errores con esto. – Stephen

+0

@Stephen continúa. –

4
  1. empty ya verifica si una variable isset.
  2. is_numeric es un poco prolijo, ya que también se está comprobando en contra de 0.
  3. Una sentencia switch es el más adecuado para el control de las variables contra la cadena de múltiples valores

Me gustaría hacer esto:

$mid = empty($_GET['mid']) ? 0 : (int)$_GET['mid']; 
           // casting as an integer will 
           // make undesirable strings = 0 

if ($mid > 0 && !empty($_GET['op'])) { 
    switch($_GET['op']) { 
     case 'info': 
      break; 
     case 'cast': 
      break; 
     default: 
      break; 
    } 
} 

Si necesita almacenar $_GET['op'] en una variable para más adelante, usted podría hacerlo antes del bloqueo del interruptor, aunque no lo haría a menos que fuera necesario.

2

Lo que podría hacer es definir una función de filtro (que ya existe en PHP> = 5.2) que filtraría una variable basada en un argumento sobre qué tipo es, si es un número, una cadena o más en tus requerimientos

function myfilter($variable, $type) { 
    switch($type){ 
     case 'numeric': 
     //check for numbers 
     return the number or false based on check 
     break; 
     case 'alphanumberic': 
     //check for alphanumeric 
     return the text or false based on check 
     break; 
    } 
} 

A continuación, utilice esta función para filtrar los valores que se obtienen usando $ _GET

$foo = myfilter($_GET['foo'], 'numeric'); 
$bar = myfilter($_GET['bar'], 'alphanumeric'); 
+0

Actualmente existe en PHP> = 5.2 – Stephen

+0

Ah, gracias, editando mi respuesta – Nigel

0

Haría algo como lo siguiente. Más o menos. Pero también puedes usar filtros para muchas de estas cosas. Y también puede desactivar las advertencias y simplemente usar empty() y no preocuparse por isset en el primer fragmento.

function checkVar($var) 
{ 
    if(isset($var) && !empty($var)) { 
     return true; 
    } 
    return false; 
} 

function checkID($id){ 
    if(checkVar($id) && is_numeric($id) && $id > 0) { 
     return $id; 
    } 
    return false; 
} 

if($mid = checkID($_GET['mid'])) { 
    if(checkVar($_GET['op'])) { 
     switch($_GET['op']) { 
      case 'info': 
      break; 

      case 'cast': 
      break; 
     } 
    } 
} 
+1

Comprobando si una variable 'isset' y/o no' empty' es redundante. 'empty' ya verifica si está configurado. – Stephen

+0

@Stephen: http://php.net/manual/en/function.empty.php No de acuerdo con los documentos. Lo que significa que arrojaría una advertencia. Tal vez tienes advertencias desactivadas y nunca lo has visto. – DampeS8N

+0

Tsk. Tsk. Verifique sus hechos. Esto es de la página a la que se hace referencia: "empty() es lo opuesto a var (booleano), excepto que no se genera ninguna advertencia cuando la variable no está configurada". – Stephen

0

Parece un poco complejo. Pero parece que quieres probar una gran cantidad de condiciones de borde. Sin embargo, hay formas de unificar el proceso. Estoy usando un wrapper class para ello:

if ($_GET->int["mid"]) { 
if ($_GET->in_array("op", "info,cast")) { 

Pero se podría definir un método personalizado que combina toda la isset y is_numeric cheques o lo que sea.

+0

Eso sobrecarga el superglobal '$ _GET'? ¡No está bien! – Stephen

+0

@Stephen: Sí. La semántica está cerca. Pero si le gusta la complejidad, también puede definir objetos de envoltura: '$ getVars = new input ($ _ GET)' yikes. – mario

+0

No sé por qué esto fue votado negativamente. Puede que no esté de acuerdo con la implementación recomendada, pero sigue siendo una estrategia válida. +1 para el equilibrio. – Stephen

3

Me gusta la idea de crear una clase InputFilter que implemente ArrayAccess. Esto está más orientado a objetos y más personalizable, ya que puede agregar métodos a voluntad para la personalización y trabajar con el mismo objeto de filtro principal.

$get = new InputFilter($_GET); 
echo $get->value_integer('variable_name'); 

Lo que también es bueno de esto es que es reutilizable por $ _POST, etc. Sólo había necesidad de hacer algo como $post = new InputFilter($_POST);. Y también puede usarlo para otras fuentes de entrada.

O, si tiene una versión lo suficientemente nueva de php, podría implementar filter_input() más adelante también, como lo sugiere @Arkh. OMI, tener su propia clase se siente mucho más reutilizable y duradera.

<?php 

// empty for now, fill in later if desired 
class InputFilterException extends Exception {} 

/* 
* Use the ArrayAccess interface as a template. 
* 
* Usage examples: 
* $controller->get = InputFilter($_GET); 
* echo $controller->get->value_string_html('variable'); 
* $controller->post = InputFilter($_POST); 
* echo $controller->get->value_integer('variable'); 
*/ 
class InputFilter implements ArrayAccess { 

    protected $data; 

    function __construct($data) { 
     if(!is_array($data)) { 
      throw new InputFilterException ("Only arrays are allowed here"); 
     } 
     $this->data = $data; 
    } 

    // do not actually use these 
    function __get($offset) { 
     throw new InputFilterException("Don't use as an array, use functions ->string() ->int() etc: ['" . $offset . "']"); 
    } 
    function __set($offset, $value) { 
     throw new InputFilterException("Don't modify directly: ['" . $offset . "'] = \"" . $value . "\""); 
    } 

    // implement ArrayAccess 

    function offsetExists($offset) { 
     return isset($this->data[$offset])); 
    } 

    function offsetSet($offset, $value) { 
     $this->data[$offset] = $value; 
    } 

    function offsetUnset($offset) { 
     unset($this->data[$offset]); 
    } 

    function offsetGet($offset) { 
     throw new InputFilterException ("Don't use this object as an array, but were an array : ". $offset); 
    } 

    protected function getValue($offset) { 

     if(is_array($this->data[$offset])) { 
      throw new InputFilterException ("must use the asArray() function"); 
     } 
     return $this->data[$offset]; 
    } 

    function data_count() { 
     return count($this->data); 
    } 

    public function set_value($offset, $data) { 
     $this->offsetSet($offset, $data); 
    } 

    // get an array *in* the data 
    public function asArray($offset) { 

     if(!is_array ($this->data[$offset])) { 
      throw new InputFilterException("only use asArray() for arrays"); 
     } 
     return new Filter($this->data[$offset]); 
    } 

    // validators... 

    function is_set($offset) { 
     return $this->offsetExists($offset); 
    } 

    function is_empty($offset) { 
     return $this->is_set($offset) && strlen($this->data[$offset]) == 0; 
    } 

    function is_numeric($offset) { 
     return $this->is_set($offset) && is_numeric($this->data[$offset]); 
    } 

    function is_integer($offset) { 

     if(!$this->is_set($offset)) { 
      return false; 
     } elseif(is_numeric($this->data[$offset])) { 
      $int_value = intval($this->data[$offset]); 
      return $int_value == $this->data[$offset]; 
     } elseif(strlen($this->data[$offset]) == 0) { 
      return true; 
     } 
     return false; 
    } 

    function is_array($offset) { 
     return $this->is_set($offset) && is_array($this->data[$offset]); 
    } 

    // return data formatted 

    function value_string($offset) { 
     return $this->getValue($offset); 
    } 

    function value_string_html($offset) { 
     return htmlentities($this->getValue($offset), null, 'UTF-8'); 
    } 

    function value_integer($offset) { 
     return intval(trim($this->getValue ($offset))); 
    } 

    function value_numeric($offset) { 
     return doubleval($this->getValue ($offset)); 
    } 

    function value_alphanumeric($offset) { 
     return preg_replace("*[^A-Za-z0-9]*", "", $this->getValue ($offset)); 
    } 

    function value_unfiltered($offset) { 
     return $this->getValue($offset); 
    } 

} 

?> 
0

me gusta que el enfoque de variables enteras siguiente:

private function _extract_int_val($val) { 
    if (isset($val)) { 
     $number = esc_sql($val); 
     if (is_numeric($number) && $number >= 0) { 
      return (int) $number; 
     } 
    } 
} 
Cuestiones relacionadas