变量
自定义变量
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。后续会在实际的应用场景中一一演示。
- $GLOBALS — 引用全局作用域中可用的全部变量
- $_SERVER — 服务器和执行环境信息
- $_GET — HTTP GET 变量
- $_POST — HTTP POST 变量
- $_FILES — HTTP 文件上传变量
- $_REQUEST — HTTP Request 变量
- $_SESSION — Session 变量
- $_ENV — 环境变量
- $_COOKIE — HTTP Cookies
- $php_errormsg — 前一个错误信息
- $HTTP_RAW_POST_DATA — 原生POST数据
- $http_response_header — HTTP 响应头
- $argc — 传递给脚本的参数数目
- $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