はじめに
PHPでMySQLデータベースを動的に作成する方法を調べていて、mysql_create_db
という関数に出会ったことはありませんか?この関数は、かつてPHPスクリプトからMySQLデータベースを作成するために使用されていましたが、現在は**非推奨(deprecated)**となり、PHP 7.0で完全に削除されました。
この記事では、mysql_create_db
関数について詳しく解説し、なぜ使用が推奨されなくなったのか、そして現在推奨される安全で効率的なデータベース作成方法について分かりやすく説明します。
mysql_create_db関数とは?
mysql_create_db
は、PHPスクリプトからMySQLサーバー上に新しいデータベースを作成するために使用されていた関数です。PHP 4.0から利用可能でしたが、セキュリティ上の問題や機能の制限により、PHP 5.5.0で非推奨となりました。
基本的な構文
bool mysql_create_db(string $database_name [, resource $link_identifier])
パラメータの説明
- $database_name: 作成するデータベース名
- $link_identifier: MySQLリンク識別子(省略時は最後にオープンされた接続を使用)
戻り値
- 成功時: TRUE
- 失敗時: FALSE
使用例(参考のみ – 使用不可)
<?php
// 注意: この方法は非推奨で、現在は使用できません!
$connection = mysql_connect('localhost', 'username', 'password');
if (!$connection) {
die('接続に失敗しました: ' . mysql_error());
}
$database_name = 'my_new_database';
$result = mysql_create_db($database_name, $connection);
if ($result) {
echo "データベース '$database_name' が正常に作成されました";
} else {
echo 'データベースの作成に失敗しました: ' . mysql_error();
}
mysql_close($connection);
?>
なぜmysql_create_db関数は非推奨になったのか?
1. セキュリティの脆弱性
mysql_create_db
を含む古いMySQL拡張機能は、以下のセキュリティ問題を抱えていました:
- SQLインジェクション攻撃に対する十分な保護機能の欠如
- 入力値の検証が不十分
- 権限管理の問題
2. 機能の制限
- 文字セットの指定ができない
- **照合順序(Collation)**の設定ができない
- 詳細なエラー情報が取得できない
- プリペアドステートメントのサポートなし
3. 設計思想の変化
現代のWeb開発では、データベースの作成は通常、アプリケーションレベルではなく、データベース管理者や専用の管理ツールで行うことが一般的になりました。
現在推奨される代替手段
1. MySQLi(MySQL Improved)を使用した方法
MySQLiを使用してデータベースを作成する現代的な方法です。
<?php
// 手続き型スタイル
$connection = mysqli_connect('localhost', 'username', 'password');
if (!$connection) {
die('接続に失敗しました: ' . mysqli_connect_error());
}
$database_name = 'my_new_database';
$query = "CREATE DATABASE `$database_name` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci";
if (mysqli_query($connection, $query)) {
echo "データベース '$database_name' が正常に作成されました";
} else {
echo 'データベースの作成に失敗しました: ' . mysqli_error($connection);
}
mysqli_close($connection);
?>
<?php
// オブジェクト指向スタイル
$mysqli = new mysqli('localhost', 'username', 'password');
if ($mysqli->connect_error) {
die('接続に失敗しました: ' . $mysqli->connect_error);
}
$database_name = 'my_new_database';
$query = "CREATE DATABASE `$database_name` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci";
if ($mysqli->query($query)) {
echo "データベース '$database_name' が正常に作成されました";
} else {
echo 'データベースの作成に失敗しました: ' . $mysqli->error;
}
$mysqli->close();
?>
2. PDO(PHP Data Objects)を使用した方法
PDOを使用したより安全で汎用的な方法です。
<?php
$host = 'localhost';
$username = 'username';
$password = 'password';
try {
// まず接続(データベース指定なし)
$pdo = new PDO("mysql:host=$host", $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$database_name = 'my_new_database';
$query = "CREATE DATABASE `$database_name` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci";
$pdo->exec($query);
echo "データベース '$database_name' が正常に作成されました";
} catch (PDOException $e) {
echo 'データベースの作成に失敗しました: ' . $e->getMessage();
}
?>
3. プリペアドステートメントを使用した安全な方法
データベース名が動的な場合でも安全に処理する方法:
<?php
function createDatabaseSafely($host, $username, $password, $database_name) {
try {
$pdo = new PDO("mysql:host=$host", $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// データベース名の検証
if (!preg_match('/^[a-zA-Z0-9_]+$/', $database_name)) {
throw new InvalidArgumentException('無効なデータベース名です');
}
// 安全な方法でクエリを作成
$query = "CREATE DATABASE `" . str_replace('`', '``', $database_name) . "`
CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci";
$pdo->exec($query);
return "データベース '$database_name' が正常に作成されました";
} catch (PDOException $e) {
return 'データベースの作成に失敗しました: ' . $e->getMessage();
} catch (InvalidArgumentException $e) {
return 'エラー: ' . $e->getMessage();
}
}
// 使用例
echo createDatabaseSafely('localhost', 'username', 'password', 'my_new_database');
?>
高度なデータベース作成オプション
現代の方法では、より詳細な設定が可能です:
文字セットと照合順序の指定
<?php
// 日本語対応の設定
$query = "CREATE DATABASE `my_database`
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci";
// 英語のみの場合
$query = "CREATE DATABASE `my_database`
CHARACTER SET latin1
COLLATE latin1_swedish_ci";
?>
存在確認付きデータベース作成
<?php
function createDatabaseIfNotExists($pdo, $database_name) {
try {
$query = "CREATE DATABASE IF NOT EXISTS `$database_name`
CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci";
$pdo->exec($query);
return "データベースの確認/作成が完了しました";
} catch (PDOException $e) {
return 'エラー: ' . $e->getMessage();
}
}
?>
セキュリティベストプラクティス
1. 入力値の検証
<?php
function validateDatabaseName($name) {
// 英数字とアンダースコアのみ許可
if (!preg_match('/^[a-zA-Z0-9_]+$/', $name)) {
return false;
}
// 長さの制限
if (strlen($name) > 64) {
return false;
}
// MySQLの予約語チェック(一部)
$reserved = ['information_schema', 'mysql', 'performance_schema', 'sys'];
if (in_array(strtolower($name), $reserved)) {
return false;
}
return true;
}
?>
2. 権限の最小化
<?php
// データベース作成専用ユーザーの使用例
$db_admin_user = 'db_creator'; // CREATE権限のみを持つユーザー
$db_admin_pass = 'secure_password';
try {
$pdo = new PDO("mysql:host=localhost", $db_admin_user, $db_admin_pass);
// データベース作成処理
} catch (PDOException $e) {
// エラーハンドリング
}
?>
エラーハンドリングと例外処理
<?php
class DatabaseManager {
private $pdo;
public function __construct($host, $username, $password) {
try {
$this->pdo = new PDO("mysql:host=$host", $username, $password);
$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
throw new Exception('データベース接続に失敗しました: ' . $e->getMessage());
}
}
public function createDatabase($name, $charset = 'utf8mb4', $collate = 'utf8mb4_unicode_ci') {
if (!$this->validateDatabaseName($name)) {
throw new InvalidArgumentException('無効なデータベース名です');
}
try {
$query = "CREATE DATABASE `" . str_replace('`', '``', $name) . "`
CHARACTER SET $charset COLLATE $collate";
$this->pdo->exec($query);
return true;
} catch (PDOException $e) {
if ($e->getCode() == '42000') {
throw new Exception("データベース '$name' は既に存在します");
}
throw new Exception('データベースの作成に失敗しました: ' . $e->getMessage());
}
}
private function validateDatabaseName($name) {
return preg_match('/^[a-zA-Z0-9_]+$/', $name) && strlen($name) <= 64;
}
}
// 使用例
try {
$dbManager = new DatabaseManager('localhost', 'username', 'password');
$dbManager->createDatabase('my_new_database');
echo 'データベースが正常に作成されました';
} catch (Exception $e) {
echo 'エラー: ' . $e->getMessage();
}
?>
パフォーマンスとメンテナンス性の考慮
1. 接続の再利用
<?php
class DatabaseCreator {
private static $pdo = null;
private static function getConnection() {
if (self::$pdo === null) {
self::$pdo = new PDO("mysql:host=localhost", 'username', 'password');
self::$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
return self::$pdo;
}
public static function createDatabase($name) {
$pdo = self::getConnection();
// データベース作成処理
}
}
?>
2. ログ機能の実装
<?php
function createDatabaseWithLog($name) {
$logFile = 'database_creation.log';
$timestamp = date('Y-m-d H:i:s');
try {
// データベース作成処理
$pdo = new PDO("mysql:host=localhost", 'username', 'password');
$query = "CREATE DATABASE `$name` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci";
$pdo->exec($query);
// 成功ログ
file_put_contents($logFile, "[$timestamp] SUCCESS: Database '$name' created\n", FILE_APPEND);
return true;
} catch (Exception $e) {
// エラーログ
file_put_contents($logFile, "[$timestamp] ERROR: Failed to create database '$name' - " . $e->getMessage() . "\n", FILE_APPEND);
return false;
}
}
?>
まとめ
mysql_create_db
関数は過去のPHP開発において重要な役割を果たしましたが、セキュリティと機能の観点から現在は使用すべきではありません。
重要なポイント
- mysql_create_db は PHP 7.0 で完全に削除済み
- MySQLi または PDO を使用して現代的な方法でデータベースを作成
- セキュリティ対策(入力値検証、権限の最小化)を必ず実装
- エラーハンドリングを適切に行う
- 文字セットと照合順序を明示的に指定
推奨事項
- 新規プロジェクト: PDO または MySQLi を使用
- セキュリティ: 入力値の検証を必須とする
- 保守性: クラスベースの設計を検討
- ログ: データベース作成の記録を残す
- 権限管理: 最小権限の原則に従う
現代のPHP開発においては、セキュリティと保守性を重視した開発手法が求められています。適切な方法でデータベース作成機能を実装し、安全で効率的なWebアプリケーションを構築していきましょう。