如何";适当地;在PHP中处理$\u获取变量?
目前,我有以下代码:如何";适当地;在PHP中处理$\u获取变量?,php,validation,variables,get,Php,Validation,Variables,Get,目前,我有以下代码: 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(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') {
}
}
}
}
但我认为if语句中的if语句太“复杂”了,等等
你会以不同的方式处理吗?你如何使它更简单
[编辑]接受答案:
嗯,我学到了一些我不知道的小细节和新的PHP函数。我认为没有一个完全正确的方法来完成我的要求。很明显,我以错误的方式使用了一些PHP函数,我会解决这个问题
在我看来,像这样的输入应该通过PHP过滤函数进行验证/净化,因此我将Arkh的回答标记为已接受
但是,对于一个特定的大学项目(PHP代码与此完全无关),我将使用他的答案与Tatu的帮助函数思想的混合。但是对于一个不同的项目,我将混合使用他的答案和Ignacio的类想法,因为它看起来更好、更有条理。我将编写一个函数,该函数将采用索引的名称,并在
$\u GET
中返回值或抛出异常
或将其封装在类似于以下内容的类中:
#$_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";
您可以创建一个助手函数:
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') {
}
}
这将使您的代码更简洁,但您的代码本身是正确的。这没有什么问题。嵌套的if语句是绝对正确的。 不过你可以用
empty
已检查变量是否已设置
是数值的
有点冗长,因为您也在检查0
$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;
}
}
如果以后需要在变量中存储
$\u GET['op']
,您可以在开关块之前执行此操作,但除非需要,否则我不会执行此操作。您可以定义一个筛选函数(已存在于PHP>=5.2中),该函数将根据变量的类型、是否是数字、字符串、,或更多,取决于您的要求
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;
}
}
然后使用此函数过滤使用$\u get获得的值
$foo = myfilter($_GET['foo'], 'numeric');
$bar = myfilter($_GET['bar'], 'alphanumeric');
我会使用过滤器\消毒\编号\浮动过滤器作为mid。类似于:
$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;
}
}
我会像下面这样做。或多或少。但是你也可以用过滤器来处理这些事情。您还可以关闭警告,只需使用empty(),而不用担心第一个块中的isset
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;
}
}
}
看起来有点复杂。但是,您似乎需要测试大量的边缘条件。然而,有一些方法可以统一这个过程。我使用的是一个:
if ($_GET->int["mid"]) {
if ($_GET->in_array("op", "info,cast")) {
但是可以定义一个自定义方法,该方法将所有isset和数字或任何检查组合在一起 我喜欢创建一个实现ArrayAccess的InputFilter类。这是更面向对象和更可定制的,因为您可以随心所欲地添加自定义方法,并使用相同的主筛选对象
$get = new InputFilter($_GET);
echo $get->value_integer('variable_name');
还有一点很好,就是它可以被$\u POST等重用。您只需要做一些类似于$POST=new InputFilter($\u POST)代码>。而且,您还可以将其用于其他输入源
或者,如果您有足够新的php版本,您也可以稍后实现filter_input(),正如@Arkh所建议的那样。在我看来,拥有自己的类感觉更加可重用和持久
<?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 );
}
}
?>
我喜欢整数变量的以下方法:
private function _extract_int_val($val) {
if ( isset($val) ) {
$number = esc_sql($val);
if ( is_numeric($number) && $number >= 0) {
return (int) $number;
}
}
}
首先,使您的代码合理if(is numeric($mid)&&$mid>0){
if(is numeric($mid))
,if(isset($\u GET['mid'])&!empty($\u GET['mid'])
if(!empty($\u GET['mid'])等等。看我不知道是数值()
为0
返回false。另一个我也不知道。它不知道。在0
上返回TRUE
。但是,你可以将isset()
折叠成!empty()
。@马克·特拉普:告诉40%的回答者。是数字,但你已经用empty()检查了0,因此,不需要额外的$mid>0是的,问题更多的是关于“代码复杂度”的外观。我通常倾向于有80个字符长的行,并且有很多嵌套的if语句,“真正的代码”会有很少的喘息空间。好吧,对于初学者来说,empty已经检查了一个变量是否已设置。你能给出一个关于该类方法的示例吗?相当不错,尽管使用static并不是那么“好”或可重复使用_POST@zanlok:将数组传递给构造函数是留给读者的一个练习。您的答案没有相同的方法;根本不同。过于保守?我想知道如果您这样做会发生什么;echo GET::int('hour'))
当您的url类似时;?hour=0
检查变量是否设置了
和/或为空
是多余的。为空
已检查它是否已设置。这有一个问题:if$\u GET['op']
包含字符串info
,您的开关块在任何情况下都会运行所有代码。您应该添加中断。@Mark ehh…没有想到。实际上它存在于PHP>=5.2中,它会重载$\u GET
超全局?不好!@Stephen:是的。语义很接近。但如果您喜欢复杂性,还可以定义wrapper对象:$getVars=新输入($\u-GET)
yikes。我不知道为什么会被否决。我可能不同意建议的实现,但它仍然是一个有效的策略。+1表示平衡。@Stephen:我可能也否决了它,因为它对于OP想要的东西来说有点太过苛刻了。但是它是一个选项,而且确实简化了事情——一旦你成为朋友或扩展了API.Ch检查变量isset
和/或notempty
是否冗余。empty
已经检查了它是否已设置。@Stephen:不是根据文档。这意味着它会抛出警告。可能吧