php语言 百文网手机站

PHP中的Division by zero报错处理技巧

时间:2023-02-23 09:00:58 蔼媚 php语言 我要投稿
  • 相关推荐

PHP中的Division by zero报错处理技巧

  ecshop部分模板使用时,会出现“Warning: Division by zero inxxxxxlib_goods.php”错误,那么怎么处理呢?来看看小编的分享吧!

  错误提示

  在打开某些产品分类或者某些产品页面的时候,特定语言才报错。

  错误是:Division by zero in xxx

  错误原因

  这个错误的原因,就是运算的过程中,被除数是0。上过小学的都知道“0是不可以作为被除数的”。

  解决思路

  1:判断值为0的时候跳过运算;

  2:如果非要赋值给一个变量,可以做判断后赋固定值或者输出false,后面代码判断如果变量是true才使用它进行下一步代码的实现。

  DEBUGING

  解决问题之前,先来个两个小知识点:

  1、在opencart中,vqmod的优先等级是最高的;

  2、哪里报错不一定错误就在哪里,但是首先看的还是报错的地方。

  从上图中,我们找到了vqcache下对应的文件对应行数,发现如下代码:

  //Cosyonecustomcodestarts

  if((float)$result['special']){

  $sales_percantage=((($this->tax->calculate($result['price'],$result['tax_class_id'],$this->config->get('config_tax')))-($this->tax->calculate($result['special'],$result['tax_class_id'],$this->config->get('config_tax'))))/(($this->tax->calculate($result['price'],$result['tax_class_id'],$this->config->get('config_tax')))/100));

  }else{

  $sales_percantage=false;

  }

  从这个代码可以看出有若干个参数,我们留意“/”后面的被除数就好,这里被除数有两个地方,其中第二个是正整数100,可以排除。那么问题就在下面这段代码中:

  $this->tax->calculate($result['price'],$result['tax_class_id'],$this->config->get('config_tax'))

  我们从上面这个方法里看到三个参数,分别用print_r打印了下参数的值,结果发现第二个参数“$result['tax_class_id']”是“000000”。很显然,如果这个是0,我们就要让:

  $sales_percantage = false ;

  所以我们这里的代码要修改为:

  //Cosyonecustomcodestarts

  if((float)$result['special']&&$result['tax_class_id']){

  $sales_percantage=((($this->tax->calculate($result['price'],$result['tax_class_id'],$this->config->get('config_tax')))-($this->tax->calculate($result['special'],$result['tax_class_id'],$this->config->get('config_tax'))))/(($this->tax->calculate($result['price'],$result['tax_class_id'],$this->config->get('config_tax')))/100));

  }else{

  $sales_percantage=false;

  }

  也就是,加多一个判断依据,必须满足两个值都存在的前提下,才进行如下运算,否则是false。

  修改代码,保存代码,上传文件,刷新页面,警告提示语消失,over。

  但是,毕竟我们改的是缓存文件,真正要修改好代码,我们还是要把代码写到核心文件或者插件的文件里。

  修改源

  首先,我们从三个地方查找,分别是:

  核心文件:/catalog/controller/product/category.php;

  vqmod:/vqmod/xml/*.xml;

  ocmod:上传插件的ocmod.xml文件备份,或者数据库查看:oc_modification表xml字段;

  虽然vqmod的优先等级高于ocmod,但是其实先从比较方便的地方找起也是可以的。有个方法可以排除是否ocmod。如果是ocmod插件的,缓存文件名必定有“system_storage_modification”。

  但是也由于vqmod优先等级最高,所以被ocmod缓存的文件的文件名也可能有这个字样,所以排查的顺序如上所述。【如果报错指向“/system/storage/modification/”则一定是ocmod插件引起】

  核心文件的话,编辑器打开ctrl+F进行关键字查找修改。

  如果是vqmod的xml,要么排除法排除不可能是的文件,然后从可能是的文件里查找。如果文件太多就用notepad++等编辑器或者IDE工具,可以进行目录搜索,从中找到文件。

  如果是ocmod,则用MYSQL工具进行字段like %...% 搜索,或者用SQL语句:

  SELECT*FROM`oc_modification`WHERE`xml`like"%关键代码%"

  由于这里存的数据被转义过,所以搜索的内容不要带有换行之类的,抓取比较有特点的代码进行查找和修改。修改的时候注意转义的影响哈。当然现在很多MYSQL管理工具这一点做的还是挺好的。建议最好修改插件的ocmod.xml文件,然后重新上传一次。平时插件装了后自己留备份还是有必要的。如果没文件就导出备份再修改。

  扩展

  上面的示例代码刚好是刚遇到的,所以拿来举例子。授人以鱼不如授人以渔,有的小问题大家花钱又心疼,想自己折腾也未尝不可以,以后还是会提供更多这类比较初级的解决方案给大家。下面另外举例子:

  $a=0;

  $value=$key/$a;

  //这样可能会提示警告语

  if($a){

  $value=$key/$a;

  }else{

  $value=false;

  }

  //对$value进行赋值计算结果或者false,也可以赋值预设数字,以便后面进行引用。

  上面的方法只是一些示例和排错的技巧,一种思路,具体情况具体分析,但是解决问题要有清晰的思路哈。学会一种技巧少走一些弯路,少花一些钱还是可以的。不过如果要赚钱,舍得花钱找技术开发更适合自己的网站,是很有必要的,花钱减少自己的时间浪费,也少出现一些不必要的麻烦,最重要的是专业的代码和业余的代码还是很大区别的。再者,一个很简单的道理“花钱就是投资”。

  PHP7系列中的异常处理

  在PHP7中异常或者说错误被分为不同的等级

  1. 语法错误级别,也就是经常看到的Parse Error,这种错误,会在Zend引擎进行语法分析和编译的时候就提示错误,注意这种错误一般都是比较低级的手写错误,或者是关键词写错,或者是少些一些分号等。对于这类错误,一般设置error_reporting(E_ALL)或者ini_set('display_errors','on'),在发生错误的时候,就会抛出异常,通过追踪异常堆栈就可以发现问题所在

  2. Fatal Error错误,这种错误一般会导致PHP进程直接退出,也就是导致场景的白屏现象或者webserver返回500。这种错误是不能捕获的,无法通过try...catch或者其他手段进行处理。(PHP7在这一块做了比较明显的升级,方便我们更好的处理部分异常,详见后文分析)

  3. 正常的Exception。对于Exception我们常见的处理方式有两种,一种是用try...catch语句。

  另一种的写法常见于MVC框架,就是调用钩子函数,在作者写的Pfinal MVC框架中就用了这种方法,可以做到全局处理异常,当有未捕获的异常的时候,使用钩子函数注册的处理函数进行处理,不至于会把异常堆栈丢给用户,这是PHP5中高级一点的异常处理方法。以下是作者的Pfinal框架中的异常处理核心文件

  PHP7中的异常处理升级

  PHP7的改动中,影响比较大的,包括异常处理。PHP7实现了一个全局的throwable接口,原来的Exception和部分Error都实现了这个接口(interface), 以接口的方式定义了异常的继承结构。于是,PHP7中更多的Error变为可捕获的Exception返回给开发者,如果不进行捕获则为Error,如果捕获就变为一个可在程序内处理的Exception。这些可被捕获的Error通常都是不会对程序造成致命伤害的Error,例如函数不存。

  PHP7中,基于/Error exception,派生了5个新的engine exception:ArithmeticError / AssertionError / DivisionByZeroError / ParseError / TypeError。在PHP7里,无论是老的/Exception还是新的/Error,它们都实现了一个共同的interface: /Throwable。

  对比原来的PHP5,处理语法错误Parse Error,针对于语法错误,原来的PHP5是遇到语法错误,就会终止PHP进程,同时抛出语法错误的提示。在新的PHP7中,这种异常类型被封装为ParseError异常类,你可以在代码中通过try...catch(ParseError $e){}来处理,妈妈在也不用担心我少写一个分号会导致系统直接奔溃了

  处理Fatal Error,例如以下代码函数参数定义是classInstanceA的类型,但是实际调用的时候传入了classInstanceB的类型,在PHP5中,会触发一个Fatal Error,导致进程终止运行。

  现在在PHP7中,可以通过捕获异常,处理以上错误,不会抛出Fatal Error

【PHP中的Division by zero报错处理技巧】相关文章:

PHP中的表单处理09-10

PHP中cron的批处理08-05

PHP编程中字符串处理的5个技巧08-05

PHP7系列中的异常处理03-26

PHP的中文文字处理技巧09-08

PHP中文文字处理技巧09-18

如何在PHP中处理Protocol Buffers数据09-14

PHP中date函数常用时间处理方法08-09

PHP异常处理办法10-13