首页
关于
Search
1
给你10个市场数据调研报告的免费下载网站!以后竞品数据就从这里找!
185 阅读
2
php接口优化 使用curl_multi_init批量请求
144 阅读
3
《从菜鸟到大师之路 ElasticSearch 篇》
107 阅读
4
2024年备考系统架构设计师
104 阅读
5
PHP 文件I/O
92 阅读
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
累计撰写
786
篇文章
累计收到
33
条评论
首页
栏目
php
thinkphp
laravel
工具
开源
mysql
数据结构
总结
思维逻辑
令人感动的创富故事
读书笔记
前端
vue
js
css
书籍
开源之旅
架构
消息队列
docker
教程
代码片段
副业
redis
服务器
nginx
linux
科普
java
c
ElasticSearch
测试
php进阶
php基础
页面
关于
搜索到
560
篇与
的结果
2023-08-09
浅析 PHP 中的异常与错误
浅析 PHP 中的异常与错误异常与错误异常是指程序运行中不符合预期情况以及与正常流程不同的状况。错误则属于自身问题,是一种非法语法或者环境问题导致的、让编译器无法通过检查设置无法运行的情况。由于php最开始是没有异常处理,后来为了进军企业级开发,模仿java等语言,推出了异常。导致php中遇到任何自身错误都会触发一个错误,而不是抛出一个异常(某些情况下,会同时抛出错误和异常)。PHP一旦遇到非正常代码,大多数情况下,都是直接抛出错误,而不是异常。php只有在你throw 一个异常后,才能用try...catch来捕获异常(一般情况下如此,也有部分异常可以自动捕获)。在php中通常会在以下场景中使用异常:对程序的悲观预测:如果认为自己的代码无法一一处理各种可预见的情况、不可预见的情况。程序的需要和对业务的关注 : 如果对数据的一致性要求很高时,可以用try...catch把异常造成的逻辑中断破坏将到最小,并且经过补救处理后,不影响业务逻辑的完整性。语言级别的健壮性要求 : 通过精确控制运行时的流程,在程序中断时,有预见的用try...catch缩小可能出错的范围,及时捕获异常并做出相应的补救。怎样看待php的异常历史原因导致php的异常处理是不足的,绝大多数情况下,无法自动抛出异常,必须使用if...else先进行判断,再手动抛出异常。手动抛出异常的意义不是很大,因为这意味着在代码里已经充分的预期到错误的出现。同时这种方式还会让你在复杂的逻辑判断和处理中晕头转向。导致失去异常真正的优点。那么有更好的异常抛出方法吗?有,那就是结合使用错误php中的错误错误就是会使脚本运行不正常的情况。在php中主要的错误等级如下:deprecated: 最低级别的错误,表示"不推荐, 不建议"。例如在php 5中使用了ereg系列的正则函数就会出现。这类错误一般由于使用了不推荐的、过时的函数或语法造成。不影响程序正常运行,但建议修正。notice: 一般指语法中存在不恰当的地方。如使用变量但是未定义就会报此错误。不影响程序正常流程。warning: 较高级别的错误,在语法中出现很不恰当的情况才会出现此错误,比如函数参数不匹配。会导致得不到预期的结果,需要修改代码。fetal error: 致命错误,直接导致程序终止运行。这类错误必须修改。prase error: 语法解析错误,上面几种都属于运行时错误,此错误在运行前就会抛出。在php中,总共有16错误级别,但是主要的就是上面几种。error.php$data = '2012-12-20';if (ereg("([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})", $data, $regs)) {echo "$reg[3].$regs[2].$regs[1]";} else {echo "Invalid data format: $data";}$a = array('o' => 2, 4, 6, 8);echo $a[o];$result = array_sum($a, 3);echo func();echo '致命错误后,还会执行吗?';//echo '最高级别错误', $55;上面代码执行后,会有四个错误级别,如果你无法完全看到的话,你需要去修改你的ini配置文件中错误显示级别为 E_ALL自定义错误处理程序可以使用 set_error_handler() 函数来托管错误处理程序,可自行定制错误的处理流程。如果要取消托管的话,可以在同一个页面中使用restore_error_handler()来取消托管。如果想要自己抛出一个错误的话,可以使用trigger_error()函数。<?php//自定义错误处理程序function customError($errno, $errstr, $errfile, $errline){echo "<b>错误代码:</b>[{$errno}] {$errstr}", PHP_EOL; echo "错误所在代码行:{$errline} 文件{$errfile}", PHP_EOL; echo "PHP版本", PHP_VERSION, "(", PHP_OS, ")", PHP_EOL;}set_error_handler("customError", E_ALL | E_STRICT);$a = array('o' => 2, 4, 6, 8);echo $a[o];执行上面的代码,可以看到错误信息是由我们自定义的处理程序输出的,完全绕开了系统的处理程序。如果错误发生在自定义处理程序前,则不会调用我们自定义的错误处理程序,所以应当先定义错误处理程序。当然不是所有的错误级别都可以用set_error_handler来托管,如E_ERROR、E_PARSE、E_CODE_WARNING、E_COMPILE_ERROR、E_COMPILE_WARNING以及E_STRICT中的部分。这些错误信息会以原始的方式来显示或者不现实。PHP把许多异常看作是错误,所以这些"异常"同样可以使用set_error_handler来接管:function customError($errno, $errstr, $errfile, $errline){//自定义错误处理是,手动抛出异常 throw new Exception($errstr);}set_error_handler('customError', E_ALL | E_STRICT);try {$a = 5/0;} catch (Exception $e) {echo '错误信息:', $e->getMessage();}当然这种处理方式也有自己的优缺点:缺点: 必须依靠程序员自己来掌控对异常的处理,对于异常的高发区、敏感区,如果程序员处理不好,就会导致业务数据不一致的问题。优点: 可以获得程序运行时的上下文信息,以进行针对性的补救。fetal error这样的错误无法捕获,也无法在发生后恢复流程处理,但是可以使用register_shutdown_function()函数在程序终止或die时触发一个函数,给程序带来一个短暂的回光返照。在php4时,不支持析构函数,也常用于模拟实现析构函数。class Shutdown{public function stop() { if (error_get_laster()) { print_r(error_get_laster()); } die('Stop.'); }}register_shutdown_function(array(new Shutdown(), 'stop'));$a = new a(); //致命错误,导致失败echo '必须终止';Parse error级别的错误,除了修改ini文件,将错误信息写到日志中,什么也做不了。小结php中错误和异常是两个不同的概念,这种设计根本上导致了php的异常和错误与其它语言相异。java中,异常时错误唯一的报告方式。说到底,两者的区别就是对异常的认识不同产生的。php异常绝大部分是通过某种方式手动抛出,才能捕获到。是一种半自动化的异常处理机制。无论是错误还是异常,都可以使用handler接管系统已有的处理机制。
2023年08月09日
12 阅读
0 评论
0 点赞
2023-08-09
php-fpm解读-进程管理的三种模式
php-fpm解读-进程管理的三种模式php-fpm进程管理一共有三种模式:ondemand、static、dynamic,我们可以在同一个fpm的master配置三种模式,看下图1。php-fpm的工作模式和nginx类似,都是一个master,多个worker模型。每个worker都在accept本pool内的监听套接字(linux已不存在惊群现象)。图1ondemand在php-fpm启动的时候,不会给这个pool启动任何一个worker,是按需启动,当有连接过来才会启动。配置文件(我的配置文件地址为:/usr/local/php/etc/php-fpm.conf)当前pool的名字为test原理ondemand原理图从上图可以看出,新建worker的触发条件是连接的到来,而不是实际的请求(例如,只进行连接比如telnet,不发请求数据也会新建worker)worker的数量受限于pm.max_children配置,同时受限全局配置process.max(准确的说,三种模式都受限于全局配置)3.1秒定时器作用找到空闲worker,如果空闲时间超过pm.process_idle_timeout大小,关闭。这个机制可能会关闭所有的worker。配置项要求pm.max_children> 0pm.process_idle_timeout> 0,如果不设置,默认10s优缺点优点:按流量需求创建,不浪费系统资源(在硬件如此便宜的时代,这个优点略显鸡肋)缺点:由于php-fpm是短连接的,所以每次请求都会先建立连接,建立连接的过程必然会触发上图的执行步骤,所以,在大流量的系统上master进程会变得繁忙,占用系统cpu资源,不适合大流量环境的部署dynamic在php-fpm启动时,会初始启动一些worker,在运行过程中动态调整worker数量,worker的数量受限于pm.max_children配置,同时受限全局配置process.max当前pool的名字为test原理dynamic原理图1秒定时器作用检查空闲worker数量,按照一定策略动态调整worker数量,增加或减少。增加时,worker最大数量<=max_children· <=全局process.max;减少时,只有idle >pm.max_spare_servers时才会关闭一个空闲worker。idle > pm.max_spare_servers,关闭启动时间最长的一个worker,结束本次处理idle >= pm.max_children,打印WARNING日志,结束本次处理idle < pm.max_children,计算一个num值,然后启动num个worker,结束本次处理配置项要求pm.min_spare_servers/pm.max_spare_servers有效范围(0,pm.max_children]pm.max_children> 0pm.min_spare_servers<=pm.max_spare_serverspm.start_servers有效范围[pm.min_spare_servers,pm.max_spare_servers]如果没有配置,默认pm.min_spare_servers + (pm.max_spare_servers - pm.min_spare_servers) / 2优缺点优点:动态扩容,不浪费系统资源,master进程设置的1秒定时器对系统的影响忽略不计;缺点:如果所有worker都在工作,新的请求到来只能等待master在1秒定时器内再新建一个worker,这时可能最长等待1s;staticphp-fpm启动采用固定大小数量的worker,在运行期间也不会扩容,虽然也有1秒的定时器,仅限于统计一些状态信息,例如空闲worker个数,活动worker个数,网络连接队列长度等信息。当前pool的名字为test原理配置项要求1、pm.max_children> 0 必须配置,且只有这一个参数生效优缺点如果配置成static,只需要考虑max_children的数量,数量取决于cpu的个数和应用的响应时间,我司配置的是50。我司不考虑动态的增加减少那么十几个或者几十个worker,我们的内存没有紧张到这个程度,所以,我们一步到位,把worker数配置到支持最大流量,(哈哈,50也是随便定的,足矣足矣呢)最后我们再介绍下worker的工作流程此图出自大表哥@要要fastcgi与php-fpm的关系一句话解读:fastcgi只是通信应用协议,php-fpm就是实现了fastcig协议,并嵌入了一个 PHP 解释器。完
2023年08月09日
13 阅读
0 评论
0 点赞
2023-08-09
swoole流程结构图
swoole流程结构图
2023年08月09日
14 阅读
0 评论
0 点赞
2023-08-09
启用php-fpm状态详解
启用php-fpm状态详解php-fpm和nginx一样内建了一个状态页,对于想了解php-fpm的状态以及监控php-fpm非常有帮助。为了后续的zabbix监控,我们需要先了解php-fpm状态页是怎么回事。启用php-fpm状态功能12cat /usr/local/php-5.5.10/etc/php-fpm.conf | grep status_pathpm.status_path = /status默认情况下为/status,当然也可以改成其他的,例如/ttlsa_status等等。nginx配置在默认主机里面加上location或者你希望能访问到的主机里面。12345678910server {listen *:80 default_server; server_name _; location ~ ^/(status|ping)$ { include fastcgi_params; fastcgi_pass 127.0.0.1:9000; fastcgi_param SCRIPT_FILENAME $fastcgi_script_name; }}重启nginx/php-fpm请依照你的环境重启你的nginx和php-fpm12service nginx restartservice php-fpm restart打开status页面123456789101112131415curl http://www.ttlsa.com/statuspool: wwwprocess manager: dynamicstart time: 14/May/2014:22:40:15 +0800start since: 58508accepted conn: 33listen queue: 0max listen queue: 8listen queue len: 0idle processes: 2active processes: 1total processes: 3max active processes: 5max children reached: 0slow requests: 2091php-fpm status详解pool – fpm池子名称,大多数为wwwprocess manager – 进程管理方式,值:static, dynamic or ondemand. dynamicstart time – 启动日期,如果reload了php-fpm,时间会更新start since – 运行时长accepted conn – 当前池子接受的请求数listen queue – 请求等待队列,如果这个值不为0,那么要增加FPM的进程数量max listen queue – 请求等待队列最高的数量listen queue len – socket等待队列长度idle processes – 空闲进程数量active processes – 活跃进程数量total processes – 总进程数量max active processes – 最大的活跃进程数量(FPM启动开始算)max children reached - 大道进程最大数量限制的次数,如果这个数量不为0,那说明你的最大进程数量太小了,请改大一点。slow requests – 启用了php-fpm slow-log,缓慢请求的数量php-fpm其他参数php-fpm状态页比较个性化的一个地方是它可以带参数,可以带参数json、xml、html并且前面三个参数可以分别和full做一个组合。6.1 json12curl http://127.0.0.1/status?json{"pool":"www","process manager":"dynamic","start time":1400078415,"start since":59624,"accepted conn":27,"listen queue":0,"max listen queue":8,"listen queue len":0,"idle processes":2,"active processes":1,"total processes":3,"max active processes":5,"max children reached":0,"slow requests":2145}6.2 xml1234567891011121314151617curl http://127.0.0.1/status?xml<?xml version="1.0" ?>wwwdynamic140007841559640360802135021456.3 html12345678910111213141516171819202122curl http://127.0.0.1/status?html<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">PHP-FPM Status Page poolwww process managerdynamic start time14/May/2014:22:40:15 +0800 start since59662 accepted conn8 listen queue0 max listen queue8 listen queue len0 idle processes2 active processes1 total processes3 max active processes5 max children reached0 slow requests2147 6.4 full12345678910111213141516171819202122232425262728293031curl http://127.0.0.1/status?fullpool: wwwprocess manager: dynamicstart time: 14/May/2014:22:40:15 +0800start since: 59695accepted conn: 1listen queue: 0max listen queue: 8listen queue len: 0idle processes: 2active processes: 1total processes: 3max active processes: 5max children reached: 0slow requests: 2148pid: 29050state: Idlestart time: 15/May/2014:15:09:32 +0800start since: 338requests: 62request duration: 1025585request method: GETrequest URI: /index.phpcontent length: 0user: -script: /data/site/www.ttlsa.com/index.phplast request cpu: 45.83last request memory: 24903680.....省略几个PID....6.5 full详解pid – 进程PID,可以单独kill这个进程. You can use this PID to kill a long running process.state – 当前进程的状态 (Idle, Running, …)start time – 进程启动的日期start since – 当前进程运行时长requests – 当前进程处理了多少个请求request duration – 请求时长(微妙)request method – 请求方法 (GET, POST, …)request URI – 请求URIcontent length – 请求内容长度 (仅用于 POST)user – 用户 (PHP_AUTH_USER) (or ‘-’ 如果没设置)script – PHP脚本 (or ‘-’ if not set)last request cpu – 最后一个请求CPU使用率。last request memorythe - 上一个请求使用的内存完成php-fpm状态页非常使用,使用zabbix或者nagios监控可以考虑使用xml或者默认方式。用web的话,推荐使用html,表格会比较清晰。
2023年08月09日
5 阅读
0 评论
0 点赞
2023-08-09
你所不知道 ❌ PHP 自动加载
你所不知道 ❌ PHP 自动加载前言很多的小伙伴在,学习 PHP 的时候最早面对的问题之一就是 require 、 include 和 require_once 、include_once 的相爱相杀。在了解了它们相爱相杀的故事后,往往就开始使用起了框架。框架固然是干活的好工具,但是你知道你平时 new 一个新类的时候,发生了什么吗?有想过为什么我们 遵循规范 就会自动的帮我们做好一切的加载吗? 让我们一切来探索发现其中的奥秘。时间线蒸汽时代在 PHP 代码的顶部你是不是经常看到这样的代码。require 'lionis.php';require 'is.php';require 'cool.php';如果只是引入几个 PHP 脚本,那还可以接受。那引入成千上万个脚本的时候,爆炸是在所难免的。如果对一个脚本改了个名字,还需要对引入改脚本的每个脚本改名,能不爆炸吗?连打出这段话都怎么绕。电气时代在 PHP 电气时代,开始出现了 __autoload 和 spl_autoload_register 函数注册自定义的自动加载策略。通俗的来说,__autoload 和 spl_autoload_register 是一个 杀手组织,他们会去雇佣 各国杀手 (函数)。当我们想搞定某个人的时候(new),只需要提供名字(类名),剩下的 杀手 会帮我们搞定的。__autoloadPHP 5 开始提供这个函数 传送门。当你使用的 类 找不到的时候,它把类名当成参数扔进这个函数。<?php// Lionis.phpclass Lionis {public function __construct() { echo '欧耶耶, 我就是 Lionis'; }}<?php// index.phpfunction __autoload($classname) {$filename = './' . $classname . '.php'; require_once $filename;}$lionis = new Lionis();输出欧耶耶, 我就是 Lionisspl_autoload_register如果我们 项目 很大很老又或者你是一个 爱折腾 的少先队员,需要引入的东西有不一样的规范,这时候如果都放在 __autoload 函数里,这个函数马上就会膨胀的。而且 __autoload 是全局唯一的,如果被人占用了,可能会导致错误。(欲使一个人灭亡,必将先使其膨胀。)PHP 5.1.2 开始提供这个函数 传送门,注册给定的函数作为 __autoload 的实现。所以,我们看一些框架或插件在自己使用的时候,为了兼容可能会出现 function_exists(spl_autoload_register)。<?phpfunction lionisIsCoolFind($classname) {require './' . $classname . '.php';}// 函数spl_autoload_register('lionisIsCoolFind');// 匿名函数spl_autoload_register(function($require) {require './' . $classname . '.php';});// 类中的函数spl_autoload_register(array('Lionis', 'loadClass'));欧耶,这下我们可以写很多不同的自动加载函数了。信息时代师傅小心,前面有妖气! 。如果我们每个人都自己实现一套自动加载的方法,每个PHP 组件和 框架都使用独特的自动加载器,而且每个框架使用不同的逻辑加载PHP类、接口和性状。那当我们使用一些第三方框架的时候,还需要去弄清楚引导文件中的 自动加载器,那样是有多和 时间 过不去呢。 PHP-FIG 认识到了这个问题了,推荐使用 PSR-4 规范,来促进组件之间的 互操作性,这样我们就可以使用一个自动加载器了。PSR-4 规范利用命名空间的前缀和文件系统中的目录对应起来。映射关系为namespace => filePath\Lionis\Cool => cool带有命名空间的类<?php// 该文件为 cool/Real.phpnamespace \Lionis\Cool;class Real {}创建一个对象<?php// 该文件为 index.php$lionis = new \Lionis\Cool\Real;这个时候,按照 PSR-4 的规范,自动加载器应该去加载 cool/ 目录下的 Real.php。不对!那这样不是还要自己去实现 自动加载器 嘛,不然怎么 无中生有 出现 自动加载器 呢?难道官方 内置 了?你 out 了吧,我们可以使用依赖管理器 composer 来生成 PSR-4 自动加载器。你可能会疑问,那我的旧项目没有遵循 PSR-4 规范怎么办?嘿嘿,让我们来探索发现一下 composer 是怎么解决这个问题的吧。Composer哦吼吼,我们这次的重点在与探究自动加载,所以 composer 的安装和使用等,就不去讨论了。composer 自动加载设置了 4种 加载方式:PSR-0PSR-4classmapfilesPSR-0要求命名空间和目录层层对应,且可以使用 _ 作为路径分隔符,但是这会导致目录结果变得过深。在 composer 执行 install 等操作时,composer 会把文件中的配置存储在 vendor/composer/autoload_psr0.php文件中的返回数组中。例如:定义了Very\Good=>vendor\Lionis\IsReal\Cool,在调用 use Very\Good\Love\SomeClass,PSR-0 加载的实际目录为 vendor/Lionis/IsReal/Cool/Very/Good/Love/SomeClass.php。对吧,这简直深得吓人,所以 PSR-0 被官方废除了。但是一些主流的框架已经实现了 PSR-0,为了向下兼容还是要实现 PSR-0。composer.json配置:"autoload": {"psr-0": { "Very\\Good": "vendor\Lionis\IsReal\Cool" }}PSR-4PSR-4 是现在比较推荐的方法,用于替代 PSR-0。与 PSR-0 不同的是,取消掉了 _ 作为分隔符和目录结构。在 composer 执行 install 等操作时,composer 会把文件中的配置存储在 vendor/composer/autoload_psr4.php文件中的返回数组中。例如:定义了Very\Good=>vendor\Lionis\IsReal\Cool,在调用 use Very\Good\Love\SomeClass,PSR-4 加载的实际目录为 vendor/Lionis/IsReal/Cool/Love/SomeClass.php。composer.json配置:"autoload": {"psr-4": { "Very\\Good": "vendor\Lionis\IsReal\Cool" }}classmapclassmap 通过配置指定的目录和文件,在 composer 执行 install 等操作时,composer 会去扫描对应的目录下以.php结尾的文件中的 class,并存储在 vendor/composer/autoload_classmap.php文件中的返回数组中。composer.json配置:"autoload": {"classmap": [ "Lionis/", "Xiaoer/" ]}如果 Lionis 下有一个叫 VeryCool的文件,那么在vendor/composer/autoload_classmap.php 中会生成。<?php// autoload_classmap.php @generated by Composer$vendorDir = dirname(dirname(__FILE__));$baseDir = dirname($vendorDir);return array('VeryCool' => $baseDir . '/Lionis/VeryCool.php', // 其他的映射);filesfiles 就是直接简单粗暴的加载文件。在 composer 执行 install 等操作时,composer 会把文件中的配置存储在 vendor/composer/autoload_static.php文件中的生成一个 $files 数组。composer.json 配置:"autoload": {"files": ["Lionis/Very/Cool.php"]}小结composer 通过使用 composer.json,用 json 的格式来指定我们需要自动加载的规则。我们只要在入口文件引入 vendor/autoload.php 就能很方便的便能使用 自动加载。如果你对 composer 实现 自动加载 的原理感兴趣,可以顺着 vendor 中的 autoload.php 去看看源码。总结从 石器时代 到 信息时代,PHP 经历了很多试验和改变后正在变得越来越好。当然,许多优秀的框架让我们开发速度更快,需要理解的一些知识点也随之被隐藏起来,让我们更加专注于实现逻辑。但是,我们有的时候还是要尝试的去理解他们工作的原理,来提升我们自己。像我老师说过的,所不定一下子踩到狗屎运了呢。更多细说 PHP 类库自动加载
2023年08月09日
13 阅读
0 评论
0 点赞
1
...
63
64
65
...
112