Kotchasan Framework Documentation

Kotchasan Framework Documentation

Csv Class - การจัดการไฟล์ CSV

TH 05 Feb 2026 07:46

Csv Class - การจัดการไฟล์ CSV

คลาส Csv เป็นเครื่องมือสำหรับการนำเข้าและส่งออกข้อมูล CSV ในกรอบงาน Kotchasan

namespace

Kotchasan\Csv;

คุณสมบัติ

คลาส Csv รองรับการอ่านและเขียนไฟล์ CSV พร้อมกับการจัดการ character encoding และการตรวจสอบข้อมูล

คุณสมบัติสำคัญ

private $charset;   // การเข้ารหัสตัวอักษร
private $columns;   // ข้อมูลคอลัมน์
private $datas;     // ข้อมูลที่นำเข้า
private $keys;      // คอลัมน์สำหรับตรวจสอบข้อมูลซ้ำ;

เมธอดหลัก

import()

นำเข้าข้อมูล CSV

class ExampleClass {
    <?php
public static function import($csv, $columns, $keys = null, $charset = 'UTF-8'): array;
}

Parameters:

  • $csv - ที่อยู่ไฟล์ CSV
  • $columns - อาร์เรย์ข้อมูลคอลัมน์ array('column1' => 'data type', 'column2' => 'data type')
  • $keys - ชื่อคอลัมน์สำหรับตรวจสอบข้อมูลซ้ำ (null = ไม่ตรวจสอบ)
  • $charset - การเข้ารหัสไฟล์ (ค่าเริ่มต้น UTF-8)

Returns: อาร์เรย์ข้อมูลที่นำเข้า

ตัวอย่างการใช้งาน:

use Kotchasan\Csv;

// นำเข้าข้อมูลสมาชิก
$columns = [
    'name' => 'string',
    'email' => 'string',
    'age' => 'int',
    'salary' => 'double',
    'phone' => 'number',
    'join_date' => 'date'
];

$data = Csv::import('/path/to/members.csv', $columns);

foreach ($data as $row) {
    echo "ชื่อ: {$row['name']}, อีเมล: {$row['email']}, อายุ: {$row['age']}\n";
}

// นำเข้าข้อมูลพร้อมตรวจสอบซ้ำตาม email
$keys = ['email']; // ตรวจสอบซ้ำตาม email
$data = Csv::import('/path/to/members.csv', $columns, $keys);

// นำเข้าข้อมูลจากไฟล์ที่เป็น TIS-620
$data = Csv::import('/path/to/thai_data.csv', $columns, null, 'TIS-620');

// นำเข้าข้อมูลผลิตภัณฑ์
$productColumns = [
    'product_code' => 'en',        // ตัวอักษรอังกฤษและตัวเลขเท่านั้น
    'product_name' => 'string',
    'price' => 'float',
    'stock' => 'int',
    'created_date' => 'datetime'
];

$products = Csv::import('/path/to/products.csv', $productColumns, ['product_code']);

// นำเข้าข้อมูลการขายรายวัน
$salesColumns = [
    'sale_date' => 'date',
    'amount' => 'double',
    'customer_id' => 'int',
    'sale_time' => 'time'
];

$sales = Csv::import('/path/to/daily_sales.csv', $salesColumns);

// ใช้ฟังก์ชันแบบกำหนดเองสำหรับการประมวลผลข้อมูล
$customColumns = [
    'email' => function($value) {
        return filter_var(trim($value), FILTER_VALIDATE_EMAIL) ?: null;
    },
    'phone' => function($value) {
        return preg_replace('/[^0-9]/', '', $value);
    },
    'name' => function($value) {
        return ucwords(trim($value));
    }
];

$cleanData = Csv::import('/path/to/contacts.csv', $customColumns);

read()

อ่านไฟล์ CSV และประมวลผลแต่ละแถวข้อมูล

public static function read(
    $file,
    $onRow,
    $headers = null,
    $charset = 'UTF-8',
    $onBeforeRead = null,
    $args = null
): void;

Parameters:

  • $file - ที่อยู่ไฟล์ CSV
  • $onRow - ฟังก์ชัน callback ที่จะทำงานกับแต่ละแถว function($row, $args)
  • $headers - อาร์เรย์หัวข้อที่คาดหวัง (ไม่บังคับ)
  • $charset - การเข้ารหัสไฟล์ (ค่าเริ่มต้น UTF-8)
  • $onBeforeRead - ฟังก์ชัน callback ก่อนอ่านข้อมูล function($columns, $args) (ไม่บังคับ)
  • $args - ข้อมูลเพิ่มเติมที่จะส่งไปยัง callbacks (ไม่บังคับ)

Throws: Exception หากเกิดข้อผิดพลาด

ตัวอย่างการใช้งาน:

use Kotchasan\Database;

<?php
use Kotchasan\Csv;

// อ่านไฟล์ CSV และแสดงผลแต่ละแถว
Csv::read('/path/to/data.csv', function($row) {
    echo "ประมวลผลแถว: " . print_r($row, true);
});

// อ่านไฟล์พร้อมตรวจสอบหัวข้อ
$expectedHeaders = ['name', 'email', 'phone'];
Csv::read('/path/to/contacts.csv', function($row) {
    // บันทึกข้อมูลลงฐานข้อมูล
    $db = \Kotchasan\Database::create();
    $db->table('contacts')->insert($row);
}, $expectedHeaders);

// ระบบนำเข้าข้อมูลขนาดใหญ่แบบ batch
$batchSize = 1000;
$batch = [];
$count = 0;

Csv::read('/path/to/large_file.csv', function($row) use (&$batch, &$count, $batchSize) {
    $batch[] = $row;
    $count++;

    if (count($batch) >= $batchSize) {
        // บันทึก batch
        $db = \Kotchasan\Database::create();
        $db->table('large_table')->insert($batch);

        echo "ประมวลผล {$count} แถว\n";
        $batch = []; // รีเซ็ต batch
    }
});

// บันทึก batch สุดท้าย
if (!empty($batch)) {
    $db = \Kotchasan\Database::create();
    $db->table('large_table')->insert($batch);
    echo "ประมวลผลเสร็จสิ้น รวม {$count} แถว\n";
}

// ระบบตรวจสอบและทำความสะอาดข้อมูล
Csv::read('/path/to/user_data.csv', function($row) {
    $errors = [];

    // ตรวจสอบอีเมล
    if (!filter_var($row['email'], FILTER_VALIDATE_EMAIL)) {
        $errors[] = "อีเมลไม่ถูกต้อง: {$row['email']}";
    }

    // ตรวจสอบเบอร์โทร
    if (!preg_match('/^[0-9]{10}$/', $row['phone'])) {
        $errors[] = "เบอร์โทรไม่ถูกต้อง: {$row['phone']}";
    }

    if (empty($errors)) {
        // ข้อมูลถูกต้อง บันทึกลงฐานข้อมูล
        echo "บันทึกข้อมูล: {$row['name']}\n";
    } else {
        // ข้อมูลไม่ถูกต้อง บันทึก log
        error_log("ข้อมูลไม่ถูกต้อง: " . implode(', ', $errors));
    }
});

send()

สร้างและส่งไฟล์ CSV เป็นการดาวน์โหลด

public static function send(
    $file,
    $header,
    $datas,
    $charset = 'UTF-8',
    $bom = true
): void;

Parameters:

  • $file - ชื่อไฟล์ (ไม่รวมนามสกุล)
  • $header - อาร์เรย์หัวข้อของไฟล์ CSV
  • $datas - อาร์เรย์ข้อมูลแถวของไฟล์ CSV
  • $charset - การเข้ารหัสไฟล์ (ค่าเริ่มต้น UTF-8)
  • $bom - ใส่ Byte Order Mark หรือไม่ (ค่าเริ่มต้น true)

Returns: void (ส่งไฟล์และ exit)

ตัวอย่างการใช้งาน:

use Kotchasan\Database;

<?php
use Kotchasan\Csv;

// ส่งออกข้อมูลสมาชิก
$headers = ['ชื่อ', 'นามสกุล', 'อีเมล', 'เบอร์โทร'];
$memberData = [
    ['สมชาย', 'ใจดี', 'somchai@example.com', '0812345678'],
    ['สมหญิง', 'รักดี', 'somying@example.com', '0823456789'],
    ['สมศักดิ์', 'มั่นคง', 'somsak@example.com', '0834567890']
];

Csv::send('members', $headers, $memberData);

// ส่งออกข้อมูลจากฐานข้อมูล
$db = \Kotchasan\Database::create();
$users = $db->table('users')
    ->select('name', 'email', 'created_at')
    ->toArray();

$headers = ['ชื่อ', 'อีเมล', 'วันที่สมัคร'];
$userData = [];

foreach ($users as $user) {
    $userData[] = [
        $user['name'],
        $user['email'],
        date('Y-m-d', strtotime($user['created_at']))
    ];
}

Csv::send('user_report', $headers, $userData);

// ส่งออกข้อมูลเป็น TIS-620 สำหรับโปรแกรมไทย
Csv::send('thai_report', $headers, $userData, 'TIS-620');

// ส่งออกข้อมูลขายรายเดือน
function exportMonthlySales($year, $month) {
    $db = \Kotchasan\Database::create();
    $sales = $db->table('sales s')
        ->join('products p', 'p.id = s.product_id')
        ->select('p.name', 's.quantity', 's.price', 's.total', 's.sale_date')
        ->where('YEAR(s.sale_date)', $year)
        ->where('MONTH(s.sale_date)', $month)
        ->toArray();

    $headers = ['ชื่อสินค้า', 'จำนวน', 'ราคาต่อหน่วย', 'ยอดรวม', 'วันที่ขาย'];
    $salesData = [];

    foreach ($sales as $sale) {
        $salesData[] = [
            $sale['name'],
            $sale['quantity'],
            number_format($sale['price'], 2),
            number_format($sale['total'], 2),
            $sale['sale_date']
        ];
    }

    $filename = "sales_{$year}_{$month}";
    return Csv::send($filename, $headers, $salesData);
}

// ส่งออกรายงานผู้ใช้งานระบบ
function exportUserActivity() {
    $db = \Kotchasan\Database::create();
    $activities = $db->table('user_logs ul')
        ->join('users u', 'u.id = ul.user_id')
        ->select('u.name', 'u.email', 'ul.action', 'ul.ip_address', 'ul.created_at')
        ->order('ul.created_at DESC')
        ->limit(10000)
        ->toArray();

    $headers = ['ชื่อผู้ใช้', 'อีเมล', 'การกระทำ', 'IP Address', 'เวลา'];
    $activityData = [];

    foreach ($activities as $activity) {
        $activityData[] = [
            $activity['name'],
            $activity['email'],
            $activity['action'],
            $activity['ip_address'],
            $activity['created_at']
        ];
    }

    return Csv::send('user_activity_log', $headers, $activityData);
}

ตัวอย่างการใช้งานขั้นสูง

use Kotchasan\Csv;
use Kotchasan\Database;

// ระบบจัดการ CSV แบบครบชุด
class CsvManager
{
    // นำเข้าข้อมูลผู้ใช้จาก CSV
    public static function importUsers($csvFile) {
        $columns = [
            'username' => 'en',
            'email' => function($value) {
                $email = trim($value);
                return filter_var($email, FILTER_VALIDATE_EMAIL) ? $email : null;
            },
            'name' => 'string',
            'phone' => 'number',
            'birthdate' => 'date',
            'salary' => 'double'
        ];

        $keys = ['username', 'email']; // ไม่ให้ username หรือ email ซ้ำ

        try {
            $users = Csv::import($csvFile, $columns, $keys);

            $db = Kotchasan\Database::create();
            $imported = 0;
            $errors = [];

            foreach ($users as $user) {
                // ตรวจสอบข้อมูลที่จำเป็น
                if (empty($user['username']) || empty($user['email'])) {
                    $errors[] = "ข้อมูลไม่ครบ: " . json_encode($user);
                    continue;
                }

                // ตรวจสอบว่ามีในระบบแล้วหรือไม่
                $exists = $db->table('users')
                    ->where('username', $user['username'])
                    ->orWhere('email', $user['email'])
                    ->first();

                if ($exists) {
                    $errors[] = "ผู้ใช้ซ้ำ: {$user['username']} / {$user['email']}";
                    continue;
                }

                // เพิ่มข้อมูลเพิ่มเติม
                $user['password'] = password_hash('123456', PASSWORD_DEFAULT);
                $user['status'] = 1;
                $user['created_at'] = date('Y-m-d H:i:s');

                // บันทึกลงฐานข้อมูล
                $db->table('users')->insert($user);
                $imported++;
            }

            return [
                'success' => true,
                'imported' => $imported,
                'total' => count($users),
                'errors' => $errors
            ];

        } catch (Exception $e) {
            return [
                'success' => false,
                'message' => $e->getMessage()
            ];
        }
    }

    // ส่งออกรายงานการขาย
    public static function exportSalesReport($startDate, $endDate) {
        $db = Kotchasan\Database::create();

        $sales = $db->table('sales s')
            ->join('products p', 'p.id = s.product_id')
            ->join('users u', 'u.id = s.user_id')
            ->select(
                's.id',
                'p.name as product_name',
                'p.code as product_code',
                'u.name as customer_name',
                's.quantity',
                's.unit_price',
                's.total_price',
                's.sale_date',
                's.status'
            )
            ->whereBetween('s.sale_date', [$startDate, $endDate])
            ->order('s.sale_date DESC')
            ->toArray();

        $headers = [
            'รหัสการขาย',
            'รหัสสินค้า',
            'ชื่อสินค้า',
            'ลูกค้า',
            'จำนวน',
            'ราคาต่อหน่วย',
            'ยอดรวม',
            'วันที่ขาย',
            'สถานะ'
        ];

        $salesData = [];
        $totalAmount = 0;

        foreach ($sales as $sale) {
            $statusText = $sale['status'] == 1 ? 'สำเร็จ' : 'ยกเลิก';

            $salesData[] = [
                $sale['id'],
                $sale['product_code'],
                $sale['product_name'],
                $sale['customer_name'],
                $sale['quantity'],
                number_format($sale['unit_price'], 2),
                number_format($sale['total_price'], 2),
                $sale['sale_date'],
                $statusText
            ];

            if ($sale['status'] == 1) {
                $totalAmount += $sale['total_price'];
            }
        }

        // เพิ่มแถวสรุป
        $salesData[] = ['', '', '', '', '', '', '', '', ''];
        $salesData[] = ['', '', '', 'ยอดรวมทั้งหมด', '', '', number_format($totalAmount, 2), '', ''];

        $filename = "sales_report_{$startDate}_to_{$endDate}";
        return Csv::send($filename, $headers, $salesData);
    }

    // นำเข้าข้อมูลสินค้า
    public static function importProducts($csvFile) {
        $result = [
            'total' => 0,
            'imported' => 0,
            'updated' => 0,
            'errors' => []
        ];

        Csv::read($csvFile, function($row) use (&$result) {
            $result['total']++;

            try {
                $db = Kotchasan\Database::create();

                // ทำความสะอาดข้อมูล
                $productData = [
                    'code' => trim($row['code'] ?? ''),
                    'name' => trim($row['name'] ?? ''),
                    'price' => (float)($row['price'] ?? 0),
                    'cost' => (float)($row['cost'] ?? 0),
                    'stock' => (int)($row['stock'] ?? 0),
                    'category_id' => (int)($row['category_id'] ?? 0),
                    'description' => trim($row['description'] ?? ''),
                    'updated_at' => date('Y-m-d H:i:s')
                ];

                // ตรวจสอบข้อมูลที่จำเป็น
                if (empty($productData['code']) || empty($productData['name'])) {
                    $result['errors'][] = "ข้อมูลไม่ครบ: รหัสสินค้าหรือชื่อสินค้าไม่มี";
                    return;
                }

                // ตรวจสอบว่ามีสินค้านี้อยู่แล้วหรือไม่
                $existing = $db->table('products')
                    ->where('code', $productData['code'])
                    ->first();

                if ($existing) {
                    // อัพเดทข้อมูล
                    $db->table('products')
                        ->where('code', $productData['code'])
                        ->update($productData);
                    $result['updated']++;
                } else {
                    // เพิ่มข้อมูลใหม่
                    $productData['created_at'] = date('Y-m-d H:i:s');
                    $db->table('products')->insert($productData);
                    $result['imported']++;
                }

            } catch (Exception $e) {
                $result['errors'][] = "บรรทัดที่ {$result['total']}: " . $e->getMessage();
            }
        });

        return $result;
    }

    // ส่งออกเทมเพลต CSV
    public static function exportTemplate($type) {
        $templates = [
            'users' => [
                'filename' => 'user_import_template',
                'headers' => ['username', 'email', 'name', 'phone', 'birthdate', 'salary'],
                'sample' => [
                    ['john_doe', 'john@example.com', 'John Doe', '0812345678', '1990-01-15', '50000'],
                    ['jane_smith', 'jane@example.com', 'Jane Smith', '0823456789', '1985-05-20', '45000']
                ]
            ],
            'products' => [
                'filename' => 'product_import_template',
                'headers' => ['code', 'name', 'price', 'cost', 'stock', 'category_id', 'description'],
                'sample' => [
                    ['P001', 'สินค้า A', '100.00', '80.00', '50', '1', 'รายละเอียดสินค้า A'],
                    ['P002', 'สินค้า B', '200.00', '150.00', '30', '2', 'รายละเอียดสินค้า B']
                ]
            ]
        ];

        if (!isset($templates[$type])) {
            return false;
        }

        $template = $templates[$type];
        return Csv::send(
            $template['filename'],
            $template['headers'],
            $template['sample']
        );
    }
}

// ระบบ Controller สำหรับจัดการ CSV
class CsvController extends \Kotchasan\Controller
{
    public function import() {
        if ($this->request->getMethod() === 'POST') {
            $uploadedFile = $this->request->getUploadedFile('csv_file');
            $type = $this->request->getParsedBodyParam('type');

            if ($uploadedFile && $uploadedFile->getError() === UPLOAD_ERR_OK) {
                $tempFile = $uploadedFile->getTempName();

                switch ($type) {
                    case 'users':
                        $result = CsvManager::importUsers($tempFile);
                        break;
                    case 'products':
                        $result = CsvManager::importProducts($tempFile);
                        break;
                    default:
                        $result = ['success' => false, 'message' => 'ประเภทไม่ถูกต้อง'];
                }

                header('Content-Type: application/json');
                echo json_encode($result);
            }
        } else {
            // แสดงฟอร์มอัพโหลด
            include ROOT_PATH . 'modules/csv/views/import.php';
        }
    }

    public function export() {
        $type = $this->request->getQueryParam('type');
        $format = $this->request->getQueryParam('format', 'data');

        switch ($type) {
            case 'sales':
                $startDate = $this->request->getQueryParam('start_date');
                $endDate = $this->request->getQueryParam('end_date');
                CsvManager::exportSalesReport($startDate, $endDate);
                break;

            case 'users':
                if ($format === 'template') {
                    CsvManager::exportTemplate('users');
                } else {
                    // ส่งออกข้อมูลผู้ใช้จริง
                }
                break;

            case 'products':
                if ($format === 'template') {
                    CsvManager::exportTemplate('products');
                } else {
                    // ส่งออกข้อมูลสินค้าจริง
                }
                break;
        }
    }
}

หมายเหตุการใช้งาน

  1. การเข้ารหัส: รองรับ UTF-8, TIS-620 และ character encoding อื่นๆ
  2. ประเภทข้อมูล: string, int, double, float, number, en, date, datetime, time
  3. ฟังก์ชันกำหนดเอง: สามารถใช้ callback function สำหรับการประมวลผลข้อมูล
  4. BOM: รองรับการเพิ่ม Byte Order Mark สำหรับ UTF-8
  5. ข้อมูลขนาดใหญ่: ใช้ read() สำหรับการประมวลผลแบบ streaming

คลาส Csv เป็นเครื่องมือที่ทรงพลังสำหรับการจัดการไฟล์ CSV ในกรอบงาน Kotchasan รองรับการนำเข้าและส่งออกข้อมูลในรูปแบบต่างๆ และเหมาะสำหรับการใช้งานในระบบเว็บแอปพลิเคชัน