Ask your WordPress questions! Pay money and get answers fast! Comodo Trusted Site Seal
Official PayPal Seal

Need function to save custom field as post_content on save/update WordPress

  • SOLVED

I am using Advanced Custom Fields (plugin) to allow users to post from the front-end of my site. I would like one of the custom fields to be the "content" of each post. However, I also want to be able to Wordpress's native tools when dealing with the_content (like sanitizing, excerpts, etc). I've been trying to find a way to save the custom-field as post_data before the post is saved to the database on both the first publish and each subsequent update of the post.

I found this snippet of code while searching around, but I'm not a plugin developer so it's a little over my head.


//Write custom field to be used as post_content in database
function filter_handler( $data , $postarr )
{
// do something with the post data
return $data;
}

add_filter( 'wp_insert_post_data' , 'filter_handler' , '99', 2 );


Can somebody help?

Answers (2)

2013-03-23

Kyle answers:

How are you submitting the info from the frontend? If there is a way to hook into the info being submitted before creating the post that is the best bet because the post hasn't been created yet (so rather than alter an existing post, you are modifying it before it is created).


Zac Eckstein comments:

I am submitting via a template function from ACF. It creates the post form for me automatically and then the fields are saved as meta data on the post. I think it would have to be a filter or something that catches the content before it goes into the database. Like pre_save_posts or something like that. I just don't quite know how to use it.

Not sure if it's helpful, but I'm using another custom function to make ACF work on the front-end which may or may not be part of a solution to this. Here is that code:


//Allow new posts to be created with ACF
// custom action for saving the front end form
function tsv_acf_form_pre_save_post( $post_id ){
// create a new post

$title = $_POST['ptitle'];
if( $_POST['post_id' ] == 'new_post' ) {
$post = array('post_status' => 'publish' , 'post_type' => 'post' , 'post_title' => $title ,);
// insert the post
$post_id = wp_insert_post( $post );
// save the data
do_action('acf/save_post' , $post_id);
// redirect
$permalink = get_permalink($post_id);
wp_redirect($permalink);
exit;
} else {
//otherwise, just pass along the post id
$post_id = $_POST['post_id' ];
}

return $post_id;
}

add_filter('acf_form_pre_save_post' , 'tsv_acf_form_pre_save_post' );


Kyle comments:

You aren't doing re-editing of the post from this same function are you?


Zac Eckstein comments:

The ELSE statement passes along the ID back to ACF and then ACF does the updating part, if need be. So no, this function only publishes new posts because ACF doesn't have that built-in functionality.


Kyle comments:

You have everything you need there, you just need to include whatever form input is your post content in with what you are submitting. It goes right in with the title and everything you have above. If you don't know the form input you need the $POST_ var that is submitting it like post_id

function tsv_acf_form_pre_save_post( $post_id ){
$id = $_POST['post_id'];
if( !empty($id)) {
$post_c = PUT YOUR USER INPUT ID HERE;
$post = array('post_status' => 'publish' , 'post_type' => 'post' , 'post_title' => $title , post_content => $post_c );
$post_id = wp_insert_post( $post );
do_action('acf/save_post' , $post_id);
$permalink = get_permalink($post_id);
wp_redirect($permalink);
exit;
} else { }
return $post_id;
}
add_filter('acf_form_pre_save_post' , 'tsv_acf_form_pre_save_post' );


Zac Eckstein comments:

Ah yes, this was my first thought. I should have explained why I can't get this to work. ACF outputs keys for the "name" field of the inputs.

For instance, this specific field I'm referencing above renders like this:


<textarea id="wysiwyg-acf-article_content" class="wp-editor-area" name="fields[field_514a83d7a3365]" ></textarea>


That would fine in some cases (if not a bit fragile) but I'm planning on implementing this for multiple post-types and they will all have different field-keys, even if I give them the same ID or name or class in ACF settings.


Zac Eckstein comments:

Unless there is a way to use get_field as mentioned in an answer above to get the field by its slug instead of the $_POST name.


Kyle comments:

With ACF's way of storing vars with unique IDs it may be best to go with something that pulls the post once it has been saved and modifies it, like Arnav's code said above.

So you'll want to use that hook to pull the save_post and grab the vars and modify them. Do you know what wasn't working with his code?


Zac Eckstein comments:

I'm not sure exactly what's not working in the above code. When I put that in my functions file it doesn't save the custom field OR the_content. It only saves the title. It also doesn't do the redirect to the new post after I publish it.


Kyle comments:

Redirect you can handle last. Try this below, it is Arnav's but uses get_post_meta instead of get_field.

add_action('save_post', 'change_content');
function change_content($post_id) {

$post_content = get_post_meta($post_id,'ACF_FIELD_NAME',true);

$my_post = array();
$my_post['ID'] = $post_id;
$my_post['post_content'] = $post_content;

wp_update_post( $my_post );

}


A good trick you can try to check if the values are being pulled is to email them out to yourself. So for this it would be

add_action('save_post', 'change_content');
function change_content($post_id) {

$post_content = get_post_meta($post_id,'ACF_FIELD_NAME',true);

wp_mail('[email protected]', 'Content Test', $post_content );

$my_post = array();
$my_post['ID'] = $post_id;
$my_post['post_content'] = $post_content;

wp_update_post( $my_post );

}


If this doesn't work, we can try a different hook than save_post, like new_to_publish


Kyle comments:

Don't forget to put in your ACF field above too


Zac Eckstein comments:

OK, that was interesting....

That didn't work but now I can't get wordpress to stop sending emails! I'm getting endless emails even after removing wp_mail from the function and reuploading the file. How do I stop this??

So lost here....


Kyle comments:

Delete the wp_mail function

For some reason your wp is stuck in a save_post loop. Delete the function and eventually it will timeout


Zac Eckstein comments:

OK, it stopped. That was scary for a moment!

What I think caused it is that the solution didn't work from the front end so I tried it on the back end by entering content into the custom field from there to see if it would populate the regular content. It didn't, but it did pass that info over to the function which emailed me the correct content (over and over, haha).

So it seems like from the front-end the function is not firing or is getting skipped due to ACF probably. Here is the ACF api.php that process the $_POST form, updates the database, etc, maybe this will help going forward:

https://github.com/elliotcondon/acf4/blob/master/core/api.php

The frontend stuff starts at line 912


Kyle comments:

I realized what the problem is, using save_post and wp_update_post together causes an infinite loop because wp_update_post uses save post.

Was anything being sent in the emails? That is most important

You can still try with that function but need to eliminate the loop

add_action('save_post', 'change_content');
function change_content($post_id) {
$post_content = get_post_meta($post_id,'ACF_FIELD_NAME',true);
wp_mail('[email protected]', 'Content Test', $post_content );
$my_post = array();
$my_post['ID'] = $post_id;
$my_post['post_content'] = $post_content;
remove_action('save_post', 'change_content');
wp_update_post( $my_post );
add_action('save_post', 'change_content');
}


Still can also try with the new_to_publish hook too


Zac Eckstein comments:

We're getting closer!

From the front end, the post was created but without sending the email or automatically updating the post content. BUT, if I try it on the back end (admin) it works beautifully and as expected both when the post is created and when the post is updated.

So now we just have to figure out how to get the front-end form to do the same thing.

Thanks for the help so far, you've been awesome!


Kyle comments:

Is the email sent when you update on the backend?

My guess is the acf form is missing the hook somehow. Do you update the post from the frontend too? We can add another hook and see if it hits it when the form is submitted:

add_action('new_to_publish', 'change_content');
add_action('save_post', 'change_content');
function change_content($post_id) {
$post_content = get_post_meta($post_id,'ACF_FIELD_NAME',true);
wp_mail('[email protected]', 'Content Test', $post_content );
$my_post = array();
$my_post['ID'] = $post_id;
$my_post['post_content'] = $post_content;
remove_action('save_post', 'change_content');
remove_action('new_to_publish', 'change_content');
wp_update_post( $my_post );
add_action('save_post', 'change_content');
add_action('new_to_publish', 'change_content');
}


You're welcome, happy to help


Kyle comments:

Let me know if that works, after looking through the acf api it looks like it uses its own version of save_post on frontend, which is why it it was missing.


Zac Eckstein comments:

Yes I will be updating the post via the frontend as well. The email did send when added/updated from the back-end. Although, with this new function it doesn't seem to be working on the back-end anymore (both the email and the updating of the post).

Maybe we do need to use the custom save post from ACF.


Kyle comments:

Okay let's break it up into two functions, one for the back and one for the front. There is no reason the email shouldn't be going out, are you inserting your email each time?


add_action('save_post', 'change_content');
function change_content($post_id) {
$post_content = get_post_meta($post_id,'ACF_FIELD_NAME',true);
wp_mail('[email protected]', 'Content Test', $post_content );
$my_post = array();
$my_post['ID'] = $post_id;
$my_post['post_content'] = $post_content;
remove_action('save_post', 'change_content');
wp_update_post( $my_post );
add_action('save_post', 'change_content');
}


add_action('acf/save_post', 'change_content');
function change_content($post_id) {
$post_content = get_post_meta($post_id,'ACF_FIELD_NAME',true);
wp_mail('[email protected]', 'Content Test (front)', $post_content );
$my_post = array();
$my_post['ID'] = $post_id;
$my_post['post_content'] = $post_content;
remove_action('acf/save_post', 'change_content');
wp_update_post( $my_post );
add_action('acf/save_post', 'change_content');
}


Zac Eckstein comments:

Oh whoops, I did not change the ACF field name and email for that lost one, sorry. Just tried it again and got the same behavior as before. Works on the back-end, but not the front end.

Let me try the two-function solution real quick...


Zac Eckstein comments:

BTW, the field name is article_title


Kyle comments:

Okay, yes good to know so you don't have to change it over and over :)


Zac Eckstein comments:

Whoops, the name of the field is actually article_content, not article_title.

Anyway, the two-functions are throwing a server error now. It might just be a syntax error, but I can't find the issue looking through it.


Zac Eckstein comments:

Oh! I figured it out! It's because the two functions had the same name. I changed the 2nd function to change_content_frontend and it made everything work like it should!

Brilliant, I think we got it!


Kyle comments:

Oh that's my fault the functions are named the same. Change the second one to this:


add_action('acf/save_post', 'change_content_2');
function change_content_2($post_id) {
$post_content = get_post_meta($post_id,'ACF_FIELD_NAME',true);
wp_mail('[email protected]', 'Content Test (front)', $post_content );
$my_post = array();
$my_post['ID'] = $post_id;
$my_post['post_content'] = $post_content;
remove_action('acf/save_post', 'change_content_2');
wp_update_post( $my_post );
add_action('acf/save_post', 'change_content_2');
}


Kyle comments:

Awesome glad to hear it! That took awhile


Kyle comments:

If you are able to add a little to the pot I wouldn't object :) up to you though


Zac Eckstein comments:

It did indeed, but thank you for sticking with me! This was a huge roadblock on this project that I can now move past!


Zac Eckstein comments:

I voted for you to receive the $25, hopefully it gets to you! I don't quite understand how the payment situation works on here quite yet....


Zac Eckstein comments:

Uh oh, i ran into a problem.

When I attempt to update (not create) an existing post it doesn't update and instead re-populates with the same values as the first publish. I have editing the function a bit to do more things, here is the current version. Any ideas on that?

//Save ACF field as post_content for front-end
add_action('acf/save_post', 'change_content_frontend');
function change_content_frontend($post_id) {
if(get_post_type( $post_id ) != 'acf'){ //This function won't run if adding/updated fields/field-groups in wp-admin
$post_content = get_post_meta($post_id,'user_post_content',true);
$post_title = get_post_meta($post_id, 'user_post_title' , true);
$post_slug = sanitize_title_with_dashes ($post_title,'','save');
$post_slugsan = sanitize_title($post_slug);
//wp_mail('[email protected]', 'Content Test (front)', $post_content ); //debugging
$my_post = array();
$my_post['ID'] = $post_id;
$my_post['post_content'] = $post_content;
$my_post['post_title'] = $post_title;
$my_post['post_name'] = $post_slugsan;
remove_action('acf/save_post', 'change_content_frontend');
wp_update_post( $my_post );
add_action('acf/save_post', 'change_content_frontend');
}
}


Zac Eckstein comments:

Oh, and I got everything to work using 1 function after-all. The above is working fine for creating posts.

2013-03-23

Arnav Joy answers:

try this

<?php

add_action('save_post', 'change_content');

function change_content($post_id) {

$post_content = get_field('ACF_FIELD_NAME',$post_id);
wp_update_post(array('ID' => $post_id, 'post_content' => $post_content ));


}
}
?>


Arnav Joy comments:

please change custom field name to yours

$post_content = get_field('ACF_FIELD_NAME',$post_id);

// ACF_FIELD_NAME to be changed


Zac Eckstein comments:

That didn't seem to work. Using that it actually no longer saves the custom field content either.


Arnav Joy comments:

can you share your full code which you are using at front end?


Zac Eckstein comments:

Here is the page in question: http://theseattlevine.com/wordpress2013/publish/

The actual code to generate the form is a function from ACF, so I'm not sure if it's helpful:


$options = array(
'post_id' => 'new_post' ,
'field_groups' => array(68) ,
'html_before_fields' => '
<p class="label">
<label for="ptitle">Post Title</label>
</p>
<input type="text" name="ptitle" id="ptitle" class="text" value="" />
',
);
acf_form($options);