文字列を規定の桁数になるまで任意の文字で埋めるために、PHPのstr_pad()を使うことがあるかと思います。
ただし、以下のようなマルチバイト文字をstr_pad()にかけて指定した桁数の文字列を出力しようとしても、バイト数で計算されるため意図した通りに出力されません。
echo str_pad('東京', 8, '●', STR_PAD_RIGHT).PHP_EOL;
echo str_pad('名古屋', 8, '●', STR_PAD_LEFT).PHP_EOL;
echo str_pad('大阪', 8, '●', STR_PAD_BOTH);
出力結果は以下の通り…
8桁の文字列が出力されてほしいところですが、先に述べたように意図した通りになりません。
その上、文字化けになってしまいました。
東京�
名古屋
�大阪�
そこで、マルチバイト文字にも対応したmb_str_pad()を作成しました。
使い方はstr_pad()とほとんど変わりありませんが、バイト数ではなく文字数で計算するようになっています。
/**
* 文字列を固定長の他の文字列で埋める(マルチバイト対応)
*
* @param string $input 対象の文字列
* @param int $pad_len 埋める文字数
* @param string $pad_str 埋める文字列
* @param int $pad_type 埋め方(STR_PAD_RIGHT, STR_PAD_LEFT, STR_PAD_BOTH)
* @param string $encoding 文字列のエンコーディング
* @return string
*/
function mb_str_pad($input, $pad_len, $pad_str=' ', $pad_type=STR_PAD_RIGHT, $encoding=null)
{
if (!$encoding || strtolower($encoding) == 'auto') {
$encoding = mb_internal_encoding();
}
$input_len = mb_strlen($input, $encoding);
$pad_str_len = mb_strlen($pad_str, $encoding);
$target_len = $pad_len - $input_len;
if (!$input_len || !$pad_str_len || $target_len <= 0) {
return $input;
}
if ($pad_type === STR_PAD_BOTH) {
$target_len /= 2;
}
$repeat = str_repeat($pad_str, ceil($target_len / $pad_str_len));
if ($pad_type === STR_PAD_BOTH || $pad_type === STR_PAD_LEFT) {
$left = mb_substr($repeat, 0, floor($target_len), $encoding);
} else {
$left = '';
}
if ($pad_type === STR_PAD_BOTH || $pad_type === STR_PAD_RIGHT) {
$right = mb_substr($repeat, 0, ceil($target_len), $encoding);
} else {
$right = '';
}
return $left.$input.$right;
}
先ほどと同じ文字列を、mb_str_pad()にかけてみます。
echo mb_str_pad('東京', 8, '●', STR_PAD_RIGHT).PHP_EOL;
echo mb_str_pad('名古屋', 8, '●', STR_PAD_LEFT).PHP_EOL;
echo mb_str_pad('大阪', 8, '●', STR_PAD_BOTH);
出力結果は以下の通りです。
東京●●●●●●
●●●●●名古屋
●●●大阪●●●
今度は意図した通りの結果になりました!