สามจีไทย ทำไมมันใช้ยากนักหนา

สิ้นสุดการรอคอยกันแล้วกับสามจีประเทศไทยตอนนี้เรามีให้ใช้งานได้แล้วทุกค่าย ซึ่งก็เป็นที่น่ายินดีเสียยิ่งนักสำหรับประเทศไทยทั้งๆ ที่ประเทศรอบข้างเรา ไปกันไกลลิบแล้วเราจะเริ่มตอนนี้ก็ยังไม่สาย มองโลกในแง่ดีซะว่าดีกว่ายังไม่เริ่ม จริงไหม :)

มาตรฐานสามจีของประเทศไทยมีสองระบบคือ CDMA สำหรับค่าย hutch เดิมหรือตอนนี้กลายเป็น Truemove H ไปแล้ว กับระบบ HSPA ที่เป็นระบบของค่ายอื่นๆ ที่ใช้งานกันอยู่แล้วก็เป็นระบบที่มีอยู่ในโทรศัพท์มือถือแทบทุกเครื่องที่ใช้งานสามจีได้อยู่แล้ว

แต่ปัญหามันไม่ใช่แค่นี้สิ มาตรฐานโลกสามจีเขาใช้งานกันที่ความถี่ 900MHz กับ 2100MHz แต่เนื่องจากมีแมวมาขวางโลกอยู่ทำให้การประมูลคลื่น 2100MHz เมื่อปี 2553 ไม่สามารถทำได้ ดึงเรื่องมาจนปี 2555 ก็ยังคงไม่เริ่มการประมูลเสียที ทำให้ผู้ให้บริการแต่ละรายต้องใช้วิธีซิกแซกใช้ความถี่อันน้อยนิดของตัวเองมาให้บริการสามจี สำหรับ AIS นั้นไม่มีปัญหาอยู่แล้วเพราะเดิมได้ให้บริการมือถือบนความถี่ 900MHz ก็เลยสามารถให้บริการสามจีบนความถี่นี้ได้ทันที แต่สำหรับ Truemove และ Dtac เดิมทีได้ให้บริการบนความถี่ 1800MHz แต่พอมาใช้งานสามจีแล้ว จำเป็นต้องเปลี่ยนมาใช้ที่ 850MHz แทน เนื่องจากอุปกรณ์ที่รองรับ HSPA 1800MHz มีไม่มาก

ดูเหมือนว่าปัญหามันจะจบแล้ว แต่มันยังไม่จบ เนื่องจากว่า มือถือทุกวันนี้รองรับระบบ GSM ที่ความถี่ 850/900/1800/1900 กันครบอยู่แล้ว แต่สิ่งที่เราต้องสนใจคือ UMTS เพื่อที่จะใช้งานสามจีในระบบ HSPA ซึ่งส่วนใหญ่จะสนับสนุนกันที่ 900/2100 ถ้าเป็นรุ่นกลางๆ ก็ได้ 1900 เพิ่มขึ้นมา แต่ถ้าจะเอา 850/900/1900/2100 ละก็ เป็นรุ่นใหญ่เท่านั้น อย่างเช่น Galaxy S2 หรือ iPhone4 ขึ้นไป ซึ่งราคามันก็แตะๆ สองหมื่นทั้งนั้น สำหรับชาวรากหญ้าอย่างเราคงไม่มีเงินมากพอสำหรับมือถือเครื่องละเกือบๆ สองหมื่น แต่อยากสัมผัสสามจีบ้างเวลาที่จะเปลี่ยนมือถือใหม่ก็ต้องดูด้วยว่ามันรองรับหรือเปล่า

สำหรับเพื่อนๆ ที่ใช้ซิมของ AIS หยิบเครื่องไหนในประเทศไทยก็ได้ มากกว่า 90% ใช้ได้หมด แต่ถ้าใช้ Truemove หรือ Dtac อันนี้คงต้องดูให้มากละว่าจะเอาเครื่องไหน วิธีการดูถ้าหากเราไม่มีกล่องเดิมของมัน เราก็คงต้องใช้วิธีเปิดเครื่องแล้วค้นหาเครือข่าย ลองมาดูตัวอย่างจากรูปข้างล่างเลย

ถ้าเจอ 52000 แบบนี้แสดงว่าสนับสนุน 850MHz

ถ้าไม่เจอจะใช้งานได้แค่ 900MHz

เครื่องที่ทดสอบเป็น Galaxy Cooper ที่ซื้อมาจากศูนย์ Samsung ที่สนับสนุนความถี่ 900/2100 และ Galaxy Cooper เหมือนกันที่ซื้อมาจากศูนย์ Dtac ที่สนับสนุนความถี่ 850/2100 ถ้าหากเราทดลองค้นหาเครือข่ายแล้วเจอเครือข่าย 52000 ก็แสดงว่าเครื่องเราสนับสนุนความถี่ 850MHz ด้วย ทีนี้เราก็สามารถใช้งานสามจีของ Truemove และ Dtac ได้อย่างสบายใจ แต่จะไม่สามารถใช้งานของ AIS ได้นะ

หมายเหตุ เครือข่าย 52000 คือ Truemove H นะ ครอบคลุมทั่วประเทศไทย

Posted in blog | Tagged , , | Leave a comment

แก้ขนาด facebook comment

สำหรับคนที่ทำเว๊ปแบบ responsive แล้วใช้ facebook comment แล้ว ปัญหาใหญ่คือ เมื่อแสดงผลในมือถือหรือถ้า block ที่เราออกแบบไว้เปลี่ยนขนาด คงจะมีปัญหาเรื่อง block ของ facebook comment ไม่ปรับขนาดตาม วิธีแก้ปัญหาง่ายๆ เลย เราก็แค่เพิ่ม css นี้เข้าไป แค่นี้ก็ใช้งานได้แล้ว

.fb-comments, .fb-comments iframe[style] {
   width: 100% !important;
}

แค่นี้ขนาดของ facebook comment ก็เปลี่ยนไปตามขนาดหน้าจอแล้ว สบายๆ เลย :)

Posted in blog | Tagged , , | Leave a comment

บทที่ 10 การติดต่อฐานข้อมูล MySQL

หลังจากบทที่แล้วเราติดตั้งฐานข้อมูล MySQL เสร็จเรียบร้อยแล้ว และทำให้ใช้งานร่วมกับ PHP ได้แล้ว ทีนี้เราจะเริ่มใช้งานมันได้ยังไง เดี๋ยวมาดูกันครับ

การติดต่อ MySQL จาก PHP จากที่เคยทำมามันก็มี 2 วิธีหลักๆ คือ ติดต่อโดยตรงโดยผ่าน Native Driver ที่มาพร้อมกับ PHP เลย กับอีกวิธีคือใช้ PDO (PHP Data Object) จริงๆ ผมไม่อยากเรียก PDO ว่าเป็น Native Driver เท่าไหร่ เพราะมันติดต่อฐานข้อมูลได้หลายแบบเหลือเกิน แต่ในเว๊ปของ MySQL บอกไว้แบบนั้นงะ

ลำดับการทำงานของทั้งสองขั้นตอนจะคล้ายๆ กันคือ

      สร้างการเชื่อมต่อกับ MySQL
      ติดต่อกับฐานข้อมูลที่จะใช้งาน
      ปิดการเชื่อมต่อกับ MySQL

ผมจะอธิบายรายละเอียดเฉพาะแบบแรกนะครับ ส่วนแบบที่สองจะให้ตัวอย่างแล้วอธิบายนิดหน่อย เพราะถ้าเข้าใจเรื่อง OOP แล้ว PDO มันไม่ยากเลย บางทีอ่านแค่ Class กับ Method ก็เอาไปใช้งานได้แหละ อีกอย่างเซิร์ฟเวอร์ที่เราเช่าบางทีไม่เปิดใช้งาน PDO ก็มี แอบเศร้าเลย

ขั้นตอนที่ 1 เชื่อมต่อฐานข้อมูล

ทำได้โดยใช้ฟังก์ชั่น mysql_connect โดยค่าทีต้องส่งจะมีสามค่าคือ

  • string Host (IP ของ MySQL ในกรณีที่อยู่ในเครื่องเดียวกันให้ใส่ localhost)
  • string MySQL username
  • string MySQL password

เขียนได้ตามตัวอย่างนี้

<?php
   mysql_connect("host", "mysql_username", "mysql_password");
?>

ขั้นตอนที่ 2 ติดต่อกับฐานข้อมูลที่เราจะใช้งาน

โดยใช้คำสั่ง mysql_select_db โดยมีค่าที่ต้องใ่ส่คือ

  • string ชื่อฐานข้อมูล
  • link identifier (จะใส่หรือไม่ใส่ก็ได้)

เขียนได้ตามตัวอย่างนี้

<?php
   mysql_select_db("database", [$link]);
?>

ขอเน้นนิดนึง

ตรงที่ผมเขียนว่า $link ผมใส่ bucket ไว้หมายความว่า จะใส่หรือไม่ใส่ก็ได้ ใส่แล้วมันก็ไม่ได้ทำงานเร็วขึ้นหรือดีขึ้น แต่ผมแนะนำให้ใส่ทุกครั้ง และให้ทำจนเป็นนิสัยเลย... ทำไมอ่า เมื่อกี้ยังบอกว่า "ไม่ใส่ก็ได้" เลย คืองี้ครับ ถ้าหากเราทำงานกับฐานข้อมูลหลายๆ ตัว และอยู่คนละโฮส เอาง่ายๆ ถ้าต้องการติดต่อฐานข้อมูลในเครื่องเรา และเครื่องที่ทำงาน เราต้องเขียนการเชื่อมต่อสองครั้ง แล้วถ้าเราต้องการ query ล่ะ จะรู้ได้ไงว่าเอามาจากไหน มันก็เลยต้องมีตัวเชื่อมต่อเพื่อบอกว่าเราจะเอาจากเครื่องของเรา หรือจากเครื่องที่ทำงานไงครับ...

แต่ถ้าเกิดเหตุการณ์ที่ต้องเอาฐานข้อมูลจากสองที่คนละโฮส เมื่อก่อนผมก็ทำแบบที่ผมว่าข้างบน แต่เดี๋ยวนี้เขียน XML นิดๆ หน่อยๆ สะดวกกว่าครับ อาจไม่เร็วเท่าต่อโดยตรง แต่ปลอดภัยกว่า

ขั้นตอนที่ 3 ปิดการเชื่อมต่อ

ในเมื่อมีการเชื่อมต่อแล้วก็ต้องทำการปิดการเชื่อมต่อด้วยสิ ถ้าหากรอ session ใน MySQL หมดแล้วให้มันตัดการเชื่อมต่อเองเดี๋ยวหน่วยความจำของเซิร์ฟเวอร์จะหมดเกลี้ยงเสียก่อน ถ้าหากเราใช้งานแค่คนเดียวก็ไม่เท่าไหร่ แต่เข้ามาสัก 1000 คน 1000 connections 1000 processes ถ้าไม่คืนหน่วยความจำให้หลังจากใช้งานเสร็จหน่วยความจำเท่าไหร่ก็ไม่พออ่ะครับ วิธีการคืนหน่วยความจำก็ง่ายๆ เลย

<?php
   mysql_close([$link]);
?>

ผมใส่ bucket อีกแล้ว คำสั่งนี้จะมีตัวที่เชื่อมต่อส่งเข้าไปด้วยหรือไม่ก็ได้ ถ้าหากเราส่งตัวเชื่อมต่อเข้าไป มันก็จะปิดตัวเชื่อมต่อตัวนั้น แต่ถ้าไม่ใส่เข้าไป มันจะปิดตัวเชื่อมต่อตัวล่าสุดที่ทำการสร้างการเชื่อมต่อ ... งง ไหมเนี่ย เอาเป็นว่า อย่างที่บอกอ่ะครับ ควรกำหนดตัวเชื่อมต่อให้เป็นนิัสัยเลย เวลาปิดจะได้กำหนดไปเลยว่าจะปิดตัวไหน

ทีนี้ลองเอามาใช้งานจริงกัน

ในฐานข้อมูล MySQL จะมีฐานข้อมูลชื่อ mysql อยู่แล้ว เราก็ลองเรียกดูข้อมูลผ่าน PHP ล่ะกัน แต่ อย่าไปแก้ไขอะไรมันนะครับ เดี๋ยวเจ้งเอา

<?php
   $connect = mysql_connect("localhost", "root", "cmdevhub") or die("ติดต่อ MySQL ไม่ได้"); // เก็บการเชื่อมต่อไว้ที่ตัวแปร $connect
   mysql_select_db("mysql", $connect) or die("ติดต่อฐานข้อมูลไม่ได้"); // ทำการติดต่อฐานข้อมูล

   $SQLCom = "select * from user"; // สร้างคำสั่ง SQL เก็บไว้ในตัวแปรชื่อ $SQLCom
   $query = mysql_query($SQLCom, $connect); // ทำการคิวรี่
   $rs = mysql_fetch_assoc($query); // เอาออกมาแค่แถวเดียวก็พอ
   print_r($rs); // พิมพ์ออกหน้าจอ
   mysql_close($connect); // ปิดการเชื่อมต่อ
?>

ผลลัพท์ที่ได้ก็จะเป็นแบบนี้



ถ้าหากได้ผลลัพท์ประมาณนี้แสดงว่าคุณเชื่อมต่อกับฐานข้อมูลได้แล้วและพร้อมจะเขียนโปรแกรมที่ใช้งานจริงได้แล้วทันที (ง่ายไหม) ส่วนคำสั่งอื่นๆ ยังไม่ต้องสนใจครับ เอาไว้มาคุยรายละเอียดกันทีหลัง

การเชื่อมต่อฐานข้อมูลเราต้องทำการเชื่อมต่อทุกครั้งในทุกๆ หน้าที่มีการเชื่อมต่อกับฐานข้อมูล (งงไหมเนี่ย) ตีความง่ายๆ คือ ถ้าหากมีไฟล์ในเว๊ปของเรา 100 ไฟล์ เราก็ต้องเขียนการเชื่อมต่อทั้ง 100 ไฟล์เลย เราขยันอยู่แล้ว ไม่ใช่ปัญหา แต่ปัญหาจะเกิดขึ้นทันทีเมื่อ เราเอางานของเราไปไว้ที่อื่น ตัวอย่างง่ายๆ ก็คือการอัพโหลไปไว้ในโฮส แน่นอนฐานข้อมูลต้องไม่ใช่ชื่อเดิม username และ password ก็ต้องเปลี่ยน ทีนี้เราก็ต้องไล่เปลี่ยนทั้ง 100 ไฟล์เลย สนุกสนานแน่นอน...

เพราะงั้นเรามาทำให้ชีวิตเราง่ายขึ้นดีกว่า จาก บทที่ 8 เรื่องฟังก์ชั่น (ดูจากข้างๆ หรือจิ้มที่ลิงค์เลย) เราสามารถเขียนฟังก์ชั่นครั้งเดียวแล้วเรียกใช้กี่ทีก็ได้ โอ้ว ทำไมช่างสะดวกเช่นนี้

ผมจะใช้วิธีสร้างไฟล์ขึ้นมาไฟล์หนึ่งเก็บฟังก์ชั่นไว้แล้วถ้าต้องการติดต่อฐานข้อมูลก็แค่ include เข้าไป (จะใช้ require ก็ได้ไม่ว่ากัน) จากนั้นก็เรียกฟังก์ชั่นติดต่อฐานข้อมูลเอา เท่านี้ก็เสร็จแล้ว ตัวอย่างตามนี้เลยครับ

<?php
   // ไฟล์ชื่อ function.inc.php

   function connect() {
      global $connect;
      $connect = mysql_connect("localhost", "root", "cmdevhub") or die("ติดต่อ MySQL ไม่ได้");
      mysql_select_db("mysql", $connect) or die("ติดต่อฐานข้อมูลไม่ได้");
   }

   function disconnect() {
      global $connect;
      mysql_close($connect);
   }
?>

ไฟล์ function.inc.php สร้างไว้สำหรับ include อย่างเดียว มี 2 ฟังก์ชั้นคือ connect() และ disconnect()

<?php
   // ไฟล์ชื่อ testmysql.php

   require_once('function.inc.php'); // อย่าลืมเอาไฟล์นี้ไว้ที่เดียวกันนะครับ
   connect();
   $SQLCom = "select * from user";
   $query = mysql_query($SQLCom, $connect);
   $rs = mysql_fetch_assoc($query);
   print_r($rs);
   disconnect();
?>

ผลลัพท์ที่ได้ก็เหมือนเดิมทุกอย่าง แต่ถ้าเราย้ายโฮสปุ๊ป ก็แค่ไปแก้ไข username และ password ในไฟล์ function.inc.php เท่านั้นเอง ไฟล์อื่นๆ เราไม่ต้องไปยุ่งอะไรกับมันเลย ชีวิตสบายขึ้นอีกเยอะเลย หุหุ

ทำให้ดูเป็นมืออาชีพขึ้นหน่อยไหม

ในเมื่อ PHP สามารถเขียนเป็น OO ได้ (Object Oriented) ทำไมเราจะไม่เขียนให้มันเป็น OO หน่อยล่ะ หุหุ (เนื่องจากมันไม่มีอะไรมาก ผมไม่เอา Class Diagram ลงเนอะ มีแค่ 2 Class เอง)

เพื่อให้ (ดูเหมือน) เป็นมืออาชีพ เวลาผมเขียนโปรแกรมผมชอบที่จะแยกไฟล์สำหรับเก็บ Constant Variable, Class ไว้แยกกัน ก็เอาตามนี้เลยครับ

<?php
   // ไฟล์ชื่อ user.inc.php

   define("DBHOST", "localhost");
   define("DBUSER", "root");
   define("DBPASS", "cmdevhub");
   define("DBNAME", "mysql");
?>

<?php
   // ไฟล์ชื่อ class.inc.php

   require_once("user.inc.php");

   class mysql {
      private $connect;
      private $query;
      private $result;

      public function connect() {
         if(!$this->connect = mysql_connect(DBHOST, DBUSER, DBPASS)) {
            echo get_class($this) . "::connect() Error Connect MySQL " . mysql_error();
            return false;
         }
         else {
            if(!mysql_select_db(DBNAME, $this->connect)) {
               echo get_class($this) . "::connect Error Select Database " . mysql_error();
               mysql_query("set names utf8", $this->connect);
            }
         }
      }

      public function query($command) {
         if (!$this->connect) {
            $this->connect();
         }
         if (!$this->query = mysql_query($command, $this->connect)) {
            echo get_class($this) . "::query() SQL Command invalid " . mysql_error();
         }
         else {
            return $this->query;
         }
      }

      public function fetch_assoc($query = '') {
         if ($query == NULL) {
            $result = mysql_fetch_assoc($this->query);
         }
         else {
            $result = mysql_fetch_assoc($query);
         }

         if (is_null($result)) {
            echo get_class($this) . "::fetch_assoc() Error fetch result";
         }
         else {
            return $result;
         }
      }

      public function num_rows($query = '') {
         if ($query == NULL) {
            return mysql_num_rows($this->query);
         }
         else {
            return mysql_num_rows($query);
         }
      }

      function __destruct() {
         if($this->connect) {
            mysql_close($this->connect);
         }
      }
   }
?>

ไฟล์นี้ผมไม่ขออธิบายเนอะ ไว้ค่อยคุยกันวันหลัง แต่เป็นการเชื่อมต่อฐานข้อมูลที่ผมใช้งานจริงๆ อยู่อ่ะ (เอาไปใช้ได้นะ)

วิธีการใช้งานก็ง่ายๆ แบบนี้เลยครับ

<?php
   require_once("class.inc.php");

   $mysql = new mysql();
   $SQLCom = "select * from user";
   $mysql->query($SQLCom);
   $rs = $mysql->fetch_assoc();
   print_r($rs);
?>

ง่ายใช่ไหมครับ ตอนนี้เราโยนทุกอย่างให้เป็นหน้าที่ของคลาส mysql ส่งคำสั่งไปคิวรี่โดยไม่ต้องสร้างการเชื่อมต่อ โดยเมธอด query จะทำการตรวจสอบเองว่ามีการสร้างการเชื่อมต่อมาแล้วหรือยัง แล้วพอจบหน้าก็ไม่ต้องทำการตัดการเชื่อมต่อ destructor จะตัดการเชื่อมต่อเองโดยอัตโนมัติ (สบายเลย)

Posted in php, tutorial | Tagged , , | Leave a comment

บทที่ 9 ติดตั้ง MySQL

หลังจาก 8 บทแรกที่ผมเขียนไว้เมื่อชาติปางก่อน ผมก็ไม่ได้เขียนอะไรเกี่ยวกับ PHP อีกเลย รวมเวลาน่าจะเกินครึ่งปีแล้วล่ะ

ถ้าเราจะเขียน PHP หรือโปรแกรมอะไรก็แล้วแต่ การเก็บข้อมูลเป็นอะไรที่สำคัญพอๆ กับ logic ของโปรแกรมเลย ถ้าหากโปรแกรมสามารถประมวลผลได้อย่างดี ทำงานได้ตรงตามความต้องการทุกอย่าง แต่ถ้าหากเราต้องการเก็บผลลัพธ์ไว้ล่ะ เมื่อก่อนตอนที่ผมเขียน C++ บน DOS จนมาถึง perl และช่วงที่เขียน PHP ใหม่ๆ วิธีการเก็บข้อมูลที่ง่ายที่สุดคือ text file นี่แหละ ซึ่งมันก็ง่ายจริงๆ fopen, fclose ก็จบ ใช้เครื่องหมาย comma คั่นระหว่างข้อมูล (field) มันก็ทำงานได้ดีกับข้อมูลจำนวนไม่มากแต่ถ้าหากข้อมูลมีจำนวนมากขึ้นล่ะ จะเริ่มมีปัญหาขึ้นมาทันทีเลยทั้งเรื่องขนาดของไฟล์ที่เก็บ ความเร็ว และการเขียนข้อมูลพร้อมๆ กันในกรณีที่ใช้ไฟล์ร่วมกัน วิธีการแก้ปัญหาที่ง่ายที่สุดคือ เปลี่ยนไปใช้ฐานข้อมูลซะ

ฟังดูเหมือนง่าย แต่มันก็ง่ายจริงๆ ข้อดีของ PHP อย่างหนึ่งคือ มันสามารถติดต่อกับฐานข้อมูลได้หลายชนิดมากๆ หรือถ้าหากไม่รู้ว่าจะใช้ฐานข้อมูลอันไหน ก็เขียน PDO ไปเลย (อันนี้ค่อยคุยกันทีหลัง) สำหรับฐานข้อมูลที่นิยมสำหรับ PHP ก็คงหนีไม่พ้น MySQL

ข้อดีของ MySQL คือ มันฟรี แล้วสามารถใช้งานได้ในหลายๆ ระบบปฎิบัติการ (multi platform) แต่ข่าวร้่ายนิดๆ หลังจากโดนซื้อโดย SUN MySQL ที่ฟรีจะเหลือแค่ Community ซึ่งความสามารถอาจน้อยกว่าตัวที่ขายกัน แต่ก็ไม่ต้องห่วง แค่นี้ก็เพียงพอแล้วจริงๆ คือ ไม่ต้องไปสนใจมันหรอก อันไหนฟรีเราก็ใช้ไปเหอะ เนอะ

อันนี้แอบแทรกนิดหน่อย จริงๆ แล้วฐานข้อมูลที่ควรจะรู้อีกสองคือ SQLite กับ postgreSQL สองตัวนี้ก็ฟรีเหมือนกัน โดยเฉพาะ SQLite หากงานไม่ใหญ่มาก ผมแนะนำตัวนี้เลย สะดวก รวดเร็ว แถมประสิทธิภาพยังดีกว่าใช้ text file

วิธีการติดตั้ง MySQL (สำหรับท่านที่ลงแบบแยกเท่านั้นนะ

ก่อนอื่นเลยก็เข้าไปที่ www.mysql.com แล้วเลือกไปที่ download จากนั้นเลือก Windows MSI Installer ก่อนที่จะโหลดจำเป็นต้องลงทะเบียนก่อนอันนี้ไม่ยากเท่าไหร่ ทำไม่กี่ขั้นตอนก็เสร็จแล้วล่ะครับ


ในขั้นตอนการติดตั้งก็กด next ไปเรื่อยๆ ตามสไตล์การติดตั้งโปรแกรมของคนไทย (ที่ไม่ค่อยอ่านเท่าไหร่ ผมก็เป็นหนึ่งในนั้น)

หลังจากติดตั้งเสร็จให้ทำการตั้งค่า MySQL ทันที

ทำการเลือก standard configuration

ติดตั้ง MySQL ให้เป็น Service ตัวหนึ่งของ Windows เราจะได้ไม่ต้องสั่งให้ MySQL ทำงานทุกครั้งที่เริ่ม Windows ใหม่ แต่ถ้าหากเครื่องไม่แรงมาก และนานๆ ใช้ MySQL ก็เอาเครื่องหมาย ถูก หน้าช่อง Launch the MySQL automatically ออกไป แต่ก็ต้องมาสั่ง start ทุกครั้งที่จะใช้งาน MySQL

อย่าลืมกำหนดรหัสผ่านของ MySQL ด้วยนะครับ

เสร็จแล้ว....

หลังจากติดตั้ง MySQL เสร็จ เราจะยังไม่สามารถใช้งาน MySQL ร่วมกับ PHP ได้ทันทีต้องก๊อปปี้ไฟล์ libmysql.dll ที่อยู่ใน php ไปไว้ใน Windows/System32 ก่อน



แล้วก็ไปเปิดใช้งาน MySQL โดยแก้ไฟล์ php.ini ที่อยู่ใน directory php นำเครื่องหมาย ; หน้า extension=php_mysql.dll ออกไปซะ (จะเอา mysqli ออกด้วยก็ได้ไม่ผิดกติกา)

จากนั้นทำการ restart apache โดยกดปุ่มเขียวตรง task bar ด้านล่าง

แค่นี้ก็สามารถใช้งาน MySQL กับ PHP ได้แล้ว ทดลองตรวจสอบได้โดยรัน phpinfo()

Posted in php, tutorial | Tagged , , | Leave a comment

บทที่ 8 ฟังก์ชั่น

ปกติแล้วโปรแกรมทุกๆ โปรแกรม จะทำงานจากบนลงล่าง และประมวลผลจากซ้ายไปขวา เมื่อทำงานเสร็จก็ถือว่าจบการทำงาน ถ้าหากเราต้องการทำงานเดิม ก็ต้องเขียนโปรแกรมซ้ำอีก ฟังก์ชั่นเลยเป็นที่รวบรวมส่วนที่เราจะเรียกใช้งานบ่อยๆ ให้รวมเป็นกลุ่มก้อนเดียวกัน โดยเรียกเพียงชื่อฟังก์ชั่นเท่านั้น ก็จะได้โปรแกรมที่ทำงานตามที่เราต้องการ และยังมีข้อดีคือ ถ้าหากต้องการแก้ไข ก็แก้ไขเพียงแต่ในฟังก์ชั่นเท่านั้น โปรแกรมทั้งหมดของเราก็จะทำงานตามการทำงานของฟังก์ชั่นที่แก้ไขเลย

Function ในภาษา PHP มาอยู่ 4 ชนิดคือ

  1. ฟังก์ชั่นภายใน (invoking a function)
  2. ฟังก์ชั่นที่สร้างขึ้นมาเอง (creating a function)
  3. ฟังก์ชั่นซ้อนฟังก์ชั่น (nesting function)
  4. ฟังก์ชั่นเรียกตัวเอง (recursive function)

1. ฟังก์ชั่นภายใน

เป็นฟังก์ชั่นพื้นฐานที่มากับ php (ชื่อก็บอกอยู่แล้ว) มีราวๆ พันกว่าฟังก์ชั่น (ใครเคยนับบ้างเนี่ย) ซึ่งจะครอบคลุมการทำงานพื้นฐา่นทั้งหมดของการเขียนโปรแกรม PHP จนบางครั้ง เราสามารถเขียนโปรแกรมที่ทำงานได้จริงโดยไม่จำเป็นต้องเขียนฟังก์ชั่นเพิ่มเติมเลยแม้แต่ฟังก์ชั่นเดียว เหมือนที่ผมเคยได้ยินมาว่า "คนที่เขียนโปรแกรมเก่ง ไม่จำเป็นต้องเขียนโค๊ดได้ดี เพียงแค่รู้จักฟังก์ชั่น แล้วรู้จักใช้มันก็พอ"

ฟังก์ชั่นภายในทั้งหลาย สามารถดูได้จาก help ของ PHP ได้ โดยโหลดได้ที่ http://www.php.net/docs.php

ตัวอย่างฟังก์ชั่นภายใน ผมขอยกตัวอย่างฟังก์ชั่น pow() ถ้าหากเปิดดู help จะเขียนเป็นลักษณะนี้

number pow ( number $base, number $exp )
  • number คือ ค่าที่ฟังก์ชั่นนี้ส่งกลับออกมา (return) ซึ่งเดี๋ยวเราค่อยมาอธิบายกัน
  • pow คือ ชื่อฟังก์ชั่น
  • (number $base, number $exp) คือ ค่าที่ต้องส่งให้ฟังก์ชั่นนี้ โดย number หมายถึงชนิดของค่า (datatype) ที่ต้องส่งไปให้

เพราะฉะนั้น ฟังก์ชั่น pow() เราต้องส่งค่าให้จำนวน 2 ค่า เมื่อฟังก์ขั่นทำงานเสร็จแล้วจะคืนค่ากลับมาเป็นชนิดตัวเลข

 <?php
	$value = pow(5,2);	// เรียกฟังก์ชั่น pow() โดยส่งค่า 5 เป็นเลขฐาน และ 2 เ้ป็นเลขชี้กำลัง แล้วเก็บค่าไว้ที่ตัวแปร $value
	echo $value;	// พิมพ์ค่าจากตัวแปร $value
?> 

ถ้าหากเราไม่ได้นำค่าที่ได้ไปทำการคำนวน เราสามารถแสดงค่าออกมาได้เลย โดยไม่จำเป็นต้องเก็บค่าไว้ในตัวแปรใดๆ ลองดูตัวอย่างกันครับ

 <?php
	echo pow(5,2);	// พิมพ์ค่า 5 ยกกำลัง 2 ออกทางหน้าจอเลย
	echo "<br />";
	echo "ผลลัพท์ของ 5 ยกกำลัง 2 คือ " . pow(5,2);
?> 

เห็นไหมครับ ไม่ยากเลย แต่เราจะรู้ได้อย่างไรว่าฟังก์ชั่นไหน ใช้งานอย่างไร หรือเราจะใช้ฟังก์ชั่นไหนทำงานให้เรา อันนี้ก็ต้องอยู่ที่แต่ละท่านล่ะครับ ถ้าหากเล่นบ่อยๆ ก็จะพบกับฟังก์ชั่นที่เรายังไม่เคยใช้งานเองแหละครับ ถึงแม้ว่า PHP จะมีฟังก์ชั่นมากกว่า 1000 ฟังก์ชั่น แต่ที่ใช้งานทั่วๆ ไป จะมีไม่ถึง 200 ฟังก์ชั่นครับ (ลดไปเยอะเลย)

2.ฟังก์ชั่นที่สร้างขึ้นมาเอง

เป็นฟังก์ชั่นที่สร้างขึ้นมาเอง เพื่อให้ทำงานนอกเหนือจากฟังก์ชั่นที่มีอยู่ใน PHP หรือเราต้องการให้โปรแกรมทำงานตรงกับความต้องการของเรา รูปแบบการเขียนฟังก์ชั่นเป็นดังนี้

 <?php
	function ชื่อฟังก์ชั่น (ค่าที่ส่งให้) {
		การทำงานของฟังก์ชั่น
	}
?> 

ลองดูตัวอย่างการสร้างฟังก์ชั่นชื่อ cmdevhub() กันครับ

 <?php
	function cmdevhub() {
		echo "welcome to cmdevhub";
	}

	// เราสามารถเรียกฟังก์ชั่นได้โดยเรียกจากชื่อฟังก์ชั่น

	cmdevhub();	// พิมพ์ welcome to cmdevhub
?> 

เห็นไหมครับ ไม่ยากเลย ส่วนข้อกำหนดในการสร้างฟังก์ชั่นนั้นก็เหมือนกันการสร้างตัวแปรเลยครับ ถ้าหากจำไม่ได้ก็ย้อนกลับไปดูได้เลย

หลังจากเราสร้างฟังก์ชั่นได้แล้ว ฟังก์ชั่นของเราจะไม่มีประโยชน์อะไรเลยถ้าหากไม่สามารถรับค่าเพื่อใช้คำนวนตามที่เราต้องการได้ การส่งค่าให้ฟังก์ชั่นทำการคำนวนนั้นมี 2 รูปแบบคือ ส่งค่าไปตรงๆ เลย และ ส่งค่าอ้างอิงตำแหน่งของตัวแปร ส่วนวิธีการรับค่าของฟังก์ชั่นทำได้โดยใส่ตัวแปรเข้าไปใน ( ) มาดูตัวอย่างกัน

2.1 การส่งค่าโดยตรง

 <?php
	function cArea($r) {	// ฟังก์ชั่นหาพื้นที่วงกลม
		echo $r * 22 / 7;
	}
	function sArea($h, $w) {	// ฟังก์ชั่นหาพื้นที่สี่เหลี่ยม
		echo $h * $w;
	}

	cArea(15);	// ผลลัพท์ 47.1428571429
	echo "<br />";
	sArea(3, 15); // ผลลัพธ์ 45
?> 

เราสามารถส่งค่าไปให้ฟังก์ชั่นโดยใช้ค่าที่อยู่ในตัวแปรส่งไปได้ด้วย

 <?php
	function sArea($h, $w) {
		echo $h * $w;
	}

	$width = 12;
	$height = 3;
	sArea($width, $height);
?> 

ถ้าหากส่งค่าให้ฟังก์ชั่นมากเกินกว่าที่ฟังก์ชั่นรับไว้ ค่าที่เกินมา จะไม่ถูกนำไปใช้งาน แต่ถ้าหากส่งค่าไปไม่ครบจะเกิดข้อผิดพลาด Warning: Missing argument ตรงนี้ก็ระวังกันด้วยนะครับ

2.2 การส่งค่าอ้างอิงตำแหน่งตัวแปร

โดยปกติการส่งค่าให้ฟังก์ชั่นจะทำการส่งค่าของตัวแปรนั้นๆ เข้าไปยังฟังก์ชั่นเลย ถ้าหากต้องการผลลัพธ์ของการคำนวนก็ทำการคืนค่า (return) กลับมา แต่เราสามารถเขียนให้ง่ายกว่านั้นได้อีก โดยการส่งตำแหน่ง (address) ของตัวแปรนั้นเข้าไปยังฟังก์ชั่นแทน ก็สามารถทำการคำนวนและเปลี่ยนค่าของตัวแปรที่เราต้องการได้โดยไม่ต้องทำการคืนค่ากลับออกมา ตัวอย่างที่ผมใช้บ่อยและใช้ตลอดก็คือการคำนวนภาษี (ยังหาโปรแกรมอื่นๆ ที่ใช้ฟังก์ชั่นแบบนี้ไม่ได้เลย) ลองดูตัวอย่างกันครับ

 <?php
	function cal_tax(&$cost, $tax) {
		$cost += $cost * $tax;
	}

	$cost = 200;
	$tax = 0.07;

	echo "จำนวนเงินก่อนคำนวนภาษี " . $cost;	// ผลลัพธ์ 200
	echo "<br />";

	cal_tax($cost, $tax);

	echo "จำนวนเงินหลังคำนวนภาษี " . $cost;	// ผลลัพธ์ 214
?> 

จะเ้ห็นว่า เราสามารถเปลี่ยนตัวแปร $cost โดยไม่ต้องทำการคืนค่าในฟังก์ชั่นเลย จริงๆ แล้ว ตัวอย่างด้านบนสามารถเขียนได้อีกแบบดังนี้

 <?php
	function cal_tax($cost, $tax) {
		$cost += $cost * $tax;
		return $cost;
	}

	$cost = 200;
	$tax = 0.07;

	echo "จำนวนเงินก่อนคำนวนภาษี " . $cost;
	echo "<br />";

	$cost = cal_tax($cost, $tax);

	echo "จำนวนเงินหลังคำนวนภาษี " . $cost;
?> 

ซึ่งผลลัพธ์ที่ได้จะเหมือนกันทุกอย่าง แต่การเรียกใช้งานจะไม่เหมือนกัน จุดนี้ก็แล้วแต่ล่ะครับ ว่าจะเลือกใช้วิธีไหน ถ้าหากทำงานเ็ป็นทีม การใช้งานฟังก์ชั่นที่คืนค่ากลับมาจะเข้าใจได้ง่ายกว่า แต่ถ้าหากทำงานไม่กี่คน หรือแค่คนเดียว การอ้างอิงหน่วยความจำจะทำให้โค๊ดสั่นกว่า และเข้าใจยากกว่า (ถ้าหากเราลืม อิอิ) เอาเ็ป็นว่า รู้ไว้เฉยๆ ก็ได้ครับ เพราะบางทีเราอาจจะไม่ได้เขียนฟังก์ชั่นแบบนี้เลยก็ได้ (แต่ลองใช้แล้วจะติดใจ)

2.3 การกำหนดค่าเริ่มต้นให้ฟังก์ชั่น

ในการสร้างฟังก์ชั่นที่ทำการรับค่านั้น เราจำเป็นที่จะต้องส่งค่าให้กับฟังก์ชั่นนั้นๆ จนครบตามจำนวนที่กำหนดไว้ ถ้าหากส่งค่าไม่ครบจะเกิดข้อผิด Warning: Missing argument ขึ้น หรือ ถ้าเราต้องการสร้างฟังก์ชั่นที่เรารู้ค่าที่ใช้คำนวนอยู่แล้ว เช่นฟังก์ชั่นที่คิดภาษีที่เรารู้อยู่แล้วว่าต้องคิดที่ 7% แต่ต้องการให้สามารถเปลี่ยนค่าได้โดยที่ไม่ต้องแก้ไขฟังก์ชั่นใหม่ ก็สามารถทำการกำหนดค่าเริ่มต้นขึ้นมาได้เลย ลองดูตัวอย่างกัน

 <?php
	function cal_tax(&$cost, $tax = 0.07) {
		$cost += $cost * $tax;
	}
	$cost = $cost1 = 200;
	echo "จำนวนเงินก่อนคำนวนภาษี " . $cost;
	echo "<br />";
	cal_tax($cost);
	echo "จำนวนเงินหลังคำนวนภาษี " . $cost;
	echo "<hr />";
	echo "คิดภาษีที่ 10%";
	echo "<br />";
	echo "จำนวนเงินก่อนคำนวนภาษี " . $cost1;
	echo "<br />";
	cal_tax($cost1, 0.1);
	echo "จำนวนเงินหลังคำนวนภาษี " . $cost1;
	echo "<br />";
?> 

จากตัวอย่าง ทำการผสมผสานกันระหว่างการเรียกฟังก์ชั่นโดยใช้อ้างอิงตำแหน่งตัวแปร กับการกำหนดค่าเริ่มต้นให้ฟังก์ชั่น จะเห็นได้ว่า เราเรียกฟังก์ชั่นครั้งแรกโดยไม่ส่งค่าไปแค่ตัวเดียวคือตำแหน่งของตัวแปร $cost เราได้ทำการกำหนดค่าเริ่มต้นให้ตัวแปร $tax แล้วทำให้ตัวแปร $tax มีค่า 0.07 ตามที่เรากำหนดไว้ แต่พอเรียกครั้งที่สองเราได้ส่งค่า 0.1 ให้กับตัวแปร $tax ด้วย ทำให้ค่าของตัวแปร $tax ถูกเปลี่ยนจาก 0.07 เป็น 0.1 แทน

2.4 การคืนค่าของฟังก์ชั่น

ในการสร้างฟังก์ชั่นขึ้นมาใช้งานนั้น ถ้าหากไม่มีการส่งค่ากลับคืนมาเมื่อทำงานเสร็จ ฟังก์ชั้นนั้นก็แทบจะไม่มีประโยชน์อะไรเลย เนื่องจากไม่สามารถนำค่าที่ฟังก์ชั่นคำนวนได้กลับมาใช้งาน การคืนค่าของฟังก์ชั่น สามารถทำได้โดยใช้คำสั่ง return โดยสามารถคืนค่าจากผลลัพธ์การคำนวนได้หนึ่งค่า หรือถ้าต้องการคืนหลายๆ ค่าพร้อมกัน สามารถใช้ตัวแปรแบบ array หรือ list ก็ได้ ลองดูตัวอย่างกันครับ

การคืนค่าหนึ่งค่า

 <?php
	function cal_tax($cost, $tax = 0.07) {
		$cost += $cost * $tax;
		return $cost;
	}

	$cost = 200;
	echo "ค่าก่อนคำนวนภาษี " . $cost;
	$cost = cal_tax($cost);
	echo "<br />";
	echo "ค่าหลังคำนวนภาษี " . $cost;
?> 

การเรียกใช้งานฟังก์ชั่นที่มีการคืนค่านั้น จำเป็นต้องมีตัวแปร หรือคำสั่งใดๆ รองรับการคืนค่านั้นๆ ไม่เช่นนั้นแล้ว ค่าที่คืนกลับมา ก็ไม่สามารถนำไปใช้งานใดๆ ได้เลย

การคืนค่าหลายค่า

การคืนค่าหลายๆ นั้น ต้องทำให้ตัวแปรนั้นเป็น array ก่อน โดยจะสร้างให้ตัวแปรนั้นเป็น array หรือใช้คำสั่ง list() ในการรับค่าก็ได้ ตัวอย่างการใช้ฟังก์ชั่น list()

 <?php
	$color = array('red', 'green',' blue');
	list($red, $green, $blue) = $color;
	// ตัวแปร $red เก็บค่า red, $green เก็บค่า green, $blue เก็บค่า blue
?> 

ตัวอย่างการใช้งานฟังก์ชั่นที่คืนค่าแบบ array

 <?php
	function user() {
		$name[] = "POP EYE";
		$name[] = "shikimasan[a]gmail[dot]com";
		$name[] = "www.cmdevhub.com";
		return $name;
	}
	// รับค่าโดยใช้ฟังก์ชั่น list ต้องทำการสร้างตัวแปรรับค่าให้ตรงกับค่าที่คืนกลับมา
	list($name, $email, $web) = user();

	// รับค่าโดยใช้ตัวแปร ทำให้ตัวแปรนั้นถูกเปลี่ยนเป็นแบบ array โดยอัตโนมัติ
	$name = user();

	// การอ้างอิงค่าต้องทำการอ้างอิงจาก index ของ array โดยตรง
	echo $name[0];
	echo $name[1];
?> 

จากตัวอย่างจะเห็นได้ว่าเราสามารถรับค่าจากฟังก์ชั่นที่คืนค่าเป็น array ได้ทั้ง 2 แบบ แต่ในการใช้งานจริงๆ จะใช้ฟังก์ชั่น list() รับค่ามากกว่า เพราะต้องกำหนดตัวแปรให้กับค่าที่คืนมาแต่ละค่า ซึ่งจะสื่อความหมายมากกว่ารับค่าโดยใช้ตัวแปรและอ้างอิงโดยใช้หมายเลข index อ้างอิง

2.5 ฟังก์ชั่นซ้อนฟังก์ชั้น (Nesting Function)

ในภาษา PHP เราสามารถสร้างฟังก์ชั่นขึ้นมาภายในฟังก์ชั่นอีกทีได้ แบบตัวอย่าง

 <?php
	function cal_tax ($price, $tax) {
		function cal_vat ($total) {
			return $total * 0.07;
		}
		$price += $price * $tax;
		echo "จำนวนเงินทั้งหมดหลังรวมภาษี " . $price . " หลังรวมภาษีมูลค่าเพิ่ม " . ($price + cal_vat($price));
	}
	cal_tax(1500, 0.1);	// ผลลัพธ์ 1650 , 1765.5
	echo "<br />";
	echo cal_vat(100);	// ผลลัพธ์ 7
?> 

Nesting Function ของภาษา PHP ไม่มีการกำหนดระดับของการเข้าถึง (scope) ทำให้ไม่ว่าจะเขียนฟังก์ชั่นไว้ที่ไหน ก็สามารถเรียกใช้ได้ การเขียนแบบนี้ ไม่ค่อยได้ใช้ในชีวิตจริงเท่าไหร่ แต่ก็ให้รู้ไว้ว่าเราสามารถสร้างฟังก์ชั่นแบบนี้ได้ เผื่อเอาไปสอบ CERT นะครับ

2.6 ฟังก์ชั่นเรียกตัวเอง (Recursive Function)

ฟังก์ชั่นเรียกตัวเอง ใช้สำหรับทำงานซ้ำๆ กันโดยที่เราไม่รู้จำนวนรอบในการทำงาน โดยจะมีจุดสิ้นสุดการทำงานอยู่ในฟังก์ชั่นเองอยู่แล้ว เพื่อให้ฟังก์ชั่นหยุดการทำงาน การเขียนฟังก์ชั่นแบบเรียกตัวเอง จะลดระยะเวลาในการเขียนโปรแกรมไปได้อย่างมาก แต่ปัญหาคือการออกแบบและเขียนได้ยากมาก ทำให้ไม่ค่อยได้เห็นคนเขียนฟังก์ชั่นแบบนี้กันเท่าไหร่ เรามาดูตัวอย่างฟังก์ชั่นเรียกตัวเองที่เขียนกันบ่อยๆ 2 ตัวอย่างกัน

 <?php
	function fibo($num) {
		if ($num == 1 || $num == 2) {
			return 1;
		}
		else {
			return fibo($num - 1) + fibo($num - 2);
		}
	}

	echo fibo(20);
?> 

ตัวอย่างแรกเป็นตัวเลข Fibonacci การใช้งานคือ เรียกฟังก์ชั่น fibo() แล้วใส่ตัวเลขตำแหน่งหลักที่ต้องการเข้าไปเช่น fibo(20) หมายถึงตัวเลข fibonacci ในตำแหน่งที่ 20

 <?php
	function fac($num) {
		if ($num == 0 || $num == 1) {
			return 1;
		}
		else {
			return fac($num - 1) * $num;
		}
	}

	echo fac(5);
?> 

ตัวอย่างที่สองเป็นตัวเลข Factorial หรือ n! การทำงานก็คล้ายๆ กับ fibonacci แต่ผลลัพธ์ที่ได้จะเป็นค่าของ n! เลย

จะเห็นว่า ถ้าหากเราเขียนโปรแกรมแบบปกติ จะต้องมีการใช้คำสั่งวนรอบมาเกี่ยวข้อง แต่ถ้าใช้ฟังก์ชั่นเรียกตัวเองเราไม่ต้องใช้คำสั่งวนรอบเข้ามาเกี่ยวข้องกับการทำงานของฟังก์ชั่นเลย แต่จะต้องมีเงื่อนไขในการจบฟังก์ชั่นที่แน่นอนด้วย

 

ก็จบกันไปอีกแล้วกับฟังก์ชั่นในภาษา PHP บทนี้เขียนกันข้ามเดือนเลย เนื่องจากงานเยอะ (แต่มีเวลาเล่นเกม) ก็ต้องขออภัยเพื่อนๆ ที่รอกันอยู่นะครับ ตอนนี้ก็ปิดเทอมแล้ว ยังไงจะพยายามเขียนให้ได้มากที่สุดเท่าที่จะทำได้ แล้วเจอกันครับ

Posted in php, tutorial | Tagged , , | Leave a comment

บทที่ 7.5 คำสั่งควบคุม คำสั่งวนรอบ

หลังจากเราเข้าใจการทำงานของคำสั่งวนรอบแล้ว ทีนี้ก็มาถึงวิธีการควบคุมการทำงานของคำสั่งวนรอบแล้ว ซึ่งก็มีเพียง 2 คำสั่งคือ

  • break
  • continue

สำหรับคำสั่งควบคุมนี้ ต้องใช้งานร่วมกับคำสั่งเงื่อนไขภายในลูปควบคุมการทำงาน

คำสั่ง break

จะทำให้ลูปที่กำลังทำงานนั้น หยุดลงทันที ใช้ร่วมกับ for, foreach, while, do while, switch โดยเฉพาะ switch นั้น ต้องใส่ break สำหรับแต่ละ case ด้วย ไม่เช่นนั้นจะทำงานไปเรื่อยๆ จนหมด switch ลองดูตัวอย่างกันเลยล่ะกันครับ

 <?php
	for ($i = 0; $i < 10; $i++ ) {
		if ($i == 5) {
			break;
		}
		echo $i;
	}
?> 

จากตัวอย่าง for ถูกให้ทำงานเป็นจำนวน 10 รอบ แต่ภายในลูปมีเงื่อนไขอยู่ ถ้าหากวนไปไ้ด้ถึง 5 รอบก็จะตรงกับเงื่อนไขที่ตั้งไว้ คำสั่ง break จะถูกเรียกใช้งาน ทำให้ for หยุดทำงาน ทำให้ผลลัพท์ที่ได้เป็น 01234

คำสั่ง continue

เหมือนกับ break ทุกๆ อย่างเลยครับ เพียงแต่จะหยุดทำงานในรอบนั้นๆ แล้วทำงานรอบต่อไปจนหมดลูปแทน จากโค๊ดข้างบน ถ้าเปลี่ยนจาก break เป็น continue โปรแกรมก็จะข้ามการทำงานเมื่อวนไปได้ถึงรอบที่ 5 ทำให้ผลลัพท์เป็น 012346789 แทน

 <?php
	for ($i = 0; $i < 10; $i++ ) {
		if ($i == 5) {
			continue;
		}
		echo $i;
	}
?> 

ต้องลองเล่นดูบ่อยๆ ครับ ถึงจะเห็นประโยชน์ของมัน

โจทย์ขำๆ ครับ ลองคิดกันเล่นๆ ดีกว่า

 <?php
	// พิมพ์ 1 - 100 ยกเว้นเลขที่หาร 2 หรือ 5 ลงตัว
	for ($i = 1; $i < 100; $i++ ) {
		if (($i % 2 == 0) || ($i % 3 == 0)) {
			continue;
		}
		echo $i . "<br />";
	}
?> 

มาลองคิดกันดูครับ ว่าจะได้ผลลัพท์อะไร

 <?php
	// อันนี้ไม่ยากเท่าไหร่ครับ
	$count = 0;
	for ($i = 6; $i > $count; $i--, ++$count ) {
		echo $count . "<br />";
	}
?> 
 <?php
	// ยากขึ้นมาอีกนิดนึง
	$x = 0;
	$y = 0;
	for ($z = 0; $z < 5; $z++ ) {
		if (( ++$x > 2) || (++$y > 2)) {
			$x++;
		}
	}
	echo "X = " . $x;
	echo "<br />";
	echo "Y = " . $y;
?> 

จริงๆ ทั้งสองคำสั่งนี้ มันไม่มีอะไรให้เล่นเลยอ่ะครับ อีกอย่าง ก็เผากันสุดๆ เลย (ไม่รู้จะเขียนยังไงเหมือนกัน) ก็ทำความเข้าใจกันไว้ครับ เพราะยังไงก็ได้ใช้งานแน่นอน แต่อาจจะไม่บ่อยเท่าไหร่

แล้วพบกันใหม่ โอกาสหน้าครับ

Posted in php, tutorial | Tagged , | Leave a comment

บทที่7 คำสั่งวนรอบ

คำสั่งวนรอบ ใช้สำหรับทำงานซ้ำๆ กัน ในภาษา PHP มีคำสั่งวนรอบทั้งหมด 4 คำสั่งคือ

  • for
  • while
  • do while
  • foreach

ส่วนประกอบของคำสั่งวนรอบจะมี 3 ส่วนใหญ่ๆ คือ

  1. ค่าเริ่มต้น (initialization)
  2. เงื่อนไขในการทำงาน (condition)
  3. คำสั่งเปลี่ยนค่า (update)

คำสั่งวนรอบ จะทำงานก็ต่อเมื่อเงื่อนไขยังคงเป็นจริง เพราะฉะนั้นเราต้องทำให้เงื่อนไขเป็นเท็จเพื่อให้จบการทำงานโดยการเปลี่ยนค่าไปเรื่อยๆ ถ้าหากไม่มีการจบเงื่อนไขโปรแกรมก็จะไม่จบการทำงาน ดังนั้นให้ระวังตรงนี้ด้วยนะครับ

for loop

เป็นเงื่อนไขที่เข้าใจได้ง่ายที่สุด เพราะมีการกำหนดค่า เงื่อนไข และเปลี่ยนแปลงค่า อยู่ภายในคำสั่งเดียวกันทั้งหมด มีรูปแบบการเขียน ดังนี้

 <?php
	for ( initialization; condition; update ) {
		statement;
	}
?> 

คำสั่ง for จะใช้มากในงานที่เรารู้จำนวนรอบการทำงานที่แน่นอน ตัวอย่างพิมพ์เลข 1 - 100

 <?php
 	for ($i = 1; $i <= 100; $i++ ) {
 		echo $i . "<br />";
 	}
?>  

ดูแล้ว เข้าใจไม่ยากเลยนะครับ ก็ถือว่าเป็นคำสั่งวนรอบที่ง่ายที่สุดแล้วล่ะครับ

while loop

เป็นเงื่อนไขที่เข้าใจยากขึ้นอีกนิด แต่ก็ใช้บ่อยมากพอสมควร while จะมีแต่การเช็คเงื่อนไขเพียงอย่างเดียว การกำหนดค่าเริ่มต้น จะทำก่อนที่จะเข้าเงื่อนไข และการอัพเดทค่าจะทำอยู่ภายในเงื่อนไข มีรูปแบบการเขียน ดังนี้

 <?php
	initialization;
	while (condition) {
		statement;
		update;
	}
?> 

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

 <?php
	$a = $b = $c = 5;
	// พิมพ์เลข 5 - 10
	while ($a <= 10) {
		echo $a . "<br />";
		$a++;
	}
	// ไม่หลุดลูปเนื่องจากไม่มีการอัพเดทค่า
	while ($b <= 10) {
		echo $b . "<br />";
		// จะแสดงเลข 5 ออกมาเรื่อยๆ แต่โปรแกรมไม่หยุดทำงาน เนื่องจากเงื่อนไขยังคงเป็นจริง
	}
	// ไม่หลุดลูปเนื่องจากการอัพเดท ไม่ทำให้เงื่อนไขเป็นเท็จ
	while ($c <= 10) {
		echo $c . "<br />";
		$c--;
	}
	// จะไม่ทำงาน เนื่องจากเงื่อนไขเริ่มต้นเป็นเท็จ
	while ($a < 10) {
		echo $a . "<br />";
		$a++;
		// ไม่เข้ามาทำงาน เนื่องจากค่าของ $a = 11 จากลูปแรกแล้ว
	}
?> 

โค๊ดตัวอย่างข้างบน ถ้าหากนำไปรัน ก็เตรียม end task ตัว browser ได้เลยนะครับ เพราะมันจะทำงานไม่หยุดเลย

จากตัวอย่าง ลูปสุดท้าย จะไ่ม่ทำงานนะครับ เนื่องจากค่าของ $a เป็น 11 ไปแล้ว หลังจากทำงานลูปแรกสุดเสร็จแล้ว เพราะฉะนั้น การใช้งาน while loop เราจำเป็นต้องตรวจสอบเงื่อนไขให้ดีก่อน ไม่เช่นนั้น โปรแกรมใน while loop ของเรา จะไม่มีวันทำงานเลย

do while loop

จากปัญหาที่ว่า ถ้าเงื่อนไขเป็นเท็จก่อนที่จะเริ่มลูป คำสั่งในนั้นจะไม่ทำงานเลย ก็เลยมี do while ออกมาเพื่อทำให้โปรแกรมในส่วนนั้นทำงานอย่างน้อยที่สุด 1 ครั้ง ไม่ว่าเงื่อนไขจะเป็นจริง หรือเท็จก็ตาม ทำให้การตรวจสอบเงื่อนไข ถูกย้ายไปไว้ด้านล่างสุดของลูป มีรูปแบบการเขียน ดังนี้

 <?php
	initialization;
	do {
		statement;
		update
	} while (condition);
?> 

ดูๆ แล้ว คล้ายกับ while loop เลยใช่ไหมครับ เพียงย้าย while ไปไว้ด้านล่างและมี do มาอยู่แทนที่ while เท่านั้นเอง งั้นลองดูที่โปรแกรมกันครับ

 <?php
	$a = 10;
	// เงื่อนไขเป็นเท็จ ไม่ทำงานใน while
	while ($a < 10) {
		echo $a;
		$a++;
	}
	// เงื่อนไขเป็นเท็จ แต่ใช้ do while ซึ่งจะทำงานอย่างน้อย 1 ครั้ง
	do {
		echo $a;
		$a++;
	} while ($a < 10);
?> 

while กับ do while นั้น อาจจะเข้าใจยากนิดหนึ่ง แต่ก็ไม่น่าจะยากเกินไปนะครับ ถ้าหากไม่เข้าใจ ก็ลองพยายามเขียนบ่อยๆ เดี๋ยวก็จะเข้าใจเองครับ

แล้วในเมื่อ for ก็ทำงานได้เหมือนกัน จะมี while มาทำไม?

สำหรับ for นั้น จะใช้สำหรับการทำงานที่รู้จำนวนรอบที่แน่นอน แต่สำหรับ while แล้ว จะใช้ร่วมกับฟังก์ชั่นที่คืนค่าเป็นจริงหรือเท็จกลับมา เช่นคำสั่ง mysql_fetch_assoc(); หรือ feof(); เป็นต้น เพราะเราไม่รู้ว่าจำนวนแถวที่ select มาได้มีทั้งหมดกี่แถว (คำสั่ง mysql_fetch_assoc) หรือว่าไฟล์ที่เรา้เปิดมาอ่านนั้นหมดหรือยัง (คำสั่ง feof)

ลองดูตัวอย่าง โค๊ดอ่านข้อความที่อยู่ในไฟล์ แล้วพิมพ์ออกมาที่หน้าจอครับ

 <?php
	$fp = fopen("hello.txt", "r");
	while (!feof($fp)) {
		echo fgets($fp);
	}
	fclose($fp);
?> 

รูปผลลัพท์ที่ได้

fopen example

จะเห็นได้ว่า เราไม่รู้ว่าไฟล์ของเรามีทั้งหมดกี่บรรทัด เราจึงใช้ while loop ทำการวนเพื่อให้นำข้อมูลออกมาทีละบรรทัดจนหมด ซึ่งการทำงานแบบนี้ ไม่สามารถใช้ for ได้ เพราะไฟล์ที่เปิดขึ้นมาแต่ละครั้ง อาจจะมีจำนวนบรรทัดที่ไม่เท่ากัน

สำหรับ do while บางภาษาอย่างเช่น Python ได้นำออกไปแล้ว เพราะไม่ค่อยได้ใช้งาน และหาโอกาสใช้งานจริงๆ จังๆ นั้น ยากมาก ส่วนตัวผม ก็ไม่เคยใช้งานจริงๆ เลยสักครั้งเดียว นอกจากเขียนให้ดูเป็นตัวอย่างนี่แหละครับ

foreach

ใช้ร่วมกับ Array สำหรับนำค่าออกมาได้เลย ซึ่งปกติในภาษาอื่นๆ (เช่นภาษา C) ถ้าหากต้องการเข้าถึงตัวแปร Array ต้องใช้คำสั่ง for แต่ในภาษา PHP และภาษาระดับสูงรุ่นใหม่ๆ จะมีคำสั่ง foreach สำหรับเข้าถึงค่าภายในตัวแปรได้เลย รูปแบบการเขียน foreach เขียนแบบนี้

 <?php
	foreach ( array as $value ) {
		statement;
	}
?> 

ลองมาดูตัวอย่าง และเปรียบเทียบกับคำสั่ง for เพื่อความเข้าใจที่มากขึ้นครับ

 <?php
	$a = array("www.cmdevhub.com", "www.blognone.com", "www.pc-cm.com", "www.pantip.com");

	// ใช้ for ในการเข้าถึงค่าในอาเรย์
	for ( $i = 0; $i < count($a); $i++ ) {
		echo $a[$i];
		echo "<br />";
	}
	echo "<hr />";
	// ใช้ foreach ในการเข้าถึงค่าในอาเรย์
	foreach ( $a as $value ) {
		echo $value;
		echo "<br />";
	}
?> 
foreach array

จากตัวอย่าง ถ้าลองเอาไปรันดู จะเห็นว่า ผลลัพท์ที่ได้จะเหมือนกันเลย เพื่อนๆ อาจจะเห็นว่า ใช้ for แล้ว ง่ายกว่าอีก แค่กำหนดขอบเขตการวนรอบโดยใช้ count เท่านั้นเอง ซึ่งมันก็จริง แต่ถ้าเป็นอาเรย์แบบจับคู่ล่ะ (associative) เราจะเข้าถึงข้อมูลทั้งหมดโดยใช้ for ได้อย่างไร ในเมื่อ index ไม่ใช่ตัวเลขแล้ว ลองดูตัวอย่างกันครับ

 <?php
	$com = array("CPU" => "E8200", "RAM" => "2GB", "HDD" => "640GB", "VGA" => "9600GSO", "Monitor" => "Samsung 22\"");
	// Spec คอมที่เอาไว้เล่นเกมครับ
	// เราสามารถใช้ foreach ดึงข้อมูลออกมาได้แบบนี้ครับ
	foreach ( $com as $value ) {
		echo $value;
		echo "<br />";
	}
	echo "<hr />";
	// ถ้าต้องการนำ index ออกมาด้วย ก็เขียนรูปแบบนี้ครับ
	foreach ( $com as $key => $value ) {
		echo $key . " => " . $value;
		echo "<br />";
	}
?> 
foreach associative array

เห็นไหมครับ แค่นี้ก็สามารถทราบข้อมูลทั้งหมดที่อยู่ภายใน Array แล้ว ทั้งแบบปกติ แล้วแบบจับคู่ แต่ถ้าแค่ต้องการรู้ค่าใน Array เฉยๆ ไม่ได้ไปวนลูปเพื่อเอาค่าไปใช้งาน ก็สามารถใช้คำสั่ง print_r() ก็ได้ครับ

 <?php
	$com = array("CPU" => "E8200", "RAM" => "2GB", "HDD" => "640GB", "VGA" => "9600GSO", "Monitor" => "Samsung 22\"");
	// Spec คอมที่เอาไว้เล่นเกมครับ
	print_r($com);
	echo "<hr />";
	echo "<pre>";
	print_r($com);
	echo "</pre>";
?> 
print_r

คำสั่ง print_r() ถ้าหากไม่ใส่ <pre> ครอบเข้าไป จะได้ข้อความที่ต่อกันเป็นแถวเดียว ดูยากครับ แต่ถ้าใส่แล้ว จะสวยงาม ดูง่ายมากๆ ว่ามีค่าอะไรอยู่ข้างใน

ก็จบกันไปแล้วกับคำสั่งวนรอบ จริงๆ แล้วเราไม่จำเป็นต้องใช้ทุกคำสั่ง โดยเฉพาะ do while ที่ผมก็ไม่เคยใช้งานจริงเหมือนกัน แต่ for และ while ขอให้เน้นให้มากๆ ครับ ส่วน foreach ถ้าหากไม่ได้จริงๆ ก็ใช้ for แทนก็ได้ครับ แต่ถ้าเข้าใจแล้ว การเข้าถึงตัวแปร Array จะง่ายขึ้นอีกเยอะเลยครับ

เจอกันใหม่ในบทหน้านะครับ

Posted in php, tutorial | Tagged , | Leave a comment

บทที่ 6 คำสั่งเงื่อนไข

เงื่อนไขในการเขียนโปรแกรม เป็นการกำหนดเส้นทางการทำงานของโปรแกรมตามที่เราต้องการ เราสามารถกำหนดการทำงานได้จาก ผลลัพท์ของการเปรียบเทียบ หรือ การคืนค่าของฟังก์ชั่น

คำสั่งเงื่อนไขในภาษา PHP มี 2 คำสั่งคือ

 

if... elseif... else...
switch... case...

เงื่อนไข if... elseif... else... จะถูกแบ่งเป็น 3 แบบใหญ่ๆ คือ

  • มีเงื่อนไขเดียว
  • มีสองเงื่อนไข
  • มีหลายเงื่อนไข

แบบเงื่อนไขเดียว จะทำงานก็ต่อเมื่อเงื่อนไขเป็นจริงเท่านั้น รูปแบบการเขียนคือ

 <?php
	if (เงื่อนไข) {
		// ทำงานในส่วนนี้เมื่อเงื่อนไขเป็นจริง
	}

	// ตัวอย่าง

	$a = 10;

	if ( 2 < 5 ) {
		echo "สองน้อยกว่าห้า";
	}

	if ($a + 5 < 20) {
		echo "สิบบวกห้าน้อยกว่ายี่สิบ";
	}
?> 

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

แบบสองเงื่อนไข เมื่อเงื่อนไขเป็นจริง จะทำงานในส่วน if แ่ต่ถ้าเงื่อนไขเป็นเท็จจะทำงานในส่วน else

<?php
 	if (เงื่อนไข) {
 		// ทำงานเมื่อเงื่อนไขเป็นจริง
 	}
 	else {
 		// ทำงานเมื่อเงื่อนไขเป็นเท็จ
 	}

  	// ตัวอย่าง

  	$a = 10;
  	if ($a < 10) {
 		echo "เงื่อนไขเป็นจริง";
 	}
 	else {
 		echo "เงื่อนไขเป็นเท็จ";
 	}
?>  

ไม่ยากใช่ไหมครับ คล้ายๆ กับแบบเงื่อนไขเดียว คือจะทำงานก็ต่อเมื่อเงื่อนไขเป็นจริง แต่เพิ่มการทำงานเมื่อเงื่อนไขเป็นเท็จด้วย ทำให้การทำงานของโปรแกรมเพิ่มเป็น 2 ทาง

แบบหลายเงื่อนไข การทำงาน 2 แบบแรก จะมีการเปรียบเทียบเงื่อนไขเพียงเงื่อนไขเดียว แต่ถ้าหากเราต้องการเปรียบเทียบหลายๆ เงื่อนไข โดยแต่ละเงื่อนไขจะทำงานไม่เหมือนกัน สามารถเขียนได้ดังนี้

 <?php
	if (เงื่อนไข 1) {
		// ทำงานเมื่อเงื่อนไข 1 เป็นจริง
	}
	elseif (เงื่อนไข 2) {
		// ทำงานเมื่อเงื่อนไข 2 เป็นจริง
	}
	elseif (เงื่อนไข 3) {
		// ทำงานเมื่อเงื่อนไข 3 เป็นจริง
	}
	elseif (เงื่อนไข n) {
		// ทำงานเมื่อเงื่อนไข n เป็นจริง
	}
	else {
		// ทำงานเมื่อเงื่อไขข้างบนเป็นเท็จทั้งหมด
	}
?> 

ลองมาดูโปรแกรมตัดเกรดง่ายๆ กัน

 <?php
	$score = 79;

	if ($score > 80) {
		echo "Grade A";
	}
	elseif ($score > 70) {
		echo "Grade B";
	}
	elseif ($score > 60) {
		echo "Grade C";
	}
	elseif ($score > 50) {
		echo "Grade D";
	}
	else {
		echo "Grade F";
	}
?> 

ผลลัพท์ที่ได้คือ Grade B แล้วทำไมถึงเป็นแบบนี้ ในเมื่อเงื่อนไขอื่นๆ ก็เป็นจริงเหมือนกัน แต่ทำไมผลลัพท์ที่ได้ จึงเป็นแค่ Grade B เพราะการทำงานของ if..elseif.. เมื่อเจอเงื่อนไขที่เป็นจริงแล้ว จะทำงานที่เงื่อนไขนั้น และข้ามการทำงานของเงื่อนไขอื่นๆ ไป

นอกจากนั้น เรายังสามารถใช้เงื่อนไขซ้อนเงื่อนไขได้ด้วย ลองดูตัวอย่างครับ

 <?php
	$a = 25;
	if ($a < 100) {
		if ($a < 50) {
			echo "a น้อยกว่า 50";
		}
		else {
			echo "a มากกว่า 50";
		}
	}
?> 

จะเห็นว่า เราสามารถซ้อนเงื่อนไขกี่ชั้นก็ได้ ตามใจเรา (มากกว่านี้ก็ได้ครับ) แต่ในชีวิตจริงแล้ว สัก 3 - 4 ชั้น ก็เริ่มแย่แล้วล่ะครับ ตอนหา Jordan Matrix แทบแย่เลย

งั้นถ้าเราลองเขียนโดยไม่ใช่เครื่องหมายปีกกาล่ะ? ก็จะได้ตัวอย่างแบบนี้

  <?php
	if (expression1) if (expression2) statement1; else statement2;

	// ลองเขียนใหม่ เผื่อจะเข้าใจง่ายขึ้น	

	// แบบที่ 1

	if (expression1)
		if (expression2)
			statement1;
	else
		statement2;

	// แบบที่ 2

	if(expression1)
		if (expression2)
			statement1;
		else
			statement2;
?> 

จากตัวอย่างข้างบนเป็นปัญหาของโปรแกรมเกือบทุกภาษา ปัญหานี้เรียกว่า Dangling else ถ้ามองโจทย์เป็นแบบที่ 1 ก็จะมองได้ว่า else เป็นของ if ตัวนอก แต่ถ้าเป็นแบบที่ 2 จะมองได้ว่า else เป็นของ if ตัวข้างใน ซึ่งการเขียนทั้ง 2 แบบ ถูกต้องตามหลักไวยากรณ์ของ if..else.. ทุกอย่าง แล้วปัญหานี้ โปรแกรมจะแก้ไขอย่างไร?

บางภาษาเช่น Ada จะมีการจบ if ด้วย end if ทำให้ไม่มีปัญหานี้เกิดขึ้น แต่ภาษา php ไม่มีการจบ if โปรแกรมจะถือว่า else ตัวใดๆ จะ้เป็นของ if ตัวที่อยู่ใกล้ที่สุด จะทำให้โปรแกรมไม่มีทางสับสน แต่คนเขียนนี่แหละจะสับสนเอง...

ทางแก้ปัญหาที่ (ผมคิดว่า) ถูกต้องคือ ใส่ block ให้มันซะ ไม่ว่าคำสั่งที่ทำงานหลังจาก if จะมีแค่คำสั่งเดียวก็ตาม เพราะนอกจากโปรแกรมจะดูเป็นระเบียบแล้ว ถ้าหากเรากลับมาอ่านทีหลัง จะไม่สับสนเอง แล้วยังกำหนดการทำงานได้ตามต้องการด้วย

 <?php
	// ลองเขียนใหม่
	if (expression1) {
		if (expression2) {
			statement1;
		}
	}
	else {
		statement2;
	}
	// else เป็นของ if ตัวแรก ไม่ใช่ if ที่อยู่ใกล้ที่สุด

	if(expression1) {
		if (expression2) {
			statement1;
		}
		else {
			statement2;
		}
	}
	// else เป็นของ if ตัวที่สอง
?> 
ฝึกให้เป็นนิสัยเลยครับทุกๆ ครั้งที่เขียนเงื่อนไขให้ใส่ block ด้วย แม้ว่าจะทำงานแค่คำสั่งเดียวก็ตาม

เงื่อนไข switch... case...

switch... case... จะว่าไปมันก็ไม่เชิงเป็นเงื่อนไข เนื่องจากต้องมีการกำหนดค่าที่แน่นอนของตัวเลือก ไม่เหมือนกับ if ที่สามารถกำหนดเป็นช่วง หรือเป็นการคำนวนได้ ทำให้หลายๆ ภาษาอย่างเช่น Python ตัด switch... case... ออกไป รูปแบบการเขียนจะเป็นดังนี้

 <?php
	$web = "cmdevhub";
	switch ($web) {
		case: "cmdevhub" :
			echo "http://www.cmdevhub.com";
			break;
		case: "pantip";
			echo "http://www.pantip.com";
			break;
		default:
			echo "ไม่ได้เลือกเว๊ป";
			break;
	}
?> 

จะเห็นว่าทางเลือกของ switch... case... นั้น จะมีเพียงทางเดียว ซึ่งจะว่าไป ก็ไม่ค่อยจะมีประโยชน์สำหรับโปรแกรมระดับสูงเท่าไหร่ ผมจำได้ว่าครั้งสุดท้ายที่เขียนโปรแกรมแล้วใช้ switch... case... แบบจริงจัง ก็เขียนภาษา C บน Dos แล้วจับแป้นลูกศรทั้ง 4 ตัวล่ะครับ

แต่ถ้าหากเรารู้ค่าที่แน่นอนและเส้นทางที่แน่นอน การใช้ switch... case... จะเป็นทางเลือกที่ดีมากกว่า if เืนื่องจากเมื่อพบเปรียบเทียบแล้ว จะข้ามไปทำงานตามสิ่งที่ switch เจอเลยถ้าไม่พบ จะไปทำที่ default: แทน แต่ถ้าเป็น if จะทำการเปรียบเทียบไปเรื่อยๆ จนครบ ถ้าหากมีเงื่อนไขมากก็ต้องเปรียบเทียบจนครบ อันนี้ก็แล้วแต่ความเหมาะสมของโปรแกรมครับ

ตอนหน้าก็จะเป็นเรื่องคำสั่งวนรอบ (loop) ล่ะครับ

Posted in php, tutorial | Tagged , | Leave a comment

บทที่ 5 ตัวดำเนินการทางคณิตศาสตร์

ในการเขียนโปรแกรมทุกๆ โปรแกรม ต้องมีการคำนวนเข้ามาเกี่ยวข้องด้วยเสมอ แล้วสิ่งที่ใช้คำนวนนั้นก็คือตัวดำเนินการทางคณิตศาสตร์ที่เรารู้จักกันนั่นเอง ตัวดำเนินการทางคณิตศาสตร์ในภาษา PHP ก็เหมือนกับภาษาอื่นๆ สำหรับท่านที่เขียนโปรแกรมได้แล้ว อาจจะข้ามตรงนี้ไปเลยก็ได้ครับ เพราะเหมือนเอาของเก่ามาเล่าใหม่ เล่ากี่ที กี่ที มันก็ไม่ต่างไปจากเดิมเท่าไหร่หรอกครับ แต่สำหรับท่านที่กำลังเริ่มเขียนโปรแกรมแล้ว จุดนี้ ถือเป็นสิ่งที่ต้องรู้และต้องเข้าใจด้วย ไม่เช่นนั้นแล้ว อาจจะเขียนโปรแกรมเพื่อที่จะใช้งานจริงๆ ไม่ได้เลย

 

ตัวดำเนินการกำหนดค่า

การกำหนดค่าให้ตัวแปร ใช้เครื่องหมาย = (เท่ากับ) ในการกำหนดค่า วิธีการจำง่ายๆ ก็คือ สิ่งที่ทำด้านขวา (เช่นการคำนวน หรือ ข้อความ) จะถูกส่งไปยังด้านซ้าย ตามตัวอย่าง

 <?php
	$a = "cmdevhub";	// $a เ้ก็บข้อความว่า cmdevhub
	$b = 1;	// $b เก็บตัวเลข 1
	$c = 1 + 2;	// $c เก็บผลลัพท์จากการคำนวนด้านขวา คือ 3
	$d = $c + 3;	// ผลลัพท์ $d เก็บค่า 6 เนื่องจาก $c เก็บค่า 3 ไว้อยู่แล้ว
?> 

ตรงนี้ไม่ค่อยยากเท่าไหร่ หวังว่าทุกๆ ท่านจะเข้าใจนะครับ ถ้าหากไม่เข้าใจ ก็ให้พยายามทำความเข้าใจให้ได้ครับ ไม่เช่นนั้นจะไปต่ออีกไม่ได้เลย

(จริงๆ แล้วคำสั่ง += , -= , *= , /= , %= ก็จัดอยู่ในหมวดนี้ แต่ผมขอแยกออกไปอยู่ในตัวดำเนินการเชิงคณิตศาสตร์ล่ะกันครับ)

ตัวดำเนินการเชิงคณิตศาสตร์

เป็นเครื่องหมายทางคณิตศาสตร์ทั่วๆ ไป ที่เราคุ้นเคยกันดีอยู่แล้ว คือ บวก (+) ลบ (-) คูณ (*) หาร (/) แต่จะมีตัวพิเศษเพิ่มขึ้นมาอีกตัวหนึ่งคือ หารเอาเศษ (%) ลองดูตัวอย่างกันครับ

 $a + $b $a บวก $b
 $a - $b $a ลบ $b
 $a * $b $a คูณ $b
 $a / $b $a หาร $b
 $a % $b $a หาร $b แต่เอาเศษ
 <?php
	$a = 5;
	$b = 2;

	$a + $b;	// ผลลัพธ์ 7
	$a - $b;	// ผลลัพธ์ 3
	$a * $b;	// ผลลัพธ์ 10
	$a / $b;	// ผลลัพธ์ 2
	$a % $b;	// ผลลัพธ์ 1
?> 
ตรง $a / $b นั้น เป็นแค่ทางทฤษฎีนะครับ แต่ในภาษา PHP นั้น เนื่องจากการประกาศตัวแปรไม่มีการบอกว่าเป็นชนิดไหน
จึงทำให้ผลลัพธ์จากการหารนั้น เป็นจำนวนทศนิยมไปด้วย
สำหรับการหารเอาเศษ ข้อสังเกตง่ายๆ ว่าผลลัพธ์ถูกหรือไม่คือ ค่าที่ได้ จะเป็นเลขตั้งแต่ 0 ไปจนถึงตัวหารลบด้วย 1
เช่น หารด้วย 8 เศษที่ได้จะมีตั้งแต่ 0 จนถึง 7 เท่านั้น

ตัวดำเนินการทางคณิตศาสตร์สามารถคำนวน และกำหนดค่าให้ตัวแปรได้เลย โปรแกรมจะทำการคำนวนผลลัพธ์ให้เสร็จเสียก่อน แล้วจึงกำหนดค่าให้กับตัวแปรนั้นๆ ลองดูตัวอย่างกันครับ

 <?php
	$a = 5;
	$b = 2;
	$c = 3 + 4;	// ทำการคำนวน 3 + 4 ก่อน และค่อยกำหนดค่าให้ $c
	$d = $a + $b;	// ทำการคำนวนก่อนเช่นกัน

	$a = $a + 5;	// นำค่าในตัวแปร $a ไปบวกกับ 5 และกำหนดค่าที่ได้ให้ตัวแปร $a
	$b = $b + $c;	// นำค่าในตัวแปร $b ไปบวกกับค่าของ $c และกำหนดค่าที่ได้ให้ตัวแปร $b
?> 

จากตัวอย่าง จะเห็นว่า เราสามารถทำการคำนวนและกำหนดค่าได้ในครั้งเดียว ลองสังเกตุตรงที่ การนำตัวแปรไปคำนวน และกำหนดค่าให้ตัวมันเอง เราสามารถเขียนย่อลงได้ เพื่อให้โปรแกรมสั้นลง และทำงานได้เร็วขึ้น ดังนี้

$a = $a + $b; $a += $b;
$a = $a - $b; $a -= $b;
$a = $a * $b; $a *= $b;
$a = $a / $b; $a /= $b;
$a = $a % $b; $a %= $b;

ทั้งสองแบบ ได้ผลลัพท์ที่เหมือนกัน เขียนโปรแกรมใหม่ๆ อาจจะ งง กันพอสมควรครับ แต่ถ้าทำไปนานๆ แล้วจะคล่องเอง อันนี้ก็ต้องพยายามกันเยอะๆ หน่อยนะครับ ที่สำคัญ การเขียนแบบย่อ โปรแกรมจะทำงานได้เร็วกว่าครับ เพราะทำการ get operand 1 ครั้ง get operator 2 ครั้ง แต่ถ้าหากเขียนแบบเต็มจะ get operand 2 ครั้ง get operator 3 ครั้ง ไว้เรามาเขียนโปรแกรมหาความแตกต่างในโอกาสต่อไปนะครับ (แน่นอน ต้องภาษา C เท่านั้น)

สำหรับความสำคัญของเครื่องหมาย ก็ต้องเอามาคิดด้วยครับ เพราะไม่เช่นนั้น ผลลัพท์ที่คำนวนมาได้ จะไม่ถูกต้องตามที่เราต้องการ ระดับความสำคัญของเครื่องหมายตามตารางนี้เลยครับ

เครื่องหมาย ความหมาย ระดับ
( )  วงเล็บเปิด / ปิด 3
*, /, %  คูณ, หาร, หารเอาเศษ 2
+, -  บวก, ลบ 1

การคำนวนต้องคำนึงถึงระดับความสำคัญของเครื่องหมาย เพื่ออะไร? งั้นลองดูตัวอย่างกันเลยครับ (ในบางภาษาเช่น Python จะมียกกำลังด้วย ความสำคัญจะสูงกว่า *, /, % นะครับ)

 <?php
	echo 2 + 3 * 5;
?> 

อ่า... คิดว่าผลลัพท์ที่ได้ จะเป็นอะไร? ระหว่าง 30 หรือ 17 คำตอบนั้น ลองไปรันเองเลยล่ะกันครับ แต่แล้ว ทำไมผลลัพท์ถึงเป็นแบบนี้ เพราะว่าลำดับความสำคัญของเครื่องหมาย * มีมากกว่า + จึงมีการคำนวนในเทอมของ * ก่อน เสร็จแล้วจึงมาทำการ + ซึ่งรูปแบบการคำนวนนี้ เหมือนกันทุกภาษาครับ ถ้าหากท่านใดเคยเรียน data structure มา คงจะเคยเล่น in fix กับ post fix กันอย่างสนุกสนานล่ะครับ

ลองมาคิดกันเล่นๆ ต่อครับ

 <?php
	echo 10 - 2 * 15 / 3 - 2;
	echo 10 - 2 * (15 / 3) - 2;
	echo 10 - 2 * 15 / (3 - 2);
	echo (10 - 2) * 15 / (3 - 2);
	echo (10 - 2) * 15 / 3 - 2;
	echo 10 - (2 * (15 / (3 - 2)));
?> 

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

ตัวเพิ่มค่า (Increment) ลดค่า (Decrement)

ตัวเพิ่มค่า เขียนโดยใช้เครื่องหมาย บวกสองตัวต่อกัน (++) ใช้สำหรับเพิ่มค่าตัวแปรทีละ 1 ส่วนตัวลดค่า เขียนโดยใช้เครื่องหมายลบสองตัวต่อกัน (--) ใช้สำหรับลดค่าตัวแปรทีละ 1

 <?php
	// ตัวอย่างการเพิ่มค่าทีละ 1
	$a = 1;
	$a = $a + 1;
	$a += 1;
	// สามารถใช้คำสั่งเพิ่มค่าได้ดังนี้
	$a++;
?> 

จากตัวอย่าง จะเห็นว่า ผลลัพท์ของทั้ง 3 แบบ จะได้เหมือนกันหมด แล้วจะมีมาเพื่ออะไร?

ใน CPU ทุกตัว จะมีคำสั่ง ADD และ INC อยู่ด้วย ซึ่งคำสั่ง INC จะใช้ CPU Time น้อยกว่าคำสั่ง ADD อยู่แล้ว
สมมุติ... ใน CPU แบบ CISC (ตระกูล X86) แต่ละคำสั่ง จะใช้ CPU Time (Clock Cycle) ไม่เท่ากัน
ผมให้ INC = 1 clock ADD = 2 clock ถ้ามีการวนลูปสัก 1 ล้านรอบ ก็มีความต่างกันถึง 1 ล้าน Clock
อาจจะฟังดูน้อยเพราะ CPU ทำงานเร็วอยู่แล้ว แต่ถ้าเป็นเว๊ปใหญ่ๆ แล้วคนเ้ข้าเยอะๆ อันนี้มีผลแน่นอน
(ส่วน CPU ตระกูล RISC พวก Sparc ของ SUN ก็คิดอีกแบบ แต่ผลลัพท์ก็คล้ายๆ กันครับ)

ตัวเพิ่มค่า ละลดค่า สามารถเขียนได้ 2 ตำแหน่งคือ หน้าตัวแปร และ หลังตัวแปร

++$a , $a++ เพิ่มค่าทีละ 1
--$a, $a-- ลดค่าทีละ 1

ถ้าหากเราวางเครื่องหมายไว้หน้าตัวแปร ก็จะทำการเพิ่มตัวแปรนั้นก่อน จึงจะทำคำสั่งอื่นๆ ที่อยู่ในบรรทัดนั้น แต่ถ้าหากวางเครื่องหมายไว้หลังตัวแปร จะทำคำสั่งอื่นๆ ให้หมดก่อน ลองดูตัวอย่างตามนี้นะครับ

 <?php
	$a = 1;
	echo $a++;	// ผลลัพท์ 1 เนื่องจากทำคำสั่ง echo ก่อน จึงทำการเพิ่มค่า
	$a = 1;
	echo ++$a;	// ผลลัพท์ 2 เนื่องจากทำการเพิ่มค่าก่อน แล้วจึงทำคำสั่ง echo
	$a = 1;
	echo 1 + $a++;	// ผลลัพท์ 2 เนื่องจากทำการบวก 1 และ echo ก่อนจึงทำการเพิ่มค่า
	$a = 1;
	echo 1 + ++$a;	// ผลลัพท์ 3 เนื่องจากทำการเพิ่มค่าก่อน และบวก 1 แล้วจึงทำคำสั่ง echo
?> 

จะ้เห็นว่า การวางเครื่องหมายด้านหน้า หรือด้านหลัง ให้ผลลัพท์ที่แตกต่างกันอย่างมาก หลายๆ ท่านที่ผมเคยคุยด้วย ก็เคยตกม้าตายเพราะตำแหน่งของเครื่องหมายนี่แหละครับ ดังนั้นก็ให้ระมัดระวังในการเขียนด้วยนะครับ

ตัวเชื่อมข้อความ

ในภาษา PHP การกำหนดตัวแปรเป็นข้อความ (String) สามารถทำได้ 2 แบบคือใช้เครื่องหมาย Singe Quote (') หรือ Double Quote (") ถ้าต้องการนำข้อความหลายๆ ข้อความมาต่อกัน สามารถใช้เครื่องหมายจุด (.) เพื่อทำให้ตัวแปรเชื่อมต่อกัน หรือจะใช้เครื่องหมายจุด เพื่อเชื่อมข้อความกับตัวแปรก็ได้ ลองดูตัวอย่างกันครับ

 <?php
	$a = "Hello" . "World";
	$b = "Hello";
	$b = $b . "World";
	$c = "http:/www.cmdevhub.com";
	$c.= "โปรแกรมที่ไม่มีบักคือโปรแกรมที่ยังไม่ได้เขียน";	// ท่องเอาไว้ครับ อิอิ

	$total = 100;
	echo "Total Price = " . $total;
?> 

การนำข้อความมาเชื่อมกับตัวแปรเดิม สามารถเขียนได้ 2 แบบ ตามตัวอย่างข้างบนนะครับ

การเชื่อมข้อความ ดูแล้วเหมือนไม่ยาก ถ้าหากใช้บ่อยๆ แล้วจะคล่องเองครับ

ตัวเปรียบเทียบ

ตัวเปรียบเทียบในทุกๆ ภาษา จะเปรียบเทียบตัวซ้าย เทียบกับตัวขวา และได้ผลลัพท์เป็น จริง (true) หรือ เท็จ (false) เท่านั้น ในภาษา PHP ก็มีวิธีการเปรียบเทียบเหมือนกับภาษาอื่นๆ เหมือนกัน ผลลัพท์ที่ได้ก็มีแต่ จริง และ เท็จ เท่านั้น เหมือนกัน ตัวเปรียบเทียบ จะใช้ในการกำหนดทิศทางของโปรแกรม

$a < $b น้อยกว่า คืนค่าเป็นจริง ถ้า $a น้อยกว่า $b
$a > $b มากกว่า คืนค่าเป็นจริง ถ้า $a มากกว่ากว่า $b
$a <= $b น้อยกว่า หรือ เท่ากับ คืนค่าเป็นจริง ถ้า $a น้อยกว่า หรือ เท่ากับ $b
$a >= $b มากกว่า หรือ เท่ากับ คืนค่าเป็นจริง ถ้า $a มากกว่า หรือ เท่ากับ $b
$a == $b เท่ากับ คืนค่าเป็นจริง ถ้า $a เท่ากับ $b
$a != $b ไม่เท่ากับ คืนค่าเป็นจริง ถ้า $a ไม่เท่ากับ $b
$a === $b เท่ากับทั้งหมด คืนค่าเป็นจริง ถ้า $a เท่ากับ $b และ ต้องเป็นชนิดข้อมูลเดียวกัน

การเปรียบเทียบ === ทั้งค่าในตัวแปร และ ชนิดตัวแปร ต้องเหมือนกัน จึงจะไ้ด้ค่าจริงกลับมา แต่ == ค่าเท่ากัน แต่ตัวแปรเป็นคนละชนิด ก็ได้ค่าจริงกลับมาแล้ว จริงๆ แล้ว เครื่องหมาย === ไม่ค่อยได้ใช้เท่าไหร่หรอกครับ

 <?php
	$a = 1;
	$b = 2;
	$c = "1";

	$a < $b;	// true
	$a > $b;	// false
	$a <= $b;	// true
	$a <= $c;	// true
	$a >= $b;	// true
	$a >= $c;	// true
	$a == $b;	// false
	$a == $c; 	// true
	$a === $b;	// false
	$a === $c;	// false
?> 

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

ตัวดำเนินการทางตรรกศาสตร์

ในการเปรียบเทียบค่า เราสามารถเปรียบเทียบได้หลายๆ ค่าพร้อมกัน โดยใช้ตัวเปรียบเทียบทางตรรกศาสตร์มาช่วยหาคำตอบสุดท้ายของการเปรียบเทียบ ตัวเปรียบเทียบ จะมีเพียง 4 ตัวคือ and , or , not , xor

and หรือ && ได้ค่าจริง เมื่อเป็นจริงทั้งหมด
or หรือ || ได้ค่าเท็จ เมื่อเป็นเท็จทั้งหมด
not หรือ ! กลับค่า จากจริงเป็นเท็จ และ เท็จเป็นจริง
xor ตัวเปรียบเทียบ เหมือนกัน ได้ค่าเท็จ ต่างกันได้จริง

ถ้าเขียนเป็นตาราง จะได้ค่าตามนี้ (ผมให้ 0 = false และ 1 = true)

$a $b $a && $b $a || $b $a xor $b !$a
0 0 0 0 0 1
0 1 0 1 1 1
1 0 0 1 1 0
1 1 1 1 0 0

ดูจากตารางแล้ว ถ้าเคยเรียน Digital มาก่อน คงจะเข้าใจไม่ยาก แต่ถ้ายังไม่เข้าใจ ก็ลองท่องตรงนี้เอาครับ
and เป็นจริงเมื่อเป็นจริงทั้งหมด นอกนั้นเป็นเท็จ
or เป็นเท็จเมื่อเป็นเท็จทั้งหมด นอกนั้นเป็นจริง
xor เหมือนกันเป็นเท็จ ต่างกันเป็นจริง
not จริงเป็นเท็จ เท็จเป็นจริง
(ปล. สูตรใครสูตรมันนะครับ แต่ผมจับใจความมาได้แบบนี้อ่ะ)

ตัวเปรียบเทียบบิต

... เดี๋ยวค่อยมาต่อครับ ไม่ค่อยได้ใช้หรอกอ่ะ

Posted in php, tutorial | Tagged , | Leave a comment

บทที่ 4 ชนิดข้อมูล (ภาค 2)

พบกันอีกแล้วหลังจากหายไปซะสัปดาห์กว่าๆ ก็ไม่มีไรหรอกครับ แอบไปแข่งเกมมา ปีนี้ก็สนุกดีครับ แต่เสียดายคนน้อยไปหน่อย

เรามาเข้าเรื่องของเราเลยดีกว่า ตอนนี้ก็เป็นเรื่องของตัวแปร หลายๆ ท่านคงจะทราบแล้วว่าวีธีการประกาศตัวแปรใน PHP นั้น ง่ายแสนง่าย เพียงแต่ใส่เครื่องหมาย $ เข้าไปข้างหน้า ข้อความนั้นก็จะเป็นตัวแปรแล้ว แต่มีข้อแม้อยู่นิดนึงคือ

  1. ห้ามมีช่องว่างในตัวอักษร
  2. ห้ามขึ้นต้นด้วยตัวเลข
  3. ห้ามมีเครื่องหมายพิเศษ (Control Charecter)
  4. ตัวอักษรเล็ก-ใหญ่ ถือว่าเป็นคนละตัวกัน (Case sensitive)

การกำหนดค่าให้ตัวแปร

เราสามารถกำหนดค่าให้ตัวแปรตั้งแต่ตอนที่เราประกาศตัวแปรขึ้นมาได้เลย โดยใช้เครื่องหมาย = ในการกำหนดค่าให้กับตัวแปรนั้นๆ ลองดูตัวอย่างกันครับ

 <?php
	$color = "green";	// ตัวแปร color = string
	$num = 12;	// ตัวแปร num = integer
	$age = "13.5";	// ตัวแปร age = string
	$sum = 12 + "13";	// ผลลัพท์คือ 25 เป็น integer เนื่องจาก 13 ถูก cast เป็น Integer
	$total = $sum + $age;	// ผลลัพท์คือ 38.5 เป็น double เนื่องจาก age ถูก cast เป็น double -> double + integer = double
?> 

ในภาษา PHP นั้น ไม่ค่อยให้ความสำคัญในเรื่อง Datatype เท่าใด หลายๆ คนอาจจะมองว่าเ็ป็นข้อดีของมัน แต่ให้ระวัง ตอนไปเขียนภาษาอื่น โดยเฉพาะ Java ส่วนเรื่องการ casting ของตัวแปรนั้น ค่อยคุยกันในโอกาสต่อไปนะครับ

การใช้ตัวแปรอ้างอิงถึงกัน (Reference)

รูปแบบนี้ ไม่ค่อยได้ใช้กันเท่าไหร่หรอกครับ การทำงานของมันก็คือ เราสร้างตัวแปรขึ้นมาตัวหนึ่ง สมมุติชื่อ $a แล้วใช้ตัวแปรอีกตัว สมมุติชื่อ $b อ้างอิงตำแหน่งหน่วยความจำที่ $a ชี้อยู่ ดังนั้น ถ้าหากเราเปลี่ยนค่าที่ $b ค่าของ $a ก็จะเปลี่ยนไปด้วย เพราะชี้ตำแหน่งหน่วยความจำที่เดียวกัน (คนที่เคยเขียนภาษา C มาก่อนคงจะนึกภาพออกนะครับ) ลองดูตัวอย่างกันเลย

 <?php
	$a = "cmdevhub";
	$b = &$a;	// $b อ้างอิงหน่วยความจำที่ $a ชี้อยู่
	$b = "This is chiangmai dev hub";

	echo $a; // ผลลัพธ์ This is chiangmai dev hub
?>  

วิธีการก็คือ ใส่เครื่องหมาย & (ampersand) ข้างหน้าตัวแปรที่เราต้องการอ้างอิงหน่วยความจำเท่านั้น ก็คล้ายๆ ภาษา C แหละครับ จากการเขียน PHP มานานพอสมควร โอกาสใช้นั้น มีน้อยมากๆ เลย ครับ (แต่รู้ไว้ใช่ว่า จริงไหม)

ขอบเขตของตัวแปร (Variable Scope)

เมื่อเราสร้างตัวแปรมาสักตัวหนึ่ง ก็ใช่ว่าเราจะสามารถใช้งานตัวแปรนั้นๆ ได้ตลอดทั้งโปรแกรม ตัวแปรบางตัว สร้างไว้ในฟังก์ชั่น ก็จะสามารถใช้งานได้ภายในฟังก์ชั่นนั้นๆ เท่านั้น ถ้าหากเราไม่ทราบถึงขอบเขตของตัวแปรแล้ว อาจทำให้โปรแกรมของเราทำงานผิดพลาดได้ เพราะเราอาจจะกำหนดค่าไปซ้ำกับตัวแปรที่เราไม่ต้องการก็ได้ ขอบเขตของตัวแปร มีทั้งหมด 4 แบบดังนี้

  1. Local variable
  2. Function parameter
  3. Global variable
  4. Static variable

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

1.Local variable

เป็นตัวแปรที่ประกาศในฟังก์ชั่น และใช้งานได้แต่ภายในฟังก์ชั่นที่ประกาศไว้เท่านั้น (อันนี้ขอเน้นเลยล่ะครับ โดยเฉพาะ ถ้าเขียนเป็น OO เมื่อไหร่ สนุกสนานกันแน่นอน) ลองดูตัวอย่างกันครับ

 <?php
	$x = 10;
	function showx() {
		$x = 0;
		echo "x is " . $x;
	}
	// เริ่มทำงานตรงนี้
	showx();
	echo "<br />";
	echo "x is " . $x;
?> 

จากตัวอย่าง จะเห็นว่า เราประกาศตัวแปรชื่อเดียวกันคือ $x แต่ตัวหนึ่งอยู่ภายในฟังก์ชั่น showx() ส่วนอีกตัวอยู่ภายนอกฟังก์ชั่น เมื่อเราเรียกใช้ฟังก์ชั่น showx() คำสั่ง echo ในฟังก์ชั่น จะพิมพ์ค่า $x ที่อยู่ในฟังก์ชั่นออกมา แต่ถ้าหากเราทำการลบคำสั่ง $x = 0; ออกไป จะเกิด Notice: Undefined variable: x เนื่องจากตัวแปร $x ไม่ได้ถูกประกาศขึ้นมา และฟังก์ชั่น showx() ก็มองไม่เห็นตัวแปร $x ที่อยู่ข้างนอก ลองดูภาพได้ครับ

จากรูป ผมได้ทำการ comment คำสั่ง $x = 0; ออกไป ทำให้ในฟังก์ชั่น showx() ไม่มีตัวแปร $x อยู่ จึงเกิด error แบบนี้ขึ้น (ขึ้นอยู่กับการปรับระดับ error ในไฟล์ php.ini ด้วยนะครับ)

อ่า แล้วคำสั่ง global ล่ะ คำสั่งที่เอาไว้ใช้เรียกตัวแปรภายนอก เข้ามาภายในฟังก์ชั่น คำสั่งนี้ เมื่อประกาศแล้ว ตัวแปรนั้นๆ จะกลายเป็น global variable ไปโดยอัตโนมัติ คือ ไม่่ว่าจะทำการเรียกตัวแปรนี้ที่ไหน ก็จะถือว่าเป็นตัวแปรเดียวกันหมด ลองดูตัวอย่างนะครับ

สรุปง่ายๆ ก็คือ Local variable จะมองเห็น และใช้งานได้ภายในฟังก์ชั่นที่ประกาศตัวแปรนั้นๆ ขึ้นมาเท่านั้น แต่ถ้าหากเราใช้คำสั่ง global เมื่อไหร่ ตัวแปรนั้นจะกลายเป็น Global variable ไปทันที ซึ่งจะมองเห็นเป็นตัวแปรตัวเดียวกันทั้งโปรแกรม

2.Function parameter

ง่ายๆ ตรงๆ เลยครับ เป็นตัวแปรที่รับค่าในฟังก์ชั่น ซึ่งก็เหมือนกับ Local variable ที่จะมองเห็น และใช้งานได้ภายในฟังก์ชั่นนั้นๆ เท่านั้น เอาไว้เราค่อยมาต่อกันในเรื่องของฟังก์ชั่นล้วนๆ เลยล่ะกันครับ ตรงนี้ก็ติดไว้แค่นี้ก่อน ลองดูตัวอย่างนะครับ

 <?php
	function sqr($num) {
		$num = $num * $num;
		return $num;
	}
?> 

จากตัวอย่าง เป็นฟังก์ชั่นที่คำนวนเลขยกกำลังสองของค่าที่ส่งเข้ามา และคืนค่ากลับไป ตัวแปรแบบ Function parameter นี้จะถูกสร้างขึ้นตอนที่ฟังก์ชั่นนั้นถูกเรียก และจะถูกทำลายเมื่อฟังก์ชั่นนั้นทำงานเสร็จสิ้น

3.Global Variable

จากตัวอย่างใน Local variable ตัวอย่างสุดท้าย ผมได้ยกตัวอย่างตัวแปรแบบ global ไปแล้ว สรุปง่ายๆ ก็คือ ตัวแปรไหนที่ถูกประกาศเป็น global ตัวแปรนั้นจะสามารถถูกเรียกใช้งานจากที่ไหนก็ได้ในโปรแกรม โดยวิธีการประกาศตัวแปรให้เ็ป็น global ทำได้โดยใช้คำสั่ง GLOBAL ตามด้วยชื่อตัวแปรนั้นๆ ลองดูตัวอย่างอีกสักครั้งครับ

 <?php
	$value = 15;
	function plus() {
		GLOBAL $value;
		$value++;
		echo $value;
	}
	plus();	// ผลลัพธ์ 16
?> 

(จริงๆ แล้วมีอีกวิธีหนึ่ง คือนำตัวแปร $value ไปใส่ในตัวแปรแบบ super global ที่ชื่อ $_GLOBAL แต่วิธีนี้ เดี๋ยวเราค่อยมาคุยกันครับ)

4.Static variable

ปกติแล้ว ถ้าหากเราสร้างตัวแปรอะไรขึ้นมาสักตัวหนึ่งในฟังก์ชั่นเป็นแบบ Local variable ตัวแปรนั้นๆ จะถูกทำลายเมื่อฟังก์ชั่นนั้นทำงานเสร็จสิ้น แต่ตัวแปรแบบ Static จะยังคงอยู่ จนกว่าโปรแกรมนั้นจะทำงานเสร็จสิ้น วิธีการสร้างตัวแปร Static ก็เหมือนกับการสร้างตัวแปรทั่วๆ ไปแหละครับ แต่ให้เขียนคำสั่ง STATIC นำหน้าตัวแปรนั้นๆ ลองดูตัวอย่างกันครับ

 <?php
	function getNum() {
		STATIC $num = 0;
		$num++;
		echo $num;
		echo "<br />";
	}

	getNum();	// ผลลัพท์ 1
	getNum();	// ผลลัพท์ 2
	getNum();	// ผลลัพท์ 3
?> 

จะเห็นว่าตัวแปร $num ยังคงเก็บค่าเอาไว้ ถึงแม่ว่าฟังก์ชั่นนั้นจะทำงานเสร็จแล้วก็ตาม วิธีนี้ ใช้เขียนโปรแกรมนับจำนวนครั้งที่เรียกฟังก์ชั่นได้น่ะครับ จะได้ดูว่า โปรแกรมเรา Optimize ได้ดีหรือยัง หรือฟังก์ชั่นที่เรียกใช้บ่อยๆ สามารถเขียนให้สั้นลงกว่านี้ได้หรือไม่

ค่าคงที่ (Constant)

เป็นการกำหนดค่าที่ไม่สามารถเปลี่ยนได้ในโปรแกรมแล้ว และค่านั้นจะอยู่ไปจนจบโปรแกรม ใช้งานมากพอสมควร โดยเฉพาะการกำหนดค่าที่เรารู้แน่นอนอยู่แล้ว เช่น PI ค่าคงที่สามารถกำหนดได้โดยใช้คำสั่ง define() ลองดูตัวอย่างกันนะครับ

 <?php
	define("PI", 3.1415926);

	echo "ค่าพายคือ " . PI;	// พิมพ์ 3.1415926 ออกมา
	echo "<br />";
	$cur = 3 * 3 * PI;
	echo "พื้นที่วงกลมรัศมี 3 หน่วย คือ " . $cur; // ผลลัพท์ 28.274328
?> 

ก็จบกันไปอีกอันหนึ่งสำหรับเรื่องของตัวแปร แต่ก็ไม่จบหมดซะทีเดียว เพราะยังเหลือตัวแปรอีก 2 ชนิดคือ super global และ variable variable (ประมาณ $$a = $b; หรือ ${a}; ทำนองนี้) ก็ขอติดไว้ก่อนครับ ขออนุญาติไปเขียนตอนต่อๆ ไปก่อน เดี๋ยวจะไม่จบเอา อย่าลืมติดตามนะครับ

Posted in php, tutorial | Tagged , | Leave a comment