こんにちは!
スマレジ・テックファーム の Webエンジニア やまて と申します。
はじめに
「独学エンジニアの課題として、ログ解析システムを作った。」というタイトルで、課題の製作物完成までの道のりを投稿しています。
GitHub の Public リポジトリで閲覧できるようにしています。
独学エンジニア とは
『独学エンジニア』とは、Web開発(主にサーバーサイド)の動画学習教材です。
連載の目次
「独学エンジニアの課題として、ログ解析システムを作った。」の連載については、以下の順に投稿しています。
- Step1. 製作物の確認
- Step2. DBのテーブル作成
- Step3. データのインポート
- Step4. SELECT 文での検索
- Step5. プログラムからのSQLの操作①
- Step6. プログラムからのSQLの操作②
今回は Step5. プログラムからのSQLの操作① です。
作成する予定の以下の 2 つの取得機能のうち、今回は 1 について作成します。
- 最もビュー数の多い記事
- 指定したドメインコードの人気順
目次
環境
バージョン | |
---|---|
macOS Big Sur | 11.6 |
Docker Desktop | 4.7.0 |
PHP | 8.1.7 |
MySQL | 8.0.28 |
インポートしたデータ形式の確認
domain_code | page_title | count_views | total_response_size |
---|---|---|---|
ドメインコード | ページタイトル | 各時間のページ表示回数 | 合計レスポンスサイズ |
aa | Main_Page | 4 | 0 |
aa | Wikipedia | 1 | 0 |
1. 処理の流れの確認
最もビュー数の多い記事を、指定した記事数分だけビュー数が多い順にソートし、ドメインコードとページタイトル、ビュー数を提示する
という要件を満たすため、以下の流れで処理します。
2. ファイルの作成・編集
以下の 3 ファイルを作成して、編集します。
lib/sql.php、lib/validation.php については、プログラム間で共通化します。
2-1. most_viewed_pages.php の作成・編集
呼び出して処理を実行するプログラムを作成・編集します。
<?php require_once 'lib/sql.php'; require_once 'lib/validation.php'; const NO_ARG = 1; const DEFAULT_NUM_OF_SEARCH = 10; // 1. 入力値の受け取り if ($_SERVER['argc'] === NO_ARG) { $input = DEFAULT_NUM_OF_SEARCH; } else { $input = $_SERVER['argv'][1]; } // 2. 入力値のバリデーション(正の整数かどうか) $error = validationInputOfMostViewedPages($input); // 数字以外→エラーメッセージ if (!empty($error)) { echo $error; } else { // 3. SELECT文の実行 $data = getMostViewedPages($input); // 4. 結果の表示 foreach ($data as $record) { echo '"' . $record['domain_code'] . '", "' . $record['page_title'] . '", ' . $record['count_views'] . PHP_EOL; } }
検索件数を設定しなかった場合、 10 件をデフォルト値としておきます。
2-2. lib/sql.php の作成・編集
下記2つのメソッドを書きます。
<?php /** * DB接続 * * @return PDO */ function dbConnect(): PDO { $dbHost = 'db'; $dbUsername = 'test_user'; $dbPassword = 'pass'; $dbDatabase = 'test_database'; $dataSourceName = "mysql:host=$dbHost;dbname=$dbDatabase;charset=utf8mb4"; try { $dbh = new PDO($dataSourceName, $dbUsername, $dbPassword, [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, ]); } catch (PDOException $e) { echo 'DB接続エラー' . $e->getMessage(); exit(); }; return $dbh; } /** * 最もビュー数の多い記事を、指定した記事数分だけビュー数が多い順にソートし、ドメインコードとページタイトル、ビュー数を取得する。 * * @param string $input コマンドラインで受け取った入力値 ex. 10 * @return array $results ex. [ 0 => ['domain_code' => 'en.m', 'page_title' => 'Main_Page', 'count_views' => 122058],... */ function getMostViewedPages(string $input): array { $sql = <<<SQL SELECT domain_code, page_title, count_views FROM page_views ORDER BY count_views DESC LIMIT :input ; SQL; $dbh = dbConnect(); // DB接続 $stmt = $dbh->prepare($sql); // 実行準備 $stmt->bindValue(':input', (int)$input, PDO::PARAM_INT); $stmt->execute(); $results = $stmt->fetchAll(PDO::FETCH_ASSOC); $dbh = null; // DB切断 return $results; }
•
PDO::FETCH_ASSOC
: は、結果セットに 返された際のカラム名で添字を付けた配列を返します。
(引用:PHP: PDOStatement::fetch - Manual)
$results
の中身は、例えば以下のような配列です。
array ( 0 => array ( 'domain_code' => 'en.m', 'page_title' => 'Main_Page', 'count_views' => 122058, ), 1 => array ( 'domain_code' => 'en', 'page_title' => 'Main_Page', 'count_views' => 69181, ), )
2-3. lib/validation.php の作成・編集
コマンドラインでの入力値をバリデーションするメソッドを書きます。
<?php require_once 'lib/sql.php'; /** * most_viewed_pages.php のコマンドラインでの入力値をバリデーションする。 * * @param string $input コマンドラインで受け取った入力値 ex. 10 * @return string $error */ function validationInputOfMostViewedPages(string $input): string { $error = ''; if (((int)$input < 0) || !preg_match('/^-?[0-9]+$/', $input)) { $error = '1 以上の整数を入力してください。' . PHP_EOL; } return $error; }
3. プログラムの使い方
下記コマンドを実行します。
docker compose exec app php most_viewed_pages.php 20
コマンド実行例❶
most_viewed_pages.php の後に半角スペースを開けて、指定するページ数を入力します。
# r_yamate @ mbp in ~/Documents/code/wikipedia-log-analysis-tool on git:feature/create-program x [7:25:16] $ docker compose exec app php most_viewed_pages.php 20 "en.m", "Main_Page", 122058 "en", "Main_Page", 69181 "en", "Special:Search", 26630 "de", "Wikipedia:Hauptseite", 20739 "en.m", "Special:Search", 19119 "ja", "メインページ", 18475 "es.m", "Wikipedia:Portada", 15335 "es", "Wikipedia:Portada", 15261 "fr", "Wikipédia:Accueil_principal", 14744 "thankyou", "Thank_You/en", 13449 "ru", "Заглавная_страница", 13336 "en", "Lotfi_A._Zadeh", 12864 "it", "Pagina_principale", 12731 "zh", "Wikipedia:首页", 10782 "pt", "Wikipédia:Página_principal", 10485 "de.m", "Wikipedia:Hauptseite", 10386 "ja.m", "メインページ", 9421 "en", "Bible", 9024 "fr.m", "Wikipédia:Accueil_principal", 8705 "en", "-", 7227
コマンド実行例❷
検索件数を指定しなかった場合、 10 件表示されます。
# r_yamate @ mbp in ~/Documents/code/wikipedia-log-analysis-tool on git:feature/create-program x [7:28:44] $ docker compose exec app php most_viewed_pages.php "en.m", "Main_Page", 122058 "en", "Main_Page", 69181 "en", "Special:Search", 26630 "de", "Wikipedia:Hauptseite", 20739 "en.m", "Special:Search", 19119 "ja", "メインページ", 18475 "es.m", "Wikipedia:Portada", 15335 "es", "Wikipedia:Portada", 15261 "fr", "Wikipédia:Accueil_principal", 14744 "thankyou", "Thank_You/en", 13449
コマンド実行例❸
バリデーションエラーの場合、エラーメッセージが表示されます。
# r_yamate @ mbp in ~/Documents/code/wikipedia-log-analysis-tool on git:feature/create-program x [7:29:36] $ docker compose exec app php most_viewed_pages.php a 1 以上の整数を入力してください。
おわりに
今回は「独学エンジニアの課題として、ログ解析システムを作った。」の Step5. プログラムからのSQLの操作① でした。
次回は、Step6. プログラムからのSQLの操作② について投稿します。
ありがとうございました。
いただきます🙏 pic.twitter.com/SUsS2NhdZv
— やまて|Webエンジニア2年目 (@r_yamate) 2023年1月11日
息子5歳がママの料理の手伝いをするのが好きで作ってくれたおにぎり。