Laravel Collections avg() — วิธีหาค่าเฉลี่ยใน Collection ง่ายๆ

Laravel Collections avg() terminal


avg() คืออะไร? ทำไมต้องคำนวณค่าเฉลี่ยใน Laravel?

ถ้าคุณเขียน Laravel อยู่แล้ว น่าจะเคยเจอ scenario หาค่าเฉลี่ยอยู่บ่อยๆ ไม่ว่าจะเป็น:

  • ราคาเฉลี่ยสินค้า — ประเมินว่าร้านเราขายสินค้าราคาเฉลี่ยเท่าไหร่
  • Rating เฉลี่ย — คำนวณดาวเฉลี่ยของรีวิวสินค้า
  • ยอดสั่งซื้อเฉลี่ย — วิเคราะห์ยอดขายต่อออร์เดอร์

ปกติถ้าเขียน PHP แบบเดิม คงต้องใช้ foreach วนลูปบวกค่า แล้วหาร — เขียนหลายบรรทัด อ่านยาก แถมยังต้อง handle divide-by-zero ด้วยตัวเอง ยิ่งโค้ดซับซ้อนขึ้น ยิ่งเสี่ยงพลาด

Laravel มีทางออกที่ดีกว่านั้น — avg() method ที่อยู่ใน Illuminate\Support\Collection ช่วยให้คุณหาค่าเฉลี่ยได้ในบรรทัดเดียว ไม่ว่าข้อมูลจะมาจาก array, Eloquent model, หรือ API response

สิ่งสำคัญที่ต้องจำ: avg() คืนค่าเป็น float หรือ null (กรณี Collection ว่าง)

แล้ว average() ล่ะ? เป็นแค่ alias — ใช้แทนกันได้เลย 100%


พื้นฐานการใช้งาน avg()

ค่าเฉลี่ยจากตัวเลขใน Collection

collect([1, 1, 2, 4])->avg();
// ผลลัพธ์: 2
// (1 + 1 + 2 + 4) / 4 = 2

ง่ายๆ แบบนี้เลย — ส่ง array ของตัวเลขเข้า collect() แล้วเรียก .avg() ต่อได้เลย

หาค่าเฉลี่ยจาก Field ที่กำหนดด้วย avg('field')

$products = collect([
    ['price' => 100],  // หนังสือ
    ['price' => 200],  // คอร์สเรียน
    ['price' => 150],  // อุปกรณ์เขียนโค้ด
]);

$products->avg('price'); // ผลลัพธ์: 150

นี่คือรูปแบบที่ใช้บ่อยที่สุด — ระบุ field name ที่ต้องการหาค่าเฉลี่ย Laravel จะ loop ให้อัตโนมัติ ใช้ได้ทั้งกับ associative array และ object

average() — alias อีกชื่อ

collect([10, 20, 30])->average(); // ผลลัพธ์: 20
collect([10, 20, 30])->avg();     // ผลลัพธ์: 20

ทั้งคู่ทำงานเหมือนกันทุกประการ — เลือกใช้อันไหนก็ได้ตามความชอบ


ใช้งานขั้นสูง — ก้าวขึ้นอีกระดับ

Nested Key ด้วย Dot Notation

$orders = collect([
    ['product' => ['price' => 99.99]],
    ['product' => ['price' => 799.99]],
]);

$orders->avg('product.price'); // ผลลัพธ์: 449.99

จุดเด่นของ Laravel Collections — รองรับ dot notation สำหรับ nested array/object ไม่ต้อง loop หลายชั้น เรียก 'product.price' ตรงๆ ได้เลย ถ้าเทียบกับ PHP แบบเดิม ต้องเขียน foreach ซ้อนกัน 2 ชั้นแน่นอน

ใช้ Callback คำนวณค่าก่อนหาค่าเฉลี่ย

$orders = collect([
    ['price' => 100, 'qty' => 2],  // order ที่ 1: 100*2 = 200
    ['price' => 200, 'qty' => 3],  // order ที่ 2: 200*3 = 600
    ['price' => 150, 'qty' => 1],  // order ที่ 3: 150*1 = 150
]);

// คำนวณ price * qty ก่อน แล้วค่อยหาค่าเฉลี่ย
// (200 + 600 + 150) / 3 = 316.67
$orders->avg(fn($item) => $item['price'] * $item['qty']); // ผลลัพธ์: 316.67

นี่คือสิ่งที่คู่แข่งส่วนใหญ่ยังไม่ค่อยเขียนเป็นภาษาไทย — ความสามารถในการ transform ข้อมูลก่อนหาค่าเฉลี่ย ทำให้ avg() ยืดหยุ่นมาก เหมาะกับโจทย์ที่ต้องคำนวณ derived value เช่น ยอดรวมต่อ order (price × qty)

Laravel Collections avg() terminal


Higher-Order Message — $collection->avg->price

$products = collect([
    (object)['price' => 100],
    (object)['price' => 200],
]);

$products->avg->price; // ผลลัพธ์: 150

นี่คือ syntactic sugar ที่เรียกว่า Higher-Order Message — รูปแบบย่อสำหรับ object collection โดยเฉพาะ เขียนสั้นลง แต่ต้องระวัง: ใช้ได้เฉพาะกับ object เท่านั้น ใช้กับ array ไม่ได้


Edge Cases ที่ต้องรู้ก่อนเอาไปใช้งานจริง

Empty Collection คืนค่าอะไร?

collect([])->avg(); // ผลลัพธ์: null (ไม่ใช่ 0!)

สำคัญมาก! — ถ้า Collection ว่าง จะคืน null ไม่ใช่ 0 ถ้าเอาไปใช้ต่อโดยไม่ handle อาจเกิด error ได้ แนะนำให้ใช้ ?? 0 หรือตรวจสอบด้วย is_null() ก่อน

ค่า Null กับ Non-numeric

collect([
    ['price' => 100],
    ['price' => null],  // ค่า null จะถูก skip
    ['price' => 200],
])->avg('price'); // ผลลัพธ์: 150
  • ค่า null ใน field จะถูก skip ไม่เอามาคำนวณ
  • Non-numeric จะถูก cast เป็น 0 หรือ ignore ขึ้นอยู่กับ PHP version

เตือน: ตรวจสอบ nullable field ใน database ให้ดีก่อนเอาค่าไปใช้ โดยเฉพาะ Eloquent model ที่ดึงจาก DB


ตัวอย่างใช้งานจริง — เขียนโค้ดให้เพื่อน Thai Dev ดู

คำนวณราคาเฉลี่ยสินค้า (E-commerce)

// จาก Eloquent model — ดึงสินค้าทั้งหมดมาหาค่าเฉลี่ย
$avgPrice = Product::all()->avg('price');

// จาก API response — parse แล้วหาค่าเฉลี่ย
$avgPrice = collect($apiProducts)->avg('price');

คำนวณ Rating เฉลี่ยของรีวิวสินค้า

$product = Product::with('reviews')->find($id);

// rating เฉลี่ยทั้งหมด
$avgRating = $product->reviews->avg('rating');

// rating เฉลี่ยเฉพาะ verified purchase
$avgVerifiedRating = $product->reviews
    ->filter(fn($r) => $r->is_verified)  // กรองเฉพาะรีวิวที่ซื้อจริง
    ->avg('rating');

คำนวณยอดสั่งซื้อเฉลี่ยต่อ Order

// ยอดสั่งซื้อเฉลี่ย = ผลรวม (price * qty) ของแต่ละ order
$avgOrderValue = Order::all()->avg(fn($order) =>
    $order->items->sum(fn($item) => $item->price * $item->quantity)
);

ตัวอย่างนี้เหมาะกับ admin dashboard สำหรับร้านค้าออนไลน์ไทย ที่ต้องการวิเคราะห์ยอดขายเฉลี่ยต่อออร์เดอร์

เทคนิคเพิ่มเติม: ใช้ pluck() ดึงเฉพาะ field ก่อน

$products = collect([
    ['name' => 'Book', 'price' => 150],
    ['name' => 'Pen', 'price' => 50],
    ['name' => 'Notebook', 'price' => 80],
]);

// ดึงเฉพาะ price มาหาค่าเฉลี่ย
$products->pluck('price')->avg(); // ผลลัพธ์: 93.33

รูปแบบ pluck()->avg() อ่านง่าย เหมาะกับกรณีที่ต้องการเฉพาะ field เดียวมาหาค่าเฉลี่ย


สรุป — จำได้ใน 1 นาที

Syntax การใช้งาน
avg() ค่าเฉลี่ยจากตัวเลขใน Collection
avg('field') ค่าเฉลี่ยจาก field ที่ระบุ
avg('nested.field') dot notation สำหรับ nested data
avg(fn(...)) คำนวณ derived value ก่อนหาค่าเฉลี่ย
$coll->avg->field Higher-order message (object collection)
ว่าง คืน null — อย่าลืม handle!

average() เป็นแค่ alias ของ avg() — ใช้ตัวไหนก็ได้

จำง่ายๆ: ถ้าต้องหาค่าเฉลี่ยใน Laravel — อย่าวนลูปเอง มี avg() ให้ใช้แล้ว


Tags: Laravel Collections, Laravel avg, Laravel average, PHP Collections, Higher-Order Message

เกี่ยวกับผู้เขียน

ITTHIPAT

สวัสดีครับผม อิทธิพัทธ์ (เป้) ชอบหาเทคนิคต่างๆที่ทำให้ชีวิต Programmer ง่ายขึ้น ทั้ง Automate, Library ชอบทำ Blog และ Video ถ้ามีเวลานะ!

ขอบคุณทุกคนที่ติดตาม และอ่านบทความของผมครับ ผมหวังว่าความรู้ที่เขียนขึ้นในเว็บไซต์นี้จะช่วยทุกท่านได้ไม่มากก็น้อย 

Scroll to Top