こんにちは!今回は、PHPの標準関数であるstripcslashes()について詳しく解説していきます。addcslashes()でエスケープされた文字列を元に戻すための関数です!
stripcslashes関数とは?
stripcslashes()関数は、addcslashes()によってエスケープされた文字列を元の状態に戻す関数です。
C言語スタイルのバックスラッシュエスケープシーケンス(\n、\t、\rなど)を解釈して、対応する文字に変換します!
基本的な構文
stripcslashes(string $string): string
- $string: エスケープを解除する文字列
- 戻り値: エスケープが解除された文字列
エスケープシーケンスの対応表
| エスケープシーケンス | 変換後 | 説明 |
|---|---|---|
\n | 改行 (LF) | ラインフィード |
\r | 復帰 (CR) | キャリッジリターン |
\t | タブ | 水平タブ |
\v | 垂直タブ | 垂直タブ |
\f | フォームフィード | 改ページ |
\\ | バックスラッシュ | バックスラッシュそのもの |
\0 | NULL文字 | NULL (0x00) |
\xHH | 16進数 | 16進数表記の文字 |
\OOO | 8進数 | 8進数表記の文字 |
基本的な使用例
シンプルな使用例
// エスケープされた文字列
$escaped = "Hello\\nWorld\\tTest";
// エスケープを解除
$unescaped = stripcslashes($escaped);
echo $unescaped . "\n";
// 出力:
// Hello
// World Test
// バックスラッシュのエスケープ
$escaped = "C:\\\\Users\\\\Documents";
$unescaped = stripcslashes($escaped);
echo $unescaped . "\n";
// 出力: C:\Users\Documents
addcslashes()との組み合わせ
$original = "Hello\nWorld\tTest";
// エスケープ
$escaped = addcslashes($original, "\n\t");
echo "エスケープ後: " . $escaped . "\n";
// 出力: Hello\nWorld\tTest
// 元に戻す
$restored = stripcslashes($escaped);
echo "復元後: " . $restored . "\n";
// 出力: Hello
// World Test
// 完全に一致するか確認
var_dump($original === $restored); // bool(true)
16進数と8進数
// 16進数エスケープ
$hex = "\\x48\\x65\\x6C\\x6C\\x6F"; // "Hello"
echo stripcslashes($hex) . "\n";
// 出力: Hello
// 8進数エスケープ
$oct = "\\110\\145\\154\\154\\157"; // "Hello"
echo stripcslashes($oct) . "\n";
// 出力: Hello
// NULL文字
$withNull = "Hello\\0World";
$result = stripcslashes($withNull);
echo strlen($result) . "\n"; // 11(NULL文字を含む)
実践的な使用例
例1: データベースからのデータ復元
class DatabaseDataHandler {
/**
* データベースに保存する際にエスケープ
*/
public static function escapeForStorage($data) {
// 改行、タブ、バックスラッシュをエスケープ
return addcslashes($data, "\n\r\t\\");
}
/**
* データベースから取得したデータを復元
*/
public static function unescapeFromStorage($data) {
return stripcslashes($data);
}
/**
* 複数フィールドの処理
*/
public static function prepareForStorage($record) {
$prepared = [];
foreach ($record as $key => $value) {
if (is_string($value)) {
$prepared[$key] = self::escapeForStorage($value);
} else {
$prepared[$key] = $value;
}
}
return $prepared;
}
/**
* 複数フィールドの復元
*/
public static function restoreFromStorage($record) {
$restored = [];
foreach ($record as $key => $value) {
if (is_string($value)) {
$restored[$key] = self::unescapeFromStorage($value);
} else {
$restored[$key] = $value;
}
}
return $restored;
}
}
// 使用例
$original = [
'title' => 'Sample Title',
'content' => "Line 1\nLine 2\tTabbed",
'path' => 'C:\Users\Documents'
];
echo "=== 元のデータ ===\n";
print_r($original);
// 保存用に変換
$forStorage = DatabaseDataHandler::prepareForStorage($original);
echo "\n=== 保存用データ ===\n";
print_r($forStorage);
// content => "Line 1\\nLine 2\\tTabbed"
// path => "C:\\Users\\Documents"
// 復元
$restored = DatabaseDataHandler::restoreFromStorage($forStorage);
echo "\n=== 復元されたデータ ===\n";
print_r($restored);
// 一致確認
var_dump($original === $restored); // bool(true)
例2: 設定ファイルの読み込み
class ConfigFileParser {
/**
* 設定ファイルを読み込む
*/
public static function parseConfigFile($filename) {
if (!file_exists($filename)) {
throw new Exception("設定ファイルが見つかりません: {$filename}");
}
$lines = file($filename, FILE_IGNORE_NEW_LINES);
$config = [];
foreach ($lines as $line) {
$line = trim($line);
// コメント行と空行をスキップ
if (empty($line) || $line[0] === '#') {
continue;
}
// key=value 形式
if (strpos($line, '=') !== false) {
list($key, $value) = explode('=', $line, 2);
$key = trim($key);
$value = trim($value);
// エスケープシーケンスを解釈
$value = stripcslashes($value);
$config[$key] = $value;
}
}
return $config;
}
/**
* 設定ファイルに書き込む
*/
public static function writeConfigFile($filename, $config) {
$lines = [];
foreach ($config as $key => $value) {
// エスケープ
$escapedValue = addcslashes($value, "\n\r\t\\");
$lines[] = "{$key}={$escapedValue}";
}
return file_put_contents($filename, implode("\n", $lines));
}
}
// 使用例
// config.txt の内容:
// database_host=localhost
// database_path=C:\\Program Files\\MySQL
// message=Welcome!\nEnjoy your stay.
$config = ConfigFileParser::parseConfigFile('config.txt');
print_r($config);
/*
Array (
[database_host] => localhost
[database_path] => C:\Program Files\MySQL
[message] => Welcome!
Enjoy your stay.
)
*/
// 新しい設定を追加
$config['log_file'] = "/var/log\tapplication.log";
// 書き込み
ConfigFileParser::writeConfigFile('config_new.txt', $config);
例3: ログファイルの処理
class LogProcessor {
/**
* ログエントリをエスケープ
*/
public static function escapeLogEntry($message) {
// 改行とタブをエスケープ(1行のログとして保存)
return addcslashes($message, "\n\r\t");
}
/**
* ログエントリを復元
*/
public static function unescapeLogEntry($message) {
return stripcslashes($message);
}
/**
* ログファイルに書き込む
*/
public static function writeLog($filename, $level, $message) {
$timestamp = date('Y-m-d H:i:s');
$escapedMessage = self::escapeLogEntry($message);
$logEntry = "[{$timestamp}] [{$level}] {$escapedMessage}\n";
return file_put_contents($filename, $logEntry, FILE_APPEND);
}
/**
* ログファイルを読み込む
*/
public static function readLog($filename) {
if (!file_exists($filename)) {
return [];
}
$lines = file($filename, FILE_IGNORE_NEW_LINES);
$entries = [];
foreach ($lines as $line) {
if (preg_match('/^\[([\d\-: ]+)\] \[(\w+)\] (.+)$/', $line, $matches)) {
$entries[] = [
'timestamp' => $matches[1],
'level' => $matches[2],
'message' => self::unescapeLogEntry($matches[3])
];
}
}
return $entries;
}
/**
* ログをフィルタリング
*/
public static function filterLogByLevel($filename, $level) {
$entries = self::readLog($filename);
return array_filter($entries, function($entry) use ($level) {
return strcasecmp($entry['level'], $level) === 0;
});
}
}
// 使用例
$logFile = 'application.log';
// 複数行のメッセージを書き込む
$message = "エラーが発生しました。\n詳細:\n\tファイルが見つかりません";
LogProcessor::writeLog($logFile, 'ERROR', $message);
LogProcessor::writeLog($logFile, 'INFO', 'アプリケーション起動');
// ログを読み込む
$logs = LogProcessor::readLog($logFile);
foreach ($logs as $log) {
echo "[{$log['timestamp']}] [{$log['level']}]\n";
echo $log['message'] . "\n\n";
}
// エラーのみ表示
$errors = LogProcessor::filterLogByLevel($logFile, 'ERROR');
print_r($errors);
例4: JSONデータの処理
class JsonDataHandler {
/**
* 特殊文字を含むデータをJSON用に準備
*/
public static function prepareForJson($data) {
if (is_array($data)) {
return array_map([self::class, 'prepareForJson'], $data);
}
if (is_string($data)) {
// バックスラッシュなどをエスケープ
return addcslashes($data, "\0..\37");
}
return $data;
}
/**
* JSONから復元
*/
public static function restoreFromJson($data) {
if (is_array($data)) {
return array_map([self::class, 'restoreFromJson'], $data);
}
if (is_string($data)) {
return stripcslashes($data);
}
return $data;
}
/**
* 安全にJSONをデコード
*/
public static function safeJsonDecode($json) {
$data = json_decode($json, true);
if (json_last_error() !== JSON_ERROR_NONE) {
throw new Exception('JSON decode error: ' . json_last_error_msg());
}
return self::restoreFromJson($data);
}
}
// 使用例
$data = [
'name' => 'John Doe',
'message' => "Hello\nWorld\tTest",
'path' => 'C:\Users\Documents'
];
$prepared = JsonDataHandler::prepareForJson($data);
$json = json_encode($prepared);
echo "JSON: " . $json . "\n";
$decoded = JsonDataHandler::safeJsonDecode($json);
print_r($decoded);
例5: CSVファイルの処理
class CsvHandler {
/**
* CSVフィールドをエスケープ
*/
public static function escapeField($field) {
// 改行、タブ、カンマをエスケープ
return addcslashes($field, "\n\r\t,");
}
/**
* CSVフィールドを復元
*/
public static function unescapeField($field) {
return stripcslashes($field);
}
/**
* CSV行を生成
*/
public static function generateCsvLine($fields) {
$escaped = array_map([self::class, 'escapeField'], $fields);
return implode(',', $escaped);
}
/**
* CSV行をパース
*/
public static function parseCsvLine($line) {
$fields = explode(',', $line);
return array_map([self::class, 'unescapeField'], $fields);
}
/**
* CSVファイルに書き込む
*/
public static function writeCsv($filename, $data) {
$lines = [];
foreach ($data as $row) {
$lines[] = self::generateCsvLine($row);
}
return file_put_contents($filename, implode("\n", $lines));
}
/**
* CSVファイルを読み込む
*/
public static function readCsv($filename) {
if (!file_exists($filename)) {
return [];
}
$lines = file($filename, FILE_IGNORE_NEW_LINES);
$data = [];
foreach ($lines as $line) {
$data[] = self::parseCsvLine($line);
}
return $data;
}
}
// 使用例
$data = [
['Name', 'Description', 'Path'],
['John Doe', "Line 1\nLine 2", 'C:\Users\John'],
['Jane Smith', 'Simple, text', 'D:\Documents'],
];
// CSVに書き込む
CsvHandler::writeCsv('data.csv', $data);
// CSVから読み込む
$loaded = CsvHandler::readCsv('data.csv');
print_r($loaded);
// 元のデータと一致するか確認
var_dump($data === $loaded);
例6: シリアライズデータの処理
class SerializedDataHandler {
/**
* データをシリアライズして保存
*/
public static function serialize($data) {
$serialized = serialize($data);
// バイナリセーフなエスケープ
return addcslashes($serialized, "\0..\37");
}
/**
* シリアライズされたデータを復元
*/
public static function unserialize($data) {
$unescaped = stripcslashes($data);
return unserialize($unescaped);
}
/**
* ファイルに保存
*/
public static function saveToFile($filename, $data) {
$serialized = self::serialize($data);
return file_put_contents($filename, $serialized);
}
/**
* ファイルから読み込み
*/
public static function loadFromFile($filename) {
if (!file_exists($filename)) {
return null;
}
$content = file_get_contents($filename);
return self::unserialize($content);
}
}
// 使用例
$data = [
'user' => 'admin',
'settings' => [
'theme' => 'dark',
'language' => 'ja',
'notifications' => true
],
'last_login' => time()
];
// ファイルに保存
SerializedDataHandler::saveToFile('session.dat', $data);
// ファイルから読み込み
$loaded = SerializedDataHandler::loadFromFile('session.dat');
print_r($loaded);
// 一致確認
var_dump($data == $loaded);
例7: コマンドライン引数の処理
class CommandLineHelper {
/**
* 引数をエスケープ
*/
public static function escapeArgument($arg) {
// スペース、タブ、改行をエスケープ
return addcslashes($arg, " \t\n\r");
}
/**
* 引数を復元
*/
public static function unescapeArgument($arg) {
return stripcslashes($arg);
}
/**
* コマンドライン文字列を生成
*/
public static function buildCommandLine($command, $args) {
$escapedArgs = array_map([self::class, 'escapeArgument'], $args);
return $command . ' ' . implode(' ', $escapedArgs);
}
/**
* コマンドライン文字列をパース
*/
public static function parseCommandLine($commandLine) {
$parts = explode(' ', $commandLine);
$command = array_shift($parts);
$args = array_map([self::class, 'unescapeArgument'], $parts);
return [
'command' => $command,
'args' => $args
];
}
}
// 使用例
$command = 'myapp';
$args = [
'--input=file with spaces.txt',
"--message=Line 1\nLine 2",
'--verbose'
];
// コマンドライン文字列を生成
$commandLine = CommandLineHelper::buildCommandLine($command, $args);
echo "コマンドライン:\n{$commandLine}\n";
// パース
$parsed = CommandLineHelper::parseCommandLine($commandLine);
print_r($parsed);
stripslashes()との違い
// stripslashes(): シンプルなバックスラッシュの除去
$str1 = "Hello\\nWorld";
echo stripslashes($str1) . "\n";
// 出力: Hello\nWorld(バックスラッシュのみ除去、\nは解釈されない)
// stripcslashes(): エスケープシーケンスを解釈
$str2 = "Hello\\nWorld";
echo stripcslashes($str2) . "\n";
// 出力:
// Hello
// World(\nが改行に変換される)
// もう一つの例
$path = "C:\\\\Users\\\\Documents";
echo "stripslashes: " . stripslashes($path) . "\n";
// C:\Users\Documents
echo "stripcslashes: " . stripcslashes($path) . "\n";
// C:\Users\Documents
// 16進数エスケープの違い
$hex = "\\x48\\x65\\x6C\\x6C\\x6F";
echo "stripslashes: " . stripslashes($hex) . "\n";
// \x48\x65\x6C\x6C\x6F(解釈されない)
echo "stripcslashes: " . stripcslashes($hex) . "\n";
// Hello(16進数が解釈される)
注意点と制限事項
バイナリデータの扱い
// NULL文字を含むデータ
$data = "Hello\\0World";
$result = stripcslashes($data);
echo "長さ: " . strlen($result) . "\n"; // 11
echo "表示: " . $result . "\n"; // HelloWorld(NULLは表示されない)
// バイナリセーフな処理が必要な場合は注意
不完全なエスケープシーケンス
// 不完全な16進数エスケープ
$incomplete = "\\x4"; // 1桁のみ
echo stripcslashes($incomplete) . "\n";
// 結果は環境依存
// 不完全な8進数エスケープ
$incomplete = "\\7";
echo stripcslashes($incomplete) . "\n";
パフォーマンス
// 大量のデータ処理
$largeData = str_repeat("Line\\n", 10000);
$start = microtime(true);
$result = stripcslashes($largeData);
$time = microtime(true) - $start;
echo "処理時間: {$time}秒\n";
echo "元のサイズ: " . strlen($largeData) . " bytes\n";
echo "結果のサイズ: " . strlen($result) . " bytes\n";
実用的なヘルパークラス
class EscapeHelper {
/**
* 安全にエスケープ
*/
public static function safeCslashesEncode($data) {
if (is_string($data)) {
return addcslashes($data, "\0..\37");
}
if (is_array($data)) {
return array_map([self::class, 'safeCslashesEncode'], $data);
}
return $data;
}
/**
* 安全にアンエスケープ
*/
public static function safeCslashesDecode($data) {
if (is_string($data)) {
return stripcslashes($data);
}
if (is_array($data)) {
return array_map([self::class, 'safeCslashesDecode'], $data);
}
return $data;
}
/**
* エスケープシーケンスを可視化
*/
public static function visualizeEscapes($string) {
$replacements = [
"\n" => "\\n",
"\r" => "\\r",
"\t" => "\\t",
"\0" => "\\0",
"\\" => "\\\\"
];
return strtr($string, $replacements);
}
}
// 使用例
$data = [
'text' => "Line 1\nLine 2",
'path' => 'C:\Users\Documents',
'nested' => [
'field' => "Tab\tSeparated"
]
];
$encoded = EscapeHelper::safeCslashesEncode($data);
echo "エンコード後:\n";
print_r($encoded);
$decoded = EscapeHelper::safeCslashesDecode($encoded);
echo "\nデコード後:\n";
print_r($decoded);
// 可視化
echo "\n可視化:\n";
echo EscapeHelper::visualizeEscapes($data['text']) . "\n";
まとめ
stripcslashes()関数の特徴をまとめると:
できること:
- Cスタイルのエスケープシーケンスを解釈
addcslashes()の逆操作- 16進数・8進数表記の変換
- NULL文字の処理
主なエスケープシーケンス:
\n: 改行\t: タブ\r: 復帰\\: バックスラッシュ\xHH: 16進数\OOO: 8進数
推奨される使用場面:
- 設定ファイルの読み込み
- ログファイルの処理
- データベースからのデータ復元
- シリアライズデータの処理
- CSVファイルの処理
注意点:
- バイナリデータの扱いに注意
- 不完全なエスケープシーケンス
- NULL文字を含むデータ
関連関数:
addcslashes(): Cスタイルでエスケープstripslashes(): バックスラッシュのみ除去addslashes(): クォートをエスケープ
stripcslashes()はaddcslashes()とペアで使用することで、特殊文字を含むデータを安全に保存・復元できます。適切に使いこなすことで、堅牢なデータ処理システムを構築できます!
