๋ฒ์
PHP ๋ฒ์ : 7.2
๋ผ๋ผ๋ฒจ ๋ฒ์ : 5.7
ํจํค์ง ๋ฒ์ : 3.1
์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค: /Users/administrator/Sites/blog/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/RowIterator.php์์ '์์ ํ(2)์ด ๊ฐ์ฅ ๋์ ํ(1)์ ๋ฒ์ด๋ฌ์ต๋๋ค'
์คํ๋ ๋์ํธ๋ ์ฒซ ๋ฒ์งธ ํ์ ๋จธ๋ฆฌ๊ธ์ด ์๊ณ ๋จ์ผ ์ํธ์ ๋๋ค. ๋ ๋ฒ์งธ ํ์ ๋น์ด ์์ง๋ง ๊ด์ฐฎ์ง ์์ต๋๊น? ์ด ์๋๋ฆฌ์ค๋ฅผ ์ค๋ช ํ๋ ๋ฐฉ๋ฒ์ ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค. ๋์์ ์ฃผ์๋ฉด ๊ฐ์ฌํ๊ฒ ์ต๋๋ค. ๊ฐ์ฌํฉ๋๋ค.
App\Imports\PoliciesImport.php
<?php
namespace App\Imports;
use App\Policy;
use Maatwebsite\Excel\Concerns\ToModel;
use Maatwebsite\Excel\Concerns\WithValidation;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Concerns\Importable;
use Maatwebsite\Excel\Concerns\WithMultipleSheets;
use Auth;
class PoliciesImport implements ToModel, WithValidation, WithHeadingRow, WithMultipleSheets
{
use Importable;
/**
* <strong i="14">@param</strong> array $row
*
* <strong i="15">@return</strong> \Illuminate\Database\Eloquent\Model|null
*/
public function model(array $row)
{
return new Policy([
'user_id' => Auth::user()->id,
'policy_name' => $row['name'],
'phone' => $row['phone'],
'street' => $row['address'],
'city' => $row['city'],
'state' => $row['state'],
'postal_code' => $row['postal_code'],
]);
}
public function sheets(): array
{
return [
// Select by sheet index
0 => new PoliciesImport(),
];
}
public function rules(): array
{
return [
'policy_name' => 'required|string',
'*.policy_name' => 'required|string',
];
}
}
์ ์ฑ ์ปจํธ๋กค๋ฌ.php
public function import(Request $request)
{
if ($request->hasFile('file')) {
// validate incoming request
$this->validate($request, [
'file' => 'required|file|mimes:xls,xlsx,csv|max:10240', //max 10Mb
]);
if ($request->file('file')->isValid()) {
$file = $request->file('file');
$path = $file->store('uploads/policy');
$fileHeaders = current((new HeadingRowImport)->toArray($path)[0]);
$validHeaders = [
'name','phone','address','state','city','postal_code'
];
sort($fileHeaders);
sort($validHeaders);
// Check the File Headers
if ($fileHeaders == $validHeaders) {
// Import the saved excel file
(new PoliciesImport)->import($path);
}
Storage::delete($path);
}
}
return back();
}
์ ์ฒด ์คํ ์ถ์ ์ ๊ฒ์ํ ์ ์์ต๋๊น? ์ด๋ค ์์ ํ์ด ๊ทธ๊ฒ์ ์ผ์ผํค๋์ง ์ง๊ธ์ ๋ณด๊ธฐ ์ด๋ ต์ต๋๋ค.
/Users/administrator/Sites/blog/vendor/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Worksheet/RowIterator.php
*
* <strong i="8">@param</strong> int $startRow The row number at which to start iterating
*
* <strong i="9">@throws</strong> PhpSpreadsheetException
*
* <strong i="10">@return</strong> RowIterator
*/
public function resetStart($startRow = 1)
{
if ($startRow > $this->subject->getHighestRow()) {
throw new PhpSpreadsheetException("Start row ({$startRow}) is beyond highest row ({$this->subject->getHighestRow()})");
}
$this->startRow = $startRow;
if ($this->endRow < $this->startRow) {
$this->endRow = $this->startRow;
}
$this->seek($startRow);
return $this;
}
/**
* (Re)Set the end row.
*
๋ฏธ์ํฉ๋๋ค. ๋์์ด ๋๋์?
๊ฐ์ฌ ํด์!
์ฌ๊ธฐ์ ๊ฐ์ ๋ฌธ์ ๊ฐ ์์ต๋๋ค!
์คํ ์ถ์ ์ ๋ฐ๋ฅด๋ฉด ํ์ผ์๋ 1๊ฐ์ ํ(์ ๋ชฉ ํ)๋ง ์์ต๋๋ค. ๊ฐ ํ์ ๊ฐ์ ธ์ค๋ ค๊ณ ํ ๋ PhpSpreadsheet๋ ๋ ๋ฒ์งธ ํ์ด ์๊ณ ๋ ๋ฒ์งธ ํ๋ณด๋ค ๋ ๋ฉ๋ฆฌ ํ์ด ์๋ค๊ณ ๋ถํํฉ๋๋ค.
@patrickbrouwers ์ ๊ฒฝ์ฐ์๋ 1ํ์ ๋์ด์๋ ํ๊ณผ ๊ฐ์ด ๋ถ๋ช
ํ ์์ต๋๋ค. ๋ฌธ์ ๋ฅผ ํต๊ณผํ๋ ค๋ฉด WithChunkReading
๋ฐ WithCustomChunkSize
๋ฌธ์ ๋ฅผ ๋ชจ๋ ๊ตฌํํ๋์ง ํ์ธํด์ผ ํฉ๋๋ค. ์ฆ, ์ Excel ํ์ผ๋ ๋ง๋ค๊ณ ์ด์ ํ์ผ ๊ฐ์ ๋ณต์ฌํ์ต๋๋ค.
๊ฐ์ ์ ํ์ผ์ ๋ณต์ฌํ ํ ์๋ํ๋ค๋ฉด ํ์ผ์ ๋ฌธ์ ๊ฐ ์๋ ๊ฒ ๊ฐ์ต๋๋ค.
CSV์ธ ๊ฒฝ์ฐ ์ฌ๋ฐ๋ฅธ ๊ตฌ๋ถ ๊ธฐํธ๋ฅผ ์ฌ์ฉํ์ง ์์ต๋๊น?
์. ๊ฝค ๊ฐ๋ฅํฉ๋๋ค. ๋ช ๊ฐ์ง ๋ค๋ฅธ ํ์ผ์ ๊ณง ์ฒ๋ฆฌํ ๊ฒ์ด๋ฏ๋ก ๋ค์ ํ์๋๋ฉด ์ฌ๊ธฐ๋ก ๋์์ค๊ฒ ์ต๋๋ค. ๋ชจ๋ XLSX ํ์ผ์ ๋๋ค.
์๊ฒ ์ต๋๋ค. ์๋ ค์ฃผ์ธ์!
@patrickbrowers ๋ค, ์ฌ์ค์ ๋๋ค. ์ด ๊ฒฝ์ฐ ์๋ฒ ์ค๋ฅ๋ฅผ ๋ฐฉ์งํ๋ ค๊ณ ํ๋๋ฐ ์ด๋ป๊ฒ ์ก์์ ๊ฐ์ ธ์ค๊ธฐ ๋ชจ๋ธ ๋ฉ์๋๊ฐ ์คํ๋์ง ์๋๋ก ํ๋ ๋ฐฉ๋ฒ์ ๊ณ ๋ฏผํ๊ณ ์์ต๋๋ค.
App\Imports\PoliciesImport.php์์ RegistersEventListeners๋ฅผ ์ฌ์ฉํ์ฌ ์ฌ๋ฐ๋ฅธ ๋ฐฉํฅ์ผ๋ก ๊ฐ๊ณ ์์ต๋๊น? ๊ฐ์ฅ ๋์ ํ์ ์ป๋ ๋ฐฉ๋ฒ์ ์์ ๋์ง๋ง์ด ๊ฐ์ ์ ๋ฌํ๋ ๋ฐฉ๋ฒ์ด๋ ์ฌ๊ธฐ์์ ์ด๋๋ก ๊ฐ์ผํ๋์ง ์ ์ ์์ต๋๋ค.
public static function beforeImport(BeforeImport $event)
{
$worksheet = $event->reader->getActiveSheet();
$highestRow = $worksheet->getHighestRow(); // e.g. 10
dd($highestRow);
}
@abbylovesdon ๊ฐ์ฅ ์ข์ ๋ฐฉ๋ฒ์ beforeImport์์ ์์ธ๋ฅผ ๋์ง๊ณ ์ปจํธ๋กค๋ฌ์์ try-catchํ๋ ๊ฒ์ ๋๋ค. ์์ธ๋ฅผ ํตํด ๊ฐ์ฅ ๋์ ํ์ ์ ๋ฌํ ์ ์์ต๋๋ค.
@patrickbrowers ๋์ ์ฃผ์ ์ ์ ๋ง ๊ฐ์ฌํฉ๋๋ค! ์ ๋ PHP/Laravel/This Package๋ฅผ ์ฒ์ ์ฌ์ฉํ๋ฏ๋ก ๋ค๋ฅธ ์ฌ๋์ด ๋ด ์ ์ฅ์ด๋ผ๋ฉด ์ฌ๊ธฐ์์ ๋ด๊ฐ ํ ์ผ์ด ์์ต๋๋ค.
๋ด ๊ฐ์ ธ์ค๊ธฐ ํด๋์ค: App\Imports\PoliciesImport.php
<?php
namespace App\Imports;
use App\Policy;
use Auth;
use Maatwebsite\Excel\Concerns\ToModel;
use Maatwebsite\Excel\Validators\Failure;
use Maatwebsite\Excel\Validators\ValidationException;
use Maatwebsite\Excel\Concerns\WithValidation;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Concerns\Importable;
use Maatwebsite\Excel\Concerns\WithEvents;
use Maatwebsite\Excel\Concerns\RegistersEventListeners;
use Maatwebsite\Excel\Events\BeforeImport;
use Maatwebsite\Excel\Concerns\WithMultipleSheets;
class PoliciesImport implements ToModel, WithValidation, WithHeadingRow, WithMultipleSheets, WithEvents
{
use Importable, RegistersEventListeners;
public static function beforeImport(BeforeImport $event)
{
$worksheet = $event->reader->getActiveSheet();
$highestRow = $worksheet->getHighestRow(); // e.g. 10
if ($highestRow < 2) {
$error = \Illuminate\Validation\ValidationException::withMessages([]);
$failure = new Failure(1, 'rows', [0 => 'Now enough rows!']);
$failures = [0 => $failure];
throw new ValidationException($error, $failures);
}
}
/**
* <strong i="8">@param</strong> array $row
*
* <strong i="9">@return</strong> \Illuminate\Database\Eloquent\Model|null
*/
public function model(array $row)
{
return new Policy([
'user_id' => Auth::user()->id,
'policy_name' => $row['name'],
'phone' => $row['phone'],
'street' => $row['address'],
'city' => $row['city'],
'state' => $row['state'],
'postal_code' => $row['postal_code'],
]);
}
public function sheets(): array
{
return [
// Select by sheet index
0 => new PoliciesImport(),
];
}
public function rules(): array
{
return [
'name' => 'required|string',
'*.name' => 'required|string',
];
}
}
์ด์ ๋ด ์ปจํธ๋กค๋ฌ์์ ๋ค์์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
try {
(new PoliciesImport)->import($path);
} catch (\Exception $e) {
$failures = $e->failures();
dd($failures[0]);
}
์ฌ๊ธฐ์ ๊ฐ์ ๋ฌธ์ ๊ฐ ์์ต๋๋ค! :((
์ฌ๊ธฐ์ ๊ฐ์ ๋ฌธ์ ๊ฐ ์์ต๋๋ค! :((
์์ ์ ์ ๋ฐ ์๋ฅผ ์ฌ์ฉํ์ฌ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์๋ ๊ฒฝ์ฐ ๋ฌธ์ ํ ํ๋ฆฟ์ ์ฌ์ฉํ์ฌ ์ ๋ฌธ์ ๋ฅผ ์ด์ด ๋ฌ๋ผ๊ณ ์์ฒญํฉ๋๋ค. ๊ฐ์ฌ ํด์!
๋๋ ๊ฐ์ ์ค๋ฅ๊ฐ ์์ต๋๋ค!
ํ์ง๋ง ์ํธ 2, 3์ ์ ๊ฑฐํ ํ ํด๊ฒฐ!!
์ด ์ํฉ์์๋ ๋ค์๊ณผ ๊ฐ์ด ์ํธ ์ธ๋ฑ์ค๋ฅผ ์ ์ํด์ผ ํฉ๋๋ค.
public function sheets(): array
{
return [
// Select by sheet index
0 => new pricelist_items(),
];
}
๊ฐ์ ๊ฒฝ์ฐ๊ฐ ๋ฐ์ํ๋๋ฐ ์์ ํ์ผ์ ์ฌ๋ฌ ์ฅ์ ์ํธ๊ฐ ์กด์ฌํ๊ธฐ ๋๋ฌธ์ ๋ฐ์ํ๋ค๋ ๊ฒ์ ๊นจ๋ฌ์์ต๋๋ค.
๋ฐฉ๊ธ ๊ฐ์ ๋ฌธ์ ๊ฐ์์์ต๋๋ค. ์ฝ๊ฐ์ ์ข์ ํ์ ๋ด ๊ทผ๋ณธ์ ์ธ ์์ฌ์ด ์ฌ์ค๋ก ํ๋ช
๋์์ต๋๋ค. ์คํ๋ ๋์ํธ์ ๋ถํ ๋ก ์ธํด ๋ฐ์ํ์ต๋๋ค. ์ฒซ ๋ฒ์งธ ํ์ '๋ถํ ํด์ 'ํ ํ ์๋ํ์ต๋๋ค.
์คํ ์ถ์ ์ ๋ฐ๋ฅด๋ฉด ํ์ผ์๋ 1๊ฐ์ ํ(์ ๋ชฉ ํ)๋ง ์์ต๋๋ค. ๊ฐ ํ์ ๊ฐ์ ธ์ค๋ ค๊ณ ํ ๋ PhpSpreadsheet๋ ๋ ๋ฒ์งธ ํ์ด ์๊ณ ๋ ๋ฒ์งธ ํ๋ณด๋ค ๋ ๋ฉ๋ฆฌ ํ์ด ์๋ค๊ณ ๋ถํํฉ๋๋ค.
Excel์ ๋จธ๋ฆฌ๊ธ ํ๋ง ์๋ ๊ฒฝ์ฐ ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ. ํด๋ผ์ด์ธํธ์ ์ ์ ํ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ํ์ํ๊ณ ์ถ์ต๋๋ค.
์๋ ํ์ธ์, ์ด ์ค๋ ๋๊ฐ ์ด๋ฏธ ๋ซํ ์๋ค๋ ๊ฒ์ ์๊ณ ์์ง๋ง ์ฌ๊ธฐ์์๋ ๋์ผํ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๊ณ ์ด ์ค๋ ๋์ ์๋ฌด ๊ฒ๋ ๋ด ๋ฌธ์ ์ ๋์์ด ๋์ง ์์ต๋๋ค.
๋์์ 10k ํ์ ์
๋ก๋ํ๊ณ ์๋๋ฐ Start row (2) is beyond highest row (1)
์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค. ํ์ง๋ง 5k๋ก ๋๋๋ฉด ๋ง๋ฒ์ฒ๋ผ ์๋ํฉ๋๋ค.
์ฌ๊ธฐ์ ๋ฌด์์ด ๋ฌธ์ ์ธ ๊ฒ ๊ฐ์ต๋๊น?
๋ฏธ๋ฆฌ ๊ฐ์ฌ๋๋ฆฝ๋๋ค!
์๋ ํ์ธ์, ์ด ์ค๋ ๋๊ฐ ์ด๋ฏธ ๋ซํ ์๋ค๋ ๊ฒ์ ์๊ณ ์์ง๋ง ์ฌ๊ธฐ์์๋ ๋์ผํ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๊ณ ์ด ์ค๋ ๋์ ์๋ฌด ๊ฒ๋ ๋ด ๋ฌธ์ ์ ๋์์ด ๋์ง ์์ต๋๋ค.
๋์์ 10k ํ์ ์ ๋ก๋ํ๊ณ ์๋๋ฐ
Start row (2) is beyond highest row (1)
์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค. ํ์ง๋ง 5k๋ก ๋๋๋ฉด ๋ง๋ฒ์ฒ๋ผ ์๋ํฉ๋๋ค.์ฌ๊ธฐ์ ๋ฌด์์ด ๋ฌธ์ ์ธ ๊ฒ ๊ฐ์ต๋๊น?
๋ฏธ๋ฆฌ ๊ฐ์ฌ๋๋ฆฝ๋๋ค!
๋ถํ ํ์ฌ ํด๊ฒฐํ๋ ์๋ณธ ํ์ผ์ ์ค๋ฅ์ผ ์ ์์ต๋๋ค. ์ฑ๋ฅ ๋ฌธ์ ์ผ ์๋ ์์ง๋ง ์ฝ๋์ ์๋ฒ ์ฌ์์ ๋ณด์ง ์๊ณ ๋ ๋งํ๊ธฐ ์ด๋ ต์ต๋๋ค. ํ์ผ ์ค๋ฅ์ธ ๊ฒ ๊ฐ์์.
๋ฐฉ๊ธ ๋์๊ฒ ์ด๋ฐ ์ผ์ด ์ผ์ด๋ฌ์ต๋๋ค. ํ์ผ์ด PHP์ 'upload_max_filesize' ์ง์๋ฌธ๋ณด๋ค ํด ๋ ๋ฐ์ํฉ๋๋ค. AWS AMI์์ ์ต๋ 'upload_max_filesize'๊ฐ 2MB์ธ ๋ฐ๋ฉด 40,000๊ฐ์ ํ์ด ์๋ 5MB์ ํ์ผ ํฌ๊ธฐ์ 500๊ฐ์ ์ฒญํฌ๋ฅผ ์ฌ์ฉํ์ต๋๋ค. ์์ฑ์์๊ฒ ์ต๋ ์
๋ก๋ ํฌ๊ธฐ ํ์ธ์ ๊ตฌํํ๊ณ ํผ๋์ค๋ฌ์ด Start row (2) is beyond highest row (1)
๋์ ์ด ์ค๋ฅ๋ฅผ ์ธ์ํ๋๋ก ์ ์ํ ์ ์์ต๋๋ค. 'upload_max_filesize' ์ ํ์ ๋๋ฆฌ๋ฉด ์ค๋ฅ๊ฐ ์ฌ๋ผ์ง๊ณ ํ์ผ ์
๋ก๋๊ฐ ์ฑ๊ณตํ์ต๋๋ค.
phpspreadsheet๊ฐ ๊ทธ ์ค๋ฅ๋ฅผ ๋์ง ์ ์๋ ๋ ๋ง์ ์ด์ ๊ฐ ์์ ๊ฒ์ ๋๋ค. ๋น์ ์ ํญ์ ๊ฑฐ๊ธฐ์์ PR์ ์๋ํ ์ ์์ต๋๋ค.
@GlennM ๋ต๋ณ ๊ฐ์ฌํฉ๋๋ค!
๋๋ ๊ทธ๊ฒ์ ๋ํ ํด๊ฒฐ ๋ฐฉ๋ฒ์ ๋ง๋ค์๊ณ ์ง๊ธ์ ๋ด ํ๋ก์ ํธ์ ์๊ตฌ ์ฌํญ์ ์๋ง์ต๋๋ค. ์์ผ๋ก์ด ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ฉด ๊ทํ์ ์ ์์ ๊ณ ๋ คํ ๊ฒ์
๋๋ค.
@patrickbrouwers ์ ๊ฒฝ์ฐ์๋ 1ํ์ ๋์ด์๋ ํ๊ณผ ๊ฐ์ด ๋ถ๋ช ํ ์์ต๋๋ค. ๋ฌธ์ ๋ฅผ ํต๊ณผํ๋ ค๋ฉด
WithChunkReading
๋ฐWithCustomChunkSize
๋ฌธ์ ๋ฅผ ๋ชจ๋ ๊ตฌํํ๋์ง ํ์ธํด์ผ ํฉ๋๋ค. ์ฆ, ์ Excel ํ์ผ๋ ๋ง๋ค๊ณ ์ด์ ํ์ผ ๊ฐ์ ๋ณต์ฌํ์ต๋๋ค.
๊ทธ๊ฒ์ ๋๋ฅผ ์ํด ๋์์ด๋ฉ๋๋ค. ์ฌ์ ํ ๊ฐ์ ๋ฌธ์ ๊ฐ ์์ต๋๋ค
์ญ์ ์ํฌ์ํธ๊ฐ ๋น์ด ์์ต๋๋ค.
์ญ์ ์ํฌ์ํธ๊ฐ ๋น์ด ์์ต๋๋ค.
์ด๊ฒ์ ํ์ผ์ ๋น ์ํฌ์ํธ๊ฐ ์๊ณ "WithHeadingRow"๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ์ด ๋ฌธ์ ๊ฐ ๋ํ๋ฉ๋๋ค.
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
๋๋ ๊ฐ์ ์ค๋ฅ๊ฐ ์์ต๋๋ค!
ํ์ง๋ง ์ํธ 2, 3์ ์ ๊ฑฐํ ํ ํด๊ฒฐ!!
์ด ์ํฉ์์๋ ๋ค์๊ณผ ๊ฐ์ด ์ํธ ์ธ๋ฑ์ค๋ฅผ ์ ์ํด์ผ ํฉ๋๋ค.