Kotchasan Framework Documentation
Kotchasan\View
Kotchasan\View
View เป็นคลาสที่รับผิดชอบการจัดการ presentation layer ใน MVC pattern จัดการการสร้าง HTML และการจัดการ template
สารบัญ
- ภาพรวม
- การติดตั้งและเตรียมความพร้อม
- เมธอดหลัก
- ตัวอย่างการใช้งาน
- Best Practices
- ข้อผิดพลาดที่พบบ่อย
- คลาสที่เกี่ยวข้อง
ภาพรวม
View class เป็นส่วนประกอบสำคัญของ Kotchasan Framework ที่ทำหน้าที่:
- Template Management: จัดการ HTML templates และการแทนที่เนื้อหาด้วย regex patterns
- Asset Management: จัดการ CSS, JavaScript files และ meta tags
- Content Rendering: สร้าง HTML output ที่สมบูรณ์จาก templates
- Header Management: ควบคุม HTTP headers และ responses
- Script Integration: เพิ่ม JavaScript files และ inline scripts
ใช้เมื่อไหร่:
- เมื่อสร้างหน้า HTML ใน MVC controller
- เมื่อสร้าง email templates
- เมื่อสร้าง dynamic content ด้วย template placeholders
- เมื่อจัดการ page assets (CSS/JS) แบบ programmatic
การติดตั้งและเตรียมความพร้อม
ความต้องการ
- PHP 7.4 หรือสูงกว่า
- Kotchasan Framework
- HTML template files (.html)
การเตรียมพื้นฐาน
use Kotchasan\View;
// สร้าง view instance
$view = View::create();View class จะตั้งค่าเริ่มต้นใน templates โดยอัตโนมัติ:
/{WEBTITLE}/- ชื่อเว็บไซต์จาก configuration/{WEBDESCRIPTION}/- คำอธิบายเว็บไซต์จาก configuration/{WEBURL}/- URL พื้นฐานของเว็บไซต์/{SKIN}/- path ของ template/skin ปัจจุบัน
เมธอดหลัก
create()
สร้าง View instance ใหม่ (Factory method)
Signature:
public static function create(): staticReturns: View instance
ตัวอย่าง:
$view = View::create();setContents()
ตั้งค่า content placeholders สำหรับ template replacement
Signature:
public function setContents(array $array): voidParameters:
$array(array) - Key-value pairs โดย keys เป็น patterns (เช่น'/{NAME}/') และ values เป็น strings ที่จะแทนที่
ตัวอย่าง:
$view->setContents([
'/{TITLE}/' => 'ชื่อหน้า',
'/{CONTENT}/' => 'เนื้อหาของหน้า',
'/{COPYRIGHT}/' => '© 2024 เว็บไซต์ของฉัน'
]);setContentsAfter()
ตั้งค่า content ที่จะถูกแทนที่ AFTER ที่ template ถูก render แล้ว มีประโยชน์สำหรับการแก้ไขขั้นสุดท้าย
Signature:
public function setContentsAfter(array $array): voidParameters:
$array(array) - Key-value pairs สำหรับการแทนที่หลัง rendering
ตัวอย่าง:
$view->setContentsAfter([
'/{FINAL_SCRIPT}/' => '<script>console.log("Page loaded");</script>'
]);addCSS()
เพิ่ม CSS file link ใน HTML head
Signature:
public function addCSS(string $url): voidParameters:
$url(string) - URL หรือ path ของ CSS file
ตัวอย่าง:
$view->addCSS('/css/bootstrap.min.css');
$view->addCSS('/css/custom.css');HTML ที่สร้างขึ้น:
<link rel="stylesheet" href="/css/bootstrap.min.css">
<link rel="stylesheet" href="/css/custom.css">addJavascript()
เพิ่ม JavaScript file ใน HTML head
Signature:
public function addJavascript(string $url): voidParameters:
$url(string) - URL หรือ path ของ JavaScript file
ตัวอย่าง:
$view->addJavascript('/js/jquery.min.js');
$view->addJavascript('/js/app.js');HTML ที่สร้างขึ้น:
<script src="/js/jquery.min.js"></script>
<script src="/js/app.js"></script>addScript()
เพิ่ม inline JavaScript code ที่จะแทรกใน head section
Signature:
public function addScript(string $script): voidParameters:
$script(string) - JavaScript code (ไม่ต้องใส่<script>tags)
ตัวอย่าง:
$view->addScript('
$(document).ready(function() {
console.log("Page ready");
});
');HTML ที่สร้างขึ้น:
<script>
$(document).ready(function() {
console.log("Page ready");
});
</script>setHeaders()
ตั้งค่า HTTP headers สำหรับ response
Signature:
public function setHeaders(array $array): voidParameters:
$array(array) - Key-value pairs ของชื่อ header และค่า
ตัวอย่าง:
$view->setHeaders([
'Content-Type' => 'text/html; charset=utf-8',
'X-Frame-Options' => 'DENY',
'X-Content-Type-Options' => 'nosniff'
]);setMetas()
เพิ่ม custom meta tags ใน HTML head
Signature:
public function setMetas(array $array): voidParameters:
$array(array) - Key-value pairs โดย values เป็น HTML ของ meta tag ทั้งหมด
ตัวอย่าง:
$view->setMetas([
'description' => '<meta name="description" content="คำอธิบายเว็บไซต์">',
'keywords' => '<meta name="keywords" content="คำค้น1, คำค้น2">',
'og:title' => '<meta property="og:title" content="ชื่อหน้า">'
]);renderHTML()
Render HTML output สุดท้ายโดยประมวลผล template ด้วย content ที่ตั้งค่าไว้ทั้งหมด
Signature:
public function renderHTML(?string $template = null): stringParameters:
$template(string|null) - Template content หรือ null เพื่อใช้ 'index.html' จาก Template::load()
Returns: string - HTML ที่ render แล้ว
ตัวอย่าง:
// ใช้ template เริ่มต้น (index.html)
$html = $view->renderHTML();
// ใช้ custom template content
$template = '<html><head>{/TITLE/}</head><body>{/CONTENT/}</body></html>';
$html = $view->renderHTML($template);output()
ส่ง HTTP headers และ output เนื้อหาไปยัง browser
Signature:
public function output(string $content): voidParameters:
$content(string) - เนื้อหาที่จะ output
ตัวอย่าง:
$html = $view->renderHTML();
$view->output($html);back()
สร้าง URL สำหรับการนำทาง โดยรักษา query string parameters จาก request ปัจจุบัน
Signature:
public static function back(array|string $f): stringParameters:
$f(array|string) - Query string หรือการแก้ไข parameters
Returns: string - URL ที่แก้ไขแล้ว
หมายเหตุ: ต้องการ HTTP request context ที่ active (ต้องมีการ initialize Request object)
ตัวอย่าง:
// ใน controller ที่มี active request
$backUrl = View::back('module=home&action=index');
// Returns: URL ปัจจุบันพร้อม parameters ที่แก้ไข/เพิ่มarray_value()
ดึงค่าจาก array อย่างปลอดภัยพร้อม default fallback
Signature:
public static function array_value(array $array, string $key, mixed $default = ''): mixedParameters:
$array(array) - Source array$key(string) - Key ที่ต้องการดึง$default(mixed) - ค่า default ถ้า key ไม่มี (default: '')
Returns: mixed - ค่าที่ได้หรือ default
ตัวอย่าง:
$data = ['name' => 'สมชาย', 'age' => 30];
$name = View::array_value($data, 'name', 'ไม่ระบุ'); // Returns: 'สมชาย'
$city = View::array_value($data, 'city', 'ไม่ทราบ'); // Returns: 'ไม่ทราบ'object_value()
ดึงค่า property จาก object อย่างปลอดภัยพร้อม default fallback
Signature:
public static function object_value(object $source, string $key, mixed $default = ''): mixedParameters:
$source(object) - Source object$key(string) - ชื่อ property ที่ต้องการดึง$default(mixed) - ค่า default ถ้า property ไม่มี (default: '')
Returns: mixed - ค่า property หรือ default
ตัวอย่าง:
$user = (object)['name' => 'สมหญิง', 'email' => 'somying@example.com'];
$name = View::object_value($user, 'name', 'ไม่ระบุ'); // Returns: 'สมหญิง'
$phone = View::object_value($user, 'phone', 'ไม่มี'); // Returns: 'ไม่มี'ตัวอย่างการใช้งาน
1. การ Render หน้าพื้นฐาน
use Kotchasan\View;
class HomeController
{
public function index()
{
// สร้าง view
$view = View::create();
// ตั้งค่าเนื้อหาหน้า
$view->setContents([
'/{TITLE}/' => 'ยินดีต้อนรับสู่เว็บไซต์ของเรา',
'/{HEADING}/' => 'ยินดีต้อนรับ!',
'/{CONTENT}/' => 'นี่คือเนื้อหาของหน้าแรก',
'/{YEAR}/' => date('Y') + 543 // ปี พ.ศ.
]);
// เพิ่ม CSS
$view->addCSS('/css/style.css');
// เพิ่ม JavaScript
$view->addJavascript('/js/main.js');
// Render และ output
$html = $view->renderHTML();
$view->output($html);
}
}2. หน้ารายละเอียดสินค้า
use Kotchasan\View;
class ProductController
{
public function show($id)
{
// ดึงข้อมูลสินค้า
$product = $this->getProduct($id);
// สร้าง view
$view = View::create();
// ตั้งค่าเนื้อหา
$view->setContents([
'/{TITLE}/' => $product->name . ' - ร้านค้าของเรา',
'/{PRODUCT_NAME}/' => htmlspecialchars($product->name),
'/{PRODUCT_PRICE}/' => number_format($product->price, 2),
'/{PRODUCT_DESCRIPTION}/' => nl2br(htmlspecialchars($product->description)),
'/{PRODUCT_IMAGE}/' => '<img src="'.$product->image.'" alt="'.htmlspecialchars($product->name).'">'
]);
// เพิ่ม assets เฉพาะสินค้า
$view->addCSS('/css/product.css');
$view->addJavascript('/js/product-gallery.js');
// เพิ่ม structured data สำหรับ SEO
$view->addScript('
var productData = {
id: '.$product->id.',
name: "'.addslashes($product->name).'",
price: '.$product->price.'
};
');
return $view->renderHTML();
}
}3. หน้าที่ปรับ SEO
$view = View::create();
// ตั้งค่าเนื้อหาหน้า
$view->setContents([
'/{TITLE}/' => 'สินค้ายอดนิยม 2024 - ดีลสุดคุ้ม',
'/{CONTENT}/' => $pageContent
]);
// เพิ่ม SEO meta tags ที่ครบถ้วน
$view->setMetas([
'description' => '<meta name="description" content="ค้นหาสินค้าคุณภาพด้วยดีลสุดพิเศษในปี 2024">',
'keywords' => '<meta name="keywords" content="สินค้า, ดีล, 2024, ช้อปปิ้ง">',
'og:title' => '<meta property="og:title" content="สินค้ายอดนิยม 2024">',
'og:description' => '<meta property="og:description" content="ค้นหาสินค้าคุณภาพ">',
'og:image' => '<meta property="og:image" content="https://example.com/image.jpg">',
'og:url' => '<meta property="og:url" content="https://example.com/products">',
'canonical' => '<link rel="canonical" href="https://example.com/products">'
]);
// เพิ่ม security headers
$view->setHeaders([
'X-Frame-Options' => 'SAMEORIGIN',
'X-Content-Type-Options' => 'nosniff',
'X-XSS-Protection' => '1; mode=block'
]);
$html = $view->renderHTML();4. Email Template
use Kotchasan\View;
class EmailService
{
public function sendWelcomeEmail($user)
{
$view = View::create();
// ตั้งค่าเนื้อหา email template
$view->setContents([
'/{USER_NAME}/' => htmlspecialchars($user->name),
'/{USER_EMAIL}/' => htmlspecialchars($user->email),
'/{ACTIVATION_LINK}/' => $this->generateActivationLink($user),
'/{WEBSITE_NAME}/' => 'เว็บไซต์ของเรา',
'/{WEBSITE_URL}/' => 'https://example.com',
'/{SUPPORT_EMAIL}/' => 'support@example.com'
]);
// โหลด email template
$template = file_get_contents(ROOT_PATH.'templates/emails/welcome.html');
$emailHTML = $view->renderHTML($template);
// ส่งอีเมล
mail($user->email, 'ยินดีต้อนรับ!', $emailHTML, 'Content-Type: text/html');
}
}5. AJAX JSON Response พร้อม HTML
use Kotchasan\View;
class CommentController
{
public function add()
{
try {
// บันทึกความคิดเห็น
$comment = $this->saveComment($_POST);
// สร้าง HTML สำหรับความคิดเห็นใหม่
$view = View::create();
$view->setContents([
'/{COMMENT_ID}/' => $comment->id,
'/{AUTHOR_NAME}/' => htmlspecialchars($comment->author_name),
'/{COMMENT_TEXT}/' => nl2br(htmlspecialchars($comment->text)),
'/{COMMENT_DATE}/' => date('d/m/Y H:i', strtotime($comment->created_at))
]);
$template = file_get_contents(ROOT_PATH.'templates/comment-item.html');
$commentHTML = $view->renderHTML($template);
// ส่งกลับเป็น JSON พร้อม HTML
header('Content-Type: application/json');
echo json_encode([
'success' => true,
'html' => $commentHTML,
'message' => 'เพิ่มความคิดเห็นสำเร็จ'
]);
} catch (Exception $e) {
header('Content-Type: application/json', true, 400);
echo json_encode([
'success' => false,
'message' => $e->getMessage()
]);
}
}
}Best Practices
1. การจัดระเบียบ Template
// จัดระเบียบ templates ตามวัตถุประสงค์
// templates/
// ├── layouts/
// │ ├── main.html
// │ └── admin.html
// ├── pages/
// │ ├── home.html
// │ └── about.html
// ├── emails/
// │ └── welcome.html
// └── partials/
// ├── header.html
// └── footer.html2. ความปลอดภัย: Escape User Input เสมอ
// ✅ ดี: Escape user input
$view->setContents([
'/{USER_NAME}/' => htmlspecialchars($userName, ENT_QUOTES, 'UTF-8'),
'/{SAFE_HTML}/' => $trustedContent // เฉพาะ trusted content เท่านั้น
]);
// ❌ ไม่ดี: ใช้ user input โดยตรง
$view->setContents([
'/{USER_NAME}/' => $_POST['name'] // ช่องโหว่ XSS!
]);3. ประสิทธิภาพ: ลด Assets
// ✅ ดี: ใช้ไฟล์ที่รวมและ minify แล้ว
$view->addCSS('/css/combined.min.css');
$view->addJavascript('/js/combined.min.js');
// ❌ ไม่ดี: ไฟล์แยกมากเกินไป
$view->addCSS('/css/bootstrap.css');
$view->addCSS('/css/font-awesome.css');
$view->addCSS('/css/custom.css');
$view->addCSS('/css/responsive.css');
// ... (HTTP requests มากเกินไป)4. Asset Versioning สำหรับ Cache Busting
$version = '1.2.5'; // อัพเดตเมื่อไฟล์เปลี่ยน
$view->addCSS('/css/app.css?v=' . $version);
$view->addJavascript('/js/app.js?v=' . $version);5. แยก Concerns
// ✅ ดี: Controller เตรียมข้อมูล, View render
class ProductController
{
public function show($id)
{
// Business logic
$product = $this->productService->getById($id);
$relatedProducts = $this->productService->getRelated($id);
// View rendering
return $this->renderProductView($product, $relatedProducts);
}
private function renderProductView($product, $related)
{
$view = View::create();
// ... set contents
return $view->renderHTML();
}
}
// ❌ ไม่ดี: Concerns ปะปน
class ProductController
{
public function show($id)
{
$view = View::create();
$product = DB::table('products')->find($id); // Business logic ใน view method
$view->setContents(['/{NAME}/' => $product->name]);
return $view->renderHTML();
}
}ข้อผิดพลาดที่พบบ่อย
❌ ข้อผิดพลาด 1: ไม่ Escape User Input
// ผิด - ช่องโหว่ XSS
$view->setContents([
'/{COMMENT}/' => $_POST['comment']
]);
// ถูกต้อง
$view->setContents([
'/{COMMENT}/' => htmlspecialchars($_POST['comment'], ENT_QUOTES, 'UTF-8')
]);❌ ข้อผิดพลาด 2: รูปแบบ Pattern ผิด
// ผิด - ไม่มี regex delimiters
$view->setContents([
'{TITLE}' => 'หัวข้อ' // ใช้งานไม่ได้!
]);
// ถูกต้อง - ใช้รูปแบบ regex pattern
$view->setContents([
'/{TITLE}/' => 'หัวข้อ'
]);❌ ข้อผิดพลาด 3: ลืม Render
// ผิด - จะไม่มี output
$view = View::create();
$view->setContents(['/{TITLE}/' => 'ทดสอบ']);
// ขาด: $view->renderHTML()
// ถูกต้อง
$view = View::create();
$view->setContents(['/{TITLE}/' => 'ทดสอบ']);
$html = $view->renderHTML();
$view->output($html);❌ ข้อผิดพลาด 4: ตั้ง Headers หลัง Output
// ผิด - ต้องตั้ง headers ก่อน output
echo "อะไรบางอย่าง";
$view->setHeaders(['Content-Type' => 'application/json']); // สายเกินไป!
// ถูกต้อง - ตั้ง headers ก่อน
$view = View::create();
$view->setHeaders(['Content-Type' => 'text/html; charset=utf-8']);
$html = $view->renderHTML();
$view->output($html);คลาสที่เกี่ยวข้อง
- Template - Template loading และ processing engine
- Controller - MVC controller base class
- Database - Database operations สำหรับ dynamic content
หมายเหตุเพิ่มเติม
💡 เคล็ดลับ: View class ใช้การแทนที่แบบ regex Patterns อย่าง
/{NAME}/ถูกแทนที่ด้วยpreg_replace()ตรวจสอบให้แน่ใจว่า patterns เป็น regex patterns ที่ถูกต้อง⚠️ คำเตือน: เมธอด
back()ต้องการ HTTP request context ที่ active จะใช้งานไม่ได้ถ้าเรียกนอก web request (เช่น ใน CLI scripts)ℹ️ หมายเหตุ: CSS และ JavaScript ทั้งหมดที่เพิ่มผ่าน
addCSS()และaddJavascript()จะถูกแทรกโดยอัตโนมัติก่อน</head>tag ขณะrenderHTML()