我是PHP的新手,已经有过Perl / C / Scheme的一些经验,我觉得我很困扰我 不知道如何在块内定义变量,例如if / for / while,并使其在块外不可见。
我是否必须将代码放入一个函数中以使其成为本地代码?
例如,我的很多错误都是由这样的代码引起的:
<?php
for($id = 0; $id<10; $id++)
{
$a = $id;
}
if(1)
{
$b = 3;
}
echo $a;//9
echo $id;//10;
echo $b;//3
?>
但是,我知道,这样的代码是安全的:
#!/usr/bin/perl
use 5.014;
use strict;
use warnings;
for(my $id = 0; $id < 10; $id++)
{
my $a = $id;
}
if(1)
{
my $b = 3;
}
#say $a; #error
#say $b; #error
#say $id; #error
并且在C中,这样的代码将导致错误(使用-std = gnu99编译)
#include<stdio.h>
int main()
{
for(int i=0; i<10; i++)
{
int a = i;
}
if(1)
{
int b = 3;
}
//printf("%d\n",i);//err
//printf("%d\n",a);//err
//printf("%d\n",b);//err
return 0;
}
那么,我怎么能避免错误,因为PHP缺少块范围?
答案 0 :(得分:2)
有几种可能的方法,但它们几乎可以归结为:将代码分解为函数。这一切都回归到了这一切。无论PHP缺少块范围,您都应该为可维护和可重用的代码执行此操作。
global
。在映射操作,迭代器和回调方面考虑更多,例如:
// Look ma, no $i or other superfluous iterator variables!
$foo = array_map(function ($bar) { return /* something */; }, $baz);
$foo = array_reduce($bar, function ($foo, $baz) { return /* something */; });
$files = new RecursiveIteratorIterator(
new RecursiveCallbackFilterIterator(
new RecursiveDirectoryIterator(__DIR__),
function ($file) { return /* something */; }
)
);
foreach ($files as $file) {
/* A lot of code that would have gone here is in the
RecursiveCallbackFilterIterator callback now. */
}
通常,您现在看到的最安全的PHP代码会广泛使用依赖注入OOP,并且包含许多具有许多小方法的小类。这最大化了代码的可重用性,灵活性并减少了问题。
作为一种丑陋的黑客攻击,你可以通过模仿IIFE的常见Javascript实践来人为地引入范围:
$foo = call_user_func(function () {
/* your variables here */
return $result;
});
这可能适用于一次性脚本,这些脚本基本上只是很长且是程序性的,但您仍希望按范围进行隔离。我不会一般地推荐这种做法。
答案 1 :(得分:0)
在每个块的末尾使用unset($var);
。
答案 2 :(得分:0)
这在PHP中很烦人,而且我个人遇到了很多与此问题有关的错误。
你可以做的一种方法是在块的末尾unset()变量。所以在您的代码中执行类似
的操作<?php
for($id = 0; $id<10; $id++)
{
$a = $id;
}
if(1)
{
$b = 3;
unset($b);
}
echo $a;//9
echo $id;//10;
echo $b;//unset notice
?>
或在使用之前将null赋值给变量。