【问题标题】:PHP Variables made with foreach使用 foreach 制作的 PHP 变量
【发布时间】:2011-05-16 21:08:04
【问题描述】:

我有几个变量来自 $POST_['array'] 中的一个数组.

例如,如果我有

$POST_['name'];
$POST_['last'];
$POST_['age'];
$POST_['sex'];

我希望循环从 $_POST 中的数组创建每个变量,变量名称如下:

$name = 'John';
$last = 'Doe';
$age = '32';
$sex = 'male';

注意 - 该数组来自一个序列化的 jquery 字符串,该字符串将表单中的所有变量和值组合成一个大字符串。

这可能吗?

【问题讨论】:

  • 如果您使用extract,请注意 PHP 手册中详述的潜在安全后果。

标签: php post


【解决方案1】:

你不需要循环,你想要extract

extract($_POST); // But use caution, see below


注意事项和最佳做法

如 cmets 中所述,这会强制 $_POST 数组中的所有参数进入当前符号空间。

在全局空间中

<?php
extract($_GET);
var_dump($_SERVER); // Can be overwritten by the GET param
?>

上面的代码说明了as shown in this answer 的问题——一些非常危险的东西可以在 global 空间中被覆盖。

函数内部

function myFunc() {
    // (Mostly) empty symbol space! (excluding super globals)
    extract($_POST);
}

在函数内部,作为第一行,没有坏处。

重要提示:您可能认为因为$_SERVERsuper global,这个漏洞也可能发生在函数内部 .然而,在我的测试中,在 PHP 版本 5.3.4 上,它是在函数内安全——$_SERVER$_POST$_GET$_SESSION 都不是,或者可能是其他超全局变量,可能会被覆盖。

有选项

您也可以使用extract with extract_type options that do not overwrite

在我看来,最好的选择是简单地为提取中的所有变量添加前缀:

// $_GET = test=1&name=Joe

extract($_GET, EXTR_PREFIX_ALL, "request_get");

echo $request_get_test; // 1
echo $request_get_name; // Joe

这样你就没有覆盖问题,但你也知道你从数组中得到了所有东西。

备用 - 带条件的循环

如果您想手动(但仍然是动态地)执行此操作,只想有条件地提取少数变量,您可以使用variable variables

foreach ($_POST as $key => $value) {
    if (isset($$key)) continue;

    $$key = $value;
}

(我使用的示例条件是防止覆盖。)

【讨论】:

  • @jakenoble 关注手册并使用默认行为以外的选项来防止覆盖变量就可以了。
  • @jakenoble - 解释原因会很有帮助,而不是 -1 和对每个帖子的评论。单独来看,比如我知道$_POST的内容是什么,有什么区别?
  • 我已经添加了自己的答案,尽管该答案已被否决而没有 cmets。我赢不了。您可能会覆盖您想要的变量,这将导致不可预测的行为。没有人可以利用它,但它只是一个示例,如果一开始没有正确解释,它可以被 PHP 的新用户使用然后误用。这就是 PHP 之所以名声不好的原因,是因为 extract() 之类的东西以及它们的滥用。
  • @KingCrunch @Reensis 所有这些都很好,但请确保将其写在答案中,您不能假设 OP 或其他人会在字里行间阅读,甚至阅读手册并使用该功能因为它应该被使用。快速修复很好,但请确保将其解释为快速修复。
  • 帖子中有一个指向手册的链接,其中显然有防止覆盖的选项,如果方法使用得当就很好,如果您知道帖子中的内容首先,您应该有一个足够体面的命名约定,以免覆盖已经实例化的变量。我个人认为这比 foreach 更好,只是因为它更干净并迫使您拥有更好的命名标准。
【解决方案2】:

在使用$_POST时尽量不要使用extract()。您可能会覆盖您想要的变量,这将导致不可预测的行为。养成一个坏习惯,而动态可能不是最好的解决方案。

你可以这样做:

foreach($_POST as $key => $value)
{
    switch($key)
    {
        case "name":
            $name = $value;
        break;
        case "last":
            $last = $value;
        break;
    }
}

【讨论】:

  • 这是很好的建议。其他帖子介绍了可能存在错误且肯定不安全的代码。
  • @jake 我刚刚意识到我做了 -1 这个虽然你必须相信我这不是报复性的投票,因为我什至没有注意到是谁发布的。很抱歉没有发表评论。原因是因为这不是动态的,非常冗长,并且使用新的/更改的名称更新代码变得更加困难。也许他们不需要那个。但如果他们想要动态提取,还有其他方法可以避免覆盖。如果您编辑您的答案(我的投票现在被锁定)并对此进行一些扩展,我肯定会删除我的反对票,没有难过的感觉。
  • @jakenoble - 完成,我还根据这个讨论扩展了我的答案。感谢您的意见。
  • 我做了一个测试。它不起作用.. 发布了 10 个表单值,但此代码仅返回最后一个表单值。
【解决方案3】:

为什么不使用foreach

foreach($_POST as $key=>$val){
    ${$key} = $val;
}

【讨论】:

  • 我打算使用 foreach 但提取命令很棒。它确实完成了手头的工作。
  • 我做了一个测试。它不起作用.. 发布了 10 个表单值,但此代码仅返回最后一个表单值。
【解决方案4】:

您实际上可以使用名为extract的内置函数

【讨论】:

  • 真的吗?怎么会有人利用它?也许发送一个名为“loggedIn”=>“true”或类似的帖子?
  • 不占便宜,但进入会是个坏习惯
  • @Peter:他们可以做_POST=haha I nuked your _POST array!,其余的超全局变量也是如此。
【解决方案5】:

我只想提一下,您可以改进 foreach 技术,因为我们在 HTML 中能够使用方括号表示法来命名我们的表单字段,如果我们这样做,HTML 会做的是提交一系列值作为数组。

<input name="user[name]">
<input name="user[last]">
<input name="user[age]">
<input name="user[sex]">

仅使用一行代码将输入字段中的所有值分配到本地数组 $args 中。

$args = $_POST['user'];

这意味着当我们去处理表单时,我们正在查看一个值数组,而不是我们必须检索的一堆单个值。

所以我们可以简单地转到超级全球帖子并要求一项:即用户。我们得到的是一个关联数组。因此,我们不必一次又一次地检索所有这些值来构建该数组,而是立即获得一个数组,这仅仅是因为我们以不同的方式命名了表单字段。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-12
    • 1970-01-01
    • 2023-04-06
    • 2014-05-27
    相关资源
    最近更新 更多