PHP 基础
PHP 代码结构
PHP 标签
嵌入在 HTML 中:
// html
<?php
// ...
?>
// html
作为一个单文件时允许标签不闭合:
<?php
// ...
另外还允许简写(需要在php.ini
中添加short_open_tag = On
) :
<?
// ...
?>
此外还允许使用script
标签:
<script language="php">
// ...
</script>
PHP 注释
单行注释:
# 注释
// 注释
多行注释:
/*
注释
注释
*/
PHP 语句
PHP 代码以分号;
结尾。
<?php
echo "Hello world!";
?>
如果末尾存在?>
,可以省略最后一行的分号;
,但不建议这么做:
<?php
echo "We wil not use“, ”‘Hello,World’";
echo "Hello world!"
?>
PHP 运算符
赋值相关运算符:
PHP 中存在一种用于连接字符串的运算符.
。
字符串连接符:
$str = '高' . '厉害';
$str = '高';
$str .= '厉害';
幂运算云算符:
$integer ** 2;
错误抑制符:
错误抑制符@
可以抑制notice
、warning
级别的错误报出。
例如:
@(10/0);
就可以防止该Division by zerov
警告的输出。
比较运算符:
PHP7 的新特性 —— 飞船运算符<=>
,左大返回 1,左小返回 -1,相等返回 0。
1 <=> 2;
-1
PHP 中也存在==
和===
运算符。
与js
基本相同,==
允许隐式转换,而===
不允许。
1 == '1';
true
1 === '1';
false
合并运算符:
PHP7 的新特性。
exp1 ?? exp2;
主要用来实现js
中的param && "defaultVal"
。
即当param
存在时使用param
,否则使用"defaultVal"
。
三目运算符:
与 C 风格的完全一样,但额外支持一种简化写法:
exp1 ? : exp2;
等价于:
exp1 ? exp1 : exp2;
这里的等价于仅仅是从逻辑上等价,而非执行效果,因为我们不一定要functional
地编写代码。
这里我们不讨论函数式编程的问题,但我们要知道,大多数语言的函数是不纯净的,或者说这一直都取决于开发者的想法。
看下面这个例子:
<?php
function getCounter(){
$var = 0;
return (function (){
global $var;
return ++$var;
});
}
$counter = getCounter();
echo $counter() ? $counter() : '';
?>
2
<?php
function getCounter(){
$var = 0;
return (function (){
global $var;
return ++$var;
});
}
$counter = getCounter();
echo $counter() ? : '';
?>
1
这个程序很简单,我使用了一个闭包函数,每次调用将会使外部作用域的$var
自增 1,并返回自身。
前者使用了exp1 ? exp1 : exp2
的方式来调用这个counter
,而后者则采用上面提到的简化方式exp1 ? : exp2
。
这两种方式最大的区别就是,前者在返回exp1
时进行了二次针对exp1
的求值,而后者仅进行一次求值。
注意exp1 ?: exp2
的含义与var1 ?? var2
非常相近,但前者无法代替后者,因为我们无法保证exp1
是否存在,若不存在,则会报notice Undefined variable
,而后者则不会。
逻辑运算符:
PHP 中支持语义化的逻辑运算符or
、and
(没有not
),当然也允许使用||
、&&
。
可以配合exit
(或die
)函数进行方便地语义化地终止程序进行。
exit
和die
作用相同,都是输出一条语句并结束脚本运行:
// 如果打开失败,就终止运行
fopen(/* arg */, "r") or exit("Unable to connect to $site");
PHP 标签语法
首先,PHP 允许使用这种模板语法:
<table border="1">
<?php for ($i = 1; $i <= 9; $i++) { ?>
<tr>
<?php for ($j = 1; $j <= $i; $j++) { ?>
<td>
<?php
echo $i . ' x ' . $j . ' = ' . (string)$i * $i;
?>
</td>
<?php } ?>
</tr>
<?php } ?>
</table>
这将输出一个 9 * 9 乘法表
其中的:
<?php for ($j = 1; $j <= $i; $j++) { ?>
// ...
<?php } ?>
可以更改为:
<?php for ($j = 1; $j <= $i; $j++) : ?>
// ...
<?php endfor; ?>
从而变成:
<table border="1">
<?php for ($i = 1; $i <= 9; $i++) : ?>
<tr>
<?php for ($j = 1; $j <= $i; $j++) : ?>
<td>
<?php echo $i . ' x ' . $j . ' = ' . (string)$i * $i; ?>
</td>
<?php endfor; ?>
</tr>
<?php endfor; ?>
</table>
用来令代码结构更加清晰(感觉提升不大。。。)。
PHP 变量和数据
PHP 变量
变量
PHP 是动态类型语言。
PHP 中想要引用变量必须以$
符号开头:
$str = "今天学妹去自习没找我!";
var_dump
可以输出某个变量的详细信息:
$str = '明天怎么把她约出来呢?';// string 字面量允许使用单引号
var_dump($str);
string(33) “明天怎么把她约出来呢?”
unset
可以将某个变量释放:
$str = 'QAQ';
unset($str);
静态变量
使用static
关键字定义静态变量:
static $var = 1;
若该变量存在于局部作用域,退出作用域时不会被释放。
预定义变量:
变量名 | 描述 |
---|---|
$_GET | 用户通过 get 方式提交的数据 |
$_POST | 用户通过 post 方式提交的数据 |
$_REQUEST | 用户通过 get/post 方式提交的数据 |
$_SERVER | 用户和服务器的基本信息数据 |
$_FILES | 用户提交的文件数据 |
$_SESSION | session 数据 |
$_COOKIE | cookie 数据 |
$GLOBALS | 所有全局变量,注意不以下划线开头 |
$_ENV | 环境数据 |
变量的引用
PHP 存在变量的引用,通过&
指示:
$var = '';
$ref = &$var; // 引用
PHP 的参数传递思想与 Java 相同,永远是值传递。这就意味着,我们不可能改变外部引用的指向。
PHP 常量
定义常量
使用define
函数:
define('VAL', 2);
使用const
关键字:
const VAL = 2;
访问常量
引用常量不需要使用前导$
符号:
echo VAL;
注意到define
函数的特殊性,我们可以定义一些明显不合法的变量名,例如1_INVALID
:
define('1_INVALID', 2);
这时直接访问该常量显然是语法错误,但是我们可以使用constant
函数,它接收一个字符串参数,代表欲访问的常量名:
echo constant('1_INVALID');
魔术常量
魔术常量是 PHP 的预定义常量,随环境动态变化。
常量名 | 描述 |
---|---|
__DIR__ | 当前文件绝对路径 |
__FILE__ | 当前文件绝对路径,包含文件名 |
__FUNCTION__ | 当前函数名 |
__CLASS__ | 当前类名 |
__NAMESPACE__ | 当前命名空间 |
__METHOD__ | 当前方法名 |
__LINE__ | 当前代码行数 |
PHP 数据类型
PHP 数据类型
基本数据类型:int
,float
,bool
,string
符合数据类型:array
,object
特殊类型:resource
(外部资源的引用),null
布尔类型
在 PHP 中,bool
赋值对大小写不敏感。
例如,下面的代码没有语法错误:
$boolean = trUe;
$boolean = faLsE;
进制
PHP 允许通过数值字面量前缀指定进制:
$hex = 0xabc; # 十六进制
$oct = 0456; // 八进制
$bin = 0b11101; // 二进制
可以通过 C 风格的printf
函数对变量进行格式化输出:
$hex = 0xabc;
printf('%0x', $hex);
abc
还可以通过dechex
函数将十进制数转换为形式上的十六进制:
echo dechex(123);
7b
此外还有全套类似风格的二进制转十进制bindec
,十六进制转八进制hexoct
等。
字符串
在 PHP 中,允许字符串字面量用单引号'
和双引号"
表示,且存在区别。
单引号基本不转义字符,仅转义必要的字符,例如\n
不会被转义,而显然必要的'
会被转义。
双引号则可以转义更多的字符,例如\n
,\t
,\r
,\$
等。
额外地,双引号中允许使用$val
引用变量,使用方法类似js
中的模板字符串。
例如:
$str1 = 'hello';
$str2 = '$str1 world';
echo $str2;
hello world
为了保证被引用变量名的正确性和可读性,PHP 允许使用${val}
或{$val}
来分割变量和其他子串。
同时,直接用空格将变量和其他子串隔开也是可以的。
此外,还有heredoc
和nowdoc
方式表示的字符串字面量,用来表示多行文本:
<?php
$heredoc = <<<EOT
<html>
<head>
<title> </title>
</head>
<body>
</body>
</html>
EOT;
$nowdoc = <<<'EOT'
<html>
<head>
<title> </title>
</head>
<body>
</body>
</html>
EOT;
?>
上面代码展示了heredoc
和nowdoc
字符串字面量,前者的转义字符解析方式与双引号相同,后者与单引号相同。
即heredoc
相当于双引号多行字符串字面量,nowdoc
相当于单引号多行字符串字面量。
其中的EOT
表示"结束标识符"/“定界符”,可以自定义,例如:
$str = <<<ABC
...
ABC;
$str = <<<'_123'
...
_123;
!!注意
- 在定界符内部,注释也被认为是文本的一部分
- 定界符后不允许出现任何内容
- 结束定界符不允许出现缩进
类型判定
判定一个变量是否是某种类型。
例如通过is_numeric
可以判断是否是数值型,is_scalar
可以判断是否是基础类型。
此外就是各种准确类型,is_int
,is_bool
等…
类型转换
PHP 可以使用 C 风格的类型转换:
$toBeConverted = 10;
var_dump((bool)$toBeConverted);
bool(true)
还可以使用settype
,这将改变该变量的类型:
$int2bool = 0;
settype($int2bool, 'bool');
var_dump($int2bool);
bool(false)
PHP 数组
PHP 的数组是 map 结构,相当于 js 原生支持的 JSON 格式一样,通过 key - value 储存数据。
创建
创建一个数组:
$map = array(/* ele ...*/);
或者通过字面量:
$map = [/* ele... */];
初始化时可以使用=>
指定key
:
$people = [
'name' => '学妹',
'chara' => '开朗活泼、上进又可爱',
'age' => 17,
// 注意,与 js 相同,允许在末尾添加一个用于扩展的逗号
];
$people = array(
/* key */ => /* value */,
/* key */ => /* value */,
/* key */ => /* value */,
);
添加/修改
key
允许是任何数据类型:
$map[/* key */] = /* val */;
向 map 尾部插入元素,key
自动编号:
$map[] = /* val */;
删除
通过unset
删除元素或整个数组:
unset($map[/* key */]);
unset($map);
PHP 流程控制
循环
利用count
函数可以返回数组的大小。
for($i = 0, $length = count($arr); $i < $length; $i++) {
$arr[$i];
// ...
}
foreach 循环
foreach($arr as $key => $val) {
$key, $val;
// ...
}
示例:
使用range
函数。
foreach(range(1,10) as $index) {
echo $index;
}
0123456789
循环控制
PHP 中允许通过简单的方式跳出深层循环:
for(/* ... */) {
for(/* ... */) {
// 跳出两层循环
break 2;
}
}
break 1
等价于break
,break ${deep}
表示跳出几层循环。
同样,PHP 也提供了类似的continue
,continue ${count}
表示跳过几次循环。
PHP 函数
函数结构
与js
基本相同,但注意,PHP 不存在变量提升
,且函数默认返回null
。
function /* fun name */ ( /* args */ ) {
// body ...
}
形参默认值
PHP 允许定义参数的默认值:
function fun($param = 'default') {
// ...
}
可变参数
令函数可以接受任意数量的参数:
function fun($param1, ...$args) {
// ...
}
在函数内部,$args
将会是一个数组类型。
额外地,...$var
还可以用来解构数组:
var_dump(...[1, 2, 3]);
int(1)
int(2)
int(3)
严格类型限定
PHP 允许在定义函数时显式指定参数类型:
function fun(int $a){
// ...
}
也允许显式指定返回值类型:
function fun() : int {
// ...
return /* intType */;
}
不过,PHP 仍然允许存在大量隐式类型转换(例如''
=> false
),如果不希望允许这种隐式转换,那么需要在脚本第最前边写上:
declare(strict_types = 1);
引用传参
在形参前加一个&
表示接受一个变量的引用:
function fun(&$ref) {
// ...
}
作用域
在局部使用全局变量,需要使用global
关键字:
$var = 'global';
function fun() {
global $var;
// ...
}
或者通过$GLOBAL
访问,$GLOBAL
称为超级全局变量,其中储存了所有全局变量。
$var = 'global';
function fun() {
$GLOBAL['var'];
// ...
}
函数的引用(匿名函数)
将匿名函数赋值给一个变量,可以通过这个变量直接调用:
$funRef = function (){
// ...
};
$funRef();
或者通过字符串调用:
function fun(){
// ...
};
$funStr = 'fun';
$funStr();
实际上$funStr
仍然是字符串类型,只不过 PHP 允许通过字符串直接调用全局作用域下的函数。
即上面代码中的$funStr();
等价于'fun'();
。
array_map 函数
类似js
中的map
方法:
arr.map((key, val) => return val * 2;);
等价于
array_map(function ($val){ return $val * 2; }, arr);
实现闭包
PHP 不能直接访问外部作用域,而对于全局作用域,还需要显式使用global
关键字声明才能访问。
在 PHP 中,想要访问外部(上级)作用域需要在函数声明处使用use
关键字:
以一个计数器闭包的实现为例:
function outer(int $start) {
$counter = $start;
return function () use (&$counter){
return $counter++;
};
}
!!注意,默认访问的是外部作用域变量的拷贝,而不是引用,如果必要,需要加一个&
符。
PHP 文件包含
文件包含
包含文件有四个关键字:
关键字 | 解释 |
---|---|
include | 可以多次包含,找不到文件将报warning ,开销小 |
include_once | 仅允许包含一次,找不到文件将报warning ,开销大 |
require | 可以多次包含,找不到文件将报error ,开销小 |
require_once | 仅允许包含一次,找不到文件将报error ,开销大 |
例如:
include "file";
解析器遇到文件包含时,将会即时解析,而不是全部包含后解析。
路径
若使用相对路径进行文件包含,则以工作目录为当前路径,那么对于不同文件的互相包含不能保证路径逻辑的正确性。
所以应该避免使用相对路径./ ../
。
PHP 常用 API
日期时间
时间戳
秒:
time(void) : int
毫秒:
microtime([ bool $get_as_float]) : mixed
传入true
则返回一个float
,否则是一个字符串,包含小数部分(到毫秒)和整数部分(秒),以空格隔开。
日期到文本
date( string $format[, int $timestamp] ) : string
format | 说明 | 返回值例子 |
---|---|---|
日 | — | — |
d | 月份中的第几天,有前导零的 2 位数字 | 01 到 31 |
D | 星期中的第几天,文本表示,3 个字母 | Mon 到 Sun |
j | 月份中的第几天,没有前导零 | 1 到 31 |
l | 星期几,完整的文本格式 | Sunday 到 Saturday |
N | ISO-8601 格式数字表示的星期中的第几天(PHP 5.1.0 新加) | 1(表示星期一)到 7(表示星期天) |
S | 每月天数后面的英文后缀,2 个字符 | st,nd,rd 或者 th。可以和 j 一起用 |
w | 星期中的第几天,数字表示 | 0(表示星期天)到 6(表示星期六) |
z | 年份中的第几天 | 0 到 365 |
星期 | — | — |
W | ISO-8601 格式年份中的第几周,每周从星期一开始(PHP 4.1.0 新加的) | 例如:42(当年的第 42 周) |
月 | — | — |
F | 月份,完整的文本格式,例如 January 或者 March | January 到 December |
m | 数字表示的月份,有前导零 | 01 到 12 |
M | 三个字母缩写表示的月份 | Jan 到 Dec |
n | 数字表示的月份,没有前导零 | 1 到 12 |
t | 指定的月份有几天 | 28 到 31 |
年 | — | — |
L | 是否为闰年 | 如果是闰年为 1,否则为 0 |
o | ISO-8601 格式年份数字。这和 Y 的值相同,只除了如果 ISO 的星期数(W)属于前一年或下一年,则用那一年。(PHP 5.1.0 新加) | Examples: 1999 or 2003 |
Y | 4 位数字完整表示的年份 | 例如:1999 或 2003 |
y | 2 位数字表示的年份 | 例如:99 或 03 |
时间 | — | — |
a | 小写的上午和下午值 | am 或 pm |
A | 大写的上午和下午值 | AM 或 PM |
B | Swatch Internet 标准时 | 000 到 999 |
g | 小时,12 小时格式,没有前导零 | 1 到 12 |
G | 小时,24 小时格式,没有前导零 | 0 到 23 |
h | 小时,12 小时格式,有前导零 | 01 到 12 |
H | 小时,24 小时格式,有前导零 | 00 到 23 |
i | 有前导零的分钟数 | 00 到 59> |
s | 秒数,有前导零 | 00 到 59> |
u | 毫秒 (PHP 5.2.2 新加)。需要注意的是 date() 函数总是返回 000000 因为它只接受 integer 参数, 而 DateTime::format() 才支持毫秒。 | 示例: 654321 |
时区 | — | — |
e | 时区标识(PHP 5.1.0 新加) | 例如:UTC,GMT,Atlantic/Azores |
I | 是否为夏令时 | 如果是夏令时为 1,否则为 0 |
O | 与格林威治时间相差的小时数 | 例如:+0200 |
P | 与格林威治时间(GMT)的差别,小时和分钟之间有冒号分隔(PHP 5.1.3 新加) | 例如:+02:00 |
T | 本机所在的时区 | 例如:EST,MDT(【译者注】在 Windows 下为完整文本格式,例如"Eastern Standard Time",中文版会显示"中国标准时间")。 |
Z | 时差偏移量的秒数。UTC 西边的时区偏移量总是负的,UTC 东边的时区偏移量总是正的。 | -43200 到 43200 |
完整的日期/时间 | — | — |
c | ISO 8601 格式的日期(PHP 5 新加) | 2004-02-12T15:19:21+00:00 |
r | RFC 822 格式的日期 | 例如:Thu, 21 Dec 2000 16:01:07 +0200 |
U | 从 Unix 纪元(January 1 1970 00:00:00 GMT)开始至今的秒数 | 参见 time() |
文本到日期
strtotime(string $time[, int $now = time()]) : int
example:
<?php
echo strtotime("now"), "\n";
echo strtotime("10 September 2000"), "\n";
echo strtotime("+1 day"), "\n";
echo strtotime("+1 week"), "\n";
echo strtotime("+1 week 2 days 4 hours 2 seconds"), "\n";
echo strtotime("next Thursday"), "\n";
echo strtotime("last Monday"), "\n";
?>
数学
随机数
mt_rand(int $min, int $max) : int
mt_rand( void) : int
rand
函数已经不建议使用。
很多老的 libc 的随机数发生器具有一些不确定和未知的特性而且很慢。PHP 的 [rand()](mk:@MSITStore:A:\Others\Developing documents\PHP 手册.chm::/res/function.rand.html) 函数默认使用 libc 随机数发生器。mt_rand() 函数是非正式用来替换它的。该函数用了 Mersenne Twister 中已知的特性作为随机数发生器,它可以产生随机数值的平均速度比 libc 提供的 rand() 快四倍。
四舍五入
round(float $val[, int $precision = 0[, int $mode = PHP_ROUND_HALF_UP]]) : float
将$val
舍入到第$precision
位小数点。
PHP_ROUND_HALF_UP: 四舍五入
PHP_ROUND_HALF_DOWN: 五舍六入
PHP_ROUND_HALF_EVEN: 四舍五入(不明?)
PHP_ROUND_HALF_ODD: 四舍五入(不明?)
向上向下取整
ceil(float $value) : float
floor(float $value) : float
最大最小值
max(...$args) : mixed
min(...$min) : mixed
字符串
Ascii 反向转义
例如将"Is your name O'reilly?"
=> "Is your name O\'reilly?"
。
addslashes(string $str) : string
Html 反向转义
例如"<html>"
=> "<html>"
。
htmlspecialchars(string $string[...]) : string
html 转义
与htmlspecialchars
正好相反。
htmlspecialchars_decode( string $string[...] ) : string
Ascii <–> int 互相转换
chr(int $ascii) : string
ord(string $string) : int
字符串分割
相当于js
中的split
:
explode(string $delimiter, string $string[, int $limit]) : array
将$string
通过$delimiter
切割为数组。
字符串连接
相当于js
中的join
:
implode(string $glue, array $pieces) : string
将$pieces
通过$glue
连接。
取字符串长度
strlen(string $string) : int
字符串查找
strpos(string $haystack, mixed $needle[, int $offset = 0]) : int
返回$needle
在$haystack
中首次出现的位置。
不区分大小写的版本:
stripos(string $haystack, string $needle[, int $offset = 0] ) : int
字符串切割
substr(string $string, int $start[, int $length]) : string
返回字符串 string
由 start
和 length
参数指定的子字符串。
字符串替换
str_replace(mixed $search, mixed $replace, mixed $subject[, int &$count]) : mixed
将字符串或数组$subject
中全部的$search
都替换为$replace
。
去除首尾空白字符
trim(string $str[, string $character_mask = " \t\n\r\0\x0B"]) : string
去除 HTML 和 PHP 标记
strip_tags(string $str[, string $allowable_tags]) : string
数组
头插
array_push(array &$array, mixed $value1[, mixed $...]) : int
头删
array_shift(array &$array) : mixed
尾插
array_unshift(array &$array[, mixed $...]) : int
尾删
array_pop(array &$array) : mixed
查找 key
array_key_exists(mixed $key, array $array) : bool
查找 value
in_array(mixed $needle, array $haystack[, bool $strict = FALSE]) : bool
获取 keySet
array_keys(array $array[, mixed $search_value = null[, bool $strict = false]]) : array
合并数组
array_merge(array $array1[, array $...]) : array
相同字符串 key 的 value 将被覆盖,而数值 key 则会重排。
解构
通过语言结构list
:
list($a, $b, $c) = $arr;