ป้ายกำกับ: preg_match

บั๊กที่แท้มันคืออะไรตับไตใส้พุงบั๊กที่แท้มันคืออะไรตับไตใส้พุง

มี user ถามมาว่า bug คืออะไร ทำไม่มี bug ก็เลยลองเขียนตัวอย่างให้ดู ยกตัวอย่างบัคที่เกิดจาการกรอกข้อมูลผิดไปจากที่ระบบออกแบบและคาดหวังไว้ ก็มีคำถามกลับมาประมาณว่าทำไม่ไม่ตรวจให้หมดละ เลยลองทำตัวอย่างออกมา

<?php

$strings = [
 '!@#$%^&*()_-+="{}[]\+:<>,./?',
 'Apple Inc.',
 'email.gmail.com',
 'email.job.co.th',
 '[email protected]',
 '[email protected]',
 'https://pitt.plusmagi.com/about/',
 'https://pitt.plusmagi.com/เชื่อมต่อ-php-กับ-sql-server-sqlsrv/',
 'james bond 007',
 'johnny english พยัคฆ์ร้าย 00ก๊าก',
 'pitt@小米科技.cn',
 'sale 20%',
 'Xiaomi Inc. (小米科技)',
 'Xiaomi Inc.',
 'พิชญ์ พันธุ์สนิท pitt phunsanit',
 'พิชญ์ พันธุ์สนิท',
 'พิชญ์@gmail.com',
 'หนึ่งในพระราชดำริ ช่อง 9',
 'หนึ่งในพระราชดำริ ช่อง ๙',
 'ไทย นี่มันไทยจริง ๆ ',
];

function validateAlphanumeric($string)
{
 if (preg_match('/[^A-Za-z0-9]/', $string)) {
  return true;
 } else {
  return false;
 }
}

function validateAlphanumericEnglish($string)
{
 if (preg_match('/^[a-zA-Z0-9\s]+$/', $string)) {
  return true;
 } else {
  return false;
 }
}

function validateAlphanumericThai($string)
{
 if (preg_match('/[^A-Za-z0-9-ก-๙]/', $string)) {
  return true;
 } else {
  return false;
 }
}

function validateAlphanumericThaiOnly($string)
{
 /* อักษรภาษาไทย และ space */
 if (preg_match('/^[ก-ฮ\s]+$/', $string)) {
  return true;
 } else {
  return false;
 }
}

function validateEmail($string)
{
 if (filter_var($string, FILTER_VALIDATE_EMAIL)) {
  return true;
 } else {
  return false;
 }
}

function validateFilterURL($string)
{
 if (filter_var($string, FILTER_VALIDATE_URL)) {
  return true;
 } else {
  return false;
 }
}

function validatePregURL($string)
{
 if (preg_match('/\b(?:(?:https?|ftp):\/\/|www\.)[-a-z0-9+&@#\/%?=~_|!:,.;]*[-a-z0-9+&@#\/%=~_|]/i', $string)) {
  return true;
 } else {
  return false;
 }
}

echo '<!doctype html>
<html>
 <head>
  <meta charset="utf-8">
  <title>PHP String Validation By Ptii Phunsanit</title>
  <meta name="author" content="Pitt Phunsanit">
  <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" type="text/css">
 </head>
 <body>
  <table class="table table-striped">
  <caption>
   PHP String Validation
  </caption>
  <thead>
   <tr>
   <th>Test</th>
   <th>String</th>
   <th colspan="4">Alphabet</th>
   <th>Email</th>
   <th colspan="2">URL</th>
   </tr>
   <tr>
   <th></th>
   <th></th>
   <th>Alphanumeric</th>
   <th>Alphanumeric English</th>
   <th>Alphanumeric Thai</th>
   <th>Alphanumeric Thai Only</th>
   <th>Email</th>
   <th>Filter URL</th>
   <th>Preg URL</th>
   </tr>
  </thead>
  <tbody>';
foreach ($strings as $no => $string) {
 echo '<tr>',
 '<th>', ($no + 1), '</th>',
 '<th>', $string, '</th>',
 '<td>', (int) validateAlphanumeric($string), '</td>',
 '<td>', (int) validateAlphanumericEnglish($string), '</td>',
 '<td>', (int) validateAlphanumericThai($string), '</td>',
 '<td>', (int) validateAlphanumericThaiOnly($string), '</td>',
 '<td>', (int) validateEmail($string), '</td>',
 '<td>', (int) validateFilterURL($string), '</td>',
 '<td>', (int) validatePregURL($string), '</td>',
  '</tr>';
}
echo '</tbody></table></body></html>';

ผลที่ได้ ดูเต็ม ๆ เว็บนี้ยังมี bug เลย แต่ไม่คุ้มที่จะแก้
1 คือผ่านการทดสอบ 0 คือ ไม่ผ่านการทดสอบ

PHP String Validation
Test String Alphabet Email URL
Alphanumeric Alphanumeric English Alphanumeric Thai Alphanumeric Thai Only Email Filter URL Preg URL
1 !@#$%^&*()_-+=”{}[]\+:<>,./? 1 0 1 0 0 0 0
2 Apple Inc. 1 0 1 0 0 0 0
3 email.gmail.com 1 0 1 0 0 0 0
4 email.job.co.th 1 0 1 0 0 0 0
5 [email protected] 1 0 1 0 1 0 0
6 [email protected] 1 0 1 0 1 0 0
7 https://pitt.plusmagi.com/about/ 1 0 1 0 0 1 1
8 https://pitt.plusmagi.com/เชื่อมต่อ-php-กับ-sql-server-sqlsrv/ 1 0 1 0 0 0 1
9 james bond 007 1 1 1 0 0 0 0
10 johnny english พยัคฆ์ร้าย 00ก๊าก 1 0 1 0 0 0 0
11 pitt@小米科技.cn 1 0 1 0 0 0 0
12 sale 20% 1 0 1 0 0 0 0
13 Xiaomi Inc. (小米科技) 1 0 1 0 0 0 0
14 Xiaomi Inc. 1 0 1 0 0 0 0
15 พิชญ์ พันธุ์สนิท pitt phunsanit 1 0 1 0 0 0 0
16 พิชญ์ พันธุ์สนิท 1 0 1 1 0 0 0
17 พิชญ์@gmail.com 1 0 1 0 0 0 0
18 หนึ่งในพระราชดำริ ช่อง 9 1 0 1 0 0 0 0
19 หนึ่งในพระราชดำริ ช่อง ๙ 1 0 1 1 0 0 0
20 ไทย นี่มันไทยจริง ๆ 1 0 1 1 0 0 0

เริ่มจากชุดแรก Alphanumeric ใช้ preg_match(‘/[^A-Za-z0-9]/’, $string เหมือนจะดูดี ตามคู่มือคือเทียบโดยตัวอักษร a ถึง z และตัวเลข 0 ถึง 9 แต่ขอโทษชุดสตริงค์ แปลก ๆ ?!@#$%^&*()_-+=”{}[]\+:<>,./ มันยังผ่าน จนด้วยคำพูดจริง ๆ ใส่อะไรก็ผ่าน

ชุดที่ 2 Alphanumeric English ใช้ preg_match(‘/^[a-zA-Z0-9\s]+$/’, $string) ผลคือ ที่มีอักษรไทยอยู่ตกหมด และ james bond 007 ผ่าน แต่ Apple Inc. กับตัวอื่น ๆ ตกไปง่าย ๆ แค่ใส่ . สรุปถ้าเขียนเป็นประโยคมาก็จบชีวิต

ชุดที่ 3 Alphanumeric Thai ใช้ preg_match(‘/[^A-Za-z0-9-ก-๙]/’, $string) รั่วทุกตัวอักษรอีกชุก ถึงจะใส่ ก-๙ มาอักษรจีนก็ยังรอดอยู่ดี

ชุดที่ 4 Alphanumeric Thai Only ใช้ preg_match(‘/^[ก-ฮ\s]+$/’, $string) มันไทยมากจริง อย่าได้ใส่เลขอารบิกมาเชียว บางคนก็ไม่รู้นะครับว่าเลขไทยนะมันพิมพ์ยังไง

ชุดที่ 5 Email ใช้ filter_var($string, FILTER_VALIDATE_EMAIL) ตรวจว่าเป็นอีเมลจริง ๆ รึเปล่า ผ่าน email.gmail.com และ พิชญ์@gmail.com ก็หลอกมันไม่ได้

ชุดที่ 6 ติดใจคำสั่ง filter_var ในข้อที่แล้วใช้ filter_var($string, FILTER_VALIDATE_URL) ผลคือ เกือบจะดีแล้ว ตรวจ url ได้จริง ๆ ยกเว้น https://pitt.plusmagi.com/เชื่อมต่อ-php-กับ-sql-server-sqlsrv/ link ของบล๊อคของผมเองยังไม่ผ่าน ปวดตับ แม้แต่ function สำเร็จรูปก็ไม่ได้ดีเสมอตามที่คิดว่า “ใช้กันมากเป็นมาตราฐานมันต้องดีกว่าเขียนเองซิ” function filter_var ของ PHP มันออกมาตั้งแต่ 2 November 2006 ก็แค่ไม่กี่ปีเองมั๊ง ปีนี้ ค.ศ. อะไรแล้ว แต่มันก็ยังไม่รับภาษาอื่นนอกจากภาษาอังกฤษอยู่เหมือนเดิม ไม่ใช่ไม่มีคนแจ้งไปที่คนเขียนภาษา php นะ ตามนี้ แต่พี่แกก็ยังไม่แก้แค่นั้นเอง

ชุดที่ 7 ใช้ preg_match(‘/\b(?:(?:https?|ftp):\/\/|www\.)[-a-z0-9+&@#\/%?=~_|!:,.;]*[-a-z0-9+&@#\/%=~_|]/i’, $string) ยาวยืดอย่าพิมพ์ผิดเชียว ผมก็ก๊อบเค้ามา แต่ตรวจ url ได้ถูกต้อง

ที่ทำตัวอย่างให้ดูสรุปคือ ในการเขียนโปรแกรมไม่มีอะไรที่ทำงานได้ดี 100% เต็ม ทำอย่างหนึ่งจะมีการแลกเปลี่ยนที่เท่าเทียม (รึเปล่า) ตามมาด้วยเสมอ อย่างตรวจ link แบบชุดที่ 6 จริง ๆ มันตรวจว่าเป็นลิงค์เว็บจริง ๆ มาได้หลายปีแล้ว แต่เว็บหลัง ๆ เน้นทำ SEO กับท้องถิ่นตามภาษาและประเทศมากขึ้นแทนที่จะใช้ภาษาอังกฤษอย่างเดียว ตอนนี้เลยต้องมาเขียนตัวตรวจสอบกันแบบยาว ๆ และปวดตับมากกกก

การที่กว่าจะได้งานที่สมบูรณ์ที่สุดไกล้ความสมบูรณ์แบบถึงต้องใช้พลังและความร่วมมือจากทุก ๆ คน และมีค่าใช้จ่ายและเวลาที่สูงมาก ผลคือ การลดค่าใช้จ่ายอย่าง

  • บอกมานิดเดียว น้องไปคิดต่อเอาเองนะ พี่มางานอื่น (พี่ครับ ผมต้องเขียน business plan ต้องมาคิดให้ว่าบริษัทพี่นี่ มันขายอะไร ต้องทำยัง บริการอะไรบ้าง และมันทำงานยังไง สุดท้ายก็ออกมาขาด ๆ เกิน ๆ )
  • ไม่จ้าง tester ครับ programmer เขียนเสร็จก็ต้องมาลองเอง เพราะว่าออกแบบและเขียนเองมากะมือ มันเลยจำติดอยู่ในสมองว่า ตรงนี้ต้องกรอกอะไร ตอนทดสอบ ก็เผลอทำแบบเดิม ทำมาให้กรอกตัวเลข ต้อนทดสอบก็ใส่ 1555, 5544, 444, 85 มัว ๆ ไป ตอนให้ user ทำลองใช้ มีคนใส่โง่ ๆ “100 บาท” เกิดอะไรขึ้น
    1. โปรแกรมก็เอา 100 บาท ไปใส่ในสูตร
      จำนวนบาท คูณจำนวน ก็ออกมาเป็น
      100บาท x 5 = ?
      แล้วก็บอกกลับมาว่า พ่องมึง คูณได้เหรอวะ แต่มันบอกมาแบบที่มีแต่โปรแกรมเมอร์ที่เข้าใจ แลัวฆ่าตัวตายไปต่อหน้าต่อตา
    2. บัญชีก็บอกว่า นี่ทำเสร็จแล้วเหรอ เทสแล้วแน่นะ
    3. คนเขียนเห็นก็อยากจะบอกว่า ข้างหลังใส่ label บาทให้ละ จะกรอกไปทำซากอะไร
    4. ทีนี้เกินอะไรขึ้นต่อไปในการประชุม
      • project manager ก็บอกว่านิดหนึ่งพี่ แก้ไม่ถึง 5 นาทีก็เสร็จแล้วครับ
      • programmer คิด มึงเคยถามกูยัง ทำไงต่อ ทำนานปะ แก้แล้วตรงไหนจะพังมั่ย แล้วอย่างอื่นมันจะทันป่าว
      • บัญชีของลูกค้าก็คิด ขี้เกียจเทสแน่ ๆ เมื่อไหร่จะได้ใช้
      • เซลล์ก็คิด ทำไม่ไม่เอาใบส่งสินค้าที่เขียนกับมือ เข้าเครื่องถ่ายเอกสาร แล้วได้รายงานออกมาเลย ไม่เสียเวลา เอาไปขายให้ที่ไหนมีแต่คนอยากซื้อ ทำไม่ไม่ยอมทำ จะได้ขายง่าย ๆ ซักที % จะได้เยอะ ๆ อุสาห์คิดให้ดี ๆ ไม่เข้าใจ
      • ลูกค้า ก็คิด รู้งี้ยอมจ่ายอีกนิดจ้างอีกเจ้า ยอมไม่ไปเที่ยวเมืองนอกก็ได้ จะได้ทำอย่างอื่นซะที
    5. จ้างมาแพง ต้องรีบ ๆ ทำงาน ให้ได้ function ผลคือไม่ได้ test งานจริง ๆ หรือให้มันใช้งานได้ง่าย อย่างงานที่เคยเจอต้องมีคนมา เอารูปถ่ายสินค้ามาตัดให้พอดีกับขนาดที่ใช้ในเว็บ ทั้ง ๆ ที่ ก็ถ่ายโดยกล้องเดิม ขนาดเดิม และมุมกล้องเดิมทุกวัน ทุกชิ้น ถ้ายอมให้เวลาเขียนโปรแกรมเพิ่มอีกนิด ก็แค่วางของที่เดิม กดถ่ายรูปแล้วโยนให้โปรแกรมมันตัดรูป เปลี่ยนขนาด แล้วเอาให้ลูกค้าดูเอง ประหยัดเวลาในชีวิตออกไปได้เยอะเลยแท้ ๆ แต่พี่รีบ พี่ไม่อยากจ่ายเงินเพิ่ม

มันก็เหมือนคำพูดที่ว่า ของดีไม่แพง นั้นละครับ ยอมจ่ายได้แค่ไหน คนขายก็ประมาณ ต่อกันอย่างนี้ ขอฟรีเลยมั๋ยพี่ ที่สำคัญคือ จะหาจุดสมดุลย์ได้ที่ไหน ถึงจะพอใจกันทั้งสองฝ่าย