I am using the save_post action to inspect a metadata field in a custom post and take some action on that value. This is the essential guts of how I am doing it:
add_action('save_post', 'my_save_post');
function my_save_post($post_id)
{
// Check if not autosaving, processing correct post type etc.
// ...
// Get the custom field value.
$my_field_value = get_post_meta($post_id, 'my_field', true);
// Do some action
// ...
}
This works fine when updating the post through the admin page. However, when first creating the post, the my_field_value is always empty. The field does get saved correctly, but this action trigger does not seem to be able to see it, nor any other custom field values.
I would like the action to be performed on all posts of this type created, and I will be importing many through the CSV Imported plugin. Even then, the custom fields do get imported correctly, and the action trigger does get fired for each row imported, but the save_post action still cannot see the custom field value.
So far as I can see from documentation, the post has already been created by the time this action fires, so I should always be able to see that custom metafield.
The answer, it seems, is in the order in which things happen. When creating a post from a form, the custom fields are all collected by the appropriate actions and added to the post before my save_post action fires. This means my trigger is able to see those custom field values.
When importing from CSV, the basic post is created first, and then the custom metafields are added. The save_post trigger fires on the first creation, before the metafields are added, and so the custom field data is not visible to the save_post action.
My solution was to catch the updates of the metadata using the updated_post_meta and added_post_meta actions as well as the save_post action:
add_action('updated_post_meta', 'my_updated_post_meta', 10, 4);
add_action('added_post_meta', 'my_updated_post_meta', 10, 4);
function my_updated_post_meta($meta_id, $post_id, $meta_key, $meta_value)
{
// Make sure we are handling just the meta field we are interested in.
if ($meta_key != 'my_custom_field') return;
if (wp_is_post_revision($post_id)) return;
if (get_post_type($post_id) != 'my_post_type') return;
if (trim($meta_value) == '') return;
// Do my custom task (linking this post to a parent post in a different
// post type). This is the same task performed by the save_post action.
my_link_product_track($post_id, trim($meta_value));
}
That is essentially what I do, and it seems to work well. I do encapsulate all the above into a custom class in the theme, and don't recommend using global scope variables as shown here, but this is just to show the method.
You should look at using $post->ID instead of $post_id -
$my_field_value = get_post_meta($post->ID, 'my_field', true);
get_post_meta in the Codex
EDIT:
Could you do something like this?
if($post->ID == ''){
$pid = $post_id;
} else {
$pid = $post->ID;
}
//$pid = $post->ID or $post_id, whichever contains a value
$my_field_value = get_post_meta($pid, 'my_field', true);
something that looks for a value in $post->ID and $post_id, and uses whichever one isn't blank?
Related
I have a custom post-type called reference. When I save a standard wp-post I would also like to save a copy of that post with the only difference is that it has post_type = 'reference';
I am using the following hook:
add_action('publish_post', 'create_reference', 10, 3);
function create_reference($id)
{
$post = get_post($id);
$ref = $post;
$ref->post_type = 'reference';
wp_insert_post($ref);
return $post // Seems that I need this line, otherwise the standard post wont save.
}
This seems to work but also changes the view in wp-admin which is confusing. Even though i am creating the post in the standard post view. The view changes to the reference post-type view.
I do not understand why this is happening and how it can be avoided.
Thank you.
This question is in regards to a plug-in I'm developing.
I'm trying to fire a function each time a custom post type called "Product" is added or edited. In particular, I need a hook that fires before the meta boxes load on the add/edit page, but that only fires on that "Product" custom post type's edit page.
The function that will fire makes an API request, and caches the response in a transient.
The reason for the action hook is because in my current code, when the transient has expired, the add/edit page is broken during the first page load. However if you refresh the page after that, it shows up as intended. I'm fairly certain this is happening because the current conditional statement that checks the transient is located inside of the function that generates the meta box. So my theory is if I can set up an action hook to check the transient before the meta box is generated, it might solve the problem.
However I've got a second theory that the problem is being caused because of the time it takes to make the API request and return the response is longer than the time it takes for the page to load. So if there is an action hook that will delay page loading until the function finishes executing it would be an ideal solution, but I don't believe such an action hook exists. I'm not even certain if such a delay is possible.
I'd really appreciate any help or alternative suggestions you guys might have. Thanks for your time guys.
Code Example:
add_action( 'edit_product', 'llc_hook_campaign_find_active' );
function llc_hook_campaign_find_active() {
if (!$t_campaign_find_active){
limelight_cart_campaign_find_active();
return false;
}
}
Since you are using an action hook, it is not waiting for your API response.
Try using a filter hook instead.
Try using wp_insert_post_data
function filter_handler( $data , $postarr ) {
//make your API call, get the response and store it in post meta or data wherever you want
$response = 'your API response';
//e.g. update_post_meta($postarr['ID'], 'meta_key', $response); OR
//$data['post_content'] = $response;
return $data;
}
add_filter( 'wp_insert_post_data', 'filter_handler', '99', 2 );
In your case, following should work -
add_filter( 'wp_insert_post_data', 'llc_hook_campaign_find_active', '99', 2 );
function llc_hook_campaign_find_active( $data , $postarr ) {
if (!$t_campaign_find_active){
limelight_cart_campaign_find_active();
return $data;
}
}
I was able to make the API request before the meta boxes loaded on the Admin Add/Edit screen by using the action filter edit_form_top. That particular action hook is fired as soon as the Add/Edit page for any post/page/custom post type is loaded. In order to narrow it down so that the function only fires on the Add/Edit screen for my "product" custom post type, I used get_current_screen() along with an if statement.
add_action('edit_form_top', 'llc_hook_campaign_find_active');
function llc_hook_campaign_find_active() {
//Fetch current screen information
$screen = get_current_screen();
//Check if post type is "product"
if($screen->post_type == "product") {
//API Request that checks for an existing transient
$t_campaign_find_active = get_transient('campaign_find_active');
if (!$t_campaign_find_active){
limelight_cart_campaign_find_active();
return false;
}
}
}
Works like a charm.
I would like to know how to run a function when a meta information of a custom post type is changed.
For example, I have a radio box associated with a custom post type. And made it with metaboxes, and when I change the option, I would like to run a function.
How would I do that?
Originally in OP's question.
I think I found what I wanted
function do_my_stuff($post_ID) {
//do my stuff here;
return $post_ID;
}
add_action('save_post', 'do_my_stuff');
Wordpress: executing function when saving or editing post
But is it possible to track what changes were made?
Yup, did it with your help diggy, but had to change something.
function do_my_stuff($post_ID) {
$newvalue = $_POST['my_metabox_value'];
echo $newvalue;
$oldvalue= get_post_meta($post_id, 'my_metabox_value', true );
echo $oldvalue;
}
add_action('pre_post_update', 'do_my_stuff');
In my custom post type, once the user saves the post, is there a way to check the value of one of the fields and update it? The value I will insert will depend on the post's ID so save_post needs to be used in case it's a new post.
Yes you can have all of your data from $_POST or global $post after you save or update the post using save_post hook as you mentioned in your question
add_action( 'save_post', 'afterSavePost' );
function afterSavePost($pid)
{
$postId=$pid;
// or
global $post;
$postId=$post->ID;
$postTitle=$post->post_title;
// or
$postId=$_POST['ID'];
$postTitle=$_POST['post_title'];
}
You mentioned custom field and in that case you can use
$yourCustomField=get_post_meta($postId, 'your_custom_field',true); // get a custom field
and
$yourCustomField="New value";
update_post_meta($postId, 'your_custom_field', $yourCustomField); // update a custom field
I am trying to automatically display all the custom fields of a custom post type alongside it's title and content.(Not in admin but on my actual site)
I need to be able to do this with an action hook or filter, rather than creating a template.
After scouring the web I was able to find the 'publish_{custom_post_type_name}' hook:
function my_cool_hook() {
echo get_post_meta($post->ID, 'my-custom-field-name', true);
}
add_action( 'publish_past_symposia', 'my_cool_hook' );
but it doesn't seem to do anything when I view my published custom post type on my site. Any ideas?
add_action( 'publish_past_symposia', 'my_cool_hook' );
This hook triggered only if PUBLISH post type.
YOu need to trigger the hook on web part - so...
add_filter('the_content', 'my_cool_hook');
function my_cool_hook($content){
return $content.get_post_meta(get_the_id(), 'my-custom-field-name', true);
}
now the content body filtred and your string from custom fields added.