wordpress_woocommerce_deep_guides 29/03/2026 3 דק׳ קריאה

איך להסיר סוגי משלוח לפי קטגוריות המוצר בעמוד לתשלום בווקומרס ?

פבלו רותם · 0 תגובות

איך להסיר סוגי משלוח לפי קטגוריות המוצר בעמוד לתשלום בווקומרס ?

איך להסיר סוגי משלוח לפי קטגוריות המוצר בעמוד לתשלום בווקומרס ?

בשיעור הזה אני מלמד אותך איך לשלוט על שיטות משלוח ב-WooCommerce לפי קטגוריות המוצרים שנמצאות כרגע בעגלה. המטרה היא לא רק למחוק method אחד עם if גנרי, אלא להבין מאיפה WooCommerce טוענת shipping rates, מתי נכון להתערב בפילטר, איך לכתוב תנאים אמינים, ואיך לבנות קוד שלא יישבר בכל פעם שמתווספת קטגוריה, מחלקת משלוח או אזור משלוח חדש.

הבעיה העסקית שמאחורי הדרישה

בחנויות אמיתיות הדרישה הזו מופיעה כל הזמן: מוצרים דיגיטליים שלא צריכים שליח, מוצרים שבירים שדורשים שליח מיוחד, ריהוט שלא ניתן למשלוח לנקודת איסוף, או קטגוריה כמו קירור שצריכה אזור ושיטת משלוח ייעודיים. אם לא מטפלים בזה נכון, הלקוח רואה אפשרויות לא רלוונטיות בקופה, בוחר שיטה לא חוקית מבחינת העסק, ואז אתה נאלץ ליצור מעקפים ידניים.

הפתרון המקצועי הוא לעבוד על ה-rates ש-WooCommerce כבר יצרה, ולא לנסות להסתיר שיטות בממשק עם JavaScript בלבד. למה? כי ההחלטה צריכה להתרחש בשרת, לא רק ב-UI. כך גם אם checkout מתרענן, session משתנה, או תוסף אחר מעדכן את הסל, הכללים נשמרים.

להבין את זרימת הנתונים של משלוחים ב-WooCommerce

WooCommerce מחשבת שיטות משלוח לפי zone, מחלקות משלוח, כתובת הלקוח והעגלה הנוכחית. אחרי החישוב הזה אפשר להתערב בפילטר woocommerce_package_rates ולסנן את ה-rates לפני שהם מוצגים ללקוח. זה בדיוק המקום שבו אני מעדיף לעבוד, כי שם כבר יש לך את כל הנתונים: מזהי שיטות, עלויות, package contents ופרטי המוצרים.

  • שלב 1: WooCommerce מזהה package.
  • שלב 2: היא מחשבת shipping methods לפי zone.
  • שלב 3: היא שולחת מערך rates.
  • שלב 4: אנחנו מסננים או משאירים methods לפי קטגוריות המוצרים.

ברגע שתבין את הרצף הזה, תפסיק לירות snippets עיוורים ותתחיל לפתח התאמות checkout בצורה מקצועית באמת.

קוד בסיסי שעובד נכון על השרת

הקוד הבא נותן לך בסיס מקצועי: קודם פונקציה שבודקת אם קיימת קטגוריה בעגלה, ואז פילטר שמחליט אילו rates להסיר. שים לב שאני לא מסתמך על שמות מוצגים של השיטות אלא על method_id ו-instance_id, כי זה אמין יותר.

<?php
/**
 * הסרת סוגי משלוח לפי קטגוריות מוצרים בעגלה.
 *
 * Author: pablo rotem
 */

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

/**
 * בודק האם יש בעגלה מוצר מקטגוריה מסוימת.
 *
 * @author pablo rotem
 */
function pablo_rotem_cart_has_category( array $package, array $category_slugs ): bool {
    foreach ( $package['contents'] as $cart_item ) {
        if ( empty( $cart_item['product_id'] ) ) {
            continue;
        }

        if ( has_term( $category_slugs, 'product_cat', $cart_item['product_id'] ) ) {
            return true;
        }
    }

    return false;
}

/**
 * מסנן שיטות משלוח לפי קטגוריות.
 *
 * @author pablo rotem
 */
function pablo_rotem_filter_shipping_methods_by_category( array $rates, array $package ): array {
    $has_fragile = pablo_rotem_cart_has_category( $package, array( 'fragile', 'glass' ) );
    $has_digital = pablo_rotem_cart_has_category( $package, array( 'digital-downloads' ) );

    foreach ( $rates as $rate_id => $rate ) {
        $method_id = $rate->method_id ?? '';
        $instance  = $rate->instance_id ?? 0;

        if ( $has_fragile && 'local_pickup' === $method_id ) {
            unset( $rates[ $rate_id ] );
            continue;
        }

        if ( $has_digital && in_array( $method_id, array( 'flat_rate', 'free_shipping', 'local_pickup' ), true ) ) {
            unset( $rates[ $rate_id ] );
            continue;
        }

        if ( $has_fragile && 12 === (int) $instance ) {
            unset( $rates[ $rate_id ] );
        }
    }

    return $rates;
}
add_filter( 'woocommerce_package_rates', 'pablo_rotem_filter_shipping_methods_by_category', 20, 2 );

היתרון בגישה הזאת הוא שאפשר להרחיב אותה בקלות: לעבוד עם כמה קטגוריות, להפעיל whitelist במקום blacklist, או לבנות טבלת חוקים מסודרת במקום ifים מפוזרים.

מתי עדיף לעבוד בשיטת whitelist

ברוב החנויות הבינוניות והגדולות אני מעדיף דווקא whitelist: במקום להגיד מה להסיר, אתה מגדיר מה מותר לכל סוג סל. זה מייצר פחות הפתעות כשמישהו מוסיף בעתיד שיטת משלוח חדשה בלוח הניהול ושוכח לעדכן את הקוד.

<?php
/**
 * שומר רק שיטות משלוח מותרות לפי קטגוריה.
 *
 * Author: pablo rotem
 */

function pablo_rotem_keep_allowed_shipping_methods( array $rates, array $package ): array {
    $allowed_methods = array();

    if ( pablo_rotem_cart_has_category( $package, array( 'refrigerated' ) ) ) {
        $allowed_methods = array( 'flat_rate:18', 'local_delivery:4' );
    } elseif ( pablo_rotem_cart_has_category( $package, array( 'furniture' ) ) ) {
        $allowed_methods = array( 'flat_rate:22' );
    }

    if ( empty( $allowed_methods ) ) {
        return $rates;
    }

    foreach ( $rates as $rate_id => $rate ) {
        if ( ! in_array( $rate_id, $allowed_methods, true ) ) {
            unset( $rates[ $rate_id ] );
        }
    }

    return $rates;
}
add_filter( 'woocommerce_package_rates', 'pablo_rotem_keep_allowed_shipping_methods', 30, 2 );

זוהי גישה מצוינת כשיש לך קבוצות מוצרים ברורות: קירור, ריהוט, ציוד מקצועי, מוצרים דיגיטליים וכדומה. במקום לשאול מה אסור, אתה שואל מה מותר – וזו שאלה בטוחה יותר.

איך לזהות נכון method_id, rate_id ו-instance_id

אחת הנקודות שהכי מבלבלות מפתחים היא ההבדל בין method_id לבין rate_id. method_id הוא סוג השיטה, למשל flat_rate או local_pickup. לעומת זאת rate_id כולל לעיתים גם את ה-instance, למשל flat_rate:18. אם אתה עובד עם shipping zones רבים, instance_id חשוב במיוחד.

הדרך הטובה ביותר ללמוד את זה באתר שלך היא להדפיס לוג זמני או להשתמש ב-debug log. כך תראה בדיוק אילו rates WooCommerce מחשבת בסל שלך.

דיבוג מסודר במקום ניחושים

אל תנחש. תמדוד. בזמן פיתוח, לוג קצר יחסוך לך שעות של ניסוי וטעייה. כך תוכל לראות איך WooCommerce מכנה כל rate באתר שלך.

<?php
/**
 * הדפסת shipping rates ללוג לצורכי דיבוג.
 *
 * Author: pablo rotem
 */

function pablo_rotem_log_shipping_rates( array $rates, array $package ): array {
    if ( ! defined( 'WP_DEBUG_LOG' ) || ! WP_DEBUG_LOG ) {
        return $rates;
    }

    foreach ( $rates as $rate_id => $rate ) {
        error_log(
            sprintf(
                'Rate ID: %s | Method: %s | Instance: %s | Label: %s',
                $rate_id,
                $rate->method_id ?? '',
                (string) ( $rate->instance_id ?? '' ),
                $rate->label ?? ''
            )
        );
    }

    return $rates;
}
add_filter( 'woocommerce_package_rates', 'pablo_rotem_log_shipping_rates', 5, 2 );

אחרי שסיימת לזהות את המזהים הנכונים, הסר את הלוג. אל תשאיר קוד דיבוג פעיל ב-production אם אין צורך.

תקלות נפוצות שצריך להיזהר מהן

אני רואה שוב ושוב את אותן טעויות: בדיקה רק של המוצר הראשון בסל, עבודה לפי שם מוצג של השיטה במקום ID, חוסר התחשבות במוצרים וירטואליים, ואי-בדיקה מול shipping zones שונים. טעות נוספת היא כתיבת קוד שמתאים לעגלת מוצר בודד, אבל נשבר כשיש כמה קטגוריות יחד.

  • אם הסל משלב כמה קטגוריות, צריך להחליט מי גובר על מי.
  • אם יש חבילות split packages, צריך להבין שהפילטר מקבל package ולא בהכרח את כל הסל בבת אחת.
  • אם אתה עובד עם checkout block, בדוק התאמה גם לארכיטקטורה החדשה.

לכן אני ממליץ לכתוב specification עסקי קצר לפני הקוד: אילו קטגוריות קיימות, איזו שיטת משלוח מותרת או אסורה לכל אחת, ומה קורה כשיש שילוב ביניהן.

תהליך QA שאני ממליץ עליו בכל חנות

  1. צור לפחות מוצר אחד בכל קטגוריה רלוונטית.
  2. בדוק סל עם מוצר יחיד בכל קטגוריה.
  3. בדוק סל משולב עם שתי קטגוריות מתנגשות.
  4. בדוק אזורי משלוח שונים וכתובות שונות.
  5. בדוק קופונים, משלוח חינם, ומצבי guest ו-logged-in.
  6. בדוק checkout קלאסי וגם block אם האתר משתמש בו.

המבחן האמיתי הוא לא האם snippet רץ, אלא האם הלקוח תמיד רואה רק את השיטות שמותרות מבחינת העסק – בלי הפתעות.

סיכום

אם תיקח מהמדריך הזה רק עיקרון אחד, קח את זה: החלטות משלוח ב-WooCommerce צריכות להתקבל על השרת, לפי package ורשימת rates אמיתית. ברגע שאתה עובד דרך woocommerce_package_rates, מזהים נכונים, ולוג דיבוג מסודר, אתה שולט בקופה בצורה מקצועית ולא עם טלאים.

קישורים רשמיים להמשך עבודה

  https://developer.woocommerce.com/docs/code-snippets/customising-checkout-fields/ | https://woocommerce.com/document/introduction-to-hooks-actions-and-filters/ | https://woocommerce.github.io/code-reference/hooks/hooks.html | https://developer.woocommerce.com/docs/apis/ | https://developer.wordpress.org/plugins/hooks/