[PHP]str_ends_with関数を完全解説!文字列が特定の文字で終わるか確認する方法

PHP

こんにちは!今回は、PHPの標準関数であるstr_ends_with()について詳しく解説していきます。文字列が特定の文字列で終わっているかを簡単にチェックできる、PHP 8.0で追加された便利な関数です!

str_ends_with関数とは?

str_ends_with()関数は、文字列が指定した文字列で終わっているかを判定する関数です。

PHP 8.0で追加された関数で、サフィックス(接尾辞)のチェックが非常に簡潔に書けるようになりました!

基本的な構文

str_ends_with(string $haystack, string $needle): bool
  • $haystack: 検索対象の文字列
  • $needle: 末尾で検索する文字列
  • 戻り値: 末尾が一致する場合はtrue、一致しない場合はfalse

基本的な使用例

シンプルな判定

// 基本的な使用(PHP 8.0+)
$text = "Hello World";

if (str_ends_with($text, "World")) {
    echo "「World」で終わっています\n";
}
// 出力: 「World」で終わっています

if (str_ends_with($text, "Hello")) {
    echo "「Hello」で終わっています\n";
} else {
    echo "「Hello」で終わっていません\n";
}
// 出力: 「Hello」で終わっていません

大文字小文字の区別

$text = "Hello World";

// 大文字小文字は区別される
var_dump(str_ends_with($text, "world"));  // false
var_dump(str_ends_with($text, "World"));  // true

// 大文字小文字を区別しない場合
$text_lower = strtolower($text);
var_dump(str_ends_with($text_lower, strtolower("WORLD")));  // true

空文字列の扱い

$text = "Hello World";

// 空文字列は常にtrueを返す
var_dump(str_ends_with($text, ""));  // true

// 空の文字列で判定
var_dump(str_ends_with("", "test"));  // false
var_dump(str_ends_with("", ""));      // true

1文字の判定

$text = "Hello World";

// 1文字でも判定可能
var_dump(str_ends_with($text, "d"));  // true
var_dump(str_ends_with($text, "D"));  // false

PHP 8.0未満での代替実装

// PHP 8.0未満用のポリフィル
if (!function_exists('str_ends_with')) {
    function str_ends_with($haystack, $needle) {
        if ($needle === '') {
            return true;
        }
        
        $length = strlen($needle);
        return substr($haystack, -$length) === $needle;
    }
}

// 使用例
$text = "Hello World";
var_dump(str_ends_with($text, "World"));  // true

実践的な使用例

例1: ファイル拡張子チェック

class FileExtensionChecker {
    /**
     * 特定の拡張子か判定
     */
    public static function hasExtension($filename, $extension) {
        if ($extension[0] !== '.') {
            $extension = '.' . $extension;
        }
        
        return str_ends_with(strtolower($filename), strtolower($extension));
    }
    
    /**
     * 複数の拡張子のいずれかか判定
     */
    public static function hasAnyExtension($filename, $extensions) {
        $filename = strtolower($filename);
        
        foreach ($extensions as $extension) {
            if ($extension[0] !== '.') {
                $extension = '.' . $extension;
            }
            
            if (str_ends_with($filename, strtolower($extension))) {
                return true;
            }
        }
        
        return false;
    }
    
    /**
     * 画像ファイルか判定
     */
    public static function isImage($filename) {
        $extensions = ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp', '.svg'];
        return self::hasAnyExtension($filename, $extensions);
    }
    
    /**
     * ドキュメントファイルか判定
     */
    public static function isDocument($filename) {
        $extensions = ['.pdf', '.doc', '.docx', '.txt', '.rtf', '.odt'];
        return self::hasAnyExtension($filename, $extensions);
    }
    
    /**
     * 動画ファイルか判定
     */
    public static function isVideo($filename) {
        $extensions = ['.mp4', '.avi', '.mov', '.wmv', '.flv', '.mkv'];
        return self::hasAnyExtension($filename, $extensions);
    }
    
    /**
     * 音声ファイルか判定
     */
    public static function isAudio($filename) {
        $extensions = ['.mp3', '.wav', '.flac', '.aac', '.ogg', '.m4a'];
        return self::hasAnyExtension($filename, $extensions);
    }
    
    /**
     * 圧縮ファイルか判定
     */
    public static function isArchive($filename) {
        $extensions = ['.zip', '.rar', '.7z', '.tar', '.gz', '.bz2'];
        return self::hasAnyExtension($filename, $extensions);
    }
    
    /**
     * 実行ファイルか判定
     */
    public static function isExecutable($filename) {
        $extensions = ['.exe', '.bat', '.cmd', '.sh', '.app'];
        return self::hasAnyExtension($filename, $extensions);
    }
    
    /**
     * スクリプトファイルか判定
     */
    public static function isScript($filename) {
        $extensions = ['.php', '.js', '.py', '.rb', '.pl', '.sh'];
        return self::hasAnyExtension($filename, $extensions);
    }
    
    /**
     * 拡張子を取得
     */
    public static function getExtension($filename) {
        $dotPos = strrpos($filename, '.');
        
        if ($dotPos === false) {
            return null;
        }
        
        return substr($filename, $dotPos);
    }
    
    /**
     * ファイル種別を取得
     */
    public static function getFileType($filename) {
        if (self::isImage($filename)) return 'image';
        if (self::isDocument($filename)) return 'document';
        if (self::isVideo($filename)) return 'video';
        if (self::isAudio($filename)) return 'audio';
        if (self::isArchive($filename)) return 'archive';
        if (self::isExecutable($filename)) return 'executable';
        if (self::isScript($filename)) return 'script';
        return 'other';
    }
}

// 使用例
echo "=== ファイル拡張子チェック ===\n";

$files = [
    'photo.jpg',
    'document.pdf',
    'video.mp4',
    'music.mp3',
    'archive.zip',
    'script.php',
    'program.exe',
    'README'
];

foreach ($files as $file) {
    echo "\nファイル: {$file}\n";
    echo "  拡張子: " . (FileExtensionChecker::getExtension($file) ?? 'なし') . "\n";
    echo "  種別: " . FileExtensionChecker::getFileType($file) . "\n";
    echo "  画像: " . (FileExtensionChecker::isImage($file) ? 'Yes' : 'No') . "\n";
    echo "  ドキュメント: " . (FileExtensionChecker::isDocument($file) ? 'Yes' : 'No') . "\n";
    echo "  スクリプト: " . (FileExtensionChecker::isScript($file) ? 'Yes' : 'No') . "\n";
}

echo "\n=== 特定拡張子チェック ===\n";
var_dump(FileExtensionChecker::hasExtension('image.jpg', '.jpg'));    // true
var_dump(FileExtensionChecker::hasExtension('image.jpg', 'jpg'));     // true
var_dump(FileExtensionChecker::hasExtension('image.JPG', '.jpg'));    // true
var_dump(FileExtensionChecker::hasExtension('image.png', '.jpg'));    // false

例2: URL/パスの処理

class PathSuffixChecker {
    /**
     * スラッシュで終わるか判定
     */
    public static function endsWithSlash($path) {
        return str_ends_with($path, '/') || str_ends_with($path, '\\');
    }
    
    /**
     * ディレクトリパスか判定(スラッシュで終わる)
     */
    public static function isDirectory($path) {
        return self::endsWithSlash($path);
    }
    
    /**
     * クエリ文字列を含むか判定
     */
    public static function hasQueryString($url) {
        return str_contains($url, '?');
    }
    
    /**
     * フラグメントで終わるか判定
     */
    public static function hasFragment($url) {
        return str_contains($url, '#');
    }
    
    /**
     * 特定のパスで終わるか判定
     */
    public static function endsWithPath($url, $path) {
        return str_ends_with(rtrim($url, '/'), rtrim($path, '/'));
    }
    
    /**
     * ファイル名で終わるか判定
     */
    public static function endsWithFile($path, $filename) {
        return str_ends_with($path, $filename);
    }
    
    /**
     * バックアップファイルか判定
     */
    public static function isBackupFile($filename) {
        $backupSuffixes = ['.bak', '.backup', '.old', '~'];
        
        foreach ($backupSuffixes as $suffix) {
            if (str_ends_with(strtolower($filename), $suffix)) {
                return true;
            }
        }
        
        return false;
    }
    
    /**
     * 一時ファイルか判定
     */
    public static function isTempFile($filename) {
        $tempSuffixes = ['.tmp', '.temp', '.swp', '~'];
        
        foreach ($tempSuffixes as $suffix) {
            if (str_ends_with(strtolower($filename), $suffix)) {
                return true;
            }
        }
        
        return false;
    }
}

// 使用例
echo "=== パス/URLチェック ===\n";

$paths = [
    '/var/www/html/',
    '/var/www/html/index.php',
    'https://example.com/path/',
    'https://example.com/page.html',
    'document.pdf.bak',
    'file.txt.tmp'
];

foreach ($paths as $path) {
    echo "\nパス: {$path}\n";
    echo "  スラッシュ終了: " . (PathSuffixChecker::endsWithSlash($path) ? 'Yes' : 'No') . "\n";
    echo "  ディレクトリ: " . (PathSuffixChecker::isDirectory($path) ? 'Yes' : 'No') . "\n";
    echo "  バックアップ: " . (PathSuffixChecker::isBackupFile($path) ? 'Yes' : 'No') . "\n";
    echo "  一時ファイル: " . (PathSuffixChecker::isTempFile($path) ? 'Yes' : 'No') . "\n";
}

echo "\n=== パス終了チェック ===\n";
var_dump(PathSuffixChecker::endsWithPath('/var/www/html', '/html'));     // true
var_dump(PathSuffixChecker::endsWithPath('/var/www/html/', '/html'));    // true
var_dump(PathSuffixChecker::endsWithFile('/path/to/file.txt', 'file.txt')); // true

例3: 文の終わり方検出

class SentenceEnding {
    /**
     * 文が完結しているか判定
     */
    public static function isComplete($sentence) {
        $endings = ['.', '!', '?', '。', '!', '?'];
        $sentence = trim($sentence);
        
        foreach ($endings as $ending) {
            if (str_ends_with($sentence, $ending)) {
                return true;
            }
        }
        
        return false;
    }
    
    /**
     * 疑問文か判定
     */
    public static function isQuestion($sentence) {
        $sentence = trim($sentence);
        return str_ends_with($sentence, '?') || str_ends_with($sentence, '?');
    }
    
    /**
     * 感嘆文か判定
     */
    public static function isExclamation($sentence) {
        $sentence = trim($sentence);
        return str_ends_with($sentence, '!') || str_ends_with($sentence, '!');
    }
    
    /**
     * 平叙文か判定
     */
    public static function isStatement($sentence) {
        $sentence = trim($sentence);
        return str_ends_with($sentence, '.') || str_ends_with($sentence, '。');
    }
    
    /**
     * 省略符で終わるか判定
     */
    public static function isEllipsis($sentence) {
        $sentence = trim($sentence);
        return str_ends_with($sentence, '...') || 
               str_ends_with($sentence, '…');
    }
    
    /**
     * 引用符で終わるか判定
     */
    public static function endsWithQuote($sentence) {
        $sentence = trim($sentence);
        return str_ends_with($sentence, '"') || 
               str_ends_with($sentence, "'") ||
               str_ends_with($sentence, '」') ||
               str_ends_with($sentence, '』');
    }
    
    /**
     * 文のタイプを取得
     */
    public static function getSentenceType($sentence) {
        if (self::isQuestion($sentence)) return 'question';
        if (self::isExclamation($sentence)) return 'exclamation';
        if (self::isStatement($sentence)) return 'statement';
        if (self::isEllipsis($sentence)) return 'ellipsis';
        return 'incomplete';
    }
    
    /**
     * 丁寧な終わり方か判定(日本語)
     */
    public static function isPoliteEnding($sentence) {
        $politeEndings = ['です。', 'ます。', 'ました。', 'ません。'];
        
        foreach ($politeEndings as $ending) {
            if (str_ends_with($sentence, $ending)) {
                return true;
            }
        }
        
        return false;
    }
}

// 使用例
echo "=== 文の終わり方検出 ===\n";

$sentences = [
    'What is PHP?',
    'This is amazing!',
    'PHP is a programming language.',
    'I was thinking...',
    'He said "Hello"',
    'これはPHPです。',
    'ありがとうございます。',
    'Incomplete sentence'
];

foreach ($sentences as $sentence) {
    echo "\n文: {$sentence}\n";
    echo "  完結: " . (SentenceEnding::isComplete($sentence) ? 'Yes' : 'No') . "\n";
    echo "  種類: " . SentenceEnding::getSentenceType($sentence) . "\n";
    echo "  疑問文: " . (SentenceEnding::isQuestion($sentence) ? 'Yes' : 'No') . "\n";
    echo "  感嘆文: " . (SentenceEnding::isExclamation($sentence) ? 'Yes' : 'No') . "\n";
    echo "  省略符: " . (SentenceEnding::isEllipsis($sentence) ? 'Yes' : 'No') . "\n";
    echo "  引用符終了: " . (SentenceEnding::endsWithQuote($sentence) ? 'Yes' : 'No') . "\n";
    echo "  丁寧: " . (SentenceEnding::isPoliteEnding($sentence) ? 'Yes' : 'No') . "\n";
}

例4: データバリデーション

class DataValidator {
    /**
     * メールアドレスのドメインチェック
     */
    public static function hasEmailDomain($email, $domain) {
        return str_ends_with(strtolower($email), '@' . strtolower($domain));
    }
    
    /**
     * 会社のメールアドレスか判定
     */
    public static function isCompanyEmail($email, $companyDomains) {
        $email = strtolower($email);
        
        foreach ($companyDomains as $domain) {
            if (str_ends_with($email, '@' . strtolower($domain))) {
                return true;
            }
        }
        
        return false;
    }
    
    /**
     * フリーメールか判定
     */
    public static function isFreeEmail($email) {
        $freeDomains = ['gmail.com', 'yahoo.com', 'hotmail.com', 'outlook.com'];
        return self::isCompanyEmail($email, $freeDomains);
    }
    
    /**
     * 電話番号が特定の市外局番で終わるか
     */
    public static function hasAreaCode($phone, $areaCode) {
        $phone = preg_replace('/[^0-9]/', '', $phone);
        return str_ends_with($phone, $areaCode);
    }
    
    /**
     * URLがトップレベルドメインで終わるか
     */
    public static function hasTLD($url, $tld) {
        if ($tld[0] !== '.') {
            $tld = '.' . $tld;
        }
        
        // クエリ文字列やフラグメントを除去
        $url = strtok($url, '?#');
        
        return str_ends_with(strtolower($url), strtolower($tld));
    }
    
    /**
     * 特定の国のTLDか判定
     */
    public static function hasCountryTLD($url) {
        $countryTLDs = ['.jp', '.us', '.uk', '.cn', '.de', '.fr'];
        
        foreach ($countryTLDs as $tld) {
            if (self::hasTLD($url, $tld)) {
                return true;
            }
        }
        
        return false;
    }
    
    /**
     * セキュアなファイル名か判定(安全な拡張子)
     */
    public static function isSafeExtension($filename) {
        $safeExtensions = ['.txt', '.pdf', '.jpg', '.png', '.gif', '.doc', '.docx'];
        $filename = strtolower($filename);
        
        foreach ($safeExtensions as $ext) {
            if (str_ends_with($filename, $ext)) {
                return true;
            }
        }
        
        return false;
    }
    
    /**
     * 危険なファイル名か判定
     */
    public static function isDangerousExtension($filename) {
        $dangerousExtensions = ['.exe', '.bat', '.cmd', '.sh', '.php', '.js', '.vbs'];
        $filename = strtolower($filename);
        
        foreach ($dangerousExtensions as $ext) {
            if (str_ends_with($filename, $ext)) {
                return true;
            }
        }
        
        return false;
    }
}

// 使用例
echo "=== データバリデーション ===\n";

// メールアドレスチェック
$emails = [
    'user@example.com',
    'john@gmail.com',
    'staff@company.co.jp'
];

echo "メールアドレスチェック:\n";
foreach ($emails as $email) {
    $isFree = DataValidator::isFreeEmail($email) ? 'フリー' : '独自';
    echo "  {$email}: {$isFree}\n";
}

// ドメインチェック
echo "\n会社ドメインチェック:\n";
$companyDomains = ['example.com', 'company.co.jp'];
foreach ($emails as $email) {
    $isCompany = DataValidator::isCompanyEmail($email, $companyDomains) ? 'Yes' : 'No';
    echo "  {$email}: {$isCompany}\n";
}

// TLDチェック
echo "\nTLDチェック:\n";
$urls = [
    'https://example.com',
    'https://example.co.jp',
    'https://example.de'
];

foreach ($urls as $url) {
    echo "  {$url}:\n";
    echo "    .com: " . (DataValidator::hasTLD($url, '.com') ? 'Yes' : 'No') . "\n";
    echo "    .jp: " . (DataValidator::hasTLD($url, '.jp') ? 'Yes' : 'No') . "\n";
    echo "    国別TLD: " . (DataValidator::hasCountryTLD($url) ? 'Yes' : 'No') . "\n";
}

// ファイル拡張子の安全性チェック
echo "\nファイル安全性チェック:\n";
$files = ['document.pdf', 'script.php', 'photo.jpg', 'program.exe'];
foreach ($files as $file) {
    $safe = DataValidator::isSafeExtension($file) ? '安全' : '要確認';
    $dangerous = DataValidator::isDangerousExtension($file) ? '危険' : 'OK';
    echo "  {$file}: {$safe} / {$dangerous}\n";
}

例5: バージョン文字列の処理

class VersionChecker {
    /**
     * ベータバージョンか判定
     */
    public static function isBeta($version) {
        return str_ends_with(strtolower($version), '-beta') ||
               str_ends_with(strtolower($version), '.beta');
    }
    
    /**
     * アルファバージョンか判定
     */
    public static function isAlpha($version) {
        return str_ends_with(strtolower($version), '-alpha') ||
               str_ends_with(strtolower($version), '.alpha');
    }
    
    /**
     * リリース候補か判定
     */
    public static function isReleaseCandidate($version) {
        return str_ends_with(strtolower($version), '-rc') ||
               preg_match('/-rc\d+$/i', $version);
    }
    
    /**
     * 開発版か判定
     */
    public static function isDev($version) {
        return str_ends_with(strtolower($version), '-dev') ||
               str_ends_with(strtolower($version), '.dev');
    }
    
    /**
     * 安定版か判定
     */
    public static function isStable($version) {
        return !self::isBeta($version) &&
               !self::isAlpha($version) &&
               !self::isReleaseCandidate($version) &&
               !self::isDev($version);
    }
    
    /**
     * LTS(長期サポート)版か判定
     */
    public static function isLTS($version) {
        return str_ends_with(strtolower($version), '-lts') ||
               str_ends_with(strtolower($version), '.lts');
    }
    
    /**
     * バージョンタイプを取得
     */
    public static function getVersionType($version) {
        if (self::isAlpha($version)) return 'alpha';
        if (self::isBeta($version)) return 'beta';
        if (self::isReleaseCandidate($version)) return 'rc';
        if (self::isDev($version)) return 'dev';
        if (self::isLTS($version)) return 'lts';
        if (self::isStable($version)) return 'stable';
        return 'unknown';
    }
}

// 使用例
echo "=== バージョンチェック ===\n";

$versions = [
    '1.0.0',
    '2.0.0-beta',
    '3.0.0-alpha',
    '4.0.0-rc1',
    '5.0.0-dev',
    '6.0.0-lts'
];

foreach ($versions as $version) {
    $type = VersionChecker::getVersionType($version);
    echo "{$version}: {$type}\n";
}

echo "\n=== 詳細チェック ===\n";
foreach ($versions as $version) {
    echo "\n{$version}:\n";
    echo "  Alpha: " . (VersionChecker::isAlpha($version) ? 'Yes' : 'No') . "\n";
    echo "  Beta: " . (VersionChecker::isBeta($version) ? 'Yes' : 'No') . "\n";
    echo "  RC: " . (VersionChecker::isReleaseCandidate($version) ? 'Yes' : 'No') . "\n";
    echo "  Dev: " . (VersionChecker::isDev($version) ? 'Yes' : 'No') . "\n";
    echo "  Stable: " . (VersionChecker::isStable($version) ? 'Yes' : 'No') . "\n";
    echo "  LTS: " . (VersionChecker::isLTS($version) ? 'Yes' : 'No') . "\n";
}

例6: ユーザー名/IDの検証

class UsernameValidator {
    /**
     * ボット用アカウントか判定
     */
    public static function isBot($username) {
        $botSuffixes = ['_bot', '-bot', 'Bot', '_BOT'];
        
        foreach ($botSuffixes as $suffix) {
            if (str_ends_with($username, $suffix)) {
                return true;
            }
        }
        
        return false;
    }
    
    /**
     * 管理者アカウントか判定
     */
    public static function isAdmin($username) {
        $adminSuffixes = ['_admin', '-admin', 'Admin', '_ADMIN'];
        
        foreach ($adminSuffixes as $suffix) {
            if (str_ends_with($username, $suffix)) {
                return true;
            }
        }
        
        return false;
    }
    
    /**
     * テストアカウントか判定
     */
    public static function isTest($username) {
        $testSuffixes = ['_test', '-test', 'Test', '_TEST', '_demo'];
        
        foreach ($testSuffixes as $suffix) {
            if (str_ends_with($username, $suffix)) {
                return true;
            }
        }
        
        return false;
    }
    
    /**
     * 数字で終わるか判定
     */
    public static function endsWithNumber($username) {
        return preg_match('/\d$/', $username) === 1;
    }
    
    /**
     * アンダースコアで終わるか判定
     */
    public static function endsWithUnderscore($username) {
        return str_ends_with($username, '_');
    }
    
    /**
     * 公式アカウントか判定
     */
    public static function isOfficial($username) {
        $officialSuffixes = ['_official', 'Official', '_公式'];
        
        foreach ($officialSuffixes as $suffix) {
            if (str_ends_with($username, $suffix)) {
                return true;
            }
        }
        
        return false;
    }
}

// 使用例
echo "=== ユーザー名検証 ===\n";

$usernames = [
    'john_doe',
    'support_bot',
    'admin_user',
    'test_account',
    'user123',
    'company_official',
    'normaluser'
];

foreach ($usernames as $username) {
    echo "\nユーザー名: {$username}\n";
    echo "  ボット: " . (UsernameValidator::isBot($username) ? 'Yes' : 'No') . "\n";
    echo "  管理者: " . (UsernameValidator::isAdmin($username) ? 'Yes' : 'No') . "\n";
    echo "  テスト: " . (UsernameValidator::isTest($username) ? 'Yes' : 'No') . "\n";
    echo "  公式: " . (UsernameValidator::isOfficial($username) ? 'Yes' : 'No') . "\n";
    echo "  数字終了: " . (UsernameValidator::endsWithNumber($username) ? 'Yes' : 'No') . "\n";
    echo "  _終了: " . (UsernameValidator::endsWithUnderscore($username) ? 'Yes' : 'No') . "\n";
}

例7: 言語/文字コード検出

class LanguageDetector {
    /**
     * 日本語で終わるか判定
     */
    public static function endsWithJapanese($text) {
        $japaneseEndings = ['です', 'ます', 'した', 'だ', 'か', 'ね', 'よ', '。'];
        
        foreach ($japaneseEndings as $ending) {
            if (str_ends_with($text, $ending)) {
                return true;
            }
        }
        
        return false;
    }
    
    /**
     * 英語の文で終わるか判定
     */
    public static function endsWithEnglishSentence($text) {
        $text = trim($text);
        return str_ends_with($text, '.') || 
               str_ends_with($text, '!') || 
               str_ends_with($text, '?');
    }
    
    /**
     * 中国語で終わるか判定
     */
    public static function endsWithChinese($text) {
        $chineseEndings = ['。', '!', '?', '了', '的', '吗'];
        
        foreach ($chineseEndings as $ending) {
            if (str_ends_with($text, $ending)) {
                return true;
            }
        }
        
        return false;
    }
    
    /**
     * HTMLタグで終わるか判定
     */
    public static function endsWithHtmlTag($text) {
        return str_ends_with(trim($text), '>');
    }
    
    /**
     * コードブロックで終わるか判定
     */
    public static function endsWithCodeBlock($text) {
        return str_ends_with(trim($text), '```') ||
               str_ends_with(trim($text), '</code>');
    }
}

// 使用例
echo "=== 言語検出 ===\n";

$texts = [
    'これはテストです',
    'This is a test.',
    '这是测试。',
    '<p>HTML content</p>',
    '```code block```',
    'Incomplete'
];

foreach ($texts as $text) {
    echo "\nテキスト: {$text}\n";
    echo "  日本語終了: " . (LanguageDetector::endsWithJapanese($text) ? 'Yes' : 'No') . "\n";
    echo "  英語終了: " . (LanguageDetector::endsWithEnglishSentence($text) ? 'Yes' : 'No') . "\n";
    echo "  中国語終了: " . (LanguageDetector::endsWithChinese($text) ? 'Yes' : 'No') . "\n";
    echo "  HTMLタグ: " . (LanguageDetector::endsWithHtmlTag($text) ? 'Yes' : 'No') . "\n";
    echo "  コードブロック: " . (LanguageDetector::endsWithCodeBlock($text) ? 'Yes' : 'No') . "\n";
}

従来の方法との比較

$text = "Hello World";
$suffix = "World";

// 新しい方法(PHP 8.0+)
if (str_ends_with($text, $suffix)) {
    echo "末尾が一致\n";
}

// 従来の方法
if (substr($text, -strlen($suffix)) === $suffix) {
    echo "末尾が一致\n";
}

// または正規表現
if (preg_match('/' . preg_quote($suffix) . '$/', $text)) {
    echo "末尾が一致\n";
}

// 利点:
// - より直感的
// - 文字列長の計算不要
// - コードが読みやすい

まとめ

str_ends_with()関数の特徴をまとめると:

できること:

  • 文字列の末尾一致チェック
  • サフィックスの検証
  • ブール値を返す

推奨される使用場面:

  • ファイル拡張子チェック
  • URL/パス処理
  • 文の終わり方検出
  • バリデーション
  • バージョン判定
  • ユーザー名検証

利点:

  • 直感的で読みやすい
  • 長さ計算不要
  • PHP 8.0で標準化

注意点:

  • PHP 8.0以降でのみ使用可能
  • 大文字小文字を区別する
  • 空文字列は常にtrue

関連関数:

  • str_starts_with(): 先頭一致
  • str_contains(): 含まれるか
  • substr(): 部分文字列を取得
  • strrpos(): 最後の出現位置

使い分け:

// 末尾一致
str_ends_with($text, $suffix)

// 先頭一致
str_starts_with($text, $prefix)

// 含まれるか
str_contains($text, $needle)

// 末尾部分を取得
substr($text, -$length)

str_ends_with()は、PHP 8.0で追加された非常に便利な関数です。ファイル拡張子のチェックや文の終わり方の判定など、様々な場面で活躍します。PHP 8.0以降を使用している場合は積極的に活用しましょう!

タイトルとURLをコピーしました