波哥教你学PHP7之四:PHP变量与常量

变量

自定义变量

PHP变量用$加变量名来表示,注意变量名区分大小写,这意味着,如下两个变量是不一样的。

$a = 'abc';
$A = 'def';

var_dump($a, $A);

有效的变量名是字母下划线开头,后面任意位字母下划线数字。

$__abc = ''; // 合法
$A__   = ''; // 合法
$中国   = '我的中国心'; // 合法,但不建议用
$.abc  = ''; // 不合法
$ab*   = ''; // 不合法

$this 是一个特殊的变量,不能被赋值。在《类与对象》里,表示自己。

Class Human {
    public $populationNumber = 72; /* populationNumber 作为类变量定义时前有 $ 符号 */

    public function print($str) {
        echo $str;
    }

    public function population()
    {
        $populationNumber = $this->populationNumber; /* populationNumber 用 $this 调用时无 $ 符号 */
        $this->print("世界人口太多了,目前有{$populationNumber}亿了\n");
    }
}

(new Human())->population();

未定义值时,变量实际为NULL
变量的引用示例。打印出来的$var1和$var2变量是一样的。

$var1 = '中国';
$var2 = &$var1;
$var1 = $var1 . '风景很好' . "\n";

echo $var1;
echo $var2;

预定义变量

预定义变量,可以直接使用。为PHP内置的一些变量。后续教程会慢慢用到这些预定义变量。
比较常用的为$_GET、$_POST、$_SESSION、$_COOKIE、$_SERVER。后续会在实际的应用场景中一一演示。

  1. $GLOBALS — 引用全局作用域中可用的全部变量
  2. $_SERVER — 服务器和执行环境信息
  3. $_GET — HTTP GET 变量
  4. $_POST — HTTP POST 变量
  5. $_FILES — HTTP 文件上传变量
  6. $_REQUEST — HTTP Request 变量
  7. $_SESSION — Session 变量
  8. $_ENV — 环境变量
  9. $_COOKIE — HTTP Cookies
  10. $php_errormsg — 前一个错误信息
  11. $HTTP_RAW_POST_DATA — 原生POST数据
  12. $http_response_header — HTTP 响应头
  13. $argc — 传递给脚本的参数数目
  14. $argv — 传递给脚本的参数数组

预定义变量示例,请在浏览器中访问 http://localhost/phpstudy/example_17.php?name=Mary&age=18

<?php
/* example_17.php */

/* 预定义变量 */

var_dump('<pre>', $_GET);
var_dump('<pre>', $_SERVER);

可变变量

可变变量就是把一个变量的值作为变量的名称,在一些场景下会用到。具体说明见如下代码

/* 可变变量 */

$hello = 'kitty';
$$hello = "is a Cat"; // 实际上定义了一个变量  $kitty

echo "$hello ${$hello} \n";
echo "$hello $kitty \n";

/* 可变类属性 */
class V
{
    public $a = 'I am a';
    public $b = ['I am b0', 'I am b1', 'I am b2'];
    public $c = 'I am c';
    public $abc = 'I am abc';
}

$v = new V();
$attr1 = 'a';
$attr2 = ['a', 'b', 'c', 'd'];
$attr3 = 'abc';

echo $v->$attr1 . "\n"; // $attr1 是 a 所以 $v->a 就是 I am a
// echo $v->$attr2[0] . "\n"; // only php5
echo $v->{$attr2[0]} . "\n"; // php7 & php5 {$attr2[0]} 是 b
echo $v->$attr3 . "\n";
echo $v->{$attr3[1]}[1] . "\n"; // {$attr3[1]} 是 b 所以 $v->b[1] 就是 I am b1

在命令行下输出:

kitty is a Cat 
kitty is a Cat 
I am a
I am a
I am abc
I am b1

静态变量

假设我们想实现一个函数运行一次就自增1,nonStatic方法就无法达到。但使用了静态变量的 staticVar 就可以实现。静态变量也可以用于类,S类里的 a 属性就是静态属性,所以不管实例化多少次,只要运行了add就会自动加1。

function nonStatic()
{
    $a = 1;
    echo $a . "\n";
    $a ++;
}

nonStatic(); // 1
nonStatic(); // 1

function staticVar()
{
    static $a = 1;
    echo $a . "\n";
    $a ++;
}

staticVar(); // 1
staticVar(); // 2
staticVar(); // 3

class S
{
    public static $a = 1;

    public function add() {
        echo self::$a . "\n";
        self::$a ++;
    }
}

$s1 = new S();
$s1->add(); // 1

$s2 = new S();
$s2->add(); // 2 

(new S())->add(); // 3

变量的作用域

如下示例可以看到,在函数(类)外层定义的变量,是无法直接在函数内部直接使用的,只有使用特定的关键词或者预定义变量才可以访问。函数内部定义的变量在外面也无法访问。
如果使用include require等文件包含函数 比如 a.php 里 包含了 b.php 可以把两个文件看成一个拼合后的文件,再思考变量的作用域。

/* 变量的作用域 */
$zone1 = 11;
$zone2 = 12;
$zone3 = 13;

function zoneFun() {
    echo $zone1 . "\n"; // 无法访问到方法外层的 $zone1

    global $zone2; // 用 global 可以使用方法外层的 $zone2
    echo $zone2 . "\n";

    echo $GLOBALS['zone3'] . "\n"; // 也可以直接使用预定义变量 $GLOBALS 来访问

    $zone4 = 14; // 方法内的局部变量
}

zoneFun();

echo $zone4 . "\n"; // zoneFun函数里定义的变量,方法外层也无法访问到。

输出结果如下:

Notice: Undefined variable: zone1

12
13

Notice: Undefined variable: zone4

常量

常量是一种预先定义好,运行时不可以后期再修改的类型。一个常量一旦被定义,就不能再改变或者取消定义。比如圆周率,比如光速,都是一些固定值,提前定义好就行了,可以不用像变量一样去定义。

一般常量

一般的常量都是用全大写字母下划线来表示,并且没有$前缀。常量是全局变量,可以像$GLOBALS一样随处使用。如下示例,我们可以用 define 和 const 来定义常量,可以用 defined 来判断是否定义了某个常量。get_defined_constants(true)['user'] 可以获取所有我们在代码里定义的常量。如果常量名是动态的,也可以用函数 constant() 来获取常量的值。

<?php
/* example_18.php */

define('PI', 3.1415926);
define('COLOR_LIST', ['red', 'green']); // PHP7 only 之前的版本不可以定义数组
const SEX = ['男', '女'];

// 如果没有定义 SEX 就再定义一下
if (!defined('SEX')) {
    define('SEX', ['男', '女']);
}

var_dump(constant('PI'));
var_dump(SEX, COLOR_LIST);
var_dump(get_defined_constants(true)['user']);

运行的结果如下:

float(3.1415926)
array(2) {
  [0]=>
  string(3) "男"
  [1]=>
  string(3) "女"
}
array(2) {
  [0]=>
  string(3) "red"
  [1]=>
  string(5) "green"
}
array(3) {
  ["PI"]=>
  float(3.1415926)
  ["COLOR_LIST"]=>
  array(2) {
    [0]=>
    string(3) "red"
    [1]=>
    string(5) "green"
  }
  ["SEX"]=>
  array(2) {
    [0]=>
    string(3) "男"
    [1]=>
    string(3) "女"
  }
}

魔术常量

在PHP运行时,我们可以使用一些魔术常量来方便我们的工作,这些魔术常量是由PHP本身定义的。魔术常量同样的名字在不同的环境下,得到的结果是不一样的。如下可以看到魔术常量由两个下划线加名称再加两个下划线组成。

__LINE__        文件中的当前行号。
__FILE__        文件的完整路径和文件名。如果用在被包含文件中,则返回被包含的文件名。
__DIR__         文件所在的目录。如果用在被包括文件中,则返回被包括的文件所在的目录。除非是根目录,否则目录中名不包括末尾的斜杠。(PHP 5.3.0中新增)
__FUNCTION__    函数名称(区分大小写)
__CLASS__       类的名称(区分大小写)。类名包括其被声明的作用区域(例如 Foo\Bar)
__TRAIT__       Trait 的名字(PHP 5.4.0 新加)。自 PHP 5.4 起此常量返回 trait 被定义时的名字(区分大小写)。Trait 名包括其被声明的作用区域(例如 Foo\Bar)。
__METHOD__      类的方法名(PHP 5.0.0 新加)。返回该方法被定义时的名字(区分大小写)。
__NAMESPACE__   当前命名空间的名称(区分大小写)。此常量是在编译时定义的(PHP 5.3.0 新增)。

一个比较详细的例子如下,分析结果,可以更容易的掌握这些魔术常量

<?php
/* example_19.php */
namespace utils;

echo '这是第' . __LINE__ . "行\n";
echo '这是第' . __LINE__ . "行\n";
echo '当前文件目录:' . __DIR__ . "\n";
echo '当前文件路径:' . __FILE__ . "\n";

function whatIsMyName()
{
    echo '函数名是:' . __FUNCTION__ . "\n";
}

whatIsMyName();

// Tool trait
trait Tool
{
    public function getBall()
    {
        echo '函数名:' . __FUNCTION__ . "\n";
        echo '类名是:' . __CLASS__ . "\n";
        echo '函数名:' . __METHOD__ . "\n";
        echo '命名空间:' . __NAMESPACE__ . "\n";
        echo 'TRAIT:' . __TRAIT__ . "\n";
    }
}

// 检查类
class Checker
{
    use Tool;

    public function isQQ()
    {
        echo '函数名:' . __FUNCTION__ . "\n";
        echo '类名是:' . __CLASS__ . "\n";
        echo '函数名:' . __METHOD__ . "\n";
        echo '命名空间:' . __NAMESPACE__ . "\n";

        echo "下面是trait里的结果:\n";
        $this->getBall();
    }
}

(new Checker)->isQQ();

运行结果如下:

这是第5行
这是第6行
当前文件目录:/phpstudy
当前文件路径:/phpstudy/example_19.php
函数名是:utils\whatIsMyName
函数名:isQQ
类名是:utils\Checker
函数名:utils\Checker::isQQ
命名空间:utils
下面是trait里的结果:
函数名:getBall
类名是:utils\Checker
函数名:utils\Tool::getBall
命名空间:utils
TRAIT:utils\Tool
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,542评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,596评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,021评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,682评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,792评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,985评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,107评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,845评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,299评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,612评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,747评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,441评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,072评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,828评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,069评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,545评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,658评论 2 350

推荐阅读更多精彩内容

  • 一、php可以做什么 php是一种可以在服务器端运行的编程语言,可以运行在Web服务器端。 php是一门后台编程语...
    空谷悠阅读 3,091评论 4 97
  • php基础 基本语法形式 区分大小写 主要是指变量名区分大小写 常量通常也区分,但常量也可以自己设定为不区分(不推...
    代码与艺术阅读 1,022评论 1 12
  • php可以做什么 php是一种可以在服务器端运行的编程语言,可以运行在Web服务器端。 php是一门后台编程语言,...
    dptms阅读 1,912评论 1 15
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,637评论 18 139
  • php.ini设置,上传大文件: post_max_size = 128Mupload_max_filesize ...
    bycall阅读 6,744评论 3 64