Я новичок в voyager, есть ли способ загружать пользователей через CSV в voyager. Я предполагаю, что мне придется создать для этого собственный шаблон, любой, кто может указать мне правильное направление в этом вопросе, я был бы очень признателен.






Я знаю, что это старый вопрос, но поскольку это первое, с чем я сталкиваюсь, когда исследую то же самое, я хотел добавить ответ, чтобы те, кто приходит сюда, могли извлечь выгоду.
Это решение для Laravel 8.9.0 и Voyager 1.4.
Здесь есть выбор перед загрузкой CSV, это не обязательно, но полезно, поэтому вам не нужно настраивать CSV перед загрузкой.
Я использовал другой ресурс для этого, который был в Laravel 5.5, вы можете увидеть исходные коды из Импорт CSV для Laravel-5.5
Я также добавлю форк, который обновился до Laravel 9.0 после того, как я закончил свой собственный проект.
Во всяком случае, я использую Laravel-Excel 3.1.24 для чтения CSV. Ресурс использовал старую версию.
Начнем кодирование
Прежде чем подключать его к Voyager, сначала вы должны знать, что вам нужно написать свое представление и контроллер для выполнения этой работы.
Также нам понадобится наша модель. Убедитесь, что вы добавили все необходимые поля для своей модели пользователя. Создайте миграцию с теми же потребностями.
Например, если в вашей модели пользователя это есть;
protected $fillable = [
'name',
'email',
'password',
];
Убедитесь, что ваша миграция;
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
После настройки модели и миграции вам понадобится еще одна модель для хранения CSV-файла. Это будет полезно при выборе полей CSV и базы данных. В нем будет всего три поля; csv_filename, csv_header, csv_data.
После настройки наших моделей нам нужно добавить config / app.php к нашему выбору.
'db_fields' => [
'name',
'email',
'password',
]
Эти поля мы получим из CSV, вы можете удалить пароль, если у вас нет пароля в вашем CSV-файле.
Прежде чем войти в наш Контроллер, мы должны добавить Laravel-Excel. Из документации все, что вам нужно сделать, это запустить эту команду в терминале.
composer require "maatwebsite/excel:3.1.24"
Это добавит Laravel-Excel в наш проект. Нашему контроллеру потребуется «import», который является классом, который помогает нам импортировать файлы, поставляется с Laravel-Excel. За это;
php artisan make:import CsvImport --model=User
Вы можете использовать его для быстрого старта, как рекомендовано в документации Laravel-Excel. Теперь мы можем войти в наш Контроллер. Мы создадим контроллер для команд Laravel. Нам понадобится куча вещей;
use App\Imports\CsvImport; //This is needed for Laravel-Excel.
use Illuminate\Http\Request;
use App\Models\User; //Our user model.
use App\Models\CsvData; //Our model for csv.
use App\Http\Requests\CsvImportRequest; //I'll share this in a sec.
use Maatwebsite\Excel\Facades\Excel; //This is from Laravel-Excel
use Illuminate\Support\Str; //This is for basic password creation
class ImportController extends Controller
{
Нам нужны следующие функции:
public function form()
{
return view('import.form');
}
Эта функция довольно проста. Это вернет наш взгляд. Второй - когда мы анализируем наш CSV и сохраняем в нем добавляем CSV_Data. Но сначала нам нужен запрос, как того хотел Laravel.
php artisan make:request CSVImportRequest
Я поделюсь своим;
class CsvImportRequest extends FormRequest
{
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'csv_file' => 'required|file'
];
}
Теперь мы можем вернуться к нашему контроллеру;
public function parseImport(CsvImportRequest $request)
{
//we getting with the request the file. So you need to create request with
//Laravel. And you should add this to your Controller as use App\Http\Requests\CsvImportRequest;
$path = $request->file('csv_file')->getRealPath();
if ($request->has('header')) {
//this is coming from Laravel-Excel package. Make sure you added to your
//controller; use Maatwebsite\Excel\Facades\Excel;
$data = Excel::toArray(new CsvImport, request()->file('csv_file'))[0];
} else {
$data = array_map('str_getcsv', file($path));
}
if (count($data) > 0) {
//checking if the header option selected
if ($request->has('header')) {
$csv_header_fields = [];
foreach ($data[0] as $key => $value) {
$csv_header_fields[] = $key;
}
}
$csv_data = array_slice($data, 0, 2);
//creating csvdata for our database
$csv_data_file = CsvData::create([
'csv_filename' => $request->file('csv_file')->getClientOriginalName(),
'csv_header' => $request->has('header'),
'csv_data' => json_encode($data)
]);
} else {
return redirect()->back();
}
//this is the view when we go after we submit our form.We're sending our data so we can select to match with db_fields.
return view('import.fields', compact('csv_header_fields', 'csv_data', 'csv_data_file'));
}
А теперь функция импорта.
public function processImport(Request $request)
{//we are getting data from request to match the fields.
$data = CsvData::find($request->csv_data_file_id);
$csv_data = json_decode($data->csv_data, true);
$request->fields = array_flip($request->fields);
foreach ($csv_data as $row) {
$contact = new User();
foreach (config('app.db_fields') as $index => $field) {
//using config app.db_fields while matching with request fields
if ($data->csv_header) {
if ($field == "null") {
continue;
} else if ($field == "password") {
//this is checkin if password option is set. If not, it is creating a password. You can eliminate this according to your needs.
if (isset($request->fields['password'])) {
$pw = $row[$request->fields['password']];
} else {
$pw = Str::random(10);
}
} else
$contact->$field = $row[$request->fields[$field]];
} else
//same with the if but without headers. You can create a function to avoid writing
//codes twice.
{
if ($field == "null") {
continue;
} else if ($field == "password") {
if (isset($request->fields['password'])) {
$pw = $row[$request->fields['password']];
} else {
$pw = Str::random(10);
}
} else
$contact->$field = $row[$request->fields[$index]];
}
}
$user = User::where(['email' => $contact->email])->first();
//checking for duplicate
if (empty($user)) {
$contact->password = bcrypt($pw);
$contact->save();
} else {
$duplicated[] = $contact->email;
//if you want you can keep the duplicated ones to check which ones are duplicated
}
}
//you can redirect wherever you want. I didn't need an success view so I returned
//voyagers original users view to see my data.
return redirect(route('voyager.users.index'));
}
Теперь мы можем создавать наши маршруты. Поскольку мы используем Voyager, не забудьте добавить voyager., Чтобы мы могли использовать его с панелью администратора Voyager.
use App\Http\Controllers\ImportController;
Route::group(['prefix' => 'admin','as' => 'voyager.', 'middleware' => 'admin.user'],
function()
{
Route::get('import',[ImportController::class, 'form'])->name("import.form");
Route::post('import/parse', [ImportController::class, 'parseImport'])-
>name("import.parse");
Route::post('import/process', [ImportController::class, 'processImport'])-
>name("import.process");
});
Также нам понадобится представление при импорте и выборе. Я создал свои представления в views / import.
Для вашего лезвия формы вы хотите использовать его с voyager, поэтому вам следует
@extends('voyager::master')
используйте это, чтобы иметь ту же тему. После этого вам нужно добавить свой html с разделом.
@section('content')
<div class = "container">
<div class = "row">
<div class = "col-md-8 col-md-offset-2">
<div class = "panel panel-default">
<div class = "panel-heading">CSV Import</div>
<div class = "panel-body">
<form class = "form-horizontal" method = "POST" action = "{{ route('voyager.import.parse') }}" enctype = "multipart/form-data">
{{ csrf_field() }}
<div class = "form-group{{ $errors->has('csv_file') ? ' has-error' : '' }}">
<label for = "csv_file" class = "col-md-4 control-label">CSV file to import</label>
<div class = "col-md-6">
<input id = "csv_file" type = "file" class = "form-control" name = "csv_file" required>
@if ($errors->has('csv_file'))
<span class = "help-block">
<strong>{{ $errors->first('csv_file') }}</strong>
</span>
@endif
</div>
</div>
<div class = "form-group">
<div class = "col-md-6 col-md-offset-4">
<div class = "checkbox">
<label>
<input type = "checkbox" name = "header" checked> File contains header row?
</label>
</div>
</div>
</div>
<div class = "form-group">
<div class = "col-md-8 col-md-offset-4">
<button type = "submit" class = "btn btn-primary">
Parse CSV
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection
Как видите, мы используем «путешественник». чтобы добавить наш маршрут. Это также поможет нам в настройках Voyager. Наше второе представление - это то, где мы выбираем наши db_fields.
@extends('voyager::master')
@section('content')
<div class = "container">
<div class = "row">
<div class = "col-md-8 col-md-offset-2">
<div class = "panel panel-default">
<div class = "panel-heading">CSV Import</div>
<div class = "panel-body">
<form class = "form-horizontal" method = "POST" action = "{{ route('voyager.import.process') }}">
{{ csrf_field() }}
<input type = "hidden" name = "csv_data_file_id" value = "{{ $csv_data_file->id }}" />
<table class = "table">
@if (isset($csv_header_fields))
<tr>
@foreach ($csv_header_fields as $csv_header_field)
<th>{{ $csv_header_field }}</th>
@endforeach
</tr>
@endif
@foreach ($csv_data as $row)
<tr>
@foreach ($row as $key => $value)
<td>{{ $value }}</td>
@endforeach
</tr>
@endforeach
<tr>
@foreach ($csv_data[0] as $key => $value)
<td>
<select name = "fields[{{ $key }}]">
<option value = "null">Do Not Save</option>
@foreach (config('app.db_fields') as $db_field)
<option value = "{{ (\Request::has('header')) ? $db_field : $loop->index }}"
@if ($key === $db_field) selected @endif>{{ $db_field }}</option>
@endforeach
</select>
</td>
@endforeach
</tr>
</table>
<button type = "submit" class = "btn btn-primary">
Import Data
</button>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection
Это оно! Теперь у нас есть набор для импорта. Нам просто нужно настроить с помощью Voyager.
НАСТРОЙКИ VOYAGER
Во-первых, нам нужен пункт меню для доступа к нашему представлению импорта. После того, как вы попали в панель «Вояджер», вам нужно перейти в конструктор меню, чтобы создать пункт меню. Все, что вам нужно сделать, это сделать URL-адрес элемента как / admin / import, при этом, когда вы щелкнете этот элемент, вы перейдете к нашему представлению формы импорта. Что касается других параметров, вы можете изменить их по своему усмотрению.
Вам также может потребоваться изменить свою пользовательскую модель BREAD на App \ Models \ User, чтобы она могла получать все созданные нами поля.