WordPress實作-網站白皮書|新建表單|回傳pdf檔案

前情提要:計劃在一個WordPress網站上,新增一個帶有表單的頁面,在使用者填按下送出,後台接受到表單後,回傳一個pdf檔案給使用者,並且自動下載到使用者的電腦。

前置作業

前置使用的工具

  • Custom Post Type UI (CPT UI):專門用來新增客製化文章類型及分類表的免費外掛。
  • Advanced Custom Field(ACF):新增自訂欄位的免費外掛。

Custom Post Type UI (CPT UI)

  1. 在外掛先下載CPT UI,啟用後,控制台左側欄可以找到「CPT UI」
  2. 進入CPT UI中去新增一個Post Type

    • Post Type Slug:作為文章類型會出現在文章的網址里,因為是在網址裡面所以只能填寫英文或數字,程式碼抓取有時也會使用到。
    • Plural Label:後台管理介面會顯示的分類名稱。
    • Singular Label:和Plural Label相同內容即可。
  3. 關閉不必要的欄位,計畫讓後續使用者單純地對於欄位輸入內容,不用麻煩的自行排版,這裡目前不了解,可先略過,接續後面前端部分做完會比較了解。
  4. Has Archive這功能要開啟,預設是false,這功能開啟後才正在文張列表頁有個分類呈現這個新增的Post Type

Advanced Custom Field(ACF)

  1. 在外掛先下載ACF,啟用後,控制台左側欄可以找到「自訂欄位」。
  2. 進入「自訂欄位」中去針對剛剛新增的Post Type編輯欄位。
  3. 下方的設定,文章類型等於剛才建立的Post Type
  4. 設定完成按下儲存。
    下圖為針對白皮書需求設定的欄位:

    • 名稱是後續語法抓取欄位會使用的
    • 類型:檔案可以讓管理者在該欄位放置一個檔案
    • 類型:可視化編輯器可以讓管理者在該欄位不是單純放一串文字,而是可以進行排版編輯。

前端

前端使用的工具

  • 範本>主題建構器

  • Elementor:視覺化介面快速編輯前端排版。

  • Unlimied Elements:當Elementor中內的Widget不夠用時,可以自行在這寫程式碼新增一個自己做的Widget。

  • Code Snippest:新增程式碼來使用

    針對特定Post Type排版

    1. 範本>主題建構器>新增

      2.處理的版型類型選擇:Single Psot
      3.使用Elementor對這個Post Tpye進行版面編輯,後續所有Post Type都會是這個排版。因為本次需求是在現存網站多加功能,所以網站風格要延續原版,所以我直接從現存的Single Psot複製一個出來進行編輯。
      以下是我建立的範本,導覽器可以快速協助了解版面元素

      透過範本呈現給使用者看的畫面如下:

      Elementor使用

      Elementor的使用本身可以自成一篇文章,本文只會針對特別要用到的功能進行解說。

  • 標題文:在Elementor中的個Widget不是只可以生硬的輸入文字,也可以動態抓取新增文章時輸入的標題、自訂欄位中的資訊。

  • 圖片,我選擇「特色圖片」,特色圖片指的是精選輯圖片。
    -內容編輯器:選擇ACF欄位(內文描述),這個ACF欄位就是自己建立的,可意識需求調整。

  • 表單:使用Elementor建立表單,可以讓形式快速符合版面,不用自己辛苦的打程式碼。
    -短代碼:透過Code Snippest新增一個shortcode,來針對提交動作進行監聽,在使用者順利提交後,發送請求給後端得到檔案回傳給使用者
    以下Elementor中的內容

    以下為Code Snippest中的內容

    下方為程式碼內容

    add_shortcode( 'DownloadFile', 'DownloadFile' );
    function DownloadFile( $atts ) {
    ob_start();
    ?>
    <script>
        document.querySelector('form[name=whiteBookForm]').addEventListener('submit', async function(e){
            e.preventDefault() 
            const data = {
                "post_id": <?= get_the_ID() ?>
            }
            const config = {
                method: "POST",
                body: JSON.stringify(data),
                headers: {
                    "Content-type": "application/json",
                    "Accept": "*/*",
                    "Accept-Encoding": "identity"
                }
            }
            const res = await fetch('https://digitspark.co/wp-json/api/white-book', config)
            if (res.status == 200){
                const blob = await res.blob();
                const link = document.createElement('a');
                link.href = window.URL.createObjectURL(blob);
                link.download = '<?= get_field('white_book_file', get_the_ID())['filename'] ?>';
                link.click();
            }                                                      
        })
    </script>
    <?php
    return ob_get_clean();
    }

    針對特定Post Type的文章列表排板

    1. 到Unlimied Elements中建立Widget
    2. 基本上是用HTML、CSS、JS組出自己需要的樣式
      3.至於內部資料的呈現樣版引擎Twig呼叫WP的方法來取得
      這部分我依然沿用先前的Widget做修改
      要完全自行製作必須對HTML、CSS、JS、Twig及WP的方法有基本認識

後端

後端使用的工具

  • 內建的媒體庫:上傳要回傳的檔案
  • Prevent Direct Access:避免媒體庫的檔案可以直接透過URL被取得
  • WP File Manager:Wordpress網站檔案管理工具
  • Code Snippest:新增程式碼來使用

    開啟一個API供前端呼叫

    使用Code Snippest開啟一個API

    add_action( 'rest_api_init', function () {
    
    register_rest_route( 'api', 'white-book', array(
    'methods' => 'POST',
    'callback' => 'download_whiteBook',
    ) );
    
    function download_whiteBook(WP_REST_Request $request )
    {
        $id = $request->get_param( 'post_id' );
    
        $file = get_field('white_book_file', $id);
    
        if ($file) {
            $path = get_attached_file($file['id']);
            if ($path) {
                $filename = $file['filename'];
                header( 'Content-Type: application/pdf' );
                header( 'Content-Disposition: attachment; filename = '.$filename);
                readfile($path); //讀取檔案資料,回傳給前端
                exit;
            }
        }
    }
    } );

    對媒體庫檔案進行保障

    這需求本身是為了得到潛在開發客戶的資訊,因此並不會希望使用者在未提交表單的情況下直接透過URL取得媒體庫的檔案

    1. 因此使用外掛Prevent Direct Access,安裝完成並啟用
    2. 在媒體進入到要管理的檔案會有Prevent Direct Access的選項可以勾選,先將其勾選。
    3. 接著透過管理整個網站的檔案外掛如:WP File Manager,進到_pda資料夾裡,路徑如下:wp-content>uploads>_pda
      4.在這個資料夾裡新增一個.htaccess,其中內容如下:

      Order allow,deny
      Deny from all
      ErrorDocument 403 /file_not_found

以上步驟就能完成這個白皮書需求了