Kod:Tümünü seç Kopyala
<?php
// index.php
ini_set('display_errors', 1);
error_reporting(E_ALL);
// --- AYARLAR: veritabanı bilgilerinizi buraya yazın ---
$dbHost = '127.0.0.1';
$dbName = 'wolvox';
$dbUser = 'dbuser';
$dbPass = 'dbpass';
$uploadDir = __DIR__ . '/uploads';
$chunkSize = 1000; // her yüklemede kaç satır okunup işlenecek (gerektiğinde 500-2000 arası dene)
// composer autoload
require __DIR__ . '/vendor/autoload.php';
use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
use PhpOffice\PhpSpreadsheet\Reader\IReadFilter;
// Basit chunk read filter
class ChunkReadFilter implements IReadFilter {
private $startRow = 0;
private $endRow = 0;
public function setRows($startRow, $chunkSize) {
$this->startRow = $startRow;
$this->endRow = $startRow + $chunkSize - 1;
}
public function readCell($column, $row, $worksheetName = '') {
if ($row >= $this->startRow && $row <= $this->endRow) {
return true;
}
return false;
}
}
// helper: normalize string for hashing
function norm($s) {
if ($s === null) return '';
$s = trim((string)$s);
$s = preg_replace('/\s+/', ' ', $s);
return mb_strtolower($s, 'UTF-8');
}
// try parse date in format d.m.Y H:i or d.m.Y
function parseDateToMySQL($val) {
if ($val === null || $val === '') return null;
// if PhpSpreadsheet already returned a DateTime object
if ($val instanceof \DateTime) {
return $val->format('Y-m-d H:i:s');
}
$v = trim((string)$val);
// common Excel numeric date: PhpSpreadsheet gives float -> treat earlier
if (is_numeric($v)) {
// convert Excel timestamp
try {
$d = \PhpOffice\PhpSpreadsheet\Shared\Date::excelToDateTimeObject($v);
return $d->format('Y-m-d H:i:s');
} catch (\Exception $e) {
// fallthrough
}
}
// try d.m.Y H:i
$dt = \DateTime::createFromFormat('d.m.Y H:i', $v);
if ($dt) return $dt->format('Y-m-d H:i:s');
// try d.m.Y
$dt = \DateTime::createFromFormat('d.m.Y', $v);
if ($dt) return $dt->format('Y-m-d H:i:s');
// try Y-m-d H:i:s
$dt = \DateTime::createFromFormat('Y-m-d H:i:s', $v);
if ($dt) return $dt->format('Y-m-d H:i:s');
// as last resort, return null or original string stored as NULL (we store null)
return null;
}
function respond($html) {
echo $html;
}
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['excel'])) {
if (!is_dir($uploadDir)) mkdir($uploadDir, 0755, true);
$file = $_FILES['excel'];
if ($file['error'] !== UPLOAD_ERR_OK) {
respond("<p>Dosya yüklenirken hata: " . $file['error'] . "</p>");
exit;
}
$filename = basename($file['name']);
$targetPath = $uploadDir . '/' . time() . '_' . preg_replace('/[^a-zA-Z0-9._-]/','_', $filename);
if (!move_uploaded_file($file['tmp_name'], $targetPath)) {
respond("<p>Dosya taşınamadı.</p>");
exit;
}
// DB bağlantısı (PDO)
$dsn = "mysql:host={$dbHost};dbname={$dbName};charset=utf8mb4";
$pdo = new PDO($dsn, $dbUser, $dbPass, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => false, // büyük veri için
]);
$reader = new Xlsx();
$reader->setReadDataOnly(true);
// determine highest row count requires reading, but we'll loop chunks until no rows returned
$filter = new ChunkReadFilter();
$reader->setReadFilter($filter);
$startRow = 2; // varsayılan: 1. satır başlık olduğu için 2'den başla
$totalInserted = 0;
$totalSkipped = 0;
$batchSize = 500; // insert batch boyutu (daha büyük de olabilir)
$insertBuffer = [];
// prepared insert statement template (we will build multi-row insert per batch)
// but we will use transaction per batch
while (true) {
$filter->setRows($startRow, $chunkSize);
$spreadsheet = $reader->load($targetPath);
$sheet = $spreadsheet->getActiveSheet();
$rows = $sheet->toArray(null, true, true, true); // get as associative with columns A..I
// free memory of spreadsheet after copying rows
$spreadsheet->disconnectWorksheets();
unset($spreadsheet);
gc_collect_cycles();
// remove possible header row in first chunk if present
// if rows empty or only header, break
if (count($rows) <= 1 && $startRow > 2) break;
if (empty($rows)) break;
// for each row in chunk
foreach ($rows as $r => $cols) {
// Note: $r is actual excel row number
// map columns A..I:
$telefon = isset($cols['A']) ? $cols['A'] : null;
$baslamaRaw = isset($cols['B']) ? $cols['B'] : null;
$hizmet_no = isset($cols['C']) ? $cols['C'] : null;
$operator = isset($cols['D']) ? $cols['D'] : null;
$ad_soyad = isset($cols['E']) ? $cols['E'] : null;
$tc_kimlik = isset($cols['F']) ? $cols['F'] : null;
$aciklama = isset($cols['G']) ? $cols['G'] : null;
$dogum = isset($cols['H']) ? $cols['H'] : null;
$tipi = isset($cols['I']) ? $cols['I'] : null;
// normalize for hash
$hashInput = implode('|', [
norm($telefon),
norm($baslamaRaw),
norm($hizmet_no),
norm($operator),
norm($ad_soyad),
norm($tc_kimlik),
norm($aciklama),
norm($dogum),
norm($tipi)
]);
$rowHash = md5($hashInput);
// parse baslama to DATETIME
$baslama = parseDateToMySQL($baslamaRaw);
// prepare normalized values
$insertBuffer[] = [
'telefon' => (string)$telefon,
'baslama' => $baslama,
'hizmet_no' => (string)$hizmet_no,
'operator' => (string)$operator,
'ad_soyad' => (string)$ad_soyad,
'tc_kimlik' => (string)$tc_kimlik,
'aciklama' => (string)$aciklama,
'dogum' => (string)$dogum,
'tipi' => (string)$tipi,
'hash' => $rowHash
];
// when buffer reaches batchSize, flush to DB
if (count($insertBuffer) >= $batchSize) {
try {
$pdo->beginTransaction();
// build multi insert
$placeholders = [];
$values = [];
foreach ($insertBuffer as $row) {
$placeholders[] = "(?,?,?,?,?,?,?,?,?,?)";
$values[] = $row['telefon'];
$values[] = $row['baslama'];
$values[] = $row['hizmet_no'];
$values[] = $row['operator'];
$values[] = $row['ad_soyad'];
$values[] = $row['tc_kimlik'];
$values[] = $row['aciklama'];
$values[] = $row['dogum'];
$values[] = $row['tipi'];
$values[] = $row['hash'];
}
$sql = "INSERT IGNORE INTO musteri_kayitlari
(telefon_numarasi, baslama, hizmet_no, operator, ad_soyad, tc_kimlik, aciklama, dogum_tarihi, tipi, row_hash)
VALUES " . implode(',', $placeholders);
$stmt = $pdo->prepare($sql);
$stmt->execute($values);
$affected = $stmt->rowCount(); // inserted rows in this batch (PDO->rowCount with INSERT may vary)
$pdo->commit();
$totalInserted += $affected;
$insertBuffer = [];
} catch (Exception $e) {
if ($pdo->inTransaction()) $pdo->rollBack();
respond("<p>DB hata: " . htmlspecialchars($e->getMessage()) . "</p>");
exit;
}
}
}
// move to next chunk
$startRow += $chunkSize;
// if fewer rows than chunkSize, we've reached EOF
if (count($rows) < $chunkSize) break;
}
// flush remaining buffer
if (count($insertBuffer) > 0) {
try {
$pdo->beginTransaction();
$placeholders = [];
$values = [];
foreach ($insertBuffer as $row) {
$placeholders[] = "(?,?,?,?,?,?,?,?,?,?)";
$values[] = $row['telefon'];
$values[] = $row['baslama'];
$values[] = $row['hizmet_no'];
$values[] = $row['operator'];
$values[] = $row['ad_soyad'];
$values[] = $row['tc_kimlik'];
$values[] = $row['aciklama'];
$values[] = $row['dogum'];
$values[] = $row['tipi'];
$values[] = $row['hash'];
}
$sql = "INSERT IGNORE INTO musteri_kayitlari
(telefon_numarasi, baslama, hizmet_no, operator, ad_soyad, tc_kimlik, aciklama, dogum_tarihi, tipi, row_hash)
VALUES " . implode(',', $placeholders);
$stmt = $pdo->prepare($sql);
$stmt->execute($values);
$affected = $stmt->rowCount();
$pdo->commit();
$totalInserted += $affected;
$insertBuffer = [];
} catch (Exception $e) {
if ($pdo->inTransaction()) $pdo->rollBack();
respond("<p>DB hata (flush): " . htmlspecialchars($e->getMessage()) . "</p>");
exit;
}
}
respond("<h2>İçe aktarma tamamlandı</h2>
<p>Toplam eklenen satır (yaklaşık): " . intval($totalInserted) . "</p>
<p>Yüklenen dosya: " . htmlspecialchars($filename) . "</p>
<p>Not: 'Aynı tüm alanları birebir eşleşen' satırlar tekrar eklenmedi (unique row_hash ile).</p>");
exit;
}
// Form göster
?>
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Excel Yükle & İçeri Aktar</title>
</head>
<body>
<h1>Excel (.xlsx) Yükle</h1>
<p>Excel sütun eşleşmesi (zorunlu):<br>
A: telefon_numarasi, B: baslama (örn. 15.09.2027 08:00), C: hizmet_no, D: operator, E: ad_soyad, F: tc_kimlik, G: aciklama, H: dogum_tarihi, I: tipi
</p>
<form method="post" enctype="multipart/form-data">
<input type="file" name="excel" accept=".xlsx,.xls,.csv" required>
<br><br>
<button type="submit">Yükle ve Aktar</button>
</form>
</body>
</html>