カテゴリー
PHP-DB-Web Software Tech

[備忘録]PHP7.4⇒8.0 アップ … ウェブページのデータベース接続構文を変更 | AmpiTa Project

 PHPのバージョンが『非推奨』になって久しいのでアップグレード(アップデート)を決行しました。

 単にPHPのバージョンを7.xから8.xへ移行(Migrating)しただけではデータベースでエラーが発生してしまいます。

 認証方法が変わったことが原因のようなので、phpプログラムも更新しました。




  1. 多くなった『データベース接続確立エラー』
  2. PHPのバージョン
  3. データベースの挙動
  4. 下位互換性のない変更点
  5. 更新作業1.データベース接続
  6. 更新作業2.クエリの実行
  7. 更新作業3.レコード数とページ数
  8. PHP8.x対応コード
  9. データベースチェック
  10. おわりに



多くなった『データベース接続確立エラー』

 手前どもが管理しているウェブサイトがいくつかありますが、閲覧している最中に『データベース接続確立エラー』という表示が出てしまう事がときどきあります。

 おそらく1カ月くらい前から頻繁に見るようになったのですが、普段は自己管理下にあるページを見ないので、もしかするとずっと前からあったのかもしれません。

WordPressデータベース接続確立エラー
WordPressデータベース接続確立エラー

 WordPressの管理ページを開いている際にエラーが発生すると下図のようにコメント付きの画面が表示されます。

データベース接続確立エラー
 これは、wp-config.php ファイルのユーザー名とパスワードが正しくないか、あるいは mysql77.sakura.sakura.ne.jp のデータベースサーバーに接続できないかのどちらかを意味します。ホスティングサービスのデータベースサーバーがダウンしているかもしれません。
○ユーザー名とパスワードに間違いはありませんか?
○正しいホスト名を入力しましたか?
○データベースサーバーは動作中ですか?
 こうした用語が何を意味しているのか分からない場合は、ホスティングサービスに連絡するべきでしょう。助けが必要であればいつでも WordPres
WordPressデータベース接続確立エラー

データベース接続確立エラー

 これは、wp-config.php ファイルのユーザー名とパスワードが正しくないか、あるいは mysql77.sakura.sakura.ne.jp のデータベースサーバーに接続できないかのどちらかを意味します。ホスティングサービスのデータベースサーバーがダウンしているかもしれません。

  • ユーザー名とパスワードに間違いはありませんか?
  • 正しいホスト名を入力しましたか?
  • データベースサーバーは動作中ですか?

 こうした用語が何を意味しているのか分からない場合は、ホスティングサービスに連絡するべきでしょう。助けが必要であればいつでも WordPress サポートフォーラムを訪れることができます。

データベース接続確立エラー




PHPのバージョン

 私たちが契約しているさくらインターネットのレンタルサーバでは、以下のバージョンのPHPを利用できます。

バージョン推奨サポート
PHP 8.3推奨サポート中
PHP 8.2推奨サポート中
PHP 8.1非推奨サポート終了予定
PHP 8.0非推奨サポート終了
PHP 7.4非推奨サポート終了
PHP 5.6非推奨サポート終了
PHP 5.4非推奨サポート終了
PHP 5.3非推奨サポート終了
PHP 5.2非推奨サポート終了

 データベースを利用しているのはWordPressと独自データを掲載したPHPページです。

 WordPressはPHPのバージョンを変更しても問題なさそうです。最新バージョンへの即日対応を目指しているとのことで、私たちのように最新版公開から遅れて変更する者には問題が無いように見えます。

WordPress は PHP の新しいバージョンがリリースされた当日に可能な限りサポートすることを目指しています。プロジェクトとして、これらの新しいバージョンをサポートするプロセスは、それぞれの新しい PHP バージョンが機能フリーズを迎え、ベータ版にタグ付けされたあとに開始されます。これにより、計画した機能が削除されたり実装が変更されたりしても、WordPress を元に戻したり追加の機能を加える必要がなくなります。
PHPの互換性とWordPressのバージョン

 ウェブサイトのアクセス数が減ってしまうことを脅威とみなして、PHPバージョンを最新のものに変更しました。

さくらのレンサバ・コントロールパネル
さくらのレンサバ・コントロールパネル




データベースの挙動

 正常な状態であれば、下図のように表(テーブル)が表示されます。

MeKiKiデータベース(PHPを活用した公開データベース)
PHPを活用した公開データベース(MeKiKiデータベース)

 しかしながら、PHP7.4で正常に動作していたデータベース表示ページは、PHP8.0以降のバージョンでは表示されません。

 PHPのウェブページが接続エラーになる訳ではなく、データベースへの接続に失敗している点が注目すべきところだと思いました。

データベースエラー
データベースエラー

 画面の最上段に表示されている内容は以下のとおりでした。

Error: SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens

PHP7.4向けデータベースをPHP8.xバージョンで表示した場合のエラー

 英語なので、日本語に訳してみると以下のとおりパラメーターの異常であることがわかります。

エラー:
SQLSTATE[HY093]:
パラメータ番号が無効です:
バインドされた変数の数がトークンの数と一致しません。

DeepLで翻訳

 このエラー番号『HY093』は、PHP のエラー、かつ、PDO を利用しているときのエラーです。

 PHPの構文は何も書き換えていない状態で、PHPのバージョンだけ変更したときに現れるので、書き間違いではなく、そもそもこれまで使っていたPDO(PHP Data Objects)が使えないということを示唆しています。

【参考】MeKiKi:医療機器検索(クラス分類表/一般的名称)




下位互換性のない変更点

 『PHPマニュアル』というウェブサイトによると、『PHP 7.4.x から PHP 8.0.x への移行』において『下位互換性のない変更点』が挙げられています。

下位互換性のない変更点
下位互換性のない変更点

 そのページには PDO MySQL という項目もありました。

PDO::inTransaction() は、 PDO が管理しているおおよその情報ではなく、 実際のトランザクションの状態を報告するようになりました。 クエリが “暗黙のコミット” に依存していた場合、 PDO::inTransaction() は後に false を返します。 なぜなら、トランザクションが既にアクティブではないからです。

PDO MySQL

 わかる人にはわかる文章なのかもしれませんが、まず『トランザクション』とはデータベースの実行や管理などの処理の仕組みみたいなものです。それが『アクティブ』ということは、処理が実行されている、実行できる状態にあるようなときだと思います(詳しくないのでわかりませんが)。

 処理に伴って『暗黙のコミット』が存在したようですが、それができなくなるという内容だと思います。
 すなわち、PDOの処理(トランザクション)後に自動的に行われていた暗黙的なコミットが行われない、その時点で false を返すということで、処理が止まることを意味している、かなと思います。

 『PHPマニュアル』というウェブサイトには『MySQL 関数 (PDO_MYSQL) 』というページもあり、そちらにMySQL 8 という項目がありました。こちらには PDO に関する記述がたくさんありますが、理解できませんでした。

MySQL 関数(PDO MYSQL)
MySQL 関数(PDO MYSQL)

 とりあえず、PDOは使えなくなったので、新たなMySQLの利用方法を考えてください、ということのようです。

【参考】PHPマニュアル




更新作業1.データベース接続

 元のコードでは、下記のような記述でした。

$dsn = 'mysql:host=mysql777.db.sakura.ne.jp;dbname=データベース名;charset=utf8';
$user = 'ユーザー名';
$password = 'SQLのパスワード';
$dbh = new PDO($dsn, $user, $password);
(以下省略)

 変数『$dsn』に『mysql』『dbname』『charset』の順でデータを登録しておき、『$dbh』で PDO を実行する内容でした。

 新しいコードでは PDO の代わりに mysqli を使います。以下のコードに書き換えました。

$servername = 'mysql777.db.sakura.ne.jp';
$dbname = 'データベース名';
$username = 'ユーザー名';
$password = 'SQLのパスワード';
$connsql= new mysqli($servername, $username, $password, $dbname);
if ($connsql->connect_error) 
{
	die("Connection failed: ".$connsql->connect_error);
	print('Error:'.$e->getMessage());
	$errors['error'] = "データベース接続失敗しました。";
}
(以下省略)

 冒頭で変数にデータを入れていきます。

 SQLに接続するために『new mysqli』で『$connsql』へ処理を渡します。

 『$connsql』にエラーが無い事を『if』で確認します。

 データベースへの接続はこれで確立しました。




更新作業2.クエリの実行

 元のコードでは、下記のような記述でした。

$strSelect = "SELECT * FROM ○○○○";
$strOrderLimit = " ORDER BY ".$Sort_ID;
$statement = $dbh->prepare($strSelect.$strWhere.$strOrderLimit);
if($statement)
{
	$like_Kobetsu_ID = "%".$Kobetsu_ID."%";
	$statement->bindValue('1', $Kobetsu_ID, PDO::PARAM_STR);
	if($statement->execute())
	{
		$row_count = $statement->rowCount();
		while($row = $statement->fetch())
		{
			$rows[] = $row;
			$General_Name = $row['項目名'];
		}
	}
	else
	{
		$errors['error'] = "検索失敗しました。";
	}
	$dbh = null;	
}

 正しいデータが『$statement』に格納されていれば、それを1行ずつ読込んで『$row』として扱えるようにしてください、といった処理です。その処理は PDO で行われています。

 新しいコードでは、接続が mysqli で接続が確立している『$connsql』にクエリ『$sql』を適用して実行します。
 該当するデータが1件以上であれば表示のための処理を実行します。件数を取得し、その件数分だけwhileで循環させるという処理は旧構文と同じです。

 最後に『$connsql->close』で接続を切断します。

$sql = $strSelect.$strWhere.$strOrderLimit;
$result = $connsql->query($sql);
if ($result->num_rows > 0)
{
	$row_count = $result->num_rows;
	while($row = $result->fetch_assoc()) 
	{
		$rows[] = $row;
		$General_Name = $row['項目名'];
	}
}
else
{
	$errors['error'] = "データは0件です。";
}
$connsql->close();




更新作業3.レコード数とページ数

 レコード数が多いデータベースでは、1度に表示する件数を抑えていました。多い物ですと100万件を超えるデータが格納されているので、全件表示は不可能でした。

 元のコードでは、下記のような記述でした。全部で何件あるかを『$Max_row_count』に格納、それを1回の表示上限数である変数『MAX』で除して『ceil』で整数化してページ数を取得するという記述です。

$Max_statement = $dbh->prepare($strSelect.$strWhere);
if($Max_statement)
{
	if($Max_statement->execute())
	{
		$Max_row_count = $Max_statement->rowCount();
		$Max_Page = ceil($Max_row_count / MAX);
	}
}

 新しいコードでも実施内容は同じです。『$sql_max』と『$result_max』は最大値を取得するための処理ですが、内容はクエリの実行と同じです。

$sql_max = $strSelect.$strWhere;
$result_max = $connsql->query($sql_max);
$Max_row_count = $result_max->num_rows;
$Max_Page = ceil($Max_row_count / MAX);




PHP8.x対応コード

 実際にPHP8.3でも動作したPHP構文は以下のとおりです。一部、機密に関わる部分は差し替えてます。参考程度にご覧ください。

$servername = 'mysql777.db.sakura.ne.jp';
$dbname = 'データベース名';
$username = 'ユーザー名';
$password = 'SQLのパスワード';
$connsql = new mysqli($servername, $username, $password, $dbname);
if ($connsql->connect_error) 
{
	die("Connection failed: " . $connsql->connect_error);
	print('Error:'.$e->getMessage());
	$errors['error'] = "データベース接続失敗しました。";
}
$strWhere = "";
$strShubetsu = '全件表示';
ini_set("memory_limit", "3072M");
$strSelect = "SELECT * FROM ○○○○ a left join ◇◇◇◇ b on a.項目1 = b.項目2";
$strOrderLimit = " ORDER BY ".$Sort_ID." " Desc LIMIT ".$RecordNumber.", ".MAX;

$sql_max = $strSelect.$strWhere;
$result_max = $connsql->query($sql_max);
$Max_row_count = $result_max->num_rows;
$Max_Page = ceil($Max_row_count / MAX);

$sql = $strSelect.$strWhere.$strOrderLimit;
$result = $connsql->query($sql);
if ($result->num_rows > 0)
{
	$row_count = $result->num_rows;
	while($row = $result->fetch_assoc()) 
	{
		$rows[] = $row;
		$General_Name = $row['項目3'];
		$Class_1_4 = $row['項目4'];
	}
}
else
{
	$errors['error'] = "検索は失敗しました。";
}
$connsql->close();




データベースチェック

 更新作業を終えたデータベースをすべて確認していきました。全件表示、キーワード検索などを実施して正常動作を確認しました。


医療機器クラス分類表検索

医療機器クラス分類・一般的名称一覧検索(一般的名称・類別名称・中分類名)

医療機器クラス分類表検索

医療機器名称検索(項目選択): 一般的名称 中分類名 類別名称

医療機器回収・改修情報検索(PMDA+MHLW)

回収情報: 一般的名称 クラス分類コード 販売名 企業名

医療機器認証・承認基準検索(PMDA)

認証基準名称検索(項目選択): 一般的名称 認証基準名称

医療機器添付文書検索(PMDA)

医療機器JANコードを入力

サンプルデータ:04582270690137


医療機関検索(医科・歯科)

医療機関(病院・診療所): 医療機関名 都道府県 所在地 院長名 標榜科目

保険調剤薬局検索

保険調剤薬局:
医療機関名 都道府県 所在地 開設者 管理者 標榜科目


医療機関施設基準検索

医療機関: 届出名称 記号

地域防災計画都市別データベース

フリーワード検索(項目選択): 市町村名 都道府県

災害アーカイブ(デジタル画像検索)

項目選択: 災害名  撮影場所  データ提供者  ファイル名  関連タグ 




おわりに

 今回はPHPのバージョンを非推奨から推奨へ、7.4から8.3へとアップグレード(アップデート)しました。

 それに伴い、PHPウェブページで表示していたデータベースが接続不可となったため、コードの書き換えを行いました。新しい構文を使わなければならないので、正常動作に辿り着くまでに時間を要し、その後の検証もエラーが出そうな箇所がわからないので時間がかかりました。

 とりあえず、この記事を書き終えている時点では問題ありません。

 変更動機となった、WordPressページの表示エラー、データベース接続エラーについては、改善されたかわかりません。PHPのバージョンの問題であったとすれば、今後は大丈夫だと思いますが、様子観察して参ります。

「[備忘録]PHP7.4⇒8.0 アップ … ウェブページのデータベース接続構文を変更 | AmpiTa Project」への2件の返信