PHP
1. PHP 简介
PHP 是一种流行的编程语言。
1.1. Redhat 中安装 PHP
1.1.1. 从仓库中安装 php
如果 Redhat 官方仓库中找不到打好包的 php,可以使用“Remi's RPM repository”中的 php,如:
$ sudo yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm # 启用EPEL $ sudo yum install -y http://rpms.remirepo.net/enterprise/remi-release-7.rpm # 启用Remi's RPM repository $ sudo yum install php73 # 安装PHP $ sudo yum install php73-php-fpm # 安装PHP FastCGI Process Manager
下面是安装 mysql 扩展:
sudo yum install php73-php-pdo sudo yum install php73-php-mysqlnd
安装完成后,可以使用下面命令启动 php-fpm:
$ sudo systemctl start php73-php-fpm.service
1.1.2. 从源码安装 php
下载源码包后,主要安装步骤如下:
$ tar zxf php-x.x.x $ cd ../php-x.x.x $ ./configure --enable-fpm --with-mysqli --with-curl # 其它模块可以酌情增加 $ make $ sudo make install
参考:
http://php.net/manual/en/install.unix.nginx.php
https://blog.csdn.net/xiao_zhui/article/details/72556781
1.2. 安装 PHP 扩展(pear vs. pecl)
扩展 PHP 有两种方法:
1、用纯粹的 PHP 代码写函数和类,Pear 就是这样一个项目,可以认为它是 PHP 的上层扩展,其主页是 https://pear.php.net ,使用命令行工具 pear
可以安装这类扩展;
2、用 C 或者 C++编写“外部模块”加载至 PHP 中,Pecl 是这样一个项目,可以认为它是 PHP 底层扩展,其主页是 https://pecl.php.net ,使用命令行工具 pecl
可以安装这类扩展。
参考:
pear help
pecl help
1.2.1. 实例:安装 redis 扩展
下面是安装 redis 扩展的例子:
$ sudo pecl install redis
上面命令执行成功后,你会发现配置文件 php.ini(它的具体位置可以通过 php --ini
查看)中会增加下面内容:
extension="redis.so"
1.3. 查看已安装的模块
执行命令 php -m
可以查看已经安装的模块(包括内置模块和外部模块),如:
$ php -m [PHP Modules] bcmath Core ctype curl date dom filter ftp gd gettext hash iconv intl json libxml mbstring mcrypt mysqli mysqlnd openssl pcntl pcre PDO pdo_mysql pdo_sqlite Phar posix Reflection session shmop SimpleXML soap sockets SPL sqlite3 standard sysvsem tokenizer xml xmlreader xmlrpc xmlwriter xsl zip zlib [Zend Modules]
执行命令 php --ini
可查看 php.ini 文件的位置:
$ php --ini Configuration File (php.ini) Path: /usr/local/php/etc Loaded Configuration File: /usr/local/php/etc/php.ini Scan for additional .ini files in: /usr/local/php/conf.d Additional .ini files parsed: (none)
1.4. Composer
Composer is a tool for dependency management in PHP. It allows you to declare the libraries your project depends on and it will manage (install/update) them for you. PHP 的 Composer 类似于 node 的 npm。
工程根目录中的文件 composer.json 用于描述当前工程的依赖。下面命令会安装 composer.json 中声明的依赖到工程根目录下的 vendor 子目录中:
$ composer install
2. PHP 基本语法
2.1. Hello World(PHP Tag 介绍)
下面是 PHP 版本的 Hello World:
<!DOCTYPE html> <html> <head> <title>PHP Test</title> </head> <body> <?php echo '<p>Hello World</p>'; ?> </body> </html>
php 仅处理 php tag 中的内容,php tag 以 <?php
开始, ?>
结束。
<?php echo '<p>Hello World</p>'; ?>
其中,开始标记中的 PHP 关键字也可以省略,即上行代码等同于:
<? echo '<p>Hello World</p>'; ?>
如果文件内容是纯 PHP 代码,最好在文件末尾删除 PHP 结束标记。 这可以避免在 PHP 结束标记之后万一意外加入了空格或者换行符,会导致 PHP 开始输出这些空白,但这很可能不是期望的行为。
<?php echo "Hello world"; // ... more code echo "Last statement"; // 脚本至此结束,不需要 PHP 结束标记
2.2. 注释
PHP 支持三种形式的注释(两种 C++风格的注释以及 Shell 风格的注释):
<?php echo "This is a test"; // This is a one-line c++ style comment /* This is a multi line comment yet another line of comment */ echo "This is yet another test"; echo 'One Final Test'; # This is a one-line shell-style comment ?>
2.3. 变量
PHP 中变量以 $
符号开头,其后是变量的名称。 变量名是区分大小写的。变量名必须以字母或下划线开头。
<?php $var = 'Bob'; $Var = 'Joe'; // 变量名称是大小写敏感的,和上面变量不同 echo "$var"; // 输出 "Bob" echo "$Var"; // 输出 "Joe" ?>
注: $this
是一个特殊的变量,它不能被赋值。
变量默认总是传值赋值。那也就是说,当将一个表达式的值赋予一个变量时,整个原始表达式的值被赋值到目标变量。这意味着,例如,当一个变量的值赋予另外一个变量时,改变其中一个变量的值,将不会影响到另外一个变量。
PHP 也提供了另外一种方式给变量赋值:引用赋值。这意味着新的变量简单的引用(换言之,“成为其别名” 或者 “指向”)了原始变量。改动新的变量将影响到原始变量,反之亦然。 引用赋值的语法是将一个 &
符号加到将要赋值的变量前(源变量)。 如:
<?php $foo = 'Bob'; // Assign the value 'Bob' to $foo $bar = &$foo; // 这是引用赋值 $bar = "My name is $bar"; // 修改 $bar 时,也会修改 $foo echo $bar; // 输出My name is Bob echo $foo; // 也输出My name is Bob ?>
2.3.1. 预定义变量
PHP 提供了大量的预定义变量。由于许多变量依赖于运行的服务器的版本和设置,及其它因素,所以可能并没有详细的说明文档。有关这些变量的详细列表,请参阅 http://php.net/manual/zh/reserved.variables.php。
下面是使用预定义变量 $_ENV
的例子:
<?php echo 'My username is ' .$_ENV["USER"] . '!'; ?>
2.3.2. 变量范围
变量的范围即它定义的上下文背景(也就是它的生效范围)。
一般地,PHP 中全局变量在函数中使用时必须声明为 global
,这点和 C 语言是不同的。
<?php $a = 1; /* global scope */ $b = 2; /* global scope */ function test() { echo $a; // 什么都不会输出,这里 $a 是函数test中没有被赋值的局部变量 global $b; // 函数内要使用全局变量,需要声明为 global echo $b; // 输出 2 } test(); ?>
需要说明的是,那些预定义的超全局变量(Superglobals),可以直接在函数内使用,不需要使用 global 关键字声明,比如 $_ENV, $_GET, $_POST
等这些数组都是超全局变量。
2.4. 常量
PHP 中常量使用 define 函数来定义,不需要前导的 $
符号,常量名一般约定为大写字母。如:
<?php define('FOO', 100); define('BAR', 200); echo FOO; // 输出100 echo BAR; // 输出200 ?>
2.4.1. 魔术常量
有九个魔术常量它们的值随着它们在代码中的位置改变而改变。例如 __LINE__
的值就依赖于它在脚本中所处的行来决定。 这些特殊的常量不区分大小写 ,如表 1 所示。
Name | Description |
---|---|
__LINE__ |
The current line number of the file. |
__FILE__ |
The full path and filename of the file with symlinks resolved. If used inside an include, the name of the included file is returned. |
__DIR__ |
The directory of the file. If used inside an include, the directory of the included file is returned. This is equivalent to dirname(__FILE__) . This directory name does not have a trailing slash unless it is the root directory. |
__FUNCTION__ |
The function name. |
__CLASS__ |
The class name. |
__TRAIT__ |
The trait name. The trait name includes the namespace it was declared in (e.g. Foo\Bar). |
__METHOD__ |
The class method name. |
__NAMESPACE__ |
The name of the current namespace. |
ClassName::class |
The fully qualified class name. |
3. 数据类型
PHP 支持 10 种原始数据类型(Primitive Types),即:
四种标量类型:
- boolean(布尔型)
- integer(整型)
- float(浮点型)
- string(字符串)
三种复合类型:
- array(数组)
- object(对象)
- callable(可调用)
- iterable(可遍历)
最后是两种特殊类型:
- resource(资源)
- NULL(无类型)
3.1. 布尔类型
这是最简单的类型。要指定一个布尔值,使用常量 TRUE
或 FALSE
,两个都不区分大小写。
要明确地将一个值转换成 boolean,用 (bool)
或者 (boolean)
来强制转换。但是很多情况下不需要用强制转换,因为当运算符,函数或者流程控制结构需要一个 boolean 参数时,该值会被自动转换。
当转换为 boolean 时,以下值被认为是 FALSE:
- 布尔值 FALSE 本身
- 整型值 0(零)
- 浮点型值 0.0(零)
- 空字符串,以及字符串
"0"
- 不包括任何元素的数组
- 特殊类型 NULL(包括尚未赋值的变量)
- 从空标记生成的 SimpleXML 对象
所有其它值都被认为是 TRUE(包括任何资源 和 NAN)。
下面是一些布尔类型的简单测试:
<?php var_dump((bool) ""); // bool(false) var_dump((bool) 1); // bool(true) var_dump((bool) -2); // bool(true) var_dump((bool) "foo"); // bool(true) var_dump((bool) 2.3e5); // bool(true) var_dump((bool) array(12)); // bool(true) var_dump((bool) array()); // bool(false) var_dump((bool) "false"); // bool(true) ?>
3.2. 整型
整型值可以使用十进制,十六进制,八进制或二进制表示,前面可以加上可选的符号( -
或者 +
)。
要使用八进制表达,数字前必须加上 0
。要使用十六进制表达,数字前必须加上 0x
。要使用二进制表达,数字前必须加上 0b
。
<?php $a = 1234; // 十进制数 $a = -123; // 负数 $a = 0123; // 八进制数 (等于十进制 83) $a = 0x1A; // 十六进制数 (等于十进制 26) $a = 0b11111111; // 二进制数字 (等于十进制 255) ?>
注意:如果给定的一个数超出了 integer 的范围,将会被解释为 float。同样如果执行的运算结果超出了 integer 范围,也会返回 float。如:
<?php $large_number = 9223372036854775807; var_dump($large_number); // int(9223372036854775807) $large_number = 9223372036854775808; var_dump($large_number); // float(9.2233720368548E+18) $million = 1000000; $large_number = 50000000000000 * $million; var_dump($large_number); // float(5.0E+19) ?>
3.3. 浮点型
浮点型(也叫浮点数 float,双精度数 double 或实数 real)可以用以下任一语法定义:
<?php $a = 1.234; $b = 1.2e3; $c = 7E-10; ?>
浮点数的精度有限。尽管取决于系统,PHP 通常使用 IEEE 754 双精度格式。
3.4. 字符串
一个字符串就是由一系列的字符组成。可以用单引号或者双引号包围起来,他们的区别在于单引号不会进行转义,而引号中的变量和特殊字符(如 \n
)会进行转义。
除此外,还可以使用类似 Shell 中的 heredoc 句法结构来表示字符串。
使用 .
可以连接两个字符串,使用 .=
可以连接并赋值。如:
<?php $a = "Hello "; $b = $a . "World!"; // now $b contains "Hello World!" $c = "Hello "; $c .= "World!"; // now $c contains "Hello World!" ?>
3.5. 数组(Ordered Map)
An array in PHP is actually an ordered map.
PHP 中使用 array()
函数(或者 []
)来声明数组,基本语法为:
<?php $a = array( "k1" => "v1", "k2" => "v2", ); echo $a["k1"]; // 输出 v1 // 从 PHP 5.4 开始,支持 [] 简化数组声明 $b = [ "k1" => "v1", "k2" => "v2", ]; echo $b["k1"]; // 输出 v1 ?>
直接为数组元素赋值的方式也可以声明数组。如:
<?php $a["k1"] = "v1"; // 直接为数组元素赋值的方式也可以声明数组 $a["k2"] = "v2"; ?>
3.5.1. 省略 key
数组不一定要指定 key,默认 key 是从零开始的整数。如:
<?php $a = ["foo", "bar", "hello", "world"]; // 没有指定key的数组,默认key依次为整数0, 1, 2, ... var_dump($a); // 上面数组 a 相当于: $b = [ 0 => "foo", 1 => "bar", 2 => "hello", 3 => "world", ]; var_dump($b); ?>
还可以只对某些单元指定 key 而对其它单元不指定 key:
<?php $a = [ "a", "b", 6 => "c", "d", ]; var_dump($a); // 上面数组 a 相当于: $b = [ 0 => "a", 1 => "b", 6 => "c", 7 => "d", ]; var_dump($b); ?>
3.5.2. key 只能是整数或者字符串
PHP 数组中,key 可以是整数或者字符串。而 value 可以是任意类型。
此外 key 会有如下的强制转换:
- 包含有合法整型值的字符串会被转换为整型。例如键名 "8" 实际会被储存为 8。但是 "08" 则不会强制转换,因为其不是一个合法的十进制数值。
- 浮点数也会被转换为整型,意味着其小数部分会被舍去。例如键名 8.7 实际会被储存为 8。
- 布尔值也会被转换成整型。即键名 true 实际会被储存为 1 而键名 false 会被储存为 0。
- Null 会被转换为空字符串,即键名 null 实际会被储存为 ""。
- 数组和对象不能被用为键名。坚持这么做会导致警告:Illegal offset type。
如果在数组定义中多个单元都使用了同一个键名,则只使用了最后一个,之前的都被覆盖了。如:
<?php $a = [ 1 => "a", "1" => "b", 1.5 => "c", true => "d", // 由key强制转换规则,1, "1", 1.5, true都会转换为1,所以之前的会被覆盖 "ab" => "bar" ]; echo $a[1]; // 输出 d echo $a["ab"]; // 输出 bar var_dump($a); // 上面数组 a 相当于: $b = [ 1 => "d", "ab" => "bar" ]; var_dump($b); ?>
3.5.3. 增加元素
当我们在意 key 为什么值时,可以这样增加元素:
<?php $myArray['key1'] = 'test'; // 如果key1已存在,会修改它;不存在就增加 ?>
当我们不在意 key,可以不指定 key,即 $a[] = 'newElement'
的方式来增加元素。 未指定键名时,PHP 将自动使用之前用过的最大整数键名(前面说明键名有两类:整数和字符串)加上 1 作为新的键名。 如:
<?php $myArray1[] = 'test1'; // 相当于: $myArray1[0] = 'test1' $myArray1[] = 'test2'; // 相当于: $myArray1[1] = 'test2' $myArray2[100] = 'ab'; $myArray2["foo"] = 'bar'; $myArray2[] = 'test1'; // 相当于: $myArray1[101] = 'test1' $myArray2[] = 'test2'; // 相当于: $myArray1[102] = 'test2' $myArray3["foo"] = 'bar'; $myArray3[] = 'test1'; // 相当于: $myArray3[0] = 'test1' $myArray3[] = 'test2'; // 相当于: $myArray3[1] = 'test2' ?>
3.5.4. 遍历数组
foreach 语法结构提供了遍历数组的简单方式。foreach 仅能够应用于数组和对象,如果尝试应用于其他数据类型的变量,或者未初始化的变量将发出错误信息。有两种语法:
foreach (array_expression as $value) statement foreach (array_expression as $key => $value) statement
下面是 foreach
的例子:
<?php $colors = array('red', 'blue', 'green', 'yellow'); foreach ($colors as $color) { // 只关心value echo "Do you like $color?\n"; } $a = array( "one" => 1, "two" => 2, "three" => 3, "seventeen" => 17 ); foreach ($a as $k => $v) { // 即关心key,又关心value echo "key = $k, value = $v.\n"; } ?>
3.5.5. 操作数组的一些函数
使用 count
函数可以得到数组元素个数,其它操作数组的一些函数可参考:http://php.net/manual/en/ref.array.php
3.6. NULL
特殊的 NULL 值表示一个变量没有值。NULL 类型唯一可能的值就是不区分大小写的常量 NULL。
在下列情况下一个变量被认为是 NULL:
- 被赋值为 NULL。
- 尚未被赋值。
- 被 unset()。
4. 函数
用户定义的函数声明以关键字 function
开头:
<?php function foo($arg_1, $arg_2, /* ..., */ $arg_n) { echo "Example function.\n"; return $retval; } ?>
函数名对大小写不敏感。如果省略了 return 语句,则返回值为 NULL。
4.1. 参数传递(默认为值传递,可修改为引用传递)
默认情况下,函数参数通过值传递(因而即使在函数内部改变参数的值,它并不会改变函数外部的值)。如果希望允许函数修改它的参数值,必须通过引用传递参数。
如果想要函数的一个参数通过引用传递,可以在函数定义中该参数的前面加上符号 &
,如:
<?php function add_some_extra(&$string) // 参数前加了 & ,就是“引用”方式传递参数 { $string .= 'and something extra.'; } $str = 'This is a string, '; add_some_extra($str); // 调用函数add_some_extra会修改它的参数 echo $str; // 输出 'This is a string, and something extra.' ?>
4.2. 默认参数
PHP 函数支持默认参数,其使用实例如下:
<?php function makecoffee($type = "cappuccino") // 为参数 $type 指定了默认参数 { return "Making a cup of $type.\n"; } echo makecoffee(); // Making a cup of cappuccino. echo makecoffee(null); // Making a cup of . echo makecoffee("espresso"); // Making a cup of espresso. ?>
默认值必须是常量表达式,不能是诸如变量,类成员,或者函数调用等。
4.3. 可变数量的参数列表
PHP 在用户自定义函数中支持可变数量的参数列表。在 PHP 5.6 及以上的版本中,由 ...
语法实现,如:
<?php function sum(...$numbers) { // 这是可变数量的参数 $acc = 0; foreach ($numbers as $n) { $acc += $n; } return $acc; } echo sum(1, 2, 3, 4); // 输出 10 ?>
4.4. 匿名函数
匿名函数(Anonymous functions),允许临时创建一个没有指定名称的函数。最经常用作回调函数(callback)参数的值。如下面例子中内置函数 preg_replace_callback 的第 2 个参数是匿名函数:
<?php echo preg_replace_callback('~-([a-z])~', function ($match) { return strtoupper($match[1]); }, 'hello-world'); // 输出 helloWorld ?>
匿名函数也可以作为变量的值来使用,如:
<?php $greet = function($name) { printf("Hello %s\n", $name); }; $greet('World'); // 输出 Hello World $greet('PHP'); // 输出 Hello PHP ?>
4.5. 参数和返回值的类型声明
在 PHP7 中,可以为函数的参数和返回值声明类型,如:
<?php function add2ints(int $a, int $b): int { // ^ ^ ^ // 类型声明 类型声明 类型声明 return $a + $b; } echo add2ints(1, 2); ?>
不过,声明类型时不能使用类型别名,如 boolean 是 bool 的别名,声明布尔类型时必须写为 bool,不能写为 boolean:
<?php function test(boolean $param) {} // 错误的类型声明 test(true); // 会报错。把函数test的参数类型声明从boolean修改为bool后变正常 ?>
默认,PHP 会把错误的类型转换为所声明的类型,如果 PHP 文件中指定了 declare(strict_types=1);
,则不会进行转换,当类型不匹配时直接抛出 TypeError。 如:
<?php declare(strict_types=1); function add2ints(int $a, int $b): int { return $a + $b; } echo add2ints(1, 2); echo add2ints(1.1, 2); // 这一行仅当文件中指定了 declare(strict_types=1); 后才会抛出TypeError ?>
5. 类和对象
自 PHP 5 起完全重写了对象模型以得到更佳性能和更多特性。这是自 PHP 4 以来的最大变化。PHP 5 具有完整的对象模型。
下面是类的定义及基本使用:
<?php class SimpleClass { // 声明属性 public $var1 = "a default value\n"; // 声明方法 public function displayVar() { echo $this->var1; } } $instance = new SimpleClass(); // 创建对象 $instance->displayVar(); // 调用对象方法 echo $instance->var1; // 使用对象属性 ?>