1 PHP简介
1.1 PHP是什么
PHP(全称 Hypertext Preprocessor,超文本预处理器的字母缩写)是一种服务器端脚本语言,它可嵌入到 HTML 中,尤其适合 WEB 开发。
一个简单的 PHP 文件示例
<html>
<head>
<title>Example</title>
</head>
<body>
<p>
<?php echo 'Hello World!';?>
</p>
</body>
</html>
其中被 <?php 和 ?> 包围的内容即是 PHP 程序,在装了 PHP 解释器的服务端运行该文件时,PHP 程序能够被解析到 HTML 页面中,上例中结果为
<html>
<head>
<title>Example</title>
</head>
<body>
<p>Hello ShiYanLou!</p>
</body>
</html>
1.2 PHP能干什么
- 服务端脚本。这是 PHP 最传统,也是最主要的目标领域。需要具备以下三点:PHP 解析器(CGI 或者服务器模块),WEB 服务器(如 Nginx,Apache)和浏览器。
- 命令行脚本。可以编写一段 PHP 脚本,并且不需要任何服务器或者浏览器来运行它,仅需要 PHP 解析器来执行。
- 桌面应用程序。桌面应用程序可以通过 PHP 高级特性 PHP-GTK 来编写。PHP-GTK 是 PHP 的一个扩展,在通常发布的 PHP 包中并不包含它。
1.3 PHP如何运行
- 命令行脚本文件
在目录 /home/project 创建 hello.php,并编辑内容
<?php
echo 'Hello World';
?>
命令行执行
php hello.php
Hello World
也可以在 PHP 脚本第一行加入 PHP 路径,通过 ./hello 执行
编辑文件 hello
cd /home/project
vim hello
#!/usr/bin/php
<?php
echo 'Hello World';
保存退出后,修改文件权限
chmod +x hello
./hello
Hello World
- 交互模式
php -a
php > $a = 'Hello World';
php > echo $a;
Hello World
- 直接运行代码
php -r "echo 'Hello World!';"
Hello World
- 服务器端
cgi,如 Nginx 的 fast-cgi。
模块,如 Apache 的 mod_php。
在开发和测试阶段还可以使用 PHP 内置服务器
cd /home/project
php -S localhost:8080
端口号 8080 可以自定义
浏览器输入 http://localhost:8080/hello.php
Hello World
2 PHP基本语法
2.1 PHP标记
通常 PHP 标记为 <?php 和 ?>,输出内容可使用短格式 <? 和 ?>。所有这些标签内的部分都会被 PHP 解析器解析。
如果文件内容是纯 PHP 代码,最好在文件末尾删除 PHP 结束标记。这可以避免在 PHP 结束标记之后万一意外加入了空格或者换行符,会导致 PHP 开始输出这些空白。
<?php
$a = 'Hello';
echo "$a World";
注意文件末尾省略了结束标签 ?>
在 PHP5.4 以后短标签无需任何设置,都是合法标签。
<?="Hello Wolrd"?>
注意:在 PHP7 中以下两个标记方式已经不再适用
- <% 和 %>
2.2 从 HTML 中分离
通常情况下可以使用 echo 输出 HTML 页面
编辑 /home/project/html.php
<?php
$highlight = true;
echo "<html>
<body>
<p".($highlight ? " class='highlight'" : '').">
This is a paragraph
</p>
</body>
</html>";
命令行执行
php html.php
由于在一对开始和结束标记之外的内容都会被 PHP 解析器忽略,我们可以在 HTML 中需要使用 PHP 的地方在执行 PHP 程序,因此,上面例子可以写成
<?php
$highlight = true;
?>
<html>
<body>
<p <?=$highlight ? "class='highlight'" : ''?>>
This is a paragraph
</p>
</body>
</html>
命名行执行
php html.php
两次执行的结果是一样的,因此可以使用第二种方式将 PHP 代码嵌入到 HTML 中,避免使用 echo 输出整段 html 代码。
2.3 指令分隔符
PHP 需要在每个语句后用分号(;)结束指令。如果后面还有新行,则代码段的结束标记包含了行结束。
2.4 注释
PHP 支持多种注释风格
- 单行注释。 // 和 # 仅仅注释到行末或者当前的 PHP 代码块。
- 多行注释。注释在碰到第一个 */ 时结束
<?php
#单行注释
echo 'Hello World';
$a = 'shiyanlou';//单行注释
/**
* 多行注释
* 注释内容
* */
3 数据类型
3.1 数据类型简介
四种标量类型:
- boolean(布尔型)
- integer(整型)
- float(浮点型,也称作 double)
- string(字符串)
两种复合类型: - array(数组)
- object(对象)
最后是两种特殊类型: - resource(资源)
- NULL(无类型)
3.2 类型检测
- var_dump() 函数可以查看表达式的值和类型
- gettype() 函数用于检测变量类型
- is_ 加类型,如 is_int(),is_array() 等,判断变量是否为该类型
.PHP_EOL是换行符。
<?php
$a = TRUE;
$b = "foo";
$c = 0.1;
$d = 12;
if (is_string($b)){
echo "$b 是字符串".PHP_EOL;
}
if (is_int($c)){
echo "$c 是整型".PHP_EOL;
}
var_dump($a);
var_dump($b);
echo gettype($c).PHP_EOL;
echo gettype($d);
结果输出:
foo 是字符串
bool(true)
string(3) "foo"
double
integer
3.3 Boolean 布尔类型
布尔类型表达了真值,可以为 TRUE 或 FALSE,不区分大小写。
<?php
$a = True;
$b = False;
var_dump($a);// bool(true)
var_dump($b);// bool(false)
运算符返回 boolean 类型的结果:
<?php
// == 是一个操作符,它检测两个变量值是否相等,并返回一个布尔值
if ($a == "say_hello") {
echo "Hello World";
}
// $b 的值是否为 true:
if ($res) {
echo "This is true";
}
注意当下列情况转换为 Boolean 时,其值为 FALSE
- 布尔值 FALSE 本身
- 整型值 0(零)
- 浮点型值 0.0(零)
- 空字符串,以及字符串 “0”
- 不包括任何元素的数组
- 特殊类型 NULL(包括尚未赋值的变量)
- 从空标记生成的 SimpleXML 对象
<?php
$a = '';
$b = 0;
$c = false;
$d = "0";
var_dump($a == $b);
var_dump($b == $d);
var_dump($a == $c);
var_dump($b == $c);
结果为:
bool(true)
bool(true)
bool(true)
bool(true)
3.4 Integer 整型
整型值可以使用十进制,十六进制,八进制或二进制表示,前面可以加上可选的符号(- 或者 +)。
注意:要使用八进制表达,数字前必须加上 0。要使用十六进制表达,数字前必须加上 0x。要使用二进制表达,数字前必须加上 0b。
<?php
$a = 1234; // 十进制数
$b = -123; // 负数
$c = 0123; // 八进制数 (等于十进制 83)
$d = 0x1A; // 十六进制数 (等于十进制 26)
整数溢出
如果给定的一个数超出了 integer 的范围,将会被解释为 float。同样如果执行的运算结果超出了 integer 范围,也会返回 float。
3.5 Float 浮点型
浮点型(也叫浮点数 float,双精度数 double 或实数 real)
<?php
$a = 1.234;
$b = 1.2e3;
$c = 7E-10;
浮点数的字长和平台相关,通常最大值是 1.8e308 并具有 14 位十进制数字的精度(64 位 IEEE 格式)
3.6 String 字符串类型
一个字符串 string 就是由一系列的字符组成,其中每个字符等同于一个字节,PHP 中有 4 中表达方式
- 单引号
单引号内特殊字符和变量不会被解析
<?php
$a = 'Hello';
echo '$a \n World';//$a \n World
- 双引号
双引号内的特殊字符和变量会被解析。
```php
<?php
$a = 'Hello';
/**
* Hello
* World
*/
echo "$a \n World";
- Heredoc
Heredoc 类似与双引号,内部转义字符和变量可以被解析,句法结构为
<<<EOT
字符串
EOT;
其中 EOT 为标识符,可以自定义,但是首尾标识符必须相同。开始标识符 EOT 后需换行,结束标识符 EOT 必须独占一行,且前面不许有空格。
<?php
$a ='Hello' ;
echo <<<EOT
$a Hello
EOT;
- Nowdoc
Nowdoc 类似于单引号,无法解析转移字符和变量。句法结构类似 Heredoc,但是需要在开始标识符加上单引号。
<?php
$a ='Hello' ;
echo <<<'EOD'//和 Heredoc 不同点
$a Hello
EOD;
3.7 Array 数组
数组实际上是一个有序映射。映射是一种把 values 关联到 keys 的类型。由于数组元素的值也可以是另一个数组,树形结构和多维数组也是允许的。
语法
定义数组可以用 array() 或 [] 来新建一个数组。它接受任意数量用逗号分隔的键(key) => 值(value)对。key 可以是 integer(索引数组)或者 string(关联数组),value 可以是任意类型,如对象、数组。
<?php
$a = [
"b" => "bb",
"c" => "cc",
];
$b = [
"bb",
"cc"
];
$c = [
"bb",
"cc",
"a" => $a,
"b" => $b,
];
var_dump($a);
var_dump($a[0]);
var_dump($b);
var_dump($b['b']);
var_dump($c['a']['b']);
array(2) {
["b"]=>
string(2) "bb"
["c"]=>
string(2) "cc"
}
NULL
array(2) {
[0]=>
string(2) "bb"
[1]=>
string(2) "cc"
}
NULL
string(2) "bb"
如果没有键名,则数组默认使用从 0 开始的数字键名
打印数组不存在的 key 的值时,直接返回 NULL
数组可以多维嵌套,通过键名可以获取特定值
3.8 Object 对象
使用 new 可以创建一个新的对象
<?php
class foo
{
function do()
{
echo "Action do";
}
}
$f = new foo;
$f->do();
转换为对象
如果将一个对象转换成对象,它将不会有任何变化。如果其它任何类型的值被转换成对象,将会创建一个内置类 stdClass 的实例。如果该值为 NULL,则新的实例为空。 array 转换成 object 将使键名成为属性名并具有相对应的值,除了数字键,不迭代就无法被访问。
<?php
class A
{
}
$a = new A();
$b = (object)$a;
$c = (object)'A';
$d = (object)NULL;
$e = (object)['hello'=>'world'];
var_dump($a);
var_dump($b);
var_dump($c->scalar);
var_dump($d);
var_dump($e->hello);
object(A)#1 (0) {
}
object(A)#1 (0) {
}
string(1) "A"
object(stdClass)#3 (0) {
}
string(5) "world"
从结果中可以看出
- a 是对象,转换为对象后不发生变化,所以a是对象,转换为对象后不发生变化,所以a 等于 $b
- 字符串 “A” 转换为对象时,自动生成 scalar 属性
- 数组 [‘hello’=>‘world’] 转换为对象时,键名 hello 作为属性,键值 world 为属性值
3.9 Resource 资源
资源 resource 是一种特殊变量,保存了外部资源的一个引用,如打开文件、数据库连接等,资源是通过专门的函数来建立和使用的
<?php
$file = fopen($filename);//打开文件
$db = mysqli_connect();//数据库连接
转换为资源
由于资源类型变量保存有为打开文件、数据库连接、图形画布区域等的特殊句柄,因此将其它类型的值转换为资源没有意义。
释放资源
引用计数系统是 Zend 引擎的一部分,可以自动检测到一个资源不再被引用了(和 Java 一样)。这种情况下此资源使用的所有外部资源都会被垃圾回收系统释放。因此,很少需要手工释放内存。
3.9 NULL
特殊的 NULL 值表示一个变量没有值。NULL 类型唯一可能的值就是 NULL。 在下列情况下一个变量被认为是 NULL:
- 被赋值为 NULL
- 尚未被赋值
- 被 unset()
语法
NULL 类型只有一个值,就是不区分大小写的常量 NULL。
<?php
$a = NULL;
转换到 NULL
使用 (unset) 将一个变量转换为 null 将不会删除该变量或 unset 其值。仅是返回 NULL 值而已
3.10 类型转换
PHP 是弱语言类型,定义变量的时候不需要制定变量类型,根据上下文自动解成对于的变量类型。
<?php
$foo = "0";
var_dump($foo);
$foo += 2;
var_dump($foo);
$foo = $foo + 1.3;
var_dump($foo);
$foo = 5 + "10 Little Piggies";
var_dump($foo);
$foo = 5 + "10 Small Pigs";
var_dump($foo);
从结果中可以看出,PHP 隐式转换的优先级为:浮点型 > 整型 > 字符串
类型强制转换
- (int), (integer) - 转换为整形 integer
- (bool), (boolean) - 转换为布尔类型 boolean
- (float), (double), (real) - 转换为浮点型 float
- (string) - 转换为字符串 string
- (array) - 转换为数组 array
- (object) - 转换为对象 object
- (unset) - 转换为 NULL (PHP 5)
4 变量
4.1 变量定义和命名规范
变量定义
PHP 中的变量用一个美元符号 $ 后面跟变量名来表示。
命名规范
变量名区分大小写,一个有效的变量名由字母或者下划线开头,后面跟上任意数量的字母,数字,或者下划线。
<?php
$var = 'Bob';
$Var = 'Joe';
echo "$var, $Var"; // 输出 "Bob, Joe"
$4site = 'not yet'; // 非法变量名;以数字开头
$_4site = 'not yet'; // 合法变量名;以下划线开头
$i站点is = 'mansikka'; // 合法变量名;可以用中文
?>
4.2 传值和引用
传值
变量默认总是传值赋值。这意味着,例如,当一个变量的值赋予另外一个变量时,改变其中一个变量的值,将不会影响到另外一个变量。
<?php
$a = 'hello';
$b = $a;
$a = 'hi';
var_dump($a,$b);
string(2) "hi"
string(5) "hello"
有一点重要事项必须指出,那就是只有有名字的变量才可以引用赋值。例如,&(2 * 3) 为非法形式。
<?php
$a = 'a';
$b = &$a;
$c = &$a;
$d = &$b;
$a = 'b';
var_dump($a,$b,$c,$d);
4.3 预定义变量
PHP 提供了大量的预定义变量。其中一些变量依赖于运行的服务器的版本和设置,及其它因素。
- $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 — 传递给脚本的参数数组
4.4 变量范围
变量的范围即它定义的上下文背景(也就是它的生效范围)。大部分的 PHP 变量只有一个单独的范围。这个单独的范围跨度同样包含了 include 和 require 引入的文件。例如:
<?php
$a = 1;
include 'b.php';
这里变量 $a 将会在包含文件 b.php 中生效。但是,在用户自定义函数中,一个局部函数范围将被引入。任何用于函数内部的变量按缺省情况将被限制在局部函数范围内。
<?php
$hi = 'Hi';
$hello = 'Hello';
function sayHi()
{
echo $hi;
}
function sayHello($hello)
{
echo $hello;
}
sayHi();
sayHello($hello);
结果:
Hello
从结果中可以看出,函数要使用外部变量可以通过传参实现,此外还可以使用全局变量。
4.5 全局变量
全局变量通常使用关键字 global 来声明
<?php
$a = 1;
$b = 2;
function sum()
{
global $a, $b;
$b = $a + $b;
}
sum();
echo $b;
结果输出 3。在函数中声明了全局变量 a 和a和b 之后,对任一变量的所有引用都会指向其全局版本。对于一个函数能够声明的全局变量的最大个数,PHP 没有限制。
在全局范围内访问变量的第二个办法,是用特殊的 PHP 自定义 $GLOBALS 数组。前面的例子可以写成:
<?php
$a = 1;
$b = 2;
function sum()
{
$GLOBALS['b'] = $GLOBALS['a'] + $GLOBALS['b'];
}
sum();
echo $b;
4.6 静态变量
变量范围的另一个重要特性是静态变量。静态变量仅在局部函数域中存在,但当程序执行离开此作用域时,其值并不丢失。看看下面的例子:
<?php
function test()
{
$a = 0;
echo $a;
$a++;
}
每次调用时都会将 a 的值设为 0 并输出 0。将变量加一的a的值设为0并输出0。将变量加一的a++ 没有作用,因为一旦退出本函数则变量 $a 就不存在了。
要写一个不会丢失本次计数值的计数函数,要将变量 $a 定义为静态的:
<?php
function test()
{
static $a = 0;
echo $a.PHP_EOL;
$a++;
}
test();
test();
4.7 可变变量
一个变量的变量名可以动态的设置和使用,例如:
<?php
$a = 'hello';
$$a = 'world';
var_dump($a,$hello);
结果输出
string(5) "hello"
string(5) "world"
上例中动态设置了一个变量 $hello,通常多个 会 依 次 从 最 后 边 开 始 解 析 , 最 后 生 成 会依次从最后边开始解析,最后生成 会依次从最后边开始解析,最后生成 前一个值为名称的变量。
5 常量
5.1 常量定义
命名规范
- 通常常量用大写字母表示,并且遵循和变量一样的命名规范,即以字母或下划线开头,后面跟任何字母,数字或下划线。
- 避免使用 __ 两个下划线开头,被预留为 PHP 内置魔术常量使用。
定义方式 - 使用 define() 函数定义
- 使用 const 关键字定义类之外的常量
注意使用 const 只能在类外部定义,且必须处于最顶端的作用区域,因为用此方法是在编译时定义的。这就意味着不能在函数内,循环内以及 if 语句之内用 const 来定义常量。
一个常量一旦被定义,就不能再改变或者取消定义。
5.2 相比变量
相同点
命名规范都必须以字母或下划线开头,后面跟字母,数字或下划线
不同点
- 常量前面没有美元符号 $
- 常量只能通过 define() 或 const 定义,而不能通过赋值语句
- 常量可以不用理会变量的作用域而在任何地方定义和访问
- 常量一旦定义就不能被重新定义或者取消定义
- 常量的值只能是标量
5.3 魔术常量
PHP 向它运行的任何脚本提供了大量的预定义常量。不过很多常量都是由不同的扩展库定义的,只有在加载了这些扩展库时才会出现,或者动态加载后,或者在编译时已经包括进去了。
有八个魔术常量它们的值随着它们在代码中的位置改变而改变。例如 LINE 的值就依赖于它在脚本中所处的行来决定,这些特殊的常量不区分大小写。
6 运算符
常见算术运算符包括
-
-$a,取反
-
$a + $b,加法,a 和a和b 的和
-
$a - $b,减法,a 和a和b 的差
-
$a * $b,乘法,a 和a和b 的积
-
$a / $b,除法,a 和a和b 的商
-
$a % $b,取余,a 除以a除以b 的余数
-
$a ** $b,乘方,a 的a的b 次方
-
除法运算符总是返回浮点数。只有在下列情况例外:两个操作数都是整数(或字符串转换成的整数)并且正好能整除,这时它返回一个整数。
-
取余运算符的操作数在运算之前都会转换成整数(除去小数部分)。 并且结果和被除数的符号(正负号)相同。即 a %ab 的结果和 $a 的符号相同。
6.1 赋值运算符
基本的赋值运算符是 =,意味着把右边表达式的值赋给左边的运算数。
赋值运算表达式的值也就是所赋的值。也就是说,$a = 3 的值是 3。这样就可以做一些小技巧:
<?php
$a = ($b = 4) + 5; // $a 现在成了 9,而 $b 成了 4。
对于数组 array,对有名字的键赋值是用 => 运算符。此运算符的优先级和其它赋值运算符相同。
<?php
$a = ['a' => 1, 'b' => 3 * 4];
在基本赋值运算符之外,还有适合于所有二元算术,数组集合和字符串运算符的组合运算符,这样可以在一个表达式中使用它的值并把表达式的结果赋给它,例如:
<?php
$a = 3;
$a += 5; //相当于 $a = $a + 5;
$b = "Hello ";
$b .= "There!"; //相当于 $b = $b. "There" ;
注意赋值运算将原变量的值拷贝到新变量中(传值赋值),所以改变其中一个并不影响另一个。这也适合于在密集循环中拷贝一些值例如大数组。
引用赋值
PHP 支持引用赋值,引用赋值意味着两个变量指向了同一个数据,没有拷贝任何东西。
6.2 位运算符
位运算符允许对整型数中指定的位进行求值和操作。
- $a & $b,And(按位与),将把 a 和a和b 中都为 1 的位设为 1。
- $a | $b,Or(按位或),将把 a 和a和b 中任何一个为 1 的位设为 1。
- $a ^ $b,Xor(按位异或),将把 a 和a和b 中一个为 1 另一个为 0 的位设为 1。
- ~$a,Not(按位取反),将 $a 中为 0 的位设为 1,反之亦然。
- $a << $b,Shift left(左移),将 a 中的位向左移动a中的位向左移动b 次(每一次移动都表示乘以 2)。
- $a >> $b,Shift right(右移),将 a 中的位向右移动a中的位向右移动b 次(每一次移动都表示除以 2)。
6.3 比较运算符
比较运算符,如同它们名称所暗示的,允许对两个值进行比较。
- $a == $b,如果类型转换后 a 等于a等于b,返回 TRUE。
- $a === $b,如果 a 等于a等于b,并且它们的类型也相同,返回 TRUE。
- $a != $b,如果类型转换后 a 不等于a不等于b,返回 TRUE。
- $a <> $b,等同于 !=
- $a !== $b,如果 a 和a和b 的值或类型不同,返回 TRUE。
- $a < $b ,如果 a 严格小于a严格小于b,返回 TRUE。
- $a > $b,如果 a 严格大于a严格大于b,返回 TRUE。
- $a <= $b,如果 a 小于或者等于a小于或者等于b,返回 TRUE。
- $a >= $b,如果 a 大于或者等于a大于或者等于b,返回 TRUE。
null 或 String 和 string 比较时,将 null 转换为 “”,进行数字或词汇比较
bool 或 null 和其他类型比较时,转换为 bool,FALSE < TRUE
string,resource 或 number 相互比较时,将字符串或资源转换为数字,按普通数字比较
array 之间比较时,具有较少成员的数组较小
object 和其他类型比较时,object 总是更大
array 和其他类型比较时,array 总是更大,但是比对象小
switch 中第一个条件满足时,不会执行后面满足条件的语句
6.4 错误控制运算符
PHP 支持一个错误控制运算符:@。当将其放置在一个 PHP 表达式之前,该表达式可能产生的任何错误信息都被忽略掉。
<?php
$my_file = @file ('non_existent_file') or
die ("Failed opening file: error was '$php_errormsg'");
$value = @$cache[$key];
错误控制运算符只对表达式有效。对新手来说一个简单的规则就是:
- 如果能从某处得到值,就能在它前面加上 @ 运算符。例如,可以把它放在变量,函数和 include 调用,常量,等等之前。
- 不能把它放在函数或类的定义之前,也不能用于条件结构例如 if 和 foreach 等。
注意:目前的 @ 错误控制运算符前缀甚至使导致脚本终止的严重错误的错误报告也失效。这意味着如果在某个不存在或者敲错了字母的函数调用前用了 @ 来抑制错误信息,那脚本会没有任何迹象显示原因而死在那里。
6.5 执行运算符
PHP 支持一个执行运算符:反引号(``)。注意这不是单引号!PHP 将尝试将反引号中的内容作为外壳命令来执行,并将其输出信息返回(例如,可以赋给一个变量而不是简单地丢弃到标准输出)。
<?php
$output = `ls -al`;
echo "<pre>$output</pre>";
注意,反引号运算符在激活了安全模式或者关闭了 shell_exec() 时是无效的。
6.6 递增(减)运算符
常见递增(减)运算符
- ++$a,a 的值加一返回a的值加一返回a。
- $a++,返回 a,然后将a,然后将a 的值加一。
- –$a,a 的值减一返回a的值减一返回a。
- $a–,返回 a,然后将a,然后将a 的值减一。
6.7 逻辑运算符
常见逻辑运算符
- $a and $b,逻辑与,如果 a 和a和b 都为 TRUE
- $a && $b,逻辑与,如果 a 和a和b 都为 TRUE,其中 && 优先级高于 and
- $a or $b,逻辑或,如果 a 或a或b 任一为 TRUE
- $a || $b,逻辑或,如果 a 或a或b 任一为 TRUE,|| 优先级高于 or
- $a xor $b,逻辑异或,如果 a 或a或b 任一为 TRUE,但不同时是,则返回 TRUE
- ! $a,逻辑非,如果 $a 不为 TRUE
6.8 字符串运算符
有两个字符串运算符。
- 第一个是连接运算符 .,它返回其左右参数连接后的字符串
- 第二个是连接赋值运算符 .=,它将右边参数附加到左边的参数后。
<?php
$a = "Hello ";
$b = $a . "World!"; // now $b contains "Hello World!"
$a = "Hello ";
$a .= "World!"; // now $a contains "Hello World!"
6.9 数组运算符
常见数组运算符
- $a + $b,a 和a和b 的联合
- $a == $b,a 和a和b 键和值都相同则为 TRUE
- $a === $b,a 和a和b 键和值且顺序和类型都相同返回 TRUE
- $a != $b,a 和a和b 中键或值不同返回 TRUE
- $a <> $b,等同于 !=
- $a !== $b,a 和a和b 中键,值,顺序或类型,其中一个不相同则返回 TRUE
6.10 PHP7 新增操作符
组合比较符
太空船操作符使用 <=> 表示,用于比较两个表达式。当 a 小于、等于或大于a小于、等于或大于b 时它分别返回-1、0 或 1。 比较的原则是沿用 PHP 的常规比较规则进行的。
<?php
// 整数
echo 1 <=> 1; // 0
echo 1 <=> 2; // -1
echo 2 <=> 1; // 1
// 浮点数
echo 1.5 <=> 1.5; // 0
echo 1.5 <=> 2.5; // -1
echo 2.5 <=> 1.5; // 1
// 字符串
echo "a" <=> "a"; // 0
echo "a" <=> "b"; // -1
echo "b" <=> "a"; // 1
?>
NULL 合并运算符
NULL 合并运算符使用 ?? 表示,意味着如果 ?? 之前的变量存在且值不为 NULL,它就会返回自身的值,否则返回 ?? 后的操作数。
7 控制结构
- if 语句
<?php if ($a == 5): ?>
A is equal to 5
<?php endif; ?>
<?php
if ($a == 5):
echo "a equals 5";
echo "...";
elseif ($a == 6):
echo "a equals 6";
echo "!!!";
else:
echo "a is neither 5 nor 6";
endif;
?>
- while 语句
while (expr):
statement
...
endwhile;
<?php
$i = 0;
do {
echo $i;
} while ($i > 0);
?>
- for 语句
<?php
/* example 1 */
for ($i = 1; $i <= 10; $i++) {
echo $i;
}
/* example 2 */
for ($i = 1; ; $i++) {
if ($i > 10) {
break;
}
echo $i;
}
/* example 3 */
$i = 1;
for (;;) {
if ($i > 10) {
break;
}
echo $i;
$i++;
}
/* example 4 */
for ($i = 1, $j = 0; $i <= 10; $j += $i, print $i, $i++);
?>
- foreach 语句
<?php
$arr1 = $arr2 = [1, 2, 3, 4];
foreach ($arr1 as &$value) {
$value = $value * 2;
}
var_dump($arr1);
foreach ($arr2 as $key => $value) {
$arr2[$key] = $value * 2;
}
var_dump($arr2, $value);
从结果可以看出,数组最后一个元素的 $value 引用在 foreach 循环之后仍会保留。建议使用 unset() 来将其销毁。
- break 语句
break 结束当前 for,foreach,while,do-while 或者 switch 结构的执行。 break 可以接受一个可选的数字参数来决定跳出几重循环。 - continue 语句
continue 在循环结构用来跳过本次循环中剩余的代码并在条件求值为真时开始执行下一次循环。
Note: 注意在 PHP 中 switch 语句被认为是可以使用 continue 的一种循环结构。
continue 接受一个可选的数字参数来决定跳过几重循环到循环结尾。默认值是 1,即跳到当前循环末尾。
- switch 语句
<?php
switch ($a) {
case 'apple':
//do something
break;
case 'bnanan':
//do something
break;
case 'oringe':
//do something
break;
default:
//do something
}
- declare 语句
directive 部分允许设定 declare 代码段的行为。目前只认识两个指令:ticks(更多信息见下面 ticks 指令)以及 encoding(更多信息见下面 encoding 指令)。
一般用法是 declare(ticks=N);拿declare(ticks=1)来说,这句主要作用有两种:
Zend引擎每执行1条低级语句就去执行一次 register_tick_function() 注册的函数。可以粗略的理解为每执行一句php代码(例如:$num=1;)就去执行下已经注册的tick函数。
tick 代表一个事件,事件的定义是在register_tick_function;事件的执行频率是在(ticks=3)。
<?php
declare(ticks=1);
// A function called on each tick event
function tick_handler()
{
echo "tick_handler() called\n";
}
register_tick_function('tick_handler');
$a = 1;
if ($a > 0) {
$a += 2;
print($a);
}
?>
<?php
declare(encoding='ISO-8859-1');
// code here
?>
- return 语句
如果在一个函数中调用 return 语句,将立即结束此函数的执行并将它的参数作为函数的值返回。
return 可以不接任何参数。
8 函数
8.1 用户自定义函数
<?php
function foo($arg1, ..., $argn)
{
//do something
return $retval;
}
函数无需在调用之前被定义.
PHP 不支持函数重载,也不可能取消定义或者重定义已声明的函数。
8.2 函数的参数
通过参数列表可以传递信息到函数,即以逗号作为分隔符的表达式列表。
PHP 支持按值传递参数(默认),通过引用传递参数以及默认参数。也支持可变数量的参数;
通过引用传递参数
默认参数的值
8.3 返回值
值通过使用可选的返回语句返回。可以返回包括数组和对象的任意类型。返回语句会立即中止函数的运行,并且将控制权交回调用该函数的代码行。
8.4 可变函数
PHP 支持可变函数的概念。这意味着如果一个变量名后有圆括号,PHP 将寻找与变量的值同名的函数,并且尝试执行它。可变函数可以用来实现包括回调函数,函数表在内的一些用途。
8.4 匿名函数
匿名函数(Anonymous functions),也叫闭包函数(closures),允许 临时创建一个没有指定名称的函数。最经常用作回调函数(callback)参数的值。当然,也有其它应用的情况。
9 类与对象
9.1 基本概念
<?php
class A
{
//属性
public $a;
private $b;
//方法
public function actionA()
{
}
}
9.1 对象继承
class A
{
}
class B extends A
{
}
9.2 属性
<?php
class A
{
//只能在类本身使用
private $a = "Hello";
//可以在子类和类本身使用
protected $b = <<<EOT
This is variable b;
EOT;
//除了子类,类本身,外部也可以访问
public $c;
}
9.3 类常量
<?php
class A
{
const ENV = 'env';
const HELLO = 'Hello';
}
9.4 自动加载对象
<?php
spl_autoload_register(function ($class_name) {
include $class_name . '.php';
});
new A();
new B();
9.5 构造和析构函数
构造函数
void __constuct()
创建一个对象时( new 操作),构造函数会自动调用
析构函数
void __destruct(void)
析构函数会在到某个对象的所有引用都被删除或者当对象被显式销毁时执行。
9.6 访问控制
对属性或方法的访问控制,是通过在前面添加关键字 public、protected 或 private 来实现的。如果未添加,则默认为 public。
9.7 访问控制范围解析操作符(::)
范围解析操作符,可以简单地说是一对冒号,可以用于访问静态成员、方法和常量,还可以用于覆盖类中的成员和方法。
当在类的外部访问这些静态成员、方法和常量时,必须使用类的名字。
9.8 Static 关键字
声明类成员或方法为 static,就可以不实例化类而直接访问。不能通过一个对象来访问其中的静态成员(静态方法除外)。
由于静态方法不需要通过对象即可调用,所以伪变量 $this 在静态方法中不可用。静态属性不可以由对象通过 -> 操作符来访问。
9.9 抽象类
定义为抽象的类可能无法直接被实例化,任何一个类, 如果它里面至少有一个方法是被声明为抽象的,那么这个类就必须被声明为抽象的。如果类方法被声明为抽象的, 那么其中就不能包括具体的功能实现。
9.9 接口
使用接口(interface),你可以指定某个类必须实现哪些方法,但不需要定义这些方法的具体内容。我们可以通过 interface 来定义一个接口,就像定义一个标准的类一样,但其中定义所有的方法都是空的。 接口中定义的所有方法都必须是 public,这是接口的特性。
9.10 匿名类
php7 支持通过 new class 来实例化一个匿名类,这可以用来替代一些“用后即焚”的完整类定义。