是否可以在PHP脚本中定义私有变量,以便这些变量仅在这个单独的PHP脚本中可见而在其他地方不可见?我想要一个包含文件,它可以在不污染全局命名空间的情况下执行某些操作。它必须与PHP 5.2一起使用,因此PHP命名空间不是一个选项。这里没有使用OOP所以我不是在寻找私人班级成员。我正在搜索“有点全局”的变量,这些变量在当前脚本中是全局的,但在其他任何地方都没有。
在C中,我可以使用 static 关键字进行操作,但在PHP中是否有类似内容?
以下是“common.php”脚本的简短示例:
$dir = dirname(__FILE__);
set_include_path($dir . PATH_SEPARATOR . get_include_path());
// Do more stuff with the $dir variable
当我在某个脚本中包含此文件时,$ dir变量在所有其他脚本中也是可见的,我不希望这样。那我怎么能阻止这个呢?
答案 0 :(得分:7)
您可以采取一些措施使$dir
远离后续文件
set_include_path(dirname(__FILE__) . PATH_SEPARATOR . get_include_path());
这是最明显的。
$dir = dirname(__FILE__);
set_include_path($dir . PATH_SEPARATOR . get_include_path());
// work with $dir
unset($dir);
在定义变量并使用它之后,取消设置变量。请注意,这将取消设置在包含此脚本之前使用的任何名为$dir
的变量。
define('DIR_THIS', dirname(__FILE__));
set_include_path(DIR_THIS . PATH_SEPARATOR . get_include_path());
我不太可能重新定义这样的全局常量。
function my_set_include_path {
$dir = dirname(__FILE__);
set_include_path($dir . PATH_SEPARATOR . get_include_path());
// Do more stuff with the $dir variable
$my_other_var = 'is trapped within this function';
}
my_set_include_path();
您可以在该函数中定义任意数量的变量,而不会影响全局命名空间。
第一种方法是解决此问题的最简单方法,但是因为您想再次使用$dir
,它可能并不理想。最后一个示例至少将$dir
(以及该函数中定义的任何其他函数)保留在全局名称空间之外。
答案 1 :(得分:6)
你要完成任何接近你想要的任何事情的唯一方法是将一个包含文件中的所有内容包装在一个函数中,然后调用它。如果文件需要自己执行,你仍然可以
<?php
run_myfile()
function run_myfile() {
...
}
?>
没有通用的方法可以将变量限定为仅限于名称空间,类或函数之外的文件。
答案 2 :(得分:1)
好吧,我可能会因此而受到诽谤,但如果你完全绝望,你可以使用Registry。我已经掀起了一个没有课程的小课程(因为我假设来自而且这里没有使用OOP所以我不是在寻找私人班级成员。意味着你不想这样做总共有OOP)
function ®istry_get_instance()
{
static $data = array();
return $data;
}
里面的static $data
变量保存在函数范围内,因此您可以在任何位置调用函数并始终获取相同的内容。关键点是returning by reference,例如
$registry = ®istry_get_instance(); // get $data array by reference
$registry['foo'] = 'bar'; // set something to $data
unset($registry); // delete global reference to $data
print_r(®istry_get_instance()); // show $data
显然,当从全局范围调用此方法时,您仍然将$ registry作为全局范围内的变量。因此,您可以添加更多功能,以使注册表更方便使用,例如用于将数据设置到注册表:
function registry_set($key, $value)
{
$registry = ®istry_get_instance();
$registry[$key] = $value;
}
再次将它拿出来:
function registry_get($key)
{
$registry = ®istry_get_instance();
if(array_key_exists($key, $registry)) {
return $registry[$key];
} else {
trigger_error(sprintf(
'Undefined Index: %s', htmlentities($key)
), E_USER_NOTICE);
}
}
并检查是否存在密钥:
function registry_isset($key)
{
$registry = ®istry_get_instance();
return array_key_exists($key, $registry);
}
然后你可以使用:
registry_set('foo', 'bar'); // setting something to the registry
var_dump( registry_isset('foo') ); // check foo is in the registry now
echo registry_get('foo'); // prints 'bar'
echo registry_get('punt'); // raises Notice
您可以使用其他方法从包含文件填充注册表:
function registry_load_file($file)
{
if(!is_readable(realpath($file))) {
return trigger_error(sprintf(
'File is not readable: %s', htmlentities($file)
), E_USER_WARNING);
}
$config = include $file;
if(!is_array($config)) {
return trigger_error(sprintf(
'Expected file %s to return an array', htmlentities($file))
, E_USER_WARNING);
}
$registry = ®istry_get_instance();
$registry += $config;
}
包含文件必须返回一个数组:
// config.php
return array(
'setting1' => 'something'
);
然后你可以做
registry_load_from_file('config.php'); // add the contents of config to registry
print_r(registry_get_instance()); // show content of registry
当然,现在这只是因为没有全局变量而在全局范围内有六个函数。不知道它是否值得,特别是因为我在函数中考虑static
以及所有引用可疑实践的东西。
将其作为概念证明:)
答案 3 :(得分:0)
为什么不将所有内容都放在静态类中?那么你只有一个可能与全局命名空间冲突的“变量”。
class MyClass {
public static $myvar = 1;
public static $myvar2 = "xyz";
public static function myfunction() {
self::$myvar++;
self::$myvar2 = "abc";
}
}
// References to class items, if needed
MyClass::myfunction();
MyClass::$myvar += 3;
答案 4 :(得分:-1)
如果您尝试的问题只是:
$dir = dirname(__FILE__);
set_include_path($dir . PATH_SEPARATOR . get_include_path());
// Do more stuff with the $dir variable
然后解决方案是改变相对于'。'的包含路径。在你的ini设置中。例如。改变:
include_path=includes:/usr/local/php
到
include_path=./includes:/usr/local/php
请注意,脚本不会进入范围,除非您明确包含/要求它(_once检查全局适用)但是我强烈反对在函数中调用include / require - 在脚本顶部包含/需要它更加透明。
我认为您尝试解决的问题是基于错误的前提,您应该寻找另一种解决方法。如果你希望包含文件中的代码的行为有所不同,具体取决于包含它的内容,那么你真的应该把它分成两个单独的文件 - 或者对于不同的行为可能甚至是3 - 2,而对于普通文件则是1。
下进行。