Slide: Introduction to WordPress Theme Development

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

Google Maps V3 + HTML5

จากบล็อคก่อนหน้านี้ที่แนะนำการใช้งาน Google Maps V3 ให้ลองไปใช้ดูกันแล้วนั้น อย่างหนึ่งที่ไม่ชอบก็คือตำแหน่งเริ่มต้นนั้นมันตายตัวไปหน่อย คือกำหนดแล้วฝังเข้าไปในโค้ด JavaScript เลย แล้วถ้าเราต้องการทำเว็บแอพพลิเคชั่น (เพื่อให้มันสั้นลงต่อไปจะเรียก ‘แอพ’ หรือ ‘app’) ที่คำนึงถึงตำแหน่งผู้ใช้เป็นสำคัญ เช่น ตำแหน่งร้านอาหารที่น่าสนใจใกล้เคียงนั้นๆ หรือ ร้านค้าลดราคาใกล้ๆ เป็นต้น ดังนั้นอย่างแรกที่จำเป็นก็คือตำแหน่งที่เราอยู่ปัจจุบัน เพื่อนำมาข้อมูลที่เกี่ยวข้องมาแสดงผล

ซึ่งในตัวอย่างที่จะทำนี้เป็นการพัฒนาต่อจากบล็อคก่อนหน้านี้ดังนั้นก็ให้ดาวน์โหลดไฟล์ maps-demo.html.zip มาไว้ที่เครื่องก่อนเพื่อเตรียมตัวแก้ไข ซึ่งด้านในมีโค้ดด้านล่างนี้ (ดูตัวอย่างการแสดงผล)

<!DOCTYPE html>
<html>
  <head>
    <title>Google Maps V3 Demostrate</title>
    <script src="http://maps.googleapis.com/maps/api/js?sensor=true"></script>

    <script>
      function initWithMapStart() {
        var latlng = new google.maps.LatLng(13.75, 100.517);
        var mapOptions = {
                            zoom: 12,
                            center: latlng,
                            mapTypeId: google.maps.MapTypeId.ROADMAP
                        };
        var maps = new google.maps.Map(
                         document.getElementById('map-canvas'),
                         mapOptions
                   );

        var marker = new google.maps.Marker({
                            position: latlng,
                            map: maps,
                            animation: google.maps.Animation.DROP,
                            title: "Welcome to Thailand"
                        });

        var info = new google.maps.InfoWindow({
                            content: '<h1>Hello</h1>'
                        });
        google.maps.event.addListener(marker, 'click', function(){
            info.open(maps, marker);
        });
      }
    </script>

    <style>
      header,
      footer {
        text-align: center;
      }
      #map-canvas {
        display: block;
        margin: 20px auto;
        height: 400px;
        width: 640px;
        background-color: #ccc;
      }
    </style>
  </head>
  <body onload="initWithMapStart()">
    <header>
      <h1>Google Maps Demo</h1>
    <header>
    <article>
      <div id="map-canvas"></div>
    </article>
    <footer>
      <small><a href="http://we.in.th/">we.in.th</a></small>
    </footer>
  </body>
</html>

fig.1: โค้ดเดิมสำหรับแสดงผลแผนที่

จากที่บอกในข้างต้นว่าจะพัฒนาต่อจากของเดิมที่มีอยู่แล้ว โดยสิ่งที่เพิ่มขึ้นมากก็คือคุณสมบัติที่เรียกว่า Geolocation ซึ่งอยู่ใน HTML5 ทำสามารถดึงข้อมูลตำแหน่ง เช่น พิกัด (Latitude, Longitude) หรือ ที่อยู่ปัจจุบัน ของผู้ใช้ขณะนั้นมาแสดง แต่ก่อนที่จะแสดงนั้นเบราเซอร์จะขออนุญาตจากผู้ใช้ก่อนเสมอ หากไม่ต้องการให้เว็บไซต์นำตำแหน่งไปใช้งานก็ปฏิเสธได้ ใช้งานได้กับ IE9+, Firefox 3.5+, Safari5+ และ Google Chrome 4+ โดยที่ ดังนั้นให้เพิ่มโค้ดด้านล่างถัดจากบรรทัดที่ 32 ลงไป ดังนี้

if ( (typeof( window.navigator) != 'undefined') && !!navigator.geolocation ) {
    navigator.geolocation.getCurrentPosition(
        function(position) {
            panToCurrentLocation(position, maps, marker);
        },
        errorOccur
    );
}

fig.2: โค้ดสำหรับพิกัดที่ได้จากเบราเซอร์มาแสดงผล

Google Maps with Location Acquisition Notificationโดยที่

  • บรรทัดที่ 1 คือ การตรวจสอบว่าเบราเซอร์นี้รองรับ Geolocation หรือไม่
  • บรรทัดที่ 2-7 คือ การเรียกใช้งาน Geolocation ผ่านตัวแปร navigator ซึ่งก่อนจะดึงข้อมูลตำแหน่งของผู้ใช้เบราเซอร์จะขออนุญาตผู้ใช้ก่อนเสมอ เมื่อได้รับอนุญาตและได้ตำแหน่งผู้ใช้เรียบร้อยแล้วจะส่งไปยัง function(position) (บรรทัดที่ 3-5) โดยจะส่งไปให้ฟังก์ชั่น panToCurrentLocation ต่อไปพร้อมกับตัวแปร position, maps และ marker แต่ถ้าไม่สามารถอ่านพิกัดได้จะไปทำที่ฟังก์ชั่น errorOccur แทน

ถัดไปคือการสร้างฟังก์ชัน panToCurrentLocation และ errorOccur ขึ้นใหม่ ตามที่ได้ระบุไว้ใน fig.2 ดังนี้

function panToCurrentLocation(position, maps, marker) {
  var latlng = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
  maps.setCenter( latlng );
  maps.panTo( latlng );

  marker.setPosition( latlng );
  marker.setAnimation( google.maps.Animation.DROP );
}

function errorOccur( error ) {
  console.log( error );
}

fig.3: JavaScript สำหรับเปลี่ยนตำแหน่งในแผนที่

โดยที่

  • บรรทัดที่ 2: สร้างพิกัดจากแผนที่ใหม่
  • บรรทัดที่ 3: กำหนดจุดศูนย์กลางให้แผ่นที่ใหม่
  • บรรทัดที่ 4: เลื่อนตำแหน่งของแผนที่ไปยังตำแหน่งใหม่ที่ได้
  • บรรทัดที่ 6: เปลี่ยนตำแหน่งของ marker ให้แสดงที่ตำแหน่งปัจจุบัน
  • บรรทัดที่ 7: กำหนดแอนนิเมชั่นที่จะใช้แสดงผล marker

จากที่ทดลองใช้งานการค้นหาตำแหน่งนั้นอาจคลาดเคลื่อนได้ไม่ถูกต้องทุกครั้ง ดูตัวอย่างได้ที่ไฟล์ maps-demo-navigation หรือดาวน์โหลดไฟล์ maps-demo-navigation.html

ข้อมูลเพิ่มเติม:

Google Maps V3 Introduction

ก่อนหน้านี้เคยเขียนวิธีการนำเอา Google Maps มาใช้งานกับเว็บไซต์ด้วยกัน 2 ตอน (1, 2) ตอนที่เขียนไปนั้น Google Maps เวอร์ชั่น 2.x ปัจจุบันอยู่ในสถานะ deprecated หรืออยู่ระหว่างการเลิกใช้งานนั้นเอง โดยตอนนี้ Google Maps เองก็พยายามเข็ญให้นักพัฒนาขยับไปใช้ Google Maps เวอร์ชั่นปัจจุบันคือเวอร์ชั่น 3 หรือเรียกสั้นๆ ว่า V3 ซึ่งการเรียกใช้งานนั้นง่ายกว่าเวอร์ชั่นเก่ามาก อย่างแรกที่เห็นได้ชัดคือเราไม่จำเป็นต้องสมัครเพื่อขอ API Key สำหรับใช้ดาวน์โหลด Google Maps Library อีกต่อไปแล้ว และการกำหนดค่าทั้งหมดใช้การกำหนดค่าผ่าน Object ที่เข้าใจได้ง่ายกว่าเวอร์ชั่นเก่ามาก
Continue reading

Apache + PHP สำหรับ OS X

ก่อนหน้าผมเคยลง MAMP เพื่อใช้ Apache, PHP และ MySQL เหมือนกัน แต่เพราะว่าต้องลงโปรแกรมอื่นๆ ร่วมด้วย อย่างเช่น Xcode ที่มีขนาดใหญ่เอาเรื่องอยู่เหมือนกัน พอมีโอกาสได้ format เครื่องใหม่ ก็เลยหาวิธีอื่นเอาส่วนที่ไม่จำเป็นออกไปบ้างที่กว่า

เท่าที่ได้หาข้อมูลพบว่าใน OS X (ที่ใช้คือ 10.6.4) มี Apache และ PHP ติดมากับเครื่องเป็นที่เรียบร้อยแล้ว เพียงแค่ยังไม่ได้เปิดใช้งานเท่านั้น ดังนั้นหน้าที่ของเราคือ เปิดการใช้งานซะ

  1. อย่างแรกที่ต้องทำคือทำให้ Apache และ PHP รู้จักกันซะก่อน ซึ่งโดย default แล้ว จะไม่รู้จักกัน วิธีง่ายๆ คือไปที่ไฟล์ ‘/private/etc/apache2/httpd.conf’ จากนั้นเอาเครื่องหมาย ‘#’ ที่บรรทัด 115 ออกเพื่อให้ Apache โหลดโมดูล PHP5 ขึ้นมาเมื่อเริ่มทำงาน
    เปิดการใช้งาน PHP Module

    เปิดการใช้งาน PHP Module

  2. ในไฟล์เดียวกันนี้เอง (‘/private/etc/apache2/httpd.conf’) ตรงบรรทัดที่ 167 จะเป็นตำแหน่ง DocumentRoot หากต้องการเปลี่ยนก็สามารถเปลี่ยนได้ตรงนี้ทันที แต่ในระยะยาวที่ผมชอบทำคือกำหนดค่าใน DocumentRoot ให้เป็น link ที่ชี้ไปยัง DocumentRoot ที่เราต้องการอีกทีเพื่อที่จะได้ไม่ต้องมาเปลี่ยนค่าในไฟล์นี้อีกครั้งเมื่อมีการเปลี่ยนตำแหน่งของ DocumentRoot
    DocumentRoot

    DocumentRoot

  3. สุดท้ายก็ start server ด้วยคำสั่ง apachectl
    เริ่มการทำงานของ Apache

    เริ่มการทำงานของ Apache

  4. สุดท้ายลองเขียนสคริปต์ PHP เพื่อทดสอบ
    ทดสอบสคริปต์ PHP

    ทดสอบสคริปต์ PHP

เท่านี้เราก็ได้ Server เล็กๆ เอาไว้เขียน Web app. กันแล้ว ส่วนที่เหลือคือฐานข้อมูลที่ยังไม่มีติดมากับ OS X เรื่องนี้ใครอยากได้อะไรก็แล้วถนัดเลยครับ

เครื่องมือ: Mac OS X 10.6.4, Terminal

Zend Framework 1.10 + Doctrine 1.2

ปัญหาเริ่มต้นที่ว่า ผมใช้ Zend Framework อยู่ตอนนี้ แต่ด้วยฐานข้อมูลที่มันไม่นิ่ง และกำลังมองเรื่องปริมาณการใช้งานที่เห็นว่างานนี้ถ้าเกิด มีผู้ใช้เยอะแน่ๆ ปัญหาหนึ่งที่เห็นว่ามันยังเป็นคอขวดในโปรเจ็คก็เรื่อง transaction ของฐานข้อมูล ซึ่งตอนแรกเขียน Class Map กับตารางปวดหัวมากที่เดียว เพราะอย่างหนึ่งที่ต้องยอมรับก็เพราะไม่ได้เป็นคนออกแบบเองแล้วเอกสารประกอบให้มาน้อยมาก ได้แก่ Data Dictionary ที่หยาบเอามากๆ และ ER Diagram ที่ต้องมานั่งเล็งเอาจากภาพหน้าจอโปรแกรมออกแบบ ER Diagram อีกที อย่างสุดท้ายก็คือในการใช้งานจริง ต้องเอาไปใช้ร่วมกับ Oracle อันนี้ต้องบอกว่าเป็นที่ผมเองที่ไม่เคยลองเล่นกับ Oracle มาก่อนเลยค่อนข้างจะเป็นปัญหา

สุดท้ายเลยตัดสินใจมองหา ORM (Object-Relational Mapping) มาช่วยงานดีกว่า เพราะอย่างที่เห็นได้ชัดคือ ORM มันทำงาน On top พวกฐานข้อมูลอีกที ไอ้เรื่องการจะเปลี่ยนจาก MySQL ที่ลองอยู่ไปเป็น PostgreSQL หรือ Oracle คงไม่ใช่ปัญหาใหญ่เท่าไหร่นัก อย่างมากก็แก้ที่ตัว ORM เท่านั้น แต่ก่อนอื่นต้องบอกกว่า Zend_Db ของ Zend ก็เก่งใช้ได้นะครับ แต่ข้อเสียคือถ้าต้องมา Optimize ให้เข้ากับฐานข้อมูลก็ใช้พลังงานเยอะเหมือนกัน เรียกได้ว่าถ้าต้องจบงานด้วยระยะเวลาขนาดที่เป็นอยู่คงถึงขั้นธาตุไฟเข้าแทรกอ้วกเป็นเลือดกันแน่นอน

เท่าที่ลองหาข้อมูลดู ก็มี Doctrine นี่ล่ะครับให้ PHP Developer ได้ใช้กัน แอบดีใจเล็กๆ ที่ฝั่ง PHP ก็มี ORM ใช้แล้ว ผมเองเลือกใช้ 1.2 ครับ เพราะยังมีเอกสารให้อ่านอยู่ แต่ขณะที่เขียนนี้ Doctrine มีเวอร์ชั่น 2.0 เป็น beta release ให้ลองใช้งานกันเรียบร้อยแล้ว ทำงานบน PHP 5.3 เท่านั้น!

ในอนาคตอันใกล้ๆ มีแผนว่าจะเขียนเรื่องการใช้งาน Doctrine 1.2 กับ Zend Framework 1.10 ลง blog เหมือนกัน แต่ช่วงนี้ขอเผางานนี้ให้เสร็จก่อนนะครับ แรกๆ คงเป็นการรวบยอดจากใน ZendCasts มาก่อน จากนั้นค่อยเปลี่ยนจาก Doctrine 1.2 เป็น Docctrine 2.0 กับ Zend Framework เวอร์ชั่นขณะที่เขียน ซึ่งเท่าที่ตามอ่านในรายการพัฒนาของ Zend Framwork แล้วก็แอบใจชื้นขึ้นมาอีกนิด เพราะทาง Zend Framework เองก็มีแผนที่จะพัฒนาให้สามารถเรียกใช้ Doctrine ได้ง่ายขึ้นกว่าในปัจจุบัน แต่ถ้าใครใช้ Symfony อยู่ว่าคงคุ้นเคยกับ Dcotrine นี่แล้วเพราะเท่าที่อ่านดู Symphony สามารถใช้ command line  สร้างโปรเจ็คที่ทำงานกับ Doctrine ได้นานแล้ว

สุดท้ายถ้าใครต้องการเล่นกับ Doctrine และ Zend Framework ก็ลองนัั่งฟังได้ที่ www.zendcasts.com ครับ

Doctrine, Zend Framework, Zendcasts

Google Maps :: แสดงผลข้อมูลการจราจรได้แล้ว

ข้อมูลการจราจรจาก อนุเสาวรีย์ชัยสมรภูมิ ไปยัง มหาวิทยาลัยธรรมศาสตร์ ท่าพระจันทร์

ข้อมูลการจราจรจาก อนุเสาวรีย์ชัยสมรภูมิ ไปยัง มหาวิทยาลัยธรรมศาสตร์ ท่าพระจันทร์

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

จากที่ลองค้นดูอีเมล์ที่ Google แจ้งการปรับปรุงให้ทราบเรื่อยๆ [แต่ไม่ได้สนใจ] ก็พบว่าข้อมูลการจราจร[GTrafficOverlay] เพิ่มเข้ามาตั้งแต่เวอร์ชั่น 2.81 ครับ [ปัจจุบันเวอร์ชั่น 2.170 อัพเดตวันที่ 6 สิงหาคม 2552]

Google Maps: http://maps.google.co.th
Issue Tracker: http://code.google.com/p/gmaps-api-issues/wiki/JavascriptMapsAPIChangelog