2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Laravel × GeminiAPIで遊んでみた!

Last updated at Posted at 2025-12-13

はじめに

自己紹介とまえがき

こんにちは、C3でHackをしているB2のぶりだいこんです。最近は技術バイトを始めたり、ネクストエンジニアカタパルトで他大学の人と一緒に開発をしたりしています。

さて、ここで私の近況報告は終わりにして内容に入りたいと思います。
近年、ChatGPTやGemini, Soraのような生成AIが目覚ましい発展を遂げていて、それらを組み込んだプロダクトも著しく増えてきている実感があります。

ところで、AIを使うメリットは何なのでしょうか?
考えられるメリットとしては、

・ プロダクトの拡張性が上がること

・ UXが改善されること

などが考えられますね。

また、APIを叩くだけなら実装が必要なところは少ないので、開発者視点のメリットもあります。
例えばGeminiAPIは、Googleアカウントを持ってさえいればすぐ使うことができます。

そして、この記事では実際にGeminiAPIを使ったアプリを作り、今後の開発での道具のひとつとして、LLMを使えるようになることを目標にします。

※今回はハンズオン形式で「とりあえず使ってみる」ために手順を書いています。記述しているコマンドはLaravelのインストールコマンド以外は全部Linuxで動くものを書いています。もし他のOSで動かない場合は読み替えてください。

背景

タイトルを見て不思議に思われた方も多いと思いますが、この記事ではLaravelというPHPのフレームワークを使っています。
このMVCフレームワークの歴史は古く、現在も使っている企業は昔に比べてだいぶ減ってきた印象があります。いまはRubyだったりが多いですかね。
できればLaravelではなく今人気なフレームワークを使って試してみたかったのですが、私が参加している外部のプロジェクトでの技術検証も兼ねてやらなければ、記事の〆切にもそのプロジェクトでの進捗報告にも間に合わなかったので、 (結果的に実装に詰まって記事の〆切には間に合いませんでした...)今回はしぶしぶLaravelを使用しています。

目次

Laravelの環境構築

Laravelのインストール

  • Linux
/bin/bash -c "$(curl -fsSL https://php.new/install/linux/8.4)"
  • Windows PowerShell
# Run as administrator...
Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://php.new/install/windows/8.4'))

インストールが終わったらターミナルを再起動してください。

GeminiAPI

GeminiAPIの概要(各プランと機能について)

GeminiAPIの概要・プラン、APIKeyの取得方法は下記リンクを見ていただければわかると思います!

GeminiAPIのAPI Key取得

GeminiAPIのAPI Keyを取得するためにはGoogleアカウントを用意します。

スクリーンショット 2025-12-13 141643.png

上画像の赤線で囲んだリンクにあるページでAPIキーを取得しましょう。

環境変数

.envに環境変数を追加します。

GEMINI_API_KEY='取得したAPIKeyをここに入力'

実装

作るもの

  • GeminiAPIにリクエストを送る/Geminiからの回答を得るクラス(GeminiControllerクラス)
  • 入力フォーム、GeminiControllerで得た回答を表示する画面(index.blade.php

準備

Laravelのプロジェクトを作成

composer create-project laravel/laravel gemini-client

上のコマンドでgemini-clientという名前でLaravelプロジェクトを作れたらgemini-client(プロジェクトルート)に移動しましょう。

cd gemini-client

プロジェクトのビルド・実行はこのプロジェクトルートで行います。

ライブラリのインストール

GeminiAPIを使うためのライブラリをインストールします。プロジェクトルートに移動して次のコマンドを実行しましょう。

composer require google-gemini-php/client

プログラム

Controller

GeminiAPIを使うために、Controllerを作りましょう。
./app/Http/Controllersに移動して、GeminiController.phpを作ります。

cd app/Http/Controllers

以下のコマンドでGeminiController.phpを作りますphp artisan make:controllerを使うことでひな型が書かれたファイルを作成できます。

php artisan make:controller GeminiController
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Gemini\Laravel\Facades\Gemini; // .envファイルに書いたAPIKeyの読み込みとクライアントの作成を自動で行うためのライブラリ


class GeminiController extends Controller // GeminiControllerクラス
{
    public function index(Request $request) 
    {
        return view('index'); // /indexにGeminiからの回答を乗せる
    }

    public function post(Request $request)
    {
        /* バリデーション */
        $request->validate([
            'sentence' => 'required', // 入力しないと送信ボタンを押せないようにする
        ]);

        $sentence = $request->input('sentence');
        $result = Gemini::generativeModel('gemini-2.5-flash')->generateContent($sentence);        
        $response_text = $result->text();

        return view('index', compact('sentence', 'response_text'));
    }
}

Blade

ここからは表示するためのUIを作ります

./resources/viewsに移動して新しくindex.blade.phpを作成しましょう。

cd resources/views
touch index.blade.php
blade.php
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Gemini AI チャットフォーム</title>
    
    <link rel="stylesheet" href="/css/index.css">
</head>
<body>
    <div id="app-container">
        
        <header>
            <h1>Gemini AI チャットフォーム</h1>
        </header>

        <div class="form-section">
            <form method="POST" action="/index">
                @csrf
                <input 
                    type="text" 
                    name="sentence" 
                    placeholder="質問を入力してください..." 
                    value="{{ isset($sentence) ? $sentence : '' }}"
                    required
                >
                <button type="submit">質問する</button>
            </form>
        </div>

        <div class="result-section">
            <h2>回答</h2>
            @if (isset($response_text) && $response_text)
                @if (isset($sentence))
                    <p class="question">Q: {{ $sentence }}</p>
                @endif
                <div class="response-text">
                    <pre>{{ $response_text }}</pre>
                </div>
            @else
                <p class="placeholder-text">ここにGeminiの応答が表示されます</p>
            @endif
        </div>
    </div>
</body>
</html>

動かすには最低限blade.phpのファイルがあればいいですが、余裕がある人はUIを見やすくするためにCSSでUIを改善しましょう。
私ははじめ./resource/cssにCSSを作ったのですが、うまく読み込まれなかったので./public/cssindex.cssを作りました。そうしたところ、Viteでのビルドが通るようになりました。

/* public/css/index.css */

body {
    font-family: sans-serif;
    background-color: #f4f4f9;
    color: #333;
    margin: 0;
    padding: 0;
}

#app-container {
    max-width: 700px;
    margin: 50px auto;
    padding: 20px;
    background-color: #fff;
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
    border-radius: 8px;
}

header h1 {
    text-align: center;
    color: #007bff;
    margin-bottom: 30px;
}

/* フォームセクション */
.form-section {
    margin-bottom: 30px;
    display: flex;
}

.form-section form {
    display: flex;
    width: 100%;
}

.form-section input[type="text"] {
    flex-grow: 1;
    padding: 10px;
    border: 2px solid #ccc;
    border-radius: 4px 0 0 4px;
    font-size: 16px;
}

.form-section button {
    padding: 10px 20px;
    background-color: #007bff;
    color: white;
    border: none;
    cursor: pointer;
    border-radius: 0 4px 4px 0;
    font-size: 16px;
    transition: background-color 0.3s;
}

.form-section button:hover {
    background-color: #0056b3;
}

/* 結果セクション */
.result-section h2 {
    border-bottom: 2px solid #eee;
    padding-bottom: 10px;
    margin-bottom: 15px;
    color: #555;
}

.result-section .question {
    font-style: italic;
    color: #888;
    margin-bottom: 10px;
}

.result-section .response-text pre {
    white-space: pre-wrap; /* 改行とスペースを保持 */
    background-color: #f0f0f5;
    padding: 15px;
    border-radius: 4px;
    border-left: 5px solid #007bff;
}

.placeholder-text {
    color: #aaa;
    text-align: center;
    padding: 20px;
}

Routing

LaravelはNextやReactのようなAppRouterではないので、自分でURLとHTTPメソッドを指定してあげる必要があります。

今回は/indexにかかるGETとPOSTしか使わないので、以下の2行を./routes/web.phpに追記しましょう

Route::get('/index', [GeminiController::class, 'index']);
Route::post('/index', [GeminiController::class, 'post']);

以下が私の書いたプログラムです。

<?php

use Illuminate\Support\Facades\Route;

use App\Http\Controllers\GeminiController;

Route::get('/index', [GeminiController::class, 'index']); // GETリクエストのルーティング
Route::post('/index', [GeminiController::class, 'post']); // POSTリクエストのルーティング

Route::get('/', function () { // これはもとからあるやつ
    return view('welcome');
});

実行

以下のコマンドを入力して実行してください。

npm install && npm run build # Viteでビルドするためのコマンド
php artisan serve # 最低限このコマンドを打てば実行できます

使ってみる

ここまでの工程を全部できていれば、下画像のようにGeminiを使えていると思います!
画像のように出力されているテキストはMarkdownのコードが出力されていますが、今回私はMarkdownに対応するようには作っていませんので、装飾が反映されていません。

image.png

あとがき

この記事を書くにあたり、初めてLaravelを使ってGeminiAPIを使うアプリを作りました。Laravelは公式ドキュメントこそありますが、新しく書かれたLaravelに関する技術記事が少なくて詰まった時に解決策を調べることがすごく大変でした。大変だった分自分のできることの幅が広がったと思います。また、古い技術の新しいバージョンを使うことは、記事が少ないという点でとても学習・開発が困難であり、自分の自力が試されるところでもあります。その点で、今回は自分の無能さを痛感しました。

作ったプロダクト(Githubのリポジトリ)

私が今回この記事を書くために作ったリポジトリを貼っておきます。
プロダクトについてのREADMEもなく、Issueも切っていないためプロの方からするととても突っ込みどころの多いリポジトリになっていますが、もし動いていたものの全体を見たいときは参照ください。

Qiita版記事のリンクはこちらです(自己紹介文が違うだけです)

参考文献まとめ

以下が今回参考にした記事とリポジトリです。

明日は@eru_suiranさんの「ゆっくりから見る商標登録」と小錦さんの「アニメスクショ風スチルの描き方」です!お楽しみに!

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?