我很清楚全局变量是邪恶的,这是我稍后会讨论的问题。这不是我的代码库,但我已经分配了一些清理任务。
尝试改进代码库,我决定使用一个名为AltoRouter的软件包来实现简单的路由 - 我以前使用它并且它已经很好地用于我的目的。
现在,代码库使用了在全局范围内声明的大量变量。通常,然后使用global
关键字提取这些变量。但由于某些原因,当我在闭包内工作时,这不起作用。
考虑这个简单的路由示例:
<?php
require 'vendor/autoload.php';
$router = new AltoRouter();
$router->map('GET', '/shops/[i:id]', function($id) {
$_GET['shop_id'] = $id;
require 'go_to_shop.php';
});
$match = $router->match();
if( $match && is_callable( $match['target'] ) ) {
call_user_func_array( $match['target'], $match['params'] );
}
这会调用我的闭包设置变量并需要一个文件。
这会产生错误:
致命错误:在null中调用成员函数get() 第71行/vagrant/Core/CampaignHandler.php
现在,执行此操作的代码如下(第70-71行):
// Inside a method
global $serviceContainer;
$dispatcher = $serviceContainer->get("dispatcher");
通过提前包含文件来声明$serviceContainer
:
$serviceContainer = new ServiceContainer();
$serviceContainer->set("dispatcher", new EventDispatcher());
基本上,如果我将闭包的内容移到闭包之外,一切都运行得很好 - 但是一旦我从闭包内部做到这一点,通过全局作用域访问的所有变量都是空的 - 我没有关于原因的想法。
我尝试在关闭时使用use
,这也不起作用。
我主要是寻求解释而不是解决方案。
答案 0 :(得分:1)
全球有罪是有原因的。您会收到错误,因为在调用函数时未初始化全局。 global
和require
的混乱是确切的问题,您已经在尝试处理它。
在封闭本身中使用全局变量没有问题。这个例子完全正常:
global.php:
<?php
class Foo {
public function bar() { return 'bar';}
}
$foo = new Foo;
test.php的:
<?php
require 'global.php';
$test = function($param) {
global $foo;
echo $param, $foo->bar();
}
call_user_func_array($test, ['baz']);
所以php test.php
输出bazbar
;
答案 1 :(得分:0)
我非常确定$serviceContainer
变量在全局范围内不存在,但问题就是将该部分排除在外。
您是否无法使用use( $serviceContainer )
语句将容器传递给匿名函数?这是一个更清晰的解决方案,然后不得不依赖全局。
function($id) use( $serviceContainer ) {
$_GET['shop_id'] = $id;
require 'go_to_shop.php';
}
偏离主题:不确定您之后使用该ID变量做什么以及为什么要将其重新放回到$ _GET变量中,但请注意。
答案 2 :(得分:-1)
请查看手册中的匿名函数 - 也称为闭包,实际上是对象。
http://php.net/manual/en/functions.anonymous.php
Theses callables具有扩展其范围的特定功能。
请参阅:示例#3从父作用域继承变量。
$message = 'hello';
// No "use"
$example = function () {
var_dump($message);
};
$example();
// Inherit $message
$example = function () use ($message) {
var_dump($message);
};
$example();
确定要为$ _GET全局变量分配值?
$_GET['shop_id'] = $id;
您可以从altorouter参数中提取路线中的商店ID。 (见文件。)
$router->map( 'GET', '/', function() { .. }, 'home' );
// assuming current request url = '/'
$match = $router->match();
/*
array(3) {
["target"] => object(Closure)#2 (0) { }
["params"] => array(0) { }
["name"] => 'home'
}
*/
或者,如果您想为会话存储ID,请使用$ _COOKIES或$ _SESSION全局变量。