PHP 闭包获取外部变量和global关键字声明变量的区别讲解

最近在学习workerman的时候比较频繁的接触到回调函数,使用中经常会因为worker的使用方式不同,会用这两种不同的方式去调用外部的worker变量,这里就整理一下PHP闭包获取外部变量和global关键字声明变量的区别。

闭包

闭包是一个常见的概念,我们通常可以将其与回调函数配合使用,可以使代码更加简洁易读。

闭包可以 通过拷贝的方式 让函数使用父作用域中的变量。如:

$global = 'hello';
$bbb = function()use($global){
  echo $global."\n";
};
$bbb();
//输出 'hello'

global关键字声明变量

通过global声明变量同样可以使函数体调用到函数外部的变量,不过global与use不同,globle关键字会使创建 一个与外部变量同名的引用 ,并且在函数内对变量作出修改同样会作用域外部变量。

$global = 'hello';
$fun = function(){
  global $global;
  $global =' world';
  echo $global."\n";
};
$fun();
// 输出 'world'

这里只是创建一个同名引用而已,并不会改变原本外部变量$global的作用域,也就是说在另外一个函数中调用该依旧需要声明或者使用闭包

$global = 'hello';
$fun = function(){
  global $global;
  $global =' world';
  echo 'a:'.$global."\n";
};
$ccc = function(){
  echo 'b:'.$global;
};
$fun()
$ccc()
/*

输出

a: world
Notice: Undefined variable: global in xxxxxxx on line xx
*/

再稍微改一下代码,这样更容易对比闭包和global关键字声明变量这两种访问外部变量方式的区别。

<?php
$global = 'hello';
$fun = function(){
  global $global;
  $global ='world';
  echo 'a:'.$global."\n";
};
$bbb = function()use($global){
  $global = 'china';
  echo 'c:'.$global."\n";
};
$fun();
echo 'b:'.$global."\n";
$bbb();
echo 'd:'.$global;

这里b和d两个输出可以看出来,global改变了外部变量的值,而闭包方式并没有。

输出:

a: world
b: world
c:china
d: world

最后再贴一个官方文档中比较经典的使用匿名函数,闭包与回调函数配合的例子:

class Cart
{
  const PRICE_BUTTER = 1.00;
  const PRICE_MILK  = 3.00;
  const PRICE_EGGS  = 6.95;
  protected  $products = array();
  public function add($product, $quantity)
  {
    $this->products[$product] = $quantity;
  }
  public function getQuantity($product)
  {
    return isset($this->products[$product]) ? $this->products[$product] :
      FALSE;
  }
  public function getTotal($tax)
  {
    $total = 0.00;
    $callback =
      function ($quantity, $product) use ($tax, &$total)
      {
        $pricePerItem = constant(__CLASS__ . "::PRICE_" .
          strtoupper($product));
        $total += ($pricePerItem * $quantity) * ($tax + 1.0);
      };
    array_walk($this->products, $callback);
    return round($total, 2);
  }
}
$my_cart = new Cart;
$my_cart->add('butter', 1);
$my_cart->add('milk', 3);
$my_cart->add('eggs', 6);
print $my_cart->getTotal(0.05) . "\n";

总结

以上所述是小编给大家介绍的PHP 闭包获取外部变量和global关键字声明变量的区别讲解,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

时间: 2017-12-03

php多次include后导致全局变量global失效的解决方法

本文实例讲述了php多次include后导致全局变量global失效的解决方法.分享给大家供大家参考.具体分析如下: 在多个文件中,文件一个接一个include,但最后一个文件里的函数使用global后却无法引用全局变量.例如: a.php文件: <?php $aa = 1; ?> b.php文件: <?php include a.php function show(){ global $aa; var_dump($aa); } ?> 显示:null; 这种失效是由于多种原因造成的

global.php

<?php /**  * 自动判断PHP版本,并把所有环境变量转为全局变量  *  * @author   Avenger <avenger@php.net>  * @version  $Id 2003-05-18 13:01:14 $  */ function pmyoutput(&$a) {     if (is_array($a)) {         array_walk($a,'pmyoutput');     } else {         $a = stripsl

php中global和$GLOBALS[]的分析之一

这可能引起一些问题,有些人可能漫不经心的改变一个全局变量.PHP 中全局变量在函数中使用时必须申明为全局(注意,Global这个关键字在函数中定义才有用). 1:Global的作用是定义全局变量,但是这个全局变量不是应用于整个网站,而是应用于当前页面,包括include或require的所有文件. 复制代码 代码如下: <?PHP $a=123; function aa() { Global $a; //如果不把$a定义为global变量,函数体内是不能访问函数体外部的$a的,但是可以定义一个相

php中全局变量global的使用演示代码

我来给处入行的人讲解一下全局变量global的使用,"全局变量",这个名词中的全局两个字已经告诉我们这个变量在各个地方都能用,先看一个实例: 复制代码 代码如下: <?php $a = 1; $b = 2; function Sum() { global $a, $b; //在里面声明为全局变量 $b = $a + $b; } Sum(); echo $b; ?> 结果: 3 如果没有全局变量global在方法内是不能获得$a,$b值的,所以在方法里面想用外面的变量就需要先

深入理解PHP中的global

一.实现原理 在PHP的函数中,global语法是比较常见的,大家一定都知道一旦在函数中global了某个外部变量后,这个变量就可以在这个函数中使用了,但是也有不少网友不知道这是一个什么实现原理.现在上一个例子,大家一看就知道了: 复制代码 代码如下: $globalStr = '.net'; function globalTest(){ global $globalStr; $globalStr = 'jb51'.$globalStr; unset($globalStr); } globalT

PHP Global定义全局变量使用说明

很不习惯PHP中的变量作用域,PHP中函数变量和全局是完全隔绝的,也就是无法相互访问.比如下面这样: 复制代码 代码如下: $test = 123; abc(); //这里什么都不输出,因为访问不到$test变量function abc(){    echo($test);}$test = 123;abc(); //这里什么都不输出,因为访问不到$test变量function abc(){    echo($test);} 如果,你想在函数内部访问外部变量,你需要这样: 复制代码 代码如下: $

PHP中全局变量global和$GLOBALS[]的区别分析

一.举例比较 例一: 复制代码 代码如下: <?php $var1 = 1; function test(){ unset($GLOBALS['var1']); } test(); echo $var1; ?> 因为$var1被删除了,所以什么东西都没有打印. 例二: 复制代码 代码如下: <?php $var1 = 1; function test(){ global $var1; unset($var1); } test(); echo $var1; ?> 意外的打印了1.证明

分享下PHP register_globals 值为on与off的理解

register_globals的值可以设置为:On或者Off,我们举一段代码来分别描述它们的不同. 代码: 复制代码 代码如下: <form name="frmTest" id="frmTest" action="URL"><input type="text" name="user_name" id="user_name"><input type=&quo

仅在IE6/7/8下cssText返回值少了分号的测试代码

测试代码: IE6/7/8下cssText返回值少了分号 TEST var div = document.getElementsByTagName('div'); alert(div[0].style.cssText); [Ctrl+A 全选 注:如需引入外部Js需刷新才能执行] 各浏览器输出如下 IE6/7/8 : IE9/Firefox/Chrome/Safari/Opera : 可以看到IE6/7/8中少了分号.使用cssText属性时需注意.

asp.net中js+jquery添加下拉框值和后台获取示例

复制代码 代码如下: <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title></title> <script src="Scripts/jquery-1.4.1.js" type="text/javascript"></script> <script type

分享下Asp.Net面试题目及答案集合

1. 简述 private. protected. public. internal 修饰符的访问权限. 答 . private : 私有成员, 在类的内部才可以访问. protected : 保护成员,该类内部和继承类中可以访问. public : 公共成员,完全公开,没有访问限制. internal: 在同一命名空间内可以访问. 2 .列举asp.net 页面之间传递值的几种方式. 答. 1.使用querystring, 如....?id=1; response. redirect()...

分享下自己总结的Git常用命令

使用git也有一段时间了,把自己常用的命令用自己的描述记录起来,方便自己备忘也方便其他人参考. 目录: 最基本的命令: git clone 拷贝并跟踪远程的master分支.跟踪的好处是以后可以直接通过pull和push命令来提交或者获取远程最新的代码,而不需要指定远程分支名字. git submodule init git submodule update 参考示意图 HEAD 指向当前的commit 对象,同时也用来表明我们在哪个branch上工作.所以当我们使用HEAD来操作指针的时候,其

分享下网站开发人员应该知道的61件事

不出意料地,他得到了一大堆回答. 通常情况下,你需要把所有人的发言从头到尾读一遍.但是,Stack Overflow有一个很贴心的设计,它允许在问题下方开设一个wiki区,让所有人共同编辑一个最佳答案.于是,就有了下面这篇文章,一共总结出六个方面共计61条"网站开发须知". 我发现,这种概述性的问题,最适合这种集合群智.头脑风暴式的回答方式了.这也是我第一次觉得,Stack Overflow做到了Wikipedia做不到的事.(难怪它最近挤进了全美前400大网站.) 在我的印象中,关于

jquery模拟SELECT下拉框取值效果

jquery模拟SELECT框,效果图如下:   复制代码 代码如下: <!DOCTYPE html> <html lang="en"> <head> <title>jquery模拟SELECT框</title> <meta charset="utf-8"> <style> body{padding:0;margin:0;font-size:12px;} ul,li{list-sty

分享下手机软件界面设计浅析

随着科技的不断发展,手机的功能俞之强大,基于手机系统的相关软件应运而生,手机设计的人性化已不仅仅局限于手机硬件的外观,手机的软件系统已成为用户直接操作和应用的主体,它应以美观实用.操作便捷为用户所青睐.用户界面设计的规范性显得尤为重要. 一.界面效果的整体性.一致性 手机软件运行于手机操作系统的软件环境,界面的设计应该是基于这个应用平台的整体风格,这样有利于产品外观的整合. 1.界面的色彩及风格与系统界面统一 软件界面的总体色彩应该接近和类似系统界面的总体色调,例如:系统色调以蓝色为主,我们的软

分享下perl胶水实现前后台对接的方法

1. Perl"胶水",能够将各种应用程序或者各种语言的代码结合起来.Perl可以编写普通的脚本程序,还可以使用cgi模块编写Web应用程序,同时可以使用DBI访问各种数据库.除此之外,Perl可以将各种层次的应用程序粘在一起,发挥更强大的功能. 2.前台是一个网站Web应用程序,底层或者是后台是用C,C++或者Java编写,使用Perl可以将两者对接起来,实现更强大的功能,发挥各自的优势.Perl实现该方法的途径有两个:1) 直接在Perl脚本中嵌入别的语言编写的代码,这个可以使用P

分享下页面关键字抓取www.icbase.com站点代码(带asp.net参数的)

复制代码 代码如下: <?php/** * HOST: www.icbase.com *///set_time_limit(0);// base functionfunction curl_get($url, $data = array(), $header = array(), $timeout = 15, $port = 80, $reffer = '', $proxy = ''){ $ch = curl_init(); if (!empty($data)) { $data = is_arr