เปลี่ยนจาก Geshi Filter มาเป็น Syntax Highlighter (Version โมเอง) เลยแจ้ง ณ ที่นี้

ด้วยปกติแล้วผมยอมให้ทุกคนเขียนบทความได้ (เฉพาะคนที่ผมอนุญาติ ใครสนใจก็บอกได้ครับ) แล้วแต่ละคนมีปัญหาในการเขียน Code แล้วมัน render ผิดปกติ แล้วใช้ Text Editor ไม่ได้ คราวนี้ผมได้ทำ solution ง่ายๆไว้และสามารถ edit ได้ด้วยใน text editor แต่ไม่สามารถใช้ tag <br> ได้แค่นั้นเองนี้คือตัวอย่างโค้ดครับ

<br><?php<br>echo "Hello World";<br>?><br>

แบบนี้เป็นต้นครับ โดยถ้าอยากจะ enter ภายใน code ให้คุณใช้ Shift+Enter ครับผม แล้วมันก็จะขึ้นบรรทัดใหม่ให้ (ไม่สามารถ enter เฉยๆได้เพราะมันจะเป็น tag <p>) ก็ฝากไว้เรื่องนี้กับทุกๆท่านนะครับเพราะจะเอา Geshi ออกแล้วนะครับ

Sub-Domain or Many File in Page Caching with CodeIgniter

คราวก่อนเขียนเรื่อง Page Caching with CodeIgniter and Cache Clearing code เป็นการเกริ่นถึงวิธีใช้งาน Page Caching ของ Codeigniter รวมไปถึงผมได้แนบคลาสสำหรับการ ลบแคช (Cache Clearing) เข้าไปด้วย เพื่อความสะดวกในการใช้งาน

บทความนี้เลยคล้ายๆ กับบทต่อจากเรื่องข้างต้นนะครับ เป็นกรณีศึกษาที่ผมเจอและจำเป็นต้องใช้ เลยมาขอแชร์ความรู้นิดหนึ่ง เผื่อมีใครมีแนวทางที่ดีกว่าของผมนะครับ

Mini Introduction Page Caching with CodeIgniter

เกริ่นพื้นฐานเล็กน้อยครับ ปกติการทำ Page Caching ใน Codeigniter เราจะเก็บลงโฟลเดอร์หนึ่ง สมมุติว่าชื่อ "system/cache/" นะครับ ส่วนชื่อไฟล์ที่ทำการ Cache ก็จะนำเอา URI(หรือ URL) มาเข้ารหัสด้วย md5 เช่น "http://lab.tosdn.com" จะถูกเข้ารหัสและนำไปตั้งชื่อไฟล์ คือ "53db6ab6193a34a4ebac45ebd7592da6"

ถ้าไม่เข้าใจ ไปอ่านเต็มๆ ที่บทความเก่าครับ - Page Caching with CodeIgniter and Cache Clearing code

Problem of Page Caching with CodeIgniter

คราวนี้ ปัญหาที่ผมเจอมี 2 ข้อครับ

1. หากการทำ Caching มีไฟล์มากมายมหาศาลจะทำอย่างไร? ซึ่งปํญหานี้อาจจะไม่ค่อยสำคัญ หากเว็บเราไม่ได้คิดการใหญ่ และหน้าเพจไม่มากนัก

2. ถ้าเราเปิดให้สมาชิกมี Sub-Domain ได้เอง แปลว่า ในเว็บเราจะเสมือนมีเว็บสมาชิกย่อยลงไปอีก คราวนี้ ปัญหาที่หนีไม่พ้นก็คือ ปัญหาในข้อ 1 และ ปัญหาที่สำคัญตามมาคือ การบริหารจัดการไฟล์ Caching ที่ยากขึ้น เช่น สมาชิกคนนี้เปลี่ยนแปลงชื่อใน profile ตัวเอง ดังนั้น หน้าใน Sub-Domin ต้องมีการเปลี่ยนแปลงด้วย เช่นนั้นแล้วเราต้องมาทำการค้นหาว่า Cacgin Page ของสมาชิกคนนี้ มีไฟล์ไหนบ้าง แค่คิดก็สนุกแล้วครับ T-T

หรือบางคนไม่ได้ใช้เป็น Sub-Domain แต่ใช้เก็บค่าสมาชิกใน Session หรือ Cookie หรือ อื่นๆ แต่ URI ยังใช้คงเดิม เช่น สมาชิก A,B,C ก็เข้าแก้ไขชื่อตนเองใน http://www.web.com/profile เหมือนกัน ดังนั้น Caching ที่เก็บ มันก็จะมีชื่อเหมือนกัน อยู่ที่ว่า Codeigniter ทำการ Generate Page Caching ให้คนไหนก่อน พอคนต่อมาเข้ามาใช้ มันก็จะเจอข้อมูลของคนแรกที่ถู Generate ไว้ มันช่างวุ่นวายได้อีก T-T

Solution of Page Caching with CodeIgniter

เมื่อเจอปัญหาแบบนั้น ผมเลยลองแก้ไขด้วยการจัดระเบียบโฟลเดอร์ของ Page Caching ให้ลึกลงไปอีก 2 ชั้นโดยชั้นแรกเก็บเป็นอักษรหน้า 3 ตัว และชั้นสองเก็บ อักษรเต็มของชื่อ Domain หรือ Sub-Domain ไว้ และไฟล์ข้างในโฟลเดอร์นี้ ก็จะเก็บเฉพาะ หน้านั้นๆของ Domain หรือ Sub-Domain ที่ระบุไว้เท่านั้น

เอาหละครับ เมื่อทราบที่มา ปัญหา และวิธีแก้ไข ก็ลงมือกันเลย :D

How to use Sub-Domain or Many File in Page Caching with CodeIgniter

1. สร้างไฟล์ Library ใน Application มาหนึ่งตัวครับ เช่น ปล. หากในบทความก่อน ใครสร้างไว้แล้วก็ข้ามไปครับ

/system/application/libraries/My_Output.php (ใครตั้ง Suffix ว่าอะไรก็ใส่แทน My ไปเลยครับ)

2. ทำการ Extend Output ของ CodeIgniter และใส่โค้ด ดังนี้ครับ ปล. หากในบทความก่อน ใครสร้างไว้แล้วก็ทับได้เลยครับ เพราะผมพ่วง clear_cache() มาในโค้ดนี้แล้ว

 if ( ! defined('BASEPATH')) exit('No direct script access allowed');
<br> /********<br> / TOSDN - URI from CI URI Library<br> / Update 12/12/2551 2:26<br> ********/</p> <p>/**<br> * Page Caching management class (extends from CI_Output)<br> *<br> *<br> * @package        CodeIgniter<br> * @subpackage    Libraries<br> * @hacked-by    Chitpong Wuttanan<br> */<br> class My_Output extends CI_Output {
    var $cache_name;
    <br> var $cache_expiration;
    /**<br> * Set Cache<br> *<br> * @access    public<br> * @param    integer<br> * @return    void<br> *//**<br> * Update/serve a cached file<br> *<br> * @access    public<br> * @return    void<br> */<br> function _display_cache(&$CFG, &$URI)<br> {
        <br> $cache_path = ($CFG->
        item('cache_path') == '') ? BASEPATH.'cache/' : $CFG->
        item('cache_path');
        if ( ! is_dir($cache_path) OR ! is_really_writable($cache_path))<br> {
            <br> return FALSE;
            <br>
        }
        $cache_topdomain_uri = md5($CFG->
        item('base_url'));
        <br> $cache_path_folder_uri = $cache_path."/".substr($cache_topdomain_uri, 0, 3)."/".$cache_topdomain_uri."/";
        // Build the file path.  The file name is an MD5 hash of the full URI<br> $uri =    $CFG->
        item('base_url').<br> $CFG->
        item('index_page').<br> $URI->
        uri_string;
        $filepath = $cache_path_folder_uri.md5($uri);
        if ( ! @file_exists($filepath))<br> {
            <br> return FALSE;
            <br>
        }
        if ( ! $fp = @fopen($filepath, FOPEN_READ))<br> {
            <br> return FALSE;
            <br>
        }
        flock($fp, LOCK_SH);
        $cache = '';
        <br> if (filesize($filepath) >
        0)<br> {
            <br> $cache = fread($fp, filesize($filepath));
            <br>
        }
        flock($fp, LOCK_UN);
        <br> fclose($fp);
        // Strip out the embedded timestamp<br> if ( ! preg_match("/(\d+TS--->
        )/", $cache, $match))<br> {
            <br> return FALSE;
            <br>
        }
        // Has the file expired? If so we'll delete it.<br> if (time() >
        = trim(str_replace('TS--->
        ', '', $match['1'])))<br> {
            <br> @unlink($filepath);
            <br> log_message('debug', "Cache file has expired. File deleted");
            <br> return FALSE;
            <br>
        }
        // Display the cache<br> $this->
        _display(str_replace($match['0'], '', $cache));
        <br> log_message('debug', "Cache file is current. Sending it to browser.");
        <br> return TRUE;
        <br>
    }
    /**<br> * Write a Cache File<br> *<br> * @access    public<br> * @return    void<br> */<br> function _write_cache($output)<br> {
        <br> $CI =& get_instance();
        <br> $path = $CI->
        config->
        item('cache_path');
        $cache_path = ($path == '') ? BASEPATH.'cache/' : $path;
        if ( ! is_dir($cache_path) OR ! is_really_writable($cache_path))<br> {
            <br> return;
            <br>
        }
        $cache_topdomain_uri = md5($CI->
        config->
        item('base_url'));
        <br> $cache_path_folder = $cache_path."/".substr($cache_topdomain_uri, 0, 3);
        <br> $cache_path_folder_uri = $cache_path_folder."/".$cache_topdomain_uri."/";
        if ( ! is_dir($cache_path_folder) OR ! is_really_writable($cache_path_folder))<br> {
            <br> @mkdir($cache_path_folder, 0755);
            <br> @mkdir($cache_path_folder_uri, 0755);
            <br>
        }
        if(empty($this->
        cache_name)) {
            <br> $uri = $CI->
            config->
            item('base_url').<br> $CI->
            config->
            item('index_page').<br> $CI->
            uri->
            uri_string();
            <br> $cache_path_folder_uri .= md5($uri);
            <br>
        }
        else {
            <br> $cache_path_folder_uri .= md5($this->
            cache_name);
            <br>
        }
        if ( ! $fp = @fopen($cache_path_folder_uri, FOPEN_WRITE_CREATE_DESTRUCTIVE))<br> {
            <br> log_message('error', "Unable to write cache file: ".$cache_path_folder_uri);
            <br> return;
            <br>
        }
        $expire = time() + ($this->
        cache_expiration * 60);
        if (flock($fp, LOCK_EX))<br> {
            <br> fwrite($fp, $expire.'TS--->
            '.$output);
            <br> flock($fp, LOCK_UN);
            <br>
        }
        <br> else<br> {
            <br> log_message('error', "Unable to secure a file lock for file at: ".$cache_path_folder_uri);
            <br> return;
            <br>
        }
        <br> fclose($fp);
        <br> @chmod($cache_path_folder_uri, DIR_WRITE_MODE);
        log_message('debug', "Cache file written: ".$cache_path_folder_uri);
        <br>
    }
    function clear_cache($set_uri = NULL, $all=FALSE){
        <br> $CFG =& load_class('Config');
        <br> $cache_topdomain_uri = md5($CFG->
        item('base_url'));
        <br> $cache_path_folder_uri = $CFG->
        item('cache_path')."/".substr($cache_topdomain_uri, 0, 3)."/".$cache_topdomain_uri;
        if($all == FALSE) {
            <br> $filepath = ($CFG->
            item('cache_path') == '') ? BASEPATH.'cache/' : $cache_path_folder_uri."/".md5($set_uri);
            <br> if(file_exists($filepath))<br> {
                <br> @unlink($filepath);
                <br> log_message('debug', "Cache deleted for: ".md5($set_uri)." (".$set_uri.")");
                <br>
            }
            else {
                <br> return FALSE;
                <br>
            }
            <br>
        }
        else {
            <br> $filepath = ($CFG->
            item('cache_path') == '') ? BASEPATH.'cache/' : $cache_path_folder_uri;
            <br> if ($handle = opendir($filepath)) {
                <br> while (($file = readdir($handle))  !== false) {
                    <br> if ($file != "." && $file != "..") {
                        <br> @unlink($filepath."/".$file);
                        <br>
                    }
                    <br>
                }
                <br> closedir($handle);
                <br> log_message('debug', "Cache deleted for: ".md5($set_uri)." (".$set_uri.")");
                <br>
            }
            else {
                <br> return FALSE;
                <br>
            }
            <br>
        }
        <br>
    }
    <br>
}

3. วิธีการนำไปใช้ (Usage) ใช้เหมือนเดิมทุกประการครับ :D

$this->output->cache(60); //1 Hour $this->load->view(’profile.php’);

ปิดท้ายด้วยการอธิบายโค้ดนิดหนึ่งนะครับ

โค้ดตัวนี้ผมได้ทำการ extend ไว้กับคลาส Output เดิม และทำการสร้าง Function ในชื่อเดิม เพื่อเรียกใช้แทน Function เดิม โดย

_display_cache() - จะทำหน้าที่เรียกการแสดงผล โดยตรวจสอบว่ามีการทำ Caching ไว้ไหม ถ้ามี และยังไม่หมดอายุ ตามเวลาที่กำหนด ก็จะเรียก Cache โดยตรวจสอบก่อนว่ามาจาก URI ไหน ให้เข้ารหัสด้วย md5และตัด 3 ตัวแรกออกมา เพื่อเข้าโฟลเดอร์ชั้นแรก จากนั้นเข้าโฟลเดอร์ชั้นสอง ด้วยรหัส md5 ตัวเต็ม จากนั้นจึงจะเจอไฟล์ที่มันจะตรวจสอบ แต่ถ้าไม่เจอ มันจะไปเรียก _write_cache() เพื่อสร้างไฟล์ใหม่ทันที รวมไปถึงสร้างโฟลเดอร์ให้อัตโนมัติด้วยนะครับ

_write_cache() - อันนี้ทำหน้าที่สร้างไฟล์ครับ โดยมีขั้นตอนเหมือน _display_cache() ครับ แต่ทำหน้าที่สร้างไฟล์ในโฟลเดอร์ที่เรากำหนดไว้

clear_cache() - เอาไว้ Clear Cache ครับ ตามที่เคยเขียนไว้ใน Page Caching with CodeIgniter and Cache Clearing code

ยังไงก็ลองเล่นดูนะครับ หากมีวิธีที่ดีกว่านี้ ก็เสนอได้ครับ :D

 

อ้างอิง : Sub-Domain or Many File in Page Caching with CodeIgniter

Page Caching with CodeIgniter and Cache Clearing code

Introduction Page Caching with CodeIgniter

ใน CodeIgniter จะมีคำสั่งทำ Page Caching ไว้ให้อยู่แล้ว ซึ่งมันเอาไว้ทำการ Caching หน้าเว็บไซต์ที่ได้รับการประมวลผลแล้ว มห้กลายเป็น หน้า Statics ตามระยะเวลาที่เรากำหนดไว้ ดังนั้น เมื่อโหลดหน้านั้นขึ้นมาใหม่ภายในระยะเวลานั้น จะไม่ทำการประมวลผลอีก ซึ่งจะส่งผลให้เว็บโหลดเร็วขึ้นมากๆ (เช่น โหลดจาก 0.2 วินาที เหลือเพียง 0.0020 วินาที) รวมไปถึงประหยัดทรัพยากรณ์เซอเวอร์ได้อีกมากโข

ซึ่งวิธีการใช้ ก็ง่ายมากครับ แค่ใส่คำสั่ง $this->output->cache(5); ไว้ก่อนคำสั่งเรียก View จะหมายถึงการทำ Caching สำหรับหน้า (View) นั้นๆ เป็นเวลา 5 นาที เช่น

$this->output->cache(60); //1 Hour $this->load->view('profile.php');

ดังนั้น คำสั่งทั้งหมดในหน้า profile.php จะไม่ถูก ประมวลผลซ้ำภายใน 5 นาที หลังจากมีคนเข้าครั้งแรก เพราะระบบจะไปเรียกหน้า Cache มาแสดงแทน ซึ่ง เป็นหน้านิ่งๆ (Static page) เหมือน html ธรรมดาๆ

พอเข้าใจหลักการ Page Caching ของ CodeIgniter แล้วนะครับ คราวนี้ มาพูดถึงข้อจำกัดของมันบ้าง

Restriction of Page Caching with CodeIgniter

ข้อจำกัดของ Page Caching ด้วย CodeIgniter เท่าที่คนส่วนใหญ่ รวมถึงผมพบก็คือ มันง่ายเกินไป! เพราะมันทำงานอัตโนมัตินั่นเอง :D

เพราะ วิธีการทำงานของ Page Caching ใน CodeIgniter มันจะทำการ เก็บ output ของคำสั่งประมวลผลทั้งหมด ไปเก็บไว้ในชื่อไฟล์ ที่เข้ารหัสด้วย MD5 และชื่อไฟล์นั้น มันเอามาจาก URL หรือ URI ที่เรียกมันครับ เช่น

http://lab.tosdn.com

จะถูกเข้ารหัสและนำไปตั้งชื่อไฟล์ คือ

53db6ab6193a34a4ebac45ebd7592da6

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

Problem of Page Caching with CodeIgniter

อันนี้เป็นปัญหาที่ผมเจอ รวมถึงใครหลายๆ คนที่ใช้ CodeIgniter นั่นก็คือ ต้องการลบหน้าที่ Cache ออก โดยไม่ต้องรอให้หมดเวลา แต่เราสามารถสั่งการได้เอง

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

ดังนั้น ในระบบจัดการข้อมูลของผม จำต้องมีการลบ Cache (Clear Cache) ทุกครั้งที่มีการแก้ไข

แต่ CodeIgniter ทำไม่ได้ครับ :D

Solution of Page Caching with CodeIgniter

วิธีแก้ไขปัญหาข้างต้น หลายคนไปใช้ Smarty ซึ่งเป็นระบบการจัดการ Template (Template Engine) ที่ดีมากตัวหนึ่ง หรือไปใช้ตัวอื่นๆ นำมา Integrate รวมกับ Codeigniter แทนการใช้งานระบบ Template เดิมของมัน (ที่ผมเขียนมาทั้งหมดคือระบบ Template เดิมที่มันมีมาให้อยู่แล้วนะครับ อย่าเพิ่งสับสนๆ)

แต่ที่ผมลองใช้งาน มันจัดการ Template ได้ดีสมน้ำสมเนื้อมันเอง แต่ผมรู้สึกว่ามันใหญ่เทอะทะ เพราะระบบมันฉลาดเกินไป! กล่าวคือ ผมต้องการ Page Caching ทั้งหน้าแค่นั้น ไม่ได้ต้องการแบ่งส่วนการ Caching เช่น ส่วน Header ของเว็บทำการ Cache ไว้ แต่ Body ไม่ต้องทำ อะไรทำนองนั้น

เขียนมาถึงตรงนี้ ใครเคลิ้มตาม เจอปัญหาแบบผม และต้องการใช้งานแบบผม มาลุยแก้ปัญหากันดีกว่าครับ :D

How to Cache Clearing with CodeIgniter?

1. สร้างไฟล์ Library ใน Application มาหนึ่งตัวครับ เช่น

/system/application/libraries/My_Output.php (ใครตั้ง Suffix ว่าอะไรก็ใส่แทน My ไปเลยครับ)

2. ทำการ Extend Output ของ CodeIgniter และใส่โค้ด ดังนี้ครับ

<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');

/** * Clear Cache * * Responsible for sending final output to browser * * @package        CodeIgniter * @subpackage    Libraries * @added-by    Chitpong Wuttanan */ class My_Output extends CI_Output {

function clear_cache($set_uri = NULL){ $CFG =& load_class('Config'); $filepath = ($CFG->item('cache_path') == '') ? BASEPATH.'cache/' :       $CFG->item('cache_path').md5($set_uri);

if(file_exists($filepath)) { @unlink($filepath); log_message('debug', "Cache deleted for: ".$set_uri); } else { return FALSE; } } }

?>

3. วิธีการนำไปใช้ (Usage)

3.1 ใช้แบบเดิม โดยไม่ระบุ URI ซึ่งการทำงานจะเหมือนเดิมทุกอย่าง

$this->output->cache(60); //1 Hour $this->load->view('profile.php');

4. วิธีการลบ Cache (Clear Cache)

$this->output->clear_cache('http://www.web.com/profile');

มา อธิบายโค้ดกันนิดหนึ่งครับ

โค้ดตัวนี้ผมได้ทำการ extend ไว้กับคลาส Output เดิม เพื่อสะดวกต้อการเรียกใช้ครับ โดยทำการสร้าง Function ชื่อ  clear_cache() เข้าไป

ในฟังก์ชั่นนี้ จะ เรียก URI ที่เราระบุ ทำการเข้ารหัสด้วย md5 และ ลบออก ง่ายไหมครับ ไม่ต้องไป Integrate ระบบ Template Engine ให้ยุ่งยากเลย

Reference Page Caching with CodeIgniter and Cache Clearing code

วิธีทำให้ CodeIgniter มี Code completion กับ Netbeans

ในการทำ Code Completion ใน Netbeans ทำได้ 2 วิธีโดยวิธีแรกนั้น ลุงบ๊อบ สมาชิกภายในบอร์ด CodeIgniter ได้แปลและนำมาเผยแพร่ให้แก่ชุมชมแห่งนี้ครับ

วิธีแรกโดยลุงบ๊อบ

ผมคนนึงแหละคับที่ใช้ netbeans เขียนเพราะว่ามันมี feature ที่ผมชอบคือ Code completionซึ่ง ธรรมดาแล้วถ้าเรายังไม่ทำการ define class property ลงไป (ตามด้านล่าง) จะไม่สามารถทำ Code completion กับ codeigniter ได้อย่างสมบูรณ์..ต่อไปนี้ผมจะเป็นวิธีการ implement Codeigniter กับ Code completion ของ Netbean นะคับ1. พิม /** แล้วกดปุ่ม enter ตรงนี้ืำทำใต้ tag <?php นะคับ2. มันจะ Display เป็น block ออกมาแบบนี้

  /**  *  */

3. ต่อไปเราจะทำการ define class property ลงไปใน block ที่เราสร้างขึ้น

  /**  * @property CI_ // <-- พิมถึง @property CI_ จากนั้น ให้กด CTRL+ \ หรือ ถ้าไม่ขึ้นให้กด CTRL + space  */

จากนั้นมันจะขึ้นเป็น หน้าต่างตัว Code completion ขึ้นมาให้เราเลือกว่าเราจะ define ตัีวไหน4. Just for example, we want to use some functions from the email class  ..  * @property CI_Email $email  ...ทีนี้เราก็สารถ พิม $this->CI_Email -> แล้วก็จะมี Code completion ขึ้นมาแล้วคับตัวอย่างหลายๆอัน/*** @property CI_Loader $load* @property CI_Form_validation $form_validation* @property CI_Input $input* @property CI_Email $email* @property CI_DB_active_record $db* @property CI_DB_forge $dbforge*/ซึ่งสามารถทำไปต่อยอดเป็น Template หรือ abbreviation ต่อได้คับผิดพลาดประการใดต้องขอโทษด้วยครับผม

วิธีที่สองเพิ่มเติมจากลุงบ๊อบ

ล่าสุดเราไม่จำเป็นจะต้องทำแบบนี้กับทุกไฟล์ที่เราต้องการใช้ Code Completion อีกต่อไป เราเพียงนำไฟล์นี้ ไปใส่ในโฟลเดอร์ nbproject ของโปรเจคเรา แล้วเปลี่ยนชื่อจาก netbeans_ci_code_completion.php.txt เป็น netbeans_ci_code_completion.php แค่นี้ก็ใช้งานได้แล้ว

ปล. สำหรับคนที่เห็นเป็น netbeans_ci_code_completion.php เฉยๆให้เปิดโชว์นามสกุลโดยเข้าไปใน folder แล้วกด Tools->Folder Options-> แท็บ View แล้วให้ติกถูกออก Hide extensions for known file types ก็จะเห็น .txt ขึ้นมาแล้ว ก็ให้เปลี่ยนชื่อตามที่บอกเป็นอันเสร็จ

References :http://codeigniter.com/forums/viewthread/94145/#522295http://www.mybelovedphp.com/2009/01/23/netbeans-revisited-code-completion-for-code-igniter/http://www.mybelovedphp.com/2009/01/27/netbeans-revisited-code-completion-for-code-igniter-ii/

เปลี่ยน base url แบบอัตโนมัติ เมื่อคุณนำไปใช้งานบน server

เคยเป็นไหมที่ทำงานบนเครื่อง แล้วเมื่อทำเสร็จแล้วเวลาจะนำขึ้นไปใช้บน Server จริงแล้วต้องมานั่งแก้ base url ให้ตรงกับเซิร์ฟเวอร์ที่เราจะนำขึ้นไป เพื่อแก้ปัญหานี้ผมเอา code ที่จะทำให้เราไม่ต้องมาคอยแก้ไขตรงส่วนนี้อีกเลย โดยบทความนี้ได้เอามาจาก Codeigniter's Wiki : Automatic config base url อันนี้ โดยวิธีทำก็ง่ายๆครับ เข้าไปที่ config.php ของ CodeIgniter เสร็จแล้วนำโค้ดตรงส่วนนี้แทนที่ $config['base_url'] ของเดิม

$config['base_url'] = "http://".$_SERVER['HTTP_HOST']; $config['base_url'] .= str_replace(basename($_SERVER['SCRIPT_NAME']),"",$_SERVER['SCRIPT_NAME']);

โดยโค้ดด่านบนนั้นจะใช้ได้เฉพาะแบบ http ส่วน https นั้นจะต้องใช้โค้ดด้านล่างนี้ (ถ้าทำแล้วต้องยุ่งทั้งสองอย่าง ก็ใช้ด้านล่างครับ แต่ถ้าไม่ code ด้านบนก็เพียงพอ)

 $config['base_url'] = ((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == "on") ? "https" : "http"); $config['base_url'] .= "://".$_SERVER['HTTP_HOST']; $config['base_url'] .= str_replace(basename($_SERVER['SCRIPT_NAME']),"",$_SERVER['SCRIPT_NAME']); 

หรืออันนี้ซึ่งเป็นแบบสั้นของอันที่สอง ซึ่งให้ผลเหมือนกัน

$config['base_url'] = "http://".$_SERVER['HTTP_HOST'].str_replace(basename($_SERVER['SCRIPT_NAME']),"",$_SERVER['SCRIPT_NAME']);

Syndicate content