保存 woocommerce 产品后,什么是 wordpress/woocommerce 钩子?

hus*_*emi 2 php wordpress woocommerce hook-woocommerce

我想在用户创建并保存产品数据后通过肥皂客户端将 woocommerce 产品数据发送到邮政公司的网络服务。所以我需要一个在用户创建产品后触发的钩子。我搜索了很多并找到了一些 wordpress 和 woocommerce 钩子,但它们都没有完成我的工作。发送日期后,Web 服务返回一个应设置为产品 SKU 的 ID。听到的是我的函数代码:(参数来自 save_post_product 挂钩)

function productPublished ($ID , $post , $update){
$product = wc_get_product( $post->ID);
$user = get_option ('myUsername');
$pass = get_option ('myPassword');
$name = $product->get_name();
$price = $product->get_regular_price();
$weight = $product->get_weight() * 1000;
$count = $product->get_stock_quantity();
$description = $product->get_short_description();
$result = $client -> AddStuff ([
    'username' => $user,
    'password' => $pass,
    'name' => $name,
    'price' => $price,
    'weight' => $weight, 
    'count' => $count,
    'description' => $description,
    'percentDiscount' => 0
]);
$stuff_id=(int)$result->AddStuffResult;
update_post_meta($product->get_id(),'_sku',$stuff_id);
}
Run Code Online (Sandbox Code Playgroud)

我用save_post_product行动。用户在输入名称和价格等之前单击新产品后,它似乎会触发,因为发送到网络服务的默认产品数据和在我输入任何数据之前生成并保存的 SKU。我使用transition_post_status此代码并将其添加到我的函数中:

if($old_status != 'publish' && $new_status == 'publish' && 
!empty($post->ID) && in_array( $post->post_type, array( 'product') )){
code...}
Run Code Online (Sandbox Code Playgroud)

结果与 相同save_post_product。我使用publish_product操作,结果没有改变。我用draft_to_publish钩子。在我输入产品名称和描述后,它似乎会触发。名称发送到网络服务,但价格和重量没有发送。sku 没有保存到数据库(为什么??)。我知道这里还有另一个问题,该save_post问题在发布帖子并保存到数据库后会触发。但我认为 woocommerce 是不同的。似乎在输入名称和描述之后以及输入价格等之前保存帖子。有什么建议吗???

Art*_*nix 5

您想要的操作如下:

add_action('woocommerce_update_product', 'productPublished');

add_action('woocommerce_new_product', 'productPublished');

function productPublished($product_id){
    //...
}
Run Code Online (Sandbox Code Playgroud)

您可以在此处的 Woo 源代码中找到它们(它们是从哪里触发的):

https://docs.woocommerce.com/wc-apidocs/source-class-WC_Product_Data_Store_CPT.html#237

实际上,我通过首先找到保存产品的源代码所在的位置来向后查找它们,然后在这些方法(创建/更新)中查找挂钩。

 //found on Line 134 method create
 do_action( 'woocommerce_new_product', $id );


 //found on Line 237 method update
 do_action( 'woocommerce_update_product', $product->get_id() );
Run Code Online (Sandbox Code Playgroud)

您还必须更改此行:

function productPublished ($ID , $post , $update){
    $product = wc_get_product( $post->ID);
}
Run Code Online (Sandbox Code Playgroud)

function productPublished($product_id){
    $product = wc_get_product( $product_id);
   //....
}
Run Code Online (Sandbox Code Playgroud)

我认为其他参数(缺少的)对您的代码并不重要。$post例如,如果它是更新或新产品,除了获取我们已经拥有的产品 ID 之外,我也看不到其他用途。

更新(确定回调参数)

如果您不确定回调的参数,您可以查看源代码(就像我上面所做的那样)或者如果您可以在文档中找到它或者作为最后的手段,您可以简单地输出它们。输出它们的最佳方式是这 3 种之一

这是我用一个以 WordPress 为模型的最小化/简化的工作钩子系统构建的示例。出于测试原因,并且当您知道它是如何工作时,构建起来并不难:

//global storage (functions, not classes)
global $actions;
$actions = [];

//substitute wordpress add_action function (for testing only) 
function add_action($action, $callback, $priorty=10, $num_args=1){
    global $actions;
    $actions[$action][] = [
         'exec' => $callback,
         'priorty'=>$priorty,
         'num_args' => $num_args
    ];

}
//substitute wordpress do_action function (for testing only) 
function do_action($action, ...$args){
    // PHP5.6+ variadic (...$args) wraps all following arguments in an array inside $args (sort of the opposite of func_get_args)
    global $actions;

    if(empty($actions[$action])) return;
    //sort by priory
    usort($actions[$action], function($a,$b){
       //PHP7+ "spaceship" comparison operator (<=>)
       return $b['priorty']<=>$a['priorty'];
    });

    foreach($actions[$action] as $settings){
        //reduce the argument list
        call_user_func_array($settings['exec'], array_slice($args, 0, $settings['num_args']));
    }
}

//test callback
function callback1(){
     echo "\n\n".__FUNCTION__."\n";
    print_r(func_get_args());
}

//test callback
function callback2(){
    echo "\n\n".__FUNCTION__."\n";
    try{
        //throw an empty exception
        throw new Exception;
    }catch(\Exception $e){
         //pre tags preserve whitespace (white-space : pre)
        echo "<pre>";
        //output the stacktrace of the callback
        echo $e->getTraceAsString();
        echo "\n\n</pre>";
   }
}

//Register Hook callbacks, added in opposite order, sorted by priority
add_action('someaction', 'callback2', 5, 4);
add_action('someaction', 'callback1', 1, 5);

//execute hook
do_action('someaction', 1234, 'foo', ['one'=>1], new stdClass, false);
Run Code Online (Sandbox Code Playgroud)

输出:

callback2
<pre>#0 [...][...](25): callback2(1234, 'foo', Array, Object(stdClass))
#1 [...][...](52): do_action('someaction', 1234, 'foo', Array, Object(stdClass), false)
#2 {main}

</pre>

callback1
Array
(
    [0] => 1234
    [1] => foo
    [2] => Array
        (
            [one] => 1
        )

    [3] => stdClass Object
        (
        )
    [4] =>
)
Run Code Online (Sandbox Code Playgroud)

沙盒

堆栈跟踪正如您在第一个输出中看到的,我们有应用程序的完整堆栈跟踪(减去编辑信息),包括函数调用和用于这些调用的参数。另请注意,在此示例中,我将其注册为第二个,但优先级(在 中设置add_action)使其首先执行。最后,仅使用了 5 个参数中的 4 个(也涉及如何add_action调用)。

所以do_action被这样调用(带有“action”和 5 个其他参数):

 do_action('someaction', 1234, 'foo', Array, Object(stdClass), false)
Run Code Online (Sandbox Code Playgroud)

实际的回调是这样调用的(没有“action”,只有 4 个其他参数):

 callback2(1234, 'foo', Array, Object(stdClass))
Run Code Online (Sandbox Code Playgroud)

函数参数这有点更直接,但它不会给你原始的调用,所以你不会知道参数的最大数量(你可以从堆栈跟踪中的 do_action 调用中获得)。但如果您只想快速查看传入的数据,那么它是完美的。另外我应该提到这个使用了所有 5 个参数,您可以在第二个输出的数组中清楚地看到它们。为[4] =>false,这通常是print_r显示 false 的方式(仅显示为空)。

不幸的是,调试回溯debug_print_backtrace在沙箱中被禁用(出于安全原因),并且出于安全原因,异常堆栈跟踪也被大量编辑(通常它具有调用函数和位于其中的文件名和行)。这两个都可以从连接到数据库之类的事情返回参数,例如,其中将包含纯文本的数据库密码。无论如何,debug_print_backtrace与异常堆栈跟踪的外观非常接近。

夏日

但无论如何,这应该能让您了解数据的样子。我们可以使用这样的函数(和反射)在运行时询问应用程序。我确信还有其他/更多的方法可以做类似的事情。

附言。这应该是不言而喻的,但无论如何我都会说,上面的这些方法适用于任何 PHP 函数,并且非常有用。同样如上所述,您永远不应该在实时生产机器上显示堆栈跟踪。

无论如何,祝你好运。