PHP中的Division by zero報(bào)錯(cuò)處理技巧
PHP中的Division by zero報(bào)錯(cuò)處理技巧
ecshop部分模板使用時(shí),會(huì)出現(xiàn)“Warning: Division by zero inxxxxxlib_goods.php”錯(cuò)誤,那么怎么處理呢?來看看小編的分享吧!
錯(cuò)誤提示
在打開某些產(chǎn)品分類或者某些產(chǎn)品頁面的時(shí)候,特定語言才報(bào)錯(cuò)。
錯(cuò)誤是:Division by zero in xxx
錯(cuò)誤原因
這個(gè)錯(cuò)誤的原因,就是運(yùn)算的過程中,被除數(shù)是0。上過小學(xué)的都知道“0是不可以作為被除數(shù)的”。
解決思路
1:判斷值為0的時(shí)候跳過運(yùn)算;
2:如果非要賦值給一個(gè)變量,可以做判斷后賦固定值或者輸出false,后面代碼判斷如果變量是true才使用它進(jìn)行下一步代碼的實(shí)現(xiàn)。
DEBUGING
解決問題之前,先來個(gè)兩個(gè)小知識(shí)點(diǎn):
1、在opencart中,vqmod的優(yōu)先等級(jí)是最高的;
2、哪里報(bào)錯(cuò)不一定錯(cuò)誤就在哪里,但是首先看的還是報(bào)錯(cuò)的地方。
從上圖中,我們找到了vqcache下對(duì)應(yīng)的文件對(duì)應(yīng)行數(shù),發(fā)現(xiàn)如下代碼:
//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;
}
從這個(gè)代碼可以看出有若干個(gè)參數(shù),我們留意“/”后面的被除數(shù)就好,這里被除數(shù)有兩個(gè)地方,其中第二個(gè)是正整數(shù)100,可以排除。那么問題就在下面這段代碼中:
$this->tax->calculate($result['price'],$result['tax_class_id'],$this->config->get('config_tax'))
我們從上面這個(gè)方法里看到三個(gè)參數(shù),分別用print_r打印了下參數(shù)的值,結(jié)果發(fā)現(xiàn)第二個(gè)參數(shù)“$result['tax_class_id']”是“000000”。很顯然,如果這個(gè)是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;
}
也就是,加多一個(gè)判斷依據(jù),必須滿足兩個(gè)值都存在的前提下,才進(jìn)行如下運(yùn)算,否則是false。
修改代碼,保存代碼,上傳文件,刷新頁面,警告提示語消失,over。
但是,畢竟我們改的是緩存文件,真正要修改好代碼,我們還是要把代碼寫到核心文件或者插件的文件里。
修改源
首先,我們從三個(gè)地方查找,分別是:
核心文件:/catalog/controller/product/category.php;
vqmod:/vqmod/xml/*.xml;
ocmod:上傳插件的ocmod.xml文件備份,或者數(shù)據(jù)庫查看:oc_modification表xml字段;
雖然vqmod的優(yōu)先等級(jí)高于ocmod,但是其實(shí)先從比較方便的地方找起也是可以的。有個(gè)方法可以排除是否ocmod。如果是ocmod插件的,緩存文件名必定有“system_storage_modification”。
但是也由于vqmod優(yōu)先等級(jí)最高,所以被ocmod緩存的文件的文件名也可能有這個(gè)字樣,所以排查的順序如上所述。
核心文件的話,編輯器打開ctrl+F進(jìn)行關(guān)鍵字查找修改。
如果是vqmod的xml,要么排除法排除不可能是的文件,然后從可能是的文件里查找。如果文件太多就用notepad++等編輯器或者IDE工具,可以進(jìn)行目錄搜索,從中找到文件。
如果是ocmod,則用MYSQL工具進(jìn)行字段like %...% 搜索,或者用SQL語句:
SELECT*FROM`oc_modification`WHERE`xml`like"%關(guān)鍵代碼%"
由于這里存的數(shù)據(jù)被轉(zhuǎn)義過,所以搜索的內(nèi)容不要帶有換行之類的,抓取比較有特點(diǎn)的代碼進(jìn)行查找和修改。修改的時(shí)候注意轉(zhuǎn)義的影響哈。當(dāng)然現(xiàn)在很多MYSQL管理工具這一點(diǎn)做的還是挺好的。建議最好修改插件的ocmod.xml文件,然后重新上傳一次。平時(shí)插件裝了后自己留備份還是有必要的。如果沒文件就導(dǎo)出備份再修改。
擴(kuò)展
上面的示例代碼剛好是剛遇到的,所以拿來舉例子。授人以魚不如授人以漁,有的小問題大家花錢又心疼,想自己折騰也未嘗不可以,以后還是會(huì)提供更多這類比較初級(jí)的解決方案給大家。下面另外舉例子:
$a=0;
$value=$key/$a;
//這樣可能會(huì)提示警告語
if($a){
$value=$key/$a;
}else{
$value=false;
}
//對(duì)$value進(jìn)行賦值計(jì)算結(jié)果或者false,也可以賦值預(yù)設(shè)數(shù)字,以便后面進(jìn)行引用。
上面的方法只是一些示例和排錯(cuò)的技巧,一種思路,具體情況具體分析,但是解決問題要有清晰的思路哈。學(xué)會(huì)一種技巧少走一些彎路,少花一些錢還是可以的。不過如果要賺錢,舍得花錢找技術(shù)開發(fā)更適合自己的網(wǎng)站,是很有必要的,花錢減少自己的時(shí)間浪費(fèi),也少出現(xiàn)一些不必要的麻煩,最重要的是專業(yè)的代碼和業(yè)余的代碼還是很大區(qū)別的。再者,一個(gè)很簡(jiǎn)單的道理“花錢就是投資”。
PHP7系列中的異常處理
在PHP7中異;蛘哒f錯(cuò)誤被分為不同的等級(jí)
1. 語法錯(cuò)誤級(jí)別,也就是經(jīng)?吹降腜arse Error,這種錯(cuò)誤,會(huì)在Zend引擎進(jìn)行語法分析和編譯的時(shí)候就提示錯(cuò)誤,注意這種錯(cuò)誤一般都是比較低級(jí)的手寫錯(cuò)誤,或者是關(guān)鍵詞寫錯(cuò),或者是少些一些分號(hào)等。對(duì)于這類錯(cuò)誤,一般設(shè)置error_reporting(E_ALL)或者ini_set('display_errors','on'),在發(fā)生錯(cuò)誤的時(shí)候,就會(huì)拋出異常,通過追蹤異常堆棧就可以發(fā)現(xiàn)問題所在
2. Fatal Error錯(cuò)誤,這種錯(cuò)誤一般會(huì)導(dǎo)致PHP進(jìn)程直接退出,也就是導(dǎo)致場(chǎng)景的白屏現(xiàn)象或者webserver返回500。這種錯(cuò)誤是不能捕獲的,無法通過try...catch或者其他手段進(jìn)行處理。(PHP7在這一塊做了比較明顯的升級(jí),方便我們更好的處理部分異常,詳見后文分析)
3. 正常的Exception。對(duì)于Exception我們常見的處理方式有兩種,一種是用try...catch語句。
另一種的寫法常見于MVC框架,就是調(diào)用鉤子函數(shù),在作者寫的Pfinal MVC框架中就用了這種方法,可以做到全局處理異常,當(dāng)有未捕獲的異常的時(shí)候,使用鉤子函數(shù)注冊(cè)的處理函數(shù)進(jìn)行處理,不至于會(huì)把異常堆棧丟給用戶,這是PHP5中高級(jí)一點(diǎn)的異常處理方法。以下是作者的Pfinal框架中的異常處理核心文件
PHP7中的異常處理升級(jí)
PHP7的改動(dòng)中,影響比較大的,包括異常處理。PHP7實(shí)現(xiàn)了一個(gè)全局的throwable接口,原來的Exception和部分Error都實(shí)現(xiàn)了這個(gè)接口(interface), 以接口的方式定義了異常的繼承結(jié)構(gòu)。于是,PHP7中更多的Error變?yōu)榭刹东@的Exception返回給開發(fā)者,如果不進(jìn)行捕獲則為Error,如果捕獲就變?yōu)橐粋(gè)可在程序內(nèi)處理的Exception。這些可被捕獲的Error通常都是不會(huì)對(duì)程序造成致命傷害的Error,例如函數(shù)不存。
PHP7中,基于/Error exception,派生了5個(gè)新的engine exception:ArithmeticError / AssertionError / DivisionByZeroError / ParseError / TypeError。在PHP7里,無論是老的/Exception還是新的/Error,它們都實(shí)現(xiàn)了一個(gè)共同的interface: /Throwable。
對(duì)比原來的PHP5,處理語法錯(cuò)誤Parse Error,針對(duì)于語法錯(cuò)誤,原來的PHP5是遇到語法錯(cuò)誤,就會(huì)終止PHP進(jìn)程,同時(shí)拋出語法錯(cuò)誤的提示。在新的PHP7中,這種異常類型被封裝為ParseError異常類,你可以在代碼中通過try...catch(ParseError $e){}來處理,媽媽在也不用擔(dān)心我少寫一個(gè)分號(hào)會(huì)導(dǎo)致系統(tǒng)直接奔潰了
處理Fatal Error,例如以下代碼函數(shù)參數(shù)定義是classInstanceA的類型,但是實(shí)際調(diào)用的時(shí)候傳入了classInstanceB的類型,在PHP5中,會(huì)觸發(fā)一個(gè)Fatal Error,導(dǎo)致進(jìn)程終止運(yùn)行。
現(xiàn)在在PHP7中,可以通過捕獲異常,處理以上錯(cuò)誤,不會(huì)拋出Fatal Error
版權(quán)聲明:本文內(nèi)容由互聯(lián)網(wǎng)用戶自發(fā)貢獻(xiàn),該文觀點(diǎn)僅代表作者本人。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如發(fā)現(xiàn)本站有涉嫌抄襲侵權(quán)/違法違規(guī)的內(nèi)容, 請(qǐng)發(fā)送郵件至 yyfangchan@163.com (舉報(bào)時(shí)請(qǐng)帶上具體的網(wǎng)址) 舉報(bào),一經(jīng)查實(shí),本站將立刻刪除