🍏

【Laravel 】Laravel-adminにCSVインポート機能を実装する方法

2022/06/11に公開

Laravel-adminにCSVインポート機能の実装したいがなかなか苦戦したので備忘録的に記述します!

完成イメージ

①CSVインポートボタンを押下する

②インポートしたいCSVを押下する

③アップロードができた場合、「Upload Successful」と表示される

今回使うデータ

Laravel-adminをインストールした時点でUser.phpのモデルが作成されているのでこちらを利用してUseControllerを作成する。

php artisan admin:make UserController --model=App\\Models\\User

参照:https://laravel-admin.org/docs/en/quick-start

今回は「名前・メールアドレス」をCSVインポートすると想定して実装を進めます。

※Laravel-adminのCRUD処理ついてはまたの機会に書こうと思います!

CSVインポートで使うライブラリー「Goodby/CSV」

こちらの記事をめちゃくちゃ参考にさせていただきました!!(ありがとうございます!)
https://sazaijiten.work/csv_import/
今回は「Goodby/CSV」のライブラリーを使用します。

composer require goodby/csv

上記コマンドで「Goodby/CSV」のライブラリーをインストール

composer.jsonに下記内容が記載されていたらOK(バージョンが異なる可能性があります)

composer.json
"goodby/csv": "^1.3",

実装開始!

ボタンの実装 →Actionで書いていく!

追加ボタンを作成する際には公式の「Custom tools」を参考にしました。

App/Adminの配下に「\Extensions\Tools」のフォルダを作成し、CsvImportのファイルを作成しました。
(Custom toolsの公式を参考)

CsvImport.php
<?php

namespace App\Admin\Extensions\Tools;
 
use Encore\Admin\Admin;
use Encore\Admin\Grid\Tools\AbstractTool;

class CsvImport extends AbstractTool
{
    /**
     * Set up script for import button.
     */
    protected function script()
    {
        return <<< SCRIPT

        // ボタン押下でCSVインポート
        $('.csv-import').click(function() {
            var select = document.getElementById('files');
            document.getElementById("files").click();
            select.addEventListener('change',function() {
                var fd = new FormData();
                fd.append( "file", $("input[name='user']").prop("files")[0] );
                $.ajaxSetup({
                    headers: {
                        'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
                    }
                });
                $.ajax({
                    type : "POST",
                    url : "/admin/users/import",
                    data : fd,
                    processData : false,
                    contentType : false,
                    success: function (response) {
                        $.pjax.reload("#pjax-container");
                        toastr.success('Upload Successful');
                    }
                });
            });
        });

        SCRIPT;
    }
     
    /**
     * Render Import button.
     *
     * @return string
     */
    public function render()
    {
            Admin::script($this->script());

            return view('csv_upload');
    }
}

Bladeを作成

csv_upload.blade.php
<div class="btn-group pull-right" style="margin-right: 10px">
    <a href="#" class="btn btn-sm btn-twitter csv-import"><i class="fa fa-upload"></i><span class="hidden-xs"> CSVインポート</span></a>
    <input type="file" id="files" name="user" style="display: none">
</div>

CSVインポートのメソッドを作成

今回はUserControllerに記述します。

UserContoller.php
// 追加したuse
use App\Admin\Extensions\Tools\CsvImport;
use Goodby\CSV\Import\Standard\Lexer;
use Goodby\CSV\Import\Standard\Interpreter;
use Goodby\CSV\Import\Standard\LexerConfig;
use Illuminate\Http\Request;

~~
    public function csvImport(Request $request)
    {
        $file = $request->file('file');
        $config = new LexerConfig();
        $lexer = new Lexer($config);
    
        $interpreter = new Interpreter();
        $rows = array();

        // 列数の厳密なチェックを行わない
        $interpreter->unstrict();
	
	// インポートする値を$rowに代入
        $interpreter->addObserver(function (array $row) use (&$rows) {
            $rows[] = $row;
        });

        // CSVデータをパース(データを解析しプログラムが使えるようなデータの構造に変換する)
        $lexer->parse($file, $interpreter);
        foreach ($rows as $key => $value) {
            // データの作成
            User::create([
                'name' => $value[0],
                'email' => $value[1],
                'password' => $value[3],
            ]);
        }

        return response()->json(
            [
                'data' => '成功'
            ],
            200,
            [],
            JSON_UNESCAPED_UNICODE
        );
    }

Route.phpの作成

adminフォルダの中にroute.phpがあるのでそこに以下を追記します。

route.php
    $router->post('users/import', [UserController::class, 'csvImport']);

終了!ここまでお疲れ様でした!!

なかなか上手く動かなくて苦戦したCSVImportの機能でした。
本当に他の方のサイトがなければここまで辿り着くことができませんでした。

Laravel-adminを使っての感想

カスタマイズをあまりしないのであればだいぶ楽に管理画面を作成することができるなと感じました。
ただ、カスタマイズがかなり大変。。といった印象です。
他にもLaravel-adminを触る際に自分が困ったこと等を記事にしていきたいと思っております!

最後までお読みいただきありがとうございました!
次回もお楽しみに!!

Discussion