2020-03-14 11:43:30 老公城獅
1. sessionID存儲到cookie中,如果cookie不能用了,session也就失效了。 session印象服務器性能,而且跨服務器的session很難配置。
2. 單引號只轉義 單引號和 \\ 而雙引號轉義很多,如果不加引號,會當作常量去處理。
3. GBK轉車ascii碼 -- 2個字節 UTF8 -- 3個字節 漢字的處理一般都用 mbstring來處理
4. 字符串操作 - 常見任務
=================================
* 提取/查找
* 替換/截斷
* 大小寫轉換
* 轉義/轉編碼
substr()
=========================
字符串截取是最基礎的操作之一,substr函數功能強大,通常使用substr即可完成所有所需操作。
substr_compare() 函數從指定的開始長度比較兩個字符串。
該函數返回:
- 0 - 如果兩字符串相等
- <0 - 如果 string1 (從開始位置)小於 string2
- >0 - 如果 string1 (從開始位置)大於 string2
實戰 - 獲取URL的協議名1
===========================
$url = 'http://weibo.com/rodin';
$url_https = 'https://login.sina.com.cn';
function is_https($url){
return substr($url, 0, 5) === 'https';
}
echo is_https($url) ? 'is secure' : 'not secure';
echo is_https($url_https) ? 'is secure' : 'not secure';
實戰 - 獲取URL的協議名2
===========================
function is_https2($url){
return substr_compare($url, 'https', 0, 5) === 0;
}
實戰 - 獲取URL的協議名3
===========================
parse_url(); -- 判斷url的格式,是否加了協議名稱
function is_https3($url){
$url_components = parse_url($url);
return $url_components['scheme'] === 'https';
}
實戰 - 獲取URL的協議名4
===========================
function is_https4($url){
return $url{0} === 'h'
&& $url{1} === 't'
&& $url{2} === 't'
&& $url{3} === 'p'
&& $url{4} === 's';
}
substr_replace() - 方法說明 -- 函數把字符串的一部分替換為另一個字符串
=========================
substr_replace(string,replacement,start,length)
參數描述string必需。規定要檢查的字符串。replacement必需。規定要插入的字符串。start必需。規定在字符串的何處開始替換。
- 正數 - 在第 start 個偏移量開始替換
- 負數 - 在從字符串結尾的第 start 個偏移量開始替換
- 0 - 在字符串中的第一個字符處開始替換
charlist可選。規定要替換多少個字符。
- 正數 - 被替換的字符串長度
- 負數 - 從字符串末端開始的被替換字符數
- 0 - 插入而非替換
str_ireplace -- 函數使用一個字符串替換字符串中的另一些字符,忽略大小寫
str_replace -- 函數使用一個字符串替換字符串中的另一些字符,該函數對大小寫敏感
preg_replace -- 執行正則表達式的搜索和替換
preg_replace_callback -- 用回調函數執行正則表達式的搜索和替換
實戰 - 過濾危險字符1
==========================
$dangerous='This is dangerous!';
$unsafe = str_replace('>', '>', $dangerous);
$safe = str_replace('
echo $safe;
//一次替換多個
echo str_replace(
array(''), array(''), $dangerous
);
strpos()
=========================
字符串查找是最基礎的操作之一。
系列函數中,默認為從左往右以及大小寫敏感(二進制安全)。
加i的是大小寫忽略(case-insenstive)
加r的是從右往左找,但返回的位置仍然是從左往右。
strpos/stripos 忽略大小寫
strrpos 從後向前 /strripos 忽略大小寫
int|false strpos($haystack, $needle, $offset = null);
//如果在$haystack字符串中查找到了第一個$needle的存在,返回其起始位置;
//否則返回false。
//如果指定了$offset,則會從$offset的位置開始查找,否則從$haystack
//的第一個字符開始查找。
strpos()
=========================
for($i = 0; $i <= 9; $i ++){
echo strpos('9876543210', "$i");
}
explode()
======================
字符串分離,split() 是 explode() 的別名函數
explode/split
implode/join
實戰 - 檢查是否有危險字符存在1
================================
.. code-block:: php
$sql_injection_str = "abcde' or 1=1";
if(strpos($sql_injection_str, "'") !== false){
echo 'suspected sql injection';
}else{
echo 'safe sql string';
}
實戰 - 檢查是否有危險字符存在2
================================
$sql_injection_str = "abcde' or 1=1";
if(count(explode("'", $sql_injection_str)) > 1){
echo 'suspected sql injection';
}else{
echo 'safe sql string';
}
實戰 - 提取文件名1
===========================
$file_name = 'a.rar.zip.html';
$dot_pos = strpos($file_name, '.');
$file_basename = ($dot_pos !== false)
? substr($file_name, 0, $dot_pos)
: $file_name;
echo $file_basename;
實戰 - 提取文件名2
===========================
$file_name = 'a.rar.zip.html';
$file_basename = strstr('.', $file_name, true);
echo $file_basename;
實戰 - 提取文件名3
===========================
.. code-block:: php
$file_name = 'a.rar.zip.html';
list($file_basename,) = explode('.', $file_name, 2);
echo $file_basename;
實戰 - 提取文件名4
===========================
$file_name = 'a.rar.zip.html';
$file_basename = strtok($file_name, '.');
echo $file_basename;
實戰 - 提取文件擴展名1
===========================
//只要最後一個“.“後面的
$file_name = 'a.rar.zip.html';
$dot_pos = strrpos($file_name, '.');
$file_extname = ($dot_pos !== false)
? substr($file_name, $dot_pos + 1) : '';
echo $file_extname;
實戰 - 提取文件擴展名2
===========================
$file_name = 'a.rar.zip.html';
$last_slice = strstr($file_name, '.');
$file_extname = '';
while($last_slice !== false){
$file_extname = substr($last_slice, 1);
$last_slice = strstr($file_extname, '.');
}
echo $file_extname;
實戰 - 提取文件擴展名3
===========================
$file_name = 'a.rar.zip.html';
$file_name_slices = explode('.', $file_name);
$file_extname = count($file_name_slices) > 1
? array_pop($file_name_slices) : '';
echo $file_extname;
實戰 - 提取文件擴展名4
===========================
$file_name = 'a.rar.zip.html';
$token = strtok($file_name, '.');
$file_extname = '';
while($token !== false){
$file_extname = $token;
$token = strtok('.');
}
echo $file_extname;
trim() - Usage
=====================
截掉字符串首尾的回車、換行、Tab(16)、垂直Tab(17)、空格等或者手動指定的字符。
可以用來調整字符串格式、判斷非法字符等功能
trim
ltrim -- 去除左側空格
rtrim/chop -- 去除右側空格
實戰 - 過濾字符串收尾空格
=================================
$a = $_GET['param']; // $_GET['param'] = ' asdf ';
$trimmed_a = trim($a);
$ltrimmed_a = ltrim($a);
$rtrimmed_a = rtrim($a);
echo $trimmed_a; // output: "asdf"
echo $ltrimmed_a; // output: "asdf "
echo $rtrimmed_a; // output: " asdf"
實戰 - 去掉首尾不想要的字符
====================================
$jsonp_string = <<<json>
var data = {
"code" : 1, "error" : "System error", "data" : {null}
};
JSON;
var_dump(json_decode($jsonp_string, 1)); // null
$valid_json_string = trim($jsonp_string, 'var data = ;');
var_dump(json_decode($valid_json_string, 1)); // an array
實戰 - 檢測是否只包含想要的字符
========================================
$file_path = 'sina\\..\\..\\weibo';
$trimmed_path = trim(strtolower($file_path),
"abcdefghijklmnopqrstuvwxyz1234567890\\\");// ..\\..
if($trimmed_path){
echo '不安全的路徑!';
}
//對於此例更易讀的實現是
if(!preg_match('/^[a-z0-9\\\\\\\\]+$/iD', $file_path)){
echo '不安全的路徑!';
}
大小寫轉換 - Usage
===========================
strtolower -- 轉化成小寫
strtoupper -- 轉換成大寫
ucfirst -- 讓第一個字符串大寫
ucwords
實戰 - 忽略大小寫比對字符串
======================================
$a = 'Hello World!';
if(strtolower($a) === 'hello world!'){
echo 'Same!';
}else{
echo 'Different!';
}
實戰 - 忽略大小寫比對字符串2
=======================================
$a = 'Hello worlD!';
if(strcasecmp($a, 'hello world!') === 0){
echo 'Same!';
}else{
echo 'Different!';
}
實戰 - 命名風格轉換
=======================================
$class_name = 'sina_weibo_class';
echo implode('', array_map(
'ucfirst',
explode('_', $class_name)
));
//SinaWeiboClass
實戰 - 命名風格轉換2
=======================================
$class_name = 'sina_weibo_class';
function cb_camel_style($match){
return ucfirst($match[2]);
}
echo preg_replace_callback('/(^|_)(\\w)/i',
'cb_camel_style', $class_name);
//SinaWeiboClass
各種轉義 - Usage
=====================
* HTML轉義:
- htmlentities / html_entity_decode --- 轉移所有字符
- htmlspecialchars / htmlspecialchars_decode --- 轉義個別字符 單引號等等。。。。
* URL轉義:
- urlencode / urldecode
- rawurlencode / rawurldecode(Form兼容)
各種轉義 - Usage
=====================
* JSON轉義:
- json_encode / json_decode(注意溢出)
* SQL轉義:
- addslashes / stripslashes(不推薦)
- PDO::quote (推薦)
數組操作
======================
數組是
.. class:: takahashi3
PHP精髓
http://cn.php.net/manual/en/ref.array.php
.. container:: handout
PHP Web開發使用頻率最高的操作類型
數組常見任務
==================
* 訪問
* 遍歷,過濾,排重,映射
* 排序
* 棧/隊列
* 集合
* 通過SPL擴展
實戰 - 索引數組普通操作
==========================
.. code-block:: php
//Index數組
$a = array(5, 4, 3, 2, 1); // 使用前必須先初始化!
$a[] = 0; // 追加
$a[count($a)] = 1; // Index數組追加
$a[0] === 0; // True
if(isset($a[2])) { //判斷一個index是否存在,或可以檢驗數組長度
echo "Array \\$a's length is bigger or equals to 3";
}
unset($a[1]); // 刪除一個key/index
實戰 - 關聯數組普通操作
==========================
.. code-block:: php
$a = array('a' => 'a_value', 'b' => 'b_value'); // 初始化
$a['c'] = 'c_value';
$a[] = 1; // 追加到當前索引序列的最後一個
if(isset($a['b'])) // 判斷一個key是否已經存在且不為null值
echo "\\$a['b'] is exist and not null";
if(array_key_exists('b', $a))
echo "\\$a['b'] is exist and maybe null";
unset($a['b']); //刪除一個值(或值的引用)
$a['b'] === null; //通過array_key_exists判斷仍然為真
實戰 - 更人性化的逗號1
=========================
.. code-block:: php
$fruits = array('bananas', 'apples', 'pears');
$result = 'I love to eat';
foreach($fruits as $fruit){
$result .= ' ' . $fruit . ',';
}
$result = substr($result, 0, -1) . '.';
echo $result;// I love to eat bananas, apples, pears.
實戰 - 更人性化的逗號2
=========================
.. code-block:: php
$fruits = array('bananas', 'apples', 'pears');
$result = 'I love to eat';
$result .= ' ' . implode(', ', $fruits) . '.';
echo $result;
實戰 - 函數多返回值
=======================
.. code-block:: php
function ugly(&$error_desc){
$error_code = 0;
if(error_detected()){
$error_code = 1;
$error_desc = 'not correct';
}
return $error_code;
}
if(ugly($error_desc)){
echo $error_desc;
}
實戰 - 函數多返回值2
=========================
.. code-block:: php
function beauty(){
$error_code = 0;
if(error_detected()){
$error_code = 1;
$error_desc = 'not correct';
}
return array($error, $error_desc);
}
list($error, $error_detail) = beauty();
if($error) echo $error_detail;
數組 - 集合常見操作
=============================
- 合併數組 array_combine array_merge
- 遍歷: array_walk
- 過濾/排重: array_filter
- 映射: array_map
- 聚合: array_reduce
.. class:: takahashi3
foreach
實戰 - 過濾列表空內容並按id排重
================================
.. code-block:: php
$list = array(
array(
'id' => 12345,
'content' => 'something',
'is_deleted' => false,
),
);
實戰 - 過濾列表空內容並按id排重2
================================
.. code-block:: php
$result = array();
foreach($list as $v){
if($v['is_deleted']){
continue;
}
$result[$v['id']] = $v;
}
實戰 - 過濾列表空內容並按id排重3
====================================
.. code-block:: php
function cb_filter_deleted($item){
static $map;
if($map === null) $map = array();
return !(isset($map[$item['id']])||$item['is_deleted']);
}
$result = array_filter($list, 'cb_filter_deleted');
數組操作 - 排序
=======================
.. class:: takahashi3
sort/usort
asort/uasort
ksort/uksort
...
數組操作 - 棧/隊列
========================
.. class:: takahashi2
array_pop / []
array_shift / array_unshift
數組操作 - 集合
======================
.. class:: takahashi3
array_merge / +
array_intersect
array_diff
...
實戰 - 數據合併
=====================
.. code-block:: php
$a = array('a' => '1', 'b' => '2');
$b = array('a' => 'a', 'c' => 'c');
var_export(array_merge($a, $b));
// array('a'=>'a','b'=>'2','c'=>'c');
var_export($a + $b);
// array('a'=>'1','b'=>'2','c'=>'c');
實戰 - 取交集/差集
=========================
.. code-block:: php
$a = array('a' => '1', 'b' => '2');
$b = array('a' => '1', 'c' => 'c');
var_export(array_intersect($a, $b));
// array('a' => '1');
var_export(array_diff($a, $b));
// array('b' => '2');
數組操作 - SPL擴展
===========================
.. code-block:: php
class SinaArray implements ArrayAccess{
public function offsetSet($key, $value){
echo "array's \"{$key}\" set to \"{$value}\".";
}
//需要實現offsetGet, offsetExists, offsetUnset...
}
$a = new SinaArray();
$a['sina'] = 'weibo';
// output: array's "sina" set to "weibo".
大綱
=====================
.. class:: said
字符串常用操作
-----------------
.. class:: said
數組常用操作
------------------
.. class:: next
Cookie和Session
------------------
.. class:: wait
文件上傳
------------------
.. class:: wait
PHP.ini
------------------
Cookie和Session機制
=========================
.. class:: takahashi4
用戶數據傳輸
Cookie
===============
+ 數據在用戶手中
- 易跨服務器共享
+ 消耗帶寬而非服務器運算和存儲資源
+ 長度有限制
+ 過期時間基本由用戶瀏覽器控制
Cookie
===============
+ 數據 **不可信任**
- 但可通過簽名達到數據信任
+ 容易遭受各種攻擊
- 容易被盜取 XSS
- 容易被劫持會話 CSRF
- 容易被注入 Cookie injection
Session
================
+ 可基於Cookie實現
- 通過識別cookie中的session id實現
+ 數據在服務器上
- 需要公共存儲方可實現跨服務器共享
+ 消耗服務器運算/存儲資源而非帶寬
+ 數據 *基本* 可信任
- 需要防止session id洩漏
+ 不容易遭受攻擊
- 在session id被盜或者被猜測的情況下,仍可能被劫持
Session (2)
================
+ 長度取決於服務器資源
+ PHP代碼中需要開啟 session 支持
+ 默認的Session機制中的過期時間不甚靠譜
+ 存儲機制可 擴展_
.. _擴展: http://cn.php.net/manual/en/book.session.php
大綱
=====================
.. class:: said
字符串常用操作
-----------------
.. class:: said
數組常用操作
------------------
.. class:: said
Cookie和Session
------------------
.. class:: next
文件上傳
------------------
.. class:: wait
PHP.ini
------------------
文件上傳
=======================
.. class:: takahashi3
漏洞簍子
完全版: http://cn.php.net/manual/en/features.file-upload.php
RFC-1867: http://www.ietf.org/rfc/rfc1867.txt
文件上傳 - Usage
======================
.. code-block:: html
<form>/<json>
Send this file:
文件上傳 - Usage
======================
.. code-block:: php
$uploaddir = '/var/www/uploads/';
$uploadfile = $uploaddir . basename($_FILES['userfile']['name']);
//TODO 需要做更多的安全檢測,包括文件大小限制
if(move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)){
echo "File is valid, and was successfully uploaded.\\n";
} else {
echo "Possible file upload attack!\\n";
}
文件上傳 - Usage - 安全檢查
================================
.. code-block:: php
$dot_pos = strrpos($_FILES['userfile']['name'], '.');
$file_extname = ($dot_pos !== false)
? strtolower(substr($file_name, $dot_pos + 1))
: '';
$avail_exts = array('jpg', 'jpeg', 'gif', 'png');
if(!in_array($file_extname, $avail_exts)){
echo 'wrong file type';
return;
}
//可能需要對上傳的文件的二進制內容做更進一步判斷
//如gif必須以ascii:gif89a 開頭等
文件上傳 - Usage - 安全檢查2
================================
.. code-block:: php
$file_basename = basename($_FILES['userfile']['name']);
if(preg_match('/^\\w+$/iD', $file_basename){
$uploadfile = "{$file_basename}.{$file_extname}";
}
//簡單粗暴的方法:
$uploadfile = microtime(1).random(1, 999).".{$file_extname}";
文件上傳 - 限制
============================
+ 運行時限制(Post/Request/Memory)
+ 請求執行時間
+ 長連接導致容易受DOS攻擊
+ 易出現安全問題
+ 多服務器/跨IDC同步以及備份
+ 帶寬與連接密集型需要專門優化web服務器
+ 需仔細規劃上傳目錄權限和訪問方法
文件上傳 - 限制
============================
.. class:: takahashi2
Cloud is the God!
+ 雲計算可以解決大部分問題
+ 仍有請求執行時間限制
+ 備份同樣成問題(S3除外)
+ 易遭受DOS攻擊(資源限額耗盡)
大綱
=====================
.. class:: said
字符串常用操作
-----------------
.. class:: said
數組常用操作
------------------
.. class:: said
Cookie和Session
------------------
.. class:: said
文件上傳
------------------
.. class:: next
PHP.ini
------------------
PHP.ini
========================
.. class:: takahashi3
PHP的閘門
完全參考: http://cn.php.net/manual/en/ini.php
PHP.ini - 設置方法
==========================
.. container:: handout
PHP.ini對於CGI/CLI可分開,其中CGI打了fpm補丁時可以再次指定其位置;而CLI可以在運行時指定
+ 位置:
- 通常為安裝目錄,具體需看編譯選項
+ 格式:
- INI
+ 生效:
- 一般需重啟PHP進程,但如果以fcgi模式且打了fpm補丁,則可以不重啟,reload即可
PHP.ini - 設置方法
==========================
+ 其他:
- 命令行下可以通過php -c 來指定ini位置或php -d 來設置某一項的值
- 運行時可以使用 ini_set() / ini_get()
- 也可以使用 `Apache httpd.conf中設置`_
.. _apache httpd.conf中設置: http://ca3.php.net/manual/en/configuration.changes.php
PHP.ini - 格式
==========================
.. code-block:: ini
; allow_call_time_pass_reference
; Default Value: On
; Development Value: Off
; Production Value: Off
allow_call_time_pass_reference = Off
PHP.ini - 常用選項
========================
.. code-block:: ini
expose_php = On
; 大多數情況下,生產服務器應該設置為Off
error_reporting = E_ALL & ~E_DEPRECATED & ~E_NOTICE
; 生產模式一般可以關閉E_NOTICE以防止log過大
display_errors = Off
log_errors = On
error_log = /var/log/php_errors.log
include_path = ".:/usr/share/php"
; 沒有把 . 加入include_path導致在程序裡無法按照相對路徑require
PHP.ini - 常用選項
===============================
.. code-block:: ini
max_execution_time = 30
memory_limit = 128M
; 如果128M還不夠用,請檢查程序邏輯
post_max_size = 8M
register_globals = Off
magic_quotes_gpc = Off
magic_quotes_runtime = Off
PHP.ini - 常用選項
===============================
.. code-block:: ini
allow_url_fopen = On
allow_url_include = Off
default_socket_timeout = 60
date.timezone = Asia/Chongqing
extension=msql.so
課後作業
===================
1. 通讀字符串所有函數手冊;
#. 通讀數組函數所有手冊;
#. 實際操作字符串所有的函數及嘗試其參數組合(可選參數可以忽略);
#. 實際操作數組所有的函數及嘗試其參數組合(可選參數可以忽略);
#. 完成一個文件上傳頁面示例;
#. 修改php.ini中的error_reporting參數進行錯誤控制;
#. 安裝一個php擴展,如memcache或者 pdo_mysql,然後通過php_info()/php -i檢查是否安裝成功。
Thanks
=================
.. class:: takahashi4
Thanks!
Q & A
=================
.. class:: takahashi4
Questions?
str_replace() 過濾危險字符
list() 函數的學習
調試追蹤 debug_backtrace debug_print_backtrace
mysql5.1 的一個bug, select * from user where id in(1,'2'); 這樣的語句在5.1裡面就相當於沒有索引了 會全文檢索,效率可就差了,修改 in (1,2) 或者('1','2')
var_export()
文件上傳的時候 input type=file form的type enctype ...形式
=== 比較的是兩個變量的本身字符 和 類型
__call() __callStatic() 做冗錯機制比較好
================
PHP應用技巧(二)
================
:Email: [email protected]
調查
===========================================
- 知道PHP中INT的最大值
- 瞭解GBK和UTF8
- 使用過mbstring
- PHP中異常與錯誤的區別
目錄
===========================================
- PHP版本比較及特殊流程語句寫法
- 數據類型
- 手冊的使用
- 多字節(中文)字符串處理
- PHP錯誤處理
- 常見錯誤
PHP版本比較
===========================================
============ ===== ======= =======
項目 PHP4 PHP5.2 PHP5.3
============ ===== ======= =======
面向對象支持 差 好 極好
類與對象 是 是 是
訪問控制 否 是 是
析構方法 否 是 是
對象迭代 否 是 是
對象自動加載 否 是 是
命名空間 否 否 是
匿名函數 否 否 是
CGI進程名稱 php php-cgi php-cgi
============ ===== ======= =======
如何選擇PHP版本
===========================================
x.y.z
---------------------------
- x.y 儘量與生服務器一致或高於服務器版本
- z 儘可能的選擇最高版本(非RC/Beta)
有問題的PHP版本
---------------------------
- PHP5.3.5 源代碼被入侵
- ver < PHP5.2.5 json_decode BUG嚴重
PHP特殊的流程控制寫法
===========================================
- switch...case 中可以使用運算語句
- break x 可以跳出多層循環
- if...endif(while/for/foreach等同樣適用) 寫法
- 可變變量 $$a
- 中文變量 $用戶名 = 'xxx';
數據類型
==========================================
弱類型 不等於 無類型
---------------------
======== =========================
int $var = 1;
float $var = 1.0;
string $var = '1';
boolean $var = true;
array $var = array(1,2,3);
Object $var = new stdClass;
NULL $var = null;
Resource $var = fopen('xxx', 'r');
======== =========================
數據類型間的轉換
==========================================
- (int), (integer) - 轉換為 整型(integer)
- (bool), (boolean) - 轉換為 布爾型(boolean)
- (float), (double), (real) - 轉換為 浮點型(float)
- (string) - 轉換為 字符串(string)
- (binary) - 轉換為二進制 字符串(string) (PHP 6)
- (array) - 轉換為 數組(array)
- (object) - 轉換為 對象(object)
- (unset) - 轉換為 NULL (PHP 5)
例:$var = (int)$var;
INT長度限制
==========================================
- 查看INT的最大值可以使用常量(PHP_INT_MAX)
- 32位操作系統INT的最大值為:2147483647
- 64位操作系統INT的最大值為:9223372036854775807
- 面對巨大的整型數字(如UID/微博ID),建議使用字符串表示
數據的比較
==========================================
$a == $b 等於
$a === $b 全等(PHP 4 引進,同時比較類型)
PHP弱類型的底層實現
==========================================
- Zend/zend.h
- struct _zval_struct
- typedef union _zvalue_value
手冊的使用
==========================================
- 手冊是工具
- 手冊是最好的學習資料
- PHP手冊在線/下載地址: http://php.net/docs.php
如何利用手冊查找函數
==========================================
#) 利用索引 **猜**
#) 利用相關函數和索引定位目錄 **找**
#) 利用目錄分類一層一層 **找**
多字節編碼
===========================================
為什麼要用多字節編碼?
-------------------------------------------
處理多字節編碼的字符串需注意些什麼?
-------------------------------------------
如何方便的處理多字節編碼字符串?
-------------------------------------------
多字節編碼(GBK)
===========================================
字符有一字節和雙字節,00–7F(0-127)範圍是一位,和ASCII保持一致,此範圍內嚴格上說有96個文字和32個控制符號。
之後的雙字節中,前一字節是雙字節的第一位。
總體上說第一字節的範圍是81–FE(也就是不含80和FF),第二字節的一部分領域在40–FE,其他領域在80–FE。
參考資料: http://zh.wikipedia.org/wiki/GBK
多字節編碼(UTF-8)
===========================================
- 0xxxxxxx
- 110xxxxx 10xxxxxx
- 1110xxxx 10xxxxxx 10xxxxxx
- 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
- 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
- 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
參考資料: http://zh.wikipedia.org/wiki/UTF8
多字節(中文)字符串處理
==========================================
- 設置默認字符集: mb_internal_encoding('utf-8');
- 獲取字數: mb_strlen();
- 按字數截取字符串: mb_substr();
- 獲取字符寬度: mb_strwidth();
- 按字符寬度截取: mb_strimwidth();
- 按字節數截取: mb_strcut();
- 編碼轉換:mb_convert_encoding();
PHP錯誤處理
==========================================
控制錯誤的輸出
----------------------------------
自定義錯誤處理程序
----------------------------------
出錯後如何定位出出錯的地方
----------------------------------
PHP的錯誤級別
==========================================
影響PHP錯誤輸出的相關配置
--------------------------
#) php.ini
#) error_reporting
#) display_errors
#) runtime php code
#) error_reporting()
#) ini_set()
error_reporting 配置
==========================================
- 配置值參考: http://hk.php.net/manual/zh/errorfunc.constants.php
- 配置方法參考:
- E_ALL
- E_ALL & ~E_NOTICE
- E_ALL | E_STRICT
- E_ALL | E_STRICT & ~E_NOTICE
自定義錯誤處理程序
==========================================
- 自定義錯誤函數 set_error_handler
- 自定義異常處理 set_exception_handler
- 還原系統默認處理錯誤函數 restore_error_handler
- 還原系統默認處理異常 restore_exception_handler
- 拋出用戶自定義錯誤 trigger_error (E_USER_*)
調試追蹤
==========================================
- 究竟外層是怎麼調用到底層方法的?
- debug_backtrace
- debug_print_backtrace
- 有沒有更好的辦法?
- 結合 set_error_handler,出錯後自動追蹤
常見錯誤
==========================================
語言本身的誤導性
--------------------------------
寫錯的語句仍可解析為正確語句
--------------------------------
手冊的不完整性
--------------------------------
編寫PHP代碼不嚴謹
--------------------------------
……
--------------------------------
常見錯誤(頭已輸出)
==========================================
**Cannot modify header information - headers already sent by xxx**
- 發送header(含cookie)前不要有任何輸出
- 注意 *
- 如果當前文件只有PHP代碼,可不寫 *?>*
- 注意是否有utf8 BOM頭
常見錯誤(==)
==========================================
.. code-block:: php
$a = 'weibo';
if($a = 't') {
echo 'true';
} else {
echo 'false';
}
//結果輸出true
常見錯誤(優先級)
==========================================
.. code-block:: php
$result = (int) 0.1+0.9;
echo $result;
//結果輸出0.9
常見錯誤(分號)
==========================================
.. code-block:: php
$var = false;
if($var);
{
echo 'ok';
}
//以上程序會輸出ok
常見錯誤(類型轉換後的值)
==========================================
.. code-block:: php
$a = false;
$a = (array)$a;
if($a) {
echo 'true';
} else {
echo 'false';
}
//結果輸出true
常見錯誤(丟失的數組KEY)
==========================================
.. code-block:: php
$arr = array(
110 => 'weibo',
111 => 'event',
112 => 'q',
113 => 'screen',
114 => 'service',
);
$result = array_slice($arr, 1, 3);
print_r($result);
常見錯誤(PHP BUG)
==========================================
PHP BUG: http://bugs.php.net/
謝謝大家
============
:Author: @李棖煊 (4061)
:Email: [email protected]
作業
==========================================
- 閱讀手冊mbstring部分
- 嘗試使用mbstring函數
- 嘗試調節各種錯誤級別設置
- 瞭解 https://bugs.php.net/
- 瞭解UTF8編碼 http://zh.wikipedia.org/wiki/UTF8 (可選)
- 編寫一個自定義錯誤函數,將錯誤轉換為異常 (可選)
閱讀更多 老公城獅
的文章
關鍵字:
Scheme
基礎知識
PHP
相關文章: