Laravelの基本はこちらから学べます

Laravelで画像投稿機能をつけよう。初めてのCloudinary。




今回から前回までで作成した、掲示板に画像投稿機能を作成していきます。

今回使うのは「Cloudinary」です。

画像を保存できるクラウドサービスです。Cloudinaryを使用せずとも画像投稿機能を実装することはできるのですが、こちらを利用することでリサイズができたりと非常に便利なので活用しましょう。

youtubeにも投稿しています。

Cloudinaryに登録する

私たちが使う範囲では無料ですのでご安心ください。
まずは以下リンクから新規登録をしましょう。

https://cloudinary.com/users/register/free

Your name: お名前
E- mail:メアド
Password: パスワード
Country: 国
Phone: 電話番号
Company or site name: オプショナルなので不要
Primary interest: Image and Video Management via APIs でいいと思います

新規登録時に入力したメールアドレスに認証メールが届くと思うので、そちらから認証を進めましょう。

Dashboard画面を表示できれば完了です!

Dashboard画面にある「Account Details」にあるAPI Key等はのちほど使います。

Laravel側の設定

https://github.com/jrm2k6/cloudder
利用するライブラリは上記になります。

 上記リンクを開き、README.mdを見ながら進めていきましょう。

まずはterminalでcomposerを使ってインストールをしましょう。

composer require jrm2k6/cloudder

次にenvファイルにCloudinaryのAPI Keyを登録しましょう。API KeyはCloudinaryのDashboardを確認してください。

CLOUDINARY_API_KEY=012345679890123 →あなたのKey
CLOUDINARY_API_SECRET=foobarfoobarfoob-arfoobarfo →あなたのKey
CLOUDINARY_CLOUD_NAME=foobarcorp →あなたのcloud name

config/app.phpを開いてください。以下を追記しましょう。

'providers' => [

  JD\Cloudder\CloudderServiceProvider::class,

],

'aliases' => [

  'Cloudder' => JD\Cloudder\Facades\Cloudder::class,

],

次にterminalで以下のコマンドを打ちます。

php artisan vendor:publish --provider="JD\Cloudder\CloudderServiceProvider"

カラムの追加

私たちが作成していた掲示板ではまだ、データベース側で画像投稿の準備ができていませんでした。
→Postsテーブルに画像関連カラムを準備していないという意味

なのでコマンドをうち、migrationファイルを作りましょう。

php artisan make:migration add_image_path_and_public_id_to_posts_table

database/migrations/add_image_path_and_public_id_to_posts_table.php

が作成されました。

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class AddImagePathAndPublicIdToPostsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('posts', function (Blueprint $table) {
            $table->text('image_path')->nullable();
            $table->text('public_id')->nullable();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('posts', function (Blueprint $table) {
            $table->dropColumn('image_path');
            $table->dropColumn('public_id');
        });
    }
}

上記のようにpostsテーブルにカラム「image_path」「public_id」を追加しました。

追記が完了したら、ターミナルでmigrationをしましょう。

php artisan migrate

エラーが出なければOKです!

画像アップロードの処理

私の掲示板アプリを進めていただいている方は

create.blade.phpを開きましょう。

<form action="{{ route('posts.store') }}" method="POST" enctype="multipart/form-data">
            {{csrf_field()}} 
                <div class="form-group">
                    <label>タイトル</label>
                    <input type="text" class="form-control" placeholder="タイトルを入力して下さい" name="title">
                </div>
                <div class="form-group">
                    <label>内容</label>
                    <textarea class="form-control" placeholder="内容" rows="5" name="body"></textarea>
                </div>
                <div class="form-group">
                    <label for="image">画像</label>
                    <input type="file" class="form-control-file" id="image" name="image">
                </div>
                <button type="submit" class="btn btn-primary">作成する</button>
            </form>

enctype=”multipart/form-data” を追加しました。ファイルのアップロードを行う場合に必須になりますので忘れずに記入しましょう。

input type=”file”として画像をアップロードする箇所も追加しています。

上記のようになっていればOKです。

次にPostController.phpを開きましょう。
実際にCloudinaryにアップロードし、データベースにも保存していきます。

use JD\Cloudder\Facades\Cloudder;


public function store(PostRequest $request)
    {
       $post = new Post;

        $post->title      = $request->title;
        $post->body       = $request->body;
        $post->user_id    = Auth::id();

        if ($image = $request->file('image')) {
            $image_path = $image->getRealPath();
            Cloudder::upload($image_path, null);
            //直前にアップロードされた画像のpublicIdを取得する。
            $publicId = Cloudder::getPublicId();
            $logoUrl = Cloudder::secureShow($publicId, [
                'width'     => 200,
                'height'    => 200
            ]);
            $post->image_path = $logoUrl;
            $post->public_id  = $publicId;
        }

        $post->save();
        
        return redirect()->route('posts.index');
    }

以前の処理に画像の処理を追加しました。

if文でユーザーが画像をアップロードしていた時の処理を記入しています。

getRealPath()でファイルへの絶対PATHを取得します。以下参考。

https://www.php.net/manual/ja/splfileinfo.getrealpath.php

Cloudder::upload()でCloudinaryにファイルをアップロードします。

Cloudder::getPublicId();で直前にアップロードされたファイルのpublicIdを取得します。
このpublicIdはCloudinary上の画像を削除したり、リサイズしたりする場合に必要になります。

Cloudder::show()でサイズを指定した画像へのURLを取得します。

バリデーションも追加しましょう

PostRequest.php

public function rules()
    {
        return [
            'title' => 'required|max:20',
            'body'  => 'required',
            'image' => 'mimes:jpeg,jpg,png,gif|max:10240',
        ];
    }

    public function messages()
    {
        return [
            'title.required' => 'タイトルは必須です。',
            'title.unique'   => 'タイトルが被っています',
            'title.max'      => 'タイトルは20文字以内で記入してください。',
            'body.required'  => '内容は必須です。',
            'image.mimes'    => 'ファイルタイプをjpeg,jpg,png,gifに設定してください。',
            'image.max'      => 'ファイルサイズを10MB以下に設定してください。',
        ];
    }

保存した画像を表示してみる

投稿の詳細画面で画像を表示してみたいと思います。

show.blade.php

<img src="{{ $post->image_path }}" alt="画像">

を追加しましょう。すると、

画像を出すことができました!

画像をCloudinaryから削除する。

え??削除ボタン押せばいいんじゃないの?と思った方。おしい。

データベースから「image_path」「public_id」を消してもCloudinaryから画像は削除されません。

Cloudder::destroyImage()

を使用します。

PostController.php

public function destroy($id)
    {
        $post = Post::find($id);

        if(Auth::id() !== $post->user_id){
            return abort(404);
        }

        if(isset($post->public_id)){
            Cloudder::destroyImage($post->public_id);
        }

        $post -> delete();

        return redirect()->route('posts.index');
    }

こちらで削除機能が完成しました。

実際にCloudinaryのMedia Libraryから画像が削除されているか確認しましょう。

今回はここまでにします!お疲れ様でした。




コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です