Created
January 10, 2020 00:58
-
-
Save eristoddle/eddc17707cd6c44dbeaf6014cda8339b to your computer and use it in GitHub Desktop.
Laravel CSV Import Controller
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Http\Controllers; | |
use Illuminate\Http\Request; | |
use Illuminate\Foundation\Auth\RegistersUsers; | |
use Illuminate\Support\Facades\Hash; | |
use Illuminate\Support\Facades\Validator; | |
use Illuminate\Support\Facades\Artisan; | |
use Illuminate\Support\Facades\DB; | |
use Illuminate\Support\Facades\Schema; | |
use Illuminate\Support\Facades\Log; | |
class adminController extends Controller | |
{ | |
use RegistersUsers; | |
protected $redirectTo = '/bsladmin/dashboard'; | |
// NOTE: To add another import type just add more to this array and the | |
// rest will be handled by the code. | |
protected $importTypes = [ | |
'Discounts' => [ | |
'model' => 'App\Branch', | |
'id' => 'item_id', | |
'attributes' => [ | |
'item_id', | |
'item_name', | |
'discount_percentage', | |
'discount_deadline', | |
'discount_description', | |
'discount_active_date', | |
'low_base_rate', | |
'high_base_rate', | |
'low_care_rate', | |
'high_care_rate', | |
'community_fee', | |
'real_rates_active', | |
], | |
'ignore' => [ | |
'item_name' | |
] | |
] | |
]; | |
protected $updateNulls = false; | |
/** | |
* Create a new controller instance. | |
* | |
* @return void | |
*/ | |
public function __construct() | |
{ | |
$this->middleware('auth'); | |
} | |
public function dashboard(Request $request) { | |
$imports = array_keys($this->importTypes); | |
return view('admin.dashboard', compact('imports')); | |
} | |
public function downloadTemplate(Request $request) { | |
$importType = $request->input('import'); | |
return $this->generateImportTemplate($importType); | |
} | |
public function runImport(Request $request) { | |
$file = $request->file('csv_file'); | |
if ($file == null) { | |
return redirect()->route('bsladmin/dashboard') | |
->with('error','You forgot to choose a file to import!'); | |
} | |
$path = $file->getRealPath(); | |
$importType = $request->input('import'); | |
// TODO: Figure out why backup is empty or store csv file for restore | |
// $this->backup(); | |
return $this->import($importType, $path); | |
} | |
/** | |
* Create a new user instance after a valid registration. | |
* | |
* @param array $data | |
* @return \App\User | |
*/ | |
protected function newUser(array $data) | |
{ | |
return User::create([ | |
'name' => $data['name'], | |
'email' => $data['email'], | |
'password' => Hash::make($data['password']) | |
]); | |
} | |
/** | |
* Get a validator for an incoming registration request. | |
* | |
* @param array $data | |
* @return \Illuminate\Contracts\Validation\Validator | |
*/ | |
protected function validator(array $data) | |
{ | |
return Validator::make($data, [ | |
'name' => ['required', 'string', 'max:255'], | |
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'], | |
'password' => ['required', 'string', 'min:8', 'confirmed'], | |
]); | |
} | |
protected function backup() { | |
Artisan::call('db:dump'); | |
$output = Artisan::output(); | |
Log::info("Database Backup -- new backup started before data import \r\n" . $output); | |
} | |
protected function listBackups() { | |
} | |
protected function restoreBackup() { | |
} | |
protected function generateImportTemplate(String $importType) { | |
$headers = [ | |
"Content-type" => "text/csv", | |
"Content-Disposition" => "attachment; filename=".$importType."-import-template.csv", | |
"Pragma" => "no-cache", | |
"Cache-Control" => "must-revalidate, post-check=0, pre-check=0", | |
"Expires" => "0" | |
]; | |
$importModel = $this->importTypes[$importType]; | |
$columnNames = $importModel['attributes']; | |
$dbModel = $importModel['model']; | |
$rows = $dbModel::get(); | |
$callback = function() use ($columnNames, $rows ) { | |
$file = fopen('php://output', 'w'); | |
fputcsv($file, $columnNames); | |
foreach ($rows as $row) { | |
$record = $row->toArray(); | |
$trimmed = $this->arrayOnly($record, $columnNames); | |
fputcsv($file, $trimmed); | |
} | |
fclose($file); | |
}; | |
return response()->stream($callback, 200, $headers); | |
} | |
protected function import(String $importType, String $path) { | |
$data = array_map('str_getcsv', file($path)); | |
$attributes = array_shift($data); | |
$importModel = $this->importTypes[$importType]; | |
$columnsCorrect = (count($attributes) == count($importModel['attributes'])) && !array_diff( $attributes, $importModel['attributes']); | |
if ($data == null || $attributes == null || $columnsCorrect != 1) { | |
return redirect()->route('bsladmin/dashboard') | |
->with('error','Incorrect import file!'); | |
} | |
$dbModel = $importModel['model']; | |
$instance = new $dbModel(); | |
$modelTable = $instance->getTable(); | |
$importMap = array_combine($attributes, range(0, count($attributes) - 1)); | |
foreach($data as $row) { | |
try { | |
$instance = $dbModel::where( | |
$importModel['id'], | |
$row[$importMap[$importModel['id']]])->first(); | |
foreach($importModel['attributes'] as $key) { | |
if ($key == $importModel['id']) { | |
continue; | |
} | |
if (in_array($key, $importModel['ignore'])) { | |
continue; | |
} | |
if ((!$this->updateNulls && empty($row[$importMap[$key]]))) { | |
continue; | |
} | |
$columnType = Schema::getColumnType($modelTable, $key); | |
switch ($columnType) { | |
case "date": | |
$date = null; | |
if (!empty($row[$importMap[$key]])) { | |
$date = new \Carbon\Carbon($row[$importMap[$key]]); | |
} | |
$instance->{$key} = $date; | |
break; | |
default: | |
$instance->{$key} = $row[$importMap[$key]]; | |
} | |
} | |
$instance->save(); | |
} catch (Exception $e) { | |
Log::info('Import Error', (array)$e); | |
} | |
} | |
return redirect()->route('bsladmin/dashboard') | |
->with('success','Data imported!'); | |
} | |
protected function arrayOnly($array, $keys) { | |
$remove = array_diff(array_keys($array), $keys); | |
foreach($remove as $key){ | |
unset($array[$key]); | |
} | |
return $array; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment