前情提要:計劃在一個WordPress網站上,新增一個帶有表單的頁面,在使用者填按下送出,後台接受到表單後,回傳一個pdf檔案給使用者,並且自動下載到使用者的電腦。
前置作業
前置使用的工具
- Custom Post Type UI (CPT UI):專門用來新增客製化文章類型及分類表的免費外掛。
- Advanced Custom Field(ACF):新增自訂欄位的免費外掛。
Custom Post Type UI (CPT UI)
- 在外掛先下載CPT UI,啟用後,控制台左側欄可以找到「CPT UI」
- 進入CPT UI中去新增一個Post Type
- Post Type Slug:作為文章類型會出現在文章的網址里,因為是在網址裡面所以只能填寫英文或數字,程式碼抓取有時也會使用到。
- Plural Label:後台管理介面會顯示的分類名稱。
- Singular Label:和Plural Label相同內容即可。
- 關閉不必要的欄位,計畫讓後續使用者單純地對於欄位輸入內容,不用麻煩的自行排版,這裡目前不了解,可先略過,接續後面前端部分做完會比較了解。
- Has Archive這功能要開啟,預設是false,這功能開啟後才正在文張列表頁有個分類呈現這個新增的Post Type
Advanced Custom Field(ACF)
- 在外掛先下載ACF,啟用後,控制台左側欄可以找到「自訂欄位」。
- 進入「自訂欄位」中去針對剛剛新增的Post Type編輯欄位。
- 下方的設定,文章類型等於剛才建立的Post Type
- 設定完成按下儲存。
下圖為針對白皮書需求設定的欄位:
- 名稱是後續語法抓取欄位會使用的
- 類型:檔案可以讓管理者在該欄位放置一個檔案
- 類型:可視化編輯器可以讓管理者在該欄位不是單純放一串文字,而是可以進行排版編輯。
前端
前端使用的工具
-
範本>主題建構器
-
Elementor:視覺化介面快速編輯前端排版。
-
Unlimied Elements:當Elementor中內的Widget不夠用時,可以自行在這寫程式碼新增一個自己做的Widget。
-
Code Snippest:新增程式碼來使用
針對特定Post Type排版
- 範本>主題建構器>新增
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的文章列表排板
- 到Unlimied Elements中建立Widget
- 基本上是用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取得媒體庫的檔案
- 因此使用外掛Prevent Direct Access,安裝完成並啟用
- 在媒體進入到要管理的檔案會有Prevent Direct Access的選項可以勾選,先將其勾選。
- 接著透過管理整個網站的檔案外掛如:WP File Manager,進到_pda資料夾裡,路徑如下:wp-content>uploads>_pda
4.在這個資料夾裡新增一個.htaccess,其中內容如下:Order allow,deny Deny from all ErrorDocument 403 /file_not_found
以上步驟就能完成這個白皮書需求了