目录

APCu、Opcache、Yac

  • APCu扩展

    APC 插件曾经包含字节码和对象缓存功能,但是自从 Zend 官方推出了 Opcache 后,APC 开发者就将字节码缓存功能删掉了,后来推出了 APCu 只保留对象缓存。APCu是APC的升级版。

    也就是现在的APCu扩展像是memcache和redis一样的对象缓存功能。

  • Yac扩展

    Yac 是为PHP实现的一个基于共享内存, 无锁的内容Cache。

    Yac (Yet Another cache)是鸟哥惠新宸的作品之一。

    could be used to replace APC, local memcache.

    经常用来代替APC,本地缓存。

  • opcache

    OPcache 通过将 PHP 脚本预编译的字节码存储到共享内存中来提升 PHP 的性能,存储预编译字节码的好处就是省去了每次加载和解析 PHP 脚本的开销。

    PHP 5.5.0 及后续版本中已经绑定了 OPcache 扩展,可通过phpinfo查看zend OPcache信息。

    php7.1默认开启了。

    • opcache的用处

      没有使用opcache的脚本输出:

      php script => parse => compile => execute => output

      使用opcache的脚本再次输出:

      php script => opcache => execute => output

    • opcache php.ini配置:

      PHP: 运行时配置 - opcache - Manual

    • opcache常用函数:

      • opcache_compile_file — 无需运行,即可编译并缓存 PHP 脚本。

        opcache_compile_file( string $file) : boolean
        
      • opcache_is_script_cached — Tells whether a script is cached in OPCache。

        opcache_is_script_cached( string $file) : bool
        
      • opcache_reset — 重置字节码缓存的内容

        opcache_reset() : boolean
        

错误处理和日志记录

  • 错误日志运行时配置

    PHP: 运行时配置 - 错误日志 - Manual

    • error_reporting integer

      设置错误报告的级别。也就是什么级别的错误才会报告。

      在 PHP5.3 及以上版本中,默认值为 E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED。

      开发阶段,我们建议启用E_NOTICE。

    • display_errors string

      该选项设置是否将错误信息作为输出的一部分显示到屏幕,或者对用户隐藏而不显示。

      ; Possible Values:
      ;   Off = Do not display any errors
      ;   stderr = Display errors to STDERR (affects only CGI/CLI binaries!)
      ;   On or stdout = Display errors to STDOUT
      

      建议:永远不在生产环境启用,这是一个辅助开发功能。

    • display_startup_errors boolean

      设置PHP 启动过程中的错误信息是否显示,display_errors并不会控制php启动过程中的错误信息是否显示。

    • log_errors boolean

      设置是否将脚本运行的错误信息记录到服务器错误日志或者error_log之中。

      建议:前面我们建议,永远不要在生产环境使用display_errors,这里我们建议生产环境中使用错误日志记录脚本运行的错误信息。

    • ignore_repeated_errors boolean

      不记录重复的信息。重复的错误必须出现在同一个文件中的同一行代码上,除非 ignore_repeated_source 设置为true。

    • error_log string

      设置脚本错误将被记录到的文件。该文件必须是web服务器用户可写的。

      如果设置为 syslog,则将错误信息发送到系统日志记录器。在Unix以及类似系统上,使用的是 syslog(3) ,而在 Windows NT 类系统上则为事件日志。

      ; Example:
      ;error_log = php_errors.log
      ; Log errors to syslog (Event Log on Windows).
      ;error_log = syslog
      
      

      建议:生产环境中,把脚本错误信息记录到指定的错误日志文件中。

    • syslog.ident string

      设置每条日志消息前缀的识别字符串(ident string),仅在 error_log 为 “syslog” 时有效。

  • 函数

    • error_reporting

      设置应该报告何种 PHP 错误。注意:面向的错误是php内部错误,而不是用户自定义错误,比如用户trigger_error自触发的错误。

      //关闭php的系统错误报告。
      error_reporting(0);
      // 除了 E_NOTICE,报告其他所有错误
      error_reporting(E_ALL ^ E_NOTICE);
      
    • error_log

      发送错误信息到某个地方。

      error_log( string $message[, int $message_type = 0[, string $destination[, string $extra_headers]]] ) : bool

      参数:

      • message:应该被记录的错误信息。

      • message_type:设置错误应该发送到何处。可能的信息类型有以下几个:

        0 message 发送到 PHP 的系统日志,使用操作系统的日志机制或者一个文件,取决于 error_log 指令设置了什么。这是个默认的选项。
        1 message 发送到参数 destination 设置的邮件地址。第四个参数 extra_headers 只有在这个类型里才会被用到。
        2 不再是一个选项。
        3 message 被发送到位置为 destination 的文件里。字符 message 不会默认被当做新的一行。
        4 message 直接发送到 SAPI 的日志处理程序中。

      • destination:目标。它的含义描述于以上,由 message_type 参数所决定。

      • extra_headers:额外的头。当 message_type 设置为 1 的时候使用。该信息类型使用了 mail() 的同一个内置函数。

      注意:message 不能包含 null 字符,null字符可能会截断message。注意,message 可能会发送到文件、邮件、syslog 等。所以在调用 error_log() 前需要使用适合的转换/转义函数: base64_encode()、 rawurlencode() 或 addslashes()。

      // 如果无法连接到数据库,写如error_log指令配置的日志文件
      if (!Ora_Logon($username, $password)) {
          error_log("Oracle database not available!");
          //error_log("Oracle database not available!", 0);
      }
      // 写入指定日志文件
      error_log("there is a error.", 3, "/var/tmp/php.error.log");
      
    • error_get_last array

      获取关于最后一个发生的错误的信息。

    • set_error_handler

      设置用户的函数 (error_handler) 来处理脚本中出现的错误。

      set_error_handler( callable $error_handler[, int $error_types = E_ALL | E_STRICT] ) : mixed
      

      参数:

      • $error_handler

        是一个回调函数名(注意:string),回调函数要求包含参数:错误级别errno、错误信息errstr、错误发生文件名errfile、错误发生行数errline

        function userErrorHandler($errno, $errmsg, $filename, $linenum){
            ...
        } 
        
      • $error_types

        这个参数很重要,用来控制哪些级别的错误信息需要通过回调函数$error_handler处理。

        注意:如果没有设置,则所有错误发生时都会调用回调函数$error_handler,不论是系统错误还是用户错误,也不论error_reporting如何设置。

        注意:如果设置为E_USER_ERROR,则除了E_USER_ERROR错误会触发用户自定错误处理回调函数外,其他错误信息则是走error_reporting设置的错误日志记录方式。

    • trigger_error

      产生一个用户级别的 error/warning/notice 信息。

      trigger_error( string $error_msg[, int $error_type = E_USER_NOTICE] ) : bool

      参数:

      • error_msg

        该 error 的特定错误信息,长度限制在了 1024 个字节。超过 1024 字节的字符都会被截断。

      • error_type

        用于定义这个自定义错误类型,但仅 E_USER 系列常量对其有效,默认是 E_USER_NOTICE。

    • set_exception_handler

      设置用户自定义的异常处理函数 。

      自 PHP 7 以来,大多数错误抛出 Error 异常,也能被捕获。 Error 和 Exception 都实现了 Throwable 接口。 PHP 7 起,处理程序的签名:handler( Throwable $ex) : void

      自定义异常处理函数,相比较于自定义错误处理函数更简单,会默认接手所有异常处理。

      function exception_handler($throwable) {
          //var_dump($exception);
          echo "Uncaught Throwable: " , $throwable->getMessage(), "\n";
      }
      
      set_exception_handler('exception_handler');
            
      try {
          //echo 1/0; // 仅警告
          intdiv(1, 0);
          //echo $a%0;
      }catch(Exception $e){
          throw new \Exception("catch from Excetion.");
      } catch (\DivisionByZeroError $e) {
          throw new DivisionByZeroError("catch from DivisionByZeroError.");    
      } catch (\Error $e) {
          throw new \Error("catch from Error.");
      } finally {
          echo "run before exception_handler.\n";
      }
      

      输出:

      run before exception_handler.
      Uncaught exception: catch from DivisionByZeroError.
      
    • restore_error_handler

    • restore_exception_handler

      注意:两个restore函数,是恢复到上一次set_error_handler/set_exception_handler设置的自定义处理函数,而不是完全清除之前定义的所有自定义处理函数,不是恢复到系统默认处理错误函数或异常处理。

      function exception_handler_1(Exception $e){}
      function exception_handler_2(Exception $e){}
      set_exception_handler('exception_handler_1');
      set_exception_handler('exception_handler_2');
      
      restore_exception_handler();
      
      throw new Exception('这里抛出的异常将会被exception_handler_1函数捕获处理');
      
  • 错误日志记录优先级总结

    伪代码:

    function logErrorByINI(){
        if(ini中开启了log_errors){
            if(ini中配置error_log){
                错误信息写入syslog、errlog指定日志文件;
            }
        }
    }
      
    if(存在set_error_handler函数,回调函数user_error_handler){
        if(未设置$error_type过滤错误类型){
            所有错误发生时调用用户自定义错误处理函数user_error_handler();
        }elseif(满足set_error_handler过滤错误类型){
            满足类型的错误发生时才调用用户自定义错误处理函数user_error_handler(),其他错误发生时走系统设置;
        }else{
            if(存在error_reporting函数){
                if(满足error_reporting函数定义的错误类型){
                    logErrorByINI();
                }
            }else{
                if(ini中配置了error_reporting){
                    if(满足error_reporting配置的错误类型){
                        logErrorByINI();                    
                    }
                }
                  
            }
        }
    }
    if(ini中配置display_errors){        
        if(fpm){
            if(php-fpm.www.conf开启php_flag[display_errors] = on){
                输出错误信息;
            }        
        }
        输出错误信息;
    }
    
      
    

输出缓冲控制ob函数

  • php输出缓冲

    输出缓冲相当于一个输出内容队列,用于对接存储速度、优先级不同步的设备,让这些设备的输入输出不阻塞,更加流畅。

    默认情况下,php buffer是开启的,而且该buffer默认值是4096byte。可以通过php.ini配置文件中找到output_buffering配置。当echo、print等输出用户数据的时候,输出数据都会写入到php output_buffering中,直到output_buffering写满,会将这些数据通过tcp传送给浏览器显示。也可以通过 ob_start()手动激活php output_buffering机制,使得即便输出超过了4096byte数据,也不真的把数据交给tcp传给浏览器,因为ob_start()将php buffer空间设置到了足够大 。只有直到脚本结束,或者调用ob_end_flush函数,才会把数据发送给客户端浏览器。

    注意:This directive is hardcoded to Off for the CLI SAPI。在CLI模式下是关闭的,因为可能造成性能问题。

  • ob_start

    此函数将打开输出缓冲。当输出缓冲激活后,脚本将不会输出内容(除http标头外),相反需要输出的内容被存储在内部缓冲区中。

    ob_start接受一个callalbe的output_callback函数名。

    function callback($buffer){    
        return (str_replace("apples", "bananas", $buffer));
    }
    
    ob_start('callback');
    
    echo "It's like comparing apples to oranges.\n<br />";
    
    $contents = ob_get_contents();
    
    print_r("最终输出内容:".$contents);
    
    ob_end_flush();
    
  • ob_end_flush

    冲刷出(送出)输出缓冲区内容并关闭缓冲。

    区别于ob_flush,多了关闭缓冲区。

  • ob_end_clean

    清空(擦除)缓冲区并关闭输出缓冲。

    区别于ob_clean,多了关闭缓冲区。

  • ob_get_contents

    返回输出缓冲区的内容。

  • flush与ob_flush

    在没有开启output_buffering时,脚本输出的内容都在服务器端处于等待输出的状态 ,等待脚本结束或调用flush()将等待输出的内容立即发送到客户端。

    开启缓存后,脚本输出的内容存入了输出缓冲中,这时没有处于等待输出状态的内容,直接使用flush()不会向客户端发出任何内容。

    而ob_flush()的作用就是将本来存在输出缓冲中的内容取出来(也就是官方文档写的:冲刷出(送出)输出缓冲区中的内容),设置为等待输出状态,但不会直接发送到客户端 ,这时你就需要先使用 ob_flush()再使用flush(),客户端才能立即获得脚本的输出。

    所以在默认开启output_buffering下,先ob_flush将冲刷出输出缓冲区中的内容,输出内容进入等待输出状态,再flush将输出内容刷新给tcp推送给客户端。

  • ob_implicit_flush()

    将打开或关闭绝对(隐式)刷送。绝对(隐式)刷送将导致在每次输出调用后有一次刷送操作,以便不再需要对 flush() 的显式调用。

    通俗点说就是不用再显示的调用flush来输出。

  • 更多ob函数

    只要我们理解了输出缓冲机制,充分理解ob_start、ob_flush、ob_end_flush、flush、ob_get_contents函数,其他比如ob_get_clean、ob_get_flush从字面也大概知道是什么含义了。

  • 使用场景与小结

    ob函数用于web场景,比如:

    • 脚本未结束前(可能脚本执行时间较长),先输出部分内容
    • 脚本输出前通过ob_start回调调整或检查等处理输出内容
    • 脚本输出前,记录最后输出内容

    对于没有深入理解php输出机制的小伙伴,不建议随便使用php的ob函数,一方面怕误用,另一方面由于apache、nginx等web服务对于php输出有或没有或不同程度的缓冲,导致ob函数可能会有不一样的效果,也就是官方在flush函数里介绍的,在个别web服务器里怎么样,有些apache模块怎么样,一些浏览器怎么样,也就是说效果很难一致的统一,所以我们不建议使用输出缓冲控制ob函数,除非不得已。

    比如nginx有开启proxy_buffering,php即使刷出缓冲区内容,也会再被缓存在nginx层,另外还由于gzip压缩,未满输出内容区上限,也不会提前输出到客户端。

    所以如果在nginx环境下想使用ob_flush\flush在脚本未结束前输出部分内容,就需要调整nginx配置:

    proxy_buffering off;
    gzip off;
    fastcgi_keep_conn on;
    

    当然ob_start(callable)、ob_end_flush()在服务端的效果还是一致,不论web服务器是哪个,还是能做到将输出先写入PHP的output buffer中,再传递给callable回调函数,最后通过ob_flush\flush\ob_end_flush冲出。

  • 参考

    PHP: Output Control 函数 - Manual

    【解决方法】nginx中php ob_flush和flush不起作用 - longzhankunlun - 博客园

PHP选项和信息

这些PHP选项和信息函数能让我们获得许多关于PHP本身的参数。比如:运行时的配置,被加载的扩展,版本等。

  • assert/assert_options

    assert在php7中是语言结构,不再是函数。

    assert() 会检查指定的 assertion 并在结果为 FALSE 时采取适当的行动。

    assert_options(ASSERT_ACTIVE,1);
    assert_options(ASSERT_BAIL,0);
    assert_options(ASSERT_CALLBACK,"assert_fail");
    
    function assert_fail($file, $line, $code){
        echo "<hr>Assertion Failed:
        File '$file'<br />
        Line '$line'<br />
        Code '$code'<br /><hr />";
    }
    
    assert(1==2);
    
    echo "end.";
    

    正常输出:

    Assertion Failed: File '/var/www/html/php-shiyanchang/FunctionsReference/assert.php'
    Line '26'
    Code ''
    
    Warning: assert(): assert(1 == 2) failed in /var/www/html/php-shiyanchang/FunctionsReference/assert.php on line 26
    end.
    

    很多人参考官方文档去测试例子,发现assert根本不工作,找遍国内网站,基本找不到解决方案。比如上面的例子复制过去执行,发现只返回:end.,没有其他信息可以参考:

    Assert not working in php. So simple. What am I doing wrong? - Stack Overflow

    问题在于php.ini配置,zend.assertions = 1时,php才会编译assertions:

    [Assertion]
    ; Switch whether to compile assertions at all (to have no overhead at run-time)
    ; -1: Do not compile at all
    ;  0: Jump over assertion at run-time
    ;  1: Execute assertions
    ; Changing from or to a negative value is only possible in php.ini! (For turning assertions on and off at run-time, see assert.active, when zend.assertions = 1)
    ; Default Value: 1
    ; Development Value: 1
    ; Production Value: -1
    ; http://php.net/zend.assertions
    ;zend.assertions = -1
    zend.assertions = 1 
    
    
  • extension_loaded — 检查一个扩展是否已经加载

  • get_current_user — 获取当前 PHP 脚本所有者名称

  • get_defined_constants — 返回所有常量的关联数组,键是常量名,值是常量值

  • get_extension_funcs — 返回模块函数名称的数组

  • getenv — 获取一个环境变量的值

    $ip = getenv('REMOTE_ADDR');
    
    // 或简单仅使用全局变量($_SERVER 或 $_ENV)
    $ip = $_SERVER['REMOTE_ADDR'];
    
  • getlastmod — 获取页面(即当前脚本文件)最后修改的时间

  • ini_get_all — 获取所有配置选项

  • ini_get — 获取一个配置选项的值

  • ini_set — 为一个配置选项设置值

  • ini_restore — 恢复配置选项的值

  • memory_get_usage — 返回分配给 PHP 的内存量

  • memory_get_peak_usage — 返回分配给 PHP 内存的峰值

  • php_ini_loaded_file — 取得已加载的 php.ini 文件的路径

  • php_ini_scanned_files — 返回从额外 ini 目录里解析的 .ini 文件列表

  • php_sapi_name — 返回 web 服务器和 PHP 之间的接口类型。比如:CGI PHP

  • php_uname — 返回运行 PHP 的系统的有关信息

  • phpinfo — 输出关于 PHP 配置的信息

  • phpversion — 获取当前的PHP版本

  • set_time_limit — 设置脚本最大执行时间

    设置允许脚本运行的时间,单位为秒。如果超过了此设置,脚本返回一个致命的错误。默认值为30秒,或者是在php.ini的max_execution_time被定义的值。

    当此函数被调用时,set_time_limit()会从0开始重新启动超时计数器。换句话说,如果超时默认是30秒,在脚本运行了了25秒时调用 set_time_limit(20),那么,脚本在超时之前可运行总时间为45秒。

    注意:只影响脚本本身执行的时间。只影响脚本本身执行的时间。任何发生在诸如使用system()的系统调用,流操作,数据库操作等的脚本执行的最大时间不包括其中,当该脚本已运行。

  • sys_get_temp_dir — 返回用于临时文件的目录

    // 使用 sys_get_temp_dir() 在目录里创建临时文件
    $temp_file = tempnam(sys_get_temp_dir(), 'Tux');
    //结果创建文件:/tmp/TsinghYEccT
    
  • version_compare — 对比两个「PHP 规范化」的版本数字字符串

    其实这个函数也可以用来对比规范化的产品版本数字字符串,比如:团队管理08-研发约定与规范 - 产品号管理 - 9ong

    注意:是数字,数字字符串,但甚至支持带有字符的字符串,主要要有数字版本号。

    if (version_compare('v7.1.1.beta', 'v7.2.0') >= 0) {
        print_r("我们使用的版本大于7.2.0\n");
    }else{
        print_r("我们使用的版本小于7.2.0\n");    
    }
    

    很多公司内部的框架对于这种满足数字字符串版本号的判断,都是自己封装函数来处理,还经常处理不好,入门php的开发人员还是应该通读一次php手册,至少一次。

针对命令行的扩展readline

Readline 扩展已经加入了 PHP 的官方安装包中。

$input = readline("请输入:"); // 读取命令行交互信息
echo $input, PHP_EOL; // chinese

运行 PHP 代码后,我们就进入了命令提示符等待状态,并且会提示“请输入命令:”,当我们输入了 chinese 并回车之后,输入的内容就保存到了 $line 变量中。

readline扩展还提供了readline_add_history、readline_list_history、readline_clear_history、readline_write_history等函数可以保存输入历史并操作输入历史。

压缩与归档扩展

  • Zip扩展

    此扩展可以让你透明地读写ZIP压缩文档以及它们里面的文件。

    建议使用ZipArchive类库。

    一般zip压缩包操作步骤:创建ZipArchive对象,open一个zip文件压缩包,和打开文件函数fopen一样有打开模式mode设置,然后通过getFromIndex、getFromName等方法读取指定压缩包包中的文件内容,addFile、addFromString等方法写Zip包里的文件,也可以通过extractTo方法来解压整个zip包,还可以通过set相关方法修改压缩包的信息。

    $zip = new ZipArchive();
    $filename = "test.zip";    
    
    if ($zip->open($filename, ZIPARCHIVE::CREATE)!==TRUE) {
        exit("cannot open <$filename>\n");
    }
    
    $zip->setArchiveComment('压缩包说明');
    $zip->setPassword("chinese");
    $zip->addFromString("testfilephp" . time().".txt", "#1 This is a test string added as testfilephp.txt.\n");
    $zip->addFromString("testfilephp2" . time().".txt", "#2 This is a test string added as testfilephp2.txt.\n");
    $zip->addFile(__DIR__ . "/test.php","testfromfile.php");
      
    echo "numfiles: " . $zip->numFiles . "\n";
    echo "status:" . $zip->status . "\n";
    echo "statusSys: " . $zip->statusSys . "\n";
    echo "filename: " . $zip->filename . "\n";
    echo "comment: " . $zip->comment . "\n";    
    $zip->close();
      
    

    打开zip压缩包的模式有:

    • ZIPARCHIVE::CREATE(integer) 如果不存在则创建一个zip压缩包。 注意,如果存在相同名字的zip压缩包,并不是直接报错,而是会往zip压缩包里继续写不同的文件。
    • ZIPARCHIVE::OVERWRITE(integer) 总是以一个新的压缩包开始,此模式下如果已经存在则会被覆盖。
    • ZIPARCHIVE::EXCL(integer) 如果压缩包已经存在,则出错。
    • ZipArchive::RDONLY(integer) 只读模式打开压缩包。 需要php7.4以上。
    • ZIPARCHIVE::CHECKCONS(integer) 对压缩包执行额外的一致性检查,如果失败则显示错误。
  • phar

    • 为什么phar很少有人用?

      PHP5.3 之后支持了类似 Java 的 jar 包,名为 phar。用来将多个 PHP 文件打包为一个文件。这个特性使得 PHP也可以像 Java 一样方便地实现应用程序打包和组件化。一个应用程序可以打成一个 Phar 包,直接放到 PHP-FPM 中运行。

      但是除了composer.phar本身以外,实际应用中,各种PHP开源项目以及composer上的各种包的源代码,这个phar并没有很多使用,不像java的jar包一样用途那么广泛。

      可能由于LAMP开源的思想深入PHP的程序员思维里,PHPer倾向于开源,一方面对于能看到源代码的包会更放心,另一方面是一种传承下来的学习途径,阅读优秀的源代码,甚至有时还想去调整修改源代码。

    • phar常用的三个类库

      phar有三个相关类库:Phar类、PharData类、PharFileInfo类。

      Phar类用于可执行的phar包的操作,而PharData类用于制作不可执行的phar包,PharFileInfo类用于读写及设置phar包信息及文件信息,和Phar类部分方法功能一样。

    • phar包制作

      phar包,和zip压缩包创建是类似的原理,只是phar包支持了php文件可执行,提供了执行入口设置等。

      • 准备一个src目录用于放php源码文件,一个build目录,用于存放编译后的phar包。

      • 在src目录中准备index.php与common.php文件:

        //common.php
        function my_print($data){
            echo "\n".date("Y-m-d H:i:s")."\n";
            echo print_r($data,true);
            echo "\n";
        }
        
        
        //index.php
        include_once "phar://app.phar/common.php";//注意,这里我们使用了一个app.phar的别名,这个别名是创建phar的时候为phar设置的别名。
        
        $ini = [
            "a"=>"apple",
            'b'=>"banana",
            "c"=>"chinese"
        ];
        
        my_print($ini);
        
        
      • 准备创建app.phar包

        //phar.php
        //用于创建app.phar包
        
        $phar = new Phar(__DIR__."/build/app.phar", FilesystemIterator::CURRENT_AS_FILEINFO|FilesystemIterator::KEY_AS_FILENAME,"app.phar");
        
        $phar["index.php"] = file_get_contents(__DIR__ . "/src/index.php");
        $phar["common.php"] = file_get_contents(__DIR__ . "/src/common.php");
        $phar->setStub($phar->createDefaultStub("index.php"));//设置phar入口文件
        //如果还有其他资源文件的话,还可以通过copy函数将需要的资源文件也复制到编译目录build中
        

        执行phar.php脚本后,会在build目录下生成app.phar包文件,如果有报错,注意php.ini中phar.readonly是否设置正确:

        jm@ubuntu:/var/www/html/php-shiyanchang/FunctionsReference/build$ ll
        total 16
        drwxrwxr-x 2 jm jm 4096 Feb 11 15:18 ./
        drwxrwxr-x 4 jm jm 4096 Feb 11 15:14 ../
        -rw-rw-r-- 1 jm jm 7408 Feb 11 15:18 app.phar
        
      • 开启phar读写开关配置

        当我们执行phar.php脚本时,会报Fatal error:

        PHP Fatal error:  Uncaught UnexpectedValueException: creating archive "/var/www/html/php-shiyanchang/FunctionsReference/build/app.phar" disabled by the php.ini setting phar.readonly in /var/www/html/php-shiyanchang/FunctionsReference/phar.php:11
        

        这是因为php.ini中默认phar是只读的,需要将phar.readonly设置为0或Off

        [Phar]
        ; http://php.net/phar.readonly
        phar.readonly = Off
              
        
      • 访问或执行phar包

        如果在cli模式下,我们可以直接执行phar包:

        jm@ubuntu:/var/www/html/php-shiyanchang/FunctionsReference/build$ php app.phar 
        
        2020-02-11 15:21:39
        Array
        (
            [a] => apple
            [b] => banana
            [c] => chinese
        )
        
        

        如果我们尝试在web服务里使用phar包,我们可以创建一个runphar.php这样的php文件,include引入phar包,就可以免去在web server上配置如何解析phar包:

        //runphar.php
        include_once 'build/app.phar';
        

加密扩展

  • 加密安全的随机数字或字符

    如果有需要加密安全的随机数字或字符,官方建议使用random_int、random_bytes,而不是rand函数,当然他们都是伪随机函数。

    echo rand(-1000,1000)."<br />";
    echo random_int(-1000, 1000)."<br />";
    echo bin2hex(random_bytes(2));
    //848
    //-112
    //5cf1
    
  • Hash哈希

    哈希,其实是信息摘要。信息摘要引擎允许使用各种哈希算法直接或增量处理任意长度的信息。

    • hash_aogos,在 PHP 7.4.0 中,hash_algos() 会返回下表所示的算法清单,目前大约有53种算法。比如常用的md5、sha256等
    • hash,最常用的哈希函数,hash(算法 , 数据 , true返回二进制或false返回16进制字符串),默认返回16进制字符串。
    • hash_file,除了数据是一个文件符外,其他和hash函数一样,也就是将给定的文件内容生成哈希值
    • hash_init,这里提到一个增量哈希,hash和hash_file都是一次性将数据或文件内容生成哈希值,增量哈希可以逐步多次通过hash_update等函数,增量填充要要计算哈希的数据或文件或数据流,hash_init,相当于先初始化设置本次哈希的算法等上下文信息,特别是对于hash_hmac需要提供密钥的算法。
    • hash_update,向活跃的哈希运算上下文中填充数据,在一次哈希运算上下文中,可以多次填充数据
    • hash_update_file,hash_update_stream,同hash_update一样,只是数据来源与文件或数据流
    • hash_final,结束本次哈希运算上下文,并返回摘要信息结果。通常是hash_init初始化上下文,hash_update相关函数填充上下文数据,hash_final最后返回哈希摘要结果,同样的有一个raw_output参数用于设置返回二进制或16进制字符串。
    • hash_copy,可以复制一个哈希上下文,不影响上一次的哈希上下文,可以单独用于另外的哈希计算,两个上下文相互不影响。
    • has_hmac,首先我们要了解下hmac是什么,hmac是利用哈希算法,以一个密钥和一个消息为输入,生成一个消息摘要作为输出。hash_hmac就是使用 HMAC 方法生成带有密钥的哈希值。更多参考Hash, MAC,HMAC - Songhan - 博客园
  • Mcrypt扩展

    在php7之前,phper还是很喜欢用到这个扩展的,但:

    官方警告:该特性在PHP 7.1.0中已弃用,在PHP 7.2.0中已删除。

    Mcrypt扩展大都是mcrypt_开头的函数,比如mcrypt_encrypt 、mcrypt_decrypt 、mcrypt_create_iv 等

    这里提出来,最重要的还是传播给大家:

    Warning:本函数已自 PHP 7.1.0 起废弃并将自 PHP 7.2.0 起移除。强烈建议不要使用本函数。

    Warning:本函数已自 PHP 7.1.0 起废弃并将自 PHP 7.2.0 起移除。强烈建议不要使用本函数。

    Warning:本函数已自 PHP 7.1.0 起废弃并将自 PHP 7.2.0 起移除。强烈建议不要使用本函数。

  • mhash扩展

    Note: This extension is obsoleted by Hash. 这个扩展已经过时。

    请使用hash相关函数。

  • OpenSSL

    本扩展使用 OpenSSL 库来对称/非对称加解密,以及 PBKDF2、 PKCS7、 PKCS12、 X509 和其他加密操作。除此之外还提供了 TLS 流的实现。

    openssl相关函数很多,涉及到对称加密、非对称加密,甚至ssl证书,要展开讲可以写好几篇文章,现在通信都需要数据加密防被破解,需要签名防篡改。

    • 对称加密算法

      对称加密常用的算法有:AES 、DES 、3DES 、 IDEA 、 RC2 、 RC5 等,比较常用的是 AES 和 DES 。

    • 非对称加密算法

      非对称加密常用的算法有:RSA 、Elgamal 、ECC 等,RSA 非常常用和普遍,SSL 和一些证书算法都是基于 RSA 。

      非对称的实现需要一对密钥,也就是我们常说的公钥和私钥,比如通过openssl_pkey_new生成私钥,而公钥其实是从私钥中抽取出来的,所以实际上我们进行非对称加解密的时候,私钥和公钥加解密可以相互操作,公钥加密再通过私钥解密,或者私钥加密再通过公钥解密,也就是双方通信都可以做到发送加密数据给对方,同时可以解密对方发送的数据,保证数据不暴露。

    • 经典加密技术:数字信封

      我们平常使用的加密技术,通常是数字信封的方式,就是利用对称加密和非对称加密方式各自的优点。非对称加密的安全性高,但速度慢,而且数据量越大速度越慢,那么我们就用它来加密对称加密的 key ,通常这个 key 不会很大。然后实际的数据实体使用这个对称加密的 key 来进行对称加密提升速度。这样,我们发送给客户端时,就包括两个内容,一个是非对称加密进行加密的 key ,一个使用对称加密进行加密的数据内容。客户端拿到信息后,首先使用非对称加密的密钥解码出对称加密的 key ,然后再使用这个 key 来解密最终的数据内容。

    • 签名与验签

      为了保证数据通信过程中,不会被截获篡改数据,我们需要一种技术来验证数据是否被篡改过,那就是我们常用的签名与验签。

      我们可以通过哈希摘要的方式生成签名并验签,同样OpenSSL也提供了openssl_sign与openssl_verify等函数完成签名与验签操作。

      两者的区别也可以叫做对称与不对称,但这里的对称是指使用了相同密钥或key(不能对外泄露),而openssl的签名与验签还是通过私钥与公钥分别签名与验签,比如使用公钥签名,对方使用私钥验签,或者反过来也可以。

    • 证书

      x509 是标准的公钥证书规范。通过 openssl_csr_sign() 这个函数,为 CSR 进行签名后获得的就是 x509 规范的一个证书内容。在这个证书中是可以提取出公钥信息的,我们可以将这个证书颁发给用户或者客户端,然后由客户端从证书中抽取公钥信息来进行数据加密。

    • 详细的openssl函数使用

      PHP的OpenSSL加密扩展学习(一):对称加密 - 知乎

      PHP的OpenSSL加密扩展学习(二):非对称加密 - 知乎

      PHP的OpenSSL加密扩展学习(三):证书操作 - 知乎

      或者

      php/PHP中OpenSSL扩展之对称加解密

      php/PHP中OpenSSL扩展之非对称加解密

      php/PHP中OpenSSL扩展之证书

  • 密码散列算法函数

    password_hash() 使用足够强度的单向散列算法创建密码的散列。password_hash() 会为每个密码散列自动生成随机的盐值。

    
    $password = "chinese";
    
    $pwdHash = password_hash($password, PASSWORD_DEFAULT);
    
    //$pwdHash2 = password_hash($password, PASSWORD_BCRYPT);
    if(password_verify($password, $pwdHash)){
        echo "密码正确";
    }else{
        echo "密码错误";
    }
    
  • sodium

    Sodium一个易于使用的可为我们提供加密、解密、签名,密码哈希等功能的软件库。除了自身强大的功能外,它还为我们提供了一个兼容API和一个外部API,以进一步的帮助我们提高其可用性。Sodium的目标是提供构建更高级别加密工具所需的所有核心操作。

    php也在第一时间支持了sodium模块,但官方文档正进一步完善中。

    关于openssl与sodium:

    PHP Encryption with Libsodium | Zend by Perforce

    Replacing OpenSSL with Libsodium

数据库扩展

  • mysql扩展

    从 PHP 5.5.0 起这个扩展已经被废弃,并且从 PHP 7.0.0. 开始被移除。作为替代,可以使用 mysqli 或者 PDO_MySQL 扩展代替。

  • mysqli扩展

    mysqli扩展,我们有时称之为MySQL增强扩展,可以用于使用 MySQL4.1.3或更新版本中新的高级特性。mysqli扩展在PHP 5及以后版本中包含。

    相对于mysql扩展的提升主要有:

    • 面向对象接口
    • prepared语句支持(译注:关于prepare请参阅mysql相关文档)
    • 多语句执行支持
    • 事务支持
    • 增强的调试能力
    • 嵌入式服务支持

    关于mysqli的持久化实现:

    从 PHP 5.3 mysqli 扩展开始支持持久化连接。持久化连接已经在 PDO MYSQL 和 ext/mysql 中提供支持。持久化连接的目的在于重用客户端到服务器之间的连接,而不是每次在需要的时候都重新建立一个连接。由于持久化连接可以将已经建立的连接缓存起来,以备后续的使用,所以省去了建立新的连接的开销,因此可以带来性能上的提升。

    不像 mysql 扩展,mysqli 没有提供一个特殊的方法用于打开持久化连接。需要打开一个持久化连接时,你必须在连接时在主机名前增加 p:

    使用持久化连接也会存在一些风险,因为在缓存中的连接可能处于一种不可预测的状态。例如,如果客户端未能正常关闭连接,可能在这个连接上残留了对库表的锁,那么当这个连接被其他请求重用的时候,这个连接还是处于 “有锁的状态”。所以,如果要很好的使用持久化连接,那么要求代码在和数据库进行交互的时候,确保做好清理工作,保证被缓存的连接是一个干净的,没有残留的状态。

    mysqli 扩展的持久化连接提供了内建的清理处理代码。 mysqli 所做的清理工作包括:

    • 回滚处于活动状态的事务
    • 关闭并且删除临时表
    • 对表解锁
    • 重置会话变量
    • 关闭预编译 SQL 语句(在PHP中经常发生)
    • 关闭处理程序
    • 释放通过 GET_LOCK() 获得的锁

    这确保了将连接返回到连接池的时候,它处于一种"干净"的状态,可以被其他客户端进程所使用。

    mysqli 扩展通过自动调用 C-API 函数 mysql_change_user() 来完成这个清理工作。

    自动清理的特性有优点也有缺点。优点是程序员不再需要担心附加的清理代码,因为它们会自动调用。然而缺点就是性能可能会慢一点,因为每次从连接池返回一个连接都需要执行这些清理代码。

    这个自动清理的代码可以通过在编译 php 时定义 MYSQLI_NO_CHANGE_USER_ON_PCONNECT 来关闭。

  • PDO

    PHP 数据对象 (PDO) 扩展为PHP访问数据库定义了一个轻量级的一致接口。实现 PDO 接口的每个数据库驱动可以公开具体数据库的特性作为标准扩展功能。 注意利用 PDO 扩展自身并不能实现任何数据库功能;必须使用一个 具体数据库的 PDO 驱动 来访问数据库服务。

    PDO 提供了一个 数据访问 抽象层,这意味着,不管使用哪种数据库,都可以用相同的函数(方法)来查询和获取数据。 PDO 不提供 数据库 抽象层;它不会重写 SQL,也不会模拟缺失的特性。如果需要的话,应该使用一个成熟的抽象层。

    当然,PDO也有它自己的先进性,比如一个干净的,简单的,可移植的API,它最主要的缺点是会限制让你不能使用后期MySQL服务端提供所有的数据库高级特性。比如,PDO不允许使用MySQL支持的多语句执行。

    • 连接建立

      连接是通过创建 PDO 基类的实例而建立的。不管使用哪种驱动程序,都是用 PDO 类名。构造函数接收用于指定数据库源(所谓的 DSN)以及可能还包括用户名和密码(如果有的话)的参数。

      $dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass);
      
    • 连接销毁

      连接数据成功后,返回一个 PDO 类的实例给脚本,此连接在 PDO 对象的生存周期中保持活动。要想关闭连接,需要销毁对象以确保所有剩余到它的引用都被删除,可以赋一个 NULL 值给对象变量。如果不明确地这么做,PHP 在脚本结束时会自动关闭连接。

    • 持久连接

      很多 web 应用程序通过使用到数据库服务的持久连接获得好处。持久连接在脚本结束后不会被关闭,且被缓存,当另一个使用相同凭证的脚本连接请求时被重用。持久连接缓存可以避免每次脚本需要与数据库回话时建立一个新连接的开销,从而让 web 应用程序更快。

      $dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass, array(
          PDO::ATTR_PERSISTENT => true
      ));
      

      注意:在使用表锁及事务的情况下,最好还是不要使用持久化的数据库连接。在持久连接中使用数据表锁时,如果脚本不管什么原因无法释放该数据表锁,其随后使用相同连接的脚本将会被持久的阻塞。

    • 事务与自动提交

      事务通常是通过把一批更改"积蓄"起来然后使之同时生效而实现的;这样做的好处是可以大大地提供这些更改的效率。换句话说,事务可以使脚本更快,而且可能更健壮。

      不幸的是,并非每种数据库都支持事务,因此当第一次打开连接时,PDO 需要在所谓的"自动提交"模式下运行。自动提交模式意味着,如果数据库支持,运行的每个查询都有它自己的隐式事务,如果数据库不支持事务,则没有。如果需要一个事务,则必须用 PDO::beginTransaction() 方法来启动。如果底层驱动不支持事务,则抛出一个 PDOException 异常(不管错误处理设置是怎样的,这都是一个严重的错误状态)。一旦开始了事务,可用 PDO::commit() 或 PDO::rollBack()来完成,这取决于事务中的代码是否运行成功。

      开启一个显示事务,当脚本结束或连接即将被关闭时,如果尚有一个未完成的事务,那么 PDO 将自动回滚该事务。这种安全措施有助于如果没有显式地提交事务,在脚本意外终止时避免出现不一致的情况,那么假设是某个地方出错了,所以执行回滚来保证数据安全。

      比如我们通常会在try语句里开启事务,完成业务逻辑,并提交事务,而在异常捕获catch语句中回滚事务。

    • 预处理语句

      预处理语句有两个好处:

      1、查询仅需解析一次,但可以用不同的参数执行多次。数据库查询是要经过语句分析、编译、优化、执行,而预处理语句可以避免重复分析、编译、优化时间,使得占用更少资源并运行的更快。

      2、提供给预处理语句的参数不需要用引号,驱动程序会自动处理,可以确保SQL注入安全问题。当然sql语句存在由用户输入的部分,那么也需要进行转义,否则仍然存在注入问题。

      预处理语句可以使用占位符:? 或者 :name,:value

      $stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (:name, :value)");
      
      $stmt->bindParam(':name', $name);
      $stmt->bindParam(':value', $value);
      
      // 插入一行
      $name = 'one';
      $value = 1;
      $stmt->execute();
      
      //  用不同的值插入另一行
      $name = 'two';
      $value = 2;
      $stmt->execute();
      
      
      //占位符:?
      $stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (?, ?)");
      
      $stmt->bindParam(1, $name);
      $stmt->bindParam(2, $value);
      
      // 插入一行
      $name = 'one';
      $value = 1;
      $stmt->execute();
            
      $stmt = $dbh->prepare("SELECT * FROM REGISTRY where id = ?");
      
      if($stmt->execute(array($_GET['ids']))){
          while ($row = $stmt->fetch()) {
              print_r($row);
          }            
      }
      
    • POD驱动

      PDO的MySQL驱动并不是一套API,至少从PHP程序员的角度来看是这样的。实际上,PDO的MySQL驱动处于PDO自己的下层,提供了特定的Mysql功能。程序员直接调用PDO的API,而PDO使用了PDO的MySQL驱动完成与MySQL服务器端的交互。PDO的MySQL驱动是众多PDO驱动中的一个。其他可用的PDO驱动包括Firebird,PostgreSQL等等。

      • MS SQL Server
      • Firebird
      • IBM DB2
      • MySQL
      • Oracle
      • PostgreSQL
      • SQLite等
  • 各数据库系统对应的扩展

    有OCI8(oracle)、DB2、Firebird、MongoDB、PostgreSQL、SQLite3、tokyo_tyrant等等主流数据库

PHP中的数据库连接持久化 - 知乎

日期与时间相关扩展

  • 历法calendar

    历法扩展集包括了一系列用于在不同历法间进行转换的函数。

    在国内大部分没有什么用途。

  • 日期和时间

    • DateTimeInterface接口

      DateTimeInterface接口是为了给类DateTime类和DateTimeImmutable类做类型约束用的。

      该接口定义了6个方法:

      • diff($datetime2, $absolute = false):返回两个DateTime对象的差值。接受两个参数,第一个为要进行比较的日期DateTimeInterface对象,第二个参数为可选的表示是否差值必须是正数,如果为true则总是返回正数。默认为false。返回一个 DateInterval对象来表示两个日期的差值,若比较失败则返回false。
      • format($format):返回根据指定格式格式化后的日期。接受一个参数为日期的格式字符串。若失败则返回false。此方法不受区域设置影响。
      • getOffset:以秒为单位返回日期与当前时区偏移量。
      • getTimestamp:获取unix时间戳。等同于strtotime函数。
      • getTimezone:返回日期的时区信息类DateTimeZone的对象。
      • __wakeup:魔术方法,返回一个实例化的DateTime对象。
    • DateTime 类

      PHP 5.2后新增的处理时间格式类,可以输出、转换、计算时间,很好的替代了 date() 、strtotime()等函数。

      public __construct ([ string $time = "now" [, DateTimeZone $timezone = NULL ]] )
      

      构造返回一个DateTime对象。

      除了实现DateTimeInterface接口6个方法外,DateTime类也有自己的一些方法,比如add、sub、modify、setTime、setDate、setTimestamp、setTimezone 等

    • DateTimeImmutable类

      DateTimeImmutable类是 PHP 5.5后新增的处理时间格式类,该类与DateTime相同,只是它从不修改自己,而是返回一个新对象。

    • DateTimeZone类

      DateTimeZone 表示时区的类。

      可以通过getLocation 、getName 获得时区的相关信息。

    • DateInterval类

      表示一个时间间隔的类。

      一个时间间隔表示固定量的时间(多少年,月,天,小时等), 也可以表示一个字符串格式的相对时间, 当表示相对时间的时候,字符串格式是DateTime类的构造函数所支持的格式。

      时间间隔表示格式:构造函数参数 string $duration 如:P2W。格式以字母P开头,每个持续时间段由一个整数值表示,后跟一个间隔标志符。 如果持续时间包含时间元素(表中的HMS),则在规范的该部分之前加上字母T。

      周期指示 描述
      Y years
      M months
      D days
      W weeks. These get converted into days,so can not be combined with D.
      H hours
      M minutes
      S seconds

      范例:注意P和T

      $interval = new DateInterval('P2Y4DT6H8M');
      var_dump($interval);
      
      
    • DatePeriod 类

      DatePeriod 类表示一个时间周期。

      一个时间周期可以用来在给定的一段时间之内,以一定的时间间隔进行迭代。

    • 范例

      $date = new DateTimeImmutable();
      echo $date->getTimestamp().PHP_EOL;
      echo $date->format("Y-m-d H:i:s").PHP_EOL;
      echo time().PHP_EOL;
      echo date("Y-m-d H:i:s",time()).PHP_EOL;
      
      $timestr = "2020-12-12 12:12:10";
      $date = new DateTimeImmutable($timestr);
      $time = $date->getTimestamp();
      echo PHP_EOL;
      echo $time.PHP_EOL;
      echo date("Y-m-d H:i:s",$time).PHP_EOL;
      echo strtotime($timestr).PHP_EOL;
      

      输出:

      
      1615711430
      2021-03-14 16:43:50
      1615711430
      2021-03-14 16:43:50
      
      1607746330
      2020-12-12 12:12:10
      1607746330
      
      

      DatePeriod与DateInterval的区别哪里?可以看下面的例子就更清楚两个类的用途了:

      $start = new DateTime('2020-01-01');//定义一个时间周期的开始时间
      $interval = new DateInterval('P7D');//初始化一个时间间隔7天
      $end = new DateTime('2020-01-31');//定义一个时间周期的结束时间
      
      $period = new DatePeriod($start, $interval, $end,DatePeriod::EXCLUDE_START_DATE);//通过开始时间、结束时间、时间间隔,初始化一个时间周期对象
      
      //通过遍历DatePeriod对象
      //打印该时间段内所有的重复日期。
      //注意,在EXCLUDE_START_DATE下,2020-07-01不打印。
      foreach ($period as $date) {
          echo $date->format('Y-m-d')."\n";
      }
      

      输出:

      2020-01-08
      2020-01-15
      2020-01-22
      2020-01-29
      
    • datetime函数

      datetime函数在php代码中用都很广泛,特别是date、strtotime、mktime、time、microtime等函数,很多函数都可以通过以上的接口和5个类来实现相应的逻辑。

      当然像time、microtime获取当下的时间戳还是很简便的。

      但对于strtotime,如果需要时区信息时,我们建议考虑功能更强大的DateTimeImmutable类来实现。

      使用时间和日期相关类,更符合编程思想。

      • date — 格式化一个本地时间/日期
      • getdate — 取得日期/时间信息
      • gettimeofday — 取得当前时间
      • gmdate — 格式化一个 GMT/UTC 日期/时间
      • gmmktime — 取得 GMT 日期的 UNIX 时间戳
      • gmstrftime — 根据区域设置格式化 GMT/UTC 时间/日期
      • idate — 将本地时间日期格式化为整数
      • localtime — 取得本地时间
      • microtime — 返回当前 Unix 时间戳和微秒数
      • mktime — 取得一个日期的 Unix 时间戳
      • strftime — 根据区域设置格式化本地时间/日期
      • strptime — 解析由 strftime 生成的日期/时间
      • strtotime — 将任何字符串的日期时间描述解析为 Unix 时间戳
      • time — 返回当前的 Unix 时间戳
    • 时间格式

      参考官方:PHP: Relative Formats - Manual

  • HRTime

    HRTime扩展实现了一个高分辨率的秒表类。它在不同的平台上使用最好的api,这将分辨率提高到纳秒。它还可以使用底层api提供的低电平刻度来实现自定义秒表。

文件系统相关扩展

  • 目录

    Directory类

    注意:Directory 实例是通过调用 dir() 函数创建的,而不是 new 操作符。

    • Directory::close — 释放目录句柄
    • Directory::read — 从目录句柄中读取条目
    • Directory::rewind — 倒回目录句柄

    Directory类全貌:

    Directory {
    
        /* 属性 */
    
        public string $path;
    
        public resource $handle;
    
        /* 方法 */
    
        public close([ resource $dir_handle] ) : void
    
        public read([ resource $dir_handle] ) : string
    
        public rewind([ resource $dir_handle] ) : void
    }
    

    目录函数

    • chdir — 改变目录
    • chroot — 改变根目录
    • closedir — 关闭目录句柄
    • dir — 返回一个 Directory 类实例
    • getcwd — 取得当前工作目录
    • opendir — 打开目录句柄
    • readdir — 从目录句柄中读取条目
    • rewinddir — 倒回目录句柄
    • scandir — 列出指定路径中的文件和目录

    opendir、readdir、scandir、closedir等目录函数实现和Directory类相同的功能。

    $dir = "/tmp/";
    if ($handle = opendir($dir)) {
        echo "Directory handle: $handle\n";
        echo "Files:\n";
    
        /* 这是正确地遍历目录方法 */
        while (false !== ($file = readdir($handle))) {
            echo "$file\n";
        }
    
        closedir($handle);
          
    }
    $files = scandir($dir);
    print_r($files);
    
  • Fileinfo

    本模块中的函数通过在文件的给定位置查找特定的 magic.mime来猜测文件的内容类型以及编码。虽然不是百分百的精确,但是通常情况下能够很好的工作。

    常用的函数有:finfo_open、finfo_file、finfo_close、mime_content_type

    $finfo = finfo_open(FILEINFO_MIME_TYPE); // 返回 mime 类型资源
    //遍历当下目录文件
    foreach (glob("*") as $filename) {
        echo finfo_file($finfo, $filename) . "\n";//判断每个文件的mimetype
    }
    finfo_close($finfo);
    
    echo "\n\n";
    echo mime_content_type('test.zip') . "\n";
    echo mime_content_type('test.php') . "\n";
    

    php还提供了finfo类,也是对上面函数的改造,采用对象的方式实现。

  • xattr扩展

    xattr扩展允许对文件系统上的扩展属性进行操作。

    需要额外安装pecl扩展。

    xattr扩展函数很简单:

    • xattr_set:为文件设置扩展属性信息
    • xattr_get:获取文件曾设置过的扩展属性信息
    • xattr_remove:删除文件扩展属性信息
    • xattr_list:文件扩展属性信息列表
    • xattr_supported:检查文件系统是否支持扩展信息
    
    $file = 'some_file';
    if(xattr_supported($file)){
        echo "文件系统支持扩展属性信息xattr\n";
    }else{
        echo "文件系统不支持扩展属性信息xattr\n";
        exit;
    }
    
    xattr_set($file,'Artist',"Someone");
    xattr_set($file,'Rank',"123");
    
    echo xattr_get($file,"Rank",XATTR_ROOT);
    
    $attributes = xattr_list($file);
    
    foreach ($attributes as $attr_name) {
        xattr_remove($file, $attr_name);
    }
    
  • xdiff

    xdiff扩展使您能够创建和应用补丁文件,其中包含不同版本文件之间的差异。

    这个扩展支持两种操作模式:字符串和文件,以及两种不同的补丁格式:统一和二进制。统一补丁非常适合于文本文件,因为它们易于阅读且易于检查。对于像档案或图像这样的二进制文件,二进制补丁将是足够的选择,因为它们是二进制安全的,并且可以很好地处理不可打印的字符。

    需要额外安装pecl扩展。

  • 文件系统

    文件系统是文件系统相关扩展的核心部分。有很多很常用的函数,这里将看起来熟悉又陌生的函数再梳理一下:

    • basename — 返回路径中的文件名部分

      basename() 纯粹基于输入字符串操作,它不会受实际文件系统和类似 “..” 的路径格式影响。

      在 Windows 中,斜线(/)和反斜线(\)都可以用作目录分隔符。在其它环境下是斜线(/)。dirname函数也一样。

      echo basename("/etc/sudoers.d", ".d").PHP_EOL;
      //1) sudoers
      
    • dirname — 返回路径中的目录部分

      给出一个包含有指向一个文件的全路径的字符串,本函数返回去掉文件名后的目录名,且目录深度为 levels 级,也就是要向上的父目录数量,默认是上1级(levels)

      dirname() 纯粹基于输入字符串操作,且与斜线有关。在 Windows 中,斜线(/)和反斜线(\)都可以用作目录分隔符。在其它环境下是斜线(/)。

      echo dirname("/usr/local/lib"); 
      //输出:/usr/local
      echo dirname("/usr/local/lib", 2); 
      //输出:/usr
      
    • pathinfo — 返回文件路径的信息

      pathinfo( string $path[, int $options = PATHINFO_DIRNAME | PATHINFO_BASENAME | PATHINFO_EXTENSION | PATHINFO_FILENAME] ) : mixed
      

      pathinfo() 返回一个关联数组包含有 path 的信息。返回关联数组还是字符串取决于 options。

      同时关注:dirname、basename、realpath、parse_url函数

    • chgrp — 改变文件所属的组

      只有超级用户可以任意修改文件的组,其它用户可能只能将文件的组改成该用户自己所在的组。

    • chmod — 改变文件模式

      第二个参数只支持八进制:0755,0644等

      chmod("/somedir/somefile", 0755);  // 八进制数,正确的 mode 值
      chmod("/somedir/somefile", 755);   // 十进制数,可能不对
      chmod("/somedir/somefile", "u+rwx,go+rx"); // 字符串,不对
      
    • chown — 改变文件的所有者

      只有超级用户可以改变文件的所有者。

    • clearstatcache — 清除文件状态缓存

      当使用 stat(),lstat() 或者任何列在受影响函数表(见下面)中的函数时,PHP 将缓存这些函数的返回信息以提供更快的性能。然而在某些情况下,你可能想清除被缓存的信息。例如如果在一个脚本中多次检查同一个文件,而该文件在此脚本执行期间有被删除或修改的危险时,你需要清除文件状态缓存。这种情况下,可以用 clearstatcache() 函数来清除被 PHP 缓存的该文件信息。

    • copy — 拷贝文件

    • delete — 参见 unlink 或 unset

      在 PHP 语言里,没有 delete 关键词或函数。在这里,你若要删除文件,可以使用 unlink()。在本地作用域删除变量可使用 unset()。

    • disk_free_space — 返回目录中的可用空间

    • disk_total_space — 返回一个目录的磁盘总大小

    • diskfreespace — disk_free_space 的别名

    • fclose — 关闭一个已打开的文件指针

    • feof — 测试文件指针是否到了文件结束的位置

    • fflush — 将缓冲内容输出到文件

    • fgetc — 从文件指针中读取字符

      返回一个包含有一个字符的字符串,该字符从 handle 指向的文件中得到。碰到 EOF 则返回 FALSE。

    • fgets — 从文件指针中读取一行

      从 handle 指向的文件中读取一行并返回长度最多为 length - 1 字节的字符串。碰到换行符(包括在返回值中)、EOF 或者已经读取了 length - 1 字节后停止(看先碰到那一种情况)。如果没有指定 length,则默认为 1K,或者说 1024 字节。

      while (($buffer = fgets($handle, 4096)) !== false) {
          echo $buffer;
      }
      
    • fgetss — 从文件指针中读取一行并过滤掉 HTML 标记

      和 fgets() 相同,只除了 fgetss() 尝试从读取的文本中去掉任何 HTML 和 PHP 标记。

      $handle = fopen("./test.html","r");
      if($handle){
          while(false !== ($line = fgetss($handle, 1024))){
              echo $line.PHP_EOL;
          }
      }
      
    • fread — 读取文件(可安全用于二进制文件)

      可安全用于二进制文件。

    • fputs — fwrite 的别名

      可安全用于二进制文件。

    • fwrite

      可安全用于二进制文件。

      fwrite() 把 string 的内容写入文件指针 handle 处。

    • fgetcsv — 从文件指针中读入一行并解析 CSV 字段

      和 fgets() 类似,只除了 fgetcsv() 解析读入的行并找出 CSV 格式的字段然后返回一个包含这些字段的数组。

      返回一个数组。

      while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
          ...
      }
      
    • fputcsv — 将行格式化为 CSV 并写入文件指针

      fputcsv() 将一行(用 fields 数组传递)格式化为 CSV 格式并写入由 handle 指定的文件

    • file_exists — 检查文件或目录是否存在

      对于符号链接的文件,如果指向文件不存在,即使符号链接文件存在,该函数仍然判断为文件不存在。

    • file_get_contents — 将整个文件读入一个字符串

      和 file() 一样,只除了 file_get_contents() 把文件读入一个字符串。

      // Read 14 characters starting from the 21st character
      $section = file_get_contents('./people.txt', NULL, NULL, 20, 14);
      

      虽然该函数支持stream contexts,但对于http协议,我们还是建议采用比较友好的包,比如guzzle

    • file_put_contents — 将一个字符串写入文件

      和依次调用 fopen(),fwrite() 以及 fclose() 功能一样。

      如果filename不存在,则创建该文件。否则,现有的文件将被覆盖,除非设置了FILE_APPEND标志。

    • file — 把整个文件读入一个数组中

      file( string $filename[, int $flags = 0[, resource $context]] ) : array        
      

      与file_get_content是一样的,只是返回的类型不一样,一个是数组,一个是字符串。

      在$flags参数可以设置FILE_SKIP_EMPTY_LINES跳过空行,设置FILE_IGNORE_NEW_LINES 忽略换行符。

      同样也支持流上下文:

      $trimmed = file('http://www.example.com/', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
      
    • fileatime — 取得文件的上次访问时间

    • filectime — 取得文件的 inode 修改时间

      注意是文件inode的修改时间,而不是文件的创建时间,也不是web上所想要的文件修改时间。

      在大多数 Unix 文件系统中,当一个文件的 inode 数据被改变时则该文件被认为是修改了。也就是说,当文件的权限,所有者,所有组或其它 inode 中的元数据被更新时。

      注意某些 Unix 说明文本中把 ctime 说成是该文件建立的时间,这是错的。在大多数 Unix 文件系统中没有 Unix 文件的建立时间。

    • filegroup — 取得文件的组

    • fileinode — 取得文件的 inode

    • filemtime — 取得文件修改时间

      本函数返回文件中的数据块上次被写入的时间,也就是说,文件的内容上次被修改的时间。

      这个是区别于filectime函数(获取inode的上次修改时间)。

      注意:此函数的结果会被缓存。有需要时,可以紧跟clearstatcache函数。

    • fileowner — 取得文件的所有者

    • fileperms — 取得文件的权限

    • filesize — 取得文件大小

    • filetype — 取得文件类型

      注意:以上从fileatime开始到filetype函数,这些函���都是和文件相关信息的获取,都会被缓存。

    • flock — 轻便的访问文件锁定

      flock() 允许执行一个简单的可以在任何平台中使用的读取/写入模型。

      在文件资源句柄关闭时不会自动解锁,需要手动解锁。

      flock( resource $handle, int $operation[, int &$wouldblock] ) : bool
      

      operation 可以是以下值之一:

      • LOCK_SH取得共享锁定(读取的程序)。
      • LOCK_EX 取得独占锁定(写入的程序。
      • LOCK_UN 释放锁定(无论共享或独占)。
    • fnmatch — 用模式匹配文件名

    • fopen — 打开文件或者 URL

      fopen() 将 filename 指定的名字资源绑定到一个流上。

      • ‘r+’ 读写方式打开,将文件指针指向文件头
      • ‘w+’ 读写方式打开,将文件指针指向文件头并将文件大小截为零如果文件不存在则尝试创建之
      • ‘a+’ 读写方式打开,将文件指针指向文件末尾如果文件不存在则尝试创建之
      • ‘b’ 打开是否为二进制,用“b”标识;可以结合rb、wb、ab
      • ‘t’ 打开为文本文件,可以结合rt、wt、at

      为移植性考虑,强烈建议在用 fopen() 打开文件时总是使用 ‘b’ 标记。

      $handle = fopen("/home/rasmus/file.gif", "wb");
      
    • fpassthru — 输出文件指针处的所有剩余数据

    • fscanf — 从文件中格式化输入

      每次调用 fscanf() 都会从文件中读取一行。

      while ($userinfo = fscanf($handle, "%s\t%s\t%s\n")) {
         list ($name, $profession, $countrycode) = $userinfo;
          //... do something with the values
      }
      
    • fseek — 在文件指针中定位

    • fstat — 通过已打开的文件指针取得文件信息

      获取由文件指针 handle 所打开文件的统计信息。本函数和 stat() 函数相似,除了它是作用于已打开的文件指针而不是文件名。

    • ftell — 返回文件指针读/写的位置

    • ftruncate — 将文件截断到给定的长度

    • glob — 寻找与模式匹配的文件路径

      foreach (glob("/tmp/*.php") as $filename) {
          echo "$filename size " . filesize($filename) . PHP_EOL;
      }
      
    • is_dir — 判断给定文件名是否是一个目录

    • is_executable — 判断给定文件名是否可执行

    • is_file — 判断给定文件名是否为一个正常的文件

      因为 PHP 的整数类型是有符号整型而且很多平台使用 32 位整型,对 2GB 以上的文件,一些文件系统函数可能返回无法预期的结果。

    • is_link — 判断给定文件名是否为一个符号连接

    • is_readable — 判断给定文件名是否可读

      记住 PHP 也许只能以运行 webserver 的用户名(比如 ‘nobody’,‘www-data’等)来访问文件.

    • is_uploaded_file — 判断文件是否是通过 HTTP POST 上传的

    • is_writable — 判断给定的文件名是否可写

    • is_writeable — is_writable 的别名

    • lchgrp — 修改符号链接的所有组

    • lchown — 修改符号链接的所有者

    • link — 建立一个硬连接

    • linkinfo — 获取一个连接的信息

    • lstat — 给出一个文件或符号连接的信息

      获取由 filename 指定的文件或符号连接的统计信息。

      本函数和 stat() 函数相同,只除了如果 filename 参数是符号连接的话,则该符号连接的状态被返回,而不是该符号连接所指向的文件的状态。

      注意:符号链接文件(不是硬链接)和指向文件的inode是不一样的,所以stat和lstat对于同一个符号链接文件输出的统计信息是不一样的,stat统计的是符号链接文件指向的源文件,lstat统计的是符号链接本身文件。

    • mkdir — 新建目录

      一定要确保有操作权限,另外mkdir第二个参数支持mode的修改,第三个参数支持嵌套创建不存在的目录。

      if (!mkdir($structure, 0777, true)) {
          die('Failed to create folders...');
      }
      
    • move_uploaded_file — 将上传的文件移动到新位置

    • parse_ini_file — 解析一个配置文件

      parse_ini_file() 载入一个由 filename 指定的 ini 文件,并将其中的设置作为一个联合数组返回。

      注意:ini 文件的结构和 php.ini 的相似。

      比如:

      ; This is a sample configuration file
      ; Comments start with ';', as in php.ini
      
      [first_section]
      one = 1
      five = 5
      animal = BIRD
      
      [second_section]
      path = "/usr/local/bin"
      URL = "http://www.example.com/~username"
      

      第二个参数为true支持返回多维数组:

      $ini_array = parse_ini_file("sample.ini", true);
      print_r($ini_array);
      
      输出:
      Array
      (
          [first_section] => Array
              (
                  [one] => 1
                  [five] => 5
                  [animal] => Dodo bird
              )
      
          [second_section] => Array
              (
                  [path] => /usr/local/bin
                  [URL] => http://www.example.com/~username
              )         
      
      )
      
    • parse_ini_string — 解析配置字符串

      同parse_ini_file,只不过输入是字符串而不是ini文件。

      字符串格式仍然与php.ini类似。

    • popen — 打开进程文件指针

      返回一个和 fopen() 所返回的相同的文件指针,只不过它是单向的(只能用于读或写)并且必须用 pclose() 来关闭。此指针可以用于 fgets(),fgetss() 和 fwrite()。当模式为 ‘r’,返回的文件指针等于命令的 STDOUT,当模式为 ‘w’,返回的文件指针等于命令的 STDIN。

      $handle = popen("/bin/ls", "r");
      

      如果需要双向支持,使用 proc_open()。

    • pclose — 关闭进程文件指针

    • readfile — 输出文件

      读取文件并写入到输出缓冲。

    • readlink — 返回符号连接指向的目标

      readlink() 和同名的 C 函数做同样的事,返回符号连接的内容。

      符号连接的内容其实是指向文件的名称。

    • realpath_cache_get — 获取真实目录缓存的详情

    • realpath_cache_size — 获取真实路径缓冲区的大小

    • realpath — 返回规范化的绝对路径名

      就是绝对路径的返回。

    • rename — 重命名一个文件或目录

      尝试把 oldname 重命名为 newname,必要时会在不同目录间移动。如果重命名文件时 newname 已经存在,将会覆盖掉它。如果重命名文件夹时 newname 已经存在,本函数将导致一个警告。

    • rewind — 倒回文件指针的位置

      倒回的意思就是将 handle 的文件位置指针设为文件流的开头。

    • rmdir — 删除目录

      和linux命令rmdir是一样的,尝试删除 dirname 所指定的目录。该目录必须是空的,而且要有相应的权限。

    • set_file_buffer — stream_set_write_buffer 的别名

    • stat — 给出文件的信息

      获取由 filename 指定的文件的统计信息。如果 filename 是符号连接,则统计信息是关于被连接文件本身的,而不是符号连接。可以参考lstat。

    • symlink — 建立符号连接

      首先要弄清楚硬连接与符号连接的区别。

      通过link函数创建硬连接。

    • tempnam — 建立一个具有唯一文件名的文件

      在指定目录中建立一个具有唯一文件名的文件。如果该目录不存在,tempnam() 会在系统临时目录中生成一个文件,并返回其文件名。

    • tmpfile — 建立一个临时文件

      以读写(w+)模式建立一个具有唯一文件名的临时文件,返回一个文件句柄。

      文件会在关闭后(用 fclose())自动被删除,或当脚本结束后。

    • touch — 设定文件的访问和修改时间

      touch( string $filename[, int $time = time()[, int $atime]] ) : bool
      

      尝试将由 filename 给出的文件的访问和修改时间设定为给出的 time。注意访问时间总是会被修改的,不论有几个参数。

    • umask — 改变当前的 umask

      不清楚linux的umask的话,不建议随便改动。Linux umask命令 | 菜鸟教程

      umask() 将 PHP 的 umask 设定为 mask & 0777 并返回原来的 umask。当 PHP 被作为服务器模块使用时,在每个请求结束后 umask 会被恢复。

      假设当前系统的umask是022,则通过mkdir创建目录的权限为:

      "drwxr-xr-x" = "777-022 = 755"
      
    • unlink — 删除文件

国际化与字符编码支持

  • GetText国际化解决方案

    • 待国际化源码文件i18n.php

      文件中有两行gettext / _ 文本输出:

      //设置language为zh_CH
      $lang = "zh_CN";//linux不支持zh-Hans,所以gettext、php都不支持。使用locale -a可以看到os支持的语言文字国家地区码
      putenv("LANG=".$lang);//ubuntu 需要,centos不需要此行
      setlocale(LC_ALL, $lang.'.utf8');//ubuntu 需要.utf8,centos可有可无
      
      // Specify location of translation tables
      bindtextdomain("test", dirname(__DIR__)."/locale");
      // Choose domain
      textdomain("test");
      
      // Translation is looking for in locale/zh_CN/LC_MESSAGES/test.mo
      
      // Print a test message
      echo gettext("Welcome to New World!");
      
      // Or use the alias _() for gettext()
      echo _("Have a nice day!");
      
    • po文件制作

      我们采用简单便捷的poedit工具。

      • 1、文件-新建,选择目标语言,比如zh_CN
      • 2、从源代码中提取。配置翻译属性,比如项目名称版本、复数形式、字符集、源代码字符集等,字符集比如UTF-8
      • 3、如果是目标翻译是中文,复数形式填写:nplurals=2; plural=(n!=1);
      • 4、源路径,也就是要从哪个文件或目录自动提取需要翻译的文本内容,工具会自动提取形成列表
      • 5、逐行翻译,翻译结束
      • 6、文件-编译为MO文件
      • 7、得到test.po与对应的test.mo文件
      • 8、将po与mo两个文件放入对应的目录,比如:locale/zh_CN/LC_MESSAGES/test.mo

      locale目录结构如下:

      I:\SRC\PHP-SHIYANCHANG\LOCALE
      \---zh_CN
          \---LC_MESSAGES
                  test.mo
                  test.po
      
  • iconv

    • iconv_get_encoding — 获取 iconv 扩展的内部配置变量
    • iconv_mime_decode_headers — 一次性解码多个 MIME 头字段
    • iconv_mime_decode — 解码一个MIME头字段
    • iconv_mime_encode — Composes a MIME header field
    • iconv_set_encoding — 为字符编码转换设定当前设置
    • iconv_strlen — 返回字符串的字符数统计
    • iconv_strpos — Finds position of first occurrence of a needle within a haystack
    • iconv_strrpos — Finds the last occurrence of a needle within a haystack
    • iconv_substr — 截取字符串的部分
    • iconv — 字符串按要求的字符编码来转换
    • ob_iconv_handler — 以输出缓冲处理程序转换字符编码
  • 多字节字符串

    虽然许多语言每个必要字符都能一对一映射到 8 比特(bit)的值,但也有好几种语言需要非常多的字符来书面通讯,以至于它们的编码范围不能仅仅包含在一个字节里(一个字节 Byte 由 8 比特 bit 构成。每一比特仅能包含两种不同的值: 1 或 0。所以,一字节仅能够表示 256 种不同的值,即 2 的八次方)。开发多字节字符编码方案是为了在基于字节的常规编码系统中表达超过 256 个字符。 比如说汉字编码,由于汉字较多,一个字节无法完全表达,所以出现了由2个或3个字节表示的汉字字符。

    在操作(trim、split、splice 等等)多字节编码的字符串的时候,由于在这种编码方案下,两个或多个连续字节可能只表达了一个字符,所以我们需要使用专门的函数。否则,当我们不能将检测多字节字符串的函数应用到这个字符串的时候,它可能无法检测多字节字符的起始位置,并以乱码字符串结尾,基本丢失了它原来的意思。

    mbstring 提供了针对多字节字符串的函数,能够帮你处理 PHP 中的多字节编码。除此以外,mbstring 还能在可能的字符编码之间相互进行编码转换。为了方便起见,mbstring 设计成了处理基于 Unicode 的编码,类似 UTF-8、UCS-2 及诸多单字节的编码。

    mb_多字节函数大多与普通字符串函数功能是相似的,除了多字节。

    • mb_ord — Get code point of character

    • mb_chr — Get a specific character

      这两个函数在php7.2以后的版本生效。

      echo mb_ord("中");//20013
      echo mb_chr(20018);//串
      
    • mb_convert_case — 对字符串进行大小写转换

      mode转换的模式。它可以是 MB_CASE_UPPER、 MB_CASE_LOWER 和 MB_CASE_TITLE 的其中一个。MB_CASE_TITLE是首字母大写的形式。

      print_r(mb_convert_case($str,MB_CASE_TITLE));//i Am A Chinese.
      
    • mb_strtolower — 使字符串小写

    • mb_strtoupper — 使字符串大写

    • mb_split — 使用正则表达式分割多字节字符串

    • mb_str_split — Given a multibyte string, return an array of its characters

      > php7.4

      相对于mb_split支持encoding参数

    • mb_strcut — 获取字符的一部分

      mb_strcut() 和 mb_substr() 类似,都是从字符串中提取子字符串,但是按字节数来执行,而不是字符个数。如果截断位置位于多字节字符两个字节的中间,将于该字符的第一个字节开始执行。这也是和 substr() 函数的不同之处,后者简单地将字符串在字节之间截断,这将导致一个畸形的字节序列。

      $str = "我是一名中国人。i am a chinese.";
      //echo mb_ord("中");
      
      echo mb_strcut($str, 0,6);
      
      echo "<br />";
      
      echo mb_substr($str, 0,6);
      echo "<br />";
            
      print_r(mb_split("一名", $str));
      

      输出:

      我是
      我是一名中国
      Array
      (
          [0] => 我是
          [1] => 中国人。i am a chinese.
      )
      
    • mb_strimwidth — 获取按指定宽度截断的字符串

    • mb_stripos — 大小写不敏感地查找字符串在另一个字符串中首次出现的位置

    • mb_stristr — 大小写不敏感地查找字符串在另一个字符串里的首次出现

    • mb_strlen — 获取字符串的长度

    • mb_strpos — 查找字符串在另一个字符串中首次出现的位置

    • mb_strrchr — 查找指定字符在另一个字符串中最后一次的出现

    • mb_strrichr — 大小写不敏感地查找指定字符在另一个字符串中最后一次的出现

    • mb_strripos — 大小写不敏感地在字符串中查找一个字符串最后出现的位置

    • mb_strrpos — 查找字符串在一个字符串中最后出现的位置

    • mb_strstr — 查找字符串在另一个字符串里的首次出现

    • mb_strwidth — 返回字符串的宽度

    • mb_substitute_character — 设置/获取替代字符

    • mb_substr_count — 统计字符串出现的次数

    • mb_substr — 获取部分字符串

  • Pshell

    pshell允许我们检查单词的拼写并提供建议。

    需要额外安装扩展。

图像生成和处理

  • exif扩展

    通过使用 exif 扩展,你可以操作图像元数据。例如:你可以使用 exif 相关的函数从数码相机拍摄的图片文件中读取元数据。通常 JPEG 和 TIFF 格式的图像文件都包含元数据。

    • exif_imagetype — 判断一个图像的类型

      返回的是int类型。比如常用的:

      • 1 IMAGETYPE_GIF
      • 2 IMAGETYPE_JPEG
      • 3 IMAGETYPE_PNG
    • exif_read_data — 从 JPEG 或 TIFF 文件中读取 EXIF 头信息

      EXIF 头信息往往存在于数码相机生成的 JPEG/TIFF 图像中,但不幸的是每个数码相机制造商的标记都不同,因此(编写代码时)不能依赖于某个特定的 Exif 头信息。

      exif_read_data("tsingchan.JPG");
      //输出:
      Array
      (
          [FileName] => tsingchan.JPG
          [FileDateTime] => 1550741190
          [FileSize] => 92044
          [FileType] => 2
          [MimeType] => image/jpeg
          [SectionsFound] => ANY_TAG, IFD0, THUMBNAIL, EXIF
          [COMPUTED] => Array
              (
                  [html] => width="640" height="640"
                  [Height] => 640
                  [Width] => 640
                  [IsColor] => 1
                  [ByteOrderMotorola] => 1
                  [Thumbnail.FileType] => 2
                  [Thumbnail.MimeType] => image/jpeg
              )
      
          [Orientation] => 1
          [XResolution] => 72/1
          [YResolution] => 72/1
          [ResolutionUnit] => 2
          [YCbCrPositioning] => 1
          [Exif_IFD_Pointer] => 102
          [THUMBNAIL] => Array
              (
                  [Compression] => 6
                  [XResolution] => 72/1
                  [YResolution] => 72/1
                  [ResolutionUnit] => 2
                  [JPEGInterchangeFormat] => 286
                  [JPEGInterchangeFormatLength] => 14296
              )
      
          [ExifVersion] => 0221
          [ComponentsConfiguration] => 
          [FlashPixVersion] => 0100
          [ColorSpace] => 1
          [ExifImageWidth] => 640
          [ExifImageLength] => 640
          [SceneCaptureType] => 0
      )
      
    • exif_tagname — 获取指定索引的头名称

    • exif_thumbnail — 取得嵌入在 TIFF 或 JPEG 图像中的缩略图

      exif_thumbnail() 读取 TIFF 或 JPEG 图像中的嵌入缩略图。如果图像不包含缩略图则返回 FALSE。

    • read_exif_data — 别名 exif_read_data

  • GD扩展和图像处理函数

    • gd_info — 取得当前安装的 GD 库的信息

    • getimagesize — 取得图像大小

      本函数不需要 GD 图像库。

      返回:像素值、图像类型标记、channels 对于 RGB 图像其值为 3,对于 CMYK 图像其值为 4。bits 是每种颜色的位数。以及符合该图像的 MIME 类型,此信息可以用来在 HTTP Content-type 头信息中发送正确的信息:

      Array
      (
          [0] => 640
          [1] => 640
          [2] => 2
          [3] => width="640" height="640"
          [bits] => 8
          [channels] => 3
          [mime] => image/jpeg
      )
      
    • getimagesizefromstring — 从字符串中获取图像尺寸信息

      同 getimagesize() 函数。区别是 getimagesizefromstring() 第一个参数是图像数据的字符串表达,而不是文件名。

      $info = getimagesize($imageFilename);
      $info = getimagesizefromstring(file_get_contents($imageFilename));
      
    • image_type_to_extension — 取得图像类型的文件后缀

      根据给定的常量 IMAGETYPE_XXX 返回后缀名。 比如:

      • 1 IMAGETYPE_GIF
      • 2 IMAGETYPE_JPEG
      • 3 IMAGETYPE_PNG
    • image_type_to_mime_type — 取得 getimagesize,exif_read_data,exif_thumbnail,exif_imagetype 所返回的图像类型的 MIME 类型

      image_type对应mime_type值:

      • IMAGETYPE_GIF image/gif
      • IMAGETYPE_JPEG image/jpeg
      • IMAGETYPE_PNG image/png
    • image2wbmp — 以 WBMP 格式将图像输出到浏览器或文件

    • imageaffine — 返回经过仿射变换后的图像,剪切区域可选

    • imageaffinematrixconcat — Concatenate two affine transformation matrices

    • imageaffinematrixget — Get an affine transformation matrix

    • imagealphablending — 设定图像的混色模式

    • imageantialias — 是否使用抗锯齿(antialias)功能

    • imagearc — 画椭圆弧

      imagearc() 以 cx,cy(图像左上角为 0, 0)为中心在 image 所代表的图像中画一个椭圆弧。w 和 h 分别指定了椭圆的宽度和高度,起始和结束点以 s 和 e 参数以角度指定。0°位于三点钟位置,以顺时针方向绘画。

      // 创建一个 200X200 的图像
      $img = imagecreatetruecolor(200, 200);
      // 分配颜色
      $white = imagecolorallocate($img, 255, 255, 255);
      $black = imagecolorallocate($img, 0, 0, 0);
      // 画一个黑色的圆
      imagearc($img, 100, 100, 150, 150, 0, 360, $white);
      // 将图像输出到浏览器
      header("Content-type: image/png");
      imagepng($img);
      // 释放内存
      imagedestroy($img);
      
    • imagechar — 水平地画一个字符

      imagechar() 将字符串 c 的第一个字符画在 image 指定的图像中,其左上角位于 x,y(图像左上角为 0,0),颜色为 color。如果 font 是 1,2,3,4 或 5,则使用内置的字体(更大的数字对应于更大的字体)。

      $im = imagecreate(100,100);
      
      $string = 'Tsing';
      
      $bg = imagecolorallocate($im, 255, 255, 255);
      $black = imagecolorallocate($im, 0, 0, 0);
      
      // prints a black "P" in the top left corner
      imagechar($im, 5, 30, 30, $string, $black);
      
      header('Content-type: image/png');
      imagepng($im);
      
    • imagecharup — 垂直地画一个字符

    • imagecolorallocate — 为一幅图像分配颜色

      imagecolorallocate() 返回一个标识符,代表了由给定的 RGB 成分组成的颜色。red,green 和 blue 分别是所需要的颜色的红,绿,蓝成分。这些参数是 0 到 255 的整数或者十六进制的 0x00 到 0xFF。imagecolorallocate() 必须被调用以创建每一种用在 image 所代表的图像中的颜色。

      注意:第一次对 imagecolorallocate() 的调用会给基于调色板的图像填充背景色,即用 imagecreate() 建立的图像。

    • imagecolorallocatealpha — 为一幅图像分配颜色 + alpha

      imagecolorallocatealpha() 的行为和 imagecolorallocate() 相同,但多了一个额外的透明度参数 alpha,其值从 0 到 127。0 表示完全不透明,127 表示完全透明。

    • imagecolorat — 取得某像素的颜色索引值

      返回 image 所指定的图形中指定位置像素的颜色索引值。

      如果 PHP 编译时加上了 GD 库 2.0 或更高的版本并且图像是真彩色图像,则本函数以整数返回该点的 RGB 值。用移位加掩码来取得红,绿,蓝各自成分的值:

    • imagecolorclosest — 取得与指定的颜色最接近的颜色的索引值

    • imagecolorclosestalpha — 取得与指定的颜色加透明度最接近的颜色

    • imagecolorclosesthwb — 取得与给定颜色最接近的色度的黑白色的索引

    • imagecolordeallocate — 取消图像颜色的分配

    • imagecolorexact — 取得指定颜色的索引值

    • imagecolorexactalpha — 取得指定的颜色加透明度的索引值

    • imagecolormatch — 使一个图像中调色板版本的颜色与真彩色版本更能匹配

    • imagecolorresolve — 取得指定颜色的索引值或有可能得到的最接近的替代值

      本函数可以保证对所请求的颜色返回一个颜色索引,要么是确切值要么是所能得到最接近的替代值。

      如果从文件创建了图像,只有图像中使用了的颜色会被辨析。仅出现在调色板中的颜色不会被辨析。

    • imagecolorresolvealpha — 取得指定颜色 + alpha 的索引值或有可能得到的最接近的替代值

    • imagecolorset — 给指定调色板索引设定颜色

    • imagecolorsforindex — 取得某索引的颜色

      本函数返回一个具有 red,green,blue 和 alpha 的键名的关联数组,包含了指定颜色索引的相应的值。

    • imagecolorstotal — 取得一幅图像的调色板中颜色的数目

    • imagecolortransparent — 将某个颜色定义为透明色

      imagecolortransparent() 将 image 图像中的透明色设定为 color。image 是 imagecreatetruecolor() 返回的图像标识符,color 是 imagecolorallocate() 返回的颜色标识符。

      透明色是图像的一种属性,透明度不是颜色的属性。一旦设定了某个颜色为透明色,图像中之前画为该色的任何区域都成为透明的。

    • imageconvolution — 用系数 div 和 offset 申请一个 3x3 的卷积矩阵

      图像就是一个像素矩阵,该函数经过一个3x3的matrix矩阵,得到新的像素矩阵。

    • imagecopy — 拷贝图像的一部分

      imagecopy( resource $dst_im, resource $src_im, int $dst_x, int $dst_y, int $src_x, int $src_y, int $src_w, int $src_h) : bool
      

      将 src_im 图像中坐标从 src_x,src_y 开始,宽度为 src_w,高度为 src_h 的一部分拷贝到 dst_im 图像中坐标为 dst_x 和 dst_y 的位置上。

    • imagecopymerge — 拷贝并合并图像的一部分

      两图像将根据 pct 来决定合并程度,其值范围从 0 到 100。当 pct = 0 时,实际上什么也没做,当为 100 时对于调色板图像本函数和 imagecopy() 完全一样,它对真彩色图像实现了 alpha 透明。

      理解为两张图片融合在一起,融合程度看pct透明度,0是完全透明,100是不透明。

    • imagecopymergegray — 用灰度拷贝并合并图像的一部分

      本函数和 imagecopymerge() 完全一样只除了合并时通过在拷贝操作前将目标像素转换为灰度级来保留了原色度。

    • imagecopyresampled — 重采样拷贝部分图像并调整大小

    • imagecopyresized — 拷贝部分图像并调整大小

    • imagecreate — 新建一个基于调色板的图像

      imagecreate() 返回一个图像标识符,代表了一幅大小为 x_size 和 y_size 的空白图像。

      推荐使用 imagecreatetruecolor()。

    • imagecreatefrombmp — 由文件或 URL 创建一个新图象。

    • imagecreatefromgd2 — 从 GD2 文件或 URL 新建一图像

    • imagecreatefromgd2part — 从给定的 GD2 文件或 URL 中的部分新建一图像

    • imagecreatefromgd — 从 GD 文件或 URL 新建一图像

    • imagecreatefromgif — 由文件或 URL 创建一个新图象。

    • imagecreatefromjpeg — 由文件或 URL 创建一个新图象。

    • imagecreatefrompng — 由文件或 URL 创建一个新图象。

    • imagecreatefromstring — 从字符串中的图像流新建一图像

    • imagecreatefromwbmp — 由文件或 URL 创建一个新图象。

    • imagecreatefromwebp — 由文件或 URL 创建一个新图象。

    • imagecreatefromxbm — 由文件或 URL 创建一个新图象。

    • imagecreatefromxpm — 由文件或 URL 创建一个新图象。

    • imagecreatetruecolor — 新建一个真彩色图像

      建议使用该函数创建空白图像。

    • imagecrop — Crop an image to the given rectangle

      裁剪图像。将图像裁剪到给定的矩形区域并返回结果图像。给定的图像没有被修改

    • imagecropauto — Crop an image automatically using one of the available modes

    • imagedashedline — 画一虚线

      不建议使用本函数。应该用 imagesetstyle() 和 imageline() 的组合替代之。

    • imagedestroy — 销毁一图像

      imagedestroy() 释放与 image 关联的内存

    • imageellipse — 画一个椭圆

      类似于imagearc画个圆弧。

    • imagefill — 区域填充

      $im = imagecreatetruecolor(100, 100);
      
      // 将背景设为红色
      $red = imagecolorallocate($im, 255, 0, 0);
      //将左上角的点及其相邻相同的像素点统一填充为蓝色
      $blue = imagecolorallocate($im, 0, 0, 255);
      imagefill($im, 0, 0, $blue);
      
      header('Content-type: image/png');
      imagepng($im);
      imagedestroy($im);
      
    • imagefilledarc — 画一椭圆弧且填充

    • imagefilledellipse — 画一椭圆并填充

    • imagefilledpolygon — 画一多边形并填充

      多边形通过顶点坐标来实现。

    • imagefilledrectangle — 画一矩形并填充

    • imagefilltoborder — 区域填充到指定颜色的边界为止

    • imagefilter — 对图像使用过滤器

      滤镜。

      imagefilter( resource $src_im, int $filtertype[, int $arg1[, int $arg2[, int $arg3]]] ) : bool
      

      filtertype 可以是下列中的一个:

      • IMG_FILTER_NEGATE:将图像中所有颜色反转。
      • IMG_FILTER_GRAYSCALE:将图像转换为灰度的。
      • IMG_FILTER_BRIGHTNESS:改变图像的亮度。用 arg1 设定亮度级别。
      • IMG_FILTER_CONTRAST:改变图像的对比度。用 arg1 设定对比度级别。
      • IMG_FILTER_COLORIZE:与 IMG_FILTER_GRAYSCALE 类似,不过可以指定颜色。用 arg1,arg2 和 arg3 分别指定 red,blue 和 green。每种颜色范围是 0 到 255。
      • IMG_FILTER_EDGEDETECT:用边缘检测来突出图像的边缘。
      • IMG_FILTER_EMBOSS:使图像浮雕化。
      • IMG_FILTER_GAUSSIAN_BLUR:用高斯算法模糊图像。
      • IMG_FILTER_SELECTIVE_BLUR:模糊图像。
      • IMG_FILTER_MEAN_REMOVAL:用平均移除法来达到轮廓效果。
      • IMG_FILTER_SMOOTH:使图像更柔滑。用 arg1 设定柔滑级别。
    • imageflip — Flips an image using a given mode

      使用给定模式翻转图像。

      • IMG_FLIP_HORIZONTAL 水平方向的翻转 Flips the image horizontally.
      • IMG_FLIP_VERTICAL 垂直方向的翻转 Flips the image vertically.
      • IMG_FLIP_BOTH 水平和垂直方向一起 翻转Flips the image both horizontally and vertically.
      $im = imagecreatefromjpeg($filename);
      header("Content-type:".image_type_to_mime_type(IMAGETYPE_JPEG));
      imageflip($im, IMG_FLIP_BOTH);
      
      imagejpeg($im);
      imagedestroy($im);
      
    • imagefontheight — 取得字体高度

    • imagefontwidth — 取得字体宽度

    • imageftbbox — 给出一个使用 FreeType 2 字体的文本框

    • imagefttext — 使用 FreeType 2 字体将文本写入图像

    • imagegammacorrect — 对 GD 图像应用 gamma 修正

    • imagegetclip — 获取当前的剪切矩形。不绘制像素的区域。

    • imageinterlace — 激活或禁止隔行扫描

    • imageistruecolor — 检查图像是否为真彩色图像

      在RGB色彩空间,图像深度与色彩的映射关系主要有真rl]伪bairl] 真彩色(true-color)是指图像中的每个像素值都分成R、G、B三个基色分量,每个基色分量直接决定其基色的强度,这样产生的色彩称为真彩色。

    • imagelayereffect — 设定 alpha 混色标志以使用绑定的 libgd 分层效果

      imagelayereffect( resource $image, int $effect) : bool
      
      • IMG_EFFECT_REPLACE 使用像素替换

      • IMG_EFFECT_OVERLAY 叠加有效果,黑色的背景像素将保持黑色,白色的背景像素将保持白色,但灰色的背景像素将采取前景像素的颜色。

    • imageline — 画一条线段

    • imageloadfont — 载入一新字体

    • imageopenpolygon — Draws an open polygon

    • imagepalettecopy — 将调色板从一幅图像拷贝到另一幅

    • imagepalettetotruecolor — Converts a palette based image to true color

    • imagepolygon — 画一个多边形

      imagepolygon() 在图像中创建一个多边形。points 是一个 PHP 数组,包含了多边形的各个顶点坐标,即 points[0]= x0,points[1] = y0,points[2]= x1,points[3] = y1,以此类推。num_points 是顶点的总数。

    • imagerectangle — 画一个矩形

      imagerectangle( resource $image, int $x1, int $y1, int $x2, int $y2, int $col) : bool
      

      imagerectangle() 用 col 颜色在 image 图像中画一个矩形,其左上角坐标为 x1, y1,右下角坐标为 x2, y2。图像的左上角坐标为 0, 0。

    • imageresolution — 获取或设置图像的分辨率

    • imagerotate — 用给定角度旋转图像

      imagerotate( resource $image, float $angle, int $bgd_color[, int $ignore_transparent = 0] ) : resource
      

      将 image 图像用给定的 angle 角度旋转。bgd_color 指定了旋转后没有覆盖到的部分的颜色,ignore_transparent如果被设为非零值,则透明色会被忽略(否则会被保留)。

      注意:旋转的中心是图像的中心,旋转后的图像会按比例缩小以适合目标图像的大小——边缘不会被剪去。

      $image = imagecreatefromjpeg($filename);
      $rImage = imagerotate($image, 45, 0);
      header("Content-type:".image_type_to_mime_type(IMAGETYPE_JPEG));
      imagejpeg($rImage);
      imagedestroy($image);
      imagedestroy($rImage);
      
    • imagesavealpha — 设置标记以在保存 PNG 图像时保存完整的 alpha 通道信息(与单一透明色相反)

    • imagescale — 使用给定的新宽度和高度缩放图像

      imagescale( resource $image, int $new_width[, int $new_height = -1[, int $mode = IMG_BILINEAR_FIXED]] ) : resource|false
      

      注意:imagescale不会修改原图片,而是返回新的图片资源。

    • imagesetbrush — 设定画线用的画笔图像

      当用特殊的颜色 IMG_COLOR_BRUSHED 或 IMG_COLOR_STYLEDBRUSHED 绘画时,imagesetbrush() 设定了所有画线的函数(例如 imageline() 和 imagepolygon())所使用的画笔图像。

      注意:使用完画笔图像后不需要采取什么特殊动作。但如果销毁了画笔图像,在设定一个新的画笔图像之前不能使用 IMG_COLOR_BRUSHED 或 IMG_COLOR_STYLEDBRUSHED

      参考imagesetstyle() 更多使用。

    • imagesetclip — Set the clipping rectangle

    • imagesetinterpolation — Set the interpolation method

    • imagesetpixel — 画一个单一像素

    • imagesetstyle — 设定画线的风格

      imagesetstyle() 设定所有画线的函数(例如 imageline() 和 imagepolygon())在使用特殊颜色 IMG_COLOR_STYLED 或者用 IMG_COLOR_STYLEDBRUSHED 画一行图像时所使用的风格。

    • imagesetthickness — 设定画线的宽度

    • imagesettile — 设定用于填充的贴图

    • imagestring — 水平地画一行字符串

      imagestring() 用 col 颜色将字符串 s 画到 image 所代表的图像的 x,y 坐标处(这是字符串左上角坐标,整幅图像的左上角为 0,0)。如果 font 是 1,2,3,4 或 5,则使用内置字体。

    • imagestringup — 垂直地画一行字符串

    • imagesx — 取得图像宽度

      不要记错了,虽然是x,但不是获取x坐标,而是宽度,按正常命名应该是imagesw。

    • imagesy — 取得图像高度

    • imagetruecolortopalette — 将真彩色图像转换为调色板图像

    • imagettfbbox — 取得使用 TrueType 字体的文本的范围

    • imagettftext — 用 TrueType 字体向图像写入文本

    • imagetypes — 返回当前 PHP 版本所支持的图像类型

    • iptcembed — 将二进制 IPTC 数据嵌入到一幅 JPEG 图像中

    • iptcparse — 将二进制 IPTC 块解析为单个标记

    • jpeg2wbmp — 将 JPEG 图像文件转换为 WBMP 图像文件

    • png2wbmp — 将 PNG 图像文件转换为 WBMP 图像文件

    • imagewbmp — 以 WBMP 格式将图像输出到浏览器或文件

    • imagewebp — 将 WebP 格式的图像输出到浏览器或文件

    • imagexbm — 将 XBM 图像输出到浏览器或文件

    • imagebmp — Output a BMP image to browser or file

    • imagegif — 输出图象到浏览器或文件。

    • imagegd2 — 将 GD2 图像输出到浏览器或文件

    • imagegd — 将 GD 图像输出到浏览器或文件

    • imagejpeg — 输出图象到浏览器或文件。

    • imagepng — 以 PNG 格式将图像输出到浏览器或文件

  • ImageMagick

    Imagick 是用 ImageMagic API 来创建和修改图像的PHP官方扩展。

    ImageMagick® 是用来创建,编辑,合并位图图像的一套组件。它能够用于读取,转换,写入多种不同格式的图像。包含 DPX, EXR, GIF, JPEG, JPEG-2000, PDF, PhotoCD, PNG, Postscript, SVG, 和 TIFF。

    ImageMagick支持更多富文本内容的编辑,除了图片还涉及PDF等,特别是PDF、文字、图片的相结合处理方面。

    注意: 官方扩展名称是imagick

邮件相关扩展

@todo

数学扩展

  • Math

    这些数学函数只处理计算机上的int和float类型范围内的值。如果需要处理更大的数字,建议查看使用BCmath。

    • abs — 绝对值
    • acos — 反余弦
    • acosh — 反双曲余弦
    • asin — 反正弦
    • asinh — 反双曲正弦
    • atan2 — 两个参数的反正切
    • atan — 反正切
    • atanh — 反双曲正切
    • base_convert — 在任意进制之间转换数字
    • bindec — 二进制转换为十进制
    • ceil — 进一法取整
    • cos — 余弦
    • cosh — 双曲余弦
    • decbin — 十进制转换为二进制
    • dechex — 十进制转换为十六进制
    • decoct — 十进制转换为八进制
    • deg2rad — 将角度转换为弧度
    • exp — 计算 e 的指数
    • expm1 — 返回 exp(number) - 1,甚至当 number 的值接近零也能计算出准确结果
    • floor — 舍去法取整
    • fmod — 返回除法的浮点数余数
    • getrandmax — 显示随机数最大的可能值
    • hexdec — 十六进制转换为十进制
    • hypot — 计算一直角三角形的斜边长度
    • intdiv — 对除法结果取整
    • is_finite — 判断是否为有限值
    • is_infinite — 判断是否为无限值
    • is_nan — 判断是否为合法数值
    • lcg_value — 组合线性同余发生器
    • log10 — 以 10 为底的对数
    • log1p — 返回 log(1 + number),甚至当 number 的值接近零也能计算出准确结果
    • log — 自然对数
    • max — 找出最大值
    • min — 找出最小值
    • mt_getrandmax — 显示随机数的最大可能值
    • mt_rand — 生成更好的随机数
    • mt_srand — 播下一个更好的随机数发生器种子
    • octdec — 八进制转换为十进制
    • pi — 得到圆周率值
    • pow — 指数表达式
    • rad2deg — 将弧度数转换为相应的角度数
    • rand — 产生一个随机整数
    • round — 对浮点数进行四舍五入
    • sin — 正弦
    • sinh — 双曲正弦
    • sqrt — 平方根
    • srand — 播下随机数发生器种子
    • tan — 正切
    • tanh — 双曲正切
  • BCmath

    对于任意精度的数学,PHP提供了支持用字符串表示的任意大小和精度的数字的二进制计算,最多为2147483647-1(或0x7FFFFFFF-1)。

    由于php弱类型语言,浮点数计算并不是非常精确,在存在小数点多,或者和金钱有关的浮点数运算,建议通过BCmath机型比较计算两个任意精度的数字,否则容易出现错误的情况。但如果涉及金钱的数值,建议在设计上考虑尽量不出现小数,比如把单位设置为分,避免出现小数存储与计算。

    • bcadd — 2个任意精度数字的加法计算
    • bccomp — 比较两个任意精度的数字
    • bcdiv — 2个任意精度的数字除法计算
    • bcmod — 对一个任意精度数字取模
    • bcmul — 2个任意精度数字乘法计算
    • bcpow — 任意精度数字的乘方
    • bcpowmod — Raise an arbitrary precision number to another, reduced by a specified modulus
    • bcscale — 设置所有bc数学函数的默认小数点保留位数
    • bcsqrt — 任意精度数字的二次方根
    • bcsub — 2个任意精度数字的减法

    BCmath函数都是简单的加减乘除、平方根、取模、乘方,支持任意精度的计算,函数最后一个参数scale,此可选参数用于设置结果中小数点后的小数位数。也可通过使用 bcscale() 来设置全局默认的小数位数,用于所有函数。如果未设置,则默认为 0。

    $a = '1.234';
    $b = '5';
    
    echo bcsub($a, $b);     // -3
    echo bcsub($a, $b, 4);  // -3.7660
    

进程控制扩展

  • posix

    POSIX函数默认情况下处于启用状态。 您可以使用 –disable-posix 禁用类似POSIX的功能。

      函数名称	描述
      posix_access	确定文件的可访问性
      posix_ctermid	 获取控制终端的路径名
      posix_errno	 别名posix_get_last_error
      posix_get_last_error	 检索由失败的最后一个posix函数设置的错误号
      posix_getcwd	 当前目录的路径名
      posix_getegid	 返回当前进程的有效组ID
      posix_geteuid	 返回当前进程的有效用户ID
      posix_getgid	 返回当前进程的真实组ID
      posix_getgrgid	 按组ID返回有关组的信息
      posix_getgrnam	 按名称返回有关组的信息
      posix_getgroups	 返回当前进程的组集
      posix_getlogin	 返回登录名
      posix_getpgid	 获取用于作业控制的流程组ID
      posix_getpgrp	 返回当前进程组标识符
      posix_getpid	 返回当前进程id
      posix_getppid	 返回父进程标识符
      posix_getpwnam	 按用户名返回有关用户的信息
      posix_getpwuid	 通过用户ID返回有关用户的信息
      posix_getrlimit	 返回有关系统资源限制的信息
      posix_getsid	 获取流程的当前sid
      posix_getuid	 返回当前进程的真实用户ID
      posix_initgroups	 计算组访问列表
      posix_isatty	 确定文件描述符是否是交互式终端
      posix_kill	 向过程发送信号
      posix_mkfifo	 创建一个fifo特殊文件(命名管道)
      posix_mknod	 创建一个特殊文件或普通文件(POSIX.1)
      posix_setegid	 设置当前进程的有效GID
      posix_seteuid	 设置当前进程的有效UID
      posix_setgid	 设置当前进程的GID
      posix_setpgid	 设置进程组ID以进行作业控制
      posix_setrlimit	 设置系统资源限制
      posix_setsid	 使当前流程成为会议负责人
      posix_setuid	 设置当前进程的UID
      posix_strerror	 检索与给定errno相关的系统错误消息
      posix_times	 获取处理时间
      posix_ttyname	 确定终端设备名称
      posix_uname	 获取系统名称
    

其它基本扩展

  • json

    本扩展实现了 » JavaScript对象符号(JSON)数据转换格式。 PHP 5 中的解码分析器基于 Douglas Crockford 的 JSON_checker。 PHP 7 中是改进的全新解析器,专门为 PHP 订制,软件许可证为 PHP license。

    • json_decode — 对 JSON 格式的字符串进行解码
    • json_encode — 对变量进行 JSON 编码
    • json_last_error_msg — Returns the error string of the last json_encode() or json_decode() call
    • json_last_error — 返回最后发生的错误

    注意:json_encode的option选项可以设置JSON_UNESCAPED_UNICODE 支持正常显示中文,而不是显示unicode字符串,便于阅读。

  • lua

    Lua是一个功能强大,速度快,轻量级,可嵌入的脚本语言。这个扩展嵌入Lua解释器,并对lua变量和函数提供面向对象的API。

    扩展额外安装:https://pecl.php.net/package/lua

    • Lua::assign — 将一个php变量赋值给Lua

    • Lua::call — 调用Lua函数

    • Lua::__construct — Lua 构造方法

    • Lua::eval — 将字符串当做Lua代码执行

    • Lua::getVersion — 获取Lua版本

    • Lua::include — 解析Lua脚本文件

      返回脚本文件运行结果,参数错误返回NULL ,其它错误返回FALSE。

    • Lua::registerCallback — 向Lua中注册php函数

    • LuaClosure::__invoke — 调用luaclosure

    $lua = new Lua();
    $closure = $lua->eval(<<<CODE
        return (function ()
            print("hello world")
        end)
    CODE
    );
    
    $lua->call($closure);
    /* after PHP 5.3 */
    $closure();
    //输出:hello worldhello world
    
  • seaslog

    安装扩展:https://pecl.php.net/package/seaslog

    Log 日志,通常是系统或软件、应用的运行记录。通过 Log 的分析,可以方便用户了解系统或软件、应用的运行情况;如果你的应用 Log 足够丰富,也可以分析以往用户的操作行为、类型喜好、地域分布或其他更多信息;如果一个应用的 Log 同时也分了多个级别,那么可以很轻易地分析得到该应用的健康状况,及时发现问题并快速定位、解决问题,补救损失。

    PHP 内置 error_log、syslog 函数功能强大且性能极好,但由于各种缺陷(error_log 无错误级别、无固定格式,syslog 不分模块、与系统日志混合),灵活度降低了很多,不能满足应用需求。

    好消息是,有不少第三方的log类库弥补了上述缺陷,如 log4php、plog、monolog 等(当然也有很多应用在项目中自己开发的 Log 类)。

    那么有没有一种 Log 类库满足以下需求呢:

    • 分模块、分级别
    • 配置简单(最好是勿须配置)
    • 日志格式清晰易读
    • 应用简单、性能很棒 SeasLog 正是应此需求而生。

    目前提供了什么:

    • 在 PHP 项目中便捷、规范地记录 Log
    • 可配置的默认 Log 目录与模块
    • 指定 Log 目录与获取当前配置
    • 初步的分析预警框架
    • 高效的日志缓冲、便捷的缓冲 debug
    • 遵循 PSR-3 日志接口规范
    • 自动记录错误信息
    • 自动记录异常信息
    • 连接 TCP 端口,以 RFC5424 格式发送日志
    • 连接 UDP 端口,以 RFC5424 格式发送日志
    • 支持 RequestId 区分请求
    • 支持日志模板自定义

    seaslog类:

    • SeasLog::alert — 记录 alert 日志
    • SeasLog::analyzerCount — Get log count by level, log_path and key_word
    • SeasLog::analyzerDetail — Get log detail by level, log_path, key_word, start, limit, order
    • SeasLog::closeLoggerStream — Manually release stream flow from logger
    • SeasLog::__construct — Description
    • SeasLog::critical — 记录 critical 日志
    • SeasLog::debug — 记录 debug 日志
    • SeasLog::__destruct — Description
    • SeasLog::emergency — 记录 emergency 日志
    • SeasLog::error — 记录 error 日志
    • SeasLog::flushBuffer — 将日志缓存刷新到介质中,文件介质,或者发送到远端的 TCP/UDP 服务地址。
    • SeasLog::getBasePath — 获得 SeasLog 根目录
    • SeasLog::getBuffer — 获取内存中的日志缓存数组
    • SeasLog::getBufferEnabled — Determin if buffer enabled
    • SeasLog::getDatetimeFormat — 获取 SeasLog 日期格式
    • SeasLog::getLastLogger — 获得 SeasLog 最近的一次 Logger 名称
    • SeasLog::getRequestID — 获得当前 SeasLog 中用于区分请求的 request_id
    • SeasLog::getRequestVariable — Get SeasLog request variable
    • SeasLog::info — Record info log information
    • SeasLog::log — 公共的日志记录函数
    • SeasLog::notice — 记录 notice 日志
    • SeasLog::setBasePath — 设置 SeasLog 根目录
    • SeasLog::setDatetimeFormat — 设置 SeasLog 日期格式
    • SeasLog::setLogger — 设置 SeasLog 的 Logger 名
    • SeasLog::setRequestID — 设置可以由 SeasLog 用于区分请求的 request_id
    • SeasLog::setRequestVariable — Manually set SeasLog request variable
    • SeasLog::warning — Record warning log information

    更多了解:PHP扩展seaslog面面观

  • URLs

    处理URL字符串: 编码,解码和解析。

    • base64_decode — 对使用 MIME base64 编码的数据进行解码

    • base64_encode — 使用 MIME base64 对数据进行编码

      设计此种编码是为了使二进制数据可以通过非纯 8-bit 的传输层传输,例如电子邮件的主体。

      Base64-encoded 数据要比原始数据多占用 33% 左右的空间。

    • get_headers — 取得服务器响应一个 HTTP 请求所发送的所有标头

      如果将可选的 format 参数设为 1,则 get_headers() 会解析相应的信息并设定数组的键名。

      url = 'http://www.example.com';
            
      print_r(get_headers($url, 1));//format参数设置为1
      
      Array
      (
          [0] => HTTP/1.1 200 OK
          [Date] => Sat, 29 May 2004 12:28:14 GMT
          [Server] => Apache/1.3.27 (Unix)  (Red-Hat/Linux)
          [Last-Modified] => Wed, 08 Jan 2003 23:11:55 GMT
          [ETag] => "3f80f-1b6-3e1cb03b"
          [Accept-Ranges] => bytes
          [Content-Length] => 438
          [Connection] => close
          [Content-Type] => text/html
      )
      
    • get_meta_tags — 从一个文件中提取所有的 meta 标签 content 属性,返回一个数组

      打开 filename 逐行解析文件中的 <meta> 标签。解析工作将在 </head> 处停止。

      支持本地文件与url。

    • http_build_query — 生成 URL-encode 之后的请求字符串

      使用给出的关联(或下标)数组生成一个经过 URL-encode 的请求字符串。

      $data = array('foo'=>'bar',
            'baz'=>'boom',
            'cow'=>'milk',
            'php'=>'hypertext processor');
      
      echo http_build_query($data) . "\n";
      
      foo=bar&baz=boom&cow=milk&php=hypertext+processor
      
      
    • parse_url — 解析 URL,返回其组成部分

      parse_url( string $url[, int $component = -1] ) : mixed
      

      注意:本函数不是用来验证给定 URL 的合法性的,只是将其分解为下面列出的部分。不完整的 URL 也被接受,parse_url() 会尝试尽量正确地将其解析。

      指定 PHP_URL_SCHEME、 PHP_URL_HOST、 PHP_URL_PORT、 PHP_URL_USER、 PHP_URL_PASS、 PHP_URL_PATH、 PHP_URL_QUERY 或 PHP_URL_FRAGMENT 的其中一个来获取 URL 中指定的部分的 string。

      print_r(parse_url("http://www.9ong.com/aa/bb?a=b#id"));
      
      
      Array
      (
          [scheme] => http
          [host] => www.9ong.com
          [path] => /aa/bb
          [query] => a=b
          [fragment] => id
      )
      
      
    • urlencode — 编码 URL 字符串

      返回字符串,此字符串中除了 -_. 之外的所有非字母数字字符都将被替换成百分号(%)后跟两位十六进制数,空格则编码为加号(+)。此编码与 WWW 表单 POST 数据的编码方式是一样的,同时与 application/x-www-form-urlencoded 的媒体类型编码方式一样。由于历史原因,此编码在将空格编码为加号(+)方面与 » RFC3986 编码(参见 rawurlencode())不同。

    • urldecode — 解码已编码的 URL 字符串

      注意:超全局变量 $_GET 和 $_REQUEST 已经被解码了。对 $_GET 或 $_REQUEST 里的元素使用 urldecode() 将会导致不可预计和危险的结果。

    • rawurlencode — 按照 RFC 3986 对 URL 进行编码

      返回字符串,此字符串中除了 -_. 之外的所有非字母数字字符都将被替换成百分号(%)后跟两位十六进制数。这是在 » RFC 3986 中描述的编码,是为了保护原义字符以免其被解释为特殊的 URL 定界符,同时保护 URL 格式以免其被传输媒体(像一些邮件系统)使用字符转换时弄乱。

    • rawurldecode — 对已编码的 URL 字符串进行解码

      rawurldecode() 不会把加号(‘+’)解码为空格,而 urldecode() 可以。

  • V8js

    这个扩展将»V8 Javascript引擎嵌入到PHP中。

    • V8Js::__construct — Construct a new V8Js object
    • V8Js::executeString — Execute a string as Javascript code
    • V8Js::getExtensions — Return an array of registered extensions
    • V8Js::getPendingException — Return pending uncaught Javascript exception
    • V8Js::registerExtension — Register Javascript extensions for V8Js
    $v8 = new V8Js();
    
    /* basic.js */
    $JS = <<< EOT
    len = print('Hello' + ' ' + 'World!' + "\\n");
    len;
    EOT;
    
    try {
    var_dump($v8->executeString($JS, 'basic.js'));
    } catch (V8JsException $e) {
    var_dump($e);
    }
    
    Hello World!
    int(13)
    
  • yaml

    本扩展实现了 » YAML Ain’tMarkup Language (YAML) 数据序列化标准。

    yaml数据格式:

    languages:
        - Ruby
        - Perl
        - Python 
    websites:
        YAML: yaml.org 
        Ruby: ruby-lang.org 
        Python: python.org 
        Perl: use.perl.org
    

    对应的json格式:

    { 
        languages: [ 'Ruby', 'Perl', 'Python'],
        websites: {
            YAML: 'yaml.org',
            Ruby: 'ruby-lang.org',
            Python: 'python.org',
            Perl: 'use.perl.org' 
        } 
    }
    
    • yaml_emit_file — Send the YAML representation of a value to a file
    • yaml_emit — Returns the YAML representation of a value
    • yaml_parse_file — Parse a YAML stream from a file
    • yaml_parse_url — Parse a Yaml stream from a URL
    • yaml_parse — Parse a YAML stream
    $addr = array(
    "given" => "Chris",
    "family"=> "Dumars",
    "address"=> array(
        "lines"=> "458 Walkman Dr.
        Suite #292",
        "city"=> "Royal Oak",
        "state"=> "MI",
        "postal"=> 48046,
      ),
    );
    $invoice = array (
        "invoice"=> 34843,
        "date"=> "2001-01-23",
        "bill-to"=> $addr,
        "ship-to"=> $addr,
        "product"=> array(
            array(
                "sku"=> "BL394D",
                "quantity"=> 4,
                "description"=> "Basketball",
                "price"=> 450,
            ),
            array(
                "sku"=> "BL4438H",
                "quantity"=> 1,
                "description"=> "Super Hoop",
                "price"=> 2392,
            ),
        ),
        "tax"=> 251.42,
        "total"=> 4443.52,
        "comments"=> "Late afternoon is best. Backup contact is Nancy Billsmer @ 338-4338.",
        );
    
    // 把该 invoice 转换生成 YAML 的表示法
    $yaml = yaml_emit($invoice);
    var_dump($yaml);
    
    // 把 YAML 转换成 PHP 变量
    $parsed = yaml_parse($yaml);
    
    // 来回转换,以检查两个结构是否相等效
    var_dump($parsed == $invoice);
    
  • Yaf扩展框架

    The Yet Another Framework (Yaf) 扩展是一个用来开发web应用的php框架。

    http://pecl.php.net/package/yaf

    http://cn2.php.net/manual/zh/yaf.tutorials.php (文档)

    http://www.laruence.com/manual/preface.html (文档)

  • trait

    trait是一个扩展,用于检测XSS代码(tainted string)。并可用于发现sql注入漏洞、shell注入漏洞等。

    当启用了trait,如果传递一个traited的字符串(来自$_GET,$_POST或$_COOKIE)给一些函数,trait发出警告。

  • Data Structures

    PHP7高效的数据结构,可以作为 array 的替代。

    安装:

    pecl install ds
    

    或编译:

    https://pecl.php.net/package/ds

SPL标准库

php标准库,为了完全转向面向对象,比提供一些更高级的使用方法,php封装了一些类或接口,比如数据结构的实现、迭代器、接口、异常、文件系统等,甚至提供观察者模式的一些方法封装

  • 数据结构

    • SplDoublyLinkedList类,提供了双链表的主要功能

    • SplStack类,通过使用一个双向链表来提供栈的主要功能

    • SplQueue类,通过使用一个双向链表来提供队列的主要功能

    • SplHeap类,提供了堆的主要功能

    • SplMaxHeap类,提供了堆的主要功能,将最大的堆放在最上面

    • SplMinHeap类,提供了堆的主要功能,在堆顶部保持最小值

    • SplPriorityQueue类,提供了优先化队列的主要功能,使用最大堆实现

    • SplFixedArray — The SplFixedArray class

      SplFixedArray类提供了array的主要功能。SplFixedArray和普通PHP数组的主要区别是,SplFixedArray的长度固定,只允许整数作为索引。它的优点是比标准数组使用更少的内存。

    • SplObjectStorage — The SplObjectStorage class

      SplObjectStorage类提供了一个从对象到数据的映射,或者通过忽略数据,提供一个对象集。在许多需要唯一标识对象的情况下,这两个目的都很有用。

  • 接口

    • Countable — 类实现 Countable 可被用于 count() 函数.
    • OuterIterator — 实现OuterIterator的类可用于迭代迭代器。
    • RecursiveIterator — 实现RecursiveIterator的类可用于递归地迭代迭代器。
    • SeekableIterator — The SeekableIterator interface
  • 异常

    • BadFunctionCallException — The BadFunctionCallException class
    • BadMethodCallException — The BadMethodCallException class
    • DomainException — The DomainException class
    • InvalidArgumentException — The InvalidArgumentException class
    • LengthException — The LengthException class
    • LogicException — The LogicException class
    • OutOfBoundsException — The OutOfBoundsException class
    • OutOfRangeException — The OutOfRangeException class
    • OverflowException — The OverflowException class
    • RangeException — The RangeException class
    • RuntimeException — The RuntimeException class
    • UnderflowException — The UnderflowException class
    • UnexpectedValueException — The UnexpectedValueException class
  • SPL 函数

    • class_implements — 返回指定的类实现的所有接口。
    • class_parents — 返回指定类的父类。
    • class_uses — Return the traits used by the given class
    • iterator_apply — 为迭代器中每个元素调用一个用户自定义函数
    • iterator_count — 计算迭代器中元素的个数
    • iterator_to_array — 将迭代器中的元素拷贝到数组
    • spl_autoload_call — 尝试调用所有已注册的 __autoload() 函数来装载请求类
    • spl_autoload_extensions — 注册并返回 spl_autoload 函数使用的默认文件扩展名
    • spl_autoload_functions — 返回所有已注册的 __autoload() 函数
    • spl_autoload_register — 注册给定的函数作为 __autoload 的实现
    • spl_autoload_unregister — 注销已注册的 __autoload() 函数
    • spl_autoload — __autoload()函数的默认实现
    • spl_classes — 返回所有可用的SPL类
    • spl_object_hash — 返回指定对象的hash id
    • spl_object_id — Return the integer object handle for given object
  • 文件处理

    • SplFileInfo类,为单个文件的信息提供了一个高级的面向对象的接口。
    • SplFileObject类,为文件提供了一个面向对象接口
    • SplTempFileObject类,为临时文件提供了一个面向对象的接口
  • 各种类及接口

    • ArrayObject — 这个类允许对象像数组一样工作。
    • SplObserver — SplObserver接口与SplSubject一起用于实现观察者设计模式。
    • SplSubject — SplSubject接口与SplObserver一起使用,以实现观察者设计模式。
  • 迭代器

    • AppendIterator — The AppendIterator class
    • ArrayIterator — ArrayIterator 类
    • CachingIterator — The CachingIterator class
    • CallbackFilterIterator — The CallbackFilterIterator class
    • DirectoryIterator — The DirectoryIterator class
    • EmptyIterator — The EmptyIterator class
    • FilesystemIterator — The FilesystemIterator class
    • FilterIterator — The FilterIterator class
    • GlobIterator — The GlobIterator class
    • InfiniteIterator — The InfiniteIterator class
    • IteratorIterator — The IteratorIterator class
    • LimitIterator — The LimitIterator class
    • MultipleIterator — The MultipleIterator class
    • NoRewindIterator — The NoRewindIterator class
    • ParentIterator — The ParentIterator class
    • RecursiveArrayIterator — The RecursiveArrayIterator class
    • RecursiveCachingIterator — The RecursiveCachingIterator class
    • RecursiveCallbackFilterIterator — The RecursiveCallbackFilterIterator class
    • RecursiveDirectoryIterator — The RecursiveDirectoryIterator class
    • RecursiveFilterIterator — The RecursiveFilterIterator class
    • RecursiveIteratorIterator — The RecursiveIteratorIterator class
    • RecursiveRegexIterator — The RecursiveRegexIterator class
    • RecursiveTreeIterator — The RecursiveTreeIterator class
    • RegexIterator — The RegexIterator class

SPL TYPES

这个扩展旨在帮助人们使PHP成为一个更强的类型语言,可以是一个很好的替代标量类型提示。它提供了不同的类型处理类,比如int、float、bool、enum和string

属于实验性扩展,不建议使用。

Swoole

Swoole是一个使用事件驱动、异步、非阻塞I/O模型的高性能网络框架。它可以用来开发高性能、可扩展、并发的TCP、UDP、Unix socket、HTTP、Websocket服务。

扩展安装:https://pecl.php.net/package/swoole

Swoole4 文档

其它服务

  • cURL

    PHP 支持 Daniel Stenberg 创建的 libcurl 库。libcurl 同时支持 HTTPS 证书、HTTP POST、HTTP PUT、 FTP 上传(也能通过 PHP 的 FTP 扩展完成)、HTTP 基于表单的上传、代理、cookies、用户名+密码的认证。

    • curl_init — 初始化 cURL 会话

      // 创建一个新 cURL 资源
      $ch = curl_init();
      
      // 设置 URL 和相应的选项
      $options = array(CURLOPT_URL => 'http://www.9ong.com/',
                      CURLOPT_HEADER => false
                      );
      
      curl_setopt_array($ch, $options);
      
      // 抓取 URL 并把它传递给浏览器
      curl_exec($ch);
      
      // 关闭 cURL 资源,并且释放系统资源
      curl_close($ch);
      
    • curl_exec — 执行 cURL 会话

    • curl_close — 关闭 cURL 会话

      关闭 cURL 会话并且释放所有资源。cURL 句柄 ch 也会被删除。

    • curl_setopt — 设置 cURL 传输选项

      更多option设置详见官方文档:PHP: curl_setopt - Manual

    • curl_setopt_array — 为 cURL 传输会话批量设置选项

      为 cURL 传输会话批量设置选项。这个函数对于需要设置大量的 cURL 选项是非常有用的,不需要重复地调用 curl_setopt()。

    • curl_copy_handle — 复制一个cURL句柄和它的所有选项

      复制一个cURL句柄并保持相同的选项。

    • curl_getinfo — 获取一个cURL连接资源句柄的信息

    • curl_errno — 返回最后一次的错误代码

    • curl_error — 返回当前会话最后一次错误的字符串

    • curl_strerror — 返回错误代码的字符串描述

      // 检测错误,显示错误信息
      if($errno = curl_errno($ch)) {
          $error_message = curl_strerror($errno);
          echo "cURL error ({$errno}):\n {$error_message}";
      }
      
    • curl_escape — 使用 URL 编码给定的字符串

      该函数使用 URL 根据» RFC 3986编码给定的字符串。和rawurlencode()都是按照RFC 3986对URL进行编码。

    • curl_unescape — 解码给定的 URL 编码的字符串

    • curl_version — 获取 cURL 版本信息

    • curl_multi_init — 返回一个新cURL批处理句柄

      允许并行地处理批处理cURL句柄。

      // 创建一对cURL资源
      $ch1 = curl_init();
      $ch2 = curl_init();
      
      // 设置URL和相应的选项
      curl_setopt($ch1, CURLOPT_URL, "http://www.9ong.com/");
      curl_setopt($ch1, CURLOPT_HEADER, 0);
      curl_setopt($ch2, CURLOPT_URL, "http://www.php.net/");
      curl_setopt($ch2, CURLOPT_HEADER, 0);
      
      // 创建批处理cURL句柄
      $mh = curl_multi_init();
      
      // 增加2个句柄
      curl_multi_add_handle($mh,$ch1);
      curl_multi_add_handle($mh,$ch2);
      
      $running=null;
      // 执行批处理句柄
      do {
          curl_multi_exec($mh,$running);
      } while($running > 0);
      
      // 关闭全部句柄
      curl_multi_remove_handle($mh, $ch1);
      curl_multi_remove_handle($mh, $ch2);
      curl_multi_close($mh);
      
    • curl_multi_add_handle — 向curl批处理会话中添加单独的curl句柄

    • curl_multi_exec — 运行当前 cURL 句柄的子连接

      处理在栈中的每一个句柄。无论该句柄需要读取或写入数据都可调用此方法。

    • curl_multi_setopt — 为 cURL 并行处理设置一个选项

    • curl_multi_close — 关闭一组cURL句柄

    • curl_multi_errno — 返回上一次 curl 批处理的错误码

    • curl_multi_strerror — 返回字符串描述的错误代码

    • curl_multi_getcontent — 如果设置了CURLOPT_RETURNTRANSFER,则返回获取的输出的文本流

    • curl_multi_info_read — 获取当前解析的cURL的相关传输信息

    • curl_multi_remove_handle — 移除cURL批处理句柄资源中的某个句柄资源

    • curl_multi_select — 等待所有cURL批处理中的活动连接

    • curl_share_init — 初始化一个 cURL 共享句柄。

      运行在 cURL 句柄之间共享数据。

      // 创建 cURL 共享句柄,并设置共享 cookie 数据
      $sh = curl_share_init();
      curl_share_setopt($sh, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE);
      
      // 初始化第一个 cURL 句柄,并将它设置到共享句柄
      $ch1 = curl_init("http://9ong.com/");
      curl_setopt($ch1, CURLOPT_SHARE, $sh);
      
      // 执行第一个 cURL 句柄
      curl_exec($ch1);
      
      // 初始化第二个 cURL 句柄,并将它设置到共享句柄
      $ch2 = curl_init("http://php.net/");
      curl_setopt($ch2, CURLOPT_SHARE, $sh);
      
      // 执行第二个 cURL 句柄
      //  all cookies from $ch1 handle are shared with $ch2 handle
      curl_exec($ch2);
      
      // 关闭 cURL 共享句柄
      curl_share_close($sh);
      
      // 关闭 cURL 共享句柄
      curl_close($ch1);
      curl_close($ch2);
      
      
    • curl_share_close — 关闭 cURL 共享句柄

    • curl_share_setopt — 为 cURL 共享句柄设置选项。

    • curl_share_errno — 返回共享 curl 句柄的最后一次错误号

    • curl_share_strerror — 返回错误号对应的错误消息

    • curl_pause — 暂停和取消暂停一个连接。

    • curl_reset — 重置一个 libcurl 会话句柄的所有的选项

    • curl_file_create — 创建一个 CURLFile 对象

      创建 CURLFile 对象,使用 CURLOPT_POSTFIELDS 选项上传文件。

      这是采用过程化函数实现创建上传文件对象:

      curl_file_create( string $filename[, string $mimetype[, string $postname]] ) : CURLFile
      

      另外php5.5以后提供了面向对象创建上传文件对象的方式:

      public CURLFile::__construct( string $filename[, string $mimetype[, string $postname]] )
      
            
      // Create a cURL handle
      $ch = curl_init('http://example.com/upload.php');
      
      // 通过过程化函数创建上传文件对象
      $cfile = curl_file_create('cats.jpg','image/jpeg','test_name');
      // 通过构造器创建上传文件对象
      //$cfile = new CURLFile('cats.jpg','image/jpeg','test_name');
      
      // Assign POST data
      $data = array('test_file' => $cfile);
      curl_setopt($ch, CURLOPT_POST,1);
      curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
      
      // Execute the handle
      curl_exec($ch);
      
  • memcached

    memcached是一个高性能分布式的内存对象缓存系统,通常被用于降低数据库加载压力以提高动态web应用的响应速度。

    此扩展使用了libmemcached库提供的api与memcached服务端进行交互。它同样提供了一个session处理器(memcached)。它同时提供了一个session处理器(memcached)。

    • 安装

      https://pecl.php.net/package/memcached

    • 超时时间

      部分存储命令在发送时会包含一个失效值到服务端。实际发送的值可以是一个Unix时间戳timestamp,或者是一个从现在算起的以秒为单位的数字。对于后一种情况,这个秒数不能超过60×60×24×30(30天时间的秒数),如果失效的值大于这个值,服务端会将其作为一个真实的Unix时间戳来处理而不是自当前时间的偏移。

      注意:如果失效值被设置为0(默认),此元素永不过期(但是它可能由于服务端为了给其他新的元素分配空间而被删除)。

    • sessions支持

      memcached提供了一个自定义的session处理器可以被用于存储用户session数据到memcached服务端。 一个完全独立的memcached实例将会在内部使用,因此如果需要您可以设置一个不同的服务器池。

      session.save_handler string 
      
      ;设置为memcached开启memcached的session处理器。 
      
      session.save_path string 
            
      ;定义一个逗号分隔的hostname:port样式的session缓存服务器池,例如: "sess1:11211, sess2:11211". 
      
      
    • Memcached::add — 向一个新的key下面增加一个元素

      public Memcached::add( string $key, mixed $value[, int $expiration] ) : bool
      

      Memcached::add()与Memcached::set()类似,但是如果 key已经在服务端存在,此操作会失败。

    • Memcached::addByKey — 在指定服务器上的一个新的key下增加一个元素

    • Memcached::addServer — 向服务器池中增加一个服务器

    • Memcached::addServers — 向服务器池中增加多台服务器

    • Memcached::append — 向已存在元素后追加数据

    • Memcached::appendByKey — 向指定服务器上已存在元素后追加数据

    • Memcached::cas — 比较并交换值

    • Memcached::casByKey — 在指定服务器上比较并交换值

    • Memcached::__construct — 创建一个Memcached实例

    • Memcached::decrement — 减小数值元素的值

      Memcached::decrement()减小一个数值元素的值,减小多少由参数offset决定。如果元素的值不是数值,以0值对待。如果减小后的值小于0,则新的值被设置为0.如果元素不存在,Memcached::decrement() 失败。

    • Memcached::decrementByKey — Decrement numeric item’s value, stored on a specific server

    • Memcached::delete — 删除一个元素

      Memcached::delete()从服务端删除key对应的元素. 参数time是一个秒为单位的时间(或一个UNIX时间戳表明直到那个时间), 用来表明客户端希望服务端在这段时间拒绝对这个key的add和replace命令. 由于这个时间段的存在, 元素被放入一个删除队列, 表明它不可以通过get命令获取到值, 但是同时 add和replace命令也会失败(无论如何set命令都会成功). 在这段时间过去后, 元素最终被从服务端内存删除.time参数默认0(表明元素会被立即删除并且之后对这个 key的存储命令也会成功).

    • Memcached::deleteByKey — 从指定的服务器删除一个元素

    • Memcached::deleteMulti — Delete multiple items

    • Memcached::deleteMultiByKey — Delete multiple items from a specific server

    • Memcached::fetch — 抓取下一个结果

    • Memcached::fetchAll — 抓取所有剩余的结果

    • Memcached::flush — 作废缓存中的所有元素

    • Memcached::get — 检索一个元素

      返回存储在服务端的元素的值或者在其他情况下返回FALSE。如果key不存在,Memcached::getResultCode()返回Memcached::RES_NOTFOUND。

    • Memcached::getAllKeys — Gets the keys stored on all the servers

      查询每个memcache服务器,并检索当时存储在服务器上的所有键的数组。这不是一个原子操作,因此它不是键在某个时间点上的真正一致的快照。由于memcache不能保证返回所有的键值,所以也不能假设所有的键值都已经返回。

    • Memcached::getByKey — 从特定的服务器检索元素

    • Memcached::getDelayed — 请求多个元素

      Memcached::getDelayed()向Memcached服务端发出一个检索keys指定的多个 key对应元素的请求。这个方法不会等待响应而是立即返回。当你需要收集元素值时, 调用Memcached::fetch()或 Memcached::fetchAll()。如果with_cas设置为true,会同时请求每个元素的CAS标记。

      可以通过参数value_cb指定一个result callback来替代明确的抓取结果(fetch或fetchAll为明确抓取方式)。

    • Memcached::getDelayedByKey — 从指定的服务器上请求多个元素

    • Memcached::getMulti — 检索多个元素

    • Memcached::getMultiByKey — 从特定服务器检索多个元素

    • Memcached::getOption — 获取Memcached的选项值

    • Memcached::getResultCode — 返回最后一次操作的结果代码

    • Memcached::getResultMessage — 返回最后一次操作的结果描述消息

    • Memcached::getServerByKey — 获取一个key所映射的服务器信息

    • Memcached::getServerList — 获取服务器池中的服务器列表

    • Memcached::getStats — 获取服务器池的统计信息

    • Memcached::getVersion — 获取服务器池中所有服务器的版本信息

    • Memcached::increment — 增加数值元素的值

      Memcached::increment() 将一个数值元素增加参数 offset 指定的大小。如果元素的值不是数值类型,将返回错误。如果元素不存在, Memcached::increment() 会将元素设置成 initial_value 指定的值。

    • Memcached::incrementByKey — Increment numeric item’s value, stored on a specific server

    • Memcached::isPersistent — 检查memcache服务器的连接是否为持久连接。

      检查memcache服务器的连接是否为持久连接。

    • Memcached::isPristine — Check if the instance was recently created

    • Memcached::prepend — 向一个已存在的元素前面追加数据

    • Memcached::prependByKey — Prepend data to an existing item on a specific server

    • Memcached::quit — 关闭所有打开的链接。

      Memcached::quit() 关闭所有memcache服务器的链接。

    • Memcached::replace — 替换已存在key下的元素

      Memcached::replace()和Memcached::set()类似,但是如果服务端不存在key, 操作将失败。

    • Memcached::replaceByKey — Replace the item under an existing key on a specific server

    • Memcached::resetServerList — Clears all servers from the server list

    • Memcached::set — 存储一个元素

      Memcached::set()将value 存储在一个memcached服务器上的key下。expiration参数用于控制值的过期时间。

      值可以是任何有效的非资源型php类型, 因为资源类型不能被序列化存储。如果Memcached::OPT_COMPRESSION 选项开启, 序列化的值同样会被压缩存储。

    • Memcached::setByKey — 将元素存储到指定的服务器上

    • Memcached::setMulti — 存储多个元素

      Memcached::setMulti()类似于Memcached::set(), 但是使用了参数items指定多个元素来替代单独的key/value设置以便于对多个元素的操作。expiration 参数指定的时候一次应用到所有的元素上。

    • Memcached::setMultiByKey — Store multiple items on a specific server

    • Memcached::setOption — 设置一个memcached选项

    • Memcached::setOptions — Set Memcached options

    • Memcached::setSaslAuthData — Set the credentials to use for authentication

    • Memcached::touch — 在给定的键上设置新的过期值。

      在给定的键上设置新的过期值。类似于redis的ttl。

    • Memcached::touchByKey — Set a new expiration on an item on a specific server

  • sockets

    Socket扩展是基于流行的BSD sockets,实现了和socket通讯功能的底层接口,它可以和客户端一样当做一个socket服务器。

    想了解更通用的客户端socket接口,请看 stream_socket_client(), stream_socket_server(), fsockopen(), 和 pfsockopen()。

    • socket_accept — Accepts a connection on a socket
    • socket_addrinfo_bind — Create and bind to a socket from a given addrinfo
    • socket_addrinfo_connect — Create and connect to a socket from a given addrinfo
    • socket_addrinfo_explain — Get information about addrinfo
    • socket_addrinfo_lookup — Get array with contents of getaddrinfo about the given hostname
    • socket_bind — 给套接字绑定名字
    • socket_clear_error — 清除套接字或者最后的错误代码上的错误
    • socket_close — 关闭套接字资源
    • socket_cmsg_space — Calculate message buffer size
    • socket_connect — 开启一个套接字连接
    • socket_create_listen — Opens a socket on port to accept connections
    • socket_create_pair — Creates a pair of indistinguishable sockets and stores them in an array
    • socket_create — 创建一个套接字(通讯节点)
    • socket_export_stream — Export a socket extension resource into a stream that encapsulates a socket
    • socket_get_option — Gets socket options for the socket
    • socket_getopt — 别名 socket_get_option
    • socket_getpeername — Queries the remote side of the given socket which may either result in host/port or in a Unix filesystem path, dependent on its type
    • socket_getsockname — Queries the local side of the given socket which may either result in host/port or in a Unix filesystem path, dependent on its type
    • socket_import_stream — Import a stream
    • socket_last_error — Returns the last error on the socket
    • socket_listen — Listens for a connection on a socket
    • socket_read — Reads a maximum of length bytes from a socket
    • socket_recv — 从已连接的socket接收数据
    • socket_recvfrom — Receives data from a socket whether or not it is connection-oriented
    • socket_recvmsg — Read a message
    • socket_select — Runs the select() system call on the given arrays of sockets with a specified timeout
    • socket_send — Sends data to a connected socket
    • socket_sendmsg — Send a message
    • socket_sendto — Sends a message to a socket, whether it is connected or not
    • socket_set_block — Sets blocking mode on a socket resource
    • socket_set_nonblock — Sets nonblocking mode for file descriptor fd
    • socket_set_option — Sets socket options for the socket
    • socket_setopt — 别名 socket_set_option
    • socket_shutdown — Shuts down a socket for receiving, sending, or both
    • socket_strerror — Return a string describing a socket error
    • socket_write — Write to a socket
    • socket_wsaprotocol_info_export — Exports the WSAPROTOCOL_INFO Structure
    • socket_wsaprotocol_info_import — Imports a Socket from another Process
    • socket_wsaprotocol_info_release — Releases an exported WSAPROTOCOL_INFO Structure
  • zookeeper

    这个扩展使用libzookeeper库来提供与ZooKeeper服务通信的API。

    ZooKeeper是Apache的一个项目,可以集中服务维护配置信息、命名、提供分布式同步和提供组服务。

    ZooKeeper概念详解,最全整理_春风化雨-CSDN博客_zookeeper

    配置中心——让配置管理更简单 - 云+社区 - 腾讯云

    基于zookeeper实现统一配置管理_菜 头笔记-CSDN博客_zookeeper 配置管理

网络函数

提供一系列联网函数。

  • checkdnsrr — 给指定的主机(域名)或者IP地址做DNS通信检查

  • closelog — 关闭系统日志链接

  • define_syslog_variables — Initializes all syslog related variables

  • dns_check_record — 别名 checkdnsrr

    根据不同记录(type)类型查询主机(host)相应的DNS记录。

    host:主机(host)可以是一个IP地址也可以是域名。

    type:解析记录类型(type)可能是下面这些类型中的任何一个:A,MX,NS,SOA,PTR,CNAME,AAAA,A6, SRV,NAPTR,TXT 或者 ANY。

  • dns_get_mx — 别名 getmxrr

  • dns_get_record — 获取指定主机的DNS记录

    获取指定主机(hostname)的DNS记录。

  • fsockopen — 打开一个网络连接或者一个Unix套接字连接

    fsockopen()将返回一个文件句柄,之后可以被其他文件类函数调用(例如:fgets(),fgetss(),fwrite(),fclose()还有feof())。如果调用失败,将返回FALSE。

  • gethostbyaddr — 获取指定的IP地址对应的主机名

  • gethostbyname — 返回主机名对应的 IPv4地址。

  • gethostbynamel — 获取互联网主机名对应的 IPv4 地址列表

  • gethostname — 获取主机名

  • getmxrr — 获取互联网主机名对应的 MX 记录

  • getprotobyname — Get protocol number associated with protocol name

  • getprotobynumber — Get protocol name associated with protocol number

  • getservbyname — 获取互联网服务协议对应的端口

  • getservbyport — Get Internet service which corresponds to port and protocol

  • header_register_callback — 调用一个 header 函数

    注册一个函数,在 PHP 开始发送输出时调用。

    PHP 准备好所有响应头,在发送内容之前执行 callback,创建了一个发送响应头的操作窗口。

  • header — 发送原生 HTTP 头

    header() 用于发送原生的 HTTP 头。

    请注意 header() 必须在任何实际输出之前调用,不管是普通的 HTML 标签,还是文件或 PHP 输出的空行,空格。这是个常见的错误,在通过include,require,或者其访问其他文件里面的函数的时候,如果在header()被调用之前,其中有空格或者空行。同样的问题也存在于单独的 PHP/HTML 文件中。

    //200 正常状态  
    header('HTTP/1.1 200 OK');  
      
    // 301 永久重定向,记得在后面要加重定向地址 Location:$url  
    header('HTTP/1.1 301 Moved Permanently');  
      
    // 重定向,其实就是302 暂时重定向  
    header('Location: http://www.maiyoule.com/');  
      
    // 设置页面304 没有修改  
    header('HTTP/1.1 304 Not Modified');  
      
    // 显示登录框,  
    header('HTTP/1.1 401 Unauthorized');  
    header('WWW-Authenticate: Basic realm="登录信息"');  
    echo '显示的信息!';  
    
    if (!isset($_SERVER['PHP_AUTH_USER'])) {
        header('WWW-Authenticate: Basic realm="My Realm1"');
        header('HTTP/1.0 401 Unauthorized');
        echo 'Text to send if user hits Cancel button';
        exit;
    } else {
        echo "<p>Hello {$_SERVER['PHP_AUTH_USER']}.</p>";
        echo "<p>You entered {$_SERVER['PHP_AUTH_PW']} as your password.</p>";
    }
      
    // 403 禁止访问  
    header('HTTP/1.1 403 Forbidden');  
      
    // 404 错误  
    header('HTTP/1.1 404 Not Found');  
      
    // 500 服务器错误  
    header('HTTP/1.1 500 Internal Server Error');  
      
    // 3秒后重定向指定地址(也就是刷新到新页面与 <meta http-equiv="refresh" content="10;http://www.9ong.com/ /> 相同)  
    header('Refresh: 3; url=http://www.9ong.com/');  
    echo '10后跳转到http://www.9ong.com';  
      
    // 重写 X-Powered-By 值  
    header('X-Powered-By: PHP/5.3.0');  
    header('X-Powered-By: Brain/0.6b');  
      
    //设置上下文语言  
    header('Content-language: en');  
      
    // 设置页面最后修改时间(多用于防缓存)  
    $time = time() - 60; //建议使用filetime函数来设置页面缓存时间  
    header('Last-Modified: '.gmdate('D, d M Y H:i:s', $time).' GMT');  
      
    // 设置内容长度  
    header('Content-Length: 39344');  
      
    // 设置头文件类型,可以用于流文件或者文件下载  
    header('Content-Type: application/octet-stream');  
    header('Content-Disposition: attachment; filename="example.zip"');   
    header('Content-Transfer-Encoding: binary');  
    readfile('example.zip');//读取文件到客户端  
      
    //禁用页面缓存  
    header('Cache-Control: no-cache, no-store, max-age=0, must-revalidate');  
    header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');   
    header('Pragma: no-cache');  
      
    //设置页面头信息  
    header('Content-Type: text/html; charset=iso-8859-1');  
    header('Content-Type: text/html; charset=utf-8');  
    header('Content-Type: text/plain');   
    header('Content-Type: image/jpeg');   
    header('Content-Type: application/zip');   
    header('Content-Type: application/pdf');   
    header('Content-Type: audio/mpeg');  
    header('Content-Type: application/x-shockwave-flash');   
    
    
    //声明一个下载的文件
    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename="testname.zip"');
    header('Content-Transfer-Encoding: binary');
    readfile('test.zip');
      
      
    //对当前文档禁用缓存
    header('Cache-Control: no-cache, no-store, max-age=0, must-revalidate');
    header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
      
      
      
      
    //声明一个需要下载的xls文件
    header('Content-Disposition: attachment; filename=ithhc.xlsx');
    header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
    header('Content-Length: '.filesize('./test.xls')); 
    header('Content-Transfer-Encoding: binary'); 
    header('Cache-Control: must-revalidate'); 
    header('Pragma: public'); 
    readfile('./test.xls'); 
    
  • header_remove — 删除之前设置的 HTTP 头

    删除之前用 header() 设置的 HTTP 头。

  • headers_list — 返回已发送的 HTTP 响应头(或准备发送的)

    headers_list() 会返回准备发送给浏览器/客户端的 HTTP 头列表。检测这些头是否已经发送,使用 headers_sent()。

  • headers_sent — 检测 HTTP 头是否已经发送

  • http_response_code — 获取/设置响应的 HTTP 状态码

    如果提供了 response_code,将返回先前的状态码。如果未提供 response_code,会返回当前的状态码。在 Web 服务器环境里,这些状态码的默认值都是 200。

  • inet_ntop — Converts a packed internet address to a human readable representation

  • inet_pton — Converts a human readable IP address to its packed in_addr representation

  • ip2long — 将 IPV4 的字符串互联网协议转换成长整型数字

  • long2ip — 将长整型转化为字符串形式带点的互联网标准格式地址(IPV4)

  • openlog — Open connection to system logger

  • pfsockopen — 打开一个持久的网络连接或者Unix套接字连接。

    这个函数的作用与fsockopen()完全一样的,不同的地方在于当在脚本执行完后,连接一直不会关闭。可以说它是fsockopen()的长连接版本。

  • setcookie — 发送 Cookie

    setcookie() 定义了 Cookie,会和剩下的 HTTP 头一起发送给客户端。和其他 HTTP 头一样,必须在脚本产生任意输出之前发送 Cookie(由于协议的限制)。请在产生任何输出之前(包括 和 或者空格)调用本函数。

    一旦设置 Cookie 后,下次打开页面时可以使用 $_COOKIE 读取。 Cookie 值同样也存在于 $_REQUEST。

    参数:

    • name

      Cookie 名称。 value Cookie 值。这个值储存于用户的电脑里,请勿储存敏感信息。比如 name 是 ‘cookiename’,可通过 $_COOKIE[‘cookiename’] 获取它的值。

    • expire

      Cookie 的过期时间。这是个 Unix 时间戳,即 Unix 纪元以来(格林威治时间 1970 年 1 月 1 日 00:00:00)的秒数。也就是说,基本可以用 time() 函数的结果加上希望过期的秒数。或者也可以用 mktime()。 time()+606024*30 就是设置 Cookie 30 天后过期。如果设置成零,或者忽略参数, Cookie 会在会话结束时过期(也就是关掉浏览器时)。

      expire 使用 Unix 时间戳而非 Wdy, DD-Mon-YYYYHH:MM:SS GMT 这样的日期格式,是因为 PHP 内部作了转换。

    • path

      Cookie 有效的服务器路径。设置成 ‘/’ 时,Cookie 对整个域名 domain 有效。如果设置成 ‘/foo/', Cookie 仅仅对 domain 中 /foo/ 目录及其子目录有效(比如 /foo/bar/)。默认值是设置 Cookie 时的当前目录。

    • domain

      Cookie 的有效域名/子域名。设置成子域名(例如 ‘www.example.com’),会使 Cookie 对这个子域名和它的三级域名有效(例如 w2.www.example.com)。要让 Cookie 对整个域名有效(包括它的全部子域名),只要设置成域名就可以了(这个例子里是 ‘example.com’)。

      旧版浏览器仍然在使用废弃的 » RFC 2109,需要一个前置的点 . 来匹配所有子域名。

    • secure

      设置这个 Cookie 是否仅仅通过安全的 HTTPS 连接传给客户端。设置成 TRUE 时,只有安全连接存在时才会设置 Cookie。如果是在服务器端处理这个需求,程序员需要仅仅在安全连接上发送此类 Cookie (通过 $_SERVER[“HTTPS”] 判断)。

    • httponly

      设置成 TRUE,Cookie 仅可通过 HTTP 协议访问。这意思就是 Cookie 无法通过类似 JavaScript 这样的脚本语言访问。要有效减少 XSS 攻击时的身份窃取行为,可建议用此设置(虽然不是所有浏览器都支持),不过这个说法经常有争议。 PHP 5.2.0 中添加。 TRUE 或 FALSE

  • setrawcookie — 发送未经 URL 编码的 cookie

    setrawcookie() 和 setcookie() 非常相似,唯一不同之处是发送到浏览器的 cookie 值没有自动经过 URL 编码(urlencode)。

  • socket_get_status — 别名 stream_get_meta_data

  • socket_set_blocking — 别名 stream_set_blocking

  • socket_set_timeout — 别名 stream_set_timeout

  • syslog — 生成系统日志消息

    syslog()生成将由系统日志记录器分发的日志消息。

    我们建议使用seaslog扩展来记录日志。

搜索引擎扩展

  • sphinx

    Sphinx是一款基于SQL的高性能全文检索引擎,Sphinx的性能在众多全文检索引擎中也是数一数二的,利用Sphinx,我们可以完成比数据库本身更专业的搜索功能,而且可以有很多针对性的性能优化。

    Sphinx : 高性能SQL全文检索引擎

    PHP+MySQL+Sphinx 搜索引擎架构图

    php扩展SphinxClient 为 Sphinx 提供了面向对象的接口.。

    安装:https://pecl.php.net/package/sphinx

针对服务器的扩展

  • Apache函数

    • apache_child_terminate — 在本次请求结束后终止 apache 子进程

    • apache_get_modules — 获得已加载的Apache模块列表

    • apache_get_version — 获得Apache版本信息

    • apache_getenv — 获取 Apache subprocess_env 变量

    • apache_lookup_uri — 对指定的 URI 执行部分请求并返回所有有关信息

    • apache_note — 取得或设置 apache 请求记录

    • apache_request_headers — 获取全部 HTTP 请求头信息

    • apache_reset_timeout — 重置 Apache 写入计时器

    • apache_response_headers — 获得全部 HTTP 响应头信息

    • apache_setenv — 设置 Apache 子进程环境变量

    • getallheaders — 获取全部 HTTP 请求头信息

      注意:被改名而成为 apache_request_headers() 的别名。因为此函数仅适用于 Apache 。

    • virtual — 执行 Apache 子请求

  • FPM函数

    • fastcgi_finish_request — 冲刷(flush)所有响应的数据给客户端

      此函数冲刷(flush)所有响应的数据给客户端并结束请求。这使得客户端结束连接后,需要大量时间运行的任务能够继续运行。

      在调用这个函数的时候, 会发送响应, 关闭连接. 但是不会结束PHP的运行。

      参考鸟哥对于这个函数的理解:使用fastcgi_finish_request提高页面响应速度 - 风雪之隅

      echo '例子:';
      file_put_contents('log.txt', date('Y-m-d H:i:s') . " 上传视频\n", FILE_APPEND);
      fastcgi_finish_request();
      echo "形而上学";
      sleep(1);
      file_put_contents('log.txt', date('Y-m-d H:i:s') . " 转换格式\n", FILE_APPEND);
      sleep(1);
      file_put_contents('log.txt', date('Y-m-d H:i:s') . " 提取图片\n", FILE_APPEND);
      

      通过浏览器访问此脚本, 结果发现并没有输出函数之后相应的字符串"形而上学”,但却生成了相应的文件,并记录字符串到文件。由此说明在调用fastcgi_finish_request后,客户端响应就已经结束,但与此同时服务端脚本却继续运行。

      由于函数仅在FPM环境下有效,为了兼容性:

      if (!function_exists("fastcgi_finish_request")) {
          function fastcgi_finish_request()  {
          }
      }
      

Session 扩展

  • 工作流程

    会话的工作流程很简单。当开始一个会话时,PHP 会尝试从请求中查找会话 ID (通常通过会话 cookie),如果请求中不包含会话 ID 信息,PHP 就会创建一个新的会话。会话开始之后,PHP 就会将会话中的数据设置到 $_SESSION 变量中。当 PHP 停止的时候,它会自动读取 $_SESSION 中的内容,并将其进行序列化,然后发送给会话保存管理器来进行保存。

    默认情况下,PHP 使用内置的文件会话保存管理器(files)来完成会话的保存。也可以通过配置项 session.save_handler 来修改所要采用的会话保存管理器。对于文件会话保存管理器,会将会话数据保存到配置项 session.save_path 所指定的位置。

    可以通过调用函数 session_start() 来手动开始一个会话。如果配置项 session.auto_start 设置为1,那么请求开始的时候,会话会自动开始。

    PHP 脚本执行完毕之后,会话会自动关闭。同时,也可以通过调用函数 session_write_close() 来手动关闭会话。

  • 会话id

    一个访问者访问你的 web 网站将被分配一个唯一的 id, 就是所谓的会话 id. 这个 id 可以存储在用户端的一个 cookie 中,也可以通过 URL 进行传递。

    有两种方式用来传送会话 ID:

    • Cookies
    • URL 参数

    会话模块支持这两种方式。 Cookie 方式相对好一些,但是用户可能在浏览器中关闭 Cookie,所以第二种方案就是把会话 ID 直接并入到 URL 中,以保证会话 ID 的传送。

    无需开发人员干预,PHP 就可以自动处理 URL 传送会话 ID 的场景。如果启用了 session.use_trans_sid 选项, PHP 将会自动在相对 URI 中包含会话 ID。

    会话开始之后,可以使用 SID 常量。如果客户端未提供会话 cookie,该常量的展开形式为 session_name=session_id,反之,该常量为空字符串。因此,可以直接在 URL 中包含此常量的展开字符串而无需考虑会话 ID 的实际传送方式。

  • 序列化

    $_SESSION (和所有已注册得变量) 将被 PHP 使用内置的序列化方法在请求完成时进行序列化。

  • 会话安全

    安全重于业务,目前大部分场景都还是采用php的会话方式实现通信定制,对于安全,要重视再重视,先从会话安全开始,了解会话管理、会话问题、会话安全配置等:

    PHP: 会话和安全 - Manual

    • 会话信息不安全,会话ID泄露。

      会话模块无法保证你存储在会话中的信息只能被创建会话的用户本人可见。你需要采取额外的手段来保护会话中的机密信息,至于采取何种方式来保护机密信息,取决于你在会话中存储的数据的机密程度。

      有很多种方式都可以导致会话 ID 被泄露给第三方。例如,JavaScript 注入,URL 中包含会话 ID,数据包侦听,或者直接访问你的物理设备等。如果会话 ID 被泄漏给第三方,那么他们就可以访问这个会话 ID 可以访问的全部资源。

    • 严格会话

      从 PHP 5.5.2 开始,新增加了一个配置项: session.use_strict_mode。当启用这个配置项,并且你所用的会话存储处理器支持的话,未经初始化的会话 ID 会被拒绝,并为其生成一个全新的会话,这可以避免攻击者使用一个已知的会话 ID 来进行攻击。

    • 会话与自动登录

      开发者不应该通过使用长生命周期的会话 ID 来实现自动登录功能,因为这种方式提高了会话被窃取的风险。开发者应该自己实现自动登录的机制。

    • CSRF跨站请求伪造攻击

      会话和认证无法避免跨站请求伪造攻击。开发者需要自己来实现保护应用不受 CSRF 攻击的功能。

      output_add_rewrite_var() 函数可以用来保护应用免受 CSRF 攻击。

      大部分 Web 应用框架都提供了 CSRF 保护的特性。详细信息请参考你所用的 Web 框架的文档。

      从 PHP 7.3 开始,对于会话 cookie 增加了 SameSite 属性,这个属性可以有效的降低 CSRF 攻击的风险。

  • 会话文件锁

    无论是通过调用函数 session_start() 手动开启会话,还是使用配置项 session.auto_start 自动开启会话,对于基于文件的会话数据保存(PHP 的默认行为)而言,在会话开始的时候都会给会话数据文件加锁,直到 PHP 脚本执行完毕或者显式调用 session_write_close() 来保存会话数据。在此期间,其他脚本不可以访问同一个会话数据文件。

    对于大量使用 Ajax 或者并发请求的网站而言,这可能是一个严重的问题。解决这个问题最简单的做法是如果修改了会话中的变量,那么应该尽快调用 session_write_close() 来保存会话数据并释放文件锁。还有一种选择就是使用支持并发操作的会话保存管理器来替代文件会话保存管理器。

  • 自定义会话管理器

    如果需要在数据库中或者以其他方式存储会话数据,需要使用 session_set_save_handler() 函数来创建一系列用户级存储函数。 PHP 5.4.0 之后,你可以使用 SessionHandlerInterface 类或者通过继承 SessionHandler 类来扩展内置的管理器,从而达到自定义会话保存机制的目的。

    函数 session_set_save_handler() 的参数即为在会话生命周期内要调用的一组回调函数: open, read, write 以及 close。还有一些回调函数被用来完成垃圾清理:destroy 用来删除会话, gc 用来进行周期性的垃圾收集。

    因此,会话保存管理器对于 PHP 而言是必需的。默认情况下会使用内置的文件会话保存管理器。可以通过 session_set_save_handler() 函数来设置自定义会话保存管理器。一些 PHP 扩展也提供了内置的会话管理器,例如:sqlite, memcache 以及 memcached,可以通过配置项 session.save_handler 来使用它们。

    会话管理器工作流程:

    会话开始的时候,PHP 会调用 open 管理器,然后再调用 read 回调函数来读取内容,该回调函数返回已经经过编码的字符串。然后 PHP 会将这个字符串解码,并且产生一个数组对象,然后保存至 $_SESSION 超级全局变量。

    当 PHP 关闭的时候(或者调用了 session_write_close() 之后), PHP 会对 $_SESSION 中的数据进行编码,然后和会话 ID 一起传送给 write 回调函数。 write 回调函数调用完毕之后,PHP 内部将调用 close 回调函数。

    销毁会话时,PHP 会调用 destroy 回调函数。

    根据会话生命周期时间的设置,PHP 会不时地调用 gc 回调函数。该函数会从持久化存储中删除超时的会话数据。超时是指会话最后一次访问时间距离当前时间超过了 $lifetime 所指定的值。

    所以,php会话生命周期并不是实时结束的,可能过期了,但还能访问。

  • Session函数

    • session_start — 启动新会话或者重用现有会话

      session_start() 会创建新会话或者重用现有会话。如果通过 GET 或者 POST 方式,或者使用 cookie 提交了会话 ID,则会重用现有会话。

    • session_unset — 释放所有的会话变量

      session_unset() 会释放当前会话注册的所有会话变量。

      注意:请不要使用unset($_SESSION)来释放整个$_SESSION,因为它将会禁用通过全局$_SESSION去注册会话变量

      注意:session_unset仅从会话中删除变量-会话仍然存在。如果要销毁会话请使用session_destory

    • session_destroy — 销毁一个会话中的全部数据

      session_destroy() 销毁当前会话中的全部数据,但是不会重置当前会话所关联的全局变量,也不会重置会话 cookie。如果需要再次使用会话变量,必须重新调用 session_start() 函数。

      意味着:session_destory删除整个会话

      注意:删除当前用户对应的session文件以及释放sessionid,内存中的$_SESSION变量内容依然保留。

      所以彻底的销毁一个会话,我们建议:

      session_start();
      $_SESSION["name"] = "tsingchan";
      session_unset();
      session_destroy();
      var_dump($_SESSION);
      var_dump($_SESSION['name']); //如果没有session_unset,将会继续输出tsingchan,如果没有session_detory,那么会话仍然存在,只是name不存在了
      
    • session_save_path — 读取/设置当前会话的保存路径

      指定会话数据保存的路径。必须在调用 session_start() 函数之前调用 session_save_path() 函数。

    • session_name — 读取/设置会话名称

      用在 cookie 或者 URL 中的会话名称,例如:PHPSESSID。只能使用字母和数字作为会话名称,建议尽可能的短一些,并且是望文知意的名字(对于启用了 cookie 警告的用户来说,方便其判断是否要允许此 cookie)。如果指定了 name 参数,那么当前会话也会使用指定值作为名称。

      请求开始的时候,会话名称会被重置并且存储到 session.name 配置项。因此,要想设置会话名称,那么对于每个请求,都需要在调用 session_start() 函数之前调用 session_name() 函数。

    • session_id — 获取/设置当前会话 ID

      如果指定了 id 参数的值,则使用指定值作为会话 ID。必须在调用 session_start() 函数之前调用 session_id() 函数。不同的会话管理器对于会话 ID 中可以使用的字符有不同的限制。例如文件会话管理器仅允许会话 ID 中使用以下字符:a-z A-Z 0-9 , (逗号)和 - (减号)

    • session_regenerate_id — 使用新生成的会话 ID 更新现有会话 ID

      在不修改当前会话中数据的前提下使用新的 ID 替换原有会话 ID。

      session_regenerate_id([ bool $delete_old_session = FALSE] ) : bool
      

      参数$delete_old_session表示是否删除原 ID 所关联的会话存储文件。如果你需要避免会话并发访问冲突,那么不应该立即删除会话中的数据。如果你需要防止会话劫持攻击,那么可以立即删除会话数据。

      session_start();
      $_SESSION["name"] = "tsingchan";
      
      echo session_id();
      echo "<br />";
      session_regenerate_id(true);//为当前会话重新生成会话id,下一次访问将自动更换会话id(前后端)
      echo session_id();
      echo "<br />";
      var_dump($_SESSION);
      var_dump($_SESSION['name']);
      //session_unset();
      //session_destroy();
      
    • session_write_close — Write session data and end session

      结束当前会话并存储会话数据。

      我们可以手动结束会话。

      会话数据通常在脚本终止后存储,而不需要调用session_write_close(),但是由于会话数据被锁定以防止并发写,所以在任何时候只有一个脚本可以对会话进行操作。

    • session_set_save_handler — 设置用户自定义会话存储函数

      如果需要在数据库中或者以其他方式存储会话数据,需要使用 session_set_save_handler() 函数来创建一系列用户级存储函数。 PHP 5.4.0 之后,你可以使用 SessionHandlerInterface 类或者通过继承 SessionHandler 类来扩展内置的管理器,从而达到自定义会话保存机制的目的。

      函数 session_set_save_handler() 的参数即为在会话生命周期内要调用的一组回调函数: open, read, write 以及 close。还有一些回调函数被用来完成垃圾清理:destroy 用来删除会话, gc 用来进行周期性的垃圾收集。

      session_set_save_handler有两种传参实现方式:

      session_set_save_handler( callable $open, callable $close, callable $read, callable $write, callable $destroy, callable $gc[, callable $create_sid[, callable $validate_sid[, callable $update_timestamp]]] ) : bool
      

      自 PHP 5.4 开始,可以使用下面的方式来注册自定义会话存储函数:

      session_set_save_handler( object $sessionhandler[, bool $register_shutdown = TRUE] ) : bool
      

      $sessionhandler实现了 SessionHandlerInterface, SessionIdInterface 和/或 SessionUpdateTimestampHandlerInterface 接口的对象,例如 SessionHandler。自 PHP 5.4 之后可以使用。

      $register_shutdown将函数 session_write_close() 注册为 register_shutdown_function() 函数。

    • session_abort — Discard session array changes and finish session session_abort()在不保存数据的情况下完成会话。这样就保留了会话数据中的原始值。

    • session_cache_expire — 返回当前缓存的到期时间

    • session_cache_limiter — 读取/设置缓存限制器

    • session_commit — session_write_close 的别名

    • session_create_id — Create new session id

      用于为当前会话创建newsession id。它返回无冲突的会话id。

    • session_decode — 解码会话数据

    • session_encode — 将当前会话数据编码为一个字符串

    • session_gc — Perform session data garbage collection

    • session_get_cookie_params — 获取会话 cookie 参数

    • session_is_registered — 检查变量是否在会话中已经注册

    • session_module_name — 获取/设置会话模块名称

    • session_register_shutdown — 关闭会话

    • session_register — Register one or more global variables with the current session

    • session_reset — Re-initialize session array with original values

    • session_set_cookie_params — 设置会话 cookie 参数

    • session_status — 返回当前会话状态

      • PHP_SESSION_DISABLED 会话是被禁用的。
      • PHP_SESSION_NONE 会话是启用的,但不存在当前会话。
      • PHP_SESSION_ACTIVE 会话是启用的,而且存在当前会话。
    • session_unregister — Unregister a global variable from the current session

正则相关函数

  • PCRE

    PCRE 库是一个实现了与 perl 5 在语法和语义上略有差异(详见下文)的正则表达式模式匹配功能的函数集。当前的实现对应于 perl 5.005。

    正则表达式是一个从左到右匹配目标字符串的模式。大多数字符自身就代表一个匹配它们自身的模式。

    PCRE除了要了解正则表达式外,有一些特殊的知识点:

    • 分隔符

      当使用 PCRE 函数的时候,模式需要由分隔符闭合包裹。分隔符可以使任意非字母数字、非反斜线(通常说的转义符\)、非空白字符。

      经常使用的分隔符是正斜线(/)、hash符号(#) 以及取反符号(~)。

      比如以下都是合法的:

      /foo bar/
      #^[^0-9]$#
      +php+
      %[a-zA-Z0-9_-]%
      

      除了上面提到的分隔符,也可以使用括号样式的分隔符,左括号和右括号分别作为开始和结束分隔符。

      {this is a pattern}
      
    • 元字符

      参考:正则表达式

    • 子组/子模式

      子组通过圆括号()分隔界定,并且它们可以嵌套。将一个模式中的一部分标记为子组(子模式)主要是来做两件事情:

      • 将可选分支局部化。比如,模式cat(arcat|erpillar|)匹配 “cat”, “cataract”, “caterpillar” 中的一个,如果没有圆括号的话,它匹配的则是 “cataract”, “erpillar” 以及空字符串。

      • 将子组设定为捕获子组。当整个模式匹配后,目标字符串中匹配子组的部分将会通过 pcre_exec() 的 ovector 参数回传给调用者。左括号从左至右出现的次序就是对应子组的下标(从 1 开始),可以通过这些下标数字来获取捕获子模式匹配结果。 下标 0 获取的是整个字符串。

    • 模式修饰符

      i (PCRE_CASELESS),如果设置了这个修饰符,模式中的字母会进行大小写不敏感匹配

      s (PCRE_DOTALL)如果设置了这个修饰符,模式中的点号元字符匹配所有字符,包含换行符。如果没有这个修饰符,点号不匹配换行符。

    • 区别于POSIX函数

      自 PHP 5.3.0起, POSIX 正则表达式扩展被废弃。请尽量使用PCRE函数,也就是preg_前缀的函数:

      POSIX PCRE
      ereg_replace() preg_replace()
      ereg() preg_match()
      eregi_replace() preg_replace()
      eregi() preg_match()
      split() preg_split()
      spliti() preg_split()
      sql_regcase() 无对等函数
    • PCRE函数

      • preg_match — 执行匹配正则表达式

        搜索subject与pattern给定的正则表达式的一个匹配。

        preg_match( string $pattern, string $subject[, array &$matches[, int $flags = 0[, int $offset = 0]]] ) : int
        

        pattern:要搜索的模式,字符串类型。

        subject:输入字符串。

        matches:如果提供了参数matches,它将被填充为搜索结果。 $matches[0]将包含完整模式匹配到的文本, $matches[1] 将包含第一个捕获子组匹配到的文本,以此类推。

        flags:具体使用参考官方文档,比较少使用。

        offset:通常,搜索从目标字符串的开始位置开始。可选参数 offset 用于指定从目标字符串的某个位置开始搜索(单位是字节)。

        注意:preg_match()返回 pattern 的匹配次数。它的值将是0次(不匹配)或1次,因为preg_match()在第一次匹配后将会停止搜索。preg_match_all()不同于此,它会一直搜索subject 直到到达结尾。如果发生错误preg_match()返回 FALSE。

      • preg_match_all — 执行一个全局正则表达式匹配

        搜索subject中所有匹配pattern给定正则表达式的匹配结果并且将它们以flag指定顺序输出到matches中。

        在第一个匹配找到后, 子序列继续从最后一次匹配位置搜索。

        与preg_match函数是相似的,区别在于preg_match_all()不同于此,它会一直搜索subject 直到到达结尾。

        preg_match_all("|<[^>]+>(.*)</[^>]+>|U",
            "<b>example: </b><div align=left>this is a test</div>",
            $out, PREG_PATTERN_ORDER);
        echo $out[0][0] . ", " . $out[0][1] . "\n";
        echo $out[1][0] . ", " . $out[1][1] . "\n";
        

        输出:

        <b>example: </b>, <div align=left>this is a test</div>
        example: , this is a test
        

        可以通过flag参数调整matchs多维数组返回元素的结构: flag默认为PREG_PATTERN_ORDER,我们还可以设置PREG_SET_ORDER,则输出:

        <b>example: </b>, example: 
        <div align=left>this is a test</div>, this is a test
        
        
      • preg_grep — 返回匹配模式的数组元素

        返回给定数组input中与模式pattern 匹配的元素组成的数组.。数组的key使用匹配元素在原数组的key。

        preg_grep( string $pattern, array $input[, int $flags = 0] ) : array
        

        匹配数组中是浮点数的元素:

        $array = ["1.2","3",'45','6.7','8.0','9'];
        $fl_array = preg_grep("/^(\d+)?\.\d+$/", $array);
        print_r($fl_array);
        

        输出:

        Array
        (
            [0] => 1.2
            [3] => 6.7
            [4] => 8.0
        )
        
        
      • preg_split — 通过一个正则表达式分隔字符串

        preg_split( string $pattern, string $subject[, int $limit = -1[, int $flags = 0]] ) : array
        

        通过一个正则表达式分隔给定字符串。返回一个使用 pattern 边界分隔 subject 后得到的子串组成的数组, 或者在失败时返回 FALSE。

        如果指定limit参数,将限制分隔得到的子串最多只有limit个,返回的最后一个子串将包含所有剩余部分。limit值为-1, 0或null时都代表"不限制”。

        注意:如果不需要正则表达式功能,可以有更快(并且更简单)的选择比如 explode() 或 str_split()。

        flag设置为PREG_SPLIT_NO_EMPTY可以用于过滤空串。

      • preg_replace — 执行一个正则表达式的搜索和替换

        preg_replace( mixed $pattern, mixed $replacement, mixed $subject[, int $limit = -1[, int &$count]] ) : mixed
        

        搜索 subject 中匹配 pattern 的部分,以 replacement 进行替换。

        参数:replacement

        用于替换的字符串或字符串数组。如果这个参数是一个字符串,并且 pattern 是一个数组,那么所有的模式都使用这个字符串进行替换。如果 pattern 和 replacement 都是数组,每个 pattern 使用 replacement 中对应的元素进行替换。如果 replacement 中的元素比 pattern 中的少,多出来的 pattern 使用空字符串进行替换。

        $string = 'The quick brown brown fox jumps over the lazy dog.';
        $patterns = array();
        $patterns[0] = '/quick/';
        $patterns[1] = '/brown/';
        $patterns[2] = '/fox/';
        $replacements = array();
        $replacements[2] = 'bear';
        $replacements[1] = 'black';
        $replacements[0] = 'slow';
        
        echo preg_replace($patterns, $replacements, $string);//输出:The bear black black slow jumps over the lazy dog.
        
        //ksort($replacements);
        //ksort($patterns);
        //这里注意两个数组元素排序,并不是匹配patterns[0]并替换replaces[0],如果没有ksort的操作,将会是替换replaces[2]。注意数组元素的物理顺序。
        //echo preg_replace($patterns, $replacements, $string);//输出:The slow black black bear jumps over the lazy dog.
        
        $string = 'Mayl 10, 2020';
        $pattern = '/(\w+) (\d+), (\d+)/i';
        $replacement = '${1}1,$3';
        echo preg_replace($pattern, $replacement, $string);
        //输出:Mayl1,2020
        
      • preg_replace_callback — 执行一个正则表达式搜索并且使用一个回调进行替换

        这个函数的行为除了可以指定一个 callback 替代 replacement 进行替换字符串的计算,其他方面等同于 preg_replace()。

      • preg_replace_callback_array — Perform a regular expression search and replace using callbacks

      • preg_filter — 执行一个正则表达式搜索和替换

        preg_filter()等价于preg_replace() 除了它仅仅返回(可能经过转化)与目标匹配的结果。

      • preg_quote — 转义正则表达式字符

        preg_quote()需要参数 str 并向其中每个正则表达式语法中的字符前增加一个反斜线。 这通常用于你有一些运行时字符串需要作为正则表达式进行匹配的时候。

        正则表达式特殊字符有: . \ + * ? [ ^ ] $ ( ) { } = ! < > | : - #

        注意 / 不是正则表达式特殊字符。

      • preg_last_error — 返回最后一个PCRE正则执行产生的错误代码

      • preg_last_error_msg — 返回最后一次执行PCRE regex的错误消息

        成功时返回错误消息,如果没有发生错误,则返回“No error”。当然这个函数需要php8之后才支持。

  • POSIX正则函数

    该特性在PHP 5.3.0中已弃用,在PHP 7.0.0中已删除。

    POSIX的相关函数都可以通过PCRE函数来代替:

    POSIX PCRE
    ereg_replace() preg_replace()
    ereg() preg_match()
    eregi_replace() preg_replace()
    eregi() preg_match()
    split() preg_split()
    spliti() preg_split()
    sql_regcase() 无对等函数

字符串处理

  • addslashes — 使用反斜线引用字符串

    返回字符串,该字符串为了数据库查询语句等的需要在某些字符前加上了反斜线。这些字符是单引号(')、双引号(")、反斜线(\)与 NUL(NULL 字符)。

    注意:PHP 5.4 之前 PHP 指令 magic_quotes_gpc 默认是 on, 实际上所有的 GET、POST 和 COOKIE 数据都用被 addslashes() 了。 不要对已经被 magic_quotes_gpc 转义过的字符串使用 addslashes(),因为这样会导致双层转义。 遇到这种情况时可以使用函数 get_magic_quotes_gpc() 进行检测。

  • bin2hex — 函数把包含数据的二进制字符串转换为十六进制值

  • hex2bin — 转换十六进制字符串为二进制字符串

  • chop — rtrim 的别名

  • chr — 返回指定的字符

    返回相对应于 ascii 所指定的单个字符。

    此函数与 ord() 是互补的。

  • ord — 转换字符串第一个字节为 0-255 之间的值

  • convert_uuencode — 使用 uuencode 编码一个字符串

    convert_uuencode() 使用 uuencode 算法对一个字符串进行编码。

    uuencode 算法会将所有(含二进制数据)字符串转化为可输出的字符,并且可以被安全的应用于网络传输。使用 uuencode 编码后的数据将会比源数据大35%左右。

    用法同base64_encode,可以用于对二进制数据的编码。

  • convert_uudecode — 解码一个 uuencode 编码的字符串

  • count_chars — 返回字符串所用字符的信息

    count_chars( string $string[, int $mode = 0] ) : mixed
    

    统计 string 中每个字节值(0..255)出现的次数,使用多种模式返回结果。

    mode参数:

    0 - 以所有的每个字节值作为键名,出现次数作为值的数组。

    1 - 与 0 相同,但只列出出现次数大于零的字节值。

  • crc32 — 计算一个字符串的 crc32 多项式

    生成 str 的 32 位循环冗余校验码多项式。这通常用于检查传输的数据是否完整。

  • crypt — 单向字符串散列

    password_hash()使用了一个强的哈希算法,来产生足够强的盐值,并且会自动进行合适的轮次。password_hash()是crypt()的一个简单封装,并且完全与现有的密码哈希兼容。推荐使用password_hash()。

  • echo — 输出一个或多个字符串

  • explode — 使用一个字符串分割另一个字符串

  • implode — 将一个一维数组的值转化为字符串

    explode与implode目前尽量按照分割符参数在前,字符串或数组在后

    注意:implode第一个参数分隔符可以忽略,也就是只有一个参数数组时,会默认使用空字符作为分隔符连接字符串。

    implode( string $glue, array $pieces) : string
    
    implode( array $pieces) : string
    

    注意:join函数是implode的别名

  • get_html_translation_table — 返回使用 htmlspecialchars 和 htmlentities 后的转换表

    返回 htmlspecialchars() 和 htmlentities() 处理后的转换表。

    在很多自有框架中,我们常会看到内部都有一个函数是用于手动替换html特殊符号的,其实php自身带了一个函数可以提供html特殊符号的函数,不需要我们手动保存更新:

    print_r(get_html_translation_table(HTML_ENTITIES,ENT_COMPAT|ENT_QUOTES));    
    
    Array
    (
        ["] => &quot;
        [&] => &amp;
        ['] => &#039;
        [<] => &lt;
        [>] => &gt;
        [ ] => &nbsp;
        [¡] => &iexcl;
        [¢] => &cent;
        [£] => &pound;
        [¤] => &curren;
        [¥] => &yen;
        [¦] => &brvbar;
        [§] => &sect;
        [¨] => &uml;
        [©] => &copy;
        [ª] => &ordf;
        [«] => &laquo;
        [¬] => &not;
        ...
    
  • htmlentities — 将字符转换为 HTML 转义字符

    本函数各方面都和 htmlspecialchars() 一样,除了 htmlentities() 会转换所有具有 HTML 实体的字符。

  • html_entity_decode — Convert HTML entities to their corresponding characters

    htmlentities 的反向解码操作。

  • htmlspecialchars — 将特殊字符转换为 HTML 实体

    通过get_html_translation_table函数可以知道,只有5个特殊符号被定义为htmlspecialchars:

    
    ["] => &quot;
    [&] => &amp;
    ['] => &#039;
    [<] => &lt;
    [>] => &gt;
    
  • htmlspecialchars_decode — 将特殊的 HTML 实体转换回普通字符

    htmlspecialchars的反向解析操作。

  • lcfirst — 使一个字符串的第一个字符小写

  • ucfirst — 将字符串的首字母转换为大写

  • ucwords — 将字符串中每个单词的首字母转换为大写

    ucwords( string $str[, string $delimiters = " \t\r\n\f\v" ] ) : string
    

    可选的 delimiters,包含了单词分割字符。

    $foo = 'hello|world!';
    $bar = ucwords($foo);             // Hello|world!
    
    $baz = ucwords($foo, "|");        // Hello|World!
    
  • levenshtein — 计算两个字符串之间的编辑距离

  • md5_file — 计算指定文件的 MD5 散列值

  • md5 — 计算字符串的 MD5 散列值

    由于此函数依赖的算法已不足够复杂,不推荐使用此函数对明文密码加密。如果用于创建密码哈希值,建议使用password_hash() - 创建密码的散列(hash)

  • metaphone — 计算str的变音键

    与soundex()类似,metaphone为发音相似的单词创建相同的键。它比soundex()更准确,因为它知道英语发音的基本规则。变音位生成的键是可变长度的。

  • money_format — 将数字格式化成货币字符串

  • nl2br — 在字符串所有新行之前插入 HTML 换行标记

    在字符串 string 所有新行之前插入 ‘<br />’ 或 ‘<br>’,并返回。 可以理解为将\r\n替换成html换行标签<br />

  • number_format — 以千位分隔符方式格式化一个数字

  • parse_str — 将字符串解析成多个变量

    parse_str( string $encoded_string[, array &$result] ) : void
    

    如果 encoded_string 是 URL 传递入的查询字符串(query string),则将它解析为变量并设置到当前作用域(如果提供了 result 则会设置到该数组里 )。

    注意:我们强烈建议一定要带第二个参数result,变量将会以数组元素的形式存入到这个数组。该函数没有返回值,将由result作为替代

    $str = "first=value&arr[]=foo+bar&arr[]=baz";
    
    // 推荐用法
    parse_str($str, $output);
    echo $output['first'];  // value
    echo $output['arr'][0]; // foo bar
    echo $output['arr'][1]; // baz
    
    // 不建议这么用
    parse_str($str);
    echo $first;  // value
    echo $arr[0]; // foo bar
    echo $arr[1]; // baz
    
  • print — 输出字符串

    print 实际上不是函数(而是语言结构),所以可以不用圆括号包围参数列表。

    和 echo 最主要的区别: print 仅支持一个参数,并总是返回 1。

    还是用echo吧。

  • printf — 输出格式化字符串

  • sprintf — 输出格式化字符串

    可以理解为模板化输出。

    $num = 5;
    $location = 'tree';
    
    $format = 'There are %d monkeys in the %s';
    echo sprintf($format, $num, $location);//There are 5 monkeys in the tree
    

    更多模板格式化符号详见官方文档。

  • quotemeta — 转义元字符集

    返回 在下面这些特殊字符前加 反斜线() 转义后的字符串。这些特殊字符包含:

    . \ + * ? [ ^ ] ( $ )

  • setlocale — 设置地区信息

  • sha1 — 计算字符串的 sha1 散列值

    由于此函数依赖的算法已不足够复杂,不推荐使用此函数对明文密码加密。

  • sha1_file — 计算文件的 sha1 散列值 与md5_file相似,但算法不一样。该散列值是一个 40 字符长度的十六进制数字。 md5_file返回32字符长度的16进制数字。

  • similar_text — 计算两个字符串的相似度

    两个字符串的相似程度计算依据 Programming Classics: Implementing the World’s Best Algorithms by Oliver (ISBN 0-131-00413-1) 的描述进行。注意该实现没有使用 Oliver 虚拟码中的堆栈,但是却进行了递归调用,这个做法可能会导致整个过程变慢或变快。也请注意,该算法的复杂度是 O(N**3),N 是最长字符串的长度。

    similar_text( string $first, string $second[, float &$percent] ) : int
    

    通过引用方式传递第三个参数,similar_text() 将计算相似程度百分数。

    注意:返回值是两个字符串中匹配字符的数目。而我们通常要的是相似度百分数,也就是第三个参数percent。

  • soundex — Calculate the soundex key of a string

    Soundex键具有发音相似的单词会产生相同的Soundex键的属性,因此可以用来简化在你知道发音但不知道拼写的数据库中的搜索。这个soundex函数返回一个以字母开头的4个字符的字符串。

  • sscanf — 根据指定格式解析输入的字符

  • str_getcsv — 解析 CSV 字符串为一个数组

    以 CSV 字段格式解析字符串输入,并返回包含读取字段的数组。

  • str_replace — 子字符串替换

    str_replace( mixed $search, mixed $replace, mixed $subject[, int &$count] ) : mixed
    

    如果 search 和 replace 为数组,那么 str_replace() 将对 subject 做二者的映射替换。如果 replace 的值的个数少于 search 的个数,多余的替换将使用空字符串来进行。如果 search 是一个数组而 replace 是一个字符串,那么 search 中每个元素的替换将始终使用这个字符串。该转换不会改变大小写。

    如果 search 和 replace 都是数组,它们的值将会被依次处理。

    $phrase  = "You should eat fruits, vegetables, and fiber every day.";
    $healthy = ["fruits", "vegetables", "fiber"];
    $yummy   = ["pizza", "beer", "ice cream"];
    
    $newphrase = str_replace($healthy, $yummy, $phrase);
    print_r($newphrase);//You should eat pizza, beer, and ice cream every day
    

    如果search和replace参数都是数组的时候,需要注意一个先后查找替换问题,一个特殊的范例:

    $letters = array('a', 'p');
    $fruit   = array('apple', 'pear');
    $text    = 'a p';
    $output  = str_replace($letters, $fruit, $text);
    echo $output;
    // 由于先查找了字符a,替换成apple,之后再查找字符p,再将替换后的apple的两个p字符又替换成pear
    // 输出: apearpearle pear
    
  • str_ireplace — str_replace 的忽略大小写版本

  • str_pad — 使用另一个字符串填充字符串为指定长度

    str_pad( string $input, int $pad_length[, string $pad_string = " "[, int $pad_type = STR_PAD_RIGHT]] ) : string
    

    支持左右填充指定字符,并指定长度,默认STR_PAD_RIGHT向右填充。

    注意:如果填充字符的长度不能被 pad_string 整除,那么 pad_string 可能会被缩短。

    官方范例:

    $input = "Alien";
    echo str_pad($input, 10);                      // 输出 "Alien     "
    echo str_pad($input, 10, "-=", STR_PAD_LEFT);  // 输出 "-=-=-Alien"
    echo str_pad($input, 10, "_", STR_PAD_BOTH);   // 输出 "__Alien___"
    echo str_pad($input,  6, "___");               // 输出 "Alien_"
    echo str_pad($input,  3, "*");                 // 输出 "Alien"
    
  • str_repeat — 重复一个字符串

    str_repeat( string $input, int $multiplier) : string
    

    返回 字符串input 重复 multiplier 次后的结果字符串。

    echo str_repeat("-=", 5);
    //-=-=-=-=-=
    
  • str_rot13 — 对字符串执行 ROT13 转换

    在比较旧的php代码中我们也会看一些借鉴str_rot13的加密算法,可以用来混淆。可能混淆算法不一定采用之后的第13个字符替换法。

    ROT13 编码简单地使用字母表中后面第 13 个字母替换当前字母,同时忽略非字母表中的字符。编码和解码都使用相同的函数,传递一个编码过的字符串作为参数,将得到原始字符串。

    echo str_rot13("Tsing1");//Gfvat1
      
    echo str_rot13("Gfvat1");//Tsing1
    
    
  • str_shuffle — 随机打乱一个字符串

    每次返回都是随机的,不一样的字符串

  • str_split — 将字符串转换为数组

    将一个字符串转换为数组,如果第二个参数默认是1时,返回的就是字符数组,字符串的每个字符就是数组中的一个元素。

    第二参数是将返回的数组的每个元素的长度,比如设置为3,则返回的数组中的每个元素都是长度为3的字符串。

    $str = "Hello Friend";
    
    $arr1 = str_split($str);
    $arr2 = str_split($str, 3);
    
    //print_r($arr1);
    print_r($arr2);
    

    输出:

    Array
    (
        [0] => Hel
        [1] => lo
        [2] => Fri
        [3] => end
    )
    
  • str_word_count — 返回字符串中单词的使用情况

  • strcmp — 二进制安全字符串比较

    如果 str1 小于 str2 返回 < 0;如果 str1 大于 str2 返回 > 0;如果两者相等,返回 0。

    注意:该函数不是人习惯的自然排序算法,可以考虑使用strnatcmp的字符串比较函数。

  • strcasecmp — 二进制安全比较字符串(不区分大小写)

  • strncmp — 二进制安全比较字符串开头的若干个字符

  • strncasecmp — 二进制安全比较字符串开头的若干个字符(不区分大小写)

  • strip_tags — 从字符串中去除 HTML 和 PHP 标记

    该函数尝试返回给定的字符串 str 去除空字符、HTML 和 PHP 标记后的结果。

    注意:由于 strip_tags() 无法实际验证 HTML,不完整或者破损标签将导致更多的数据被删除。

  • stripslashes — 反转义一个使用类似使用addslashes 转义的字符串

  • strpos — 查找字符串首次出现的位置

    strpos( string $haystack, mixed $needle[, int $offset = 0] ) : int
    

    在字符串$haystack中查找字符$needle,返回needle在haystack中首次出现的数字位置。

    needle:建议一定要是字符串。

    offset:如果提供了此参数,搜索会从字符串该字符数的起始位置开始统计。如果是负数,搜索会从字符串结尾指定字符数开始。

    返回 needle 存在于 haystack 字符串起始的位置(独立于 offset)。同时注意字符串位置是从0开始,而不是从1开始的。如果没找到 needle,将返回 FALSE。

    注意:strpos的参数顺序,和explode等其他字符串函数不大一样,strpos第一个参数是完整字符串,第二个参数needle是用于查找的子串或字符。

  • stripos — 查找字符串首次出现的位置(不区分大小写)

  • strrpos — 计算指定字符串在目标字符串中最后一次出现的位置

    注意:区别于strpos指定字符在目标字符串最后一次出现的位置。

  • strripos — 计算指定字符串在目标字符串中最后一次出现的位置(不区分大小写)

  • strstr — 查找字符串的首次出现,并返回第一次出现的位置开始到结尾的字符串

    strstr( string $haystack, mixed $needle[, bool $before_needle = FALSE] ) : string
    

    返回 haystack 字符串从 needle 第一次出现的位置开始到 haystack 结尾的字符串。

    注意:strchr函数是strstr的别名函数

    $url  = 'http://www.9ong.com';
    $domain = strstr($url, '//');
    echo $domain; // 输出://www.9ong.com
    
  • stristr — strstr 函数的忽略大小写版本

  • strrchr — 查找指定字符在字符串中的最后一次出现

    该函数返回 haystack 字符串中的一部分,这部分以 needle 的最后出现位置开始,直到 haystack 末尾。

    注意:该函数对应正向函数是strchr也就是strstr,如果strrchr函数的needle参数包含不止一个字符,仅使用第一个字符。该参数行为不同于strstr函数。

    注意:如果 needle 不是一个字符串,那么将被转化为整型并被视为字符顺序值。

    $nl = chr(10);//\n ASCII
    echo nl2br($nl);
    $text = "Line 1\nLine 2\nLine 3";
    $last = substr(strrchr($text, 10), 1 );
    echo $last;
    //输出:
    //<br />
    //Line 3
    
  • strlen — 获取字符串长度

  • strnatcmp — 使用自然排序算法比较字符串

    该函数实现了以人类习惯对数字型字符串进行排序的比较算法,这就是"自然顺序”。

    返回值:与其他字符串比较函数类似,如果 str1 小于 str2 返回 < 0;如果 str1 大于 str2 返回 > 0;如果两者相等,返回 0。

  • strnatcasecmp — 使用“自然顺序”算法比较字符串(不区分大小写)

  • strpbrk — 在字符串中查找一组字符的任何一个字符

    返回一个以找到的字符开始的子字符串。如果没有找到,则返回 FALSE。

  • strrev — 反转字符串

    hello反转后就是:olleh

  • strtok — 标记分割字符串

    返回值类似于一个迭代器。如果不熟悉使用方式,分割字符串建议使用explode、preg_split。注意:split已经不再建议使用,而str_split不支持指定分隔字符(串),是将字符串按单个字符分隔转换成字符数组。

    $string = "This is\tan example\nstring";
    /* 使用制表符和换行符作为分界符 */
    $tok = strtok($string, " \n\t");
    while ($tok !== false) {
        echo "Word=$tok\n";
        $tok = strtok(" \n\t");
    }
    

    输出:

    Word=This
    Word=is
    Word=an
    Word=example
    Word=string
    
  • strtolower — 将字符串转化为小写

  • strtoupper — 将字符串转化为大写

  • strtr — 转换指定字符,可用于实现字符串替换,类似于str_replace,但又更简洁实用

    函数支持两种方式:

    strtr( string $str, string $from, string $to) : string
    
    strtr( string $str, array $replace_pairs) : string
    

    该函数返回 str 的一个副本,并将在 from 中指定的字符转换为 to 中相应的字符。比如, $from[$n]中每次的出现都会被替换为 $to[$n],其中 $n 是两个参数都有效的字符串位移(offset),通俗点说就是字符串数组的下标。

    如果 from 与 to 长度不相等,那么多余的字符部分将被忽略。 str 的长度将会和返回的值一样。

    如果给出两个参数,第二个参数应该是array形式的数组(‘from’ => ‘to’,…)。返回值是一个字符串,其中所有出现的数组键都被相应的值所替换。最长的键将首先尝试。一旦子字符串被替换,它的新值将不再被搜索,这个是有区别于str_replace前两个参数都是数组的形式,str_replace会有先后替换顺序。

    echo strtr("baab", "ab", "01"),"\n";
    
    $trans = array("ab" => "01");
    echo strtr("baab", $trans),"\n";
    
    $trans = array("a" => "apple","p"=>"pear");
    echo strtr("a p", $trans),"\n";
    
    echo str_replace(["a","p"], ["apple",'pear'], 'a p'),"\n";
    

    输出:

    1001
    ba01
    apple pear
    apearpearle pear
    
  • substr — 返回字符串的子串

    substr( string $string, int $start[, int $length] ) : string
    
    • start

      如果 start 是非负数,返回的字符串将从 string 的 start 位置开始,从 0 开始计算。例如,在字符串 “abcdef” 中,在位置 0 的字符是 “a”,位置 2 的字符串是 “c” 等等。

      如果 start 是负数,返回的字符串将从 string 结尾处向前数第 start 个字符开始。

      如果 string 的长度小于 start,将返回 FALSE。

    • length

      如果没有提供 length,默认返回的子字符串将从 start 位置开始直到字符串结尾。

      如果提供了正数的 length,返回的字符串将从 start 处开始最多包括 length 个字符(取决于 string 的长度)。

      如果提供了负数的 length,那么 string 末尾处的 length 个字符将会被省略。

      如果提供了值为 0,FALSE 或 NULL 的 length,那么将返回一个空字符串。

    echo substr("abcdef", -2),"\n";    // 返回 "ef"
    echo substr("abcdef", -3, 1),"\n"; // 返回 "d"
    echo substr("abcdef", 0, -1),"\n";  // 返回 "abcde" 忽略末尾1个字符f
    echo substr("abcdef", 2, -1),"\n";  // 返回 "cde" 忽略末尾1个字符f
    echo substr("abcdef", 2, -4),"\n";  // 返回 ""
    echo substr("abcdef", -3, -2),"\n"; // 返回 "d" 忽略末尾2个字符ef
    
  • substr_count — 计算子串出现的次数

    substr_count( string $haystack, string $needle[, int $offset = 0[, int $length]] ) : int
    

    注意:该函数不会计算重叠字符串;函数还支持offset,即从哪里开始查找计算;函数支持length,即查找到哪里;

    $text = 'This is a test';
    echo substr_count($text, 'is'),"\n"; // 2
    
    $test = "xxxxx";
    echo substr_count($test, "xx"),"\n";//2
    
  • substr_replace — 替换字符串的子串

    substr_replace( mixed $string, mixed $replacement, mixed $start[, mixed $length] ) : mixed
    

    通俗上说,先通过start与length截取字符串中的子串,然后再将子串替换成replacement。相当于substr+replace的功能。start与length参考substr函数。

    $var = "-tsingchan-";
    //将9ong插入到 $var 的开头处
    echo substr_replace($var, '9ong', 0, 0) . "\n";//9ong-tsingchan-
    
    //下面两个例子使用9ong替换 $var 中的 chan
    echo substr_replace($var, '9ong', 6, -1) . "\n";//-tsing9ong-
    echo substr_replace($var, '9ong', -5, -1) . "\n";//-tsing9ong-
    
    //从 $var 中删除chan
    echo substr_replace($var, '', 6, -1) . "\n";//-tsing-
    
  • substr_compare — 二进制安全比较字符串(从偏移位置比较指定长度)

    截取子串后,再进行比较字符串,但不是自然排序的比较。

  • trim — 去除字符串首尾处的空白字符(或者其他字符)

    trim( string $str[, string $character_mask = " \t\n\r\0\x0B"] ) : string
    

    trim很简单,但又不是那么简单,主要看第二个参数character_mask:

    character_mask是可选参数,过滤字符也可由 character_mask 参数指定。一般要列出所有希望过滤的字符,也可以使用 “..” 列出一个字符范围。

    首先,character_mask默认过滤空白符,包含空格、制表符、换行符、回车符等空白符;

    其次,可以自定义character_mask字符,注意如果设置的是一个字符串(多字符),那么每个字符都会按trim的规则首尾检查并对应过滤,而不是过滤一个字符串;

    最后,character_mask参数支持..来包含一个字符范围,比如我们常用的ASCII控制符范围。

    官方文档例子:

    $text   = "\t\tThese are a few words :) ...  ";
    $binary = "\x09Example string\x0A";
    $hello  = "Hello World";
    //var_dump($text, $binary, $hello);
    
    $trimmed = trim($text);
    echo $trimmed,"\n";//These are a few words :) ...
    
    $trimmed = trim($text, " \t.");//注意:尾巴的三个.字符都被过滤
    echo $trimmed,"\n";//These are a few words :)
    
    $trimmed = trim($hello, "Hdle");//注意:不是简单的过滤Hdle字符串,而4个字符H d l e一一在首尾检查并过滤
    echo ($trimmed),"\n";//o Wor
    
    // 清除 $binary 首位的 ASCII 控制字符
    // (包括 0-31)
    $clean = trim($binary, "\x00..\x1F");//支持..范围检查过滤
    echo $clean,"\n";//Example string
    
  • ltrim — 删除字符串开头的空白字符(或其他字符)

    同trim,只是去除字符串左侧(首部)的指定字符。

  • rtrim — 删除字符串末端的空白字符(或者其他字符)

    同trim,只是去除字符串右侧(尾部)的指定字符。

  • vprintf — 输出格式化字符串

    vprintf( string $format, array $args) : int
    

    根据 format (sprintf() 函数文档中有相关描述)参数指定的格式,在一个格式化字符串中显示多个值。

    作用与 printf() 函数类似,但是接收一个数组参数,而不是一系列可变数量的参数。

    vprintf("%04d-%02d-%02d", explode('-', '2020-1-1')); // 2020-01-01
    
  • vsprintf — 返回格式化字符串

    vsprintf( string $format, array $args) : string
      
    

    注意是返回,而不是直接输出。

    作用与 sprintf() 函数类似,但是接收一个数组参数,而不是一系列可变数量的参数。

    作用于vprintf一样,但不直接输出而是返回字符串。

    echo vsprintf("%04d-%02d-%02d", explode('-', '2020-1-1')); // 2020-01-01
    
  • vfprintf — 将格式化字符串写入流

    向由 handle 指定的流资源句柄中写入根据 format 格式化后的字符串。 同vprintf,但多了个参数handle,是输出写入流。

    vfprintf( resource $handle, string $format, array $args) : int
    
  • 关于格式化字符串说明符

    %	文字百分比字符。不需要任何参数。
    b	该参数被视为整数,并以二进制数表示。
    c	该参数被视为整数,并以该ASCII形式显示为字符。
    d	该参数被视为整数,并以(有符号的)十进制数表示。
    e	该论点被视为科学记数法(例如1.2e + 2)。精度说明符表示自PHP 5.2.1起小数点后的位数。在早期版本中,它被视为有效数字(少一位)。
    E	类似于说明e符,但使用大写字母(例如1.2E + 2)。
    f	该参数被视为浮点数,并显示为浮点数(可识别语言环境)。
    F	该参数被视为浮点数,并被表示为浮点数(不支持区域设置)。自PHP 5.0.3起可用。    
    o	该参数被视为整数,并以八进制数表示。
    s	该参数被视为字符串显示。
    u	该参数被视为整数,并以无符号十进制数形式出现。
    x	该参数被视为整数,并以十六进制数字(带有小写字母)的形式呈现。
    X	该参数被视为整数,并以十六进制数字(带有大写字母)的形式呈现。
    

    参考:PHP: vsprintf - Manual

  • wordwrap — 打断字符串为指定数量的字串

    wordwrap( string $str[, int $width = 75[, string $break = "\n"[, bool $cut = FALSE]]] ) : string
    

    通过指定width宽度智能打断字符串,插入break符号,比如换行符。看函数名wordwrap,有接触过css就大概知道函数的功能了,css的word-wrap属性:允许长单词换行到下一行,达到自动换行的效果。

    如果 参数cut 设置为 TRUE,字符串总是在指定的 width 或者之前位置被打断。因此,如果有的单词宽度超过了给定的宽度,它将被分隔开来。(参见第二个范例)。当它是 FALSE ,函数不会分割单词,哪怕 width 小于单词宽度。

    $text = "A very long woooooooooooooooooord. and something";
    $cut = false;
    $newtext = wordwrap($text, 9, "\n", $cut);
    
    echo "$newtext\n";
    

    输出:

    //如果cut为 false 则:
    A very
    long
    woooooooooooooooooord.
    and
    something
    
    
    //如果cut为 true 则:    
    A very
    long
    woooooooo
    ooooooooo
    ord. and
    something
    
    

数组相关函数

  • array_change_key_case — 将数组中的所有键名修改为全大写或小写

    将 array 数组中的所有键名改为全小写或大写。本函数不改变数字索引。

  • array_chunk — 将一个数组分割成多个

    将一个数组分割成多个数组,其中每个数组的元素数目由 size 决定。最后一个数组的元素数目可能会少于 size 个。

    得到的数组是一个多维数组中的元素,其索引从零开始,每一维包含了 size 个元素。

  • array_column — 返回数组中指定的一列

    array_column( array $input, mixed $column_key[, mixed $index_key = null] ) : array
    

    array_column() 返回input数组中键值为column_key的列,如果指定了可选参数index_key,那么input数组中的这一列的值将作为返回数组中对应值的键。

    抽取数组中的一列组成一个新的数组,新数组的索引可以通过第三个参数index_key来指定(从原input二维数组指定各个子数组中的索引key)

    $records = array(
        array(
            'id' => 2135,
            'first_name' => 'John',
            'last_name' => 'Doe',
        ),
        array(
            'id' => 3245,
            'first_name' => 'Sally',
            'last_name' => 'Smith',
        ),
        array(
            'id' => 5342,
            'first_name' => 'Jane',
            'last_name' => 'Jones',
        ),
        array(
            'id' => 5623,
            'first_name' => 'Peter',
            'last_name' => 'Doe',
        )
    );    
    $last_names = array_column($records, 'last_name', 'id');
    print_r($last_names);
    
    

    从数组records中抽取各个子数组中的列last_name的值,并使用子数组中的索引id作为新索引。

    Array
    (
        [2135] => Doe
        [3245] => Smith
        [5342] => Jones
        [5623] => Doe
    )
    
  • array_combine — 创建一个数组,用一个数组的值作为新数组的键名,另一个数组的值作为新数组的值

    注意:返回一个数组,要求两个数组的值个数要一样,否则会抛出错误。

  • array_count_values — 统计数组中所有的值

    统计数组中值出现的次数。

    返回一个数组:数组的键是 array 里元素值;数组的值是 array 元素值出现的次数。

  • array_diff — 计算数组的差集

    返回在source数组而不在其他数组中的元素值,注意元素比较是先转换成字符(string)再进行全等===比较,所以该函数支持一维数组:

    $source = [1, 2, 3, 4,5,6];
    $filter1 = [3, 4,];
    $filter2 = [5, "6"];
    $result = array_diff($source, $filter1,$filter2);
    print_r($result);
    
    
      
    Array
    (
        [0] => 1
        [1] => 2
    )
    
    

    注意:支持多个数组计算差集。值检查数据值。

  • array_diff_key — 使用键名比较计算数组的差集

    根据 array1 中的键名和 array2 进行比较,返回不同键名的项。本函数和 array_diff() 相同只除了比较是根据键名而不是值来进行的。

    注意:同样是先转换成string后再全等比较key名,而且只支持一维数组。支持多个数组计算差集。

  • array_diff_ukey — 用回调函数对键名比较计算数组的差集

    array_diff_ukey( array $array1, array $array2[, array $...], callable $key_compare_func) : array
    

    array_diff_ukey() 返回一个数组,该数组包括了所有出现在 array1 中但是未出现在任何其它参数数组中的键名的值。注意关联关系保留不变。本函数和 array_diff_key() 相同,除了key比较规则由第三方函数来处理。

    该函数满足用户自定义对两个数组的key比较规则,比如有特殊情况处理,某个相同的key被要求保留在差集中。

    function key_compare_func($key1, $key2)
    {
        if ($key1 == $key2)
            return 0;
        else if ($key1 > $key2)
            return 1;
        else
            return -1;
    }
    
    $array1 = ['blue'  => 1, 'red'  => 2, 'green'  => 3, 'purple' => 4];
    $array2 = ['green' => 5];
    $array3 = ['yellow' => 7, 'cyan'   => 8, 'blue' => 6];
    
    var_dump(array_diff_ukey($array1, $array2,$array3, 'key_compare_func'));
    

    注意:key_compare_func函数要求比较两个key值后,返回小于、等于、大于0的整数,分别对应第一个数组的key小于、等于、大于第二个数组的key。

  • array_diff_assoc — 带索引检查计算数组的差集

    如果元组的key和value有一个不一样就会返回到差集中。不再仅仅是比较key或是value。

  • array_diff_uassoc — 用用户提供的回调函数做索引检查来计算数组的差集

    注意:回调函数只检查索引值

  • array_udiff — 用回调函数比较数据来计算数组的差集

    注意:回调函数只检查数据值

  • array_udiff_assoc — 带索引检查计算数组的差集,用回调函数比较数据

  • array_udiff_uassoc — 带索引检查计算数组的差集,用回调函数比较数据和索引

  • array_fill — 用给定的值填充数组

    用给定的值填充并创建数组。

    array_fill( int $start_index, int $num, mixed $value) : array
    

    array_fill() 用 value 参数的值将一个数组填充 num 个元素,键名由 start_index 参数指定的开始,一般是大于等于0的整数值。

  • array_fill_keys — 使用指定的键和值填充数组

    使用 参数value 作为值,使用 keys 数组的值作为键来填充一个数组。

    $keys = array('foo', 5, 10, 'bar');
    $a = array_fill_keys($keys, 'banana');
    print_r($a);
    
    
    Array
    (
        [foo] => banana
        [5] => banana
        [10] => banana
        [bar] => banana
    )
    
  • array_filter — 用回调函数过滤数组中的元素

    array_filter( array $array[, callable $callback[, int $flag = 0]] ) : array
    

    依次将 array 数组中的每个值传递到 callback 函数。如果 callback 函数返回 true,则 array 数组的当前值会被包含在返回的结果数组中。数组的键名保留不变。

    注意:如果没有提供 callback 函数,将删除 array 中所有等值为 FALSE 的条目,即空字符串、null、0、false等false值都会被删除。

    $entry = array(
             0 => 'foo',
             1 => false,
             2 => -1,
             3 => null,
            4 => ''
        );
    
    print_r(array_filter($entry));
    
    Array
    (
        [0] => foo
        [2] => -1
    )
    

    注意:第三个参数flag默认是标记传递给callback是元素值value,也可以指定ARRAY_FILTER_USE_KEY或ARRAY_FILTER_USE_BOTH来传递key或同时传递key与value。

  • array_flip — 交换数组中的键和值

    array_flip() 返回一个反转后的 array,例如 array 中的键名变成了值,而 array 中的值成了键名。

    注意 array 中的值需要能够作为合法的键名(例如需要是 int 或者 string)。如果类型不对,将出现一个警告,并且有问题的键/值对将不会出现在结果里。

    如果同一个值出现多次,则最后一个键名将作为它的值,其它键会被丢弃。

  • array_intersect — 计算数组的交集

    array_intersect() 返回一个数组,该数组包含了所有在 array1 中也同时出现在所有其它参数数组中的值。注意键名保留不变。

    与array_diff原理相似。

  • array_intersect_key — 使用键名比较计算数组的交集

  • array_intersect_ukey — 用回调函数比较键名来计算数组的交集

  • array_intersect_assoc — 带索引检查计算数组的交集

    比较准确的检查key和value,并得到交集

  • array_intersect_uassoc — 带索引检查计算数组的交集,用回调函数比较索引

  • array_uintersect — 计算数组的交集,用回调函数比较数据

  • array_uintersect_assoc — 带索引检查计算数组的交集,用回调函数比较数据

  • array_uintersect_uassoc — 带索引检查计算数组的交集,用单独的回调函数比较数据和索引

  • array_key_exists — 检查数组里是否有指定的键名或索引

    注意:array_key_exists() 仅仅搜索第一维的键。多维数组里嵌套的键不会被搜索到。

  • array_key_first — 获取指定数组的第一个键值

    获取数组中的第一个元素的key。

    注意:php7.3开始支持

  • array_key_last — 获取一个数组的最后一个键值

    获取数组中的最后一个元素的key。

    注意:php7.3开始支持

  • array_keys — 返回数组中部分的或所有的键名

    array_keys( array $array[, mixed $search_value = null[, bool $strict = false]] ) : array
    

    array_keys() 返回 input 数组中的数字或者字符串的键名。 在7.3之前获取第一个或最后一个元素的key时,通常我们使用array_keys后再进行获取。

    注意:如果指定了可选参数 search_value,则只返回该值的键名。否则 input 数组中的所有键名都会被返回。 这个功能通常被我们忘记,这就是我们一直想要的通过value查找key的功能。

  • array_map — 为数组的每个元素应用回调函数

    array_map( callable $callback, array $array, array ...$arrays) : array
    

    这是一个万能数组函数。返回数组,是为 array 每个元素应用 callback函数之后的数组。

    array_map() 返回一个 array,数组内容为 array1 的元素按索引顺序为参数调用 callback 后的结果(有更多数组时,还会传入 arrays 的元素)。 callback 函数形参的数量必须匹配 array_map() 实参中数组的数量。 也就是说array_map中传入n个数组,则在callback中就会有n个参数,分别对应n个数组中每个数组的元素值,不考虑key。

    callback返回的值将作为新数组的元素值,新数组的key根据传入数组的数量不同而不同,如果只有输入一个数组则保留原有key,如果多个数组时,则采用新的整数key值。

  • array_merge — 合并一个或多个数组

    array_merge([ array $...] ) : array
    

    将一个或多个数组的元素合并起来,一个数组中的值附加在前一个数组的后面。返回作为结果的数组。

    如果输入的数组中有相同的字符串键名,则该键名后面的值将覆盖前一个值。然而,如果数组包含数字键名,后面的值将 不会 覆盖原来的值,而是附加到后面。

    如果输入的数组存在以数字作为索引的内容,则这项内容的键名会以连续方式重新索引。如果像覆盖后面相同数字索引的内容,可以使用 + 号,array1 + array2来实现两个数组的合并,但同时覆盖相同的数字索引元素。

    也就是说 + 号比起array_merrge的合并更为严格。

    $array1 = array(0 => 'zero_a', 2 => 'two_a', 3 => 'three_a',"a"=>"apple");
    $array2 = array(1 => 'one_b', 3 => 'three_b', 4 => 'four_b',"a"=>"app");
    $result = $array1 + $array2;
    //$result = array_merge($array1,$array2);
    var_dump($result);
    
    array(6) {
        [0]=>
        string(6) "zero_a"
        [2]=>
        string(5) "two_a"
        [3]=>
        string(7) "three_a"
        ["a"]=>
        string(5) "apple"
        [1]=>
        string(5) "one_b"
        [4]=>
        string(6) "four_b"
    }
    
  • array_merge_recursive — 递归地合并一个或多个数组

    array_merge_recursive() 将一个或多个数组的元素合并起来,一个数组中的值附加在前一个数组的后面。返回作为结果的数组。

    如果输入的数组中有相同的字符串键名则这些值会被合并到一个数组中去,这将递归下去,因此如果一个值本身是一个数组,本函数将按照相应的条目把它合并为另一个数组。注意这里,不是覆盖,而是合并到一个数组中去,但和array_merge的理解不大一样。

    注意:如果你想使用这个函数,建议不要从array_merge_recursice字面上来理解,一定要去看下官方文档的例子,理解之后才去应用到自己的业务逻辑中。

    同时注意的是:如果数组具有相同的数值键名,后一个值将不会覆盖原来的值,而是附加到后面。

    $ar1 = array("color" => array("favorite" => "red"), 5);
    $ar2 = array(10, "color" => array("favorite" => "green", "blue"));
    $result = array_merge_recursive($ar1, $ar2);
    print_r($result);
    
    Array
    (
        [color] => Array
            (
                [favorite] => Array
                    (
                        [0] => red
                        [1] => green
                    )
    
                [0] => blue
            )
    
        [0] => 5
        [1] => 10
    )
    
  • array_multisort — 对多个数组或多维数组进行排序

    这个函数一开始是很不好理解的。特别是他的参数很灵活多变,可有可无。排序是按字典顺序排列的,官方这句话很不好理解,需要借助例子。

    array_multisort( array &$array1[, mixed $array1_sort_order = SORT_ASC[, mixed $array1_sort_flags = SORT_REGULAR[, mixed $...]]] ) : bool
    

    先看个例子:

    $arr = [
        ["10", 11, 100, 100, "a"],
        [4,5,2,3,1]
    ];
    array_multisort($arr[0], SORT_ASC, SORT_NUMERIC,
                    $arr[1], SORT_NUMERIC, SORT_DESC);
    print_r($arr);
    
    Array
    (
        [0] => Array
            (
                [0] => a
                [1] => 10
                [2] => 11
                [3] => 100
                [4] => 100
            )
    
        [1] => Array
            (
                [0] => 1
                [1] => 4
                [2] => 5
                [3] => 3
                [4] => 2
            )
    
    )
    
    

    array_multi_sort类似于sql语句的order by排序,一列值就是一个一维数组,上例中,$arr[0]先按数字升序排序,$arr[1]在$arr[0]的排序基础上,根据$arr[0]中值相同所在的字典key位置,对应$arr[1]所在字典key位置的值进行数字降序排序。

    比如上例,由于有两个100,key分别是2和3,对应$arr[1]中key为2和3值为2和3,进行数字降序后就是我们最终看到的输出结果。

    注意:多个数组排序,要保证多个数组的元素个数是一致的。一般多个数组来源于一个多维数组的不同key下的值(数组)。

    关于该函数的更多参数解释,详细看官方文档:PHP: array_multisort - Manual

  • array_pad — 以指定长度将一个值填充进数组

    array_pad() 返回 array 的一个拷贝,并用 value 将其填补到 size 指定的长度。如果 size 为正,则填补到数组的右侧,如果为负则从左侧开始填补。如果 size 的绝对值小于或等于 array 数组的长度则没有任何填补。

    注意:返回的是一个拷贝,而不是数组本身也不是引用,也就是说是返回的数组不影响原数组。

    注意:size就是新数组的长度。

  • array_pop — 弹出数组最后一个元素(出栈)

    array_pop() 弹出并返回 array 数组的最后一个元素,并将数组 array 的长度减一。

  • array_product — 计算数组中所有值的乘积

    array_product() 以整数或浮点数返回一个数组中所有值的乘积。

  • array_push — 将一个或多个元素压入数组的末尾(入栈)

    注意:array_push支持一次压入多个元素

    注意:如果用 array_push() 来给数组增加一个元素,还不如用 $array[] = $value,因为这样没有调用函数的额外负担。

  • array_rand — 从数组中随机取出一个或多个元素

    array_rand( array $array[, int $num = 1] ) : mixed
    

    如果只取出一个,array_rand() 返回随机元素的键名。否则就返回包含随机键名的数组。

  • array_reduce — 用回调函数迭代地将数组简化为单一的值

    array_reduce( array $array, callable $callback[, mixed $initial = NULL] ) : mixed
    

    array_reduce() 将回调函数 callback 迭代地作用到 array 数组中的每一个元素中,从而将数组简化为单一的值。

    不同于array_map数组应用函数,array_reduce的callback允许携带上一次迭代的值进入下一次迭代,最终简化返回一个简单的类型值(非复合类型)

    • array

      输入的 array。

    • callback

      callback( mixed $carry, mixed $item) : mixed

      • carry

        携带上次迭代里的值;如果本次迭代是第一次,那么这个值是 initial。

      • item

        携带了本次迭代的值。

    • initial

      如果指定了可选参数 initial,该参数将在处理开始前使用,或者当处理结束,数组为空时的最后一个结果。

    function product($carry, $item)
    {
        $carry *= $item;
        return $carry;
    }
    
    $a = array(1, 2, 3, 4, 5);
    
    var_dump(array_reduce($a, "product", 10)); // int(1200), = 初始值10**1*2*3*4*5
      
    
  • array_replace — 使用传递的数组替换第一个数组的元素

    array_replace() 函数使用后面数组元素相同 key 的值替换 array 数组的值。

    • 如果一个键存在于第一个数组同时也存在于第二个数组,它的值将被第二个数组中的值替换。
    • 如果一个键存在于第二个数组,但是不存在于第一个数组,则会在第一个数组中创建这个元素。
    • 如果一个键仅存在于第一个数组,它将保持不变。
    • 如果传递了多个替换数组,它们将被按顺序依次处理,后面的数组将覆盖之前的值。
    • array_replace() 是非递归的:它将第一个数组的值进行替换而不管第二个数组中是什么类型。
    array_replace( array $array[, array $replacements] ) : array
    
  • array_replace_recursive — 使用传递的数组递归替换第一个数组的元素

    array_replace_recursive( array $array1[, array $...] ) : array
    

    array_replace_recursive() 使用后面数组元素的值替换数组 array1 的值。

    • 如果一个键存在于第一个数组同时也存在于第二个数组,它的值将被第二个数组中的值替换。

    • 如果一个键存在于第二个数组,但是不存在于第一个数组,则会在第一个数组中创建这个元素。

    • 如果一个键仅存在于第一个数组,它将保持不变。

    • 如果传递了多个替换数组,它们将被按顺序依次处理,后面的数组将覆盖之前的值。

    • 另外array_replace_recursive() 是递归的:它将遍历数组并将相同的处理应用到数组的内部值。

      如果第一个数组中的值是标量,它的值将被第二个数组中的值替换,它可能是一个标量或者数组。如果第一个数组和第二个数组中的值都是数组,array_replace_recursive() 函数将递归地替换它们各自的值。

    $base = array('citrus' => array( "orange") , 'berries' => array("blackberry", "raspberry"), );
    $replacements = array('citrus' => array('pineapple'), 'berries' => array('blueberry'));
    
    $basket = array_replace_recursive($base, $replacements);
    print_r($basket);
    
    $basket = array_replace($base, $replacements);
    print_r($basket);
    
    Array
    (
        [citrus] => Array
            (
                [0] => pineapple
            )
    
        [berries] => Array
            (
                [0] => blueberry
                [1] => raspberry
            )
    
    )
    Array
    (
        [citrus] => Array
            (
                [0] => pineapple
            )
    
        [berries] => Array
            (
                [0] => blueberry
            )
    
    )
    
    
  • array_reverse — 返回元素顺序相反的数组

    接受数组 array 作为输入并返回一个元素为相反顺序的新数组。

  • array_search — 在数组中搜索给定的值,如果成功则返回首个相应的键名

    array_search( mixed $needle, array $haystack[, bool $strict = false] ) : mixed
    

    官方的解释:大海捞针,在大海(haystack)中搜索针( needle 参数)。

    如果找到了 needle 则返回它的键,否则返回 FALSE。

    注意:如果 needle 在 haystack 中出现不止一次,则返回第一个匹配的键。要返回所有匹配值的键,应该用 array_keys() 加上可选参数 search_value 来代替。

    注意:此函数可能返回布尔值 FALSE,但也可能返回等同于 FALSE 的非布尔值

  • array_shift — 将数组开头的元素移出数组

    将 array 的第一个元素移出并作为结果返回,将 array 的长度减一并将所有其它元素向前移动一位。所有的数字键名将改为从零开始计数,文字键名将不变。

    注意:数字键名的reset。

  • array_slice — 从数组中取出一段

    array_slice( array $array, int $offset[, int $length = NULL[, bool $preserve_keys = FALSE]] ) : array
    

    array_slice() 返回根据 offset 和 length 参数所指定的 array 数组中的一段序列。

    如果 offset 为负,则序列将从 array 中距离末端这么远的地方开始。

    注意:array_slice() 默认会重新排序并重置数组的数字索引。你可以通过将 preserve_keys 设为 TRUE 来改变此行为。无论本参数如何设置,都会保留字符串的键。

  • array_splice — 去掉数组中的某一部分并用其它值取代

    把 input 数组中由 offset 和 length 指定的元素去掉,如果提供了 replacement 参数,则用其中的元素取代。

    array_splice( array &$input, int $offset[, int $length = count($input)[, mixed $replacement = array()]] ) : array
    

    虽然replacement是mixed,但建议确保一定是数组。避免带来不必要的麻烦。

    注意:&$input是个引用,这是php函数又一个让我们吐槽的地方,有些函数是输入数组不是引用,而是返回一个拷贝数组,而有些函数是引用输入数组,导致记忆混乱,必须要有php手册伴随身边,或者IDE有足够语法自动补充。

    $input = array("red", "green", "blue", "yellow");
    //array_splice($input, 2);
    array_splice($input, 2,count($input),['b','y']);
    var_dump($input);
    
    array(4) {
        [0]=>
        string(3) "red"
        [1]=>
        string(5) "green"
        [2]=>
        string(1) "b"
        [3]=>
        string(1) "y"
    }
    
    
  • array_sum — 对数组中所有值求和

    同array_product求数组乘积

  • array_unique — 移除数组中重复的值

    看名字我们就知道是去重,但需要注意的是:

    键名保留不变。而且array_unique() 会先将值作为字符串排序,然后对每个值只保留第一个遇到的键名,接着忽略所有后面的键名。所以未排序的数组中同一个值的第一个出现的键名不一定会被保留。

  • array_unshift — 在数组开头插入一个或多个元素

    还有更多相关函数:array_pop、array_push、array_shift

  • array_values — 返回数组中所有的值

    返回一个数组。

  • array_walk — 使用用户自定义函数对数组中的每个元素做回调处理

    类似于array_map,但array_map会返回形成新的数组,而array_walk当下就处理元素了,没有返回新的数组或数据。

    array_walk( array &$array, callable $callback[, mixed $userdata = NULL] ) : bool
    

    通常情况下 callback 接受两个参数。array 参数的值作为第一个,键名作为第二个。

    如果提供了可选参数 userdata,将被作为第三个参数传递给 callback 函数。

    $fruits = array("d" => "lemon", "a" => "orange", "b" => "banana", "c" => "apple");
    
    function test_print($item2, $key,$prefix='')
    {
        echo $prefix."_$key: $item2\n";
    }
    
    array_walk($fruits, 'test_print', 'fruit');
    echo "... and more.\n";
    
    fruit_d: lemon
    fruit_a: orange
    fruit_b: banana
    fruit_c: apple
    ... and more.
    
    
  • array_walk_recursive — 对数组中的每个成员递归地应用用户函数

    将用户自定义函数 callback 应用到 array 数组中的每个元素。本函数会递归到更深层的数组中去。

    递归到更深层:始终获得一个key和value传入回调函数中处理。不论元素在多维数组中的哪一维。

    注意:任何值为 array 的键都不会被传递到回调函数中去。 其他与array_walk函数一样。

  • array — 新建一个数组

  • sort — 对数组排序

    sort( array &$array[, int $sort_flags = SORT_REGULAR] ) : bool
    

    注意:排序比较的是值。

    注意:$array是引用,也就是直接修改了原数组。

    注意:如果两个成员值完全相同,那么它们在排序数组中的相对顺序是未定义的,也就是说没有对下相同的值再次进行排序,可能就是随机的。

    注意:此函数为 array 中的元素赋与新的数值键名。这将删除原有的键名,而不是仅仅将键名重新排序。

    可选的第二个参数 sort_flags 可以用以下值改变排序的行为:

    排序类型标记:

    • SORT_REGULAR - 正常比较元素详细描述参见 比较运算符 章节
    • SORT_NUMERIC - 元素被作为数字来比较
    • SORT_STRING - 元素被作为字符串来比较
    • SORT_LOCALE_STRING - 根据当前的区域(locale)设置来把元素当作字符串比较,可以用 setlocale() 来改变。
    • SORT_NATURAL - 和 natsort() 类似对每个元素以"自然的顺序"对字符串进行排序。
    • SORT_FLAG_CASE - 能够与 SORT_STRING 或 SORT_NATURAL 合并(OR 位运算),不区分大小写排序字符串。

    数组的相关排序函数中关于sort_flags都可以参考这些排序类型标记,包括array_mutilsort。

  • natsort — 用“自然排序”算法对数组排序

    本函数实现了一个和人们通常对字母数字字符串进行排序的方法一样的排序算法并保持原有键/值的关联,这被称为"自然排序”。

    sort()排序结果:
    Array
    (
        [3] => img1.png
        [1] => img10.png
        [0] => img12.png
        [2] => img2.png
    )
    natsort()排序结果:
    Array
    (
        [3] => img1.png
        [2] => img2.png
        [1] => img10.png
        [0] => img12.png
    )
    
  • natcasesort — 用“自然排序”算法对数组进行不区分大小写字母的排序

  • rsort — 对数组逆向排序

  • asort — 对数组进行排序并保持索引关系

  • arsort — 对数组进行逆向排序并保持索引关系

  • usort — 使用用户自定义的比较函数对数组中的值进行排序

    usort( array &$array, callable $value_compare_func) : bool
    

    本函数将用用户自定义的比较函数对一个数组中的值进行排序。如果要排序的数组需要用一种不寻常的标准进行排序,那么应该使用此函数。

    回调函数中在第一个参数小于,等于或大于第二个参数时,该比较函数必须相应地返回一个小于,等于或大于 0 的整数。

  • uasort — 使用用户自定义的比较函数对数组中的值进行排序并保持索引关联

  • uksort — 使用用户自定义的比较函数对数组中的键名进行排序

  • ksort — 对数组按照键名排序

  • krsort — 对数组按照键名逆向排序

  • compact — 建立一个数组,包括变量名和它们的值

  • count — 计算数组中的元素数目,或对象中的属性个数

    注意:除了可以统计数组外,还可以统计对象。

    count函数有第二个可选参数mode,如果 mode 参数设为 COUNT_RECURSIVE(或 1),count() 将递归地对数组计数。

  • current — 返回数组中的当前元素

    每个数组中都有一个内部的指针指向它"当前的"元素,初始指向插入到数组中的第一个元素。

    如果内部指针指向超出了元素列表的末端,current() 返回 FALSE。

    $transport = array('foot', 'bike', 'car', 'plane');
    echo current($transport),"\n"; // echo 'foot';
    echo next($transport),"\n";    // echo 'bike';
    echo current($transport),"\n"; // echo 'bike';
    echo prev($transport),"\n";    // echo 'foot';
    echo end($transport),"\n";     // echo 'plane';
    echo current($transport),"\n"; // echo 'plane';
    
    $arr = array();
    var_dump(current($arr)); // bool(false)
    
    $arr = array(array());
    var_dump(current($arr)); // array(0) { }
    
  • each — 返回数组中当前的键/值对并将数组指针向前移动一步

    注意:函数已自 PHP 7.2.0 起废弃。强烈建议不要使用本函数。

  • end — 将数组的内部指针指向最后一个元素

    end() 将 array 的内部指针移动到最后一个元素并返回其值。

  • extract — 从数组中将变量导入到当前的符号表

    我们不是很建议使用extract和compact函数。

  • in_array — 检查数组中是否存在某个值

    in_array( mixed $needle, array $haystack[, bool $strict = FALSE] ) : bool
    

    大海捞针,在大海(haystack)中搜索针( needle),如果没有设置 strict 则使用宽松的比较。 如果找到 needle 则返回 TRUE,否则返回 FALSE。

    array_search() - 在数组中通过搜索给定的值,如果成功则返回首个相应的键名

    array_key_exists() - 检查数组里是否有指定的键名或索引

  • key_exists — 别名 array_key_exists

  • key — 从关联数组中取得键名

    key() 返回数组中当前元素的键名。

    current() 返回数组中当前元素的值。

  • list — 把数组中的值赋给一组变量

    list( mixed $var[, mixed ...$vars] ) : array
    

    像 array() 一样,这不是真正的函数,而是语言结构。 list() 可以在单次操作内就为一组变量赋值。

    $info = array('coffee', 'brown', 'caffeine');
    
    // 列出所有变量
    list($drink, $color, $power) = $info;
    
    // 或者让我们跳到仅第三个
    list( , , $power) = $info;
    
    // list() 不能对字符串起作用
    list($bar) = "abcde";
    var_dump($bar); // NULL
    
  • next — 将数组中的内部指针向前移动一位

  • pos — current 的别名

  • prev — 将数组的内部指针倒回一位

  • range — 根据范围创建数组,包含指定的元素

    range( mixed $start, mixed $end[, int|float $step = 1] ) : array
    

    start和end支持单个字符和整数。

    print_r(range(11, 5));
    
    print_r(range("f","k"));
    
    
    Array
    (
        [0] => 11
        [1] => 10
        [2] => 9
        [3] => 8
        [4] => 7
        [5] => 6
        [6] => 5
    )
    Array
    (
        [0] => f
        [1] => g
        [2] => h
        [3] => i
        [4] => j
        [5] => k
    )
    
    
  • reset — 将数组的内部指针指向第一个元素

    reset() 将 array 的内部指针倒回到第一个元素并返回第一个数组元素的值。

  • shuffle — 打乱数组

    本函数打乱(随机排列元素的顺序)一个数组。

    shuffle( array &$array) : bool
    

    注意:返回true或false,传入array是数组引用。

  • sizeof — count 的别名

类与对象相关函数

  • __autoload — 尝试加载未定义的类

    本特性已自 PHP 7.2.0 起废弃。强烈建议不要使用本特性。

  • class_alias — 为一个类创建别名

    基于用户定义的类 original 创建别名 alias。这个别名类和原有的类完全相同。

    在有些特殊的场景,有必要为一个类创建别名,避免原类名不达意或者误用的情况,兼容类名识别。

  • class_exists — 检查类是否已定义

  • method_exists — 检查类的方法是否存在

  • interface_exists — 检查接口是否已被定义

  • property_exists — 检查对象或类是否具有该属性

  • trait_exists — 检查指定的 trait 是否存在

  • is_a — 如果对象属于该类或该类是此对象的父类则返回 TRUE

  • is_subclass_of — 如果此对象是该类的子类,则返回 TRUE

  • get_called_class — 后期静态绑定(“Late Static Binding”)类的名称

  • get_class_methods — 返回由类的方法名组成的数组

  • get_class_vars — 返回由类的默认属性组成的数组

  • get_class — 返回对象的类名

  • get_declared_classes — 返回由已定义类的名字所组成的数组

  • get_declared_interfaces — 返回一个数组包含所有已声明的接口

  • get_declared_traits — 返回所有已定义的 traits 的数组

  • get_object_vars — 返回由对象属性组成的关联数组

  • get_parent_class — 返回对象或类的父类名

变量处理

  • boolval — 获取变量的布尔值

    标量类型会被转化成布尔类型。一般是空、null、空数组、0、0.0等会返回false的布尔值。

  • debug_zval_dump — Dumps a string representation of an internal zend value to output

  • doubleval — floatval 的别名

  • empty — 检查一个变量是否为空

    判断一个变量是否被认为是空的。当一个变量并不存在,或者它的值等同于FALSE,那么它会被认为不存在。如果变量不存在的话,empty()并不会产生警告。

    当var存在,并且是一个非空非零的值时返回 FALSE 否则返回 TRUE.

    以下的东西被认为是空的:

    • "” (空字符串)
    • 0 (作为整数的0)
    • 0.0 (作为浮点数的0)
    • “0” (作为字符串的0)
    • NULL
    • FALSE
    • array() (一个空数组)
    • $var; (一个声明了,但是没有值的变量)

    所以: empty() 本质上与 !isset($var) || $var == false 等价。

  • floatval — 获取变量的浮点值

    var 可以是任何标量类型。你不能将 floatval() 用于数组或对象。

  • get_defined_vars — 返回由所有已定义变量所组成的数组

    此函数返回一个包含所有已定义变量列表的多维数组,这些变量包括环境变量、服务器变量和用户定义的变量。

    $b = array(1,1,2,3,5,8);
    
    $arr = get_defined_vars();
    
    // 打印 $b
    print_r($arr["b"]);
    
    // 打印 PHP 解释程序的路径(如果 PHP 作为 CGI 使用的话)
    // 例如:/usr/local/bin/php
    echo $arr["_"];
    
    // 打印命令行参数(如果有的话)
    print_r($arr["argv"]);
    
    // 打印所有服务器变量
    print_r($arr["_SERVER"]);
    
  • get_resource_type — 返回资源(resource)类型

    此函数返回一个字符串,用于表示传递给它的 resource 的类型。如果参数不是合法的 resource,将产生错误。

    $c = mysql_connect();
    echo get_resource_type($c)."\n";
    // 打印:mysql link
    
    $fp = fopen("foo","w");
    echo get_resource_type($fp)."\n";
    // 打印:file
    
  • gettype — 获取变量的类型

    不要使用 gettype() 来测试某种类型,因为其返回的字符串在未来的版本中可能需要改变。此外,由于包含了字符串的比较,它的运行也是较慢的。

    建议使用is_函数:is_array()、is_bool()、is_float()、is_integer()、is_null()、is_numeric()、is_object()、is_resource()、is_scalar() 和 is_string()。

  • intval — 获取变量的整数值

    intval( mixed $var[, int $base = 10] ) : int
    

    通过使用指定的进制 base 转换(默认是十进制),返回变量 var 的 integer 数值。 intval() 不能用于 object,否则会产生 E_NOTICE 错误并返回 1。

    注意:除非 var 是一个字符串,否则 base 不会起作用。

    echo intval(42, 8);                   // 42
    echo intval('42', 8);                 // 34
    
  • is_array — 检测变量是否是数组

  • is_bool — 检测变量是否是布尔型

  • is_callable — 检测参数是否为合法的可调用结构

  • is_countable — Verify that the contents of a variable is a countable value

  • is_double — is_float 的别名

  • is_float — 检测变量是否是浮点型

  • is_int — 检测变量是否是整数

    若想测试一个变量是否是数字或数字字符串(如表单输入,它们通常为字符串),必须使用 is_numeric()。

  • is_integer — is_int 的别名

  • is_iterable — Verify that the contents of a variable is an iterable value

  • is_long — is_int 的别名

  • is_null — 检测变量是否为 NULL

  • is_numeric — 检测变量是否为数字或数字字符串

  • is_object — 检测变量是否是一个对象

  • is_real — is_float 的别名

  • is_resource — 检测变量是否为资源类型

  • is_scalar — 检测变量是否是一个标量

    如果给出的变量参数 var 是一个标量,is_scalar() 返回 TRUE,否则返回 FALSE。

    标量变量是指那些包含了 integer、float、string 或 boolean的变量,而 array、object 和 resource 则不是标量。

  • is_string — 检测变量是否是字符串

  • isset — 检测变量是否已设置并且非 NULL

    isset说简单又不简单,很多注意细节:

    • 检测变量是否设置,并且不是 NULL
    • 如果已经使用 unset() 释放了一个变量之后,它将不再是 isset()。
    • 若使用 isset() 测试一个被设置成 NULL 的变量,将返回 FALSE。
    • 同时要注意的是 null 字符("\0”)并不等同于 PHP 的 NULL 常量。
    • 如果一次传入多个参数,那么 isset() 只有在全部参数都以被设置时返回 TRUE 计算过程从左至右,中途遇到没有设置的变量时就会立即停止。
  • print_r — 以易于理解的格式打印变量。

    print_r( mixed $expression[, bool $return = FALSE] ) : mixed
    

    很多phper并不知道print_r可以返回值,想要获取 print_r() 输出的内容,使用 return 参数。当此参数为 TRUE,print_r() 会直接返回信息,而不是输出。

  • serialize — 产生一个可存储的值的表示

    serialize() 返回字符串,此字符串包含了表示 value 的字节流,可以存储于任何地方。 这有利于存储或传递 PHP 的值,同时不丢失其类型和结构。

    但适合在php环境内传递序列串。

  • settype — 设置变量的类型

  • strval — 获取变量的字符串值

    var 可以是任何标量类型。不能将 strval() 用于数组或对象。

  • unserialize — 从已存储的表示中创建 PHP 的值

    如果传递的字符串不可解序列化,则返回 FALSE

  • unset — 释放给定的变量

    unset( mixed $var[, mixed $...] ) : void
    

    unset() 销毁指定的变量。

    unset() 在函数中的行为会依赖于想要销毁的变量的类型而有所不同。

    • 如果在函数中 unset() 一个全局变量,则只是局部变量被销毁,而在调用环境中的变量将保持调用 unset() 之前一样的值。

      function destroy_foo() {
          global $foo;
          unset($foo);
      }
      
      $foo = 'bar';
      destroy_foo();
      echo $foo;//bar
      
    • 如果您想在函数中 unset() 一个全局变量,可使用 $GLOBALS 数组来实现

      unset($GLOBALS['bar']);
      
    • 如果在函数中 unset() 一个通过引用传递的变量,则只是局部变量被销毁,而在调用环境中的变量将保持调用 unset() 之前一样的值。

      function foo(&$bar) {
          unset($bar);
          $bar = "blah";
      }
      
      $bar = 'something';
      echo "$bar\n";//something
      
      foo($bar);
      echo "$bar\n";//something
      
    • 如果在函数中 unset() 一个静态变量,那么在函数内部此静态变量将被销毁。但是,当再次调用此函数时,此静态变量将被复原为上次被销毁之前的值。

      function foo()
      {
          static $bar;
          $bar++;
          echo "Before unset: $bar, ";
          unset($bar);
          $bar = 23;
          echo "after unset: $bar\n";
      }
      
      foo();//Before unset: 1, after unset: 23
      foo();//Before unset: 2, after unset: 23
      foo();//Before unset: 3, after unset: 23
      

    所以对于在局部中想unset一个全局(global引入)或外部变量(引用传递),并不会影响全局变量或外部变量。

    // 销毁单个变量
    unset ($foo);
    
    // 销毁单个数组元素
    unset ($bar['quux']);
    
    // 销毁一个以上的变量
    unset($foo1, $foo2, $foo3);
    
  • var_dump — 打印变量的相关信息

    支持打印多个变量表达式。

  • var_export — 输出或返回一个变量的字符串表示

    var_export() 函数返回关于传递给该函数的变量的结构信息,它和 var_dump() 函数类似,不同的是其返回的表示是合法的 PHP 代码。

    常用于返回一个数组php代码,用于保存数组配置。

    注意:var_export与print_r一样都有第二个参数,设置为true时,将不直接输出,而是返回值。

函数处理

  • function_exists — 如果给定的函数已经被定义就返回 TRUE

    在已经定义的函数列表(包括系统自带的函数和用户自定义的函数)中查找 function_name。

  • func_get_args — 返回一个包含函数参数列表的数组

    获取函数参数列表的数组。

    该函数可以配合 func_get_arg() 和 func_num_args() 一起使用,从而使得用户自定义函数可以接受自定义个数的参数列表。

    我们不建议经常使用这个函数,因为不建议给已定义无参函数传递参数的行为。

    function foo()
    {
        $numargs = func_num_args();
        echo "Number of arguments: $numargs<br />\n";
        if ($numargs >= 2) {
            echo "Second argument is: " . func_get_arg(1) . "<br />\n";
        }
        $arg_list = func_get_args();
        for ($i = 0; $i < $numargs; $i++) {
            echo "Argument $i is: " . $arg_list[$i] . "<br />\n";
        }
    }
    
    foo(1, 2, 3);//虽然foo定义时是无参的,但这里还是不会报错的
    

    建议传递一个数组或对象,可以用于灵活扩展参数。

  • func_num_args — Returns the number of arguments passed to the function

  • func_get_arg — 返回参数列表的某一项

  • call_user_func — 把第一个参数作为回调函数调用

    call_user_func( callable $callback[, mixed $parameter[, mixed $...]] ) : mixed
    

    第一个参数 callback 是被调用的回调函数,其余参数是回调函数的参数。

    function userTest($type)
    {
        echo $type."\n";
    }
    
    $func = "userTest";
    call_user_func($func, "string");
    call_user_func($func, "boolean");
    call_user_func_array($func,["array"]);
    
    
    class myclass {
        public function sayHello($name)
        {
            echo "Hello $name!\n";
        }
    }
    
    $classname = "myclass";
    
    call_user_func(array($classname, 'sayHello'),"jm");//如果是类或方法是static时,可以采用这个方式
    call_user_func($classname .'::sayHello',"jm"); // As of 5.2.3,但我们不建议
    
    $myobject = new myclass();
    call_user_func(array($myobject, 'sayHello'),"jm");//如果不是static的类与方法,我们建议采用这个方式
    call_user_func_array([$myobject,"sayHello"], ['jm']);
    
  • call_user_func_array — 调用回调函数,并把一个数组参数作为回调函数的参数

    把第一个参数作为回调函数(callback)调用,把参数数组作(param_arr)为回调函数的的参数传入。

  • create_function — 创建一个匿名函数

    $newfunc = create_function('$a,$b', 'return "$a+ $b = " . ($a + $b);');
    echo $newfunc(1,2);//1+ 2 = 3
    
  • forward_static_call_array — Call a static method and pass the arguments as array

  • forward_static_call — Call a static method

  • get_defined_functions — 返回所有已定义函数的数组

  • register_shutdown_function — 注册一个会在php中止时执行的函数

    注册一个 callback ,它会在脚本执行完成或者 exit() 后被调用。

    可以多次调用 register_shutdown_function() ,这些被注册的回调会按照他们注册时的顺序被依次调用。如果你在注册的方法内部调用 exit(), 那么所有处理会被中止,并且其他注册的中止回调也不会再被调用。

    function willExit($params){
        print_r($params);
        echo "i am exit now.";
    
    }
    register_shutdown_function('willExit',["app"]);//同样支持函数、对象方法、参数
    

    注意:如果进程被信号SIGTERM或SIGKILL杀死,那么中止函数将不会被调用。

  • register_tick_function — 注册一个在每一次时钟周期触发的执行的函数

    Tick(时钟周期)是一个在 declare 代码段中解释器每执行 N 条可计时的低级语句就会发生的事件。N 的值是在 declare 中的 directive 部分用 ticks=N 来指定的。

    不是所有语句都可计时。通常条件表达式和参数表达式都不可计时。

    declare(ticks=1);
    
    // A function called on each tick event
    function tick_handler()
    {
        echo "tick_handler() called\n";
    }
    
    register_tick_function('tick_handler');
    
    $a = 1;
    
    if ($a > 0) {
        $a += 2;
        print_r($a."\n);
    }
    
    tick_handler() called
    tick_handler() called
    tick_handler() called
    3
    tick_handler() called
    
  • unregister_tick_function — 取消注册时钟周期触发函数

Ctype扩展函数

该扩展所提供的函数用来检测在当前的区域设定下,一个字符或者字符串是否仅包含指定类型的字符。

当传入参数为字符串的时候,它会对字符串中的每个字符进行检测,仅当字符串中的每个字符都符合指定条件的情况下才会返回 TRUE。

注意:如果可以满足需求,请优先考虑使用 ctype 函数,而不是正则表达式或者对应的 “str_*” 和 “is_*” 函数。因为 ctype 使用的是原生 C 库,所以会有明显的性能优势。

  • ctype_alnum — 做字母和数字字符检测

  • ctype_alpha — 做纯字符检测

  • ctype_cntrl — 做控制字符检测

  • ctype_digit — 做纯数字检测

    虽然说这个是纯数字检测,但如果给出一个 -128 到 255 之间(含)的整数, 将会被解释为该值对应的ASCII字符 (负值将加上 256 以支持扩展ASCII字符)。

    $numeric_string = '42';
    $integer        = 42;
    
    ctype_digit($numeric_string);  // true
    ctype_digit($integer);         // false (ASCII 42 is the * character)
    
    is_numeric($numeric_string);   // true
    is_numeric($integer);          // true
    

    所以纯数字的检测,建议采用is_int、is_numeric进行检测。

  • ctype_graph — 做可打印字符串检测,空格除外

  • ctype_lower — 做小写字符检测

  • ctype_print — 做可打印字符检测

  • ctype_punct — 检测可打印的字符是不是都是标点符号

  • ctype_space — 做空白字符检测

  • ctype_upper — 做大写字母检测

  • ctype_xdigit — 检测字符串是否只包含十六进制字符

Filter过滤器函数

该Filter扩展通过验证或清理数据来筛选数据。当数据源包含未知(或外部)数据(如用户提供的输入)时,这特别有用。例如,该数据可能来自HTML表单。

过滤主要有两种:验证和清洗。

验证是用来验证或检查数据是否满足某些条件。例如,传入FILTER_VALIDATE_EMAIL将确定数据是否是有效的电子邮件地址,但不会改变数据本身。

清洗会对数据进行清洗,因此它可以通过删除不需要的字符来改变数据。例如,传入filter_sanitie_email将删除不适合电子邮件地址包含的字符。也就是说,它不能验证数据。

  • filter_list — 返回所支持的过滤器列表

    Array
    (
        [0] => int
        [1] => boolean
        [2] => float
        [3] => validate_regexp
        [4] => validate_domain
        [5] => validate_url
        [6] => validate_email
        [7] => validate_ip
        [8] => validate_mac
        [9] => string
        [10] => stripped
        [11] => encoded
        [12] => special_chars
        [13] => full_special_chars
        [14] => unsafe_raw
        [15] => email
        [16] => url
        [17] => number_int
        [18] => number_float
        [19] => magic_quotes
        [20] => callback
    )
    
    
  • filter_id — 返回与某个特定名称的过滤器相关联的id

  • filter_has_var — 检测是否存在指定类型的变量

    检查这些输入:INPUT_GET、 INPUT_POST、 INPUT_COOKIE、 INPUT_SERVER、 INPUT_ENV 里的其中一个的变量。

    var_dump(filter_has_var(INPUT_GET, "name"));
    
  • filter_var — 使用特定的过滤器过滤一个变量

    filter_var( mixed $variable[, int $filter = FILTER_DEFAULT[, mixed $options]] ) : mixed
    
  • filter_var_array — 获取多个变量并且过滤它们

    不需要重复调用 filter_var() 就能获取多个变量。

    filter_var数组形式,输入变量数组,通过过滤器数组进行相应变量的过滤得到新的变量数组。

    现代web框架都有封装各自的类似机制的filter过滤器。

    error_reporting(E_ALL | E_STRICT);
    $data = array(
        'product_id'    => 'libgd<script>',
        'component'     => '10',
        'versions'      => '2.0.33',
        'testscalar'    => array('2', '23', '10', '12'),
        'testarray'     => '2',
    );
    
    $args = array(
        'product_id'   => FILTER_SANITIZE_ENCODED,
        'component'    => array('filter'    => FILTER_VALIDATE_INT,
                                'flags'     => FILTER_FORCE_ARRAY, 
                                'options'   => array('min_range' => 1, 'max_range' => 10)
                            ),
        'versions'     => FILTER_SANITIZE_ENCODED,
        'doesnotexist' => FILTER_VALIDATE_INT,
        'testscalar'   => array(
                                'filter' => FILTER_VALIDATE_INT,
                                'flags'  => FILTER_REQUIRE_SCALAR,
                            ),
        'testarray'    => array(
                                'filter' => FILTER_VALIDATE_INT,
                                'flags'  => FILTER_FORCE_ARRAY,
                            )
    
    );
    
    $myinputs = filter_var_array($data, $args);
    
    var_dump($myinputs);
    echo "\n";
    
  • filter_input — 通过名称获取特定的外部变量,并且可以通过过滤器处理它

    filter_input( int $type, string $variable_name[, int $filter = FILTER_DEFAULT[, mixed $options]] ) : mixed
    

    除了待检查变量从INPUT_GET, INPUT_POST, INPUT_COOKIE, INPUT_SERVER或 INPUT_ENV之一中获取外,其他的过滤器、过滤规则都和filter_var一样。

  • filter_input_array — 获取一系列外部变量,并且可以通过过滤器处理它们

    这个函数当需要获取很多变量却不想重复调用filter_input()时很有用。

  • 过滤器类型

    PHP: Types of filters - Manual

反射Reflection

PHP 5 具有完整的反射 API,添加了对类、接口、函数、方法和扩展进行反向工程的能力。此外,反射 API 提供了方法来取出函数、类和方法中的文档注释。

  • Reflection类

    这是一个静态类、静态方法:

    • Reflection::export — Exports

    • Reflection::getModifierNames — 获取修饰符的名称

      就是将其他比如ReflectionMethod中getModifiers获取到的修饰符标识转换成字符标识public、private等

  • ReflectionClass类

    返回了一个类的有关信息。

    • ReflectionClass::__construct — 初始化 ReflectionClass 类
    • ReflectionClass::export — 导出一个类
    • ReflectionClass::getConstant — 获取定义过的一个常量
    • ReflectionClass::getConstants — 获取一组常量
    • ReflectionClass::getConstructor — 获取类的构造函数
    • ReflectionClass::getDefaultProperties — 获取默认属性
    • ReflectionClass::getDocComment — 获取文档注释
    • ReflectionClass::getEndLine — 获取最后一行的行数
    • ReflectionClass::getExtension — 根据已定义的类获取所在扩展的 ReflectionExtension 对象
    • ReflectionClass::getExtensionName — 获取定义的类所在的扩展的名称
    • ReflectionClass::getFileName — 获取定义类的文件名
    • ReflectionClass::getInterfaceNames — 获取接口(interface)名称
    • ReflectionClass::getInterfaces — 获取接口
    • ReflectionClass::getMethod — 获取一个类方法的 ReflectionMethod。
    • ReflectionClass::getMethods — 获取方法的数组
    • ReflectionClass::getModifiers — 获取类的修饰符
    • ReflectionClass::getName — 获取类名
    • ReflectionClass::getNamespaceName — 获取命名空间的名称
    • ReflectionClass::getParentClass — 获取父类
    • ReflectionClass::getProperties — 获取一组属性
    • ReflectionClass::getProperty — 获取类的一个属性的 ReflectionProperty
    • ReflectionClass::getReflectionConstant — Gets a ReflectionClassConstant for a class’s constant
    • ReflectionClass::getReflectionConstants — Gets class constants
    • ReflectionClass::getShortName — 获取短名
    • ReflectionClass::getStartLine — 获取起始行号
    • ReflectionClass::getStaticProperties — 获取静态(static)属性
    • ReflectionClass::getStaticPropertyValue — 获取静态(static)属性的值
    • ReflectionClass::getTraitAliases — 返回 trait 别名的一个数组
    • ReflectionClass::getTraitNames — 返回这个类所使用 traits 的名称的数组
    • ReflectionClass::getTraits — 返回这个类所使用的 traits 数组
    • ReflectionClass::hasConstant — 检查常量是否已经定义
    • ReflectionClass::hasMethod — 检查方法是否已定义
    • ReflectionClass::hasProperty — 检查属性是否已定义
    • ReflectionClass::implementsInterface — 接口的实现
    • ReflectionClass::inNamespace — 检查是否位于命名空间中
    • ReflectionClass::isAbstract — 检查类是否是抽象类(abstract)
    • ReflectionClass::isAnonymous — 检查类是否是匿名类
    • ReflectionClass::isCloneable — 返回了一个类是否可复制
    • ReflectionClass::isFinal — 检查类是否声明为 final
    • ReflectionClass::isInstance — 检查类的实例
    • ReflectionClass::isInstantiable — 检查类是否可实例化
    • ReflectionClass::isInterface — 检查类是否是一个接口(interface)
    • ReflectionClass::isInternal — 检查类是否由扩展或核心在内部定义
    • ReflectionClass::isIterable — Check whether this class is iterable
    • ReflectionClass::isIterateable — 检查是否可迭代(iterateable)
    • ReflectionClass::isSubclassOf — 检查是否为一个子类
    • ReflectionClass::isTrait — 返回了是否为一个 trait
    • ReflectionClass::isUserDefined — 检查是否由用户定义的
    • ReflectionClass::newInstance — 从指定的参数创建一个新的类实例
    • ReflectionClass::newInstanceArgs — 从给出的参数创建一个新的类实例。
    • ReflectionClass::newInstanceWithoutConstructor — 创建一个新的类实例而不调用它的构造函数
    • ReflectionClass::setStaticPropertyValue — 设置静态属性的值
    • ReflectionClass::__toString — 返回 ReflectionClass 对象字符串的表示形式。
  • ReflectionClassConstant类

    返回关于类常量的信息。

    • ReflectionClassConstant::__construct -构造一个ReflectionClassConstant

    • ReflectionClassConstant::export - 导出

    • ReflectionClassConstant::getDeclaringClass -获取声明类

    • ReflectionClassConstant::getDocComment -获取文档注释

    • ReflectionClassConstant::getModifiers -获取类常量修饰符

    • ReflectionClassConstant::getName -获取常量的名称

    • ReflectionClassConstant::getValue -获取值

    • ReflectionClassConstant::isPrivate -检查类常量是否为private

    • ReflectionClassConstant::isProtected -检查类常量是否被保护

    • ReflectionClassConstant::isPublic -检查类常量是否为public

    • ReflectionClassConstant::__toString -返回ReflectionClassConstant对象的字符串表示形式

  • ReflectionMethod类

    返回了一个方法的有关信息。

    • ReflectionMethod::__construct — ReflectionMethod 的构造函数
    • ReflectionMethod::export — 输出一个回调方法
    • ReflectionMethod::getClosure — 返回一个动态建立的方法调用接口,译者注:可以使用这个返回值直接调用非公开方法。
    • ReflectionMethod::getDeclaringClass — 获取被反射的方法所在类的反射实例
    • ReflectionMethod::getModifiers — 获取方法的修饰符
    • ReflectionMethod::getPrototype — 返回方法原型 (如果存在)
    • ReflectionMethod::invoke — Invoke
    • ReflectionMethod::invokeArgs — 带参数执行
    • ReflectionMethod::isAbstract — 判断方法是否是抽象方法
    • ReflectionMethod::isConstructor — 判断方法是否是构造方法
    • ReflectionMethod::isDestructor — 判断方法是否是析构方法
    • ReflectionMethod::isFinal — 判断方法是否定义 final
    • ReflectionMethod::isPrivate — 判断方法是否是私有方法
    • ReflectionMethod::isProtected — 判断方法是否是保护方法 (protected)
    • ReflectionMethod::isPublic — 判断方法是否是公开方法
    • ReflectionMethod::isStatic — 判断方法是否是静态方法
    • ReflectionMethod::setAccessible — 设置方法是否访问
    • ReflectionMethod::__toString — 返回反射方法对象的字符串表达
  • ReflectionProperty类

    返回了类的属性的相关信息。

    • ReflectionProperty:: __clone -克隆

    • ReflectionProperty::__construct—构造一个ReflectionProperty对象

    • ReflectionProperty::export - 导出

    • ReflectionProperty::getDeclaringClass -获取声明类

    • ReflectionProperty::getDefaultValue—返回为属性声明的默认值

    • ReflectionProperty::getDocComment -获取属性doc注释

    • ReflectionProperty::getModifiers -获取属性修饰符

    • ReflectionProperty::getName -获取属性名

    • ReflectionProperty::getType -获取属性的类型

    • ReflectionProperty::getValue -获取值

    • ReflectionProperty::hasDefaultValue -检查属性是否声明了默认值

    • ReflectionProperty::hasType -检查属性是否有类型

    • ReflectionProperty::isDefault -检查property是否为默认属性

    • ReflectionProperty::isInitialized -检查一个属性是否已初始化

    • ReflectionProperty::isPrivate -检查属性是否为私有

    • ReflectionProperty::isProtected -检查属性是否被保护

    • ReflectionProperty::isPublic -检查属性是否为公共属性

    • ReflectionProperty::isStatic -检查属性是否是静态的

    • ReflectionProperty::setAccessible -设置属性的可访问性

    • ReflectionProperty::setValue—设置属性值

    • ReflectionProperty::__toString - To string

  • ReflectionExtension类

    返回了一个扩展(extension)的有关信息。

    • ReflectionExtension::__clone — Clones
    • ReflectionExtension::__construct — Constructs a ReflectionExtension
    • ReflectionExtension::export — 导出
    • ReflectionExtension::getClasses — 获取扩展中的类列表
    • ReflectionExtension::getClassNames — 获取类名称
    • ReflectionExtension::getConstants — 获取常量
    • ReflectionExtension::getDependencies — 获取依赖
    • ReflectionExtension::getFunctions — 获取扩展中的函数
    • ReflectionExtension::getINIEntries — 获取ini配置
    • ReflectionExtension::getName — 获取扩展名称
    • ReflectionExtension::getVersion — 获取扩展版本号
    • ReflectionExtension::info — 输出扩展信息
    • ReflectionExtension::isPersistent — 返回扩展是否持久化载入
    • ReflectionExtension::isTemporary — 返回扩展是否是临时载入
    • ReflectionExtension::__toString — To string
  • ReflectionFunctionAbstract 类

    ReflectionFunction 的父类,详情请阅读它的描述。

    • ReflectionFunctionAbstract::__clone — 复制函数
    • ReflectionFunctionAbstract::getClosureScopeClass — Returns the scope associated to the closure
    • ReflectionFunctionAbstract::getClosureThis — 返回本身的匿名函数
    • ReflectionFunctionAbstract::getDocComment — 获取注释内容
    • ReflectionFunctionAbstract::getEndLine — 获取结束行号
    • ReflectionFunctionAbstract::getExtension — 获取扩展信息
    • ReflectionFunctionAbstract::getExtensionName — 获取扩展名称
    • ReflectionFunctionAbstract::getFileName — 获取文件名称
    • ReflectionFunctionAbstract::getName — 获取函数名称
    • ReflectionFunctionAbstract::getNamespaceName — 获取命名空间
    • ReflectionFunctionAbstract::getNumberOfParameters — 获取参数数目
    • ReflectionFunctionAbstract::getNumberOfRequiredParameters — 获取必须输入参数个数
    • ReflectionFunctionAbstract::getParameters — 获取参数
    • ReflectionFunctionAbstract::getReturnType — Gets the specified return type of a function
    • ReflectionFunctionAbstract::getShortName — 获取函数短名称
    • ReflectionFunctionAbstract::getStartLine — 获取开始行号
    • ReflectionFunctionAbstract::getStaticVariables — 获取静态变量
    • ReflectionFunctionAbstract::hasReturnType — Checks if the function has a specified return type
    • ReflectionFunctionAbstract::inNamespace — 检查是否处于命名空间
    • ReflectionFunctionAbstract::isClosure — 检查是否是匿名函数
    • ReflectionFunctionAbstract::isDeprecated — 检查是否已经弃用
    • ReflectionFunctionAbstract::isGenerator — 判断函数是否是一个生成器函数
    • ReflectionFunctionAbstract::isInternal — 判断函数是否是内置函数
    • ReflectionFunctionAbstract::isUserDefined — 检查是否是用户定义
    • ReflectionFunctionAbstract::isVariadic — Checks if the function is variadic
    • ReflectionFunctionAbstract::returnsReference — 检查是否返回参考信息
    • ReflectionFunctionAbstract::__toString — 字符串化
  • ReflectionFunction类

    返回了一个函数的有关信息。

    • ReflectionFunction::__construct -构造一个ReflectionFunction对象

    • ReflectionFunction::export -导出功能

    • ReflectionFunction::getClosure —为函数返回一个动态创建的闭包

    • ReflectionFunction::invoke -调用函数

    • ReflectionFunction::invokeArgs -调用函数参数

    • ReflectionFunction::isDisabled -检查功能是否被禁用

    • ReflectionFunction::__toString - toString

  • ReflectionParameter类

    取回了函数或方法参数的相关信息。

    • ReflectionParameter::allowsNull -检查是否允许为空

    • ReflectionParameter::canBePassedByValue—返回该参数是否可以通过value传递

    • ReflectionParameter:: __clone -克隆

    • ReflectionParameter:: __construct -构造

    • ReflectionParameter:export - 导出

    • ReflectionParameter::getClass — 获得类型提示类

    • ReflectionParameter::getDeclaringClass -获取声明类

    • ReflectionParameter::getDeclaringFunction -获取声明的函数

    • ReflectionParameter::getDefaultValue -获取默认参数值

    • ReflectionParameter::getDefaultValueConstantName -如果默认值为常量或null,返回默认值的常量名

    • ReflectionParameter::getName -获取参数名

    • ReflectionParameter::getPosition—获取参数位置

    • ReflectionParameter::getType -获取参数的类型

    • ReflectionParameter::hasType -检查parameter是否有类型

    • ReflectionParameter::isArray -检查parameter是否需要一个数组

    • ReflectionParameter::isCallable—返回参数是否必须可调用

    • ReflectionParameter:: isDefaultValueAvailable -检查是否有默认值。

    • ReflectionParameter::isDefaultValueConstant—返回该参数的默认值是否为常量

    • ReflectionParameter::isOptional -检查是否可选

    • ReflectionParameter::isPassedByReference—检查是否通过引用传递

    • ReflectionParameter::isVariadic -检查参数是否为variadic

    • ReflectionParameter::__toString - To string

  • ReflectionType 类

    用于获取函数、类方法的参数或者返回值的类型。

    • ReflectionType::allowsNull—检查是否允许为空

    • ReflectionType:: isbuilt -检查是否为内置类型

    • ReflectionType::__toString - toString

  • ReflectionGenerator类

    用于获取生成器的信息。 比如有yield的函数。

    • ReflectionGenerator::__construct -构造一个ReflectionGenerator对象

    • ReflectionGenerator::getExecutingFile -获取当前正在执行的生成器的文件名

    • ReflectionGenerator::getExecutingGenerator -获取正在执行的生成器对象

    • ReflectionGenerator::getExecutingLine -获取生成器当前执行的行

    • ReflectionGenerator::getFunction -获取生成器的函数名

    • ReflectionGenerator::getThis -获取生成器的$this值

    • ReflectionGenerator::getTrace -获取正在执行的生成器的跟踪信息

  • ReflectionException类

SOAP

一次清楚SOAP

一次清楚SOAP

yar高效RPC框架

Yar 是一个轻量级, 高效的RPC框架, 它提供了一种简单方法来让PHP项目之间可以互相远程调用对方的本地方法. 并且Yar也提供了并行调用的能力. 可以支持同时调用多个远程服务的方法。

  • yar的特点:

    • 快速,简单,简单

    • 支持并发RPC调用

    • 支持多种数据包(php, json, msgpack内置)

    • 支持多种传输协议(http、https、TCP)

    • 详细的调试信息

  • 运行时配置

    yar.timeout //default 5000 (ms)
    yar.connect_timeout //default 1000 (ms)
    yar.packager //default "php", when built with --enable-msgpack then default "msgpack", it should be one of "php", "json", "msgpack"
    yar.debug //default Off
    yar.expose_info // default On, whether output the API info for GET requests
    yar.content_type // default "application/octet-stream"
    yar.allow_persistent // default Off
    
  • server端

    
    class Operator {
    
        /**
        * Add two operands
        * @param interge 
        * @return interge
        */
        public function add($a, $b) {
            if(!$a || !$b){
                throw new Exception("server exception:a | b不能为空.");
            }
            return $this->_add($a, $b);
        }
          
        /**
        * Sub 
        */
        public function sub($a, $b) {
            return $a - $b;
        }
    
        /**
        * Mul
        */
        public function mul($a, $b) {
            return $a * $b;
        }
          
        /**
        * 返回一个数组
        * @return array
        */
        public function returnArray(){
            return ['a'=>"apple","b"=>'banana'];
        }
      
    
        /**
        * Protected methods will not be exposed
        * @param interge 
        * @return interge
        */
        protected function _add($a, $b) {
            return $a + $b;
        }
    }
    
    $server = new Yar_Server(new Operator());
    $server->handle();//启动服务, 开始接受客户端的调用请求. 来自客户端的调用, 都是通过POST请求发送过来的  
      
    

    假设server端脚本访问路径:http://demo.130.com/FunctionsReference/yar/yarServer.php
    则访问时会展示:

    -Operator::add($a, $b)
    ----------------------
    /**
    * Add two operands
    * @param interge
    * @return interge
    */
      
    -Operator::sub($a, $b)
    ----------------------
    /**
    * Sub
    */
    
    -Operator::mul($a, $b)
    ----------------------
    /**
    * Mul
    */
      
    ----------------------
    -Operator::returnArray()
    /**
    * 返回一个数组
    * @return array
    */    
    
  • client端

          
    //发起一个RPC调用, 并且得到返回值. 如果服务端的远程调用抛出异常, 那么本地也会相应的抛出一个Yar_Server_Exception异常. 
    $client = new yar_client("http://demo.130.com/FunctionsReference/yar/yarServer.php");
    
    //设置调用远程服务的一些配置, 比如超时值, 打包类型等. 
    //可以是: YAR_OPT_PACKAGER、YAR_OPT_PERSISTENT (需要服务端支持keepalive)、YAR_OPT_TIMEOUT、YAR_OPT_CONNECT_TIMEOUT 
    //Set timeout to 1s
    $client->SetOpt(YAR_OPT_CONNECT_TIMEOUT, 1000);
    //Set packager to JSON
    //$client->SetOpt(YAR_OPT_PACKAGER, "json");//默认php, "php", "json", "msgpack",this server accept json packager
    //设置header
    $client->SetOpt(YAR_OPT_HEADER, array("hd1: val", "hd2: val"));  //Custom headers, Since 2.0.4
    
    try{
        /*远程调用方式1: call directly */
        var_dump($client->add(1, 2));
    
        /*远程调用方式2: call via __call */
        var_dump($client->__call("add", array(3, 2)));
        var_dump($client->returnArray());
        var_dump($client->add(0, 2));//远端服务端抛出异常
          
    } catch (Yar_Server_Exception $sex) {
        //Yar_Server_Exceptioin可以捕获server端throw new exception异常
        var_dump($sex->getMessage());
    }catch(Yar_Client_Exception $cex){
        //处理Yar_Client_Exception
        var_dump($cex->getMessage());
    }
    
    
    /* public以外的方法不能被调用,so __add can not be called */
    //var_dump($client->_add(1, 2));
    

    输出:

    int(3)
    int(5)
    array(2) {
    ["a"]=>
    string(5) "apple"
    ["b"]=>
    string(6) "banana"
    }
    string(37) "server exception:a | b不能为空."
    
    
  • 并行调用

    • Yar_Concurrent_Client::call — 注册一个并行的服务调用

    • Yar_Concurrent_Client::loop — 发送所有注册的并行调用

      public static Yar_Concurrent_Client::loop([ callable $callback[, callable $error_callback]] ) : boolean
      

      如果这个回掉函数被设置, 那么Yar在发送出所有的请求之后立即调用一次这个回掉函数(此时还没有任何请求返回), 调用的时候$callinfo参数是NULL。

      如果在注册并行调用的时候制定了callback, 那么那个callback有更高的优先级。

    
    function callback($retval, $callinfo)
    {
        if ($callinfo == NULL) {
            echo "现在, 所有的请求都发出去了, 还没有任何请求返回\n";
        } else {
            echo "这是一个远程调用的返回, 调用的服务名是", $callinfo["method"],
            ". 调用的sequence是 ", $callinfo["sequence"], "\n";
            var_dump($retval);
        }
    }
    
    function loopCallback($retval, $callinfo){
          
    }
    
    function error_callback($type, $error, $callinfo)
    {
        error_log($error);
    }
    
    $webserviceApi = "http://demo.130.com/FunctionsReference/yar/yarServer.php";
    
    try{    
        Yar_Concurrent_Client::call($webserviceApi, "mul", [1,1], "callback");
          
        // if the callback is not specificed, callback in loop will be used
        Yar_Concurrent_Client::call($webserviceApi, "mul", [2,2]);   
          
        //it should be one of "php", "json", "msgpack" .默认php格式, json告诉服务端,客户端接收json格式数据
        Yar_Concurrent_Client::call($webserviceApi, "addJson", [3,3], "callback", NULL, [YAR_OPT_PACKAGER => "json"]);
          
        //custom timeout 
        Yar_Concurrent_Client::call($webserviceApi, "mul", [4,4], "callback", NULL, [YAR_OPT_TIMEOUT => 1]);
    
        //发送所有的已经通过 Yar_Concurrent_Client::call()注册的并行调用, 并且等待返回. the error_callback is optional
        Yar_Concurrent_Client::loop("callback", "error_callback"); 
    } catch (Yar_Server_Exception $ex) {
        var_dump($ex->getMessage());
    }catch(Yar_Client_Exception $ex){
        var_dump($ex->getMessage());
    }    
    
    
  • 持久调用

    在Yar 2.1.0之后,如果YAR_OPT_PERSISTENT设置为true,那么Yar就可以使用HTTP keep-alive来加速对同一个地址的重复调用,链接将在PHP请求生命周期结束时释放。

    $client = new Yar_Client("http://host/api/");
    $client->SetOpt(YAR_OPT_PERSISTENT, 1);
    
    $result = $client->some_method("parameter");
    
    /* The following calls will speed up due to keep-alive */
    $result = $client->some_other_method1("parameter");
    $result = $client->some_other_method2("parameter");
    $result = $client->some_other_method3("parameter");
    
    Yar(Yet Another RPC framework)是一个轻量级支持并行调用的PHP RPC框架,是我还在微博的时候为了优化微博的性能而开发的一个工具,Yar的并行调用在微博被大量应用以降低用户请求耗时。 最近还是因为疫情,我把Yaf,Yaconf都优化了一轮,今天也完成了Yar的优化(事实上,Yar之前写的就还不错,没啥可优化的,哈哈),也新增了俩个能力。我来简单介绍下:

  • 自定义主机名解析

    在Yar 2.1.0之后,如果Yar运行在HTTP协议上,则可以使用YAR_OPT_RESOLVE来定义自定义主机名解析。

    $client = new Yar_Client("http://host/api/");
    
    $client->SetOpt(YAR_OPT_RESOLVE, "host:80:127.0.0.1");
    
    /* call goes to 127.0.0.1 */
    $result = $client->some_method("parameter");
    
  • http代理

    在Yar 2.2.1之后,如果Yar运行在HTTP协议上,则可以使用YAR_OPT_PROXY来定义HTTP代理,例如fidder或charles。

    $client = new Yar_Client("http://host/api/");
    
    $client->SetOpt(YAR_OPT_PROXY,"127.0.0.1:8888"); //http proxy , Since 2.2.0
    
    /* call goes to 127.0.0.1 */
    $result = $client->some_method("parameter"); 
    
  • github官方地址及鸟哥关于yar的文章

    Light, concurrent RPC framework for PHP & C. Contribute to laruence/yar development by creating an account on GitHub.

    Yar(Yet Another RPC framework)是一个轻量级支持并行调用的PHP RPC框架,是我还在微博的时候为了优化微博的性能而开发的一个工具,Yar的并行调用在微博被大量应用以降低用户请求耗时。 最近还是因为疫情,我把Yaf,Yaconf都优化了一轮,今天也完成了Yar的优化(事实上,Yar之前写的就还不错,没啥可优化的,哈哈),也新增了俩个能力。我来简单介绍下:

    Yar(yet another RPC framework, 教主问我为啥都是Ya打头, 呵呵, 因为这样名字好起)是我在3个多月前, 为了解决一个实际的问题, 而开发的一个PHP扩展的, RPC框架, 和现有的RPC框架(xml-rpc, soap)不同, 这是一个轻量级的框架, 支持多种打包协议(msgpack, json, php), 并且最重要的一个特点是, 它是可并行化的..