最近用 wordpress 處理一些 MVP 的實作,沒想到竟然要對他做技術文件,這邊先筆記一下避免以後有相同需求找不到來源。
注意來源取自官網,有些可能是過時的資訊。
Modules
Wordrpess Site Architecture
Code Reference | Functions, Hooks, Classes Methods
Database Description

最近用 wordpress 處理一些 MVP 的實作,沒想到竟然要對他做技術文件,這邊先筆記一下避免以後有相同需求找不到來源。
注意來源取自官網,有些可能是過時的資訊。

最近使用 wordpress 外掛,透過 curl 可能會發生錯誤,如果遇到這類型的錯誤:

是因為許多網站都在使用全球證書,該證書已於 2021 年 9 月 30 日到期。參考:
解決方法是使用新的 crt 檔案替代 wordpress 目錄:wp-includes/certificates 底下的 ca-bundle.crt 檔案。
crt 檔案下載網址:https://github.com/WordPress/WordPress/blob/master/wp-includes/certificates/ca-bundle.crt
而這個問題預估在 wordpress 5.9 版會修復。
參考:

WordPress 有很多外掛,在藍新金流啟用時,同時有使用 Elementor 這個 page builder 外掛,在某些編輯視窗中,可能會造成 AJAX “/wp-json/elementor/v1/globals” 路徑中抓不到 wc_get_chosen_shipping_method_ids() 這個 function 的錯誤訊息。
這邊查了一下資料,不只是藍新金流外掛會這樣,應該 woocommerce 外掛和 page builder 都有可能造成類似的錯誤。紀錄一下避免老了忘記。
— 2024-01-02 update —
最近又遇到一樣的問題,查看 log 發現是 wc_get_chosen_shipping_method_ids() 裡面的問題:
2024/01/02 19:30:32 [error] 1870242#1870242: *46728 FastCGI sent in stderr: "PHP message: PHP Fatal error: Uncaught Error: Call to a member function get() on null in /xxx/xxx/wp-content/plugins/woocommerce/includes/wc-cart-functions.php:394
Stack trace:
#0 /xxx/xxx/wp-content/plugins/newebpay/class-newebpay.php(1673): wc_get_chosen_shipping_method_ids()
...
查看 woocommerce 的程式碼(參考),並且參考有類似問題的 stackoverflow:
function wc_get_chosen_shipping_method_ids() {
$method_ids = array();
$chosen_methods = WC()->session->get( 'chosen_shipping_methods', array() );
foreach ( $chosen_methods as $chosen_method ) {
$chosen_method = explode( ':', $chosen_method );
$method_ids[] = current( $chosen_method );
}
return $method_ids;
}
判斷應該是 WC()->session 取不到 get 參數,實際上就是這樣沒錯, woocommerce 當下這個沒有判斷 session 為空的狀況。
可以參考原文,於 class-newebpay.php:1676 附近, wc_get_chosen_shipping_method_ids() 呼叫之前判斷 WC()->session 是否為空。這邊於底下原文中添加新的 code 。
— 以下原文 —
附上錯誤訊息:
Fatal error: Uncaught Error: Call to undefined function wc_get_chosen_shipping_method_ids() in /xxx/wp-content/plugins/newebpay/class-newebpay.php:1676 Stack trace: #0 /xxx/wp-includes/class-wp-hook.php(303): newebpay_alter_payment_gateways(Array) ...
附上發現錯誤的版本資訊,wordpress 核心版本為 5.8.1 , Elementor 版本為 3.4.3:
/**
* newebpay Payment Gateway
* Plugin URI: http://www.newebpay.com/
* Description: 藍新金流收款/物流 模組
* Version: 1.0.3
* Author URI: http://www.newebpay.com/
* Author: 藍新金流 newebpay
* Plugin Name: 藍新金流
* @class newebpay
* @extends WC_Payment_Gateway
* @version
* @author Pya2go Libby
* @author Pya2go Chael
* @author Spgateway Geoff
* @author Spgateway_Pay2go Q //20170217 1.0.1
* @author Spgateway_Pay2go jack //20170622 1.0.2
* @author Spgateway_Pay2go Stally //20180420 1.0.3 20181018 1.0.4 20181222 newebpay 1.0.0 20190417 1.0.1 20190711 1.0.2 20200326 1.0.3
*/
目前的解決方法是在 class-newebpay.php:1676 的 newebpay_alter_payment_gateways() 內添加判斷,檢查是否有方法,沒方法就直接跳回不動作。
另外也在 plugin meta 上修改版本號和描述,避免被直接更新。不過這個外掛也沒上版控,所以屆時可能需要也是手動更新嘍。
附上修改後資訊:
<?php
/**
* newebpay Payment Gateway
* Plugin URI: http://www.newebpay.com/
* Description: 藍新金流收款/物流 模組 修復了 elementor 開啟會有 wc_get_chosen_shipping_method_ids 錯誤的問題
* Version: 99.99.99
* Author URI: http://www.newebpay.com/
* Author: 藍新金流 newebpay 修改過 By Jerry
* Plugin Name: 藍新金流
* @class newebpay
* @extends WC_Payment_Gateway
* @version
* @author Pya2go Libby
* @author Pya2go Chael
* @author Spgateway Geoff
* @author Spgateway_Pay2go Q //20170217 1.0.1
* @author Spgateway_Pay2go jack //20170622 1.0.2
* @author Spgateway_Pay2go Stally //20180420 1.0.3 20181018 1.0.4 20181222 newebpay 1.0.0 20190417 1.0.1 20190711 1.0.2 20200326 1.0.3
*/
add_action('plugins_loaded', 'newebpay_gateway_init', 0);
function newebpay_gateway_init() {
if (!class_exists('WC_Payment_Gateway')) {
return;
}
class WC_newebpay extends WC_Payment_Gateway {
...
// 選擇藍新金流超商取貨後 payment只輸出藍新金流
function newebpay_alter_payment_gateways($list) {
if(isset($_GET['pay_for_order']) && isset($_GET['key'])) {
$order_id = wc_get_order_id_by_order_key($_GET['key']);
$order = wc_get_order($order_id);
if($order->has_shipping_method('newebpay_cvscom')) {
$list = array('WC_newebpay');
}
} elseif(!is_admin()) { //後台無wc_get_chosen_shipping_method_ids function
if ( !function_exists( 'wc_get_chosen_shipping_method_ids' ) ) {
return $list;
}
// 2024-01-02 更新判斷
$session = WC()->session;
if($session){
$chosen_shipping = wc_get_chosen_shipping_method_ids();
//判斷購物車內商品是否全為虛擬商品 全為虛擬商品時會無法選擇物流方式 導致session的chosen_shipping會維持上次所選
$virtual_count = 0;
$cart_items = WC()->cart->get_cart();
foreach ($cart_items as $key => $cart_item) {
$virtual_count += ($cart_item['data']->is_virtual()) ? 1 : 0;
}
if (@in_array('newebpay_cvscom', $chosen_shipping) && $virtual_count < count($cart_items)) {
$list = array('WC_newebpay');
}
} // end 判斷
}
return $list;
}
add_filter('woocommerce_payment_gateways', 'newebpay_alter_payment_gateways', 100);
...
紀錄一下之前用很久的一個 linux 套件,主要用途是作爲讓 Server 在再斷線後,依然可以跑池長時間非背景運作。
安裝方法,權限問題請自行加上 sudo:
# ubuntu \ debian
apt-get install screen
# centos
yum install screen
一些基本的操作:
# 建立一個新的 screen
screen -U -S SCREEN_NAME
# 進入已開啟的 screen
screen -drU SCREEN_NAME
# 列出所有 screen
screen -ls
至於進入 screen 內的操作,請參考:
大概可以記住:所有指令都是 ctrl + a 開始。
以前同事有分享一個 screenrc 設定檔案,不錯用。請自行取代 /etc/screenrc 檔案:
startup_message off
defencoding utf8
encoding utf8 utf8
#caption always "%{= wk} %{= KY} [%n]%t @ %H %{-} %= %{= KR} %l %{-} | %{= KG} %Y-%m-%d %{-} "
#hardstatus alwayslastline " %-Lw%{= Bw}%n%f %t%{-}%+Lw %=| %0c:%s "
#bindkey ^[z prev
#bindkey ^[x next
termcapinfo xterm*|rxvt* 'ti@:te@'
termcapinfo xterm ti@:te@
vbell off
# C + left : prev
# C + right : next
bindkey "^[[1;5C" next
bindkey "^[O5C" next
bindkey "^[[C" next
bindkey "^[[1;5D" prev
bindkey "^[O5D" prev
bindkey "^[[D" prev
# C-a b : encoding big5
# C-a u : encoding utf8
bind b encoding big5 utf8
bind u encoding utf8 utf8
# C-b $num : move current window to number $num
bind -c move 0 number 0
bind -c move 1 number 1
bind -c move 2 number 2
bind -c move 3 number 3
bind -c move 4 number 4
bind -c move 5 number 5
bind -c move 6 number 6
bind -c move 7 number 7
bind -c move 8 number 8
bind -c move 9 number 9
bindkey "^b" command -c move
# F12 : fast kill
#bindkey "^[[24~" kill
#termcapinfo xterm 'hs:ts=\E]0;:fs=\007:ds=\E]0;bash\007'
#caption always "%{= bk} %{= wk} %-Lw%{by}%n+%f %t%{wk}%{wk}%+Lw %=%{kw}%{= R}%{-}"
shelltitle '$ |csh'
defhstatus "\005t"
#hardstatus on
#caption always "%{= wk} %{= KY} [%n]%t @ %H %{-} %= %{= KR} %l %{-} | %{= KG} %Y-%m-%d %{-} "
#hardstatus alwayslastline " %-Lw%{= Bw}%n%f %t%{-}%+Lw %=| %0c:%s "
#buttom status bar
caption always "%{= .G} %-w%<%{=ub .y}[%n %t]%{= .G}%+w "
hardstatus alwaysignore
#hardstatus alwayslastline "%{= .K} [%l]%<%=%{= .W}@%H %=%{= .y} %Y/%m/%d%{= .m} %C %A"
#shelltitle '$|csh'
#caption always "%{bw}%M/%d %c %{wb} %-w%{c}%n %t%{w}%+w%{k}"
shell -$SHELL
好久以前遇到一些伺服器鬼故事,所以參考網路上的資料,弄了一個排程檢查系統服務的機制,配合上 crontab 可以使用。
原則上,這個做法和把程式 try / catch 包起來一樣,掩耳盜鈴的行徑。在沒有安全疑慮的狀況下,建議配合 log 確認系統紀錄,這樣可以保持穩定又可以找到系統問題,不失為一個權宜之計。
使用的環境是 CentOS7 / Linode VPS ,從指令上來看應該 debian 系列的也可以用才對。
操作上只要把 service 的變數替換為對應的服務名稱即可,以下是 mysql 檢查重啟的 code.
#!/bin/bash
PATH=/usr/sbin:/usr/bin:/sbin:/bin
service=mysql
if [[ ! "$(/usr/sbin/service $service status)" =~ "running" ]]
then
echo "`date "+%Y-%m-%d %H:%M:%S"` | [logadm -on@`date "+%Y%m%d%H%M%S"`] "
echo "$service is stop!!"
/usr/sbin/service $service start
else
echo "`date "+%Y-%m-%d %H:%M:%S"` | [logadm -on@`date "+%Y%m%d%H%M%S"`] "
echo "$service is running"
fi
同場加映,今天寫這篇時,網路上再找了一下,找到一些比較進階的檢查 code:
在 iOS 的二進制檔案上傳之後,有時會有關於 Missing Purpose String in Info.plist 的錯誤,參考這個鏈結會發現需要在 info.plist 中添加說明的字串,這裡列表一份,以後可以直接使用。
<key>NSSpeechRecognitionUsageDescription</key>
<string>App需要您的同意,才能訪問語音識別</string>
<key>NSAppleMusicUsageDescription</key>
<string>App需要您的同意,才能訪問媒體資料庫</string>
<key>NSBluetoothPeripheralUsageDescription</key>
<string>App需要您的同意,才能訪問藍牙</string>
<key>NSCalendarsUsageDescription</key>
<string>App需要您的同意,才能訪問日曆</string>
<key>NSCameraUsageDescription</key>
<string>App需要您的同意,才能訪問相冊</string>
<key>NSContactsUsageDescription</key>
<string>App需要您的同意,才能訪問通信錄</string>
<key>NSHealthShareUsageDescription</key>
<string>App需要您的同意,才能訪問健康分享</string>
<key>NSHealthUpdateUsageDescription</key>
<string>App需要您的同意,才能訪問健康更新</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>App需要您的同意,才能始終訪問位置</string>
<key>NSLocationUsageDescription</key>
<string>App需要您的同意,才能訪問位置</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>App需要您的同意,才能在使用期間訪問位置</string>
<key>NSMicrophoneUsageDescription</key>
<string>App需要您的同意,才能訪問麥克風</string>
<key>NSMotionUsageDescription</key>
<string>App需要您的同意,才能訪問運動與健身</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>App需要您的同意,才能訪問相機</string>
<key>NSRemindersUsageDescription</key>
<string>App需要您的同意,才能訪問提醒事項</string>
筆記一下,避免以後換新電腦都忘記這種三百年才會設定一次的開發環境。
筆記一下,有點久沒寫 app 了。最近在用 flutter 套版實作 iOS 和 Android 工具 app , Android 上架沒意外介面大改版,不過還算難不倒我,遇到的問題比較多是 flutter 簽名的問題,寫好 shell 用 command line 執行還算簡單,但是 iOS 上架就麻煩了,真心懷疑 iOS 和 Facebook 的人工審核是包給同一家公司做的……。
這編列點一下,也把自己的經驗整理起來,希望可以記起來不要給踩兩次雷了:
革命尚未成功,還會持續更新,請同志繼續努力。
真的太久沒弄上架,目前還在和審核人員戰鬥中,希望能夠順利上架啊。稍微抱怨一下,不管是 fb 還是 iOS 的 app 審核也都滿討厭的,送審一次問題就丟一個回來,然後光是上架頁面表單填寫的問題就來來回回兩三次了,為什麼不要ㄧ次送審把有遇到的問題丟回來勒,難怪有專門幫人代操上架的工作,這也算是造就一個產業鍊吧。