[PHP]highlight_string関数とは?文字列のコードハイライト完全ガイド

PHP

PHPでコードを動的に生成し、そのコードを美しく表示したい場面はありませんか?ファイルではなく、文字列として保存されているPHPコードをハイライト表示する際に威力を発揮するのが「highlight_string関数」です。

この記事では、highlight_string関数の基本から応用まで、実践的な例を交えながら詳しく解説します。

highlight_string関数とは?

highlight_string関数は、PHP文字列の内容を構文ハイライト付きで表示するPHP標準関数です。highlight_file関数がファイルを対象とするのに対し、highlight_string関数は文字列を直接処理できる点が大きな特徴です。

基本的な構文

highlight_string(string $string, bool $return = false)

パラメータ:

  • $string: ハイライト表示したいPHPコードの文字列
  • $return: trueの場合は結果を返す、falseの場合は直接出力(デフォルト: false)

戻り値:

  • $returnがtrueの場合:ハイライトされたHTMLコードを文字列で返す
  • $returnがfalseの場合:直接HTMLを出力し、成功時はtrue、失敗時はfalseを返す

基本的な使用例

シンプルな使用方法

<?php
$code = '<?php
$message = "Hello, World!";
echo $message;
?>';

// コードをハイライト表示
highlight_string($code);
?>

この例では、$code変数に格納されたPHPコードが構文ハイライト付きで表示されます。

結果を変数に格納する方法

<?php
$code = '<?php
function greet($name) {
    return "Hello, " . $name . "!";
}

echo greet("World");
?>';

// ハイライト結果を変数に格納
$highlighted_html = highlight_string($code, true);

// 後でHTMLとして使用
echo '<div class="code-block">';
echo $highlighted_html;
echo '</div>';
?>

実践的な活用例

1. 動的コード生成とハイライト表示

<?php
function generateAndDisplayCode($className, $properties) {
    $code = "<?php\nclass {$className} {\n";
    
    foreach ($properties as $property => $type) {
        $code .= "    private \${$property}; // {$type}\n";
    }
    
    $code .= "\n    public function __construct() {\n";
    $code .= "        // コンストラクタの実装\n";
    $code .= "    }\n";
    $code .= "}\n?>";
    
    echo "<h3>生成されたクラス: {$className}</h3>";
    echo '<div style="border: 1px solid #ddd; padding: 15px; background: #f8f8f8;">';
    highlight_string($code);
    echo '</div>';
}

// 使用例
$properties = [
    'id' => 'integer',
    'name' => 'string',
    'email' => 'string'
];

generateAndDisplayCode('User', $properties);
?>

2. コードスニペット管理システム

<?php
class CodeSnippetManager {
    private $snippets = [];
    
    public function addSnippet($name, $code, $description = '') {
        $this->snippets[$name] = [
            'code' => $code,
            'description' => $description,
            'created_at' => date('Y-m-d H:i:s')
        ];
    }
    
    public function displaySnippet($name) {
        if (!isset($this->snippets[$name])) {
            echo "<p>スニペット '{$name}' が見つかりません。</p>";
            return false;
        }
        
        $snippet = $this->snippets[$name];
        
        echo "<div class='snippet-container'>";
        echo "<h3>{$name}</h3>";
        if ($snippet['description']) {
            echo "<p class='description'>{$snippet['description']}</p>";
        }
        echo "<div class='code-display'>";
        highlight_string($snippet['code']);
        echo "</div>";
        echo "<small>作成日: {$snippet['created_at']}</small>";
        echo "</div>";
        
        return true;
    }
    
    public function listSnippets() {
        foreach ($this->snippets as $name => $snippet) {
            $this->displaySnippet($name);
            echo "<hr>";
        }
    }
}

// 使用例
$manager = new CodeSnippetManager();

$manager->addSnippet('database_connection', '<?php
$pdo = new PDO("mysql:host=localhost;dbname=test", $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
?>', 'データベース接続の基本例');

$manager->addSnippet('array_filtering', '<?php
$numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
$even_numbers = array_filter($numbers, function($n) {
    return $n % 2 === 0;
});
print_r($even_numbers);
?>', '配列から偶数のみを抽出');

$manager->listSnippets();
?>

3. オンラインコードエディタ風の表示

<?php
function createCodeEditor($code, $title = 'Code Editor') {
    $highlighted = highlight_string($code, true);
    
    echo "<div class='code-editor'>";
    echo "<div class='editor-header'>";
    echo "<span class='title'>{$title}</span>";
    echo "<button onclick='copyCode()'>コピー</button>";
    echo "</div>";
    echo "<div class='editor-content'>";
    echo $highlighted;
    echo "</div>";
    echo "</div>";
    
    echo "<script>
    function copyCode() {
        const codeText = document.querySelector('.editor-content').innerText;
        navigator.clipboard.writeText(codeText).then(function() {
            alert('コードがクリップボードにコピーされました!');
        });
    }
    </script>";
    
    echo "<style>
    .code-editor {
        border: 1px solid #ddd;
        border-radius: 5px;
        margin: 10px 0;
        font-family: 'Courier New', monospace;
    }
    .editor-header {
        background: #f0f0f0;
        padding: 10px;
        border-bottom: 1px solid #ddd;
        display: flex;
        justify-content: space-between;
        align-items: center;
    }
    .editor-content {
        padding: 15px;
        background: white;
        overflow-x: auto;
    }
    button {
        padding: 5px 10px;
        background: #007cba;
        color: white;
        border: none;
        border-radius: 3px;
        cursor: pointer;
    }
    </style>";
}

// 使用例
$sample_code = '<?php
// RESTful APIのエンドポイント例
class UserController {
    public function index() {
        $users = User::all();
        return json_encode($users);
    }
    
    public function show($id) {
        $user = User::find($id);
        if (!$user) {
            http_response_code(404);
            return json_encode(["error" => "User not found"]);
        }
        return json_encode($user);
    }
}
?>';

createCodeEditor($sample_code, 'UserController.php');
?>

highlight_fileとの違いと使い分け

highlight_string vs highlight_file

特徴highlight_stringhighlight_file
入力文字列ファイルパス
用途動的コード生成既存ファイル表示
メモリ使用コードが変数に格納ファイルから直接読み込み
パフォーマンス小さなコードに適している大きなファイルに適している

使い分けの指針

<?php
// highlight_stringを使うべき場面
function showDynamicCode() {
    $code = generateCodeFromDatabase();
    highlight_string($code);
}

// highlight_fileを使うべき場面
function showStaticFile() {
    highlight_file('existing_file.php');
}

// 両方を組み合わせた例
function showCodeComparison($file1, $dynamicCode) {
    echo "<div class='comparison'>";
    echo "<div class='left-panel'>";
    echo "<h3>既存ファイル</h3>";
    highlight_file($file1);
    echo "</div>";
    
    echo "<div class='right-panel'>";
    echo "<h3>生成されたコード</h3>";
    highlight_string($dynamicCode);
    echo "</div>";
    echo "</div>";
}
?>

高度な活用テクニック

1. コードのバリデーション付きハイライト

<?php
function validateAndHighlightCode($code) {
    // 構文チェック
    $tempFile = tempnam(sys_get_temp_dir(), 'php_syntax_check');
    file_put_contents($tempFile, $code);
    
    $output = [];
    $return_var = 0;
    exec("php -l {$tempFile} 2>&1", $output, $return_var);
    
    unlink($tempFile);
    
    if ($return_var === 0) {
        echo "<div class='valid-code'>";
        echo "<h4>✅ 構文チェック: 正常</h4>";
        highlight_string($code);
        echo "</div>";
    } else {
        echo "<div class='invalid-code'>";
        echo "<h4>❌ 構文エラーが見つかりました</h4>";
        echo "<pre class='error-message'>" . implode("\n", $output) . "</pre>";
        echo "<h5>コード:</h5>";
        highlight_string($code);
        echo "</div>";
    }
}

// 使用例
$valid_code = '<?php
$name = "World";
echo "Hello, " . $name;
?>';

$invalid_code = '<?php
$name = "World"  // セミコロンが抜けている
echo "Hello, " . $name;
?>';

validateAndHighlightCode($valid_code);
validateAndHighlightCode($invalid_code);
?>

2. 色設定のカスタマイズ

<?php
function customHighlight($code, $theme = 'default') {
    $themes = [
        'default' => [
            'highlight.string' => '#008000',
            'highlight.comment' => '#FF8000', 
            'highlight.keyword' => '#0000BB',
            'highlight.default' => '#000000',
            'highlight.html' => '#808080'
        ],
        'dark' => [
            'highlight.string' => '#98C379',
            'highlight.comment' => '#7C7C7C',
            'highlight.keyword' => '#C678DD',
            'highlight.default' => '#ABB2BF',
            'highlight.html' => '#E06C75'
        ],
        'ocean' => [
            'highlight.string' => '#2ECC71',
            'highlight.comment' => '#95A5A6',
            'highlight.keyword' => '#3498DB',
            'highlight.default' => '#2C3E50',
            'highlight.html' => '#E74C3C'
        ]
    ];
    
    if (isset($themes[$theme])) {
        foreach ($themes[$theme] as $setting => $color) {
            ini_set($setting, $color);
        }
    }
    
    echo "<div class='theme-{$theme}'>";
    highlight_string($code);
    echo "</div>";
}

// 使用例
$sample_code = '<?php
// サンプルコード
$greeting = "Hello, World!";
echo $greeting; // 出力
?>';

echo "<h3>デフォルトテーマ</h3>";
customHighlight($sample_code, 'default');

echo "<h3>ダークテーマ</h3>";
customHighlight($sample_code, 'dark');

echo "<h3>オーシャンテーマ</h3>";
customHighlight($sample_code, 'ocean');
?>

セキュリティ上の注意点

1. 入力値の検証

<?php
function safeHighlightString($code) {
    // 基本的な検証
    if (empty($code)) {
        echo "エラー: コードが空です。";
        return false;
    }
    
    // 危険な関数の使用チェック
    $dangerous_functions = ['exec', 'system', 'shell_exec', 'passthru', 'eval'];
    foreach ($dangerous_functions as $func) {
        if (stripos($code, $func) !== false) {
            echo "警告: 危険な関数 '{$func}' が検出されました。";
            echo "<details><summary>コードを表示</summary>";
            highlight_string($code);
            echo "</details>";
            return false;
        }
    }
    
    // 正常な場合のハイライト表示
    highlight_string($code);
    return true;
}

// 使用例
$safe_code = '<?php
$data = ["apple", "banana", "orange"];
foreach ($data as $item) {
    echo $item . "\n";
}
?>';

$unsafe_code = '<?php
exec("rm -rf /");  // 危険なコード
?>';

echo "<h3>安全なコード</h3>";
safeHighlightString($safe_code);

echo "<h3>危険なコード</h3>";
safeHighlightString($unsafe_code);
?>

2. 出力のサニタイズ

<?php
function secureHighlightString($code, $allow_html = false) {
    if (!$allow_html) {
        // HTMLタグを除去
        $code = strip_tags($code);
    }
    
    // 結果を取得してさらにサニタイズ
    $highlighted = highlight_string($code, true);
    
    // 不要な属性を削除(セキュリティ強化)
    $highlighted = preg_replace('/on\w+="[^"]*"/i', '', $highlighted);
    
    echo $highlighted;
}
?>

パフォーマンス最適化

キャッシュ機能付きハイライト

<?php
class HighlightCache {
    private $cache_dir;
    private $cache_lifetime;
    
    public function __construct($cache_dir = 'cache', $cache_lifetime = 3600) {
        $this->cache_dir = $cache_dir;
        $this->cache_lifetime = $cache_lifetime;
        
        if (!is_dir($cache_dir)) {
            mkdir($cache_dir, 0755, true);
        }
    }
    
    public function highlightString($code, $return = false) {
        $cache_key = md5($code);
        $cache_file = $this->cache_dir . '/' . $cache_key . '.html';
        
        // キャッシュファイルが存在し、有効期限内の場合
        if (file_exists($cache_file) && 
            (time() - filemtime($cache_file)) < $this->cache_lifetime) {
            $result = file_get_contents($cache_file);
        } else {
            // ハイライト処理を実行
            $result = highlight_string($code, true);
            
            // キャッシュに保存
            file_put_contents($cache_file, $result);
        }
        
        if ($return) {
            return $result;
        } else {
            echo $result;
            return true;
        }
    }
}

// 使用例
$cache = new HighlightCache();

$code = '<?php
$users = [
    ["name" => "Alice", "age" => 25],
    ["name" => "Bob", "age" => 30],
    ["name" => "Charlie", "age" => 35]
];

foreach ($users as $user) {
    echo "Name: " . $user["name"] . ", Age: " . $user["age"] . "\n";
}
?>';

// キャッシュ機能付きでハイライト表示
$cache->highlightString($code);
?>

まとめ

highlight_string関数は、PHPコードの文字列を美しく表示するための強力なツールです。静的なファイル表示に適したhighlight_file関数とは異なり、動的に生成されたコードの表示に特に有効です。

highlight_string関数の主な特徴:

  • 文字列として保存されたPHPコードを直接ハイライト表示
  • 動的コード生成システムとの相性が良い
  • カスタマイズ可能な色設定
  • セキュリティ対策が重要

適用場面:

  • オンラインコードエディタ
  • 動的コード生成ツール
  • コードスニペット管理システム
  • プログラミング学習プラットフォーム
  • API ドキュメント生成

適切なセキュリティ対策とパフォーマンス最適化を行うことで、highlight_string関数は非常に有用な機能となります。ぜひあなたのプロジェクトでも活用してみてください。

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