Kotchasan Framework Documentation

Kotchasan Framework Documentation

คลาส Number - ยูทิลิตี้สำหรับจัดการตัวเลข

TH 03 Feb 2026 12:49

คลาส Number - ยูทิลิตี้สำหรับจัดการตัวเลข

คลาส Number เป็นยูทิลิตี้สำหรับการจัดรูปแบบตัวเลข การหารที่ปลอดภัย และการสร้างรหัสเอกสารด้วยตัวแปรวันที่

Namespace

Kotchasan\Number

ภาพรวม

Number class ประกอบด้วยเมธอดสำหรับ:

  • จัดรูปแบบตัวเลขด้วยคอมมาคั่นหลักพัน
  • การหารที่ปลอดภัย (ป้องกันหารด้วยศูนย์)
  • สร้างรหัสเอกสารด้วยรูปแบบวันที่

API Reference

format()

จัดรูปแบบตัวเลขให้มีเครื่องหมายคั่นหลักพัน (รักษาทศนิยมไว้ตามต้นฉบับ ไม่ปัดเศษ)

public static function format($value, string $thousands_sep = ','): string

Parameters:

  • $value - ตัวเลขที่ต้องการจัดรูปแบบ
  • $thousands_sep - เครื่องหมายคั่นหลักพัน (default: ,)

Returns: ตัวเลขที่จัดรูปแบบแล้ว (string)

คุณสมบัติ:

  • รองรับทศนิยม (จะรักษาทศนิยมไว้ตามต้นฉบับ)
  • ไม่ปัดเศษ
  • คั่นเฉพาะส่วนจำนวนเต็ม

Example:

use Kotchasan\Number;

// จัดรูปแบบพื้นฐาน
echo Number::format(1234567); // "1,234,567"
echo Number::format(1234.56); // "1,234.56"
echo Number::format(1000000.789); // "1,000,000.789"

// ไม่ปัดเศษทศนิยม
echo Number::format(123.456789); // "123.456789"
echo Number::format(9999.99); // "9,999.99"

// จำนวนเต็ม (ไม่มีทศนิยม)
echo Number::format(123); // "123"
echo Number::format(123.0); // "123"

// ใช้เครื่องหมายคั่นอื่น
echo Number::format(1234567, ' '); // "1 234 567"
echo Number::format(1234567, '.'); // "1.234.567"
echo Number::format(1234567, '-'); // "1-234-567"

// ใช้กับราคา
$price = 2500.50;
echo "ราคา: " . Number::format($price) . " บาท";
// "ราคา: 2,500.50 บาท"

// ใช้กับข้อมูลจากฐานข้อมูล
$total = $db->first("SELECT SUM(amount) AS total FROM orders")->total;
echo "ยอดรวม: " . Number::format($total) . " บาท";

division()

ทำการหารที่ปลอดภัย คืนค่า 0 หากตัวหารเป็น 0 (ป้องกัน division by zero error)

public static function division($dividend, $divisor)

Parameters:

  • $dividend - ตัวตั้ง (dividend)
  • $divisor - ตัวหาร (divisor)

Returns: ผลลัพธ์ของการหาร หรือ 0 (ถ้าตัวหารเป็น 0)

Example:

use Kotchasan\Number;

// การหารปกติ
echo Number::division(10, 2); // 5
echo Number::division(15, 3); // 5
echo Number::division(7, 2); // 3.5
echo Number::division(100, 7); // 14.285714285714

// ป้องกันการหารด้วยศูนย์
echo Number::division(10, 0); // 0 (ไม่เกิด error)
echo Number::division(100, 0); // 0

// คำนวณเปอร์เซ็นต์
$correct = 85;
$total = 100;
$percentage = Number::division($correct * 100, $total);
echo "คะแนน: " . $percentage . "%"; // "คะแนน: 85%"

// คำนวณค่าเฉลี่ย (ปลอดภัยถ้าไม่มีข้อมูล)
$totalAmount = 1500;
$itemCount = 0; // อาจเป็น 0 ได้
$average = Number::division($totalAmount, $itemCount);
echo "ค่าเฉลี่ย: " . Number::format($average); // "ค่าเฉลี่ย: 0"

// ใช้กับข้อมูลจริง
$itemCount = 5;
$average = Number::division($totalAmount, $itemCount);
echo "ค่าเฉลี่ย: " . Number::format($average); // "ค่าเฉลี่ย: 300"

// คำนวณอัตราส่วน
$success = $db->count('orders', ['status' => 'completed']);
$totalOrders = $db->count('orders');
$successRate = Number::division($success * 100, $totalOrders);
echo "อัตราความสำเร็จ: " . Number::format($successRate) . "%";

printf()

จัดรูปแบบตัวเลขด้วยตัวแปรวันที่ สำหรับสร้างรหัสเอกสารตามรูปแบบวันที่

public static function printf(string $format, $value, string $prefix = ''): string

Parameters:

  • $format - รูปแบบสตริงที่มีตัวแปร
  • $value - ค่าตัวเลขที่จะแทนที่ (ใช้กับ %d หรือ format specifier อื่นๆ)
  • $prefix - คำนำหน้า (optional, ใช้กับ %s)

Returns: สตริงที่จัดรูปแบบแล้ว

ตัวแปรที่รองรับ:

  • %YY - ปี พ.ศ. แบบเต็ม (2567)
  • %yy - ปี ค.ศ. แบบเต็ม (2024)
  • %Y - ปี พ.ศ. แบบ 2 หลัก (67)
  • %y - ปี ค.ศ. แบบ 2 หลัก (24)
  • %M - เดือนแบบ 2 หลัก (01-12)
  • %m - เดือนแบบไม่มี leading zero (1-12)
  • %D - วันแบบ 2 หลัก (01-31)
  • %d - วันแบบไม่มี leading zero (1-31)
  • %s - คำนำหน้า (prefix)

Example:

use Kotchasan\Number;

// สมมติวันที่ปัจจุบันคือ 1 ธันวาคม 2024

// สร้างรหัสเอกสารพื้นฐาน
echo Number::printf("DOC%YY%M%D-%04d", 123);
// "DOC25671201-0123" (ปี พ.ศ. 2567, เดือน 12, วัน 01)

// ใช้ปี ค.ศ.
echo Number::printf("INV%yy%M%D-%05d", 456);
// "INV20241201-00456"

// ปี 2 หลัก
echo Number::printf("REC%Y%M-%04d", 789);
// "REC6712-0789"

// เดือนและวันแบบไม่มี leading zero
echo Number::printf("ORD%yy%m%d-%04d", 101);
// "ORD2024121-0101" (ถ้าวันที่คือ 1/12/2024)

// ใช้คำนำหน้า
echo Number::printf("%sBILL%yy%m%d-%03d", 999, "COMP");
// "COMPBILL2024121-999"

// สร้างเลขที่ใบกำกับภาษี
echo Number::printf("TAX%YY%M-%06d", 1);
// "TAX256712-000001"

// สร้างรหัสสมาชิก
echo Number::printf("MEM%YY-%08d", 12345);
// "MEM2567-00012345"

// Format specifier มาตรฐาน
echo Number::printf("ORDER-%05d", 42); // "ORDER-00042"
echo Number::printf("ID-%010d", 123); // "ID-0000000123"

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

1. ระบบออกใบเสร็จ

use Kotchasan\Number;

class ReceiptSystem
{
    private $db;

    public function createReceipt($customerId, $items)
    {
        // คำนวณยอดรวม
        $total = 0;
        foreach ($items as $item) {
            $total += $item['price'] * $item['quantity'];
        }

        // สร้างเลขที่ใบเสร็จ
        $lastReceipt = $this->db->first("SELECT MAX(id) as last_id FROM receipts");
        $nextId = ($lastReceipt->last_id ?? 0) + 1;
        $receiptNumber = Number::printf("REC%YY%M%D-%06d", $nextId);

        // บันทึกใบเสร็จ
        $receiptId = $this->db->insert('receipts', [
            'receipt_number' => $receiptNumber,
            'customer_id' => $customerId,
            'total_amount' => $total,
            'created_date' => date('Y-m-d H:i:s')
        ]);

        return [
            'receipt_id' => $receiptId,
            'receipt_number' => $receiptNumber,
            'total_formatted' => Number::format($total) . ' บาท'
        ];
    }

    public function calculateDiscount($amount, $discountPercent)
    {
        $discountAmount = Number::division($amount * $discountPercent, 100);
        $finalAmount = $amount - $discountAmount;

        return [
            'original' => Number::format($amount),
            'discount' => $discountPercent . '%',
            'discount_amount' => Number::format($discountAmount),
            'final' => Number::format($finalAmount)
        ];
    }
}

// ใช้งาน
$receipt = new ReceiptSystem($db);
$result = $receipt->createReceipt(123, [
    ['price' => 100, 'quantity' => 2],
    ['price' => 50.50, 'quantity' => 3]
]);

echo $result['receipt_number']; // "REC25671201-000001"
echo $result['total_formatted']; // "351.50 บาท"

2. รายงานทางการเงิน

class FinancialReport
{
    public static function formatCurrency($amount)
    {
        return Number::format($amount) . ' บาท';
    }

    public static function calculatePercentage($part, $total)
    {
        $percentage = Number::division($part * 100, $total);
        return Number::format($percentage) . '%';
    }

    public static function generateSummary($sales, $target)
    {
        $achievementRate = Number::division($sales * 100, $target);
        $remaining = $target - $sales;

        return [
            'sales' => self::formatCurrency($sales),
            'target' => self::formatCurrency($target),
            'achievement' => Number::format($achievementRate) . '%',
            'remaining' => self::formatCurrency($remaining)
        ];
    }
}

// สร้างรายงาน
$report = FinancialReport::generateSummary(250000, 300000);
print_r($report);
/*
Array (
    [sales] => 250,000 บาท
    [target] => 300,000 บาท
    [achievement] => 83.333333333333%
    [remaining] => 50,000 บาท
)
*/

3. ระบบสร้างรหัสอัตโนมัติ

class DocumentNumberGenerator
{
    private static $formats = [
        'invoice' => "INV%YY%M%D-%05d",
        'receipt' => "REC%YY%M%D-%05d",
        'quotation' => "QUO%YY%M%D-%05d",
        'purchase_order' => "PO%YY%M%D-%05d"
    ];

    public static function generate($type, $sequence, $branch = '')
    {
        if (!isset(self::$formats[$type])) {
            throw new \Exception("Invalid document type: $type");
        }

        return Number::printf(self::$formats[$type], $sequence, $branch);
    }

    public static function generateWithBranch($type, $sequence, $branchCode)
    {
        $format = "%s" . self::$formats[$type];
        return Number::printf($format, $sequence, $branchCode);
    }
}

//ใช้งาน
echo DocumentNumberGenerator::generate('invoice', 123);
// "INV25671201-00123"

echo DocumentNumberGenerator::generateWithBranch('receipt', 456, "BKK");
// "BKKREC25671201-00456"

4. การคำนวณสถิติ

class Statistics
{
    public static function calculateAverage($numbers)
    {
        $sum = array_sum($numbers);
        $count = count($numbers);

        return Number::division($sum, $count);
    }

    public static function calculateGrowthRate($oldValue, $newValue)
    {
        $diff = $newValue - $oldValue;
        $growthRate = Number::division($diff * 100, $oldValue);

        return Number::format($growthRate) . '%';
    }

    public static function formatReport($data)
    {
        $total = array_sum($data);
        $average = self::calculateAverage($data);
        $count = count($data);

        return [
            'count' => Number::format($count),
            'total' => Number::format($total),
            'average' => Number::format($average),
            'max' => Number::format(max($data)),
            'min' => Number::format(min($data))
        ];
    }
}

// ใช้งาน
$salesData = [1500, 2300, 1800, 2100, 1900];
$stats = Statistics::formatReport($salesData);
print_r($stats);

echo Statistics::calculateGrowthRate(1000, 1500); // "50%"

Best Practices

1. ใช้ format() สำหรับแสดงผล

// ✅ Good - แสดงผลเป็นสตริงที่อ่านง่าย
echo "ยอดรวม: " . Number::format($total) . " บาท";

// ❌ Bad - แสดงตัวเลขโดยตรง
echo "ยอดรวม: $total บาท"; // 1234567 บาท (อ่านยาก)

2. ใช้ division() ทุกครั้งที่อาจหารด้วยศูนย์

// ✅ Good - ป้องกัน division by zero
$average = Number::division($total, $count);

// ❌ Dangerous - อาจเกิด error
$average = $count > 0 ? $total / $count : 0; // ยาวและซับซ้อน

3. สร้างรหัสเอกสารด้วย printf()

// ✅ Good - ใช้ printf() สร้างรูปแบบที่สม่ำเสมอ
$docNo = Number::printf("INV%YY%M%D-%05d", $id);

// ❌ Bad - สร้างเอง (ซับซ้อนและผิดพลาดง่าย)
$y = date('Y') + 543;
$docNo = "INV{$y}" . date('md') . "-" . str_pad($id, 5, '0', STR_PAD_LEFT);

4. จัดรูปแบบก่อนบันทึกหรือหลังบันทึก?

// ✅ Good - บันทึกเป็นตัวเลข, format เฉพาะตอนแสดงผล
$db->insert('orders', ['amount' => 1234.56]);
echo Number::format($order->amount); // "1,234.56"

// ❌ Bad - บันทึกเป็นสตริงที่ format แล้ว
$db->insert('orders', ['amount' => Number::format(1234.56)]); // "1,234.56"
// ปัญหา: ไม่สามารถคำนวณต่อได้

ข้อควรระวัง

[!WARNING]
format() ไม่ปัดเศษ: เมธอดนี้เพียงเพิ่มคอมมาคั่น ไม่ได้ปัดทศนิยม ถ้าต้องการปัดใช้ round() ก่อน

[!NOTE]
division() คืนค่า 0: เมื่อหารด้วย 0 จะคืนค่า 0 ไม่ใช่ null ระวังในกรณีที่ต้องแยก "ไม่มีข้อมูล" กับ "ผลลัพธ์คือ 0"

[!IMPORTANT]
printf() ใช้วันที่ปัจจุบัน: ตัวแปรวันที่ใช้ date() ดังนั้นจะเป็นวันที่ขณะเรียกใช้เมธอด ไม่ใช่วันที่ที่ระบุเอง

[!TIP]
ประสิทธิภาพ: เมธอดทั้งหมดเป็น static สามารถเรียกใช้ได้โดยตรงโดยไม่ต้องสร้าง instance

คลาสที่เกี่ยวข้อง

  • Text - การจัดการข้อความ
  • Currency - การจัดการสกุลเงิน
  • Date - การจัดการวันที่

สรุป

คลาส Number มี 3 เมธอดหลัก:

  1. format() - จัดรูปแบบตัวเลขด้วยคอมมาคั่นหลักพัน (รักษาทศนิยม)
  2. division() - หารที่ปลอดภัย (คืนค่า 0 ถ้าหารด้วย 0)
  3. printf() - สร้างรหัสเอกสารด้วยรูปแบบวันที่ (รองรับ พ.ศ./ค.ศ.)

เหมาะสำหรับ:

  • แสดงผลตัวเลขให้อ่านง่าย
  • คำนวณที่ต้องป้องกันหารด้วยศูนย์
  • สร้างรหัสเอกสารอัตโนมัติตามรูปแบบวันที่