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 は名前の通りエクセルファイルも扱えます。

ここまでのものはGithubに置いてます。

参考サイト
【Laravel-Excel】表ファイルを読み込んでそのままDBに保存する方法【CSVインポート】