はじめに(5月の学習全体像)
5月は以下の3つを並行して学習しました。今回はLaravel学習の内容について学んだことや、5月時点での課題項目を自分の振り返り用に整理します!
| 項目 | 期間 | 内容 |
|---|---|---|
| SQL演習 | 5月上旬 | 四大構文+JOIN・サブクエリなど手書き練習 |
| LaravelにてオリジナルWEBアプリ開発 | 5月中旬〜下旬(計11日) | 既存WEBアプリを改修し、新機能を実装 |
| 基本情報試験対策 | 5月通じて継続 | 過去問道場で60〜120問/日ペース |
Share.app の開発 — 企画から実装まで(計11日間)
プロジェクト概要
4月まで学習に使っていた既存アプリ(職業管理アプリ)をベースに、**シェアハウスの住民情報一覧アプリ(Share.app)**に改修しました。
実装機能:
- CRUD操作
- Laravel Breezeを活用したログイン機能の追加
- OpenWeatherMap API連携による天気表示
実装1:Laravel Breeze でログイン機能を追加
初めて認証フレームワークを導入しました。
導入方法はこちらの方の記事などを参考に:https://qiita.com/AKFJ21/items/c0037b1a0efc3ea74b40
私は学習サイトの兼ね合いで現状私はLaravel 9を使用しています。
ただLaravelの最新バージョンを26/3/17にリリースされた13だそうです。
そしてLaravel12のリリースの時点でBreezeはどうやら非推奨になっていたようでインストーラーからの選択が出来なかったので手動でインストールをしました。
参考
・https://laravelversions.com/ja
・https://tech.arms-soft.co.jp/entry/2025/05/28/090000
💡 学んだこと: 導入1つで「ログイン → ユーザー登録 → パスワードリセット」までの機能が生成された。
手動での生成に比べて大幅に時間短縮になるので、便利なLaravel機能には積極的に学習コストを割くべき。
実装2:基本CRUD操作
住民情報の登録・一覧・更新・削除機能を、MVCモデルに沿って実装しました。各操作における Controller → Model → View のデータの流れを確認できたので、整理します。
実装の全体像
フォーム送信(POST /residents)
↓
Controller(store メソッド)
↓
Model(Resident::create())→ DB へ保存
↓
redirect()->route() で別ページへ遷移
登録処理の具体的な流れ
1. Controller で登録メソッドを定義
public function store(Request $request)
{
$request->validate([...]); // バリデーション
$resident = Resident::create([...]); // DB に保存
return redirect()->route('admin.residents.index'); // 遷移
}
2. Model で create() メソッドを使用
Model ファイル(class Resident extends Model)では、Laravel が提供する create() update() delete() などのメソッドを継承しており、そのまま使用できます。
$resident = Resident::create([
'name' => $request->name,
'job' => $request->job,
'likes' => $request->likes,
'dislikes' => $request->dislikes,
'birthplace' => $request->birthplace,
'age' => $request->age,
'image_path' => $imagePath, // ファイルはサーバ上に保存後、パスを DB へ
'bio' => $request->bio,
]);
3. 処理完了後、ルート遷移
return redirect()->route('admin.residents.index');
web.php で定義されたルート名を指定することで、URL が変わっても自動対応します。
重要なポイント
Model の役割
-
Illuminate\Database\Eloquent\Modelを継承することで、CRUD メソッドをそのまま使用可能 - DB テーブルとの対応は、Model クラス名で自動判定(
Resident→residentsテーブル)
Controller の責務 - 現状では処理ロジックも記載していますが、実際は処理をサービスクラスに切り出し、Controller では View や Redirect を返すだけ にするのが理想的です
POST-Redirect-Get パターン - データ操作後は必ず
redirect()で別ページへ遷移 - ブラウザの F5 リロードで重複投稿されるのを防げます
設計上の工夫: フォームメソッドを POST ではなく GET に設定すれば検索条件がURL に残り、「このフィルタ状態をブックマーク」できるようになります。
実装3:OpenWeatherMap API連携による天気表示
外部APIから天気情報を取得し、ダッシュボードに表示する実装を行いました。この実装を通じて、HTTPリクエスト・JSONレスポンス・APIドキュメント読解のスキルを身につけることができました。
ステップ1:APIキーを取得して環境変数に登録
まず、OpenWeatherMap 公式サイトからAPIキーを取得します。取得後、プロジェクトの .env ファイルに追加します。
OPENWEATHER_API_KEY=(取得したキーをペースト)
この方法により、秘密情報をソースコードに埋め込まず、環境変数として安全に管理できます。
ステップ2:コントローラでAPIから天気情報を取得
Controller のメソッド内で、Http::get() を使用してOpenWeatherMap APIにリクエストを送ります。
// コントローラ側
$response = Http::get('https://api.openweathermap.org/data/2.5/weather', [
'q' => 'Tokyo',
'appid' => env('OPENWEATHER_API_KEY'),
'units' => 'metric',
'lang' => 'ja',
]);
$weather = $response->json();
// JSON形式のレスポンスをPHP配列(連想配列)に変換
return view('admin.home.index', compact('weather'));
ポイント:
-
Http::get()は Laravel が提供するHTTPクライアント -
env('OPENWEATHER_API_KEY')で.envファイルから設定値を読み込み -
$response->json()でJSON形式をPHP配列に自動変換
ステップ3:Blade テンプレートで天気情報を表示
OpenWeatherMap 公式ドキュメントを参考に、レスポンス構造を確認した上で、必要な要素をテンプレートに追記します。
{{-- 気温とアイコン --}}
<div style="display:flex; align-items:flex-end; justify-content:space-between; margin: 0.75rem 0 1rem;">
<div>
<div style="font-size:48px; font-weight:500; line-height:1; color:#222;">
{{ $weather['main']['temp'] }}<span style="font-size:20px;">°C</span>
</div>
<div style="font-size:15px; color:#666; margin-top:6px;">
{{ $weather['weather'][0]['description'] }}
</div>
</div>
<span style="font-size:56px; opacity:0.4;">🌤</span>
</div>
$weather['main']['temp'] や $weather['weather'][0]['description'] といったネストされた配列へのアクセスを通じて、階層的なJSONデータ構造を扱う実装力が身につきました。
💡 学んだこと・振り返り:
- 英語の公式ドキュメントを読みながらAPI構造を把握するのが難しかった
実装4:ルーティングの順序が重要
web.phpのコーディング中ワイルドカードルーティングで躓きました。
// ❌ ダメ:ワイルドカードが全部キャッチしてしまう
Route::get('/members/{id}', [MemberController::class, 'show']);
Route::get('/members/create', [MemberController::class, 'create']); // これが {id} にキャッチされる
// ✅ 正解:固定パスを先に書く
Route::get('/members/create', [MemberController::class, 'create']);
Route::get('/members/{id}', [MemberController::class, 'show']);
デバッグ方法: php artisan route:list でルーティング一覧を確認すると、「どのURLにどのメソッドが紐づいているか」が一目瞭然。404エラー(リソースが見つからない)が出たときは必ず確認します。
実装5:compact() 関数の役割を理解
Blade ビューに複数の変数を渡すとき、compact() 関数が便利です。
$members = Member::all();
$keyword = $request->input('keyword');
$stores = Store::all();
// これを
return view('members.index', compact('members', 'keyword', 'stores'));
// 展開すると
return view('members.index', [
'members' => $members,
'keyword' => $keyword,
'stores' => $stores,
]);
💡 初心者向けメモ: compact('a', 'b', 'c') は ['a' => $a, 'b' => $b, 'c' => $c] と同じ意味。変数名を「文字列」で渡すことが重要です。
まとめ 課題と次のステップ
5月の学習スタイル
「とにかく動かしたい」という欲求と「理解したい」という執念を両立させながら開発しました。結果として、疑問を持ちながら実装する癖がついたのは、大きな成果です。
未解決の課題・のびしろ部分
① Controller の戻り値の切り分け
- 現状:
view()かredirect()->route()か、判断基準がない
② QueryBuilder の複雑メソッド習得不足
- 現状:
join()groupBy()などが組み合わせられない
③ エラーハンドリングが甘い
- 現状:API呼び出し・DB操作が「成功前提」で実装