【问题标题】:How to access variables created dynamically inside functions and methods in PHP?如何访问在 PHP 中的函数和方法中动态创建的变量?
【发布时间】:2019-07-22 14:58:55
【问题描述】:

我无法访问在 PHP 中我的对象的函数或方法中动态创建的变量。这可能是范围问题,但我不知道为什么会像在 JavaScript 中那样,当您在函数内部声明 var 时,您仍然可以在该函数外部访问它。

我正在做的是这样的:

#code
...

$inputs = ['olympiad', 'test_type', 'year', 'level', 'country', 'test', 'answersheet'];

$Form = new Form;
$Form->addFields($inputs);

foreach (array_keys($Form->fields) as $key) {
  ${"$key"} = $Form->fields["$key"];
}

$olympiad->required(true)->type('select')->inValues($olyimpiadsArray)->label('Olmpíada')->errorMessage('some error message here');
$test_type->required(true)->type('select')->inValues($testTypeArray)->errorMessage('bla bla');
$level->required(true)->type('select')->inValues(['Nacional', 'Regional'])->label('Nível')->errorMessage('sample error message');
$year->required(true)->type('int')->range(1998, 2019)->label('Ano')->errorMessage('another error message');
$country->required(true)->type('string')->range(4, 64)->label('País')->errorMessage('these arent the real error messages');
$test->type('file')->label('Prova')->allowedExtensions(['pdf'])->errorMessage('bla bla');
$answersheet->type('file')->label('Gabarito')->allowedExtensions(['pdf'])->errorMessage('bla bla bla');

之所以可行,是因为字段是对象,它们作为引用传递,因此我可以通过 foreach 中创建的变量访问这些对象,并且表单也能够验证字段对象。

我在许多网页中都使用相同的foreach,所以这很尴尬,因为我一次又一次地复制和粘贴代码。

预期结果

我想要什么?我想这样做:

Class Form {
  #code
  ...
  public function create_vars_for_fields() {
    foreach(array_keys($this->fields) as $key) {
      ${"$key"} = $this->fields["$key"];
    }
    return $this;
  }
}

然后,在我的 PHP 网页上,我应该能够做到这一点:

require_once 'Form.php';

$inputs = ['olympiad', 'test_type', 'year', 'level', 'country', 'test', 'answersheet'];

$Form = new Form;
$Form->addFields($inputs)->create_vars_for_fields();

#code
...
//here I should be able to access my variables, which are now objects of the class Fields
echo $test_type->value; //should echo the test type of the olympiad, which is equal to $_POST['test_type']
echo $country->value; //should echo the country of the olympad, which is equal to $_POST['country']

但是,上面的代码会抛出许多错误,说明这些变量是未定义的。

Notice: Undefined variable: olympiad in C:\xampp\htdocs\projects\phpFormBuilder\tests\TestValidation.php on line 8

Fatal error: Uncaught Error: Call to a member function required() on null in C:\xampp\htdocs\projects\phpFormBuilder\tests\TestValidation.php:8 Stack trace: #0 C:\xampp\htdocs\projects\phpFormBuilder\tests\AddTest.php(3): require_once() #1 {main} thrown in C:\xampp\htdocs\projects\phpFormBuilder\tests\TestValidation.php on line 8

第8行是我说的$olympiad->required(true)

如何通过在函数或方法中动态创建这些变量来访问它们?

【问题讨论】:

  • var 相当于global,但在 PHP 或任何语言中使用全局变量会导致最终的灾难
  • foreach($_POST as $key => $value) { ${"$key"} = $value; } 另一场灾难即将发生(安全方面),使用extract() 可以更简单地完成但这也不是一个建议
  • 如果您的 $_POST 变量有一个对象,则创建同名的属性,然后使用 $Form->Name 例如
  • RiggsFolly,你说''如果你的 $_POST 变量有一个对象,那么创建同名的属性,然后使用 $Form->Name 例如''。虽然表单上没有明确显示,但实际上我现在正在使用我的表单类。
  • 因为您将 $_POST 中的每一次出现并在主范围内创建一个变量。这就是以前版本的 PHP 自动执行的操作,然后因为不安全而停止执行此操作。请记住,我可以发布这个脚本任何我想发明的 $_POST 值,可能会用我的新数据覆盖你的一个值:) 就像 is_logged_in 一样

标签: php forms function scope


【解决方案1】:

我终于找到了一个聪明、清晰的方法来完成这个!该方案使用extract内置函数。

虽然我不再需要它,因为我正在使用 Laravel 进行验证,但我仍然想分享答案,以便它可以帮助其他人。

解决方案

Class Form {
  #code
  ...
  public function getFieldsCompacted() {
    $compactedFields = [];
    foreach(array_keys($this->fields) as $key) {
      $compactedFiels["$key"] = $this->fields["$key"];
    }
    return $compactedFields;
  }
}

然后,上代码:

require_once '/path/to/Form.php';

$inputs = ['olympiad', 'test_type', 'year', 'level', 'test', 'answer_sheet'];
$Form = new Form;
$Form->addFields($inputs);
extract($Form->getFieldsCompacted());

这样我可以做到:

$olympiad->required(true)->type('select')->inValues($olyimpiadsArray)->label('Olimpíada')->errorMessage('some error message here');
$test_type->required(true)->type('select')->inValues($testTypeArray)->errorMessage('bla bla');
$level->required(true)->type('select')->inValues(['Nacional', 'Regional'])->label('Nível')->errorMessage('sample error message');
$year->required(true)->type('int')->range(1998, 2019)->label('Ano')->errorMessage('another error message');
$test->type('file')->label('Prova')->allowedExtensions(['pdf'])->errorMessage('bla bla');
$answersheet->type('file')->label('Gabarito')->allowedExtensions(['pdf'])->errorMessage('bla bla bla');

而不是做:

$Form->fields['olympiad']->required(true)->type('select')->inValues($olyimpiadsArray)->label('Olimpíada')->errorMessage('some error message here');
$Form->fields['test_type']->required(true)->type('select')->inValues($testTypeArray)->errorMessage('bla bla');
$Form->fields['level']->required(true)->type('select')->inValues(['National', 'State'])->label('Nível')->errorMessage('sample error message');
$Form->fields['year']->required(true)->type('int')->range(1998, 2019)->label('Ano')->errorMessage('another error message');
$Form->fields['test']->type('file')->label('Prova')->allowedExtensions(['pdf'])->errorMessage('bla bla');
$Form->fields['answersheet']->type('file')->label('Gabarito')->allowedExtensions(['pdf'])->errorMessage('bla bla bla');

编辑:

RiggsFolly 指出使用extract 的不安全性。我完全同意在$_POST$_GET 中使用extract。但是,这里不是这种情况,因为要提取的变量是在 $inputs = ['olympiad', 'test_type', 'year', 'level', 'test', 'answer_sheet']; 中定义的。因此,extract 只会提取这些变量,不会覆盖其他变量。因此,上面的代码没有风险。

【讨论】:

  • Extract 也是那些“不要使用”的功能之一
  • 您能解释一下为什么Extract 是“不使用”功能之一吗?
猜你喜欢
  • 1970-01-01
  • 2018-02-28
  • 1970-01-01
  • 2021-08-13
  • 1970-01-01
  • 2017-02-28
  • 2016-05-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多