Site icon PlusMagi's Blog By Pitt Phunsanit

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

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

<?php

$strings = [
    '!@#$%^&*()_-+="{}[]\+:<>,./?',
    'Apple Inc.',
    'email.gmail.com',
    'email.job.co.th',
    'email@gmail.com',
    'email@job.co.th',
    '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@gmail.com 1 0 1 0 1 0 0
6 email@job.co.th 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 กับท้องถิ่นตามภาษาและประเทศมากขึ้นแทนที่จะใช้ภาษาอังกฤษอย่างเดียว ตอนนี้เลยต้องมาเขียนตัวตรวจสอบกันแบบยาวๆ และปวดตับมากกกก

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

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

Exit mobile version