Wordpress: update_post_meta not working - php

I am modifying an existing plugin and I want to add a new field to the form and then have that field be submitted along with the post. The post gets submitted to wp_posts. I have read on Google that to do this one simply needs to use update_post_meta. I am trying to insert data into a new column I made in PHPMyAdmin. I named the column post_amount. The field name is amount_field. Although I'm a beginner, something about "just use update_post_meta" that I've read seems too simple to be all that I need. But I might be wrong. Maybe I'm using it wrong?
Note - this whole attempt is due to me wanting to create a new column in the wp_posts table and add data to it with each posts. Is this even the correct way to do this? I see the words "meta_key" and "meta_value" and it makes me think that this will actually end up adding data in the wp_postmeta table....or is that the intended destination?
$question_array = array(
'post_title' => $fields['title'],
'post_author' => $user_id,
'post_content' => apply_filters('ap_form_contents_filter', $fields['description']),
'post_type' => 'question',
'post_status' => $status,
'comment_status' => 'open',
);
if(isset($fields['parent_id']))
$question_array['post_parent'] = (int)$fields['parent_id'];
$question_array = apply_filters('ap_pre_insert_question', $question_array );
$post_id = wp_insert_post($question_array);
$post_amount = $fields['amount_field']; //My code
update_post_meta($post_id, 'post_amount', $post_amount); //My code

I think you made a mistake updating your post_id.
In update_post_meta($post_id, 'post_amount', $post_amount);
you don't have ID of the post or the ID you want to update.
$post_id parameter is declared to Insert Post in your above code.
$post_id = wp_insert_post($question_array); So, update post query didn't find the ID.
You need ID to update post meta. It didn't find any id so it didn't update meta_key. SORRY FOR MY ENGLISH.
Try using add_post_meta instead of update_post_meta.
See the Reference

Related

Why wp_update_post strip slashes?

I'm trying to update the post_content:
<?php
$something = '<a class=\"class_name\" href=\"#\">';
$my_post = array(
'ID' => 1,
'post_content' => $something,
);
wp_update_post( $my_post );
?>
Could anyone tell me why this always strips slashes from the $something?
What can I do to avoid this situation and update it just as it's in $something?
#miken32
I've looked into database and it's stripped there :-) I need this because I want to update data that's been stored by another plugin which needs specifically this format in order to work properly.
I already fixed this by replacing wp_update_post with wpdb->update. It seems that this one updates exactly as I wanted.

How to Push WordPress Post Content via Plugin Update?

We have an in-house WordPress plugin that creates content using a custom-post-type. Essentially, the content created is, for all intents and purposes, identical to WordPress 'Pages'.
The idea is that we add these custom 'pages' - via our plugin - and then deploy/update them for whomever is using the plugin. We've used our plugin to create a series of these pages, but the question is how to port this custom content with the plugin.
Initially we were thinking that since our posts have a custom post-type, we can easily identify them in the DB. In fact, we use that to remove our custom content when uninstalling the plugin.
But how do we do the inverse? Ideally we'd like to update the plugin, and with it, any custom content that we've added or modified.
Originally we were thinking of just using MySQL scripts to add this custom post content, but after a bit of research, this doesn't seem like the right way to do it.
I know WordPress has a wp_insert_post() function, but I'm just not sure of how it all fits together.
Ideally, the answer would be an overview of the process for updating our custom content. For instance, should there be a function in our plugin that, upon installation, looks for a sql file and creates new posts from it?
Thanks!
If I understand this correctly and you are trying to keep content sync'ed across multiple installations via plugin updates you will need to create a unique ID for all of your content. When you do updates programatically you are updating by the post ID but each installation will have different post IDs. You could use a post meta field to give each post a unique ID specific to your plugin. You can then query the posts based on your unique meta field.
I would code the plugin so it checks to see if there is a post with your unique ID. If it is not found then you insert a new post. If it is found then you update the post.
Let's say you have created your first piece of content and it's unique id is going to be jgohil_1. Your plugin might use something like the following to check for that unique id and then update or insert depending on if it exists.
<?php
// our meta key/value pair for our unique id
$meta_key = 'jgohil_unique_id';
$meta_value = 'jgohil_1';
// set our new content
$new_content = 'The new content here';
$new_title = 'The new title here';
// check the database to see if we have created the post already by querying for our unique id
global $wpdb;
$sql = $wpdb->prepare (
"SELECT post_id
FROM $wpdb->postmeta
WHERE meta_key = %s
AND meta_value = %s",
$meta_key,
$meta_value
);
$post_id = $wpdb->get_var( $sql );
// if we got a post id then update else insert
if ( $post_id ) {
// set up the data for updating
$data = array(
'ID' => $post_id,
'post_content' => $new_content,
'post_title' => $new_title,
);
// update the post
$updated = wp_update_post( $data );
if ( is_wp_error( $updated ) ) {
// do some error handling here
}
} else {
$data = array(
'post_title' => $new_title,
'post_content' => $new_content
'post_type' => 'your_custom_post_type'
);
$post_id = wp_insert_post( $data );
// if the insert worked give the post the unique meta id
if ( ! is_wp_error( $post_id ) && $post_id !== 0 ) {
update_post_meta( $post_id, $meta_key, $meta_value );
} else {
// do some error handling here
}
}
If you need to handle multiple pieces of content at once you would want to use a loop and change the meta value each time.

Advanced Custom Fields - front-end form, save title from another field?

I am using WordPress's Advanced Custom Fields 5 plugin to create a front-end form. I would like to save the post title as one of the fields on my form. For example, one of my form fields is 'name' so I would like the post title to be 'John Smith'.
Looking at the ACF documentation it gives example code (copied below) where pre_save_post can be hooked into achieve this. Hoewver, I have included this function and the title still fails to save.
Any ideas what I am doing wrong?
Here is the code:
function my_pre_save_post( $post_id )
{
// check if this is to be a new post
if( $post_id != 'new' )
{
return $post_id
}
// Create a new post
$post = array(
'post_status' => 'draft' ,
'post_title' => $_POST['fields']['field_123'] ,
'post_type' => 'post' ,
);
// insert the post
$post_id = wp_insert_post( $post );
// return the new ID
return $post_id;
}
add_filter('acf/pre_save_post' , 'my_pre_save_post', 10, 1 );
I am using exactly the same method and it works fine.
Just a note that field_123 in your example is not the user defined field name in the wp back end but its actually the field name assigned in the meta_key value in the wp_postmeta table of you db.

Check for duplicate Wordpress Post with Custom Meta Data on Publish

I have a site that uses a custom meta-box with the following fields using Meta-Box plugin. Code is as follows
`
$meta_boxes[] = array(
'title' => 'MLS ID',
'pages' => array('property'),
'fields' => array(
array(
'name' => 'MLS ID',
'id' => "IntegratorPropertyID",
'desc' => 'MLS: e.g. 240091025-217',
'type' => 'text',
),
array(
'name' => 'Test MLS',
'id' => "mlsTest",
'desc' => 'Test MLS for Duplicate',
'type' => 'button',
),
),
'validation' => array(
'rules' => array(
"IntegratorPropertyID" => array(
'required' => true
),
),
'messages' => array(
"IntegratorPropertyID" => array(
'required' => 'MLS is required',
),
)
)
);
Now what im looking for is to add an 'add_action( 'save_post', 'checkMLS' );' function that checks all previous CPT property for MLS number to make sure it hasn't been input before. The code I used was:
function checkMLS( $post_id ) {
$slug = 'property';
if ( $slug != $_POST['post_type'] ) {
return;
}
$mls2 = rwmb_meta('IntegratorPropertyID', 'type=text', $post_id);
$args = array( 'post_type' => 'property' );
$loop = new WP_Query( $args );
while ( $loop->have_posts() ) : $loop->the_post();
$this1 = get_the_ID();
$mls1 = rwmb_meta('IntegratorPropertyID', 'type=text', $this1);
if ( $mls2 == $mls1 ) {
$my_post = array(
'ID' => $post_id,
'IntegratorPropertyID' => 'DUPLICATE!'
);
wp_update_post($my_post);
return;
}
endwhile;
}
add_action( 'save_post', 'checkMLS' );
That code is found in the functions.php and when I try to post the screen goes white. Debugging mode does not offer any help either. :/
I'm sure I'm making some programming Major mistake somewhere. Can someone point it out? or maybe point me in the right direction? or suggest something completely different?
Thanks
Keith
OK. Firstly, your white page with no indication of why, is probably either an 'out of memory' error, or a php 'max execution time' error. This stims from one major flaw in the way the checkMLS() function works. The flaw is that you are literally cycling through ALL 'property' posts in your database. Depending on the size of your dataset, this can be a LOT, especially considering you are dealing with MLS lists.
MY RECOMMENDATION:
Figure out how the rwmb_meta() function is grabbing it's information. It is probably just a wrapper function for the get_post_meta() function, but maybe not. Assuming that it is, I propose doing the following, which I will explain the details of after as well as in the comments:
// the save_post action runs after a post has been saved/created, and has two parameters
// param 1: the id of the post
// param 2: the post object
function checkMLS($post_id, $post) {
// use the post object post_type to determine if this is a property or not.
// it will be a lot more reliable
if ($post->post_type != 'property') return;
// meta_key should be equal to the 'meta_key' field in the wp_postmeta table, for the
// id you are trying to check against. your example used IntegratorPropertyID.
// again you may want to check rwmb_meta() function to figure out if there is a
// 'prefix' or 'suffix' added to this. despite that, it is almost certainly going to
// be looking in the wp_postmeta table, so this should work nicely
$meta_key = 'IntegratorPropertyID';
// look up the current mls id for this post, which you just saved/created
$mls_id = get_post_meta($post_id, $meta_key, true);
// lookup in the actual database table for any matching row, that has the same MLS id
// that is not this post.
global $wpdb;
$q = $wpdb->prepare('select post_id from '.$wpdb->postmeta.' where meta_key = %s and meta_value = %s and post_id != %d limit 1', $meta_key, $mls_id, $post_id);
$exists = $wpdb->get_var($q);
// if it already exists, mark the value as a duplicate
if ($exists) update_post_meta($post_id, $meta_key, 'DUPLICATE!');
}
// add your check function late in the actions, at priority 10000
add_action('save_post', 'checkMLS', 10000, 2);
From the top, we create a callback with two params, because the save_post action sends two, $post_id and $post. Since save_post runs after the post has been saved, you already have an object ($post) which has all the post info in it. We can then use that $post object to determine the type of the post, which is more reliable than looking at a $_REQUEST value, mainly because $post is pulled directly from the database and passed to you.
Now, as stated before I assume that rwmb_meta() is just a kinda wrapper function for get_post_meta(). It probably adds a prefix or suffix to the $meta_key, but a little research into the rwmb_meta() function should tell you how the $meta_key is changed when passing it to the get_post_meta() function, and you can modify $meta_key from there. With the correct $meta_key, we can now get the MLS id of the property you just saved.
With that MLS id, we need to do a direct lookup in the database, to determine if there is another property with that id already. While the way in your demo function does work on small sets of data, there is no way it would work on any appreciable amount of properties. Thus the direct approach is needed. Simply we craft some special SQL to look in the wp_postmeta table for any post_id that has an MLS id that is equal to the one entered for this property, that is not this property. If we find one match that is not this property, then it is a dupe. If it is a dupe, we need to mark it as a dupe.
Notice that this solution does not do any looping at all. There is no potential for it to loop over 10000 records to find a dup id. This is streamlined. It looks up the id directly in the db, to see if there are dups.
Hopefully this is helpful to you, and hopefully others find it helpful as well. My company does WordPress work, almost exclusively. Through our years of working with WordPress we have encountered problems from the super simple to the overly complex. This same problem, in different settings, has manifested with many of our clients. This solution is simple and to the point, though highly custom. It will however, work.

How to inject a virtual post (i.e. without adding it to the database)

I use a WordPress blog and I want to show a post without adding anything to database.
What I want to say is:
I generate a post when page loads,and prepend it in homepage.
I've searched and found wp_insert_post() function but it also add to database.
How can i do this with php?
For example:
There is a post array which is generated by a query.How can I insert my post to this array before page loaded?
I want clear my idea.Here's step by step what i want.
*1)*Im generating an array like that
$arr['title] = "my title",
$arr['content'] = "my content",
*2)*WP sends a query to database and have the posts am i right? And there is an array,to show on the theme and main page?
At this point i want to add my external array(generated in step1 ) to this array(generated by WP via a query)
3) By this way i will be able to add a post without adding it to my database.
You can simply add your virtual post in one of your theme templates as raw HTML.
Alternatively, if you're feeling adventurous, you could modify the main query results and include your post inside:
add_action('loop_start', function($query){
// create the post and fill up the fields
$post = new WP_Post((object)array(
'ID' => -1,
'post_title' => 'Bla blah',
'post_content' => 'Your content',
));
// add it to the internal cache, so WP doesn't fire a database query for it
// -1 is the ID of your post
if(!wp_cache_get(-1, 'posts'))
wp_cache_set(-1, $post, 'posts');
// prepend it to the query
array_unshift($query->posts, $post);
});
The currently accepted answer causes the new post to delete the last post in the loop, because it doesn't update the post count. Here's my modified version that also includes:
Support for empty categories.
Only one place to declare the new post's ID.
Adding is_main_query() as the person who originally answered mentioned in a comment.
A setting to decide if the new post should be appended or prepended.
Hiding the post's date because otherwise you get something like 00000000. I could have used a dynamic date but it may be bad SEO to keep updating the date without updating the content.
Hiding the post's comment link because it just leads to the homepage.
A setting to control the post type. You might prefer "page" because "post" displays a general category, which I found no way to bypass. "Page" also looks more distinguished among other posts, assuming that's a good thing.
Here's the modified code:
function virtual_post($query) {
$post_type = 'page'; // default is post
if (get_class($query)=='WP')
$query = $GLOBALS['wp_query'];
if ($query->is_main_query()) {
$append = true; // or prepend
// create the post and fill up the fields
$post = new WP_Post((object)array(
'ID' => -1,
'post_title' => 'Dummy post',
'post_content' => 'This is a fake virtual post.',
'post_date' => '',
'comment_status' => 'closed'
));
if ($post_type <> 'post')
$post->post_type = $post_type;
// add it to the internal cache, so WP doesn't fire a database query for it
if(!wp_cache_get($post->ID, 'posts')) {
wp_cache_set($post->ID, $post, 'posts');
if ($query->post_count==0 || $append)
$query->posts[] = $post;
else
array_unshift($query->posts, $post);
$query->post_count++;
}
}
}
$virtual_post_settings = array('enable' => true, 'include_empty_categories' => true);
if ($virtual_post_settings['enable']) {
if ($virtual_post_settings['include_empty_categories'])
add_action('wp', 'virtual_post');
else
add_action('loop_start', 'virtual_post');
}

Categories