Je suis donc un noob complet pour Laravel et j'essaie quelque chose ici. Je veux importer un fichier CSV dans deux tables, j'ai une table appelée listes qui obtiendra le nom de la liste et un client_id
.
Ensuite, j'ai une table appelée clients qui obtiendra le nom de famille, le numéro de contact ainsi que client_id
et un list_id
.
Ce que je veux réaliser est d'importer un fichier CSV qui prendra le nom de fichier et le stockera dans la table de liste, puis créera un tableau via le fichier CSV et importera les données dans la table des clients avec la liste et les identifiants client.
J'ai fait la première partie, et elle s'insère correctement dans le tableau des listes, comment puis-je créer un tableau à partir du CSV qui se trouve dans le stockage/documents, puis l'insérer dans le tableau des clients?
namespace App\Http\Controllers;
use Input;
use DB;
use Illuminate\Http\Request;
use App\Http\Requests\ListsRequest;
use App\Lists;
use App\Clients;
use App\Http\Requests;
use App\Http\Controllers\Controller;
class ListsController extends Controller {
public function index()
{
// $list_items = Lists::all();
$clients = Clients::all();
return view('lists.show', compact('clients'));
}
public function store(Requests\ListsRequest $request)
{
$input = $request->input();
Lists::create($input);
if (Input::hasFile('name'))
{
$file = Input::file('name');
$name = time() . '-' . $file->getClientOriginalName();
$path = storage_path('documents');
$file->move($path, $name);
// All works up to here
// All I need now is to create an array
// from the CSV and insert into the customers database
}
}
}
J'ai choisi d'utiliser la réponse que j'avais acceptée mais j'ai aussi joué avec l'autre réponse et je l'ai fait fonctionner comme ça.
public function store(Requests\ListsRequest $request)
{
$input = $request->input();
$client_id = $request->input('client_id');
if (Input::hasFile('name'))
{
$file = Input::file('name');
$name = time() . '-' . $file->getClientOriginalName();
$path = storage_path('documents');
Lists::create(['client_id' => $client_id, 'name' => $name]);
$reader = Reader::createFromPath($file->getRealPath());
// Create a customer from each row in the CSV file
$headers = array();
foreach ($reader as $index => $row)
{
if ($index === 0)
{
$headers = $row;
} else
{
$data = array_combine($headers, $row);
Customers::create($data);
}
}
$file->move($path, $name);
return view('clients');
}
}
Il y a 3 étapes pour lire un fichier CSV et l'importer dans la base de données de Laravel.
Avant de commencer, j'ai créé un exemple de fichier test.csv
Et je l'ai placé dans mon dossier public sous le dossier file:
name,email,password
user1,[email protected],pasxxxxxxxxxword
user2,[email protected],pasxxxxxxxxxword
user3,[email protected],pasxxxxxxxxxword
Étape 1 et 2; J'ai créé une fonction d'aide appelée csvToArray
, je viens de la mettre dans mon contrôleur pour l'instant (cette fonction est inspirée de cela link ) elle lit simplement le fichier CSV et le convertit en tableau:
function csvToArray($filename = '', $delimiter = ',')
{
if (!file_exists($filename) || !is_readable($filename))
return false;
$header = null;
$data = array();
if (($handle = fopen($filename, 'r')) !== false)
{
while (($row = fgetcsv($handle, 1000, $delimiter)) !== false)
{
if (!$header)
$header = $row;
else
$data[] = array_combine($header, $row);
}
fclose($handle);
}
return $data;
}
Étape 3; Et voici ma dernière étape, lire le tableau et l'insérer dans notre base de données:
public function importCsv()
{
$file = public_path('file/test.csv');
$customerArr = $this->csvToArray($file);
for ($i = 0; $i < count($customerArr); $i ++)
{
User::firstOrCreate($customerArr[$i]);
}
return 'Jobi done or what ever';
}
Remarque: cette solution suppose que vous avez un modèle dans votre projet Laravel et que la table est appropriée dans votre base de données.
Dans votre méthode store()
, créez l'enregistrement dans votre table lists
, puis parcourez le contenu du fichier CSV et insérez les données dans la table customers
. Vous devez créer une relation entre les clients et les listes à cet effet. Vous feriez également mieux d’utiliser quelque chose comme le package CSV de PHP League pour lire ces fichiers:
public function store(AddCustomersRequest $request)
{
// Get uploaded CSV file
$file = $request->file('csv');
// Create list name
$name = time().'-'.$file->getClientOriginalName();
// Create a list record in the database
$list = List::create(['name' => $name]);
// Create a CSV reader instance
$reader = Reader::createFromFileObject($file->openFile());
// Create a customer from each row in the CSV file
foreach ($reader as $index => $row) {
$list->customers()->create($row);
}
// Redirect back to where you need with a success message
}
@maytham La solution de Maytham fonctionnera bien. Cependant, cela posera un énorme problème si vous essayez de traiter des données volumineuses. Même si vous faites 1000 lignes, cela créera un problème, car cela fera 1000 instructions d'insertion séparément. Je vais juste éditer la troisième méthode par lui et ajouter ma propre entrée
public function importCsv()
{
$file = public_path('file/test.csv');
$customerArr = $this->csvToArray($file);
$date = [];
for ($i = 0; $i < count($customerArr); $i ++)
{
$data[] = [
'column_name1' => 'value',
'column_name2' => 'value2',
.. so..on..and..on
];
//User::firstOrCreate($customerArr[$i]);
}
DB::table('table_name')->insert($data);
return 'Jobi done or what ever';
}
Cela appellera la base de données une fois pour insérer autant de lignes que vous le souhaitez. Que ce soit 1000, 100000 ou autre. Cependant, si vous avez un énorme csv, ce sera aussi un problème car vous devrez insérer des morceaux. Comme dans PostgreSQL, j'ai remarqué que vous pouvez insérer jusqu'à 65 000 lignes quelque chose dans une seule instruction. Peut-être Je me trompe sur le nombre mais il y a une limite dans chaque base de données et vous devez le chercher.