Woocommerce 新增商品時自動產生隨機永久連結

Woocommerce 本身提供的商品網址格式預設情況下只能用 post_idpost_name,但在非英文語系的情況下,固定網址往往會變成一長串,因為中文會先經過 URL encoding。
假設商品名稱是 推車置物架 置物推車
那網址就會變成 your-domain.com/product/%E6%8E%A8%E8%BB%8A%E7%BD%AE%E7%89%A9%E6%9E%B6-%E7%BD%AE%E7%89%A9%E6%8E%A8%E8%BB%8A,這個在轉發給他人時既無法閱讀也占版面。

但假如說換成 post_id,又能讓人從 post_id 來推測出賣場訂單數量,假設我 7 月份時上架一支商品,當時 post_id 是1000,結果8月份時再上架一支新商品 post_id 卻只到 1200。這樣就可以合理推斷過去一個月的時間產生的頁面、圖片、訂單、商品數量才不到200,可見賣場訂單量之少。

在商業上讓人摸清底牌的話對價格的談判可不有利,所以理想的網址應該要把賣場中會出現 post_id 的項目都給隱藏,並且自動產生足夠段並帶有一定識別度的網址。

Woocommerce 有提供2個 action:

  • woocommerce_product_import_inserted_product_object:批次匯入時觸發 (包括匯入更新也算)
  • woocommerce_new_product:新增商品時觸發

透過這兩個 action,就可以在商品上架的那一刻一併寫入自定義的固定網址 (sulg)

PHP
add_action('woocommerce_new_product', function ($product_id) {
    n263_generate_product_hash_url(wc_get_product($product_id));
});
add_action('woocommerce_product_import_inserted_product_object', function ($product, $data) {
    n263_generate_product_hash_url($product);
}, 10, 2);

// 透過商品ID產生自訂URL
function n263_generate_product_hash_url($product)
{
    // 確保是主商品不是變化類型
    if (!$product || $product->is_type('variation'))
        return;

    // 先檢查是否已經有格式為 yymm-隨機8碼 的固定網址,若有則跳過
    $id = $product->get_id();
    $current_slug = get_post_field('post_name', $id);
    if ($current_slug && preg_match('/^\d{4}-[a-z0-9]{8}$/', $current_slug)) {
        return;
    }

    // 產生自訂唯一網址,並檢查是否重複,若重複則最多重新產生5次
    for ($i = 0; $i < 5; $i++) {
        $random = substr(base_convert(bin2hex('1' . random_bytes(8)), 16, 36), 1, 8);
        $slug = date("ym") . '-' . $random;
        $exists = get_page_by_path($slug, OBJECT, 'product');   //檢查URL是否已經存在

        if (!$exists)
            break;
    }

    // 更新 Slug
    wp_update_post([
        'ID' => $id,
        'post_name' => $slug	 //將商品網址設定為 yymm-隨機8碼 的格式
    ]);
}

這樣當商品新增、匯入時就會自動執行這一段短代碼,只要不是變化類型的商品 且 商品的固定連結不是 yymm-8碼隨機的格式,就會幫他產生一組固定網址,避免使用 post_id ,又不會有 postname 超長一串的網址。

不過要注意的是,即使網址中隱藏了post_id,在商品頁面的 HTML > body 中的 class 還是會出現 postid,這部份要用另一段短代碼隱藏。

透過 F12 開啟 DevTools 可以看見 body 中帶有 posdid-2396 的字樣
PHP
add_filter( 'body_class', 'n263_body_class_remove_postid' );
function n263_body_class_remove_postid( $classes ) {
    // 過濾掉以 postid- 開頭的 class
    return array_filter(
        $classes,
        function( $class ) {
            return strpos( $class, 'postid-' ) !== 0 ;
        }
    );
}

body_class 這個 filter 會把所有的 Class 透過 $classes 這個陣列傳進來,這時我們只需要用 array_filter 過濾掉文字中包含 postid 的 class 即可。

發表迴響

返回頂端