Tag Archive validate

jQuery: upload แบบ ajax

ตัวอย่างการใช้ jQuery upload ไฟล์แบบ ajax

<!doctype html>
<html>

<head>
    <meta charset="utf-8">
    <title>jQuery: form > send file</title>
    <link href="../vendor/twbs/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet" type="text/css">
    <style>
        .progressbar {
            background: #c00000;
            clear: both;
            height: 10px;
            width: 0;
        }

        .progressLoaded {
            width: 50px;
        }

        .progressLoaded::after {
            content: " bytes";
        }

        .progressPercent {
            width: 50px;
        }

        .progressPercent::after {
            content: " %";
        }

        .progressTotal {
            float: left;
            width: 50px;
        }

        .progressTotal::after {
            content: " bytes";
        }

        .progressTotal::before {
            content: " of ";
        }
    </style>
</head>

<body>
    <h1>upload file with ajax</h1>
    <form action="values.php" class="form-horizontal" enctype="multipart/form-data" id="formA" method="post">
        <div class="form-group">
            <label class="col-sm-2 control-label" for="socialidI">หมายเลขบัตรประชาชน</label>
            <div class="col-sm-10">
                <input class="form-control" id="socialidI" maxlength="13" name="socialid" placeholder="หมายเลขบัตรประชาชน" type="number">
            </div>
        </div>
        <div class="form-group">
            <label class="col-sm-2 control-label" for="photoI">ภาพถ่าย</label>
            <div class="col-sm-10">
                <input class="form-control" id="photoI" name="photo" placeholder="upload file" type="file">
            </div>
        </div>
        <div class="form-group">
            <div class="col-sm-10 text-right">
                <button type="submit" class="btn btn-success">ส่งข้อมูล</button>
            </div>
        </div>
    </form>
    <div class="col-sm-12">
        <h4>Progress</h4>
        <div class="progressLoaded"></div>
        <div class="progressTotal"></div>
        <div class="progressPercent"></div>
        <div class="progressbar"></div>
    </div>
    <div class="col-sm-12" id="resultA"></div>
    <script src="../vendor/components/jquery/jquery.min.js"></script>
    <script>
        function xhrProgress(xhr) {
            if (xhr.upload) {
                // For handling the progress of the upload
                xhr.upload.addEventListener('progress', function (e) {
                    if (e.lengthComputable) {
                        $('.progressTotal').html(e.total);
                        $('.progressLoaded').html(e.loaded);

                        percentComplete = parseInt((e.loaded / e.total * 100), 10);
                        $('.progressPercent').html(percentComplete);
                        $('.progressbar').css("width", percentComplete + '%');
                    }
                }, false);
            }
            return xhr;
        }

        $(function () {

            var formA = $('#formA');

            formA.submit(function (event) {
                event.preventDefault();

                $.ajax({
                    "beforeSend": function (jqXHR, settings) {
                        /* แยกตัวแปรไว้ตรวจสอบข้อมูล */
                        var params = settings.data;

                        if (settings.data.get('socialid') == '') {

                            jqXHR.abort();
                            alert('กรุณากรอกหมายเลขบัตรประชาชน');

                            return false;
                        }

                        if (settings.data.get('photo').name == '') {

                            jqXHR.abort();
                            alert('กรุณาอัพโหลดรูปภาพ');

                            return false;
                        }

                    },
                    "contentType": false,
                    "data": new FormData(formA[0]),
                    "method": "POST",
                    "processData": false,
                    "success": function (data, textStatus, jqXHR) {
                        $('#resultA').html(data);
                    },
                    "url": "values.php",
                    "xhr": function () {
                        return xhrProgress($.ajaxSettings.xhr());
                    },

                });

            });

        });
    </script>
</body>

</html>

ไฟล์ที่รอรับข้อมูล

<?php
echo 'FILE<pre>', print_r($_FILES, true), '</pre>';
echo 'GET<pre>', print_r($_GET, true), '</pre>';
echo 'POST<pre>', print_r($_POST, true), '</pre>';

วิธีนี้ใช้ความสามารถใหม่ FormData ที่ใช้กับ browser เก่าแก่กว่า Internet Explorer 10 หรือ Edge ไม่ได้ ดูเพิ่มเติม

jQuery: ส่ง form แบบ ajax ชั้นสูง

ก่อนที่จะใช้ jQuery ส่งข้อมูลแบบ ajax ออกไป อาจจะใช้ javascript ทำงานเบื้องต้นก่อนได้เช่น การตรวจสอบข้อมูล (validation) ว่า user ได้ทำการกรอกข้อมูลตามที่จำเป็นครบรึเปล่า หรือนำข้อมูลออกไปจากแบบฟอร์ม โดยที่ไม่ต้องไปทำในฝั่ง server

ใน jQuery Ajax สามารถทำได้โดยการระบุ “beforeSend” ตาม code ตัวอย่าง

$.ajax({
    "beforeSend": function(jqXHR, settings) {

        /* ใส่ตัวแปรเข้าไปเพิ่ม */
        settings.data += '&ajax=true';

        /* แยกตัวแปรไว้ตรวจสอบข้อมูล */
        var params = new URLSearchParams(settings.data);

        /* บังคับกรอกข้อมูล */
        if (params.get('way') == 'socialid' && params.get('socialid') == '') {

            jqXHR.abort();
            alert('กรุณากรอกหมายเลขบัตรประชาชน');

            return false;
        } else if (params.get('way') == 'phone' && params.get('phone') == '') {

            jqXHR.abort();
            alert('กรุณากรอกหมายเลขโทรศัพท์');

            return false;
        }

        if (params.get('amount') == '') {

            jqXHR.abort();
            alert('กรุณากรอกจำนวนเงิน');

            return false;
        }

        /* เอาข้อมูลที่ไม่ต้องการส่งออก */
        settings.data = RemoveParameterFromUrl(settings.data, 'way');
        settings.data = RemoveParameterFromUrl(settings.data, 'way');
        if (params.get('way') == 'socialid') {
            settings.data = RemoveParameterFromUrl(settings.data, 'phone');
        } else {
            settings.data = RemoveParameterFromUrl(settings.data, 'socialid');
        }

    },
    "data": formA.serialize(),
    "method": "POST",
    "success": function(data, textStatus, jqXHR) {
        $('#resultA').html(data);
    },
    "url": "values.php",
});

เราจะดูข้อมูลที่รวบรวมมาได้ใน object settings.data และสามารถต่อ string เพิ่มเข้าไปได้เหมือนการต่อ string

settings.data += '&ajax=true';

การที่จะแยกข้อมูลออกมาสามารถใช้

var params = new URLSearchParams(settings.data);

แบ่งข้อมูลออกมาเป็น array เพื่อใช้ตรวจสอบข้อมูลหรือจะนำไปใช้ในการเปลี่ยนแปลงข้อมูล เช่นเดียวกันก็สามารถ delete ลบข้อมูลที่ไม่ได้การออกไปได้โดยใช้ function

function RemoveParameterFromUrl(url, parameter) {
    return url.replace(new RegExp('^([^#]*\?)(([^#]*)&)?' + parameter + '(\=[^&#]*)?(&|#|$)'), '$1$3$5').replace(/^([^#]*)((\?)&|\?(#|$))/, '$1$3$4');
}

ตัวอย่าง form เขียนโดยยกกรณีโอนเงินโดยใช้ พร้อมเพย์ (PromptPay) ที่ user จะเลือกได้ว่าจะโอนเงินโดยใช้ บัตรประชาชน หรือหมายเลขโทรศัพท์ของผู้รับแทนที่จะใช้หมายเลขบัญชี

<!doctype html>
<html>

<head>
    <meta charset="utf-8">
    <title>jQuery: Advance Form Send</title>
    <link href="../vendor/twbs/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet" type="text/css">
</head>

<body>
    <h1>พร้อมเพย์ (PromptPay)</h1>
    <form action="values.php" class="form-horizontal" id="formA" method="post">
        <div class="form-group">
            <label class="col-sm-2 control-label">โอนเงินด้วย</label>
            <div class="col-sm-10">
                <div class="radio">
                    <label>
                        <input checked name="way" type="radio" value="socialid"> หมายเลขบัตรประชาชน
                    </label>
                </div>
                <div class="radio">
                    <label>
                        <input name="way" type="radio" value="phone"> หมายเลขโทรศัพท์
                    </label>
                </div>
            </div>
        </div>
        <div class="form-group">
            <label class="col-sm-2 control-label" for="socialidI">หมายเลขบัตรประชาชน</label>
            <div class="col-sm-10">
                <input class="form-control" id="socialidI" maxlength="13" name="socialid" placeholder="หมายเลขบัตรประชาชน" type="number">
            </div>
        </div>
        <div class="form-group">
            <label class="col-sm-2 control-label" for="phoneI">หมายเลขโทรศัพท์</label>
            <div class="col-sm-10">
                <input class="form-control" id="phoneI" maxlength="11" name="phone" placeholder="หมายเลขโทรศัพท์" type="tel">
            </div>
        </div>
        <div class="form-group">
            <label for="amount" class="col-sm-2 control-label">จำนวนเงิน</label>
            <div class="col-sm-10">
                <div class="input-group">
                    <input class="form-control" id="amount" max="5000" min="0" name="amount" placeholder="จำนวนเงิน" type="number">
                    <div class="input-group-addon">&#3647;</div>
                </div>
            </div>
        </div>
        <div class="form-group">
            <div class="col-sm-10 text-right">
                <button type="submit" class="btn btn-success">โอนเงิน</button>
            </div>
        </div>
    </form>
    <div class="col-sm-12" id="resultA"></div>
    <script src="../vendor/components/jquery/jquery.min.js"></script>
    <script>
        function RemoveParameterFromUrl(url, parameter) {
            return url.replace(new RegExp('^([^#]*\?)(([^#]*)&)?' + parameter + '(\=[^&#]*)?(&|#|$)'), '$1$3$5').replace(/^([^#]*)((\?)&|\?(#|$))/, '$1$3$4');
        }

        $(function () {
            var formA = $('#formA');

            formA.submit(function (event) {
                event.preventDefault();

                $.ajax({
                    "beforeSend": function (jqXHR, settings) {

                        /* ใส่ตัวแปรเข้าไปเพิ่ม */
                        settings.data += '&ajax=true';

                        /* แยกตัวแปรไว้ตรวจสอบข้อมูล */
                        var params = new URLSearchParams(settings.data);

                        /* บังคับกรอกข้อมูล */
                        if (params.get('way') == 'socialid' && params.get('socialid') == '') {

                            jqXHR.abort();
                            alert('กรุณากรอกหมายเลขบัตรประชาชน');

                            return false;
                        } else if (params.get('way') == 'phone' && params.get('phone') == '') {

                            jqXHR.abort();
                            alert('กรุณากรอกหมายเลขโทรศัพท์');

                            return false;
                        }

                        if (params.get('amount') == '') {

                            jqXHR.abort();
                            alert('กรุณากรอกจำนวนเงิน');

                            return false;
                        }

                        /* เอาข้อมูลที่ไม่ต้องการส่งออก */
                        settings.data = RemoveParameterFromUrl(settings.data, 'way');
                        settings.data = RemoveParameterFromUrl(settings.data, 'way');
                        if (params.get('way') == 'socialid') {
                            settings.data = RemoveParameterFromUrl(settings.data, 'phone');
                        } else {
                            settings.data = RemoveParameterFromUrl(settings.data, 'socialid');
                        }

                    },
                    "data": formA.serialize(),
                    "method": "POST",
                    "success": function (data, textStatus, jqXHR) {
                        $('#resultA').html(data);
                    },
                    "url": "values.php",
                });
            });
        });
    </script>
</body>

</html>

และฝั่ง server side ที่ควรจะมีการ validation ตรวจสอบข้อมูลซ้ำอีกครั้งเพื่อความมั่นใจ แต่ตัวอย่างนี้จะแสดงข้อมูลที่ทางฝั่ง server ได้รับเท่านั้น เพื่อให้เห็นการ edit แก้ข้อมูลที่ส่งไป

<?php
echo 'GET<pre>', print_r($_GET, true), '</pre>';
echo 'POST<pre>', print_r($_POST, true), '</pre>';

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

มี 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 งานจริงๆ หรือให้มันใช้งานได้ง่าย อย่างงานที่เคยเจอต้องมีคนมา เอารูปถ่ายสินค้ามาตัดให้พอดีกับขนาดที่ใช้ในเว็บ ทั้งๆที่ ก็ถ่ายโดยกล้องเดิม ขนาดเดิม และมุมกล้องเดิมทุกวัน ทุกชิ้น ถ้ายอมให้เวลาเขียนโปรแกรมเพิ่มอีกนิด ก็แค่วางของที่เดิม กดถ่ายรูปแล้วโยนให้โปรแกรมมันตัดรูป เปลี่ยนขนาด แล้วเอาให้ลูกค้าดูเอง ประหยัดเวลาในชีวิตออกไปได้เยอะเลยแท้ๆ แต่พี่รีบ พี่ไม่อยากจ่ายเงินเพิ่ม

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