首页
关于
Search
1
给你10个市场数据调研报告的免费下载网站!以后竞品数据就从这里找!
135 阅读
2
php接口优化 使用curl_multi_init批量请求
128 阅读
3
2024年备考系统架构设计师
102 阅读
4
《从菜鸟到大师之路 ElasticSearch 篇》
101 阅读
5
PHP 文件I/O
89 阅读
php
thinkphp
laravel
工具
开源
mysql
数据结构
总结
思维逻辑
令人感动的创富故事
读书笔记
前端
vue
js
css
书籍
开源之旅
架构
消息队列
docker
教程
代码片段
redis
服务器
nginx
linux
科普
java
c
ElasticSearch
测试
php进阶
php基础
登录
Search
标签搜索
php函数
php语法
性能优化
安全
错误和异常处理
问题
vue
Composer
Session
缓存
框架
Swoole
api
并发
异步
正则表达式
php-fpm
mysql 索引
开发规范
协程
dafenqi
累计撰写
785
篇文章
累计收到
4
条评论
首页
栏目
php
thinkphp
laravel
工具
开源
mysql
数据结构
总结
思维逻辑
令人感动的创富故事
读书笔记
前端
vue
js
css
书籍
开源之旅
架构
消息队列
docker
教程
代码片段
副业
redis
服务器
nginx
linux
科普
java
c
ElasticSearch
测试
php进阶
php基础
页面
关于
搜索到
559
篇与
的结果
2023-08-04
360提供的PHP防注入代码
360提供的PHP防注入代码PHP代码 <?php//Code By Safe3function customError($errno, $errstr, $errfile, $errline){ echo "Error number: [$errno],error on line $errline in $errfile" ; die();} set_error_handler("customError",E_ERROR);$getfilter="'|(and|or)\b.+?(>|<|=|in|like)|\/\.+?\\/|<\s*script\b|\bEXEC\b|UNION.+?Select|Update.+?SET|Insert\s+INTO.+?VALUES|(Select|Delete).+?FROM|(Create|Alter|Drop|TRUNCATE)\s+(TABLE|DATABASE)" ;$postfilter="\b(and|or)\b.{1,6}?(=|>|<|\bin\b|\blike\b)|\/\.+?\\/|<\s*script\b|\bEXEC\b|UNION.+?Select|Update.+?SET|Insert\s+INTO.+?VALUES|(Select|Delete).+?FROM|(Create|Alter|Drop|TRUNCATE)\s+(TABLE|DATABASE)" ;$cookiefilter="\b(and|or)\b.{1,6}?(=|>|<|\bin\b|\blike\b)|\/\.+?\\/|<\s*script\b|\bEXEC\b|UNION.+?Select|Update.+?SET|Insert\s+INTO.+?VALUES|(Select|Delete).+?FROM|(Create|Alter|Drop|TRUNCATE)\s+(TABLE|DATABASE)" ;function StopAttack($StrFiltKey,$StrFiltValue,$ArrFiltReq){if(is_array($StrFiltValue)){ $StrFiltValue=implode($StrFiltValue);}if (preg_match("/".$ArrFiltReq."/is",$StrFiltValue)==1){//slog("<br><br>操作IP: ".$_SERVER["REMOTE_ADDR"]."<br>操作时间: ".strftime("%Y-%m-%d %H:%M:%S")."<br>操作页面:".$_SERVER["PHP_SELF"]."<br>提交方式: ".$_SERVER["REQUEST_METHOD"]."<br>提交参数: ".$StrFiltKey."<br>提交数据: ".$StrFiltValue); print "360websec notice:Illegal operation!" ; exit();}}//$ArrPGC=array_merge($_GET,$_POST,$_COOKIE);foreach($_GET as $key=>$value){ StopAttack($key,$value,$getfilter);}foreach($_POST as $key=>$value){ StopAttack($key,$value,$postfilter);}foreach($_COOKIE as $key=>$value){ StopAttack($key,$value,$cookiefilter);}if (file_exists('update360.php')) { echo "请重命名文件update360.php,防止黑客利用<br/>"; die();}function slog($logs){ $toppath=$_SERVER["DOCUMENT_ROOT"]."/log.htm"; $Ts=fopen($toppath,"a+"); fputs($Ts,$logs."\r\n"); fclose($Ts);}
2023年08月04日
23 阅读
0 评论
0 点赞
2023-08-04
深入理解PHP原理之foreach
深入理解PHP原理之foreach经常会有人问我, PHP的数组, 如果用foreach来访问, 遍历的顺序是固定的么? 以什么顺序遍历呢?比如:<?php$arr['laruence'] = 'huixinchen';$arr['yahoo'] = 2007;$arr['baidu'] = 2008;foreach ($arr as $key => $val) {//结果是什么?}又比如:<?php$arr[2] = 'huixinchen';$arr[1] = 2007;$arr[0] = 2008;foreach ($arr as $key => $val) {//现在结果又是什么?}要完全了解清楚这个问题, 我想首先应该要大家了解PHP数组的内部实现结构………PHP的数组在PHP中, 数组是用一种HASH结构(HashTable)来实现的, PHP使用了一些机制, 使得可以在O(1)的时间复杂度下实现数组的增删, 并同时支持线性遍历和随机访问.之前的文章中也讨论过, PHP的HASH算法, 基于此, 我们做进一步的延伸.认识HashTable之前, 首先让我们看看HashTable的结构定义, 我加了注释方便大家理解:typedef struct _hashtable {uint nTableSize; / 散列表大小, Hash值的区间 /uint nTableMask; / 等于nTableSize -1, 用于快速定位 /uint nNumOfElements; / HashTable中实际元素的个数 /ulong nNextFreeElement; / 下个空闲可用位置的数字索引 /Bucket pInternalPointer; / 内部位置指针, 会被reset, current这些遍历函数使用 */Bucket pListHead; / 头元素, 用于线性遍历 */Bucket pListTail; / 尾元素, 用于线性遍历 */Bucket *arBuckets; / 实际的存储容器 */dtor_func_t pDestructor;/ 元素的析构函数(指针) /zend_bool persistent;unsigned char nApplyCount; / 循环遍历保护 /zend_bool bApplyProtection;if ZEND_DEBUGint inconsistent;endif} HashTable;关于nApplyCount的意义, 我们可以通过一个例子来了解:<?php$arr = array(1,2,3,4,5,); $arr[] = &$arr; var_export($arr); //Fatal error: Nesting level too deep - recursive dependency?这个字段就是为了防治循环引用导致的无限循环而设立的.查看上面的结构, 可以看出, 对于HashTable, 关键元素就是arBuckets了, 这个是实际存储的容器, 让我们来看看它的结构定义:typedef struct bucket {ulong h; / 数字索引/hash值 /uint nKeyLength; / 字符索引的长度 /void pData; / 数据 */void pDataPtr; / 数据指针 */struct bucket pListNext; / 下一个元素, 用于线性遍历 */struct bucket pListLast; / 上一个元素, 用于线性遍历 */struct bucket pNext; / 处于同一个拉链中的下一个元素 */struct bucket pLast; / 处于同一拉链中的上一个元素 */char arKey[1]; / 节省内存,方便初始化的技巧 /} Bucket;我们注意到, 最后一个元素, 这个是flexible array技巧, 可以节省内存,和方便初始化的一种做法, 有兴趣的朋友可以google flexible array.h是元素的Hash值,对于数字索引的元素,h为直接索引值(通过nKeyLength=0来表示是数字索引).而对于字符串索引来说, 索引值保存在arKey中, 索引的长度保存在nKeyLength中.在Bucket中,实际的数据是保存在pData指针指向的内存块中,通常这个内存块是系统另外分配的。但有一种情况例外,就是当Bucket保存 的数据是一个指针时,HashTable将不会另外请求系统分配空间来保存这个指针,而是直接将该指针保存到pDataPtr中,然后再将pData指向本结构成员的地址。这样可以提高效率,减少内存碎片。由此我们可以看到PHP HashTable设计的精妙之处。如果Bucket中的数据不是一个指针,pDataPtr为NULL(本段来自Altair的”Zend HashTable详解”)结合上面的HashTable结构, 我们来说明下HashTable的总结构图:HashTable结构示意图HashTable结构示意图HashTable的pListhHead指向线性列表形式下的第一个元素, 上图中是元素1, pListTail指向的是最后一个元素0, 而对于每一个元素pListNext就是红色线条画出的线性结构的下一个元素, 而pListLast是上一个元素.pInternalPointer指向当前的内部指针的位置, 在对数组进行顺序遍历的时候, 这个指针指明了当前的元素.当在线性(顺序)遍历的时候, 就会从pListHead开始, 顺着Bucket中的pListNext/pListLast, 根据移动pInternalPointer, 来实现对所有元素的线性遍历.比如, 对于foreach, 如果我们查看它生成的opcode序列, 我们可以发现, 在foreach之前, 会首先有个FE_RESET来重置数组的内部指针, 也就是pInternalPointer(关于foreach可以参看深入理解PHP原理之foreach), 然后通过每次FE_FETCH来递增pInternalPointer,从而实现顺序遍历.类似的, 当我们使用, each/next系列函数来遍历的时候, 也是通过移动数组的内部指针而实现了顺序遍历, 这里有一个问题, 比如:<?php$arr = array(1,2,3,4,5);foreach ($arr as $v) {//可以获取}while (list($key, $v) = each($arr)) {//获取不到}?>了解到我刚才介绍的知识, 那么这个问题也就很明朗了, 因为foreach会自动reset, 而while这块不会reset, 所以在foreach结束以后, pInternalPointer指向数组最末端, while语句块当然访问不到了, 解决的办法就是在each之前, 先reset数组的内部指针.而在随机访问的时候, 就会通过hash值确定在hash数组中的头指针位置, 然后通过pNext/pLast来找到特点元素.增加元素的时候, 元素会插在相同Hash元素链的头部和线性列表的尾部. 也就是说, 元素在线性遍历的时候是根据插入的先后顺序来遍历的, 这个特殊的设计使得在PHP中,当使用数字索引时, 元素的先后顺序是由添加的顺序决定的,而不是索引顺序.也就是说, PHP中遍历数组的顺序, 是和元素的添加先后相关的, 那么, 现在我们就很清楚的知道, 文章开头的问题的输出是:huixinchen20072008所以, 如果你想在数字索引的数组中按照索引大小遍历, 那么你就应该使用for, 而不是foreachfor($i=0,$l=count($arr); $i<$l; $i++) { //这个时候,不能认为是顺序遍历(线性遍历)}
2023年08月04日
15 阅读
0 评论
0 点赞
2023-08-04
系统管理员应知:十大PHP最佳安全实践
系统管理员应知:十大PHP最佳安全实践导读:本文来自知名时尚媒体ELLE大陆版即《世界时装之苑》网站的香港工程师AnsonCheung文中他例举了有关PHP10个方面的最佳平安实践方式,供系统管理员学习与参考。原文是Top10PHPBestSecurPracticforSyAdmin以下是译文: PHP被广泛用于各种Web开发。而当服务器端脚本配置过失时会呈现各种问题。现今,大部分Web服务器是基于Linux环境下运行(比方:UbuntuDebian等)本文例举了十大PHP最佳平安实践方式,能够让您轻松、平安配置PHP 1.减少PHP内置模块 为了增强性能和安全性,强烈建议,减少PHP中的模块。来看看下面这个被执行命令装置的模块。 php–m 将会得到类似的结果: [PHPModules]apcbcmathbz2calendarCorectypecurldatedomeregexiffileinfofilterftpgdgettextgmphashiconvimapjsonlibxmlmbstringmemcachemysqlmysqliopensslpcntlpcrePDOpdo_mysqlpdo_sqlitePharreadlineReflectionsessionshmopSimpleXMLsocketsSPLsqlite3standardsuhosintokenizerwddxxmlxmlreaderxmlrpcxmlwriterxslzipzlib[ZendModules]Suhosin 删除一个模块,并执行此命令。例如:删除模块sqlite3 rm/etc/php.d/sqlite3.ini 或者 mv/etc/php.d/sqlite3.ini/etc/php.d/sqlite3.disableRestrict2.使PHP信息泄露最小化 默认PHP时在HTTP抬头处会生成一条线介于每个响应中,比方X-Powered-By:PHP/5.2.10而这个在系统信息中为攻击者创建了一个非常有价值的信息。 HTTP示例: HTTP/1.1200OKX-Powered-By:PHP/5.2.10Content-type:text/html;charset=UTF-8Vary:Accept-Encoding,COOKIEX-Vary-Options:Accept-Encoding;list-contains=gzip,COOKIE;string-contains=wikiToken;string-contains=wikiLoggedOut;string-contains=wiki_sessionLast-Modified:Thu,03Nov201122:32:55GMT... 因此,强烈建议,禁止PHP信息泄露,想要要禁止它要编辑/etc/php.d/secutity.ini并设置以下指令: expose_php=Off3.使PHP加载模块最小化 默认情况下,RHEL加载的所有模块可以在/etc/php.d/目录中找到要禁用或启用一个特定的模块,只需要在配置文件/etc/php.d/目录中中注释下模块名称。而为了优化PHP性能和安全性,当你应用顺序需要时,强烈建议建议启用扩展功能。举个例子:当禁用GD扩展时,键入以下命令: cd/etc/php.d/mvgd.{ini,disable}/etc/init.d/apache2restart 为了扩展PGPGD模块,然后键入以下命令: mvgd.{disable,ini}/sbin/servichttpdrestart4.记录PHP过失信息 为了提高系统和Web应用顺序的平安,PHP过失信息不能被暴露出。要做到这一点,需要编辑/etc/php.d/security.ini文件,并设置以下指令: display_errors=Off 为了便于开发者Bug修复,所有PHP过失信息都应该记录在日志中。 log_errors=Onerror_log=/var/log/httpd/php_scripts_error.log5.禁用远程执行代码 如果远程执行代码,允许PHP代码从远程检索数据功能,如FTP或Web通过PHP来执行构建功能。比方:file_get_cont 很多顺序员使用这些功能,从远程通过FTP或是HTTP协议而获得数据。然而,此法在基于PHP应用顺序中会造成一个很大的漏洞。由于大部分顺序员在传送用户提供的数据时没有做到适当的过滤功能,打开平安漏洞并且创立了代码时注入了漏洞。要解决此问题,需要禁用_url_fopenin/etc/php.d/security.ini并设置以下命令: allow_url_fopen=Off 除了这个,还建议禁用_url_includ以提高系统的平安性。 allow_url_include=Off6.禁用PHP中的危险函数 PHP中有很多危险的内置功能,如果使用不当,可能使你系统解体。可以创立一个PHP内置功能列表通过编辑/etc/php.d/security.ini来禁用它 disable_functions=exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_sourc7.资源控制 为了提高系统的稳定性,强烈建议设置每个脚本解析请求数据所花费的时间和脚本可能消耗的最大内存量。正确的配置这些参数可以防止PHP任何脚本消耗太多的资源或是内存,从而防止系统不安全或降低平安系数。 setinsecondmax_execution_time=30max_input_time=30memory_limit=40M8.限制PHP访问文件系统 该open_basedir指令指定的目录是允许PHP访问使用fopen等功能。如果任何脚本试图访问超出open_basdir定义的路径文件,PHP将拒绝打开。值得注意的不能使用一个符号链接作为一种变通方法。 ;LimitthePHPprocessfromaccessfileoutsid;ofspecifdesigndirectorisuchas/var/www/html/open_basedir="/var/www/html/";------------------------------------;Multipldirexampl;open_basedir="/home/httpd/vhost/cyberciti.biz/html/:/home/httpd/vhost/nixcraft.com/html/:/home/httpd/vhost/theos.in/html/";------------------------------------9.限制文件/目录访问 进行适当的平安设置:确保Apach作为非root用户运行,比方www-data或www对于文件和目录在基于/var/www/下同样属于非root用户。想要更改所有者,执行以下命令: chown-Rapache:apach/var/www/10.编译维护ApachPHP和MySQL配置文件 使用charrt命令编译维护配置文件 chattr+i/etc/php.inichattr+i/etc/php.d/*chattr+i/etc/my.inichattr+i/etc/httpd/conf/httpd.confchattr+i/etc/ 使用charrt命令可以编译维护PHP文件或者是文件中的/var/www/html目录: chattr+i/var/www/html/file1.phpchattr+i/var/www/html/
2023年08月04日
12 阅读
0 评论
0 点赞
2023-08-04
我们什么时候应该使用异常?
我们什么时候应该使用异常?PHP应该什么时候使用 Exception ? 它的性能如何?这个问题也算是一个久经争论的经典问题了. 我谈谈我的个人看法.异常与之对应的错误码(或者状态码), 到底各自有什么优点, 缺点, 我们应该怎么使用呢?错误码首先来说, 异常机制是在错误码机制之后才出现的, 那么根据进化论, 异常自然是避免了错误码机制的一些不足. 这些不足包括.错误信息不丰富函数, 只能有一个返回值(当然, Lua可以返回多个, 但其实也相当于在PHP中返回一个数组), 我们见过最多的函数说明就是: 成功时候返回*, 错误的时候返回FALSE, 然而一个函数出错我原因可能有多种, 出错的种类更有多种. 一个简单的FALSE, 并不能把具体的错误信息告诉调用者.于是, 我们也就见过一些, 这样的函数说明: 如果返回值大于0, 则表示成功的状态码, 如果返回值小于0, 则表示出错的状态码.然而, 这个要求函数是返回整形(或者数字), 对于一些其他函数, 我们并不能通过0, >0, <0来判别, 并且, 即使通过这样的方式, 我们还需要用返回的错误码和一些预定义宏(或者调用类似strerror())来获取具体的, 可读的错误信息. 于是, 就有一些函数使用全局的错误码, 和错误信息, 来保存具体的错误信息, 这个时候我们就看到这样的函数描述: 成功返回*, 出错的时候返回FALSE, 错误代码保存在全局变量$errno中(至少大多数Linux库函数是这样描述的, 呵呵). Okey, 这样的方式确实可以工作, 但是, 是不是觉得, 很丑陋呢?加入错误状态码可能需要改变函数签名假设, 你编写了一个函数, 这个函数很简单, 很简单, 你认为他绝对不会出错, 于是你申明为(用C语言为例, PHP没有返回类型提示):void dummy() {}但是后来你慢慢修改了这个函数, 给了它更多的功能, 此时这个函数可能会失败了. 而你现在根本无法为这个函数, 加入错误返回码了.也许有人说PHP没有返回值类型限制一说, 但是想想PHP的构造函数, 构造函数是没有返回值的, 当发生错误的时候, 如果你不使用异常, 我想你只能选择die, 或者使用2中的方法来错误继续执行了.另外, 在一个良好的软件系统中, 返回类型其实也是约定俗成的, 当所有的使用的函数的地方, 都没有检查返回值的时候, 你还是无法为这个函数加入错误返回码.错误状态码可能会被忽略当你的一个函数, 出错了, 返回了错误状态码, 而调用方并没有检测这个返回值, 会发生什么情况呢? -_#. 令一方面, 处处检测返回状态码, 会造成代码非常的,,ugly:<?php if (!call1()) { die();} if (call2() != SUCCESS) { die();} if (call3() < 0) { $msg = error_get_last(); die($msg["message"]);}异常机制那么现在我们来看看异常机制, 如果我们采用异常机制, 上面的代码可以写作:<?phptry { call1(); call2(); call3();} catch (Exception $e) { die($e->getMessage());}更方便的, 如果你的代码只是中间层, 你的调用方会负责处理错误的话, 你甚至可以简单的写作:<?phpfunction myFunc() { call1(); call2(); call3();}而一个异常对象, 可以包含更丰富的错误信息, 比如错误信息, 错误码, 错误的行数, 文件, 甚至出错上下文, 等等, 避免的"1.错误信息不丰富"的不足.我们也可以为一个返回void类型的函数增加异常, 而不改变他的函数签名, 也就不会有上面说的"2.加入错误状态码可能需要改变函数签名". 对于PHP来说, 如果我们新加入的错误没有被捕捉, 也不用担心, 会明显的出错的. 也就不会发生上面所说的"3. 错误状态码可能会被忽略"的情况.然而, 也有一些反对使用异常的声音:性能正如文章开头提问中的: "它的性能如何?", 异常机制确实要比返回状态码的方式昂贵一些, 对于C++来说, 在异常发生的时候, 还要发生堆栈解退(对于PHP来说, 没有这个逻辑, 具体的大家可以参看我之间写的一篇文章: 深入理解PHP原理之异常机制).性能和方便, 往往是一个矛盾体, 我只能说, 你需要权衡, 如果你写的是一个小的模块, 并且它的生命期可能很短, 也不需要什么特殊的设计模式, 那我觉得你可以不用异常.而如果你在为一个庞大的软件做开发, 我想你更应该看重的, 应该是, 它的可扩展性, 可维护性.太多可能的Uncaught Exception如果, 你调用了一个可能发生异常的函数, 但是却没有捕获这个异常, okey, Fatal Error了, 所以让我们的代码看起来:<?phptry {} catch () {}....try {} catch () {}....try {} catch () {}然而, 这个是可以经过良好设计避免的, 比如我在设计Yaf的时候, 就提供了全局异常处理, 也就是类似于, 你在最最顶层, 加上了一个try catch, 所有的异常错误逻辑都加到这个里面, 你也可以很方面的把你自己的异常加进去.结论
2023年08月04日
10 阅读
0 评论
0 点赞
2023-08-04
九个PHP很有用的功能
九个PHP很有用的功能下面是九个PHP中很有用的功能,不知道你用过了吗?1. 具有任意参数数量的函数您可能已经知道 PHP 允许您使用可选参数定义函数。但是还有一种方法可以允许完全任意数量的函数参数。首先,下面是一个只有可选参数的示例:// function with 2 optional arguments function foo($arg1 = '', $arg2 = '') {echo "arg1: $arg1\n"; echo "arg2: $arg2\n";}foo('hello','world');/* prints: arg1: hello arg2: world */foo();/* prints: arg1: arg2: */现在,让我们看看如何构建一个接受任意数量参数的函数。这次我们将利用func_get_args():// yes, the argument list can be empty function foo() {// returns an array of all passed arguments $args = func_get_args(); foreach ($args as $k => $v) { echo "arg".($k+1).": $v\n"; }}foo();/ prints nothing /foo('hello');/* prints arg1: hello */foo('hello', 'world', 'again');/* prints arg1: hello arg2: world arg3: again */2. 使用 glob() 查找文件许多 PHP 函数都有很长的描述性名称。但是,可能很难说出名为glob()的函数的作用,除非您已经从其他地方熟悉该术语。把它想象成 scandir() 函数的更强大的版本。它可以让您使用模式搜索文件。// get all php files $files = glob('*.php');print_r($files);/* output looks like: Array ( [0] => phptest.php [1] => pi.php [2] => post_output.php [3] => test.php ) */您可以获取多种文件类型,如下所示:// get all php files AND txt files $files = glob('*.{php,txt}', GLOB_BRACE);print_r($files);/* output looks like: Array ( [0] => phptest.php [1] => pi.php [2] => post_output.php [3] => test.php [4] => log.txt [5] => test.txt ) */请注意,文件实际上可以使用路径返回,具体取决于您的查询:$files = glob('../images/a*.jpg');print_r($files);/* output looks like: Array ( [0] => ../images/apple.jpg [1] => ../images/art.jpg ) */如果你想获取每个文件的完整路径,你可以对返回的值调用 realpath() 函数:$files = glob('../images/a*.jpg');// applies the function to each array element $files = array_map('realpath',$files);print_r($files);/* output looks like: Array ( [0] => C:\wamp\www\images\apple.jpg [1] => C:\wamp\www\images\art.jpg ) */3. 内存使用信息通过观察脚本的内存使用情况,您可以更好地优化代码。PHP有一个垃圾收集器和一个相当复杂的内存管理器。脚本使用的内存量。可以在脚本执行期间上下移动。要获取当前的内存使用情况,我们可以使用 memory_get_usage() 函数,并且要获得在任何时候使用的最高内存量,我们可以使用 memory_get_peak_usage() 函数。echo "Initial: ".memory_get_usage()." bytes \n";/* prints Initial: 361400 bytes */// let's use up some memory for ($i = 0; $i < 100000; $i++) {$array []= md5($i);}// let's remove half of the array for ($i = 0; $i < 100000; $i++) {unset($array[$i]);}echo "Final: ".memory_get_usage()." bytes \n";/* prints Final: 885912 bytes */echo "Peak: ".memory_get_peak_usage()." bytes \n";/* prints Peak: 13687072 bytes */4. CPU 使用率信息为此,我们将使用 getrusage() 函数。请记住,这在 Windows 平台上不可用。print_r(getrusage());/* prints Array ( [ru_oublock] => 0 [ru_inblock] => 0 [ru_msgsnd] => 2 [ru_msgrcv] => 3 [ru_maxrss] => 12692 [ru_ixrss] => 764 [ru_idrss] => 3864 [ru_minflt] => 94 [ru_majflt] => 0 [ru_nsignals] => 1 [ru_nvcsw] => 67 [ru_nivcsw] => 4 [ru_nswap] => 0 [ru_utime.tv_usec] => 0 [ru_utime.tv_sec] => 0 [ru_stime.tv_usec] => 6269 [ru_stime.tv_sec] => 0 ) */除非您已经拥有系统管理背景,否则这可能看起来有点神秘。以下是每个值的解释(您无需记住这些值):ru_oublock:块输出操作ru_inblock:块输入操作ru_msgsnd:发送的消息ru_msgrcv:收到的消息ru_maxrss:最大驻留集大小ru_ixrss:整体共享内存大小ru_idrss:整数非共享数据大小ru_minflt:页面回收ru_majflt:页面错误ru_nsignals:接收到的信号ru_nvcsw:自愿上下文切换ru_nivcsw:非自愿上下文切换ru_nswap:掉期ru_utime.tv_usec:用户使用时间(微秒)ru_utime.tv_sec:用户使用时间(秒)ru_stime.tv_usec:系统使用时间(微秒)ru_stime.tv_sec:系统使用时间(秒)要查看脚本消耗了多少 CPU 功率,我们需要查看“用户时间”和“系统时间”值。默认情况下,秒和微秒部分是单独提供的。您可以将微秒值除以 1 万,然后将其添加到秒值中,以十进制数的形式获得总秒数。让我们看一个例子:// sleep for 3 seconds (non-busy) sleep(3);$data = getrusage();echo "User time: ".($data['ru_utime.tv_sec'] + $data['ru_utime.tv_usec'] / 1000000);echo "System time: ".($data['ru_stime.tv_sec'] + $data['ru_stime.tv_usec'] / 1000000);/* prints User time: 0.011552 System time: 0 */尽管脚本运行大约需要 3 秒,但 CPU 使用率非常低。因为在睡眠操作期间,脚本实际上并不消耗 CPU 资源。还有许多其他任务可能需要实时时间,但可能不会占用 CPU 时间,例如等待磁盘操作。如您所见,CPU 使用率和运行时的实际长度并不总是相同的。这是另一个例子:// loop 10 million times (busy) for($i=0;$i<10000000;$i++) {}$data = getrusage();echo "User time: ".($data['ru_utime.tv_sec'] + $data['ru_utime.tv_usec'] / 1000000);echo "System time: ".($data['ru_stime.tv_sec'] + $data['ru_stime.tv_usec'] / 1000000);/* prints User time: 1.424592 System time: 0.004204 */这花费了大约 1.4 秒的 CPU 时间,几乎所有时间都是用户时间,因为没有系统调用。系统时间是 CPU 代表程序对内核执行系统调用所花费的时间。下面是一个示例:$start = microtime(true);// keep calling microtime for about 3 seconds while(microtime(true) - $start < 3) {}$data = getrusage();echo "User time: ".($data['ru_utime.tv_sec'] + $data['ru_utime.tv_usec'] / 1000000);echo "System time: ".($data['ru_stime.tv_sec'] + $data['ru_stime.tv_usec'] / 1000000);/* prints User time: 1.088171 System time: 1.675315 */现在我们有相当多的系统时间使用。这是因为脚本多次调用 microtime() 函数,该函数通过操作系统执行请求以获取时间。此外,您可能会注意到这些数字加起来不超过 3 秒。这是因为服务器上可能还有其他进程,并且脚本在 100 秒的整个持续时间内没有使用 3% CPU。5. 魔术常数PHP 提供了有用的魔术常量,用于获取当前行号 ()、文件路径 ()、目录路径 ()、函数名称 ()、类名 ()、方法名 (__METHOD__) 和命名空间 ()。__LINE____FILE____DIR____FUNCTION____CLASS____NAMESPACE__我们不会在本文中逐一介绍其中的每一个,但我会向您展示一些用例。当包含其他脚本时,最好使用常量(或者,从 PHP 5.3 开始):__FILE____DIR__// this is relative to the loaded script's path // it may cause problems when running scripts from different directories require_once('config/database.php');// this is always relative to this file's path // no matter where it was included from require_once(dirname(__FILE__) . '/config/database.php');使用使调试更容易。您可以跟踪行号:__LINE__// some code // ... my_debug("some debug message", __LINE__);/* prints Line 4: some debug message */// some more code // ... my_debug("another debug message", __LINE__);/* prints Line 11: another debug message */function my_debug($msg, $line) {echo "Line $line: $msg\n";}6. 生成唯一 ID在某些情况下,可能需要生成唯一的字符串。我见过很多人为此使用该功能,即使它并不完全是为此目的:md5()// generate unique string echo md5(time() . mt_rand(1,1000000));实际上有一个名为uniqid()的PHP函数用于此目的。// generate unique string echo uniqid();/* prints 4bd67c947233e */// generate another unique string echo uniqid();/* prints 4bd67c9472340 */您可能会注意到,即使字符串是唯一的,它们对于前几个字符看起来也很相似。这是因为生成的字符串与服务器时间相关。这实际上有一个很好的副作用,因为每个新生成的 id 都按字母顺序稍后出现,因此可以对它们进行排序。为了减少获得重复项的机会,您可以传递前缀或第二个参数来增加熵:// with prefix echo uniqid('foo_');/* prints foo_4bd67d6cd8b8f */// with more entropy echo uniqid('',true);/* prints 4bd67d6cd8b926.12135106 */// both echo uniqid('bar_',true);/* prints bar_4bd67da367b650.43684647 */此函数将生成比 更短的字符串,这也将为您节省一些空间。md5()7. 序列化您是否曾经需要在数据库或文本文件中存储复杂变量?您不必想出一个花哨的解决方案来将数组或对象转换为格式化字符串,因为 PHP 已经具有用于此目的的函数。序列化变量有两种常用方法。下面是一个使用 serialize() 和 unserialize() 的示例:// a complex array $myvar = array('hello', 42, array(1,'two'), 'apple');// convert to a string $string = serialize($myvar);echo $string;/* prints a:4:{i:0;s:5:"hello";i:1;i:42;i:2;a:2:{i:0;i:1;i:1;s:3:"two";}i:3;s:5:"apple";} */// you can reproduce the original variable $newvar = unserialize($string);print_r($newvar);/* prints Array ( [0] => hello [1] => 42 [2] => Array ( [0] => 1 [1] => two ) [3] => apple ) */这是本机 PHP 序列化方法。但是,由于JSON近年来变得如此流行,他们决定在PHP 5.2中添加对它的支持。现在你也可以使用 和 函数:json_encode()json_decode()// a complex array $myvar = array('hello', 42, array(1,'two'), 'apple');// convert to a string $string = json_encode($myvar);echo $string;/* prints ["hello",42,[1,"two"],"apple"] */// you can reproduce the original variable $newvar = json_decode($string);print_r($newvar);/* prints Array ( [0] => hello [1] => 42 [2] => Array ( [0] => 1 [1] => two ) [3] => apple ) */它更紧凑,最重要的是,与javascript和许多其他语言兼容。但是,对于复杂对象,某些信息可能会丢失。8. 压缩字符串在谈论压缩时,我们通常会考虑文件,例如 ZIP 存档。可以在PHP中压缩长字符串,而不涉及任何存档文件。在下面的示例中,我们将使用 gzcompress() 和 gzuncompress() 函数:$string ="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc ut elit id mi ultricies adipiscing. Nulla facilisi. Praesent pulvinar, sapien vel feugiat vestibulum, nulla dui pretium orci, non ultricies elit lacus quis ante. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam pretium ullamcorper urna quis iaculis. Etiam ac massa sed turpis tempor luctus. Curabitur sed nibh eu elit mollis congue. Praesent ipsum diam, consectetur vitae ornare a, aliquam a nunc. In id magna pellentesque tellus posuere adipiscing. Sed non mi metus, at lacinia augue. Sed magna nisi, ornare in mollis in, mollis sed nunc. Etiam at justo in leo congue mollis. Nullam in neque eget metus hendrerit scelerisque eu non enim. Ut malesuada lacus eu nulla bibendum id euismod urna sodales. ";$compressed = gzcompress($string);echo "Original size: ". strlen($string)."\n";/* prints Original size: 800 */echo "Compressed size: ". strlen($compressed)."\n";/* prints Compressed size: 418 */// getting it back $original = gzuncompress($compressed);我们能够实现近 50% 的尺寸减小。此外,函数 gzencode() 和 gzdecode() 通过使用不同的压缩算法获得了类似的结果。9. 寄存器关断功能有一个名为 register_shutdown_function() 的函数,它可以让您在脚本完成运行之前立即执行一些代码。假设您希望在脚本执行结束时捕获一些基准统计信息,例如运行所需的时间:// capture the start time $start_time = microtime(true);// do some stuff // ... // display how long the script took echo "execution took: ". (microtime(true) - $start_time). " seconds.";乍一看,这似乎微不足道。您只需将代码添加到脚本的最底部,它就会在完成之前运行。但是,如果您调用 exit() 函数,该代码将永远不会运行。此外,如果出现致命错误,或者脚本被用户终止(通过按浏览器中的“停止”按钮),它可能不会再次运行。使用 register_shutdown_function() 时,无论脚本停止运行的原因,代码都将执行:$start_time = microtime(true);register_shutdown_function('my_shutdown');// do some stuff // ... function my_shutdown() {global $start_time; echo "execution took: ". (microtime(true) - $start_time). " seconds.";}
2023年08月04日
17 阅读
0 评论
0 点赞
1
...
102
103
104
...
112