こんにちは!
スマレジ・テックファーム の Webエンジニア やまて と申します。
はじめに
「独学エンジニアの課題として、ログ解析システムを作った。」というタイトルで、課題の製作物完成までの道のりを投稿しています。
GitHub の Public リポジトリで閲覧できるようにしています。
独学エンジニア とは
『独学エンジニア』とは、Web開発(主にサーバーサイド)の動画学習教材です。
連載の目次
「独学エンジニアの課題として、ログ解析システムを作った。」の連載については、以下の順に投稿しています。
- Step1. 製作物の確認
- Step2. DBのテーブル作成
- Step3. データのインポート
- Step4. SELECT 文での検索
- Step5. プログラムからのSQLの操作①
- Step6. プログラムからのSQLの操作②
今回は Step6. プログラムからのSQLの操作② です。
作成する以下の 2 つの取得機能のうち、今回は 2 について作成します。
- 最もビュー数の多い記事
- 指定したドメインコードの人気順
目次
環境
バージョン | |
---|---|
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. ファイルの編集
2-1. popular_domain_codes.php の作成・編集
呼び出して処理を実行するプログラムを作成・編集します。
- 作成・編集:popular_domain_codes.php
<?php require_once 'lib/sql.php'; const MIN_NUM_OF_SEARCHES = 2; // 1. 入力値の受け取り ['popular_domain_codes.php', 'en', 'de'] → ['en', 'de'] if ($_SERVER['argc'] > MIN_NUM_OF_SEARCHES) { $inputs = array_slice($_SERVER['argv'], 1); // 2. SELECT文の実行 $data = getPopularDomainCodes($inputs); // 3. 結果の表示 foreach ($data as $record) { echo '"' . $record['domain_code'] . '", ' . $record['total_count_views'] . PHP_EOL; } } else { echo 'ドメインコードを 2 つ以上入力してください。' . PHP_EOL . 'ex: php popular_domain_codes.php en de ja'; }
2-2. lib/sql.php の編集
前回作成した sql.php ファイルにメソッドを追記します。
<?php //省略 /** * 指定したドメインコードに対して、人気順にソートし、ドメインコード名と合計ビュー数を取得する。 * * @param array $inputs コマンドラインで受け取った入力値 ex. en de ja * @return array $result ex. [0 => ['domain_code' => 'en', 'total_count_views' => '3556081'], 1 => ... */ function getPopularDomainCodes(array $inputs): array { $inClause = substr(str_repeat(',?', count($inputs)), 1); $sql = <<<SQL SELECT domain_code, SUM(count_views) AS 'total_count_views' FROM page_views WHERE domain_code IN ( {$inClause} ) GROUP BY domain_code ORDER BY SUM(count_views) DESC ; SQL; $dbh = dbConnect(); // DB接続 $stmt = $dbh->prepare($sql); // 実行準備 $stmt->execute($inputs); // SQL実行 $results = $stmt->fetchAll(PDO::FETCH_ASSOC); $dbh = null; // DB切断 return $results; }
$results
の中身は、例えば以下のような配列です。
array ( 0 => array ( 'domain_code' => 'en', 'total_count_views' => '3556081', ), 1 => array ( 'domain_code' => 'de', 'total_count_views' => '284178', ), )
- 参考:最初はバインドがうまくいかず詰まりました。
<?php // 省略 function getPopularDomainCodes(array $inputs): array { $sql = <<<SQL SELECT domain_code, SUM(count_views) AS 'total_count_views' FROM page_views WHERE domain_code IN ( :conditions ) GROUP BY domain_code ORDER BY SUM(count_views) DESC ; SQL; $dbh = dbConnect(); // DB接続 $stmt = $dbh->prepare($sql); // 実行準備 $conditions = "'" . implode("','", $inputs) . "'"; $stmt->bindValue(':conditions', $conditions, PDO::PARAM_STR); $stmt->execute(); // SQL実行 $results = $stmt->fetchAll(PDO::FETCH_ASSOC); // DB切断 $dbh = null; return $results; }
3. プログラムの使い方
下記コマンドを実行します。
docker compose exec app php popular_domain_codes.php en de ja
# r_yamate @ mbp in ~/Documents/code/wikipedia-log-analysis-tool on git:feature/create-program x [7:35:12] C:16 $ docker compose exec app php popular_domain_codes.php en de ja "en", 3556081 "ja", 367924 "de", 284178
※ 入力がない場合、エラーメッセージが表示されます。
# r_yamate @ mbp in ~/Documents/code/wikipedia-log-analysis-tool on git:feature/create-program x [7:36:08] $ docker compose exec app php popular_domain_codes.php ドメインコードを 2 つ以上入力してください。 ex: php popular_domain_codes.php en de ja
おわりに
今回は「独学エンジニアの課題として、ログ解析システムを作った。」の Step6. プログラムからのSQLの操作② でした。
ログ解析システムを作成した目的は、ソフトウェアエンジニアリングにおいて実際によく登場するタスクの一つである、ログデータを解析を実際にやってみることで、データベースとSQL スキルの向上を目指す、という目的でした。まだまだではありますが、基礎がしっかり学べたと思います。
ありがとうございました。
「楽しんでやっている人」には勝てない。とのことなので、自分が「楽しんでやっている人」に近づくために、「すべきこと」ではなくて「やりたいこと」をしている、と思える行動をなるべく選ぶ。努力する、頑張る、という類の言葉を、意識的に発さないようにする。という小さなところから始めてる。
— やまて|Webエンジニア2年目 (@r_yamate) 2023年1月11日
前職の仕事は「やりたいこと」と思える部分がなかったけど、今は分からないこと多くてしんどくても楽しいと思えるし、やりたいことと思えているから、この調子で行きたいです。