🤯

アクセスカウンター:SQLiteデータベース編

2024/08/12に公開

この記事について

この記事は、アクセスカウンターの連載記事です。

https://zenn.dev/phpbeginners/books/49b9ede3c8c30e/viewer/62bec3

この記事の動作サンプルはこちら

この記事のプログラムには問題を仕込んであります

この記事のプログラムには、色々な問題を隠しています!必ず最後まで記事を読んで下さい。

データベースが分からない方へ

この記事は、データベースの知識がなくても、プログラムできるように構成されています。

もしデータベース編につまずいたら

アクセスカウンターには、データベース編とファイル編があります。
もしデータベース編につまづいたら、ファイル編に挑戦してみて下さい❗
https://zenn.dev/phpbeginners/articles/9cb6d030c1ce57
https://zenn.dev/phpbeginners/articles/f2780aba2b6548
https://zenn.dev/phpbeginners/articles/51412cf018d50b

MySQL編もありますので、MySQL編に挑戦してみるのもいいと思います。
https://zenn.dev/phpbeginners/articles/a3087d4aaeefc1

この記事で学習できる内容

  1. SQLiteデータベースにアクセスする方法
  2. SQL文の基本的な書き方。
    3. SELECT: データベースからデータ(レコード)を取得する方法
    3. INSERT: 新しいレコードを挿入する方法
    4. UPDATE: 既にあるレコードを更新する方法
  3. ファイル・パーミッション(権限)

この記事のデータベースは、SQLiteを利用しています

PHPで主に使われるデータベースは MySQL ですが、SQL の勉強なら、どちらを使っても大差ありません。

MySQLとは

PHPで主に使われるデータベースです。XAMPPをインストールすると自動的にインストールされます。
MySQLを使うには、自分で、データベース・テーブル・アカウントの設定を行う必要があります。
SQLiteなら、アカウントの設定が必要なく、データベースはファイル形式なのでダウンロードをするだけで使えます。

SQLiteとは

SQLite とは、データベースがサーバー(デーモン)形式ではなく、ファイル形式で読み書きするデータベースです。ファイル形式なので、SQLiteサーバー などをインストールする必要がなく、言語側(PHP)のドライバーだけで読み書きできます。

この記事の課題になるデータベースは、以下のURLからダウンロードできます。
ダウンロードしたSQLite形式のデータベース・ファイルを適切なパスにコピーして下さい。
http://zen.phpbeginners.net/article/database/count.sqlite3

データベースのテーブルの構造

データベースのテーブルの構造は以下のようになっています。

SQLiteデータベースの作成・修正をするソフト

DB Browser for SQLite というソフトを使うと、SQLiteのデータベースを作成・修正ができます。
https://sqlitebrowser.org/

⚠注意⚠

このプログラムをMacやLinuxのApache Webサーバーで実行すると、パーミッション(権限)の問題が発生します。Windows上のApacheでは発生しません。(Windowsのパーミッションは、MacやLinuxと異なるからです)

パーミッションの解決方法は、あえて記事中に記載しませんでした。

インターネット検索やChatGPTで頑張って調べて解決してみて下さい❗
LINEのオープンチャットで質問して貰っても構いません。
https://line.me/ti/g2/VzA0pNDlUBijLGr67gbpi-K0TtyeD5Tr3taV7g?utm_source=invitation&utm_medium=link_copy&utm_campaign=default

もしパーミッションについて詰まったら PHP Built-in WebServer を使ってみて下さい。
こちらはパーミッションの問題が起こりません❗
https://zenn.dev/phpbeginners/articles/b53847bf620961

プログラム

今回のプログラムもコメントは3点リーダーになっています。自分でコメントを埋めてみて下さい。

一度に全部を書くと疲れるので、上の行から少しずつ追加して、動かして確認しながらプログラムを書いていくとよいと思います。

今回のデータベース編も日付毎にアクセス数をカウントしています。

<?php
//	...
error_reporting(E_ALL);

//	...
date_default_timezone_set('Asia/Tokyo');

//	...
$database_path = 'database/count.sqlite3';

//	...
if(!file_exists($database_path) ){
	$current_directory = getcwd();
	exit("<p style='color:red;'>Database file does not exist. ($current_directory, $database_path)</p>");
}

//	...
if(!is_writable($database_path) ){
	exit("<p style='color:red;'>Database file does not writable. ($database_path)</p>");
}

//	...
if(!is_writable( $dirname = dirname($database_path) ) ){
	exit("<p style='color:red;'>Database directory does not writable. ($dirname)</p>");
}

//	...
if(!class_exists('PDO') ){
	exit('<p style="color:red;">PDO is not installed.</p>');
}

//	...
$pdo = new PDO("sqlite:$database_path");

//	...
if( empty($pdo) ){
	exit("<p style='color:red;'>POD is empty.</p>");
}

//	...
$date   = date('Y-m-d');
$sql    = "SELECT count FROM t_count WHERE date='$date'";
$result = $pdo->query($sql);
$record = $result->fetch();
$count  = $record['count'] ?? null;

//	...
if( empty($count) ){
	$count = 1;
	$sql = "INSERT INTO t_count (date, count) VALUES('$date','$count');";
}else{
	$count++;
	$sql = "UPDATE t_count SET count='$count' WHERE date='$date'";
}
$result = $pdo->query($sql);

//	...
echo "{$date}: $count<br/>";

うまく動きましたか❓

もしうまく動かなかったら、どこでつまづいているのか、LINEやXで質問して下さい。

もしうまく動いていたら

おめでとうございます❗
それでは、このプログラムをもっと改造してみましょう。プログラミングが上達する方法の一つは、改造です❗

昨日のアクセス数をもとめる

この記事のプログラムでは、今日のアクセス数しかカウントしていません。
昨日のアクセス数も取得するように改造してみましょう❗

昨日と今日のアクセス数の合計をもとめる

昨日と今日の合計アクセス数をもとめてみましょう❗

今月のアクセス数をもとめる

今月のアクセス数を計数してみましょう❗
さらに、今月だけでなく、先月のアクセス数も取得してみましょう❗

今月、先月、先々月のアクセス数をもとめる

実は、今月、先月、先々月で、アクセス数をもとめる方法が微妙に変わります。
よりテクニカルなもとめ方を考えてみましょう❗

すべてのアクセス数をもとめる

全アクセス数を計算するように改造してみましょう❗

不具合1

実は、この記事のプログラムでは、ある仕様上の不具合があります。お気づきになりましたか?[1]

この記事のプログラムでは、同時に複数人がアクセスすると、正しくカウントしない可能性があります。[2]

課題1

さて、どうして複数人が同時にアクセスすると、正しくカウントできないのでしょうか?

課題2

それでは、複数人が同時にアクセスしても、正しくカウントするようにするには、どうすればいいでしょうか?

不具合2

この記事のプログラムをそのまま使うと、重大なセキュリティインシデント(個人情報の漏洩など)を引き起こす可能性のあるプログラムを作る可能性があります。[2:1]

課題3

なぜ、この記事のプログラムをそのまま使うと、重大なセキュリティインシデント(個人情報の漏洩など)を引き起こす可能性のあるプログラムを作る可能性があるのでしょうか?

課題4

それでは、重大なセキュリティインシデント(個人情報の漏洩など)を引き起こさないようにするには、どのような書き方をすれば良いのでしょうか?

ヒント

ヒントは最初に読まずに、課題のプログラムに詰まったり、完成してから、正解を確認するのに使って下さい。

パーミッションについて

パーミッションとは、直訳すると権限です。所有者・グループ・全員に、書き込み・読み込み・実行の権限を付けられます。

通常はコマンドラインで、chownでオーナーを変更したり、chmodで権限を付けたり外したりしますが、MacもWindowsもGUIで変更できます。Macの場合は、ファイルを選択した状態で⌘+Iを押すと、そのファイルに関する情報が見れますが、権限の変更をするGUIも用意されています❗

日付の指定には大なり(>)小なり(<)が使えます

SELECT文で使うWHEREは、取得するレコードを指定しますが、=だと値が一致するレコードだけを取得します。
しかし、date < '2024-08-15'とすると、2024-08-15以下のレコード全てに一致するようになります❗

データベースに保存されている過去のアクセス数をもとめる方法

SQLには集計関数があります。
集計関数を調べてみましょう❗

脚注
  1. バグ という単語は、不用意に使ってはなりません。なぜなら、開発者が気分を害するからです。必ず、不具合 と言い換えましょう❗ ↩︎

  2. 断言はなるべく控えましょう。"可能性がある"という表現は、とても良い表現です。 ↩︎ ↩︎

Discussion