declare是php的设置项,可以改变php运行的默认行为.declare(strict_types=1):启用严格类型检查模式,declare(encoding='UTF-8'):这个指令用于设置脚本的默认字符编码。declare(ticks=1):信号处理器.

参考:
https://www.php.net/manual/zh/control-structures.declare.php

strict_types

严格模式,严格类型模式.
https://www.php.net/manual/zh/language.types.declarations.php#language.types.declarations.strict

默认转换为想要的标量.开启严格模式需要完全类型匹配.
调用方应用严格类型,而不是声明文件.

declare("strict_type=1");
function sum(int $a, int $b) {
    return $a + $b;
}
sum(1,"2");//  TypeError
sum(1,2);

encoding

指定脚本编码方式.
支持的編碼:
https://www.php.net/manual/zh/mbstring.supported-encodings.php
https://www.php.net/manual/zh/function.mb-language.php
用法:
比如代码是文件是GBK文件.

$str="a123王玕";
echo $str;

-w1161
此时会语法错误,代码运行在GBK下,"玕"转换会出问题.

添加declare(encoding='gbk');

declare(encoding='gbk');
$str="a123王玕";

echo $str;

增加了declare(encoding='gbk');发生了什么事情呢?
我们使用 mb_detect_encoding 来检查一类型.

默认字符集是CP936,即是GBK.
-w1161

添加declare(encoding='gbk');后变成了UTF-8.

-w1161

发生了什么?为什么转成UTF-B了?不转成其他呢?

declare(encoding='gbk')' 表示当前脚本的编码格式,最后转换成默认字符.

上面代码相当于,不同所有字符编码都遍历转换.

define('Default_Charset','utf-8');
define('Declare_Encode','gbk');

$str="中国人123A";
$str=mb_convert_encoding($str,Default_Charset,Declare_Encode);

默认值由'internal-encoding'的配置决定,internal-encoding 默认值为空,为空时由 'default_charset' 配置决定,default_charset 默认为utf-8;所有默认转成utf-8;

[internal-encoding]
https://www.php.net/manual/zh/ini.core.php#ini.internal-encoding

[default-charset]
https://www.php.net/manual/zh/ini.core.php#ini.default-charset

; PHP internal character encoding is set to empty.
; If empty, default_charset is used.
; http://php.net/internal-encoding
; internal_encoding = ""

; PHP's default character set is set to UTF-8.
; http://php.net/default-charset
;default_charset = ""

declare(encoding)依赖 [zend.multibyte]zend.script_encoding 配置.

zend.multibyte= On 时支持每个文件单独配置那编码.
依赖mbstring. 默认是 Off;

zend.script_encoding 依赖 zend.multibyte 开关,如果设置,文件头部没设置encoding,则使用默认.

; If enabled, scripts may be written in encodings that are incompatible with
; the scanner.  CP936, Big5, CP949 and ⇧_JIS are the examples of such
; encodings.  To use this feature, mbstring extension must be enabled.
; Default: Off
zend.multibyte = On

; Allows to set the default encoding for the scripts.  This value will be used
; unless "declare(encoding=...)" directive appears at the top of the script.
; Only affects if zend.multibyte is set.
; Default: ""
zend.script_encoding = "utf-8"

影响encoding参数有:

echo 'charset:',ini_get('default_charset').PHP_EOL;
echo 'internal:',mb_internal_encoding().PHP_EOL;
echo 'language:',mb_language().PHP_EOL;// 默认: neutral
echo 'multibyte:',var_dump(ini_get('zend.multibyte'));
echo 'script_encoding:',var_dump(ini_get('zend.script_encoding'));

注意:

  1. 和严格模式不一样,encoding 以代码所在的文件为准.
    严格模式以调用方为准.
  2. opcache会缓存编码后的代码,修改配置后需要清空缓存.

ticks

时钟周期.
一般和 register_tick_function() 配合使用.
指每执行一条php语句,调用一次 register_tick_function.

下面示例,每秒执行ticks=1条语句.
条件语句不执行.

<?php
$a=1;
// 上面不执行
register_tick_function(function(){
    global $n;
    $a=2;
    // 里面代码不触发
    echo 'n:',++$n.PHP_EOL;
    sleep(1);
});
declare(ticks=1);// 从这里开始 1
$a=1; // 2
// 注释 不执行
// 函数声明不执行
function f(){
    $c=1; // 4,7
    echo $c;//5,8
}
$f=f(); // 3
if(true) { // 条件语句不执行
    f(); // 6
}// 不执行
exit();// 不执行

常见用途:
限制循环次数或最大执行时间.

例:

<?php
$n=0;
$t=time();

register_tick_function(function()use(&$n,$t){
    // 大于10次退出
    if(++$n>10){
        echo 'maxNum:',$n;
        exit;
    }
    // 大于10秒退出
    if(time() -$t >5){
        echo 'maxTime:',time()-$t;
        exit;
    }
});
declare(ticks=2);

while(true){
    echo 1;
    sleep(1);
}

定时器:

<?php

$n=0;
$t=time();

pcntl_signal(SIGALRM,function()use(&$n,$t){
    echo '执行定时器,耗时:',time()-$t,PHP_EOL;
});

declare(ticks=1); // 每执行一条语句,检查一下时钟
pcntl_alarm(1);// 定时1秒后执行

sleep(3);// 虽然过了3秒,但没有代码执行,定时器不触发

定时为1秒
当ticks=1时,1秒后就触发.
当ticks=10时,9秒后才触发.

-w983

-w991

有个问题就是,就是实际上每执行一条php低语句都要检测一下.
如果代码量很大,虽然是空检测但是性能肯定会影响.

测试100w次性能对比.
-w613

虽然注册空函数性能差异,相差6倍多.
使用 "pcntl_signal_dispatch" 代替 tick

<?php

$n=0;
$t=microtime(true);

pcntl_signal(SIGALRM,function()use(&$t,&$n){
    $endTime=microtime(true);
    $time=round($endTime-$t,4);
    echo '执行定时器,耗时:',$time,',n:',$n,PHP_EOL;
    exit;
});
pcntl_alarm(2);// 定时N秒后执行
//declare(ticks=1); // 每N条执行,检查时钟

while(true){
    pcntl_signal_dispatch();
    $n++;
}

// tick:     2.0012,n:22930565
// dispatch: 2.0051,n:39798631

原作者:阿金
本文地址:https://hi-arkin.com/archives/php-declare.html

标签: php declare strict_types ticks encoding

(本篇完)

评论