Начиная с нуля:
Создайте таблицу invoices
и соответствующую модель:
php artisan make: модель счета -m
Ваша модель должна выглядеть так:
<?php
namespace App;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
class Invoice extends Model
{
protected $table = 'invoices';
protected $fillable = [
'user_id',
'processed',
'path'
];
public function scopeNotProcessed(Builder $query)
{
return $this->where('processed', '=', false);
}
}
А вот таблица invoices
:
public function up()
{
Schema::create('uploads', function (Blueprint $table) {
$table->increments('id');
$table->string('path')->nullable(false);
$table->boolean('processed')->default(false)->nullable(false);
$table->timestamps();
});
}
После того, как все это будет сделано, сделайте следующее:
Создайте репозиторий, который будет загружать ваш CSV-файл. Этот файл должен быть помещен в
app/Repositories/CSVRepository
<?php
namespace App\Repositories;
use Illuminate\Support\Facades\Storage;
use App\Invoice;
class CSVRepository {
/**
* CSVRepository constructor.
*/
public function __construct()
{
//
}
/**
* @param $file
* @param $extension
* @return mixed
*/
public function uploadCSV($file, $extension){
return $this->upload($file, $extension);
}
/**
* @param $file
* @param $extension
* @return mixed
*/
private function upload($file, $extension){
$path = Storage::putFileAs("myFileName", $file, uniqid().".".$extension);
$uploadedFile = Invoice::create([
'path' => $path,
'processed' => false,
]);
return $uploadedFile;
}
}
Теперь создайте свой контроллер, который будет загружать файл на сервер, используя CSVRepository
:
Функция загрузки должна выглядеть следующим образом:
public function upload(CSVRepository $CSVRepository)
{
try{
$file = Input::file('file');
$extension = strtolower($file->getClientOriginalExtension());
if ($extension !== 'csv'){
$errors['file'] = 'This is not a .csv file!';
return redirect()->back()->withInput()->withErrors($errors);
}
$CSVRepository->uploadCSV($file, $extension);
$message = array(
'type' => 'success',
'text' => 'Your file has been uploaded! You will receive an email when processing is complete!',
'title' => 'Success',
);
session()->flash('message', $message);
return redirect('route-to-redirect');
}catch (\Exception $exception){
return abort(Response::HTTP_INTERNAL_SERVER_ERROR, 'Internal Server Error');
}
}
Теперь вам нужна работа, которая обрабатывает файл для вас:
Начните создавать команду с помощью команды ремесленника:
php artisan make: команда ProcessCSVCommand
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Invoice;
use Illuminate\Support\Facades\Storage;
class ProcessCSVCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'csv:process';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Process an uploaded CSV file';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
try{
//Retrieve only no processed files:
$invoices = Upload::notProcessed()->get();
if (count($files) < 1){
$this->info('No files found');
return;
}
//Process the files:
$invoices->map(function($invoice){
$file = fopen("storage/app/".$invoice->path, "r");
while (!feof($file)){
$line = fgets($file);
//Here you have a loop to each line of the file, and can do whatever you need with this line:
if(strlen($line) > 0){ //If the line is not empty:
// Add your logic here:
}
// Don't forgot to change your `processed` flag to true:
$invoice->processed = true;
$invoice->save();
}
});
}catch (\Exception $exception){
$this->error("Something went wrong");
return $exception->getMessage();
}
}
}
Теперь откройте файл app/Console/Commands/Kernel.php
:
Зарегистрируйте новую команду в массиве $commands
:
$commands = [
Commands\ProcessCSVCommand::class,
];
Запланируйте задание, которое будет выполняться на вашем сервере, проверяя файлы, которые нужно обработать, и, если это так, обрабатывайте их:
В том же файле, теперь с функцией schedule
:
protected function schedule(Schedule $schedule)
{
$schedule->command('csv:process')
->everyFiveMinutes();
}
Надеюсь, это поможет.