汇总
PHP5.1:
- autoload
- PDO
- MySQLi
- 类型约束
PHP5.2:
- JSON 支持
PHP5.3:
- 命名空间
- 匿名函数
- 闭包
- 新增魔术方法
__callStatic()
和__invoke()
- 新增魔术变量
__DIR__
- 动态调用静态方法
- 延迟静态绑定
- Heredoc和 Nowdoc
- 类外使用const定义常量
- 三元运算符
- Phar
PHP5.4:
- Short Open Tag
- 数组简写
- Traits,
- 内置 Web 服务器
- 动态访问静态方法
- 实例化时访问类成员
PHP5.5:
- yield
- list用于foreach
- 细节修改
- empty() 支持表达式作为参数
- try-catch 结构新增 finally 块
PHP5.6:
- 常量增强
- 命名空间增强
- 可变函数参数
PHP7.0:
- 标量类型声明
- 返回值类型声明
- defined定义常量数组
- 匿名类
- null合并运算符
PHP7.1:
* 可为空类型
* void类型
* 多异常捕获
PHP7.2:
- 新的对象object
- 允许重写抽象方法
PHP7.3:语法层面没有很大的改变
PHP7.4:
- 类型属性
- 箭头函数
- Null合并运算符支持方法
- Opcache 预加载
PHP8.0:
- JIT即时编译
- 命名参数
- 注解
- 联合类型
- Match表达式
- Nullsafe 运算符
- 构造器属性提升
PHP8.1
- 纯交叉类型 Pure Intersection Types
- 枚举 Enums
- never` 返回类型
- Fibers 纤程
- readonly 只读属性
PHP8.2
- 分离范式类型
- 只读类
- 新的随机数扩展random
- trait中可声明常量
- 弃用动态属性
PHP5.1
__autoload()魔术方法
这是一个自动加载函数,在PHP5中,当我们实例化一个未定义的类时,就会触发此函数。可以通过定义这个函数来启用类的自动加载。
function __autoload($className) {
$filePath = “project/class/{$className}.php”;
if (is_readable($filePath)) {
require($filePath); //这里可以只用require,因为一旦包含进来后,php引擎再遇到类A时,将不会调用__autoload,而是直接使用内存中的类A,不会导致多次包含。
}
}
$a = new A();
$b = new B();
$c = new C();
PDO
PHP 数据对象 (PDO) 扩展为PHP访问数据库定义了一个轻量级的一致接口。
安装
可以通过 PHP 的 phpinfo() 函数来查看是否安装了PDO扩展。
//Linux
extension=pdo.so
//Windows
extension=php_pdo.dll
使用
<?php
$dbms='mysql'; //数据库类型
$host='localhost'; //数据库主机名
$dbName='test'; //使用的数据库
$user='root'; //数据库连接用户名
$pass=''; //对应的密码
$dsn="$dbms:host=$host;dbname=$dbName";
try {
$dbh = new PDO($dsn, $user, $pass); //初始化一个PDO对象
echo "连接成功<br/>";
/*你还可以进行一次搜索操作
foreach ($dbh->query('SELECT * from FOO') as $row) {
print_r($row); //你可以用 echo($GLOBAL); 来看到这些值
}
*/
$dbh = null;
} catch (PDOException $e) {
die ("Error!: " . $e->getMessage() . "<br/>");
}
//默认这个不是长连接,如果需要数据库长连接,需要最后加一个参数:array(PDO::ATTR_PERSISTENT => true) 变成这样:
$db = new PDO($dsn, $user, $pass, array(PDO::ATTR_PERSISTENT => true));
MySQLi
mysqli.dll是PHP对mysql新特性的一个扩展支持,允许访问MySQL 4.1及以上版本提供的功能。
mysql与mysqli的区别:
- mysqli连接是永久连接,而mysql是非永久连接。
- mysql连接每当第二次使用的时候,都会重新打开一个新的进程。mysqli连接一直都只使用同一个进程。
使用
$conn = mysqli_connect('localhost', 'root', '123', 'db_test') or ('error');
$sql = "select * from db_table";
$query = mysqli_query($conn,$sql);
while($row = mysqli_fetch_array($query)){
echo $row['title'];
}
类型约束
通过类型约束可以限制参数的类型,不过这一机制并不完善,目前仅适用于类和 callable(可执行类型) 以及 array(数组), 不适用于 string 和 int.
// 限制第一个参数为 MyClass, 第二个参数为可执行类型,第三个参数为数组
function MyFunction(MyClass $a, callable $b, array $c)
{
// ...
}
PHP5.2
JSON
- json_encode — 对变量进行 JSON 编码
- json_decode — 对 JSON 格式的字符串进行解码
PHP5.3
命名空间
避免不同包中的类名或变量名产生冲突
<?php
namespace XXX; // 命名空间的分隔符是反斜杠,该声明语句必须在文件第一行。
匿名函数(闭包)
用来临时性地创建一个无名函数,用于回调函数等用途。
$func = function($arg)
{
print $arg;
};
$func("Hello World! hovertree.top");
新增魔术方法__callStatic()
和__invoke()
__callStatic()
:用静态方式中调用一个不可访问方法时调用
__invoke()
:以调用函数的方式调用一个对象时的回应方法
$person = new Person('小明'); // 初始赋值
$person(); //触发__invoke()
新增魔术变量__DIR__
获取当前执行的PHP脚本所在的目录
如当前执行的PHP文件为 /htdocs/index.php,则__FILE__
等于’/htdocs/index.php’,而__DIR__
等于’/htdocs’。
动态调用静态方法
public static function test($userName)
{
//...
}
$className = 'cls';
$className::test('Tom'); // PHP >= 5.3.0
延迟静态绑定
PHP 5.3.0中增加了一个static关键字来引用当前类,即实现了延迟静态绑定。
这是因为 self 的语义本来就是“当前类”,所以 PHP5.3 给 static 关键字赋予了一个新功能:后期静态绑定
class A
{
static public function callFuncXXOO()
{
print self::funcXXOO();
}
static public function funcXXOO()
{
return "A::funcXXOO()";
}
}
class B extends A
{
static public function funcXXOO()
{
return "B::funcXXOO";
}
}
$b = new B;
$b->callFuncXXOO(); //A::funcXXOO()
class A
{
static public function callFuncXXOO()
{
print static::funcXXOO();
}
// ...
}
B::callFuncXXOO(); //B::funcXXOO()
类外使用const定义常量
常量是一个简单的标识符。在脚本执行期间该值不能改变(除了所谓的魔术常量,他们其实不是常量)。常量默认大小写敏感。通常常量标识符总是大写的。
可以用define()函数来定义常量。在php5.3.0以后,可以使用const关键字在类定义的外部定义常量,先前版本const关键字只能在类(class)中使用。一个常量一旦被定义,就不能再改变或取消定义。
const和define的区别?
- const是一个语言结构,而define是一个函数。const在编译时要比define快很多。
const用于类成员变量的定义,一经定义,不可修改。Define不可以用于类成员变量的定义,可用于全局常量。
- Const可在类中使用,define不能
- Const不能在条件语句中定义常量
- const采用普通的常量名称,define可以采用表达式作为名称
- const只能接受静态的标量,而define可以采用任何表达式
- const定义的常量时大小写敏感,而define可以通过第三个参数(为true表示大小写不敏感)来指定大小写是否敏感。
简化三元运算符
从PHP 5.3开始,通过排除中间表达式,甚至可以进一步简化三元语句。 如果测试表达式在布尔上下文中评估为true,则返回其值。 否则,将返回替代方法。
<?php
$favoriteColor = $_GET["color"] ?: "pink";
Phar
PHP5.3之后支持了类似Java的jar包,名为phar。用来将多个PHP文件打包为一个文件。
创建一个phar压缩包
$phar = new Phar('swoole.phar');
$phar->buildFromDirectory(__DIR__.'/../', '/.php$/');
$phar->compressFiles(Phar::GZ);
$phar->stopBuffering();
$phar->setStub($phar->createDefaultStub('lib_config.php'));
使用phar压缩包
include 'swoole.phar';
include 'swoole.phar/code/page.php';
使用phar可以很方便的打包你的代码,集成部署到线上机器。
PHP5.4
Short Open Tag 短开放标签
自 PHP5.4 起总是可用。
//可以把
<?php echo $xxoo;?>
//简写成:
<?= $xxoo;?>
数组简写
// 原来的数组写法
$arr = array("key" => "value", "key2" => "value2");
// 简写形式
$arr = ["key" => "value", "key2" => "value2"];
Traits
Traits是 PHP 多重继承的一种解决方案。PHP中无法进行多重继承,但一个类可以包含多个Traits
// Traits不能被单独实例化,只能被类所包含
trait SayWorld
{
public function sayHello()
{
echo 'World!';
}
}
class MyHelloWorld
{
// 将SayWorld中的成员包含进来
use SayWorld;
}
$xxoo = new MyHelloWorld();
// sayHello() 函数是来自 SayWorld 构件的
$xxoo->sayHello();
优先级
基类中的成员函数将被Traits中的函数覆盖,当前类中的成员函数将覆盖Traits中的函数。
内置 Web 服务器
PHP从5.4开始内置一个轻量级的Web服务器,不支持并发,定位是用于开发和调试环境。
在开发环境使用它的确非常方便。
php -S localhost:8000
动态访问静态方法
$func = "funcXXOO";
A::{$func}();
实例化时访问类成员
(new MyClass)->xxoo();
PHP5.5
yield关键字
yield关键字用于当函数需要返回一个迭代器的时候,逐个返回值。
function number10()
{
for($i = 1; $i <= 10; $i += 1)
yield $i;
}
list() 用于 foreach
$array = [
[1, 2, 3],
[4, 5, 6],
];
foreach ($array as list($a, $b, $c))
echo "{$a} {$b} {$c}\n";
细节修改
- 不推荐使用 mysql 函数,推荐使用 PDO 或 MySQLi
- 不再支持Windows XP.
- 可用 MyClass::class 取到一个类的完整限定名(包括命名空间)
- empty() 支持表达式作为参数
- try-catch 结构新增 finally 块
PHP5.6
常量增强
定义常量时允许使用之前定义的常量进行计算
const A = 2; const B = A + 1;
允许常量作为函数参数默认值
function func($arg = C::STR2)asdf
可变函数参数
用于代替 func_get_args()
function add(...$args)
{
//...
}
同时可以在调用函数时,把数组展开为函数参数:
$arr = [2, 3];
add(1, ...$arr);
命名空间增强
命名空间支持常量和函数
PHP7.0
标量类型声明
四种标量类型:boolean (布尔型),integer (整型),float (浮点型, 也称作 double),string (字符串)
function typeString(string $a)
{
echo $a;
}
typeString('sad'); //sad
返回值类型声明
function returnErrorArray(): array
{
return '1456546';
}
print_r(returnErrorArray());
/*
Array
Fatal error: Uncaught TypeError: Return value of returnArray() must be of the type array, string returned in
*/
define 定义数组
define('ANIMALS', [
'dog',
'cat',
'bird'
]);
echo ANIMALS[1]; // 输出 "cat"
匿名类
匿名类就像一个没有事先定义的类,而在定义的时候直接就进行了实例化。
// 直接定义
$objA = new class{
public function getName(){
echo "I'm objA";
}
};
$objA->getName();
null 合并运算符
$username = $_GET['user'] ?? 'nobody';
//这两个是等效的 当不存在user 则返回?? 后面的参数
$username = isset($_GET['user']) ? $_GET['user'] : 'nobody';
PHP7.1
可为空类型
参数以及返回值的类型现在可以通过在类型前加上一个问号使之允许为空。
当启用这个特性时,传入的参数或者函数返回的结果要么是给定的类型,要么是 null 。
<?php
function testReturn(): ?string{
return 'elePHPant';
}
void类型
<?php
function swap(&$left, &$right) : void{
//...
}
多异常捕获
<?php
try {
// some code
} catch (FirstException | SecondException $e) {
// ...
}
PHP7.2
新的对象类型object
<?php
function test(object $obj) : object
{
return new SplQueue();
}
test(new StdClass());
允许重写抽象方法
当一个抽象类继承于另外一个抽象类的时候,继承后的抽象类可以重写被继承的抽象类的抽象方法。
<?php
abstract class A
{
abstract function test(string $s);
}
abstract class B extends A
{
// overridden - still maintaining contravariance for parameters and covariance for return
abstract function test($s) : int;
}
PHP7.4
类属性支持类型声明
<?php
class User {
public int $id;
public string $name;
}
箭头函数
使用隐式按值作用域绑定定义函数的简写语法。
<?php
$factor = 10;
$nums = array_map(fn($n) => $n * $factor, [1, 2, 3, 4]);
// $nums = array(10, 20, 30, 40);?>
Null 合并运算符支持方法
<?php
$array['key'] ??= computeDefault();
//if (!isset($array['key'])) {$array['key'] = computeDefault();}
?>
Opcache 预加载
Opcache将获取您的PHP源文件,将其编译为“ opcodes”,然后将这些编译后的文件存储在磁盘上。opcache会跳过源文件和PHP解释器在运行时实际需要之间的转换步骤。
PHP7.0~PHP7.1~PHP7.2~PHP7.3~PHP7.4新特性
PHP8.0
JIT即时编译
PHP 8引入了名为"Tracing JIT"的JIT编译器。它基于Zend引擎,通过分析和跟踪代码的执行路径,对频繁执行的热点代码进行即时编译,以提高性能。
使用JIT编译器,PHP 8可以在某些情况下显著提高代码的执行速度。特别是对于CPU密集型的任务和循环密集型的代码,性能提升可能更为明显。JIT编译器对于长时间运行的脚本和需要高性能的应用程序特别有用。它可以提供更好的响应时间和更高的吞吐量。
JIT编译器在PHP 8中默认处于禁用状态。要启用JIT编译器,您需要在php.ini配置文件中进行相应的设置。您可以设置opcache.jit_buffer_size
和opcache.jit
等选项来调整JIT编译器的行为。
命名参数
就是具名参数,在调用函数的时候,可以指定参数名称,指定参数名称后,参数顺序可以不安装原函数参数顺序传
//传统方式调用
balance(100, 20);
//php8 使用命名参数调用
balance(amount: 100, payment: 20);
注解
使用注解可以将类定义成一个一个低解耦,高内聚的元数据类。在使用的时候通过注解灵活引入,反射注解类实例的时候达到调用的目的。
注解类只有在被实例化的时候才会调用
联合类型
在不确定参数类型的场景下,可以使用
function printSomeThing(string|int $value)
{
var_dump($value);
}
Match表达式
和switch cash差不多,不过是严格===匹配
<?php
$key = 'b';
$str = match($key) {
'a' => 'this a',
'c' => 'this c',
0 => 'this 0',
'b' => 'last b',
};
echo $str;//输出 last b
Nullsafe 运算符
//不实例 User 类,设置为null
$user = null;
echo $user->getName();//php8之前调用,报错
echo $user?->getName();//php8调用,不报错,返回空
构造器属性提升
在构造函数中可以声明类属性的修饰词作用域
<?php
// php8之前
class User
{
protected string $name;
protected int $age;
public function __construct(string $name, int $age)
{
$this->name = $name;
$this->age = $age;
}
}
//php8写法,
class User
{
public function __construct(
protected string $name,
protected int $age
) {}
}
PHP8.1
纯交叉类型 Pure Intersection Types
你可以将类型声明添加到函数参数、返回值和类属性。 此分配称为类型提示,并确保该值在调用时具有正确的类型。 否则,它会立即抛出 TypeError。
使用 & (AND) 运算符来声明交叉类型。 使用 | (OR) 运算符来声明联合类型。
在交集类型中使用大多数标准类型将导致永远无法实现的类型(例如整数和字符串)。 因此,交叉类型只能包括类类型(即接口和类名)。
class PureIntersectionTypesClass {
private Traversable&Countable $countableIterator;
public function setIterator(Traversable&Countable $countableIterator): void {
$this->countableIterator = $countableIterator;
}
public function getIterator(): Traversable&Countable {
return $this->countableIterator;
}
}
枚举 Enums
enum Suit {
case Hearts;
case Diamonds;
case Clubs;
case Spades;
}
可以使用以下语法直接访问这些值:Suit::Hearts、Suit::Diamonds、Suit::Clubs 和 Suit::Spades。
never
返回类型
PHP 8.1 添加了一个名为 never 的新返回类型提示。 在总是抛出或退出的函数中使用它非常有帮助。
never
返回类型的函数应满足三个条件:
- 不应该明确定义 return 语句。
- 不应该隐式定义 return 语句(例如 if-else 语句)。
- 必须以退出语句(显式或隐式)结束其执行。
function redirect(string $uri): never {
header('Location: ' . $uri);
exit();
}
function redirectToLoginPage(): never {
redirect('/login');
}
Fibers 纤程
Fiber 是 PHP 通过虚拟线程(或绿色线程)处理并行性的方式。 它试图通过允许 PHP 函数中断而不影响整个调用堆栈来消除同步和异步代码之间的差异。
我们可以使用 Fibers 开发全栈、可中断的 PHP 函数,然后可以使用这些函数在 PHP 中实现协作式多任务处理。
$fiber = new Fiber(function (): void {
$value = Fiber::suspend('fiber');
echo "Value used to resume fiber: ", $value, "\n";
});
$value = $fiber->start(); //启动
echo "Value from fiber suspending: ", $value, "\n";
$fiber->resume('test'); //恢复
// Value from fiber suspending: fiber
// Value used to resume fiber: test
readonly 只读属性
PHP 8.1 增加了对只读属性的支持。 它们只能从声明它们的范围初始化一次。 初始化后,您将无法修改它们的值。 这样做会引发错误异常。
class Test {
public readonly string $kinsta;
public function __construct(string $kinsta) {
// 初始化
$this->kinsta = $kinsta;
}
}
PHP8.2新特性
分离范式类型
class Foo {
public function bar((A&B)|null $entity)
{
return $entity;
}
}
只读类
当一个类被声明为 readonly,它的所有属性都会自动声明 readonly。此外,这个类不能使用动态属性,以确保所有的属性都是有定义的。
readonly class User {
public string $username;
public string $uid;
}
新的随机数扩展
PHP 8.2内置一个新的扩展,它增加了一种更适合OOP的方式来处理随机数生成和其他随机化操作。
您可以使用此特性来打乱字符串或者打乱一个数组,在指定的数值范围获取随机数。
use Random\Randomizer;
$randomizer = new Randomizer();
$randomizer->shuffleBytes('Hello World'); // example output: "eWrdllHoo l"
$randomizer->shuffleBytes(['a', 'b', 'c', 'd']); // example output: ['b', 'd', 'a', 'c']
$randomizer->getInt(0, 100); // example output: 42
trait中可声明常量
trait WithSpatieApi {
protected const SPATIE_API_VERSION = 1;
}
弃用动态属性
PHP8.2 中最值得注意的弃用之一就是弃用动态属性。
如果一个类属性没有声明就被调用或赋值,就会退出程序。
class User {
public int $uid;
}
$user = new User();
$user->name = 'Foo';//弃用警告
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。