function utf8_substr( $str , $start , $length=null ){ // 先正常截取一遍. $res = substr( $str , $start , $length ); $strlen = strlen( $str ); /* 接著判斷頭尾各6位元組是否完整(不殘缺) */ // 如果參數start是正數 if ( $start >= 0 ){ // 往前再截取大約6位元組 $next_start = $start + $length; // 初始位置 $next_len = $next_start + 6 <= $strlen ? 6 : $strlen - $next_start; $next_segm = substr( $str , $next_start , $next_len ); // 如果第1位元組就不是 完整字元的首位元組, 再往後截取大約6位元組 $prev_start = $start - 6 > 0 ? $start - 6 : 0; $prev_segm = substr( $str , $prev_start , $start - $prev_start ); } // start是負數 else{ // 往前再截取大約6位元組 $next_start = $strlen + $start + $length; // 初始位置 $next_len = $next_start + 6 <= $strlen ? 6 : $strlen - $next_start; $next_segm = substr( $str , $next_start , $next_len ); // 如果第1位元組就不是 完整字元的首位元組, 再往後截取大約6位元組. $start = $strlen + $start; $prev_start = $start - 6 > 0 ? $start - 6 : 0; $prev_segm = substr( $str , $prev_start , $start - $prev_start ); } // 判斷前6位元組是否符合utf8規則 if ( preg_match( '@^([x80-xBF]{0,5})[xC0-xFD]?@' , $next_segm , $bytes ) ){ if ( !empty( $bytes[1] ) ){ $bytes = $bytes[1]; $res .= $bytes; } } // 判斷後6位元組是否符合utf8規則 $ord0 = ord( $res[0] ); if ( 128 <= $ord0 && 191 >= $ord0 ){ // 往後截取 , 並加在res的前面. if ( preg_match( '@[xC0-xFD][x80-xBF]{0,5}$@' , $prev_segm , $bytes ) ){ if ( !empty( $bytes[0] ) ){ $bytes = $bytes[0]; $res = $bytes . $res; } } } return $res; } |