diff --git a/public/workspace/php/twitter/db.php b/public/workspace/php/twitter/db.php new file mode 100644 index 0000000..4fe3f05 --- /dev/null +++ b/public/workspace/php/twitter/db.php @@ -0,0 +1,20 @@ +setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + } + + return $pdo; +} +?> diff --git a/public/workspace/php/twitter/index.php b/public/workspace/php/twitter/index.php new file mode 100644 index 0000000..a06f381 --- /dev/null +++ b/public/workspace/php/twitter/index.php @@ -0,0 +1,28 @@ + + + + + + + Twitterライク + + +

つぶやき投稿

+ + + + +
+ +

タイムライン

+ + + + + diff --git a/public/workspace/php/twitter/post.php b/public/workspace/php/twitter/post.php new file mode 100644 index 0000000..05aca0b --- /dev/null +++ b/public/workspace/php/twitter/post.php @@ -0,0 +1,15 @@ + diff --git a/src/components/Toc.astro b/src/components/Toc.astro index aa60ef3..23aa50a 100644 --- a/src/components/Toc.astro +++ b/src/components/Toc.astro @@ -42,6 +42,7 @@ "git", "tips", "reference", + "final-work", ]; for (const path of sectionPaths) { diff --git a/src/pages/final-work/000-overview.mdx b/src/pages/final-work/000-overview.mdx new file mode 100644 index 0000000..35abd60 --- /dev/null +++ b/src/pages/final-work/000-overview.mdx @@ -0,0 +1,79 @@ +--- +layout: "@/layouts/MarkdownLayout.astro" +--- + +import Toc from "../../components/Toc.astro"; + +export const title = "総合演習:Twitterのようなアプリを作ろう"; + +# {title} + +これまでPHPとMySQLについて学んできました。 +ここでは、それらを組み合わせて**Twitterのような投稿アプリ**を作成します。 + +## TOC + +## これまで学んだこと + +### PHPで学んだこと + +- 変数と配列 +- フォームからのデータ受け取り(`$_POST`) +- 条件分岐(`if`文) +- 繰り返し処理(`foreach`) +- Sessionを使った状態管理 + +### MySQLで学んだこと + +- データベースとテーブルの作成 +- データの追加(`INSERT`) +- データの取得(`SELECT`) +- データの削除(`DELETE`) +- データの更新(`UPDATE`) + +## 総合演習の目的 + +PHPとMySQLを組み合わせることで、以下のようなことができるようになります: + +1. **ユーザーの入力を保存する** - フォームで受け取ったデータをデータベースに保存 +2. **保存したデータを表示する** - データベースから取り出して画面に表示 +3. **データを操作する** - 削除や更新などの操作 +4. **複数のユーザーで共有する** - データベースに保存されているので、誰がアクセスしても同じデータが見える + +## 何を作るか + +**X(旧Twitter)のような投稿アプリ**を作ります。 + +**主な機能:** + +- つぶやきを投稿できる +- 投稿は新しい順に表示される(タイムライン) +- (発展)いいね機能 +- (発展)削除機能 + +**完成イメージ:** +シンプルですが、実際のSNSと同じように動作します。 +他の人が投稿すると、自分の画面にも表示されます! + +## 学習の進め方 + +この演習は**段階的に機能を追加していく**形式です。 + +### STEP1: 基本機能(必須) + +まず、最小限の機能で「動くアプリ」を作ります。 + +- つぶやきの投稿 +- タイムラインの表示 + +### STEP2: 機能追加(発展) + +基本機能ができたら、以下の機能を追加していきます。 + +- いいね機能 +- 削除機能 +- その他の改善 + +焦らず、STEP1から順番に進めましょう! + +[課題ページへ →](/final-work/010-twitter) diff --git a/src/pages/final-work/010-twitter.mdx b/src/pages/final-work/010-twitter.mdx new file mode 100644 index 0000000..745cc7c --- /dev/null +++ b/src/pages/final-work/010-twitter.mdx @@ -0,0 +1,412 @@ +--- +layout: "@/layouts/MarkdownLayout.astro" +--- + +import Toc from "../../components/Toc.astro"; +import Details from "@/components/Details.astro"; +import DockerLink from "@/components/DockerLink.astro"; + +export const title = "Twitterライクなアプリを作ろう"; + +# {title} + +X(旧Twitter)のような投稿アプリを作成します。 +つぶやきを投稿して、タイムラインで一覧表示できるアプリです。 + +## TOC + +## 完成イメージ + + + +このアプリでできること: +- つぶやきを投稿できる +- 投稿は新しい順に表示される +- 他の人の投稿も見られる + +## データベース設計 + +まず、投稿データを保存するテーブルを作成します。 + +### テーブル構造 + +**テーブル名:** `tweets` + +| カラム名 | 型 | 説明 | +|---------|-----|------| +| id | INT | 投稿ID(主キー、自動採番) | +| username | VARCHAR(50) | 投稿者の名前 | +| content | VARCHAR(280) | 投稿内容(280文字まで) | +| created_at | DATETIME | 投稿日時 | + +### テーブル作成SQL + +phpMyAdminなどで以下のSQLを実行してください。 + +```sql +CREATE TABLE tweets ( + id INT AUTO_INCREMENT PRIMARY KEY, + username VARCHAR(50) NOT NULL, + content VARCHAR(280) NOT NULL, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP +); +``` + +## ファイル構成 + +`/workspace/php/twitter/` に以下のファイルを用意します。 + +``` +twitter/ +├── db.php # データベース接続設定 +├── index.php # メインページ +└── post.php # 投稿処理 +``` + +--- + +## STEP1: 基本機能を作る【必須】 + +まずは、投稿と表示ができる最小限のアプリを作ります。 + +### db.php(データベース接続) + +データベース接続の設定ファイルです。**このファイルは最初から完成しています。** + +```php file=public/workspace/php/twitter/db.php +setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + } + + return $pdo; +} +?> +``` + +他のファイルから `require_once 'db.php';` で読み込んで、`$pdo = getDb();` で使います。 + +### index.php(メインページ) + +投稿フォームとタイムラインを表示するページです。 + +```php + + + + + + + Twitterライク + + +

つぶやき投稿

+ + + + +
+ +

タイムライン

+ + + + + +``` + +#### TODO 1: 投稿を新しい順に取得する + +
+ +```php +$pdo = getDb(); + +// 新しい順(created_atの降順)に取得 +$stmt = $pdo->query("SELECT * FROM tweets ORDER BY created_at DESC"); +$tweets = $stmt->fetchAll(PDO::FETCH_ASSOC); +``` + +- `getDb()` でデータベース接続を取得 +- `ORDER BY created_at DESC` で新しい順に並び替え +- `fetchAll(PDO::FETCH_ASSOC)` で全てのデータを配列として取得 + +
+ +#### TODO 2: 投稿フォームを作成する + +
+ +```html +
+
+ + +
+
+ + +
+ +
+``` + +- `maxlength` でTwitterと同じ280文字制限 +- `action="post.php"` で投稿処理ページに送信 + +
+ +#### TODO 3: 投稿を表示する + +
+ +```php + +
+ + + + +

+
+ +``` + +- `htmlspecialchars()` でHTMLエスケープ(セキュリティ対策) +- `nl2br()` で改行を`
`タグに変換 + +
+ +### post.php(投稿処理) + +フォームから送信されたデータをデータベースに保存します。 + +```php + +``` + +#### TODO 1: フォームから送信されたかチェックする + +
+ +```php +if ($_SERVER["REQUEST_METHOD"] !== "POST") { + header("Location: index.php"); + exit; +} +``` + +POSTメソッド以外でアクセスされた場合は、index.phpに戻します。 + +
+ +#### TODO 2: 送信されたデータを取得する + +
+ +```php +$username = $_POST["username"] ?? ""; +$content = $_POST["content"] ?? ""; + +// 空チェック +if (empty($username) || empty($content)) { + header("Location: index.php"); + exit; +} +``` + +`??` 演算子でデフォルト値を設定し、空の場合は処理を中断します。 + +
+ +#### TODO 3: データを挿入する + +
+ +```php +$pdo = getDb(); + +$stmt = $pdo->prepare("INSERT INTO tweets (username, content) VALUES (?, ?)"); +$stmt->execute([$username, $content]); +``` + +- `getDb()` でデータベース接続を取得 +- `prepare()` と `execute()` でSQLインジェクション対策 +- `created_at` は自動で設定されるので指定不要 + +
+ +#### TODO 4: index.phpにリダイレクトする + +
+ +```php +header("Location: index.php"); +exit; +``` + +投稿が完了したら、タイムラインページに戻ります。 + +
+ +### 確認方法 + + + +1. ユーザー名とつぶやきを入力して投稿 +2. タイムラインに投稿が表示されることを確認 +3. 他の人も投稿して、お互いの投稿が見えることを確認 + +**ここまでで基本機能は完成です!🎉** + +--- + +## STEP2: 機能を追加する【発展】 + +基本機能ができたら、以下の機能を追加してみましょう。 + +### 発展1: いいね機能 + +投稿に「いいね」ボタンを追加します。 + +#### テーブルの追加 + +```sql +CREATE TABLE likes ( + id INT AUTO_INCREMENT PRIMARY KEY, + tweet_id INT NOT NULL, + session_id VARCHAR(255) NOT NULL, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + UNIQUE KEY unique_like (tweet_id, session_id) +); +``` + +- `UNIQUE KEY` で同じ人が同じ投稿に2回いいねできないようにする + +#### 実装のヒント + +
+ +```php +$pdo = getDb(); + +// 各投稿のいいね数を取得 +$stmt = $pdo->prepare("SELECT COUNT(*) FROM likes WHERE tweet_id = ?"); +$stmt->execute([$tweet['id']]); +$likeCount = $stmt->fetchColumn(); + +echo "{$likeCount}いいね"; +``` + +
+ +
+ +```html +
+ + +
+``` + +`like.php` で `INSERT INTO likes` を実行します。 + +
+ +### 発展2: 削除機能 + +自分の投稿を削除できるようにします。 + +
+ +```html +
+ + +
+``` + +
+ +
+ +```php + 0) { + $pdo = getDb(); + $stmt = $pdo->prepare("DELETE FROM tweets WHERE id = ?"); + $stmt->execute([$id]); + } +} + +header("Location: index.php"); +exit; +?> +``` + +
+ +### 発展3: その他の改善 + +余裕があれば、以下の機能も追加してみましょう: + +1. **文字数カウンター** - JavaScriptで残り文字数を表示 +2. **ページネーション** - 投稿が多くなったら10件ずつ表示 +3. **検索機能** - キーワードで投稿を検索 +4. **画像投稿** - 画像をアップロードできるようにする +5. **スタイリング** - CSSで見た目を整える + +## まとめ + +この演習では、以下のことを学びました: + +**STEP1(基本機能):** +- PHPとMySQLを組み合わせたデータの保存と取得 +- フォームデータの受け取りと処理 +- データベースからのデータ取得と表示 +- セキュリティ対策(`htmlspecialchars()`、`prepare()`) + +**STEP2(発展機能):** +- データの集計(`COUNT`) +- 複数テーブルの連携 +- Sessionを使った重複防止 + +SNSのようなアプリケーションは、これらの技術を組み合わせて作られています。 +今回作ったアプリを土台に、さらに機能を追加していくことで、本格的なウェブサービスに近づいていきます!