Laravel 5.4
laravelcollective 5.4
Laravel Excel v2.1
を使用します。
Laravel Excelのインストール
Composerでインストールします。
composer require "maatwebsite/excel:~2.1.0"
Laravel Excel Documentation – Maatwebsite
初期設定
Laravel 5.5は必要ないですが、5.4まではコンフィグファイルにサービスプロバイダーとエイリアス登録します。
config/app.php
'providers' => [ // ... Maatwebsite\Excel\ExcelServiceProvider::class, ], 'aliases' => [ // ... 'Excel' => Maatwebsite\Excel\Facades\Excel::class, ],
CSVファイルについて
今回は価格表を想定したテーブル構造にしてみます。
アップロードCSVファイルの最初の行はカラム名を入れます。
price.csv
id,code,name,price 1,G001,商品1,100 2,G002,商品2,200 3,G003,商品3,300 4,G004,商品4,400 5,G005,商品5,500 6,G006,商品6,600 7,G007,商品7,700 8,G008,商品8,800 9,G009,商品9,900 10,G010,商品10,1000
データベース作成
データベースは「商品コード」「商品名」「金額」の項目を作成してみます。
config/app.php
use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreatePricesTable extends Migration { public function up() { Schema::create('prices', function (Blueprint $table) { $table->increments('id'); $table->integer('code'); $table->string('name'); $table->integer('price'); }); } public function down() { Schema::dropIfExists('prices'); } }
migrate
コマンドでデータベースにテーブルを作成します。
$ php artisan migrate
モデルの作成
モデルです。特別なことはありませんが、タイムスタンプを無効にしてます。
config/app.php
namespace App; use Illuminate\Database\Eloquent\Model; class Price extends Model { public $timestamps = false; protected $fillable = [ 'code', 'name', 'price' ]; }
ルーティングの作成
管理画面から編集するという感じにしたいので「admin」でプレフィクスやらネームスペースを付与しています。
croutes/web.php
Route::group(['prefix' => 'admin', 'namespace' => 'Admin', 'as' => 'admin::'], function() { Route::get('prices', 'PricesController@index')->name('prices'); Route::patch('prices/upload', 'PricesController@upload')->name('prices.upload'); Route::get('prices/download', 'PricesController@download')->name('prices.download'); });
ビューの作成
ビューにはファイルをアップロードするフォームとダウンロードするボタンを設置します。
resources/views/admin/prices/index.blade.php
{!! Form::model($prices, [ 'url' => route('admin::prices.upload'), 'method' => 'PATCH', 'files' => true ]) !!} <div class="row"> <div class="col-md-4"> {!! Form::file('csv_file', null, ['class' => 'form-control']) !!} </div> <div class="col-md-8"> {!! Form::submit('アップロード', ['class' => 'btn btn-primary']) !!} </div> </div> {!! Form::close() !!} {{ link_to_route('admin::prices.download', 'ダウンロード', null, ['class' => 'btn btn-primary']) }}
コントローラーの作成
メインとなる部分です。
アップロードは差し替えにしたかったので、データを挿入する前にtruncate
で全削除しています。
CSVのパース自体は\Excel::load
だけでしてくれます。
ある程度不特定のユーザーが使用擦る場合はもう少しデータのバリデーションも追記した方がよさそうですね。
app/Http/Controllers/Admin/PricesController.php
namespace App\Http\Controllers\Admin; use Illuminate\Http\Request; use App\Http\Controllers\Controller; use App\Price; class PricesController extends Controller { public function index() { $prices = Price::all(); return view('admin.prices.index', compact('prices')); } public function upload(Request $request) { $this->validate($request, [ 'csv_file' => 'required|mimes:txt|max:1000' ]); $file = $request->file('csv_file'); // ファイルの読み込み $reader = \Excel::load($file->getRealPath())->get(); $rows = $reader->toArray(); // 一度削除してから保存 Price::truncate(); if(count($rows)){ foreach ($rows as $row) { Price::firstOrCreate($row); } } \Session::flash('flash_message', '価格表を更新しました。'); return redirect()->route('admin::prices'); } public function download(){ $price = Price::get()->toArray(); return \Excel::create('price', function($excel) use ($price) { $excel->sheet('sheet', function($sheet) use ($price) { $sheet->fromArray($price); }); })->download('csv'); } }
今回はCSVでしたが、Laravel Excel は名前の通りエクセルファイルも扱えます。
参考サイト
【Laravel-Excel】表ファイルを読み込んでそのままDBに保存する方法【CSVインポート】