こんにちは!今回は、PHPの標準関数であるstrlen()について詳しく解説していきます。文字列の長さを取得する、最も基本的で重要な関数の一つです!
strlen関数とは?
strlen()関数は、文字列のバイト数(長さ)を返す関数です。
シンプルですが、バリデーション、文字数制限、データ処理など、あらゆる場面で使用される基本的な関数です!
基本的な構文
strlen(string $string): int
- $string: 長さを取得する文字列
- 戻り値: 文字列のバイト数(整数)
基本的な使用例
シンプルな使用例
// 英数字の長さ
$text = "Hello";
echo strlen($text) . "\n"; // 5
// 空文字列
$empty = "";
echo strlen($empty) . "\n"; // 0
// 数値は文字列に変換される
$number = 12345;
echo strlen($number) . "\n"; // 5
// スペースもカウントされる
$withSpaces = "Hello World";
echo strlen($withSpaces) . "\n"; // 11
日本語(マルチバイト文字)の扱い
// 日本語文字列
$japanese = "こんにちは";
echo strlen($japanese) . "\n"; // 15(UTF-8では1文字3バイト)
// mb_strlen()との違い
echo mb_strlen($japanese) . "\n"; // 5(文字数)
// 英数字と日本語の混在
$mixed = "Hello世界";
echo strlen($mixed) . "\n"; // 11(5 + 6バイト)
echo mb_strlen($mixed) . "\n"; // 7(文字数)
NULL文字の扱い
// NULL文字を含む文字列
$withNull = "Hello\0World";
echo strlen($withNull) . "\n"; // 11(NULL文字もカウント)
// 表示は途中で切れる
echo $withNull . "\n"; // Hello(NULL以降は表示されない)
実践的な使用例
例1: 入力バリデーション
class InputValidator {
/**
* 文字列長のチェック
*/
public static function validateLength($input, $min, $max) {
$length = strlen($input);
if ($length < $min) {
return [
'valid' => false,
'error' => "最低{$min}文字必要です(現在: {$length}文字)"
];
}
if ($length > $max) {
return [
'valid' => false,
'error' => "最大{$max}文字までです(現在: {$length}文字)"
];
}
return ['valid' => true];
}
/**
* パスワードの強度チェック
*/
public static function validatePassword($password) {
$length = strlen($password);
if ($length < 8) {
return [
'valid' => false,
'error' => 'パスワードは8文字以上必要です',
'strength' => 'weak'
];
}
if ($length < 12) {
$strength = 'medium';
} elseif ($length < 16) {
$strength = 'strong';
} else {
$strength = 'very_strong';
}
return [
'valid' => true,
'length' => $length,
'strength' => $strength
];
}
/**
* 空文字列チェック
*/
public static function isEmpty($input) {
return strlen(trim($input)) === 0;
}
/**
* ユーザー名のバリデーション
*/
public static function validateUsername($username) {
$length = strlen($username);
if ($length < 3) {
return [
'valid' => false,
'error' => 'ユーザー名は3文字以上必要です'
];
}
if ($length > 20) {
return [
'valid' => false,
'error' => 'ユーザー名は20文字以内にしてください'
];
}
if (!preg_match('/^[a-zA-Z0-9_]+$/', $username)) {
return [
'valid' => false,
'error' => 'ユーザー名は英数字とアンダースコアのみ使用できます'
];
}
return ['valid' => true];
}
}
// 使用例
$result = InputValidator::validateLength("test", 5, 20);
print_r($result);
// valid => false, error => "最低5文字必要です(現在: 4文字)"
$result = InputValidator::validatePassword("pass");
print_r($result);
// valid => false, error => "パスワードは8文字以上必要です"
$result = InputValidator::validatePassword("SecurePassword123");
print_r($result);
// valid => true, length => 17, strength => very_strong
var_dump(InputValidator::isEmpty(" ")); // true
var_dump(InputValidator::isEmpty("test")); // false
例2: テキストの切り詰め
class TextTruncator {
/**
* 指定長で切り詰め
*/
public static function truncate($text, $maxLength, $suffix = '...') {
if (strlen($text) <= $maxLength) {
return $text;
}
$truncated = substr($text, 0, $maxLength - strlen($suffix));
return $truncated . $suffix;
}
/**
* 単語の途中で切らない切り詰め
*/
public static function truncateWords($text, $maxLength, $suffix = '...') {
if (strlen($text) <= $maxLength) {
return $text;
}
$truncated = substr($text, 0, $maxLength - strlen($suffix));
// 最後のスペースを探す
$lastSpace = strrpos($truncated, ' ');
if ($lastSpace !== false && $lastSpace > $maxLength * 0.7) {
$truncated = substr($truncated, 0, $lastSpace);
}
return $truncated . $suffix;
}
/**
* 文の途中で切らない切り詰め
*/
public static function truncateSentences($text, $maxLength) {
if (strlen($text) <= $maxLength) {
return $text;
}
$truncated = substr($text, 0, $maxLength);
// 最後の句点を探す
$lastPeriod = max(
strrpos($truncated, '.'),
strrpos($truncated, '。')
);
if ($lastPeriod !== false && $lastPeriod > $maxLength * 0.5) {
return substr($text, 0, $lastPeriod + 1);
}
return self::truncateWords($text, $maxLength);
}
/**
* 中央を省略
*/
public static function truncateMiddle($text, $maxLength) {
if (strlen($text) <= $maxLength) {
return $text;
}
$ellipsis = '...';
$sideLength = floor(($maxLength - strlen($ellipsis)) / 2);
$start = substr($text, 0, $sideLength);
$end = substr($text, -$sideLength);
return $start . $ellipsis . $end;
}
}
// 使用例
$longText = "This is a very long text that needs to be truncated for display purposes.";
echo TextTruncator::truncate($longText, 30) . "\n";
// This is a very long text th...
echo TextTruncator::truncateWords($longText, 30) . "\n";
// This is a very long text...
$path = "/very/long/path/to/some/file/document.pdf";
echo TextTruncator::truncateMiddle($path, 25) . "\n";
// /very/long/...ument.pdf
例3: データサイズの表示
class DataSizeFormatter {
/**
* バイト数を人間が読みやすい形式に変換
*/
public static function formatBytes($bytes, $precision = 2) {
$units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
$unitIndex = 0;
while ($bytes >= 1024 && $unitIndex < count($units) - 1) {
$bytes /= 1024;
$unitIndex++;
}
return number_format($bytes, $precision) . ' ' . $units[$unitIndex];
}
/**
* 文字列のバイト数を表示
*/
public static function getStringSize($string) {
$bytes = strlen($string);
return [
'bytes' => $bytes,
'formatted' => self::formatBytes($bytes)
];
}
/**
* ファイルサイズの推定
*/
public static function estimateFileSize($content) {
$size = strlen($content);
return [
'bytes' => $size,
'formatted' => self::formatBytes($size),
'kilobytes' => round($size / 1024, 2),
'megabytes' => round($size / (1024 * 1024), 2)
];
}
}
// 使用例
$text = str_repeat("Hello World! ", 1000);
print_r(DataSizeFormatter::getStringSize($text));
/*
Array (
[bytes] => 13000
[formatted] => 12.70 KB
)
*/
$largeData = str_repeat("A", 1024 * 1024 * 5); // 5MB
print_r(DataSizeFormatter::estimateFileSize($largeData));
/*
Array (
[bytes] => 5242880
[formatted] => 5.00 MB
[kilobytes] => 5120
[megabytes] => 5
)
*/
例4: プログレスバーの表示
class ProgressBar {
private $total;
private $width;
public function __construct($total, $width = 50) {
$this->total = $total;
$this->width = $width;
}
/**
* プログレスバーを描画
*/
public function display($current) {
$percentage = ($current / $this->total) * 100;
$filled = round(($current / $this->total) * $this->width);
$empty = $this->width - $filled;
$bar = str_repeat('=', $filled) . str_repeat(' ', $empty);
// バーの長さを確認
$barLength = strlen($bar);
$display = sprintf(
"\r[%s] %3d%% (%d/%d)",
$bar,
(int)$percentage,
$current,
$this->total
);
echo $display;
if ($current >= $this->total) {
echo "\n";
}
}
/**
* 推定残り時間付き
*/
public function displayWithETA($current, $startTime) {
$percentage = ($current / $this->total) * 100;
$filled = round(($current / $this->total) * $this->width);
$empty = $this->width - $filled;
$bar = str_repeat('=', $filled) . str_repeat(' ', $empty);
$elapsed = time() - $startTime;
if ($current > 0) {
$rate = $current / $elapsed;
$remaining = ($this->total - $current) / $rate;
$eta = sprintf('%02d:%02d:%02d',
floor($remaining / 3600),
floor(($remaining % 3600) / 60),
$remaining % 60
);
} else {
$eta = '--:--:--';
}
$display = sprintf(
"\r[%s] %3d%% ETA: %s",
$bar,
(int)$percentage,
$eta
);
// 表示がターミナル幅を超えないようチェック
if (strlen($display) > 80) {
$display = substr($display, 0, 80);
}
echo $display;
if ($current >= $this->total) {
echo "\n";
}
}
}
// 使用例(シミュレーション)
/*
$progress = new ProgressBar(100);
$startTime = time();
for ($i = 0; $i <= 100; $i++) {
$progress->displayWithETA($i, $startTime);
usleep(50000); // 0.05秒待機
}
*/
例5: 文字列の統計情報
class StringStatistics {
/**
* 文字列の統計情報を取得
*/
public static function analyze($text) {
$length = strlen($text);
$trimmedLength = strlen(trim($text));
$wordCount = str_word_count($text);
$lineCount = substr_count($text, "\n") + 1;
$alphaCount = preg_match_all('/[a-zA-Z]/', $text);
$digitCount = preg_match_all('/[0-9]/', $text);
$spaceCount = substr_count($text, ' ');
$punctuationCount = preg_match_all('/[.,!?;:]/', $text);
return [
'total_length' => $length,
'trimmed_length' => $trimmedLength,
'word_count' => $wordCount,
'line_count' => $lineCount,
'alpha_count' => $alphaCount,
'digit_count' => $digitCount,
'space_count' => $spaceCount,
'punctuation_count' => $punctuationCount,
'average_word_length' => $wordCount > 0 ? round($alphaCount / $wordCount, 2) : 0
];
}
/**
* 読了時間を推定
*/
public static function estimateReadingTime($text, $wordsPerMinute = 200) {
$wordCount = str_word_count($text);
$minutes = ceil($wordCount / $wordsPerMinute);
return [
'word_count' => $wordCount,
'minutes' => $minutes,
'formatted' => $minutes . '分'
];
}
/**
* 文字列の密度を計算
*/
public static function calculateDensity($text) {
$length = strlen($text);
if ($length === 0) {
return 0;
}
$nonSpaceLength = strlen(str_replace(' ', '', $text));
return round(($nonSpaceLength / $length) * 100, 2);
}
}
// 使用例
$article = <<<TEXT
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco.
TEXT;
print_r(StringStatistics::analyze($article));
/*
Array (
[total_length] => 183
[trimmed_length] => 181
[word_count] => 26
[line_count] => 3
[alpha_count] => 142
[digit_count] => 0
[space_count] => 25
[punctuation_count] => 3
[average_word_length] => 5.46
)
*/
print_r(StringStatistics::estimateReadingTime($article));
/*
Array (
[word_count] => 26
[minutes] => 1
[formatted] => 1分
)
*/
echo "密度: " . StringStatistics::calculateDensity($article) . "%\n";
// 密度: 86.34%
例6: パスワード強度メーター
class PasswordStrengthMeter {
/**
* パスワード強度を計算
*/
public static function calculateStrength($password) {
$length = strlen($password);
$score = 0;
// 長さによるスコア
if ($length >= 8) $score += 20;
if ($length >= 12) $score += 20;
if ($length >= 16) $score += 20;
// 文字の種類によるスコア
if (preg_match('/[a-z]/', $password)) $score += 10;
if (preg_match('/[A-Z]/', $password)) $score += 10;
if (preg_match('/[0-9]/', $password)) $score += 10;
if (preg_match('/[^a-zA-Z0-9]/', $password)) $score += 10;
// 強度レベルを判定
if ($score < 40) {
$level = 'weak';
$label = '弱い';
} elseif ($score < 70) {
$level = 'medium';
$label = '普通';
} elseif ($score < 90) {
$level = 'strong';
$label = '強い';
} else {
$level = 'very_strong';
$label = '非常に強い';
}
return [
'length' => $length,
'score' => $score,
'level' => $level,
'label' => $label,
'percentage' => min(100, $score)
];
}
/**
* 強度メーターを表示
*/
public static function displayMeter($password) {
$strength = self::calculateStrength($password);
$barLength = 30;
$filled = round(($strength['percentage'] / 100) * $barLength);
$empty = $barLength - $filled;
$bar = str_repeat('█', $filled) . str_repeat('░', $empty);
return sprintf(
"[%s] %s (%d%%)",
$bar,
$strength['label'],
$strength['percentage']
);
}
}
// 使用例
$passwords = [
'pass',
'password',
'Password1',
'P@ssw0rd123',
'MyV3ry$tr0ng&P@ssw0rd!'
];
foreach ($passwords as $password) {
echo "パスワード: {$password}\n";
echo StringStatistics::displayMeter($password) . "\n";
print_r(PasswordStrengthMeter::calculateStrength($password));
echo "\n";
}
例7: CSVデータの検証
class CsvValidator {
/**
* CSVフィールドの長さを検証
*/
public static function validateFieldLengths($csvLine, $maxLengths) {
$fields = str_getcsv($csvLine);
$errors = [];
foreach ($fields as $index => $field) {
$fieldLength = strlen($field);
$maxLength = $maxLengths[$index] ?? null;
if ($maxLength !== null && $fieldLength > $maxLength) {
$errors[] = [
'field' => $index,
'length' => $fieldLength,
'max_length' => $maxLength,
'exceeded_by' => $fieldLength - $maxLength
];
}
}
return [
'valid' => empty($errors),
'errors' => $errors
];
}
/**
* 固定長フォーマットの検証
*/
public static function validateFixedLength($line, $expectedLength) {
$actualLength = strlen($line);
if ($actualLength !== $expectedLength) {
return [
'valid' => false,
'expected' => $expectedLength,
'actual' => $actualLength,
'difference' => $actualLength - $expectedLength
];
}
return ['valid' => true];
}
/**
* データサイズの確認
*/
public static function checkDataSize($data, $maxBytes) {
$size = strlen($data);
if ($size > $maxBytes) {
return [
'valid' => false,
'size' => $size,
'max_size' => $maxBytes,
'exceeded_by' => $size - $maxBytes,
'formatted_size' => DataSizeFormatter::formatBytes($size)
];
}
return [
'valid' => true,
'size' => $size,
'formatted_size' => DataSizeFormatter::formatBytes($size)
];
}
}
// 使用例
$csvLine = "John Doe,john@example.com,This is a very long comment field";
$maxLengths = [20, 50, 30]; // 各フィールドの最大長
$result = CsvValidator::validateFieldLengths($csvLine, $maxLengths);
print_r($result);
$fixedLine = "123456789012345";
$result = CsvValidator::validateFixedLength($fixedLine, 15);
var_dump($result['valid']); // true
$largeData = str_repeat("test", 10000);
$result = CsvValidator::checkDataSize($largeData, 50000);
print_r($result);
count()との違い
// strlen(): 文字列の長さ(バイト数)
$text = "Hello";
echo strlen($text) . "\n"; // 5
// count(): 配列の要素数
$array = ['a', 'b', 'c'];
echo count($array) . "\n"; // 3
// 文字列にcount()を使用すると警告
// echo count($text); // Warning
// 配列にstrlen()を使用するとエラー
// echo strlen($array); // TypeError
mb_strlen()との違い
$text = "こんにちは世界";
// strlen(): バイト数
echo "strlen: " . strlen($text) . "\n";
// 21 (UTF-8で各文字3バイト)
// mb_strlen(): 文字数
echo "mb_strlen: " . mb_strlen($text) . "\n";
// 7
// 英数字の場合は同じ
$english = "Hello World";
echo "strlen: " . strlen($english) . "\n"; // 11
echo "mb_strlen: " . mb_strlen($english) . "\n"; // 11
パフォーマンス
// strlen()は非常に高速(O(1))
$text = str_repeat("a", 1000000);
$start = microtime(true);
for ($i = 0; $i < 10000; $i++) {
strlen($text);
}
$time = microtime(true) - $start;
echo "処理時間: {$time}秒\n";
// 非常に高速(文字列の長さは内部で保持されている)
まとめ
strlen()関数の特徴をまとめると:
できること:
- 文字列のバイト数を取得
- 空文字列の判定
- 文字列の長さ制限チェック
注意点:
- バイト数を返す(文字数ではない)
- マルチバイト文字には
mb_strlen()を使用 - NULL文字も含めてカウント
推奨される使用場面:
- 入力バリデーション
- テキストの切り詰め
- データサイズの計算
- プログレス表示
- パスワード強度チェック
関連関数:
mb_strlen(): マルチバイト対応の文字数取得count(): 配列の要素数取得substr(): 部分文字列の取得str_word_count(): 単語数のカウント
パフォーマンス:
- O(1)の時間複雑度(非常に高速)
- 文字列の長さは内部で保持されている
strlen()は最も基本的な文字列関数の一つですが、マルチバイト文字を扱う場合はmb_strlen()の使用を検討しましょう。適切に使い分けることで、正確なデータ処理が可能になります!
