php開發過程當中不怎麼常見的問題

平常開發中碰到就記一下, 若是有朋友願意分享的 bug 能夠在評論中討論啊

url 當中的參數有 &timestamp=1234567890這樣的字段會被轉義成xtamp=1234567890

這個不只存在於頁面解析當中,當使用 curl 請求時拼接的參數有這種格式的也會發生轉義
解決方法有兩個:javascript

  1. 把 timestamp 這個參數放在 urlQuery 的最前面, ?timestamp=1234567890 這樣避免出現 &time發生轉義的狀況
  2. &&來代替

Automatically populating $HTTP_RAW_POST_DATA is deprecated and will be removed in a future version.

出現這句話一般說明你在用的 php 版本是5.6.並且在php<=5.6的時候,進行 application/json格式的 post 提交會把數據放在$HTTP_RAW_POST_DATA這個系統變量裏面,在php>=7的時候這個變量被移除了,通通歸總到php://input這裏
解決方法:php

  1. 根據系統提示的走:
Although that indeed would be technically impossible (as $HTTP_RAW_POST_DATA is populated in the bootstrapping phase of the PHP process) allow one to override the setting by means of calling ini_set.
要確保本身的系統中沒有使用 `HTTP_RAW_POST_DATA`這個變量,直接在`php.ini`裏面禁掉它的設置,可是容易出現系統中又打開的狀況(在框架中很常見)
  1. 改一下本身的提交方式, 使用 application/form-data或者application/x-www-form-urlencoded這種格式的提交, 而後在後端接收數據的時候再轉成本身須要的格式(一般是數組)
    參考資料

Exception 'yiidbException' with message 'SQLSTATE[HY000] [2002] No such file or directory'

這種狀況出如今平時運行的好好的, 可是忽然換 cli 模式後這個配置就出問題了,緣由在當 host=localhost時走的是 unix:socket 連接, 當host=127.0.0.1走的是 tcp 連接,這在php-fpmphp-cli中有點區別,尤爲是本地沒有安裝 mysql 的時候
解決方法有三種:html

  1. 將本地連接配置統一成 127.0.0.1
  2. 查看 MySQL 中的user表, host=localhosthost=127.0.0.1是否是用的同一個帳號密碼
  3. 配置php.ini文件中的pdo_mysql.default_socket= 寫上完整的 socket 路徑

以上三種方法均可以試一下
參考資料前端

常駐內存時發生的事情

這個是 phper 不多碰到可是很常見的狀況, 好比用 swoole 啓動了一個常駐進程的服務, 那麼就必定要當心使用靜態變量,在同步模式下會發生變量污染, 還有就是 redis,mysql 這類的連接,你會發現長時間靜置之後就會出現一些摸不着頭腦的問題, 這種狀況不妨想一下是否是 server 端回收了這個 socket,所以在 client 端怎麼都寫入不進去. 還有就是 php 在讀取消息的時候,出現消息過長的狀況,那麼就要考慮EOF終止符的問題了... 單次 http 每一次請求都是全新的代碼, 不用本身考慮 gc 的問題, 可是在常駐內存的時候,這些就是一個個的大坑了java

mysql has gone away

產生這個錯誤的主要緣由是 mysql server 端斷開了連接, client 端還拿着這個句柄去請求,解決方式有兩種:mysql

  1. show global variables like '%timeout'; 查看 wait_timeout 的時長,適當的調長一點, 這種方法治標不治本,並且有隱患
mysql> set global wait_timeout=10;
mysql> show global variables like 'wait_timeout';
  1. 使用 mysql 以前須要 mysql_ping() 一下, 若是出現斷開的錯誤就啓動重連機制

js 和 php 交互傳中文參數的編解碼問題

以前碰到了問題是:
在 php 端 urlencode 的值爲:linux

orderid%3D21111111110001954%26pid%3D257742%26reason%3D%E4%B8%AA%E4%BA%BA%E6%96%B9%E9%9D%A2%E5%8E%9F%E5%9B%A0_%E4%BD%BF%E7%94%A8%E7%BA%A2%E5%8C%85%E9%87%8D%E6%96%B0%E4%B8%8B%E5%8D%95%26token%3D041d9e5575f480b7bfd58b09bd14ab1c7ee9e9594f2fcdb9f0e3e39fc634b48f

須要 urldecode 一次redis

而在 js 端的結果是:sql

orderid%3D21111111110002170%26pid%3D257742%26reason%3D%25E4%25B8%25AA%25E4%25BA%25BA%25E6%2596%25B9%25E9%259D%25A2%25E5%258E%259F%25E5%259B%25A0_%25E4%25B8%25AA%25E4%25BA%25BA%25E8%25BA%25AB%25E4%25BD%2593%25E5%258E%259F%25E5%259B%25A0%26token%3D041d9e5575f480b7bfd58b09bd14ab1c7ee9e9594f2fcdb9f0e3e39fc634b48f

須要 urldecode 兩次json

查閱資料後:

在後端是PHP程序的狀況下,保持前端Javascript和PHP之間傳值的統一編碼可使用如下函數進行處理:
 
WEB前端JavaScript
 
編碼:escape(encodeURI(string))
 
解碼:unescape(decodeURI(string))
 
WEB後端Php
 
編碼:urlencode(string)
 
解碼:urldecode(urldecode(string))

爲何要encodeURI(url)兩次纔不會出現亂碼?

PHP中rawurlencode和urlencode、JS中encodeURI與encodeURIComponent 的區別

rawurlencode遵照是94年國際標準備忘錄RFC 1738

urlencode實現的是傳統作法,和上者的主要區別是對空格的轉義是'+'而不是'%20'
javascript的encodeURL也是94年標準,而javascript的escape是另外一種用"%xxx"標記unicode編碼的方法。
推薦在PHP中使用用rawurlencode。棄用urlencode

樣例
source:
超級無敵的人sadha sajdh數據樣本sdls fhejrthcxzb.file.jpeg

PHP urlencode:
%E8%B6%85%E7%BA%A7%E6%97%A0%E6%95%8C%E7%9A%84%E4%BA%BAsadha+sajdh%E6%95%B0%E6%8D%AE%E6%A0%B7%E6%9C%ACsdls+fhejrthcxzb.file.jpeg

PHP rawurlencode:
%E8%B6%85%E7%BA%A7%E6%97%A0%E6%95%8C%E7%9A%84%E4%BA%BAsadha%20sajdh%E6%95%B0%E6%8D%AE%E6%A0%B7%E6%9C%ACsdls%20fhejrthcxzb.file.jpeg

Javascript encodeURI|encodeURIComponent:
%E8%B6%85%E7%BA%A7%E6%97%A0%E6%95%8C%E7%9A%84%E4%BA%BAsadha%20sajdh%E6%95%B0%E6%8D%AE%E6%A0%B7%E6%9C%ACsdls%20fhejrthcxzb.file.jpeg

Javascript escape:
%u8D85%u7EA7%u65E0%u654C%u7684%u4EBAsadha%20sajdh%u6570%u636E%u6837%u672Csdls%20fhejrthcxzb.file.jpeg

帖子原文

在前端還有個問題就是, js 的 encodeURIComponentencodeURI 都不會轉換 _-.!~*'()# 這些保留字符, 而在後端的rawurlencode 則是會轉換的, 所以須要前端單獨把這幾個給拎出來, 以下:

"*".charCodeAt(0) // 42
String.fromCharCode(42) // *

這裏有張圖說的很明白

圖片來源

關於出現 <U+200B> 這種 zero-width space 字符

若是出現 mb_substr 這類操做的時候, 會出現字數判斷錯誤的問題, 這個有時候很難排查, 由於在 win 上,使用命令行或者 linux 上用cat命令是看不到字符間是有 <U+200B> 的, 以下:

這玩意兒出現的場景就是: 在前端輸入框中輸入幾個字, 而後複製粘貼. 這樣儘管看起來之間沒有空格, 可是其中仍是插入了這個字符
這玩意就叫 zero-width space 零寬空格, 處理的辦法也很簡單, 前端傳值以前給過濾一下, 好比 https://stackoverflow.com/que...https://codeday.me/bug/201711...

後端 php 處理的話和這個不同, 使用 utf-8 的處理方式, 能夠參考這篇文章 特殊字符<200b><200c><200d>的刪除辦法與原理

替換這種編碼

$value = str_replace("\xe2\x80\x8b", '', $value);
$value = str_replace("\xe2\x80\x8c", '', $value);
$value = str_replace("\xe2\x80\x8d", '', $value);

編碼對照以下:

個人博客

相關文章
相關標籤/搜索