PHP:像函数一样对待变量?

时间:2011-03-13 02:49:16

标签: php variables

我想使用像$ GET [name]这样的变量,它始终输出一个MySQL安全版本的$ _GET [name],即使$ GET [name]的值在脚本中某处发生了变化。

所以:

$_GET[name] = "Timmy O'Toole";
echo $GET[name]; // Timmy O\'Toole
$_GET[name] = "Tommy O'Toole"; 
echo $GET[name]; // Tommy O\'Toole

这可行吗?如果没有,你能想到任何其他可能不起作用的方式吗? (我希望能够在字符串中使用变量并让它们自动进行评估,而不必进行大量的连接。)

更新

我使用了马里奥解决方案的一个版本,它似乎有效:

// Assume $_REQUEST['name'] = "Timmy O'Toole";

class request_safe_vars IMPLEMENTS ArrayAccess {
    var $array = array();
    function offsetGet($varname) {
        return mysql_real_escape_string($_REQUEST[$varname]);        
    }
    function offsetSet($name, $value) { }  
    function offsetUnset($name) { }
    function offsetExists($name) { }
}  

$REQUEST = new request_safe_vars();

$_REQUEST['name'] = $_REQUEST['name'].' MODIFIED';

$query = "SELECT id FROM user WHERE name = '{$REQUEST['name']}'";  

// Query output:
// SELECT id FROM user WHERE name = 'Timmy O\'Toole MODIFIED'

3 个答案:

答案 0 :(得分:3)

你不想这样做。

相反,你要做的事情 - 确保数据库只获得正确的值 - 是正确的,但你采用的方式是一种糟糕的方法。

通过选择具有此功能的数据库适配器(<{3}}这样的数据库适配器,您应该在使用时转义所有输入,而不是在使用它时 。 。 PDO使用预准备语句和PDO is a great example 自动转义和引用输入。以下是parameter binding

的示例
$statement = $pdo->prepare('SELECT id FROM users WHERE name = ?');
$statement->execute(array( $_GET['name'] ));
if($statement->rowCount() > 0) {
    echo "I found you!";
} else {
    echo "You don't exist. :(";
}

带有占位符和绑定的预处理语句是确保SQL免受攻击的最明智和最安全的方法。

答案 1 :(得分:1)

这对于实现ArrayAccess的对象是可行的。通过将$ GET转换为对象,您可以使用魔术offsetSetoffsetGet方法来实现此目的。

class safe_vars IMPLEMENTS ArrayAccess {
    var $array = array();

    function offsetGet($varname) {
        return mysql_real_escape_string($this->array[$varname]);
    }

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

    function offsetUnset($name) {  }
    function offsetExists($name) {  }
}  

这就是你如何使用它:

$GET = new safe_vars();
$GET["name"] = "Timmy O'Toole";
echo $GET["name"]; // Timmy O\'Toole    

我实际上有一些类似的东西(但从未实现set部分),它专门适用于$_GET(如您的问题中所列)。 http://sourceforge.net/p/php7framework/svn/60/tree/trunk/php7/input.php?force=True - 例如,可以将其配置为默认应用sql过滤器。虽然这种方法有点像magic_quotes,即使它使用了正确的转义函数。

答案 2 :(得分:0)

首先,在'name'周围加上引号,除非你故意将它定义为常量。

另一个建议是使用DB包装器类,如PDO,mysqli或您自己的,并使用预准备语句并为您转义输入。这有利于在最后可能的时间转义数据,这是最佳的。或者你可以创建一个非常简单的包装函数,例如

function get($key) {
   return isset($_GET[$key]) : mysql_real_escape_string($_GET[$key]) : null;
}

定义一个类(除非你只是静态使用它)的问题是它剥离了它的超全局状态$_GET并且你被迫使用全局(邪恶)或将所有get参数传递给本地闭包。