当 a 小 于 、 等 于 、 大 于 a小于、等于、大于 a小于、等于、大于b时 分别返回一个小于、等于、大于0的integer 值。
1; // 0
echo 1 <=> 2; // -1
echo 2 <=> 1; // 1
// Floats
echo 1.5 <=> 1.5; // 0
echo 1.5 <=> 2.5; // -1
echo 2.5 <=> 1.5; // 1
// Strings
echo "a" <=> "a"; // 0
echo "a" <=> "b"; // -1
echo "b" <=> "a"; // 1
echo "a" <=> "aa"; // -1
echo "zz" <=> "aa"; // 1
// Arrays
echo [] <=> []; // 0
echo [1, 2, 3] <=> [1, 2, 3]; // 0
echo [1, 2, 3] <=> []; // 1
echo [1, 2, 3] <=> [1, 2, 1]; // 1
echo [1, 2, 3] <=> [1, 2, 4]; // -1
// Objects
$a = (object) ["a" => "b"];
$b = (object) ["a" => "b"];
echo $a <=> $b; // 0
$a = (object) ["a" => "b"];
$b = (object) ["a" => "c"];
echo $a <=> $b; // -1
$a = (object) ["a" => "c"];
$b = (object) ["a" => "b"];
echo $a <=> $b; // 1
// only values are compared
$a = (object) ["a" => "b"];
$b = (object) ["b" => "b"];
echo $a <=> $b; // 1
?>
从左往右第一个存在且不为 NULL 的操作数。如果都没有定义且不为 NULL,则返回 NULL。
由于日常使用中存在大量同时使用三元表达式和isset操作。使用null合并运算符可以简化操作
变量类型声明有两种模式。一种是强制的,和严格的。允许使用下列类型参数int、string、float、bool 同时不能再使用int、string、float、bool作为类的名字了。
建议定义函数都加上,调用的时候能有更好的提示。
function sumOfInts(int ...$ints)
{
return array_sum($ints);
}
ar_dump(sumOfInts(2, '3', 4.1)); // int(9)
# 严格模式
declare(strict_types=1);
function add(int $x, int $y)
{
return $x + $y;
}
var_dump(add('2', 3)); // Fatal error: Argument 1 passed to add() must be of the type integer
增加了返回类型声明,类似参数类型。这样更方便的控制函数的返回值.在函数定义的后面加上:类型名即可。
function fun(int $a): array
{
return $a;
}
fun(3);//Fatal error
fun([3,2,1]);//[3,2,1]
php 7+允许new class {} 来创建匿名类。个人感觉用处不大。
//php7以前
class Logger
{
public function log($msg)
{
echo $msg;
}
}
$util->setLogger(new Logger());
// php7+
$util->setLogger(new class {
public function log($msg)
{
echo $msg;
}
});
这接受一个以16进制形式的 Unicode codepoint,并打印出一个双引号或heredoc包围的 UTF-8 编码格式的字符串。 可以接受任何有效的 codepoint,并且开头的 0 是可以省略的。
echo "\u{aa}";// ª
echo "\u{0000aa}";// ª
echo "\u{9999}";// 香
闭包绑定 简短干练的暂时绑定一个方法到对象上并立刻调用它。
class A {private $x = 1;}
// PHP 7 之前版本的代码
$getXCB = function() {return $this->x;};
$getX = $getXCB->bindTo(new A, 'A'); // 中间层闭包
echo $getX();
// PHP 7+ 及更高版本的代码
$getX = function() {return $this->x;};
echo $getX->call(new A);
提供更安全的方式解包不可靠的数据。它通过白名单的方式来防止潜在的代码注入。
// 将所有的对象都转换为 __PHP_Incomplete_Class 对象
$data = unserialize($foo, ["allowed_classes" => false]);
// 将除 MyClass 和 MyClass2 之外的所有对象都转换为 __PHP_Incomplete_Class 对象
$data = unserialize($foo, ["allowed_classes" => ["MyClass", "MyClass2"]);
// 默认情况下所有的类都是可接受的,等同于省略第二个参数
$data = unserialize($foo, ["allowed_classes" => true]);
这个类自身定义了许多静态方法用于操作多字符集的 unicode 字符。需要安装intl拓展。
printf('%x', IntlChar::CODEPOINT_MAX);
echo IntlChar::charName('@');
var_dump(IntlChar::ispunct('!'));
它使得在生产环境中启用断言为零成本,并且提供当断言失败时抛出特定异常的能力。以后可以使用这个这个进行断言测试。
ini_set('assert.exception', 1);
class CustomError extends AssertionError {}
assert(false, new CustomError('Some error message'));
assert(1==2, new CustomError('两个数不相等'));
从同一个命名空间下导入的类、函数、常量支持按组一次导入。
#php7以前
use app\model\A;
use app\model\B;
#php7+
use app\model{A,B}
它允许在生成器函数中通过使用 return 语法来返回一个表达式 (但是不允许返回引用值), 可以通过调用 Generator::getReturn() 方法来获取生成器的返回值, 但是这个方法只能在生成器完成产生工作以后调用一次。
$gen = (function() {
yield 1;
yield 2;
return 3;
})();
foreach ($gen as $val) {
echo $val, PHP_EOL;
}
echo $gen->getReturn(), PHP_EOL;
# output
//1
//2
//3
现在,只需在最外层生成其中使用yield from,就可以把一个生成器自动委派给其他的生成器。
function gen()
{
yield 1;
yield 2;
yield from gen2();
}
function gen2()
{
yield 3;
yield 4;
}
foreach (gen() as $val)
{
echo $val, PHP_EOL;
}
var_dump(intdiv(10,3)) //3
session_start() 可以加入一个数组覆盖php.ini的配置
session_start([
'cache_limiter' => 'private',
'read_and_close' => true,
]);
可以使用一个关联数组来对每个正则表达式注册回调函数, 正则表达式本身作为关联数组的键, 而对应的回调函数就是关联数组的值
/
string preg_replace_callback_array(array $regexesAndCallbacks, string $input);
### /
$tokenStream = []; // [tokenName, lexeme] pairs
$input = <<<'end'
$a = 3; // variable initialisation
end;
// Pre PHP 7 code
preg_replace_callback(
[
'~\$[a-z_][a-z\d_]*~i',
'~=~',
'~[\d]+~',
'~;~',
'~//.*~'
],
function ($match) use (&$tokenStream) {
if (strpos($match[0], '$') === 0) {
$tokenStream[] = ['T_VARIABLE', $match[0]];
} elseif (strpos($match[0], '=') === 0) {
$tokenStream[] = ['T_ASSIGN', $match[0]];
} elseif (ctype_digit($match[0])) {
$tokenStream[] = ['T_NUM', $match[0]];
} elseif (strpos($match[0], ';') === 0) {
$tokenStream[] = ['T_TERMINATE_STMT', $match[0]];
} elseif (strpos($match[0], '//') === 0) {
$tokenStream[] = ['T_COMMENT', $match[0]];
}
},
$input
);
// PHP 7+ code
preg_replace_callback_array(
[
'~\$[a-z_][a-z\d_]*~i' => function ($match) use (&$tokenStream) {
$tokenStream[] = ['T_VARIABLE', $match[0]];
},
'~=~' => function ($match) use (&$tokenStream) {
$tokenStream[] = ['T_ASSIGN', $match[0]];
},
'~[\d]+~' => function ($match) use (&$tokenStream) {
$tokenStream[] = ['T_NUM', $match[0]];
},
'~;~' => function ($match) use (&$tokenStream) {
$tokenStream[] = ['T_TERMINATE_STMT', $match[0]];
},
'~//.*~' => function ($match) use (&$tokenStream) {
$tokenStream[] = ['T_COMMENT', $match[0]];
}
],
$input
);
string random_bytes(int length);
int random_int(int min, int max);
#php7+
define('ALLOWED_IMAGE_EXTENSIONS', ['jpg', 'jpeg', 'gif', 'png']);
PHP 7 改变了大多数错误的报告方式。不同于传统(PHP 5)的错误报告机制,现在大多数错误被作为 Error 异常抛出。
这也意味着,当发生错误的时候,以前代码中的一些错误处理的代码将无法被触发。 因为在 PHP 7 版本中,已经使用抛出异常的错误处理机制了。 (如果代码中没有捕获 Error 异常,那么会引发致命错误)。set_error_handle不一定接收的是异常,有可能是错误。
19.1 ERROR层级结构
interface Throwable
|- Exception implements Throwable
|- ...
|- Error implements Throwable
|- TypeError extends Error
|- ParseError extends Error
|- AssertionError extends Error
|- ArithmeticError extends Error
|- DivisionByZeroError extends ArithmeticError
function handler(Exception $e) { ... }
set_exception_handler('handler');
// 兼容 PHP 5 和 7
function handler($e) { ... }
// 仅支持 PHP 7
function handler(Throwable $e) { ... }
19.2 list
list 会按照原来的顺序进行赋值。不再是逆序了,ist不再支持解开字符串
list($a,$b,$c) = [1,2,3];
var_dump($a);//1
var_dump($b);//2
var_dump($c);//3
l
19.3 foreach不再改变内部数组指针
#php 5
int(1)
int(2)
bool(false)
#php7
int(0)
int(0)
int(0)
19.4.十六进制字符串不再被认为是数字
var_dump("0x123" == "291");
#php5
true
#php7
false
19.5 $HTTP_RAW_POST_DATA 被移
$HTTP_RAW_POST_DATA 被移 使用php://input代替
19.6. 移除了 ASP 和 script PHP 标签
//开标签 闭标签
<% %>
<%= %>
参数以及返回值的类型现在可以通过在类型前加上一个问号使之允许为空。当启用这个特性时,传入的参数或者函数返回的结果要么是给定的类型,要么是null。
#php5
function($a = null){
if($a===null) {
return null;
}
return $a;
}
#php7+
function fun() :?string
{
return null;
}
function fun1(?$a)
{
var_dump($a);
}
fun1(null);//null
fun1('1');//1
返回值声明为 void 类型的方法要么干脆省去 return 语句。对于 void来说,NULL 不是一个合法的返回值。
function fun() :void
{
echo "hello world";
}
class Something
{
const PUBLIC_CONST_A = 1;
public const PUBLIC_CONST_B = 2;
protected const PROTECTED_CONST = 3;
private const PRIVATE_CONST = 4;
}
这可以被用在参数或者返回值类型中,它代表接受数组或者实现了Traversable接口的对象。
function iterator(iterable $iter)
{
foreach ($iter as $val) {
//
}
}
一个catch语句块现在可以通过管道字符(|)来实现多个异常的捕获。 这对于需要同时处理来自不同类的不同异常时很有用
try {
// some code
} catch (FirstException | SecondException $e) {
// handle first and second exceptions
}
$data = [
["id" => 1, "name" => 'Tom'],
["id" => 2, "name" => 'Fred'],
];
// list() style
list("id" => $id1, "name" => $name1) = $data[0];
var_dump($id1);//1
$a= "hello";
$a[-2];//l
Closure新增了一个静态方法,用于将callable快速地 转为一个Closure 对象。
exposeFunction();
$privFunc('some value');
对http2服务器推送的支持现在已经被加入到 CURL 扩展
10.1、传递参数过少时将抛出错误
过去我们传递参数过少会产生warning。php7.1开始会抛出error。
10.2、 移除了ext/mcrypt拓展
function test(object $obj) : object
{
return new SplQueue();
}
test(new StdClass());
扩展文件不再需要通过文件加载 (Unix下以.so为文件扩展名,在Windows下以 .dll 为文件扩展名) 进行指定。可以在php.ini配置文件进行启用。
当一个抽象类继承于另外一个抽象类的时候,继承后的抽象类可以重写被继承的抽象类的抽象方法。
Argon2 已经被加入到密码散列(password hashing) API (这些函数以 password_ 开头), 以下是暴露出来的常量
当你准备支持多语言字符集,PDO的字符串类型已经扩展支持国际化的字符集。以下是扩展的常量:
PDO::PARAM_STR_NATL
PDO::PARAM_STR_CHAR
PDO::ATTR_DEFAULT_STR_PARAM
$db->quote('über', PDO::PARAM_STR | PDO::PARAM_STR_NATL);
use Foo\Bar\{
Foo,
Bar,
Baz,
};
7.1、number_format 返回值
var_dump(number_format(-0.01));
// now outputs string(1) "0" instead of string(2) "-0"
7.2、 get_class()不再允许null
var_dump(get_class(null))// warning
7.3、count 作用在不是 Countable Types 将发生warning
count(1), // integers are not countable
7.4、 不带引号的字符串
在之前不带引号的字符串是不存在的全局常量,转化成他们自身的字符串。现在将会产生waring。
7.5、 __autoload 被废弃
__autoload方法已被废弃
7.6、 each 被废弃
使用此函数遍历时,比普通的 foreach 更慢, 并且给新语法的变化带来实现问题。因此它被废弃了。
7.7、 is_object、gettype修正
is_object 作用在**__PHP_Incomplete_Class** 将反回 true,gettype作用在闭包在将正确返回resource
7.8、 Convert Numeric Keys in Object/Array Casts
把数组转对象的时候,可以访问到整型键的值。
// array to object
$arr = [0 => 1];
$obj = (object)$arr;
var_dump(
$obj,
$obj->{'0'}, // now accessible
$obj->{0} // now accessible
);
1.1 允许缩进关闭标记并剥离前导空格
1.2 从结算标记中删除尾随新行要求
$data = ["元素", <<
string(6) "元素"
[1]=>
string(25) "Doc Content
The new line"
[2]=>
int(42)
}
foo(
$bar,
$baz,
);
var_dump(
$foo,
$bar,
$baz,
);
PHP 7.3带来的最受欢迎的功能之一提供了一种处理JSON错误的新方法。这不是核心功能,而是JSON扩展的一个补充,它将改变json_decode()和json_encode()的错误行为。
目前,json_decode()返回null错误,但null也可以是有效的结果。这可能令人困惑,因为
只能通过调用json_last_error()或者知道是否发生错误json_last_error_msg(),它分别以机器可读和人类可读的形式返回全局错误状态。- PHP RFC
json_encode()返回FALSE错误。这更清楚,因为存在特定的错误值。无论如何,这两个函数既不会在出错时停止程序执行,也不会抛出任何警告。
try {
json_decode("{", false, 512, JSON_THROW_ON_ERROR);
}
catch (\JsonException $exception) {
echo $exception->getMessage(); // echoes "Syntax error"
}
$array = [1, 2];
list($a, &$b) = $array;
$array = [1, 2];
$a = $array[0];
$b =& $array[1];
PHP 7.3附带的另一个功能是is_countable()功能。我们在尝试count()不可数的东西时会收到错误。出于这个原因,为了避免警告,我们被迫添加以下代码:
if (is_array($foo) || $foo instanceof Countable) {
// $foo is countable
}
这个RFC提出了函数is_countable(),true如果给定变量是一个数组,它返回,false否则它是一个可数变量。因此,上面的代码可以更改如下:
if (is_countable($foo)) {
// $foo is countable
}
目前,我们可以使用reset(),end()和key()函数检索数组的第一个和最后一个键。不幸的是,使用这些函数,无法在不更改其内部状态的情况下收集数组的第一个或最后一个索引。其他选项通常会降低代码的可读性和性能。
此提议将通过向PHP核心添加两个新函数来更改此方案:
array_key_first()
array_key_last()
在PHP 7.3中,array_key_first()并array_key_last()允许取回第一和给定数组的最后一个关键,而不会影响内部数组指针。这些新功能允许我们编写不太
注意:最初的RFC提出了另外两个函数,array_value_first()并且array_value_last()这些函数在不同的投票中投票,但尚未获得批准,也不会成为PHP核心的参与者。
password_hash('password', PASSWORD_ARGON2I);
password_hash('password', PASSWORD_ARGON2ID);
$options = ['memory_cost' => 1<<11, 'time_cost' => 4, 'threads' => 2];
password_hash('password', PASSWORD_ARGON2ID, $options);
弃用并删除image2wbmp(),弃用和删除不区分大小写的常量。
instanceof 的第一个运算数支持字面量,非对象型字面量检测的结果为 false。
var_dump("literal" instanceof stdClass);
var_dump(42 instanceof stdClass);
var_dump(new stdClass() instanceof stdClass);
bool(false)
bool(false)
bool(true)
bcscale() 函数支持获取当前BC函数所使用的 scale。
LDAP:Lightweight Directory Access Protocol,轻量目录访问协议完全支持
增加了如下的选项来配置FPM的Logging:(暂未翻译)
log_limit
log_buffering
decorate_workers_output
新常量
新函数
PHP 7.4可能会在2019年12月发布。
预加载是 PHP 核心的一个惊人的补充,可以带来一些重大的性能改进。
简而言之:如果您今天使用的是框架,则必须在每次请求时加载和重新编译其文件。预加载允许 服务器 在启动时在内存中加载 PHP 文件,并使它们永久可用于所有后续请求。
性能提升当然需要付出代价:如果预加载文件的来源发生变化,则必须重新启动服务器。
此特性可以大幅提升IO性能,性能提升约30-50%,甚至更高。
类变量可以加类型提示:
此RFC已被接受,并在PHP7.4 中实施。
class A
{
public string $name;
public Foo $foo;
}
我以前写过PHP的类型系统,所以很高兴看到一些改进实际上是在PHP的核心。
类型变化 简而言之:你将能够使用协变返回类型……
class ParentType {}
class ChildType extends ParentType {}
class A
{
public function covariantReturnTypes(): ParentType
{ /* … */ }
}
class B extends A
{
public function covariantReturnTypes(): ChildType
{ /* … */ }
}
……和逆变参数。
class A
{
public function contraVariantArguments(ChildType $type)
{ /* … */ }
}
class B extends A
{
public function contraVariantArguments(ParentType $type)
{ /* … */ }
}
代替如下写法:
$data['date'] = $data['date'] ?? new DateTime();
你可以这样做:
$data['date'] ??= new DateTime();
此RFC已被接受,但尚未合并; 我们尚未100%确定它最终是否在PHP 7.4实施。
外部函数接口,简称FFI,允许从用户区调用C代码。这意味着PHP扩展可以用纯PHP编写。
应该指出,这是一个复杂的主题。您仍然需要C知识才能正确使用此功能。
现在终于能在PHP程序中写 C语言 了!!!
正如标题所说,这个扩展现在可以在所有PHP安装中永久使用。