使用 wordpress 應該有人想,讓一般使用者可以在前台編輯發布文章,不想讓他們進後台,一般使用者或是資料登入員,是不需要後台哪些功能,如填寫表單或問卷,將資料儲存成文章裡會是自訂文章類型,而不再是以送出表單方式寄到 email 信箱裡。

自製外掛起手式

*一句老話,程式碼要放在佈景主題的 function 裡,還是要放在外掛裡,來使用這功能都可,外掛起手式這裡不再詳述,去看WordPress custom post type 如何自訂文章類型這篇😃

在本機建立伺服器環境

*要在本機建立 PHP、阿帕契網站環境可以看這篇如何使用 Python 爬取原價屋價目列表😜,別辛苦在遠端測試所寫的程式。

在前台新增發布文章

建立一個表單在前台,給使用者填寫並發布文章頁面,下面程式碼使用 shortcode 的方式來添加表單到頁面上,到後台新增一個頁面將 [frontend_post_form] 將短碼貼上,檢視該頁面表單來發布文章,表單 HTML 使用 bootstrap,所以如果佈景主題不是 bootstrap 就會看沒有樣式的表單,請自行載入 bootstrap css 樣式。

PHP
function frontend_post_form_shortcode() {
    // 檢查使用者是否已登入
    if (!is_user_logged_in()) {
        return '您必須登入才能提交文章。';
    }

    // 處理表單提交
    if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['submit_post'])) {
        // 驗證 nonce
        if (!isset($_POST['frontend_post_form_nonce']) || !wp_verify_nonce($_POST['frontend_post_form_nonce'], 'frontend_post_form')) {
            return '表單驗證失敗,請重試。';
        }
        $title = sanitize_text_field($_POST['title']);
        $content = wp_kses_post($_POST['content']);
        
        // 引入必要的文件以處理文件上傳
        require_once(ABSPATH . 'wp-admin/includes/file.php');
        require_once(ABSPATH . 'wp-admin/includes/media.php');
        require_once(ABSPATH . 'wp-admin/includes/image.php');

        // 上傳圖片並獲取附件 ID
        $attachment_id = '';
        if (!empty($_FILES['image']['name'])) {
            $attachment_id = media_handle_upload('image', 0);
            if (is_wp_error($attachment_id)) {
                return '圖片上傳失敗:' . $attachment_id->get_error_message();
            }
        }

        // 建立文章
        $post_id = wp_insert_post(array(
            'post_title'   => $title,
            'post_content' => $content,
            'post_status'  => 'publish',  // 直接發佈
            'post_author'  => get_current_user_id(),
        ));

        if (!is_wp_error($post_id)) {
            // 如果有上傳圖片,將其設置為文章的特色圖片
            if (!empty($attachment_id)) {
                set_post_thumbnail($post_id, $attachment_id);
            }

            return '文章提交成功。';
        } else {
            return '文章提交失敗:' . $post_id->get_error_message();
        }
    }

    // 表單 HTML
    ob_start(); // 使用 ob_start() 來捕獲輸出
    ?>
    <form method="post" enctype="multipart/form-data" class="container mt-5">
    <?php wp_nonce_field('frontend_post_form', 'frontend_post_form_nonce', true, false); ?>
        <div class="form-group">
            <label for="title">文章標題</label>
            <input type="text" class="form-control" id="title" name="title" required>
        </div>

        <div class="form-group">
            <label for="content">文章內容</label>
            <textarea class="form-control" id="content" name="content" rows="5" required></textarea>
        </div>

        <div class="form-group">
            <label for="image">上傳圖片</label>
            <input type="file" class="form-control-file" id="image" name="image">
        </div>

        <button type="submit" class="btn btn-primary" name="submit_post">提交文章</button>
    </form>
    <?php
    return ob_get_clean(); // 返回捕獲的輸出內容
}

add_shortcode('frontend_post_form', 'frontend_post_form_shortcode');

完成上面操作應該可以看到頁面顯示的文章表單,如下圖片,填寫後送出表單後在後台也可以看到剛剛在前台的文章,前台發布的文章所上傳的圖片會載入精選圖片中,如下圖。

在前台新增文章添加自定欄位

繼續添加自訂欄位,在原本只能使用文章標題與文章內容和精選圖片三個欄位,額外再添加三個自訂欄位,如何自訂欄位請看WordPress Metabox,自訂欄位功能與資料庫這篇,程式碼如下:

PHP
function frontend_post_form_shortcode() {
    // 檢查使用者是否已登入
    if (!is_user_logged_in()) {
        return '您必須登入才能提交文章。';
    }

    // 處理表單提交
    if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['submit_post'])) {
        // 驗證 nonce
        if (!isset($_POST['frontend_post_form_nonce']) || !wp_verify_nonce($_POST['frontend_post_form_nonce'], 'frontend_post_form')) {
            return '表單驗證失敗,請重試。';
        }
        $title = sanitize_text_field($_POST['title']);
        $content = wp_kses_post($_POST['content']);
        $custom_field_1 = sanitize_text_field($_POST['custom_field_1']);
        $custom_field_2 = sanitize_text_field($_POST['custom_field_2']);
        $custom_field_3 = sanitize_text_field($_POST['custom_field_3']);

        // 引入必要的文件以处理文件上传
        require_once(ABSPATH . 'wp-admin/includes/file.php');
        require_once(ABSPATH . 'wp-admin/includes/media.php');
        require_once(ABSPATH . 'wp-admin/includes/image.php');
        
        // 上傳圖片並獲取附件 ID
        if (!empty($_FILES['image']['name'])) {
            $attachment_id = media_handle_upload('image', 0);
            if (is_wp_error($attachment_id)) {
                return '圖片上傳失敗:' . $attachment_id->get_error_message();
            }
        }

        // 建立文章
        $post_id = wp_insert_post(array(
            'post_title'   => $title,
            'post_content' => $content,
            'post_status'  => 'publish',  // 直接發佈
            'post_author'  => get_current_user_id(),
        ));

        if (!is_wp_error($post_id)) {
            // 添加自訂欄位
            if (!empty($custom_field_1)) {
                add_post_meta($post_id, 'custom_field_1', $custom_field_1, true);
            }
            if (!empty($custom_field_2)) {
                add_post_meta($post_id, 'custom_field_2', $custom_field_2, true);
            }
            if (!empty($custom_field_3)) {
                add_post_meta($post_id, 'custom_field_3', $custom_field_3, true);
            }
            // 如果有上傳圖片,將其設置為文章的特色圖片
            if (!empty($attachment_id)) {
                set_post_thumbnail($post_id, $attachment_id);
            }

            return '文章提交成功。';
        } else {
            return '文章提交失敗:' . $post_id->get_error_message();
        }
    }

    // 表單 HTML
    ob_start(); // 使用 ob_start() 来捕获输出
    ?>
    <form method="post" enctype="multipart/form-data" class="container mt-5">
        <?php wp_nonce_field('frontend_post_form', 'frontend_post_form_nonce', true, false); ?>
        <div class="form-group">
            <label for="title">文章標題</label>
            <input type="text" class="form-control" id="title" name="title" required>
        </div>

        <div class="form-group">
            <label for="content">文章內容</label>
            <textarea class="form-control" id="content" name="content" rows="5" required></textarea>
        </div>

        <div class="form-group">
            <label for="custom_field_1">自訂欄位 1</label>
            <input type="text" class="form-control" id="custom_field_1" name="custom_field_1">
        </div>

        <div class="form-group">
            <label for="custom_field_2">自訂欄位 2</label>
            <input type="text" class="form-control" id="custom_field_2" name="custom_field_2">
        </div>

        <div class="form-group">
            <label for="custom_field_3">自訂欄位 3</label>
            <select class="form-control" id="custom_field_3" name="custom_field_3">
                <option value="選項1">選項1</option>
                <option value="選項2">選項2</option>
                <option value="選項3">選項3</option>
            </select>
        </div>

        <div class="form-group">
            <label for="image">上傳圖片</label>
            <input type="file" class="form-control-file" id="image" name="image">
        </div>

        <button type="submit" class="btn btn-primary" name="submit_post">提交文章</button>
    </form>

    <?php
    return ob_get_clean(); // 返回捕获的输出内容
}

add_shortcode('frontend_post_form', 'frontend_post_form_shortcode');

將前台發布文章,改為自訂文章類型

會需要用到 wordpress 的內建功能,為了與原本文章有所區隔,會用的自訂文章類型(custom post type)功能,這樣有個好處,當文章多時或分類過多時可以不需要靠分類資料表過濾出文章,去看WordPress custom post type 如何自訂文章類型這篇😃至於要修改部分較少,只需要修改 wp_insert_post() 參數,添加 post_type 文章類型就依照自訂的,我這演示為 books,添加部分如下:

PHP
// 建立文章
        $post_id = wp_insert_post(array(
            'post_title'   => $title,
            'post_content' => $content,
            'post_status'  => 'publish',  // 直接發佈
            'post_author'  => get_current_user_id(),
            'post_type'    => 'books',  // 自訂文章類型
        ));

總結

上述方式是在 wordpress 不錯的使用方式,也不需要使用外掛的情況下,可以做的功能,雖然使用外掛帶來方便,就看各位如使用,教學就到這裡,雖然上面的在文章編輯缺少自訂欄位部分,就當練習吧!翻一下之前的文章😘感謝關賞。

最後修改日期: 2024 年 7 月 19 日

留言

撰寫回覆或留言

發佈留言必須填寫的電子郵件地址不會公開。