<?php interface TStringFunc { public function substr($str, $start, $length = null); public function strlen($str); } class TStringFunc_Core implements TStringFunc { public function substr($str, $start, $length = null) { // specifying a null $length would return an empty string if ($length === null) { return substr($str, $start); } return substr($str, $start, $length); } public function strlen($str) { return strlen($str); } } class TStringFunc_Mbstring implements TStringFunc { public function substr($str, $start, $length = null) { /** * We need to set the charset parameter, which is the second * optional parameter and the first optional parameter can't * be null or false as a "magic" value because that would * cause an empty string to be returned, so we need to * actually calculate the proper length value. */ if ($length === null) { $length = $this->strlen($str) - $start; } return mb_substr($str, $start, $length, '8bit'); } public function strlen($str) { return mb_strlen($str, '8bit'); } } class TStringFuncFactory { private static $_instance; /** * Get the Singleton instance of TStringFunc implementation that is * compatible with the current system's mbstring.func_overload settings. * * @return TStringFunc */ public static function create() { if (!self::$_instance) { self::_setInstance(); } return self::$_instance; } private static function _setInstance() { /** * Cannot use str* functions for byte counting because multibyte * characters will be read a single bytes. * * See: http://us.php.net/manual/en/mbstring.overload.php */ if (ini_get('mbstring.func_overload') & 2) { self::$_instance = new TStringFunc_Mbstring(); } /** * mbstring is not installed or does not have function overloading * of the str* functions enabled so use PHP core str* functions for * byte counting. */ else { self::$_instance = new TStringFunc_Core(); } } }