字串截取是後端輸出摘要、列表標題常見需求。Laravel 內建 Str::limit()、CodeIgniter 提供 word_limiter(),兩者實作邏輯迥異:前者以字元寬度(支援中文全形)精準截斷,後者以單字邊界(英文單字)為單位。本文對照原始碼、解析差異、提供統一介面封裝建議,助你跨框架移植或自建通用工具函式。
Str::limit()(Illuminate\Support\Str)// 簡化版核心邏輯
public static function limit(string $value, int $limit = 100, string $end = '...'): string
{
if (mb_strwidth($value, 'UTF-8') <= $limit) {
return $value;
}
// mb_strimwidth 按「視覺寬度」截取:半形=1、全形=2
return rtrim(mb_strimwidth($value, 0, $limit, '', 'UTF-8')) . $end;
}
word_limiter()if (!function_exists('word_limiter')) {
function word_limiter(string $str, int $limit = 100, string $endChar = '…'): string
{
if (trim($str) === '') return $str;
// 正則匹配前 N 個「單字」(非空白序列)
preg_match('/^\s*+(?:\S++\s*+){1,' . (int)$limit . '}/', $str, $matches);
// 若未截斷(原字串長度等於匹配長度),不加尾碼
if (strlen($str) === strlen($matches[0])) {
$endChar = '';
}
return rtrim($matches[0]) . $endChar;
}
}
| 維度 | Laravel Str::limit | CodeIgniter word_limiter |
|---|---|---|
| 計數單位 | 視覺寬度(mb_strwidth) | 單字數量(正則 \S+) |
| 中文處理 | 每個中文字算 2 寬度,精準控制顯示寬度 | 視為一個「單字」,若限制 10 個單字,10 個中文字即達標 |
| 截斷位置 | 可能在字元中間(需 rtrim 清理) | 單字邊界,不會斷字 |
| 適用場景 | 中英混排、固定寬度版面、摘要顯示 | 英文為主、按單字數截取、SEO 友善摘要 |
| 效能 | mbstring 函式,極快 | 正則匹配,稍慢但可忽略 |
| 多位元組安全 | 完整支援 UTF-8 | 依賴 PCRE UTF-8 模式(需 u 修飾符) |
$text = 'Laravel 框架優雅簡潔,適合快速開發應用。'; echo 'Laravel limit(20): ' . \Illuminate\Support\Str::limit($text, 20) . "\n"; // 輸出:Laravel 框架優雅… (視覺寬度 20,含尾碼) echo 'CI word_limiter(8): ' . word_limiter($text, 8) . "\n"; // 輸出:Laravel 框架優雅簡潔,適合快速… (前 8 個單字)
專案若同時維護 Laravel 與 CI 代碼,建議建立共用 StringHelper:
<?php
namespace App\Helpers;
class StringHelper
{
/** 按視覺寬度截取(中文友善) */
public static function byWidth(string $str, int $width, string $suffix = '...'): string
{
if (mb_strwidth($str, 'UTF-8') <= $width) return $str;
return rtrim(mb_strimwidth($str, 0, $width, '', 'UTF-8')) . $suffix;
}
/** 按單字數截取(英文友善) */
public static function byWords(string $str, int $words, string $suffix = '…'): string
{
if (trim($str) === '') return $str;
preg_match('/^\s*+(?:\S++\s*+){1,' . (int)$words . '}/u', $str, $m);
if (strlen($str) === strlen($m[0])) $suffix = '';
return rtrim($m[0]) . $suffix;
}
/** 智能截取:中文優先用寬度,英文優先用單字 */
public static function smartLimit(string $str, int $limit, string $suffix = '...'): string
{
// 簡單啟發式:若含中文(\p{Han})用寬度,否則用單字
if (preg_match('/\p{Han}/u', $str)) {
return self::byWidth($str, $limit, $suffix);
}
return self::byWords($str, $limit, $suffix);
}
}
若輸入含 HTML 標籤,直接截取會破壞結構。建議流程:
strip_tags() 移除標籤(或保留允許標籤)html_entity_decode() 還原實體htmlspecialchars() 防 XSS或使用成熟套件:htmlburger/cut-html、spatie/html-element。
Str::limit:視覺寬度導向,中英混排首選,mb_strimwidth 核心。word_limiter:單字邊界導向,英文內容首選,正則核心。掌握兩大框架截取邏輯本質,讓你在遷移、整合、自建工具時遊刃有餘,輸出優雅且安全的字串摘要。