圧倒的に開発をラクにできる Laravel を使ったアプリケーション開発入門|研修コースに参加してみた
今回参加したコースは 圧倒的に開発をラクにできる Laravel を使ったアプリケーション開発入門 です。
これまで 3 大 Web アプリケーションフレームワークのうち、 Ruby / Rails 、 Python / Django をレポートしましたが、トリを務めるのが PHP / Laravel です。
コースを受講してみると、フレームワークそれぞれに特徴がありますが、「 Laravel は圧倒的に多機能である」とわかりました。 フルスクラッチに書かずとも Laravel の機能でサッと実現できてしまいます。 これは DX 時代には重要な、開発者がラクできる = 開発スピードも開発者体験もよい、ということに繋がりそうです!
では、どのような内容だったのか、レポートします!
もくじ
コース情報
想定している受講者 |
|
---|---|
受講目標 |
|
講師紹介
このコースではプログラミング分野で演習の組み立てが上手な 冨原 祐 さんが登壇されました。
「講師を一生の仕事にする」
3 時間で学ぶ TypeScript 入門 ~ 「型」初心者が挑戦|研修コースに参加してみた
React / Express で作る Web アプリケーション開発入門|研修コースに参加してみた
はじめての Go 言語 ( golang ) 入門 研修コースに参加してみた
Laravel とは
まずは Laravel の特徴を紹介いただきました。
- MVC フレームワーク
- Model 、View 、Controller 、Router を自分で書く
- Model はほとんど書かなくていいケースが多い
- Router は、この URL ならこの処理という指定なので、都度 1 〜 2 行を書くだけ
- 書くのはほとんど View と Controller
冨原さんからは「 Laravel = 開発スピードがいい感じに出せる」と補足されました。 DX 時代にはマストな要素ですね。
では、インストールと環境構築を進めます。
- Vagrant / Virtualbox で仮想環境を構築
- Laravel を簡単に構築できる Docker Compose や Vagrant box は今回は使わない
- 仮想環境に SSH して Apache -> MariaDB -> PHP -> Composer -> Laravel とインストール and 設定
- エディタは Visual Studio Code を使用
続いて、インストールした Laravel のディレクトリ構成を見てみましょう。
config/
- 設定ファイルを配置
app/
- モデルやコントローラなどプログラムを配置
public/
- 公開用ディレクトリ。 CSS や JS 、画像などリソースを配置
resouces/
- テンプレートを配置
routes/
- ルーティングの設定
database/
- 主にデータベースのマイグレーションで利用
Rails によく似ていますね。
Controller と Template を使ってみよう
まずは、基本的な MVC モデルでの Laravel の開発の進め方を見てみましょう。
最初にコントローラから簡単なメッセージをブラウザに表示させてみます。
- Controller を作成
- artisan コマンドでコントローラのテンプレートから自動生成
$ php aritsan make:contoller IndexController
- app/Http/Controllers/ に IndexController.php が生成される
- コメントアウトされている部分に簡単な処理を書く
namespace App\Http\Controllers; use Illuminate\Http\Request; class IndexController extends Controller { public function index() { print("<h1>こんにちは! Laravel です!</h1>"); return null; } }
- このコントローラが動くように URL の設定を routes/web.php に書く
use Illuminate\Support\Facades\Route; use App\Http\Controllers\IndexController; Route::get('/', [IndexController::class, 'index']);
- localhost:8000/ の URL がリクエストされたときの処理
これでアプリケーションを動かして localhost:8000/ を表示してみます!
# artisan コマンドでアプリケーションを起動できる
$ php artisan serve
本当にスピーディにここまでできます。
ちなみに Rails では scaffold コマンドでモデルからコントローラー、ビュー、ルートなどファイル一式に加え、さらには CRUD 処理まで自動で生成されます。 Laravel でも出来るのではと調べてみると、 --resourse
オプションをつけてコントローラを作成すると、 CRUD 処理とルーティングまで自動生成できます。
$ php artisan make:controller PhotoController --resource
これは Rails 同様にスピードを出せそうですね。
Template に Controller から処理と値を渡す
さきほどはコントローラに、ブラウザに表示する処理を書きましたが、これは MVC で言うビューにわけましょう。 Laravel ではテンプレートという仕組みを使います。
- ブラウザに表示するテンプレートを書く
- Laravel では blade というエンジンを使用
- resouces/views に index.blade.php を作成
- コントローラからテンプレートに値を渡すこともできる
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" href="/css/style.css"> <title>bladeテンプレートのサンプル画面</title> </head> <body> <h1>bladeテンプレートのサンプル画面</h1> <div class="mainContent"> <div class="bold">bladeテンプレートを利用しています。</div> <div>{{$message}} {{$name}} さん!</div> </div> </body> </html>
- public/css に style.css を配置
- IndexController を変更
public function index() { // print("<h1>こんにちは! Laravel です!</h1>"); return view('index', ['message' => 'こんにちは', 'name' => '山田']); }
これでブラウザを更新して表示してみましょう!
データベースと連携してみよう
ここまでは編集に入れた値を返すだけでしたが、ここからはデータベースと連携させてみましょう。
データベースの準備
まずは MariaDB を準備します。
- MariaDB で laravel というデータベースを作成
- root などに権限を与えるのもよいが、今回は手っ取り早く新しいユーザを追加 and 全権設定
Migration でテーブルを作ってみよう
Laravel ではテーブルの作成や修正などをマイグレーションで行います。
- 現在のアプリケーションの開発は開発者各自のマシンで行うことが多い
- DBA がデータベース作成修正用の SQL を書いて配布するのでは面倒 and ミスが起きやすい
- マイグレーションを使えば、開発チーム全員が同じデータベースを用意できる
- マイグレーションファイルにデータベースの情報を記述し artisan コマンドで実行する
- モデルがテーブルを自動で認識する
マイグレーションとは
今回利用するテーブルは以下の書籍情報を保存する books テーブルです。
では、マイグレーションをやってみましょう。
- artisan コマンドでマイグレーションのテンプレートから自動生成
$ php artisan make:migration create-books-table --create=books Created Migration: 2022_10_17_063213_create-books-table
- database/migrations に 2022_10_17_063213_create-books-table.php が作成される
- テーブルのカラム定義を記述
use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class CreateBooksTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('books', function (Blueprint $table) { // id と timestamp はデフォルトで記述済 $table->id(); // ここに追加 $table->string('name', 255); $table->string('author', 255); $table->text('overview'); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('books'); } }
- 型とメソッドが対応 (ex. int 型 -> integer(), tinyint -> boolean() etc.)
- アプリケーションの設定を書く = .env ファイルのデータベース設定を編集
- プロジェクトの直下にある
- データベース側の準備で作ったユーザを指定
DB_CONNECTION=mysql DB_HOST=localhost DB_PORT=3306 DB_DATABASE=laravel DB_USERNAME=newuser DB_PASSWORD=password
- artisan コマンドでマイグレーションを実行
$ php artisan migrate Migration table created successfully. Migrating: 2014_10_12_000000_create_users_table # 中略 Migrating: 2022_10_17_063213_create-books-table Migrated: 2022_10_17_063213_create-books-table (124.72ms)
データベースで確認してみます。
mysql> show tables;
+------------------------+
| Tables_in_laravel |
+------------------------+
| books |
| failed_jobs |
| migrations |
| password_resets |
| personal_access_tokens |
| users |
+------------------------+
6 rows in set (0.00 sec)
mysql> desc books;
+------------+-----------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+-----------------+------+-----+---------+----------------+
| id | bigint unsigned | NO | PRI | NULL | auto_increment |
| name | varchar(255) | NO | | NULL | |
| author | varchar(255) | NO | | NULL | |
| overview | text | NO | | NULL | |
| created_at | timestamp | YES | | NULL | |
| updated_at | timestamp | YES | | NULL | |
+------------+-----------------+------+-----+---------+----------------+
6 rows in set (0.00 sec)
気持ち良いぐらいに、ちゃんとできています。
Models を作成して使ってみよう
続いて、データベースからモデルを自動生成します。
- artisan コマンドでモデルを自動生成
$ php artisan make:model Book; Model created successfully.
- app/Models に Book.php ができる
namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; class Book extends Model { use HasFactory; }
楽ちんですね。
今度はモデルを使って、書籍を全件表示してみましょう(別アプリケーションからデータは登録済み)。
- indexController の index() で Book モデルを使う
use App\Models\Book; class IndexController extends Controller { public function index() { $books = Book::all(); return view('index', compact('books')); } }
- all() は全件取得する OR マッパー Eloquent のメソッド
- compact() で $books を連想配列に変換
- index.blade.php でループして全件表示するように変更
<div class="mainContent"> <div class="bold">bladeテンプレートを利用しています。</div> @foreach($books as $book) {{ $book->name }}<br> {{ $book->author }}<br> {{ $book->overview }}<br> @endforeach </div>
では、これで画面を確認してみましょう。
Service Container で共通する処理をまとめよう
これまでは MVC の基本的な処理を書いてきましたが、ここからは Laravel の代名詞とも言われる機能を使います。
まずはサービスコンテナです。
- 複数のクラスをまとめてインスタンス化する
- ルーティングで使った Route() なども同じ
- コントローラから使うときは、該当のサービスコンテナを呼び出すだけで OK
- サービスコンテナは自作できるので、それをうまく使うのが腕の見せどころ
- サービスコンテナをうまく使うには DI (Dependency Injection 依存性の注入) を理解するとよい
- 言葉通り “振る舞いを外部から決める” という意味
- (使う側から)メソッドを渡すということができる
- 「大枠は一緒のものを使って、個別部分のみを書き足す」ということができる
- インターフェイスをはさんでメソッドを入れる
サービスコンテナとは
Laravel で DI を実現する
DI を実現する方法をまず解説いただきました。
- 引数にタイプヒンティングを使えば、必要なものをインスタンス化してくれる
ex.1public function index(Book $bookModel) { $books = $bookModel->all(); return view('index', compact('books')); }
ex.2
public function index(Request $resquest, Book $bookModel) { if ($request->isMethod('post')) { // post の処理 } }
- インスタンス化する new がない
- メソッドの引数にインスタンスを入れることをメソッドインジェクションという
- コンストラクタにインスタンスを入れることをコンストラクタインジェクションという
- サービスコンテナを考えるコツ
- ex. pdf / csv 出力などは画面に表示されたデータをそのまま使うことが多い -> ダウンロードや印刷のクラスをサービスコンテナにしておく
では、以下のサービスコンテナを実装してみましょう。
- app/Libs ディレクトリを作成して CsvCreator.php を作成
namespace App\Libs; use Illuminate\Database\Eloquent\Builder; use Illuminate\Routing\ResponseFactory; class CsvCreator { public function createCsv(array $header, Builder $query, string $filename = null){ $response = response(); $cb = function() use ($header, $query) { $stream = fopen('php://output', 'W'); $datas = $query->get(); fputs($stream, pack('C*', 0xEF, 0xBB, 0xBF)); fputcsv($stream, $header); foreach($query->cursor() as $row){ fputcsv($stream, $row->toArray()); } fclose($stream); }; if ($filename != null) { $outputfile = $filename; } else { $outputfile = sprintf('csv-%s.csv', date('Ymd')); } $header = [ 'Content-type' => 'application/octet-stream', ]; // Laravel には streamDownload() メソッドがあり、コールバック関数をもとに文字列をファイルにできる return $response->streamDownload($cb, $outputfile, $header); } }
- 作った csvCreator をサービスコンテナに登録
- app/Provider/AppServiceProvider.php に追加
use App\Libs\CsvCreator; class AppServiceProvider extends ServiceProvider { /** * Register any application services. * * @return void */ public function register() { app()->bind(CsvCreator::class); } // 以下、略
- bind() メソッドにクラスを渡す(呼ばれるとインスタンスを返す)
- インスタンスではなくクラスなので、利用されるまではメモリを消費しないところがポイント
では、このサービスコンテナを使うコントローラを作りましょう。
- BooksCsvController を作成
$ php artisan make:controller BooksCsvController Controller created successfully.
use App\Models\Book; use App\Libs\CsvCreator; class BooksCsvController extends Controller { public function index(Book $bookModel, CsvCreator $csv) { // createCsv() に必要な csv のヘッダーとクエリを渡す $books = $bookModel->select('name', 'author'); $header = ['書籍名', '著者名']; return $csv->createCsv($header, $books); } }
- routes/web.php に csv をダウンロードする URL を追加
use App\Http\Controllers\BooksCsvController; Route::get('/bookcsv', [BooksCsvController::class, 'index']);
localhost/bookcsv にアクセスすると、 csv ファイルがダウンロードされます。 中身を見てみましょう。
SaaS や業務アプリケーションではとっても便利に使える機能ですね。
Middleware でどの画面でも使う処理をまとめてみよう
サービスコンテナは必要なときに呼び出せる共通処理でしたが、どの画面でも使うような処理、例えば認証チェック、ログ出力などは、ミドルウェアに登録すれば、どこでも全部やってくれます。
このミドルウェアも Laravel の特徴的なところです。
- app/Http/Middleware にある
- 初期から登録されているものは app/Http/Kernel.php にある
/** * The application's global HTTP middleware stack. * * These middleware are run during every request to your application. * * @var array
*/ protected $middleware = [ // \App\Http\Middleware\TrustHosts::class, \App\Http\Middleware\TrustProxies::class, \Fruitcake\Cors\HandleCors::class, \App\Http\Middleware\PreventRequestsDuringMaintenance::class, \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class, \App\Http\Middleware\TrimStrings::class, \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class, ]; - 自作のものを登録するときは、 $middleware に追加する
では、ログを出力するミドルウェアを追加してみましょう。
- artisan コマンドでミドルウェアのテンプレートから自動生成
$ php artisan make:middleware Logger Middleware created successfully.
- app/Http/Middleware に Logger.php が作成される
namespace App\Http\Middleware; use Closure; use Illuminate\Http\Request; class Logger { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next * @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse */ public function handle(Request $request, Closure $next) { return $next($request); } }
- handle() メソッドの中にある処理が自動で動く
- リクエストヘッダーにある user-agent の情報をログに残す処理を追加
public function handle(Request $request, Closure $next) { // リクエストにある user-agent の情報をログに追加 \Log::info($request->header('user-agent')); return $next($request); }
- app/Http/Kernel.php に作った Logger のミドルウェアを追加
protected $middleware = [ // \App\Http\Middleware\TrustHosts::class, \App\Http\Middleware\TrustProxies::class, \Fruitcake\Cors\HandleCors::class, \App\Http\Middleware\PreventRequestsDuringMaintenance::class, \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class, \App\Http\Middleware\TrimStrings::class, \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class, // ここに追加 \App\Http\Middleware\Logger::class, ];
タイムゾーンを Asia/Tokyo に変更後、トップページを更新しログを見てみましょう!
Laravel のログは storage/logs/laravel.log にあります。
# laravel プロジェクトがあるディレクトリで実行
$ tail ./storage/logs/laravel.log
# 中略
[2022-10-19 19:05:33] local.INFO: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:105.0) Gecko/20100101 Firefox/105.0
無事に出力されていました!
作ったミドルウェアは登録しなくてもサービスコンテナとして使えます。 このあと試しに indexController にログを吐くメソッドを注入してみました。
最後に API サーバの作成を少しだけ紹介されましたが、ここでも便利機能が沢山ありました。
例えば、 indexController から JSON を返そうとする場合、 Laravel では、ただ return $books;
だけで JSON にしてくれます。 すごいぞ、 Laravel !!
この API サーバの作り方を紹介いただいたところ、このコースは修了しました。
まとめ
Laravel を使った基本的な MVC の処理の書き方と、特徴的なサービスコンテナ、ミドルウェアを使ってみました。 冨原さんがコース冒頭でお話された「開発のスピードが出せる」という言葉を、まざまざと体験できました。
調べてみると、他にも認証周りでは SNS などの OAuth に簡単に対応できるライブラリや、 SPA 開発のための Livewire や React / Vue.js 対応など、これでもかと機能が詰め込まれています。 最近では Laravel の非同期処理・高速化ができる Laravel Octane が登場するなど、エコシステムもとても充実しています。
フルスタックが求められる DX での技術選定には、開発スピードを上げられる機能、とても快適な開発者体験、長く付き合えるエコシステムがある Laravel はとても良い選択肢だと感じられるコースでした!
label SEカレッジを詳しく知りたいという方はこちらから !!
IT専門の定額制研修 月額 28,000 円 ~/ 1社 で IT研修 制度を導入できます。
年間 670 講座をほぼ毎日開催中!!
SEプラスにしかないコンテンツや、研修サービスの運営情報を発信しています。