CodeIgniter กับปัญหา base_url() บนเครื่องที่ติดตั้ง IIS และ Apache หรือเว็บเซิร์ฟเวอร์ที่ IP ต่างกัน

โดย SONGCHAI SAETERN

CodeIgniter กับปัญหา base_url()



ปัญหานี้เกิดขึ้นหลังจากที่เปลี่ยนมาใช้ CodeIgnditer เวอร์ชั่น 3.1.6 (ก่อนหน้านี้ใช้เวอร์ชั่น 2 สามารถเรียก base_url() ได้ปกติ) ปรากฏว่าเวอร์ชั่นใหม่นี้ จะแสดง URL เป็นไอพี ตามที่ได้ตั้งไว้กับ IIS ซึ่งเป็นเซริฟเวอร์อีกตัว ทำให้โหลดไฟล์ JS, CSS ต่างๆไม่ได้


เมื่อ echo base_url()  ออกมาดู จะเห็น URL ที่ไม่ตรงกับในช่อง url address








หลังจากค้นหาวิธีอยู่นานสองนาน ก็ได้คำตอบว่า
1. ปรับค่า $config['base_url'] ให้ตรงตาม project
2. เขียนโค้ดเพิ่มเติมโดยอ่านจาก $_SERVER



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



เมื่อรีเฟรชหน้าเว็บโปรเจ็กต์อีกครั้ง จะเห็นว่า Template แสดงผลได้ถูกต้อง และ ค่าที่ echo base_url() ออกมาตรงกับที่ช่อง URL ADDRESS




สำหรับส่วนที่ต้องแก้ไขนั้นอยู่ในไฟล์นี้

application/config/config.php

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

:: ที่มา ::

CodeIgniter base_url(), link in localhost gives me to live server
https://stackoverflow.com/questions/29474848/codeigniter-base-url-link-in-localhost-gives-me-to-live-server

วิธีแก้ไข JavaScript โดยไม่ต้อง Refresh หน้าเว็บใหม่

โดย SONGCHAI SAETERN

แก้ไข JavaScript โดยไม่ต้อง Refresh



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



ปัญหาเริ่มจากกดปุ่มลบ แล้ว Page not found 
(หรือกรณี Event ใดๆ ที่กดปุ่มแล้ว JavaScript ไม่ทำงาน)






ลองตรวจสอบ URL ที่ส่งไปเป็น /remove_price ซึ่งเกิดจากการระบุในไฟล์ JavaScript ไม่ตรงกับหน้าเว็บ









เมื่อเปิดไปที่ไฟล์ PHP ในหน้าเว็บสำหรับลบราคา ปรากฏว่า URL ที่ถูกต้องคือต้องลงท้ายด้วย /removePrice




ดังนั้นก็ต้องกลับไปทำการแก้ไขในไฟล์ .js ให้เป็น URL ที่ถูกต้อง


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


โดยการเปิดส่วนของนักพัฒนาขึ้นมา ซึ่งทำได้ 2 วิธี
1. คลิกขวา แล้วเลือก ตรวจสอบองค์ประกอบ (บน firefox) หรือ ตรวจสอบ (บน Chrome)
2. กดคีย์ลัด F2

จากนั้นก็คลิกเปิดแท็ป คอนโซล (Console)  แล้ววางโค้ดลงไป (ตรงส่วนของเครื่องหมาย >>)


จากนั้นก็กด Enter จะเห็นว่ามีเครื่องหมาย >> ปรากฏขึ้นใหม่ เพื่อพร้อมรันโค้ดต่อไป
หากไม่ปรากฏ error สีแดงใดๆ แสดงว่าโค้ด JavaScript ใหม่พร้อมใช้งาน



ให้สลับไปที่แท็ป เครือข่าย (Network) ล้างค่าเดิมออกก่อน
1. คลิกเป็นแท็ป Network
2. ล้างค่าเดิมออกก่อน
3. กดปุ่มเรียกฟังก์ชั่นลบอีกครั้ง



สังเกตว่า URL จะไปไปตามที่เราแก้ไขเรียบร้อย



ทิ้งท้ายไว้อีกนิด

สำหรับกรณีที่แก้ไขโค้ดหลายที่ จะลองคัดลอกทั้งหมดในไฟล์แล้วเอาไปรันใน Console ก็ได้ แต่อาจจะมีข้อผิดพลาดได้ หากต้องการความแน่ใจให้กด Refresh หน้าเว็บใหม่ด้วยการกด Ctrl + F5 จะได้โค้ด JavaScript ที่แก้ไขใหม่อย่างแน่นอน




PHP CI MANIA PHP Code Generator 
โปรแกรมช่วยสร้างโค้ด ลดเวลาการเขียนโปรแกรม เขียนโปรแกรมง่ายและสะดวกขึ้น
สนใจสั่งซื้อราคาสุดคุ้ม >> http://fastcoding.phpcodemania.com/

Codeigniter วิธีโหลดไฟล์ config เพื่อเชื่อมต่อฐานข้อมูลหลายๆตัว ตามค่าที่ผู้ใช้งานส่งมา

โดย CyberMAN

How to switch dynamic DATABASE  in Codeigniter?

ตัวอย่างการโหลดค่า config ของฐานข้อมูลเดิม เพื่อนำมาเชื่อมต่อใหม่ด้วยชื่อฐานข้อมูลใหม่ที่ต้องการ
$this->config->load("new_database");
$db_config = $this->config->item('new_db');

echo '<pre>';
print_r($db_config);
echo '</pre>';
ผลลัพธ์ที่ได้ จะเหมือนกับค่าใน application/config/database.php



มาดูตัวอย่างการสร้างไฟล์คอนฟิกใหม่สำหรับเรียกใช้ Dynamic Database ใน CodeIgniter

application/config/new_database.php
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

include(APPPATH. '/config/database.php');
$config['new_db'] = $db['default'];

โค้ดด้านบนนี้จะมีการ include ไฟล์คอนฟิกหลักมา และเซ็ตเข้าไปในตัวแปร $config['new_db']

ในส่วนของเปลี่ยนฐานข้อมูลเราจะแทรกใน __construct() ของไฟล์ Controller 

โดยที่คำสั่ง $this->load->database($db_config, TRUE); คือการเชื่อมต่อฐานข้อมูลอีกครั้งด้วยค่าคอนฟิกใหม่ที่โหลดเก็บไว้ใน $db_config และจะเปลี่ยนชื่อฐานข้อมูลทุกครั้งตามค่า SESSION ที่ส่งเข้ามาในตัวแปร $session_new_db
<?php

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

class Dashboard extends MY_Controller {

    public function __construct() {
        parent::__construct();
      
      
        $this->config->load("new_database");
        $db_config = $this->config->item('new_db');
        $session_new_db = $this->session->userdata('session_new_db');
        if($session_new_db != ''){
            $db_config['database'] = $session_new_db;
            $this->db = $this->load->database($db_config, TRUE);
        }
    }

    public function index() {
        $tables = $this->db->list_tables();
        echo '<pre>';
        print_r($tables);
        echo '</pre>';
    }
  
}

// ------ END Controller Class ------


ผลลัพธ์ที่ได้เมื่อสั่งแสดงรายชื่อตารางทั้งหมดของ Database




มาดูการโหลดคอนฟิกอื่นๆ มาใช้กันบ้าง กรณีไม่ได้สร้างคอนฟิกที่เป็นอาร์เรย์หลายมิติแบบ [new_db][xxx]


$prev_config = $this->config->config;
$this->config->load("pagination");
$config = $this->config->config;

echo '<pre>';
print_r($config );
echo '</pre>';

สังเกตว่าผลลัพธ์จะได้ค่า config รวมกันทั้งหมด




ดังนั้นเราจะต้องทำการคัดค่าเดิมออกไป เอาเฉพาะค่าคอนฟิกใหม่
$result = array_diff_key($config, $prev_config);
echo '<pre>';
print_r($result);
echo '</pre>';

จะได้ผลลัพธ์ที่คัดค่าคอนฟิกเดิมออกไปแล้วดังนี้


สรุป


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

$this->config->load("your_config_file");
$db_config = $this->config->item('your_config_array');




:: ฟังก์ชั่นที่เกี่ยวข้อง ::

คัดเฉพาะอาร์เรย์ที่ไม่ซ้ำกัน (ต้องการเฉพาะ Config ค่าใหม่ที่โหลดเข้ามาเท่านั้น)
http://php.net/manual/en/function.array-diff-key.php

วิธีโหลด config ของ CodeIgniter มาใช้งาน
https://www.codeigniter.com/userguide3/libraries/config.html

แสดงรายชื่อตารางทั้งหมดด้วยฟังก์ชั่น list_tables()
https://www.codeigniter.com/user_guide/database/metadata.html

วิธี include ไฟล์ config มาใช้งาน
https://www.sitepoint.com/community/t/basepath-apppath/3613/4



PHP CI MANIA PHP Code Generator 
โปรแกรมช่วยสร้างโค้ด ลดเวลาการเขียนโปรแกรม เขียนโปรแกรมง่ายและสะดวกขึ้น
สนใจสั่งซื้อราคาสุดคุ้ม >> http://fastcoding.phpcodemania.com/

มีวิธีเขียนโค้ดอย่างไร งานถึงจะเสร็จได้เร็วกว่ากัน?

โดย CyberMAN

มาหาวิธีเขียนโค้ดให้เสร็จอย่าวรวดเร็วกัน



เป็นเหมือนกันไหม "เขียนไปด้วย เทสไปด้วย"

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

หรือถ้าไม่อยากป้อนเองก็อาจจะปลั๊กอินของเว็บบราวเซอร์อย่างของ Firefox เข้ามาช่วยลดเวลาก็ได้เช่น  Selenium IDE ซึ่งหากท่านใดสนใจก็ลองค้นหาใน Google ด้วยคำว่า

"ทดสอบเว็บอัตโนมัติด้วย Selenium IDE"

แต่ถึงอย่างนั้น หากจะทดสอบทุกครั้งที่เขียนโค้ดส่วนใดส่วนหนึ่งเสร็จ ก็ยังคงเป็นการเสียเวลาสลับหน้าจอไปมาอยู่ดี จากอารมณ์ Coding มันส์ๆ ต้องสลับโหมดไป Design และยังต้องมานั่ง Test โปรแกรมอีก

งั้นลองแบบนี้ไหม ลองนึกถึงหลักการ MVC ที่แยกส่วนต่างๆออกจากกัน เรามาแบ่งตัวเองออกเป็น 3 ภาคจิตกันดีไหม?


ภาคจิตที่ 1 - Front-END


ภาคจิตที่ 2 - Back-END


ภาคจิตที่ 3 - Tester


แล้วก็วนลูปแบบนี้ไปเรื่อยๆ จนกว่าจะครบทุกส่วน 


เริ่มจาก Front-END ในมุมของ CodeIgniter ก็คือการสร้างไฟล์ View ให้ครบถ้วน หากต้องการทดสอบไฟล์ View ที่สร้างขึ้นมาเรียบร้อยแล้วนั้น อาจจะต้องเขียนส่วนของ Controller เอาไว้โหลดข้อมูลเพื่อแสดงผลลัพธ์บนหน้าเว็บบราวเซอร์ออกมาด้วย ซึ่งก็จะเป็นโครงสร้าง Controller เปล่าๆ ที่ยังไม่มีข้อมูลใดๆส่งไปใน View นั่นเอง


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

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


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

แก้ปัญหา Autocomplete ที่ชื่อว่า typeahead มักจะเลือกรายการแรกทุกครั้งที่ค้นหา

โดย CyberMAN
เปลี่ยนจากเลือกรายการแรกอัตโนมัติแบบรูปด้านซ้าย => เป็นเลือกเองแบบด้านขวา



ตัว Bootstrap Framework จะมี Autocomplete ที่ชื่อว่า typeahead ปัญหาคือ เวลากดพิมพ์ลงไป พอมันเด้งข้อมูลขึ้นมา มันก็เลือกตัวแรกให้ ทำให้กด Enter มันก็มาทันที
แก้ให้มันไม่ select อัตโนมัติก็ใช้โค้ดประมาณนี้


<script>
    // Initialize typeahead
    $("input").typeahead(...);


    // เริ่มคัดลอกโค้ดจากส่วนนี้เป็นต้นไป =>
    // Get the current typeahead instance
    var typeaheadInstance = $("input").data("typeahead");

    // Save the reference to the original implementation of the render() function
    var origRenderFunc = typeaheadInstance.render;

    // Overwrite the render() function
    typeaheadInstance.render = function() {
        // Execute the original implementation
        var result = origRenderFunc.apply(this, arguments);
        // Remove the 'active' class from the first item
        result.$menu.children().first().removeClass("active")

        return result;
    }

    // <= สิ้นสุดโค้ดที่ต้องใช้

</script>

 ตรงส่วนของ $("input").typeahead(...); คือฟังก์ชั่นที่เราสร้างไว้แล้ว ไม่ต้องนำไปใส่ในโค้ดเรา เอาเฉพาะส่วนที่ถัดมา ตั้งแต่

var typeaheadInstance = $("input").data("typeahead");

 โดยที่ $("input") ให้เปลี่ยนไปตามไอดีของ input ที่ต้องใช้
เพียงเท่านี้ก็จะได้ Autocomplete ที่ไม่เลือกรายการแรกอัตโนมัติ ทำให้เวลากด Enter ไม่ไปเลือกรายการที่เราไม่ได้ต้องการขึ้นมาอีก

ที่มา : https://bibwild.wordpress.com/2013/04/04/overriding-bootstrap-typeahead-to-not-initially-select/