變量
自定義變量
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