Kotchasan PHP Framework

[ตอนที่ 2] เวิร์คช้อป CMS อย่างง่าย เก็บข้อมูลเป็นไฟล์

กระบวนการแสดงผลหน้าเว็บของ TCMS จะมีข้อแตกต่างไปจากโปรเจ็คก่อนหน้าเล็กน้อยเท่านั้น เช่น
// เรียกไปยัง Index\Main\Controller เพื่อโหลดหน้าเว็บ
$index = createClass('Index\Main\Controller')->init($request, $module);

ในโปรเจ็คนี้ Controller หลักจะไม่ทำการเลือกหน้าเพจมาแสดงผลเอง แต่จะส่งต่อไปจัดการเลือกหน้ามาแสดงผลโดย Index\Main\Controller แทน
namespace Index\Main;

use \Kotchasan\Http\Request;
use \Kotchasan\Template;

class Controller extends \Kotchasan\Controller
{

  public function init(Request $request, $module)
  {
    // ตรวจสอบว่ามีไฟล์โมดูลที่ต้องการหรือไม่
    $index = \Index\Module\Model::get($module);
    if (!$index) {
      $index = createClass('Index\Pagenotfound\Controller')->init();
    }
    // เริ่มต้นใช้งาน View ของโมดูล Main
    $view = new \Kotchasan\View;
    // ใส่เนื้อหาลงใน View ตามที่กำหนดใน Template
    $view->setContents(array(
      // หัวข้อ
      '/{TOPIC}/' => $index['topic'],
      // เนื้อหา
      '/{DETAIL}/' => $index['detail']
    ));
    // โหลด template หน้า main (main.html)
    $template = Template::load('', '', 'main');
    // คืนค่าข้อมูลโมดูล
    return (object)array(
        'module' => $index['module'],
        'title' => $index['topic'],
        'detail' => $view->renderHTML($template)
    );
  }
}

อธิบายทีละส่วนเลยครับ
$index = \Index\Module\Model::get($module);
บรรทัดนี้จะเป็นการเรียกไปยัง \Index\Module\Model::get() อีกที
namespace Index\Module;

class Model
{

  public static function get($module)
  {
    $file = ROOT_PATH.DATA_FOLDER.'index/'.$module.'.php';
    if (file_exists($file)) {
      return include ($file);
    }
    return false;
  }
}

ซึ่ง \Index\Module\Model::get() จะทำหน้าที่ในการตรวจสอบว่า มีไฟล์ $module.php ใน datas/index/ หรือไม่ ถ้ามีก็โหลดไฟล์แล้วส่งค่ากลับมา

กลับไปที่ Index\Main\Controller บรรทัดถัดมา
if (!$index) {
  $index = createClass('Index\Pagenotfound\Controller')->init();
}

โค้ดชุดนี้จะตรวจสอบว่ามีหน้าเพจโหลดมาหรือไม่ ถ้าไม่มีจะไปใช้ข้อมูลจาก Index\Pagenotfound\Controller แทน

สุดท้ายเป็นโค้ดส่วนแสดงผล
// เริ่มต้นใช้งาน View ของโมดูล Main
$view = new \Kotchasan\View;
// ใส่เนื้อหาลงใน View ตามที่กำหนดใน Template
$view->setContents(array(
  // หัวข้อ
  '/{TOPIC}/' => $index['topic'],
  // เนื้อหา
  '/{DETAIL}/' => $index['detail']
));
// โหลด template หน้า main (main.html)
$template = Template::load('', '', 'main');
// คืนค่าข้อมูลโมดูล
return (object)array(
    'module' => $index['module'],
    'title' => $index['topic'],
    'detail' => $view->renderHTML($template)
);

จะเห็นว่าในโปรเจ็คนี้จะมีการโหลดเนื้อหาแล้วนำข้อมูลไปใส่ลงใน main.html อีกที เพื่อแสดงผล แทนการโหลดไฟล์ HTML ซึ่งเป็นวิธีการของ CMS นั่นเอง
<h2 class="margin-bottom center">{TOPIC}</h2>
{DETAIL}

โค้ดของ main.html ก็มีเท่านี้แหละครับ TOPIC แสดงส่วนหัวข้อ ส่วน DETAIL แสดงส่วนเนื้อหา

ข้อดีของการเก็บข้อมูลเนื้อหาเป็นไฟล์ PHP ตามวิธีนี้ คือ ข้อมูลเนื้อหาจะไม่สามารถเข้าถึงได้เลยจากบุคคลภายนอก ถึงแม้จะรู้ URL (ตัวอย่างก่อน เป็นไฟล์ HTML เราสามารถเรียกเฉพาะส่วนที่เป็นเนื้อหาเท่านั้นได้โดยการเรียกไปยังไฟล์โดยตรง)

ส่วนเมนู เราจะทำการโหลดเมนูที่ Index\Menu\Model::get()
namespace Index\Menu;

class Model
{

  public static function get()
  {
    $result = array();
    if (is_file(ROOT_PATH.DATA_FOLDER.'menus.php')) {
      // โหลดรายการเมนู และวนลูปรายการเมนู
      foreach (include(ROOT_PATH.DATA_FOLDER.'menus.php') as $item) {
        // จัดรูปแบบข้อมูลเมนูให้เหมาะสม สำหรับการสร้างเมนู
        $result[$item['module']] = array(
          'text' => $item['text'],
          'target' => $item['target']
        );
        if (empty($item['url'])) {
          $result[$item['module']]['url'] = WEB_URL.'index.php?module='.$item['module'];
        } else {
          $result[$item['module']]['url'] = $item['url'];
        }
      }
    }
    // คืนค่ารายการเมนูที่จัดรูปแบบแล้ว
    return $result;
  }
}

โดยที่ method \Index\Menu\Model::get() เมื่อเรียกมาแล้ว ตัว  method จะทำหน้าที่ตรวจสอบว่ามีไฟล์ /datas/menus.php หรือไม่ ถ้ามีก็จะทำการโหลดไฟล์ และทำการจัดรูปแบบของตัวแปรเมนูให้เหมาะสม ก่อนที่จะส่งกลับไปสร้างเมนูด้วย method \Kotchasan\Menu::render() เพื่อแสดงผลต่อไป
ถ้าเปิดดูไฟล์ /datas/menus.php จะพบว่ามันมีรูปแบบคล้ายโค้ดเมนูในโปรเจ็คก่อนหน้านั่นเอง (โปรเจ็คนี้ไม่สนับสนุนเมนูย่อย เนื่องจากมันจะต้องมีวิธีจัดการที่ยุ่งยากกว่า)