ผมจะแสดงวิธีคิดโจทย์ข้อนี้ให้ดู แล้วลองจับสาระสำคัญดูนะครับ จะเป็นประโยชน์อย่างมาก เวลาท่านเขียนโปรแกรม
เมื่อมีโจทย์ว่าให้หาวันจันทร์สุดท้ายของเดือนขึ้นมา ผมเริ่มต้นจากดูไปที่ปฎิทินก่อนเลย ผมไม่คิดก่อนนะว่าจะหายังไง แต่ดูปฏิทินก่อน เพราะข้อสังเกตุต่างๆมันจะมาจากปฎิทิน นั่นเอง เมื่อมองไปที่ปฏิทินแล้วคิด ผมเกิดความคิดว่า ถ้าวนลูปตั้งแต่วันที่ 1 จนไปถึงวันสุดท้ายของเดือน แล้วคอยเช็กว่าวันในลูปนั้นเป็นวันจันทร์หรือเปล่า ถ้าเป็นวันจันทร์เก็บใส่ตัวแปรอะเรย์ไว้ หลังจากลูปหมดถึงวันสุดท้ายแล้วออกจากลูป ไปดูอะเรย์ตัวสุดท้าย ก็จะได้วันจันทร์สุดท้ายของเดือนออกมา
<?php // ต้นเดือนจะเป็นวันที่ 1 เสมอ $first = 1; // หาวันสุดท้ายของเดือน $last = cal_days_in_month( CAL_GREGORIAN , date("m") , date("Y") ) ; // สร้างตัวแปรอะเรย์ไว้เก็บวันจันทร์ $mondays = array(); for( $i=$first; $i<=$last; $i++){ //เช็กว่าเป็นวันจันทร์หรือเปล่า ถ้าใช่ยัดใส่อะเรย์ $cur = strtotime(date("m")."/".$i."/".date("Y")); if( date("l", $cur) == "Monday" ){ array_push($mondays, $cur); } } //เมื่อพ้น loop แสดงอะเรย์ตัวสุดท้าย มันจะเป็นจันทร์สุดท้ายของเดือน echo date("d-m-Y", $mondays[count($mondays)-1]); ?> |
ใช้ได้
ข้อแนะนำอย่างหนึ่งที่อยากให้รุ่นน้องปฎิบัติจนเป็นนิสัยก็คือ จงเขียนคอมเม้นท์อธิบายลำดับการทำงานให้เสร็จก่อน ก่อนจะเขียนโค้ด ดู
// วนลูปตั้งแต่ วันที่ 1 จนถึงวันสุดท้ายของเดือน //ในลูปเช็กว่าเป็นวันจันทร์หรือเปล่า ถ้าใช่ยัดใส่อะเรย์ //เมื่อพ้น loop แสดงอะเรย์ตัวสุดท้าย มันจะเป็นจันทร์สุดท้ายของเดือน |
ถ้าสังเกตุจะเห็นว่าคอมเม้นท์นี้จะต่างกับคอมเม้นท์ตอนเขียนโค้ดจริงนิดหน่อย นั่นเพราะว่าพอเขียนโค้ด ความคิดเราจะแตกจากคอมเม้นท์ใหญ่ แต่มันก็ยังอยู่ในกรอบของความคิดเดิมนะ พอเริ่มเขียนเรามาดูความคิดที่เราเขียนไว้ อ๋อ วนลูปตั้งแต่ วันที่ 1 จนถึงวันสุดท้ายของเดือน ถ้าอย่างนั้นก็ต้องหา วันที่ 1 กับ วันสุดท้ายของเดือนมาก่อน (ค่อยถามตัวเองลงไปเรื่อยๆ วันสุดท้ายหาไงฟะ)
// ต้นเดือนจะเป็นวันที่ 1 เสมอ $first = 1; // หาวันสุดท้ายของเดือน $last = cal_days_in_month( CAL_GREGORIAN , date("m") , date("Y") ) ; |
ความคิดมันจะแตกย่อยลงไปอย่างสวยงาม และเขียนโปรแกรมง่ายมาก
ต่อมา ผมมองไปที่ความคิดแรกและโค้ดสำเร็จ มันมีจุดอ่อนอยู่ตรงที่จำนวนรอบของ loop ความเป็นไปได้คือ 28-31 รอบขึ้นอยู่กับเดือน ผมถามตัวเองว่าถ้าอยากให้มันสั้นกว่านี้ น่าจะมีวิธีอื่นอีก ยังไง ผมก็มองไปที่ปฎิทินใหม่ ได้ข้อสังเกตว่า วันจันทร์สุดท้ายของเดือน มันอยู่ใกล้กับวันสิ้นเดือนมาก ถ้าลูปตั้งแต่วันสุดท้ายของเดือนมาหาต้นเดือน คอยเช็กในลูปว่าเป็นวันจันทร์หรือเปล่า ถ้าเป็นวันจันทร์ จบเลยเราได้คำตอบแล้ว เด้งออกจากลูปแล้วโชว์ผลลัพธ์เลย
<?php // ต้นเดือนจะเป็นวันที่ 1 เสมอ $first = 1; // หาวันสุดท้ายของเดือน $last = cal_days_in_month( CAL_GREGORIAN , date("m") , date("Y") ) ; // สร้างตัวแปรไว้เก็บวันจันทร์ $monday = ""; for( $i=$last; $i>=$first; $i--){ //เช็กว่าเป็นวันจันทร์หรือเปล่า ถ้าใช่เก็บไว้ในตัวแปร แล้วออกจากลูป $cur = strtotime(date("m")."/".$i."/".date("Y")); if( date("l", $cur) == "Monday" ){ $monday = $cur; break; } } // แสดงผล echo date("d-m-Y", $monday); ?> |
จำนวนการวนลูปลดลงมหาศาล
ยังไม่พอ ผมคิดต่อไปอีกว่า มันจะมีวิธีอื่นอีกไหมที่มันอาจจะไม่ต้องใช้ลูป ผมก็กลับไปมองที่ปฏิทิน ได้ความคิดว่า ถ้าเราเริ่มจากวันสุดท้ายของเดือน เช็กว่ามันเป็นวันจันทร์หรือเปล่า ถ้าใช่ก็จบเลย แต่ถ้าไม่ใช่เราหาวันจันทร์ที่ผ่านมาก็จบเหมือนกัน
<?php $last = cal_days_in_month( CAL_GREGORIAN , date("m") , date("Y") ) ; //หาวันสุดท้ายของเดือน $lastday = strtotime(date("m")."/".$last."/".date("Y")); //เช็กว่าเป็นวันจันทร์หรือไม่ if( date("l",$lastday) == "Monday"){ //ถ้าใช่ ok echo date("d-m-Y",$lastday); }else{ //ถ้าไม่ใช่ หาวันจันทร์ที่ผ่านมา echo date("d-m-Y",strtotime("last monday", $lastday)); } ?> |
ผมยังมีความคิดเหลืออยู่อีก 1 ความคิดคือ หาวันสุดท้ายของเดือน เช็กว่าเป็นวันจันทร์หรือไม่ ถ้าใช่จบ แต่ถ้าไม่ใช่ มันเป็นวันอะไร? นับถอยหลังไปจนถึงวันจันทร์ กี่วัน เมื่อได้ตัวเลขแล้วนำไปลบออกจากเลขวันสิ้นเดือน ก็จะได้วันที่ของวันจันทร์ออกมา
สรุปความคิดทั้งหมด ดูนะ ผมเริ่มจากวิธีที่โง่ที่สุดมาก่อน แล้วเอาวิธีที่โง่ที่สุดนั้นมาลดกระบวนการ จะได้วิธีที่ฉลาดขึ้นมา พอต่อยอดจากความคิดที่ฉลาดขึ้นมานั้น เราก็จะได้ความคิดที่เพอเฟ็ก เราอย่าเริ่มหาวิธีที่เพอเฟ็กตั้งแต่ต้นครับ เพราะมันจะปวดหัวและคิดไม่ออก เราเอาวิธีที่คิดได้ถึงแม้มันจะมีจุดบอด แล้วค่อยพัฒนาจากวิธีนั้น จะทำให้เราคิดออกและสร้างผลงานที่ดีออกมาได้
และอีกอย่าง พยายามอ่านฟังก์ชั่นที่ PHP มีมาให้ ให้มากๆ บางครั้งอ่านให้เพียงเพื่อว่า อ้าวเฮ้ยมันมีฟังก์ชั่นอย่างนี้ด้วยแฮะ แล้ววันหนึ่งข้างหน้าท่านจะได้ใช้ ความคิดมันจะไม่ตีบตัน
ขอธรรมะคุ้มครอง ครับ
ขวัญนภา says:
20/08/2557 at 20/08/2557
ขอบคุณมากค่ะ แต่อยากถามว่า ถ้าเปลี่ยนเปนหาวันจันทร์ในเดือนนั้นทุกจันทร์ ว่ามีวันอะไรบ้างแล้วนำว่าวนลูปในฐานข้อมูลจะใช้คำสั่งอะไรอ่ะคะ
วัชรเมธน์ ชิษณุคุปต์ ศรีเนธิโรทัย says:
21/08/2557 at 21/08/2557
คุณก็ลูปตั้งแต่วันที่ 1 ถึงวันสุดท้ายของเดือน แล้วในลุปก็เอาแต่ละวันนั้น ไปเช็กดูว่าเป็นวันจันทร์หรือเปล่า ถ้าเป็นวันจันทร์ก็ เอาวันที่เก็บไว้ใน อะเรย์ พอมันหลุดออกจากลุป คุณก็จะได้ วันที่ที่เป็นวันจันทร์ทั้งหมดของเดือนออกมา
โคตรโหดกระโดดขี่เป็ด ^ ^ says:
03/10/2557 at 03/10/2557
ขอบคุณครับ… :D