<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                ## 細節注意 一些重要但是容易被忽略的細節記錄。不起眼但很重要的知識。 ![](http://cdn.aipin100.cn/微信圖片_20190316074725.jpg) 家里的電器壞了,90%的原因是因為沒有插電源插頭。 寫代碼也是這樣,很多時候往往是因為不夠細心而出了問題,比如寫錯變量名、多了空格等,所以出現問題時最應該先細心的檢查一遍代碼在做調試。 ***** ### 判斷細節 ```php if (0 == '') { echo "output"; } if (0 == 'str') { echo "output"; } if (0 == '1') { echo "not output"; } if (0 == '1str') { echo "not output"; } if ('0' == '') { echo "not output"; } if ('0' == 'str') { echo "not output"; } ---- // 整形轉換實驗 var_dump((int) '01'); // 1 var_dump((int) '0 1'); // 0 var_dump((int) '0str'); // 0 var_dump((int) '0 str'); // 0 if (0 == '01') { echo "no output"; } if (0 == '0str') { echo "output"; } if (0 == '0 1') { echo "output"; } if (0 == '0 str') { echo "output"; } ``` 字符串 `'0'` 和整數 `0` 是不一樣的,在開發中要尤其注意這個容易忽略的細節。 字符串類型 與 整形 作比較時,字符串會自動轉換成 整形 在與之比較,**所以 開發時嚴格要求必須使用 全等比較,不要使用自動轉換的特性,除了提高性能外最重要的是能夠避免這種不易發現的安全問題。** ---- ### 判斷盡量使用全等,不要讓其自動轉換布爾再比較 php7在線執行 http://www.dooccn.com/php7/ ```php var_dump((bool) 0); // false var_dump((bool) -1); // true var_dump((bool) '-1'); // true var_dump((bool) '0'); // false var_dump((bool) 'str'); // true if (0 == '') { echo 's'; // output } if (0 == 'str') { echo 's'; // output } if ('0' == '') { echo 's'; // no output } ``` 兩個類型不同的表達式進行比較時,會先各自自動換成布爾值后在進行比較,**只有當兩者類型不一致時才會發生類型自動轉換。** >[tip] 當你要用比較時,永遠優先考慮使用全等式。 盡量只讓類型確定的表達式參與比較,類型不同時也可以手動轉換成一致類型后再全等比較,而不要依賴自動的布爾轉換,這樣做的原因不僅僅是因為自動轉換的性能消耗問題,更重要的是為了避免某些隱蔽的錯誤發生,使程序更加健壯。 >[tip] 糾正:上面說,類型不同的表達式比較時會自動轉換為布爾值,這是不完全正確的,應該為:和布爾值比較時 轉換為布爾值,和整形比較時,轉換為整形后再比較。 ---- ### php與js關于判斷的區別 ```php if ('string' == 0) { echo "output"; } ``` js版本:比較上PHP和js是不同的,這有點出乎我的意料 javascript: ```javascript var a = 'string'; a == 0; // false ``` ***** ### 使用不存在變量報錯的細節 使用不存在的變量會報錯,但有一種情況例外: ```php echo $a; // 報錯 Notice: Undefined variable: a $a = null; echo $a['k']; // 不會報錯,值為null 或者 $a = false; echo $a['k']; // 不會報錯,值為null ``` 這個細節很重要,因為在嚴格框架下面,我們總會期望當使用不存在的變量時來拋出異常,如果業務邏輯依賴于此,就得小心了。 ***** #### MYSQL decimal(10,2) 四舍五入問題 ```php # number_format 也會四舍五入 echo number_format(12.088, 2, '.', ''); // 12.09 // 還指望mysql自動保留兩位小數,不進行任何四舍五入呢,沒想到在 MySQL5.5.53 版本下,會進行四舍五入(12.088 => 12.09),坑啊!看來任何時候都不要指望和依賴外部啊。(目前發現不論什么版本的MySQL 都會直接四舍五舍的) // 金額格式化(保留兩位小數,四舍五舍) function priceFormat($val) { // 保留兩位小數不四舍五入 return substr(sprintf("%.3f", $val), 0, -1); } ``` >[danger] 任何時候都不要指望和依賴外部,所有數據直接算好,交給數據庫原原本本的存就可以,不要讓數據庫參與任何的邏輯部分,以及數據處理。 所以需要自己實現一個,但這也引發一個思考,那就是業務中到底需要保留多少位小數,以及如何對待多余的小數位。最簡單粗暴的方式就是 四舍五入 或 四舍五舍,不同交易場景下,這兩種方案都有不同的副作用,比如少收或多給。復雜的可能需要考慮銀行家算法。 ***** #### 浮點數計算問題 [php浮點數的精度問題深究 - php小松 - CSDN博客](https://blog.csdn.net/a454213722/article/details/52135462) [PHP浮點數的一個常見問題的解答 | 風雪之隅](http://www.laruence.com/2013/03/26/2884.html) [關于PHP浮點數你應該知道的(All 'bogus' about the float in PHP) | 風雪之隅](http://www.laruence.com/2011/12/19/2399.html) [intval遇到小數為什么會減1-CSDN論壇](https://bbs.csdn.net/topics/390789758) [PHP: BC 數學 函數 - Manual](https://www.php.net/manual/zh/ref.bc.php) [PHP: GMP 函數 - Manual](https://www.php.net/manual/zh/ref.gmp.php) ```php // 安全的數字計算方式 // https://www.cnblogs.com/phpfensi/p/8143367.html // https://www.cnblogs.com/jiqing9006/p/5531687.html // http://php.net/manual/zh/function.bcdiv.php // https://blog.csdn.net/LJFPHP/article/details/82255389 // https://www.cnblogs.com/phpper/p/7664069.html //$m和$n代表傳入的兩個數值,主要就是這兩個數值之間的比較 //$x代表傳入的方法,比如是;add,sub等 //$scale 代表傳入的小數點位數。這個根據需求更改即可 function calc($m, $n, $x = 'add', $scale = 2) { $errors = array( '被除數不能為零', '負數沒有平方根', ); switch ($x) { case 'add': $t = bcadd($m, $n, $scale); break; case 'sub': $t = bcsub($m, $n, $scale); break; case 'mul': $t = bcmul($m, $n, $scale); break; case 'div': if ($n != 0) { $t = bcdiv($m, $n, $scale); } else { return $errors[0]; } break; case 'pow': $t = bcpow($m, $n, $scale); break; case 'mod': if ($n != 0) { $t = bcmod($m, $n, $scale); } else { return $errors[0]; } break; case 'sqrt': if ($m >= 0) { $t = bcsqrt($m); } else { return $errors[1]; } break; } return $t; } ``` ***** #### tp $db->find(null) 注意 ```php Db::name('user')->find($userId); ``` 如果 `$userId` 是 `null` ,那么 `find(null)` 會查詢出來表的第一條數據,由于我們的疏忽,沒有 `(int) $userId` ,很可能就造成業務邏輯不符合預期,甚至引起嚴重而隱秘的BUG。 突然感覺到參數類型嚴格限制語言的好處了,確實能在很大程度上幫助我們在開發時避免這類錯誤問題。 ***** ### intval() 整形轉換問題 > 不管變量前面有多少個0,且數字都小于8,它會當作是八進制數轉換成十進制數 [php中intval()函數 - ann_glx - 博客園](https://www.cnblogs.com/anns/p/3494195.html) ***** #### PHP intval() 處理大整形問題 可以使用: ```php $paysn = floatval($_POST['paysn']); ``` 不能在使用 `intval()`了 [php關于數字防注入,intval溢出,intval - u010412301的博客 - CSDN博客](http://blog.csdn.net/u010412301/article/details/55046733) [PHP長整型在32位系統中強制轉化溢出 - CleverCode的博客 - CSDN博客](http://blog.csdn.net/clevercode/article/details/46423103) [PHP-php使用intval長度超限的問題? - 德問:編程社交問答](http://www.dewen.net.cn/q/3969) last update:2018-2-9 10:48:00 ***** ### 條件判斷優先級問題之括號 ```php // 錯誤,不符合預期,且不易發現 if (!$info = $db->lock(true)->getRow($sql) || $info['s_patent_claim_status'] != 0) {} // 正確,符合預期 if (!($info = $db->lock(true)->getRow($sql)) || $info['s_patent_claim_status'] != 0) {} // 正確,符合預期 if ($patentId && $recordInfo = $db->lock(true)->getRow($sql)) {} ``` 所以必須細心謹慎對待這類條件判斷問題,越不起眼越往往越容易出錯,要確保每個功能上線前都通過完備了測試。 ***** ### mysql非嚴格模式下注意的細節 ``` `status` tinyint(4) unsigned NOT NULL DEFAULT 0 COMMENT '' ``` unsigned 無符號的,在非嚴格模式下, `SET status = -1` 不會更改任何數據,也不會報錯,這時就需要注意了。 需要詳細的測試,程序要健壯,一定要在嚴格模式環境下進行開發,對返回進行檢查,及時發現問題。 ***** ### var_export對標量不友好,特別是浮點型 ```php echo var_export(1.4, true); // 1.3999999999999999 echo var_export('1.4', true); // '1.4' ``` 所以如果用到了var_export, 請判斷一下是否為標量: ```php if (!is_scalar($value)) { $val = var_export($value, true); } else { $val = $value; } ``` ***** ### @ 關鍵字慎用!!! @ 屏蔽錯誤顯示,頁面出錯不會往下執行,但是頁面不會顯示任何報錯信息!這讓人很無語,如果不是確定的代碼,請不要使用@ 不然沒有錯誤信息怎么調試呢,錯誤也很重要,要知道錯誤、BUG也是程序的一部分,也和程序本身一樣的同等重要,沒有錯誤信息、錯誤處理的程序是不完整的,是沒有靈魂的。 ---- ### 計算時注意數據類型是否為數字 這是js中的情況: ```javascript 1 + '9' // "19" ``` php也有類似的問題,總之任何時候不要忘記,當你想要計算時,是否嚴格驗證了計算對象的數據類型。 ---- ### left join 左連一對多問題 a LEFT JOIN b ON a.id = b.mid a INNER JOIN b ON a.id = b.mid 如果 a只有一條,但是對應的 b有兩條,**那么最終結果是兩條** ,這點容易讓人忽略掉 |id|name| |---|---| |10| name | |id|mid|title| |---|---|---| |1|10| title1 | |2|10| title2 | >[tip] 如果右表 `ON` 外鍵字段有重復的,那么就會出現重復數據 ~~~ 1. select DISTINCT a.id, a.name, b.* from a left join b on a.id = b.mid 重復 2. select DISTINCT a.id, a.name from a left join b on a.id = b.mid 不重復 3. select a.id, a.name from a left join b on a.id = b.mid GROUP BY a.id 不重復 4. select group_concat(DISTINCT a.id) as id,a.name, b.* from a left join b on a.id = b.mid 不重復 https://blog.csdn.net/u010003835/article/details/79154457 DISTINCT 表示對后面的所有參數的拼接取 不重復的記錄,相當于 把 SELECT 表達式的項 拼接起來選唯一值。 即:行唯一,所以 上面 1 還是重復,2 不重復 ~~~ [https://segmentfault.com/a/1190000017067294](https://segmentfault.com/a/1190000017067294) [數據庫表連接的簡單解釋 - 阮一峰的網絡日志](http://www.ruanyifeng.com/blog/2019/01/table-join.html) [數據庫的最簡單實現 - 阮一峰的網絡日志](http://www.ruanyifeng.com/blog/2014/07/database\_implementation.html) ![](http://cdn.aipin100.cn/7ded569002d08f20605acf021f7cb979) ps: 待研究 on 和 where 的區別,對上面的情況來說理論上 where 寫 on 效果也是一樣的,甚至提前縮小了范圍表連接會更小 on a.id = b.mid where a.id = 1 表關系:條件兩邊都是表的字段,而不是其它值,如:a.id = b.mid 使用表連接,表關系不可無,并且 on 中只有寫 表關系 才有效,如果寫了 where 條件 會直接被忽略掉。 需要注意的是,表關系 也可以寫在 where 中,但是不建議這樣,應該都寫在 on 中提前縮小表連接范圍。 上面說法錯誤,正確如下: 1. 左聯或右連時 on 都不會縮小主表范圍,內聯可以縮小范圍。 2. on 只是查找副表數據與其連接,副表沒有數據不會影響結果(副表字段都是 null)。 3. where 是最終對數據行進行過濾 4. ~~on 上寫主表條件沒有作用(因為這個條件只是查找副表數據)~~,但可以寫副表 條件 縮小 副表范圍 5. ~~如果要過濾最終結果,只能依靠 where~~ 6. where/join on 在 INNER/RIGHT 時沒什么區別,但是 LEFT 時就有很大區別:on 上只能過濾 副表的數據,并不能像 where 一樣 過濾最終數據,導致如果主表數據多,最終結果可能不能如愿。 ~~~ join on 不同類型的字段比較時,如 int 與 var 比較時,會自動轉為 整形再比較,這就導致了 結果并不全等 如 1q 1_2 都是當做1來比較的 https://blog.csdn.net/u013378306/article/details/105110465/ ~~~ ---- ### js篇:不要使用 “連相等賦值” ```javascript function a() { var b = d = 1; } a(); d; // 1 // d 成了全局的了,如果你想將d賦值給b,就不要這樣寫 “連相等賦值”,而是這樣: function a() { var d = 1, b = d; } a(); ``` ---- ### mysql_insert_id() 受 insert 和update影響 所以 mysql_insert_id 不一定是取到 最后 insert 的id,如果中間 有update,則返回0 。 ***** ### 注意隱含產生的引用 ```php $arr = [['a'], ['b']]; var_dump($arr); foreach ($arr as &$item) { foreach ($item as &$value) { } // unset($value); } // unset($item); var_dump($arr); ``` ``` array(2) { [0]=> array(1) { [0]=> string(1) "a" } [1]=> array(1) { [0]=> string(1) "b" } } array(2) { [0]=> array(1) { [0]=> string(1) "a" } [1]=> &array(1) { [0]=> &string(1) "b" } } ``` ---- ### mysql 千萬不要使用 id != null SELECT * FROM `sp_led_mould` WHERE id != null; 沒有結果 SELECT * FROM `sp_led_mould` WHERE id is not NULL; 才會有結果 mysql version: 5.6.16-log ---- ### 注意不要 在 tp 同一模型上 上做多次更新 [更新 · ThinkPHP5.0完全開發手冊 · 看云](http://www.hmoore.net/manual/thinkphp5/135189) > 注意不要在一個模型實例里面做多次更新,會導致部分重復數據不再更新,正確的方式應該是先查詢后更新或者使用模型類的`update`方法更新。 ~~~ 關于多次調用save更新只有第一次更新的數據成功,后面都不成功的,可以在調用save前調用->force()來強制更新,或者調用update更新但是不要調用where方法。調用force的原因是save更新后會$this->origin = $this->data;而更新時又會調用getChangedData檢查這個屬性,不調用force就會只更新上次沒更新過的字段,所以才會導致循環save只有第一條成功。模型的update就不會有這個問題,因為這個方法每次都是重新new一個實例 ---- foreach(\[1,2,3\] as $k=>$v){ $user->save($data,\[id=>$v\]); } foreach更新只能更新第一條數據,什么原因? ~~~ ---- ### json_decode 問題 **浮點精度** php.ini 建議配置: ~~~ serialize_precision: 16 serialize_precision: -1 ~~~ 否則會導致 json_encode 中浮點數出現精度問題 ---- **大整形問題** 解決大整形數值會被轉成 科學計數法 string 類型: ```php $res = json_decode($body, true, 512, JSON_BIGINT_AS_STRING); ``` ---- last update: 2019-5-28 23:42:01
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看