$conf, $runtime; function_exists('chdir') AND chdir(APP_PATH); $r = 'mysql' == $conf['cache']['type'] ? website_set('runtime', $runtime) : cache_set('runtime', $runtime); } function runtime_truncate() { global $conf; 'mysql' == $conf['cache']['type'] ? website_set('runtime', '') : cache_delete('runtime'); } register_shutdown_function('runtime_save'); ?>taxonomy - wp_set_object_terms() Fails to Set Terms|Programmer puzzle solving
最新消息:Welcome to the puzzle paradise for programmers! Here, a well-designed puzzle awaits you. From code logic puzzles to algorithmic challenges, each level is closely centered on the programmer's expertise and skills. Whether you're a novice programmer or an experienced tech guru, you'll find your own challenges on this site. In the process of solving puzzles, you can not only exercise your thinking skills, but also deepen your understanding and application of programming knowledge. Come to start this puzzle journey full of wisdom and challenges, with many programmers to compete with each other and show your programming wisdom! Translated with DeepL.com (free version)

taxonomy - wp_set_object_terms() Fails to Set Terms

matteradmin7PV0评论

Okay guys, here's the scenario.

I'm am trying to setup a function that will automatically duplicate a post (when published) over to another post type. So, a regular blog post is published, and when it is published, all of its information is copied over to a custom post type (for WP ECommerce), automatically creating a store entry for that blog post.

I've written a function that takes care of picking up all of the information and inserting it into a new post with wp_insert_post(). It all works great, except for one thing. I'm using wp_set_object_terms() to set the store category ids of the new product based on the tags of the blog post. However, for some reason, wp_set_object_terms() never works.

Now, here's the catch. I'm running all of this on a multi site install and am using threeWP_Broadcast to allow me to cross publish posts. The blog posts (which have to be copied to the store) are published from a sub site and broadcasted to the main site. The store is on the main site.

So I've hooked my custom function into the broadcast plugin so that it gets fired when a post is broadcasted from a sub site to the main site.

Everything with my function works great, except for the wp_set_object_terms()

Here's function:

function copy_post_to_store_product() {

global $blog_id;
global $wpdb;

// only copy the post over if on main site, not subsites
if ($blog_id == 1) {

    $args = array('numberposts' => 1);
    $latest = get_posts($args);
    foreach($latest as $post) : setup_postdata($post);

        // if NOT Tip and NOT source avail, create product
        // if source, price is ALWAYS $4
        // auto create for source files only -- regular post type

        $custom_meta = get_post_custom($post->ID);

        // what kind of post is this?
        $post_type = $custom_meta['cgc_post_type'][0];
        // does this post have a source file product associated with it?
        $source_avail = $custom_meta['cgc_source_avail'][0];

        // source file price
        $price = '4';


        $product_info = array(
            'post_title'    => $post->post_title,
            'post_type'     => 'wpsc-product',
            'post_content'  => $post->post_content,
            'post_author'   => $post->post_author,
            'post_status'   => 'draft', 
        );


        if($post_type == 'Regular' && $source_avail == true) {
            // only auto create product for Regular posts that have source files for sale
            $product_id = wp_insert_post($product_info);
            update_post_meta($product_id, '_wpsc_price', $price);

            if (has_tag('blender', $post->ID)) 
            { 
                $product_cats = array(23,32);
            }
            elseif (has_tag('max', $post->ID)) {
                $product_cats = array(23,34);
            }
            elseif (has_tag('modo', $post->ID)) {
                $product_cats = array(23,19);
            }

            // set the product categories
            wp_set_object_terms($product_id, $product_cats, 'wpsc_product_category' );

        }


    endforeach;
}

}

The function works by retrieving the latest post from the main site ($blog_id == 1) and copying all of its information into variables for wp_insert_post().

Now, the really interesting thing is that works perfectly if I attach the function to a publish_post hook, but, unfortunately, I can't do that because that hook doesn't fire when a post is broadcasted.

Any ideas would be hugely appreciated.

Okay guys, here's the scenario.

I'm am trying to setup a function that will automatically duplicate a post (when published) over to another post type. So, a regular blog post is published, and when it is published, all of its information is copied over to a custom post type (for WP ECommerce), automatically creating a store entry for that blog post.

I've written a function that takes care of picking up all of the information and inserting it into a new post with wp_insert_post(). It all works great, except for one thing. I'm using wp_set_object_terms() to set the store category ids of the new product based on the tags of the blog post. However, for some reason, wp_set_object_terms() never works.

Now, here's the catch. I'm running all of this on a multi site install and am using threeWP_Broadcast to allow me to cross publish posts. The blog posts (which have to be copied to the store) are published from a sub site and broadcasted to the main site. The store is on the main site.

So I've hooked my custom function into the broadcast plugin so that it gets fired when a post is broadcasted from a sub site to the main site.

Everything with my function works great, except for the wp_set_object_terms()

Here's function:

function copy_post_to_store_product() {

global $blog_id;
global $wpdb;

// only copy the post over if on main site, not subsites
if ($blog_id == 1) {

    $args = array('numberposts' => 1);
    $latest = get_posts($args);
    foreach($latest as $post) : setup_postdata($post);

        // if NOT Tip and NOT source avail, create product
        // if source, price is ALWAYS $4
        // auto create for source files only -- regular post type

        $custom_meta = get_post_custom($post->ID);

        // what kind of post is this?
        $post_type = $custom_meta['cgc_post_type'][0];
        // does this post have a source file product associated with it?
        $source_avail = $custom_meta['cgc_source_avail'][0];

        // source file price
        $price = '4';


        $product_info = array(
            'post_title'    => $post->post_title,
            'post_type'     => 'wpsc-product',
            'post_content'  => $post->post_content,
            'post_author'   => $post->post_author,
            'post_status'   => 'draft', 
        );


        if($post_type == 'Regular' && $source_avail == true) {
            // only auto create product for Regular posts that have source files for sale
            $product_id = wp_insert_post($product_info);
            update_post_meta($product_id, '_wpsc_price', $price);

            if (has_tag('blender', $post->ID)) 
            { 
                $product_cats = array(23,32);
            }
            elseif (has_tag('max', $post->ID)) {
                $product_cats = array(23,34);
            }
            elseif (has_tag('modo', $post->ID)) {
                $product_cats = array(23,19);
            }

            // set the product categories
            wp_set_object_terms($product_id, $product_cats, 'wpsc_product_category' );

        }


    endforeach;
}

}

The function works by retrieving the latest post from the main site ($blog_id == 1) and copying all of its information into variables for wp_insert_post().

Now, the really interesting thing is that works perfectly if I attach the function to a publish_post hook, but, unfortunately, I can't do that because that hook doesn't fire when a post is broadcasted.

Any ideas would be hugely appreciated.

Share Improve this question asked Apr 25, 2011 at 19:00 PippinPippin 4,8966 gold badges34 silver badges47 bronze badges 6
  • What does wp_set_object_terms() return for you? – Rarst Commented Apr 29, 2011 at 9:40
  • Nothing at all, at least not than I can tell. It acts as though it worked, but nothing gets set. – Pippin Commented Apr 29, 2011 at 18:19
  • @Pippin it should always return something (can be different things depending on if it worked and what error is if it didn't), wrap it in var_dump() – Rarst Commented Apr 29, 2011 at 18:42
  • @Rarst this is what I'm getting: object(WP_Error)#1159 (2) { ["errors"]=> array(1) { ["invalid_taxonomy"]=> array(1) { [0]=> string(16) "Invalid Taxonomy" } } ["error_data"]=> array(0) { } } – Pippin Commented May 4, 2011 at 14:19
  • @Rarst I know that the taxonomy name is correct, as well as the IDS, so I really don't understand that error. – Pippin Commented May 4, 2011 at 14:20
 |  Show 1 more comment

7 Answers 7

Reset to default 0

I don't have a solution, but there's a ticket #20541 on Make WordPress Core.

Apparently a call to switch_to_blog() would not repopulate $wp_taxomies, which these taxonomies rely on.

I just came across the same problem and worked out a solution with help from Patriek's answer. You just need to make sure that wp_set_object_terms() is run after the custom taxonomy is registered. Since register_taxonomy() is usually run at init, you can also run your function at init action hook, but with a lower priority so it runs later.

add_action( 'init', 'register_custom_taxonomies', 0 );

function register_custom_taxonomies() {
    // register your taxonomies here    
}

add_action( 'init', 'copy_post_to_store_product', 10)

function copy_post_to_store_product() {
    // your function that runs wp_set_object_terms() here
}

This way, the taxonomy is guaranteed to be available when your function is run.

Forget about the previous answer, You say that it works fine with publish_post hook then you create a plugin in your mu-plugins (“must-use” plugins) which you can hook your function to and just add switch_to_blog before you start inserting and updating things in the database and then revert back using restore_current_blog() So

switch_to_blog($main_blog_id); //usually 1
...
//your function
...
restore_current_blog();

Just throwing this out there: I had a similar problem once where a taxonomy was not available at the time my function was running. This could either be a problem with wp ecommerce or the broadcast plugin.

Check if the wp ecommerce plugin uses this syntax for registering their taxonomy

add_action( 'init', 'taxonomy_function_name', 0 );

Check if they appended the ,0. This sets the priority of the taxonomy function to 0. Which would be as early as possible.

Is it possible to set priority for the broadcast hook?

i have got the solution,

i have investigated the taxonomy.php file, then i found that the problem is on the function taxonomy_exists(). Since the switch_to_blog() function don't read the theme and plugin code, so it will not detect our registered taxonomy on the other blog, so we need to manualy init that, just before the taxonomy_exists() function

Put this code before the wp_set_object_terms() function:

global $wp_taxonomies;
$wp_taxonomies['your_blog_taxonomy'] = array();

After trying so much trial and error I have found the real issue is that you need to set your function of setting up a taxonomy for CTP in Init with low priority.

add_action( 'init', 'your_function_product', 20 );

thank you guys, you saved my life :)
Low priority (20) for the function that inserts the post(s) will do the trick! Here is an approach for wp_insert_post() in functions.php:

function insert_db_posts() {
        $thepost = wp_insert_post(array(
                'post_type'         =>  'art',
                'post_title'        =>  'Try hard',
                ));
        wp_set_object_terms( $thepost, 37, 'artist');
}
add_action( 'init', 'insert_db_posts', 20 ); // this will fire very late so everything else is already initialized before this!!!
Post a comment

comment list (0)

  1. No comments so far