การสร้าง URL แบบกำหนดเอง (rewrite rules)

การสร้าง URI/URL แบบกำหนดเอง โดยกำหนดจากจุดเริ่มต้นของตำแหน่งติดตั้ง WordPress สามารถทำได้อย่างน้อย 2 วิธีจากที่ได้ทดลองมาแล้ว. ตัวอย่างของ URL แบบกำหนดเอง เช่น https://domain/custompage และ https://domain/custompage/my โดยในเงื่อนไขคือจะต้องรองรับหลายภาษาจาก Polylang ได้ด้วย.

แบบไม่ใช้หน้า (Pages) ของ WordPress

กรณีแรก จะใช้แบบ URL กำหนดเอง (rewrite rules) ล้วนๆ โดยไม่พึ่งพาระบบหน้า (Pages) ของ WordPress. ซึ่งข้อดีคือเราสามารถทำให้ URL ใช้สลัก(slug)เดียวกันได้ ดังตัวอย่างนี้.
https://domain/custompage (สำหรับภาษาเริ่มต้น ที่ไม่ได้แสดงภาษาใน URL),
https://domain/custompage/my,
https://domain/en/custompage,
https://domain/en/custompage/my

ซอร์สโค้ด

<?php
class Routes
{


    /**
     * @var string Main query name for the page after /custompage/ URL.
     */
    public const MAIN_QUERY_NAME = 'custompage';


    /**
     * Constructor.
     */
    public function __construct()
    {
        add_action('init', [$this, 'addRewriteRules']);
        add_action('template_redirect', [$this, 'runPages']);
    }// __construct


    /**
     * Add rewrite rules.
     */
    public function addRewriteRules()
    {
        add_rewrite_rule('^([a-zA-Z]{0,2}/?)custompage/?$', 'index.php?lang=$matches[1]&' . static::MAIN_QUERY_NAME . '=index', 'top');
        add_rewrite_rule('^([a-zA-Z]{0,2}/?)custompage/my?$', 'index.php?lang=$matches[1]&' . static::MAIN_QUERY_NAME . '=mycustompage', 'top');

        add_rewrite_tag('%' . static::MAIN_QUERY_NAME . '%', '([^&]+)');
    }// addRewriteRules


    /**
     * Run the pages based on query(s).
     */
    public function runPages()
    {
        $mainQueryVal = get_query_var(static::MAIN_QUERY_NAME, null);

        if (!is_null($mainQueryVal)) {
            switch ($mainQueryVal) {
                default:
                    var_dump($mainQueryVal);
                    echo 'hello world';
            }// endswitch;

            exit();// required! to prevent WordPress continue executing. and don't use `wp_die()`.
        }// endif;

        unset($mainQueryVal);
    }// runPages


}

ข้อเสียสำหรับตัวอย่างด้านบน คือ เมื่อตรวจสอบด้วยคำสั่งบนเท็มเพลท เช่น is_home() ภายในเมธ็อด runPages() จะได้ค่าเป็น true เสมอ. วิธีแก้ไขคือ เพิ่ม parameter 'pagename=' เข้าไปใน add_rewrite_rule() เช่น:

add_rewrite_rule('^([a-zA-Z]{0,2}/?)custompage/?$', 'index.php?lang=$matches[1]&' . static::MAIN_QUERY_NAME . '=index&pagename=mycustompage', 'top')

แต่ก็จะแลกมากับสถานะ HTTP เป็น 404 ในกรณีที่คุณใส่ชื่อหน้าที่ไม่มีอยู่บนระบบหน้า (Pages) ของ WordPress ซึ่งก็จะต้องมาแก้ไขโดยการกำหนด HTTP status และหัวข้อของหน้านั้นใหม่ และกำหนด $wp_query->is_404 = false; ภายใน hook template_redirect. นอกจากนี้ก็จะต้องแก้ไขแท็ก title ให้เหมาะผ่าน filter document_title_parts.

คุณอาจดูอ้างอิงเพื่อใส่ query vars อื่นๆได้อีก.

แบบใช้หน้า (Pages) ของ WordPress

แบบที่สองนี้ผู้อ่านจะต้องไปสร้างหน้าขึ้นมา เช่น หน้าภาษาไทยชื่อสลัก "หน้าที่กำหนดเอง" และแปลเป็นอังกฤษผ่าน Polylang ชื่อสลัก "custompage". จากนั้นนำ ID ของทั้ง 2 หน้านี้มาใส่ใน array() เช่น array(165, 166) หรือใช้ฟังก์ชั่นของ Polylang เช่น pll_get_post_translations(165); เพื่อดึงค่า post ID ทั้งหมดจากทุกภาษาที่เป็นหน้าแปลของ ID ของหน้าหลักที่เลือกไว้.

วิธีนี้ผู้อ่านจำเป็นจะต้องดึงเอา post ID จากหน้าของภาษาหลัก และ ID ของทุกๆภาษาที่สร้างหน้าแปลขึ้นมาแล้ว นำมาเพิ่มลงใน rewrite rule ในคราวเดียวกัน. มิฉะนั้น WordPress จะไม่สามารถอ่านค่า rewrite rule ของ ID ของหน้านั้นในภาษาอื่นๆได้ เนื่องจากมันทำงานไปแล้วและติดอยู่ใน cache ซึ่งจะต้องทำการ flush ใหม่โดยไม่จำเป็นและสิ้นเปลืองทรัพยากร server. การเพิ่ม rewrite rule ทุก ID (จากหน้าที่แปลทุกภาษา)ในคราวเดียวจะช่วยแก้ปัญหานี้.

การใช้รูปแบบหน้าของ WordPress นี้นั้น ผู้อ่านจะไม่สามารถใช้สลักเดียวกันได้ ยกเว้นแต่ได้ซื้อปลั๊กอิน Polylang Pro เอาไว้. ดังนั้น URL จะได้เป็นลักษณะคล้ายๆดังต่อไปนี้.
https://domain/หน้าที่กำหนดเอง
https://domain/หน้าที่กำหนดเอง/my
https://domain/en/custompage
https://domain/en/custompage/my

ซอร์สโค้ด

class Routes
{


    /**
     * @var string Main query name for the page after /custompage/ URL.
     */
    public const MAIN_QUERY_NAME = 'custompage';


    /**
     * Constructor.
     */
    public function __construct()
    {
        add_action('init', [$this, 'addRewriteRules']);
        add_action('template_redirect', [$this, 'runPages']);
    }// __construct


    /**
     * Add rewrite rules.
     */
    public function addRewriteRules()
    {
        // IDs of a post and translated posts. 165 is main post (page).
        $postIds = pll_get_post_translations(165);
        $postIds = array_values($postIds);

        foreach ($postIds as $postId) {
            $Post = get_post($postId);
            if (!is_object($Post)) {
                continue;
            }

            add_rewrite_rule('^([a-zA-Z]{0,2}/?)' . rawurldecode($Post->post_name) . '/?$', 'index.php?lang=$matches[1]&pagename=' . $Post->post_name . '&' . static::MAIN_QUERY_NAME . '=index_usepage', 'top');
            add_rewrite_rule('^([a-zA-Z]{0,2}/?)' . rawurldecode($Post->post_name) . '/my/?$', 'index.php?lang=$matches[1]&pagename=' . $Post->post_name . '&' . static::MAIN_QUERY_NAME . '=mycustompage', 'top');
            unset($Post);
        }// endforeach;
        unset($postId, $postIds);

        add_rewrite_tag('%' . static::MAIN_QUERY_NAME . '%', '([^&]+)');
    }// addRewriteRules


    /**
     * Run the pages based on query(s).
     */
    public function runPages()
    {
        $mainQueryVal = get_query_var(static::MAIN_QUERY_NAME, null);

        if (!is_null($mainQueryVal)) {
            switch ($mainQueryVal) {
                default:
                    var_dump($mainQueryVal);
                    echo 'hello world';
            }// endswitch;

            exit();// required! to prevent WordPress continue executing. and don't use `wp_die()`.
        }// endif;

        unset($mainQueryVal);
    }// runPages


}

ข้อสำคัญ

เมื่อทำการเพิ่มหรือแก้ไขโค้ดใน add_rewrite_rule() แล้ว ให้ทำการกดบันทึกที่หน้าตั้งค่าลิ้งค์ถาวร (Permalink) ด้วยทุกครั้ง เพื่อให้ระบบทำการ flush ของเก่าออกไปแล้วนำของใหม่มาใช้งาน.

ใส่ความเห็น

อีเมลของคุณจะไม่แสดงให้คนอื่นเห็น ช่องข้อมูลจำเป็นถูกทำเครื่องหมาย *

คุณอาจใช้แท็กHTMLและแอททริบิวต์เหล่านี้: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>