Je souhaite créer une fonctionnalité dans Laravel 5.8 qui puisse m'aider à télécharger un fichier CSV et à importer les données dans la base de données, mais tout devrait être en arrière-plan (côté serveur) et une fois terminé, envoyez un e-mail au utilisateur connecté. Je veux avoir une meilleure compréhension avant de commencer le processus si je le fais avec l'aide de Scheduler
ou il y aurait un meilleur moyen ou une meilleure bibliothèque qui peut m'aider à réaliser cette fonctionnalité.
Au plaisir d'entendre vos impressions :)
Merci.
3 Réponses :
Les files d'attente sont la voie à suivre pour ce genre de travail. Le téléchargement du fichier doit essentiellement se produire dans cette demande, mais au-delà de cela, vous pouvez créer une ou plusieurs files d'attente qui seront supprimées lors de la conversion du CSV en enregistrements dans la base de données.
En partant de zéro:
Créez un tableau factures
et le modèle correspondant:
php artisan make: model Invoice -m
Votre modèle devrait ressembler à ceci:
protected function schedule(Schedule $schedule) { $schedule->command('csv:process') ->everyFiveMinutes(); }
Et voici le tableau des factures
:
$commands = [ Commands\ProcessCSVCommand::class, ];
Après avoir fait ces choses, procédez comme suit:
Créez un dépôt, ce qui va télécharger votre fichier csv. Ce fichier doit être placé à
app/Repositories/CSVRepository
:
<?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 = Invoice::notProcessed()->get(); if (count($invoices) < 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(); } } }
Maintenant, créez votre contrôleur, qui téléchargera le fichier sur le serveur en utilisant le CSVRepository code>:
La fonction de téléchargement devrait ressembler à celle-ci:
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'); } }
Maintenant, vous avez besoin d'un travail qui traite le fichier pour vous:
Commencez à créer une commande la commande artisan:
php artisan make: commande ProcessCSVCommand
<?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; } }
Maintenant, ouvrez votre fichier app / Console / Kernel.php
:
Enregistrez votre nouvelle commande dans le $ commands
array:
public function up() { Schema::create('invoices', function (Blueprint $table) { $table->increments('id'); $table->string('path')->nullable(false); $table->boolean('processed')->default(false)->nullable(false); $table->timestamps(); }); }
Planifier une tâche qui s'exécute sur votre serveur, en vérifiant les fichiers à traiter et, si oui, en les traitant: p >
Dans le même fichier, maintenant à la fonction planning
:
<?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); } }
J'espère que cela aide.
Je pense que vous voudrez peut-être envisager d'utiliser les files d'attente et d'écouter l'événement traité par le travail comme mentionné ici https://laravel.com/docs/5.8/queues#job-events d'où vous pouvez ensuite envoyer vos e-mails