美文网首页
PHP手册之变量范围

PHP手册之变量范围

作者: killtl | 来源:发表于2018-03-20 12:59 被阅读0次

前言

PHP手册系列文章,会挑选一些手册中有意思的评论进行翻译
手册目录: 语言参考---变量---变量范围
参考详情

评论部分

  1. 提出一些有趣的代码,在类函数里面使用static变量
class sample_class
{
  public function func_having_static_var($x= NULL)
  {
    static $var = 0;
    if ($x === NULL)
    { return $var; }
    $var = $x;
  }
}

$a = new sample_class();
$b = new sample_class();
echo $a->func_having_static_var()."\n";
echo $b->func_having_static_var()."\n";
// this will output (as expected):
//  0
//  0

$a->func_having_static_var(3);
echo $a->func_having_static_var()."\n";
echo $b->func_having_static_var()."\n";
// this will output:
//  3
//  3
// maybe you expected:
//  3
//  0
?>

本来我们期望的可能是输出3.0,因为两个不同的实例,调用public非static方法,应该是互不干扰的.但是结果却告诉我们并非如此,方法中的static变量会作用于整个类方法以及所有的类实例,而不仅仅针对某一个实例.如果你想得到期望的输出,你应该放弃使用方法内static变量,像这样:

<?php
class sample_class
{ protected $var = 0;    //使用类内非static变量代替
  function func($x= NULL)
  { $this->var= $x; }
}

?>

我觉得正常的行为情况下是不应该像第一个例子那样使用static变量的,但也许你会用到(比如我),希望这些能对你有用.

你也可以通过类的实例来动态添加该实例的内部public变量,就像$instance->$param = $value 就会向$instance中动态添加了public的$param,当然这只针对该实例有效,不会对类及其他实例造成影响,其实该用法没什么卵用,只是想说php真特么强,笑尿.
  1. 与java和C++不同的是,在循环块和if块语句中的变量可以在块外访问
for($j=0;$j<3;$j++)
{
     if($j == 1)
        $a = 4;
}
echo $a;  //输出 4
  1. 对于嵌套函数,global始终指明的是最外层的全局变量,而不是指上一层的范围,如下将不会按照预期输出
// $var1 is not declared in the global scope
function a($var1){
    function b(){
        global $var1;
        echo $var1; // there is no var1 in the global scope so nothing to echo
    }
    b();
}
a('hello');

如果此时在function a()之上添加$var1 = 'some',将会得到输出结果'some'

  1. 提出一段有趣的代码
class obj{
    public function __destruct(){
        echo 'destruct';
    }
}

function foo ()
{
   global $testvar;
   $localvar = new obj();
   $testvar = &$localvar;
}

foo ();
var_dump($testvar);   
/*
输出
destruct
NULL
*/

因为对象引用是引用同一标识符,所以当方法结束后,相当于unset($localvar),此时没有其他标识符指向类实例,所以调用destruct,同时$testvar也相当于被unset了,为NULL,如果修改function如下

function foo ()
{
   global $testvar;
   $localvar = new obj();
   $testvar = $localvar;  //此处将引用改为赋值
}
/*
输出
object(obj)#1 (0) {
}
destruct
*/

可以看到,赋值跟引用是有区别的,赋值会copy一份标识符指向类实例,所以对$localvar的释放并不会影响$testvar,所以直到程序的最后才会调用destruct.具体的赋值与引用的区别可以参见:http://segmentfault.com/a/1190000002928594

  1. 关于类内方法使用static变量,1中已经提到过,这里指出,static变量不支持继承
class A {
    function Z() {
        static $count =0;        
        printf("%s: %d\n",get_class($this), ++$count);
    }
}

class B extends A {}
$a = new A();
$b = new B();
$a->Z();
$a->Z();
$b->Z();
$a->Z();
?>

/*
输出:
A: 1
A: 2
B: 1
A: 3
*/

可以看到,类A和类B使用了不同的静态变量,即使他们使用的是同一个方法,而且就算function Z是静态方法,结果也是一样

  1. 这里提一下,使用超全局$GLOBALS数组比使用global关键字更快
  2. 如果static变量是一个数组,并且返回它的某个元素的时候,会返回该元素的引用
function incr(&$int) {
  return $int++;
}

function return_copyof_scalar() {
  static $v;
  if (!$v)   
    $v = 1;
  return($v); 
} 

function return_copyof_arrayelement() {
  static $v;
  if (!$v) {
    $v = array();
    $v[0] =1;
  }
  return($v[0]);
} 

echo "scalar: ".
     incr(return_copyof_scalar()).
     incr(return_copyof_scalar()).
     "\n"; 
echo "arrayelement: ".
     incr(return_copyof_arrayelement()).
     incr(return_copyof_arrayelement()).
     "\n"; 
?>
/*
期望输出:
scalar:11
array element:11
*/

/*
他测试的结果:
scalar:11
array emelent:12
*/

但是我在php7上进行了同样的测试,发现结果跟期望输出是一样的,所以这里的数组元素并没有按照引用返回,如果我们要使用引用,应该像&function这样声明函数,也需要像&function一样调用它,但是有一个例外,就是当incr(return_copyof_scalar())这样作为参数调用的时候,不需要添加&,如此只需要在上述例子中的函数声明部分各自添加&就可以得到输出结果

scalar:12
array element:12
  1. 有时候你需在在其他多个函数中访问同一个static,同时这个static的可见范围也是非全局的,这里有一个简单的方法解决这个问题
  // We need a way to get a reference of our static
  function &getStatic() {
    static $staticVar;
    return $staticVar;
  }
  // Now we can access the static in any method by using it's reference
  function fooCount() {
    $ref2static = & getStatic();
    echo $ref2static++;
  }
  fooCount(); // 0
  fooCount(); // 1
  fooCount(); // 2
  1. 你不可以将方法里的static与传入进来的引用参数关联,但是你可以使用数组的形式对引用进行保存与操作
function test($arr = null){
    static $my;
    if(!$arr)return $my[0];
    $my = $arr;
}

$you = 'hello';
test(array(&$you));
$you = 'world';
var_dump(test());
/*
输出
world
*/
  1. 即使某个被include进来的file使用return返回一个value,该value仍然与include的文件中的同名value保持同一个访问范围
$foo = 'aaa';
$bar = include('include.php');
echo($foo.' / '.$bar);

// include.php
$foo = 'bbb';
return $foo;

/*
期望输出:aaa/bbb
实际输出:bbb/bbb
*/
  1. 一个比较有意思的代码
  class A
   {
     function __destruct()
      {
        global $g_Obj;
        echo "<br>#step 2: ";
        var_dump($g_Obj);
      }

     function start()
      {
        global $g_Obj;
        echo "<br>#step 1: ";
        var_dump($g_Obj);
      }
   };

  $g_Obj = new A();       // start here
  $g_Obj->start();

?>

/*
输出
#step 1: object(A)#1 (0) { }
#step 2: object(A)#1 (0) { }
*/

由上可以知道,__destruct()是在执行完后才销毁类实例的

  1. 嵌套函数需要注意重复声明以及第一次声明
function norm($a, $b) {
    static $first_time = true;
    if($first_time) {
        function square($x)
        {
            return $x * $x;
        }
        $first_time = false;
    }
    return sqrt(square($a) + square($b));
}

print norm(5,4);
print square(4);
print norm(6,5);

该例子能正确输出结果,如果将function中的判断语句if($first_time)去掉,就会造成重复声明的错误,同时,如果在语句print norm(5,4)之前调用square函数,将会导致undefined function 的错误,必须先执行一遍外部的norm函数,告诉外部存在其内部定义声明的square函数

  1. 当定义一个static变量时,你可以这样声明
static $var =1; //numbers
static $var ='strings';
static $var = array(1,'a',3);//array construct

但是你不可以这样声明(error)

static $var = some_function('arg');
static $var = (some_function('arg'));
static $var = 2+3;//any expression
static $var = new object;
  1. 当使用远程调用php文件时,远程文件中的变量将不能在调用文件中使用
// remotefile.php
$paramVal=10;

// localfile.php
include "[http://example.com/remotefile.php](http://example.com/remotefile.php)";
echo "remote-value= $paramVal";   //将不会得到预期值

这里提一下,本人没有亲自测试过,需要你自己转转脑瓜动动手测试下真伪

相关文章

  • PHP手册之变量范围

    前言 PHP手册系列文章,会挑选一些手册中有意思的评论进行翻译手册目录: 语言参考---变量---变量范围参考详情...

  • 2019-03-11 PHP学习笔记之PHP的基本语法(2)

    参考资料:《细说PHP》、《PHP、MySQL与JavaScript学习手册》 变量的类型 变量类型指保存在该变量...

  • php简明手册

    # **PHP简明手册** ## **变量 和 常量** > 1. 变量和常量是PHP中最基本的数据存储单元,它们...

  • PHP手册之可变变量

    前言 PHP手册系列文章,会挑选一些手册中有意思的评论进行翻译手册目录: 语言参考---变量---可变变量参考详情...

  • php 类中 :: 与 -> 符号的使用

    php 手册--范围解析操作符 (::) 范围解析操作符(也可称作 Paamayim Nekudotayim)或者...

  • php变量和数据类型

    php中的变量 PHP中的变量声明 PHP中的变量的使用 PHP中的数据类型之整型 PHP数据类型之浮点类型和布尔...

  • PHP引用计数

    1. PHP官方手册引用计数介绍 引用计数每个php变量存在一个叫"zval"的变量容器中。一个zval变量容器,...

  • PHP关键字

    static/global(变量范围) 变量的范围即它定义的上下文背景(也就是它的生效范围)。大部分的 PHP 变...

  • PHP变量的作用域和静态变量

    1、什么是变量的作用域 变量的作用域就是变量的范围,变量的范围即它定义的上下文背景(即它的生效范围),大部分PHP...

  • 生成器

    PHP Manual手册对于生成器的概述:PHP Manual Generator PHP Manual手册新特性...

网友评论

      本文标题:PHP手册之变量范围

      本文链接:https://www.haomeiwen.com/subject/vauvqftx.html