Saving custom fields in wp_postmeta - php

I'm trying to save a post meta data on the database, using custom post type. The problem is I can't store the meta_key, the only one storing is the meta-value. I have two textbox there, one for event date and one for event name.. I'm trying to store the date on the meta key and the event on the value. the problem is that it only store on the meta value, and i'm not sure on the meta-key. Also how do you store multiple meta-keys and meta-values on the same post? Any idea which part of this syntax is wrong? thanks :)
function add_calendar_metaboxes() {
add_meta_box('wpt_calendar_location', 'Event Date', 'wpt_calendar_location', 'calendar_holiday', 'normal', 'default');
}
// The Event Location Metabox
function wpt_calendar_location() {
global $post;
echo "<form method=\"POST\">";
// Noncename needed to verify where the data originated
echo '<input type="hidden" name="eventmeta_noncename" id="eventmeta_noncename" value="' .
wp_create_nonce( plugin_basename(__FILE__) ) . '" />';
// Get the location data if its already been entered
$event_name = get_post_meta($post->ID, '_event_name', true);
$event_date = get_post_meta($post->ID, '_event_date', true);
echo '<label>Event Date</label><input type="text" name="_event_date" value="' . $event_date . '" />';
echo '<label>Event Name</label><input type="text" name="_event_name" value="' . $event_name . '" />';
echo '<input type="submit" name="Submit">';
echo '</form>';
}
// Save the Metabox Data
function wpt_save_events_meta($post_id, $post) {
if ( !wp_verify_nonce( $_POST['eventmeta_noncename'], plugin_basename(__FILE__) )) {
return $post->ID;
}
if ( !current_user_can( 'edit_post', $post->ID ))
return $post->ID;
$events_meta[] = array($_POST['_event_date'] => $_POST['_event_name']);
foreach ($events_meta as $key => $value)
{
if( $post->post_type == 'revision' ) return;
$value = implode(',', (array)$value);
if(get_post_meta($post->ID, $key, FALSE))
{
update_post_meta($post->ID, $key, $value);
}
else
{
add_post_meta($post->ID, $key, $value);
}
if(!$value) delete_post_meta($post->ID, $key);
}
}
add_action('save_post', 'wpt_save_events_meta', 1, 2);

Why do you treat it like array ??
Try this simple function first
function wpt_save_events_meta() {
global $post;
update_post_meta($post->ID, "_event_date", $_POST["_event_date"]);
update_post_meta($post->ID, "_event_name", $_POST["_event_name"]);
}
If this is working for you, then you can put all your validation stuff .
( IF you still find a problem, try $post_id instead of $post->ID )
EDIT I after comment
When you do update_post_meta($post->ID, $_POST["_event_date"], $_POST["_event_name"] );
You are actually saving the _event_date as KEY and the _event_name as VALUE.
Unless you specifically know what you are doing - this is wrong
The point is to save 2 fields.
One named "_event_date" to hold the dates
One named "_event_name" to hold the names
In the case you wrote in the comments you will have something like ( I do not know the real data structure ..)
( post_id=1 ) 2014.03.04 => my_event_name
( post_id=2 ) 2014.03.05 => my_event_name2
( post_id=3 ) 2014.03.06 => my_event_name3
In the correct code you will have
( post_id=1 ) _event_date => 2014.03.04
_event_name => my_event_name
( post_id=2 ) _event_date => 2014.03.05
_event_name => my_event_name2
( post_id=3 ) _event_date => 2014.03.06
_event_name => my_event_name3
You can see that in the first code , it will be really hard to actually use the data in a search for example as in the second code - it has a structure .
You should treat each form field ( meatbox field ) as an independent set of key % value - each by it´s own.. Just try the code posted above .

Related

Hide Custom Field if Empty on WordPress

I've written two functions to show custom fields on the shop pages below each product, which can be viewed here. The ones specifically are Light Bulb Type and Coverage Area. However, these only apply to certain products. Right now, I am typing in N/A when they don't apply, but I would like to write a conditional statement to hide the entire section if the field is left empty.
Unfortunately, every time I do so, the code breaks the site because it is incorrectly written.
These are the functions I've written to show the custom fields.
add_action('woocommerce_shop_loop_item_title','show_coverage');
function show_coverage() {
echo '<span class="extra-info-head">Coverage Area:</span> ';
$coverage = get_post_meta( $post->ID );
$custom_fields = get_post_custom();
$coverage = $custom_fields['wpcf-coverage-area'];
foreach ( $coverage as $key => $value ) {
echo $value . '<br/>';
}}
add_action('woocommerce_shop_loop_item_title','show_bulbs');
function show_bulbs() {
echo '<span class="extra-info-head">Light Bulbs:</span> ';
$custom_fields = get_post_custom();
$bulbs = $custom_fields['wpcf-light-bulbs'];
foreach ( $bulbs as $key => $value ) {
echo $value;
}}
Apologies if these are poorly written and much appreciation to any suggestions and help!
*UPDATE: This was solved with a combination of the answer below and back-end options on WordPress's custom field posts.
Unfortunately, every time I do so, the code breaks the site because it is incorrectly written.
Your site is erroring out because you have an "undeclared variable."
In the callback function show_coverage(), you are using an undefined variable $post. The function doesn't know about this variable, because you haven't brought it into the function' scope.
While you could include the global $post, it's better to use the API function instead of the global variable.
$coverage = get_post_meta( get_the_ID(), 'wpcf-coverage-area' );
Let's go one step further. What if the custom metadata doesn't exist in the database? Then $coverage is not going to have anything in it. Let's protect for that by checking and then bailing out if nothing is returned.
function show_coverage() {
$coverage = get_post_meta( get_the_ID(), 'wpcf-coverage-area' );
if ( ! $coverage ) {
return;
}
echo '<span class="extra-info-head">Coverage Area:</span>';
foreach ( $coverage as $key => $value ) {
echo $value . '<br/>';
}
}
Now, let's do the same treatment to the other callback function:
function show_bulbs() {
$bulbs = get_post_meta( get_the_ID(), 'wpcf-light-bulbs' );
if ( ! $bulbs ) {
return;
}
echo '<span class="extra-info-head">Light Bulbs:</span> ';
foreach ( $bulbs as $key => $value ) {
echo $value;
}
}
Now the above functions will fetch the custom field (which is metadata). If it does not exist, you bail out. Otherwise, you start building the HTML markup and rendering it out to the browser.

manipulate part of array before saving

I've set up Custom Fields that accept a URL to a social media site, I would like to then check and see if the field contains http:// and if it does not, add it before saving to the db.
// Add Social Media Meta Boxes
function add_social_box()
{
add_meta_box( 'social-media',
__( 'Social Media'), 'social_meta_box_callback', 'page', 'advanced', 'high');
}
add_action( 'add_meta_boxes', 'add_social_box' );
function social_meta_box_callback( $post ) {
// Add a nonce field so we can check for it later.
wp_nonce_field( 'social_save', 'social_meta_box_nonce' ); ?>
<div id="meta-inner">
<?php
/*
* Use get_post_meta() to retrieve an existing value
* from the database and use the value for the form.
*/
$accounts = get_post_meta( $post->ID, 'accounts', true);
// foreach ($accounts as $account) {
// $parsed = parse_url($account);
// if (empty($parsed['scheme'])) {
// $account = 'http://' . ltrim($account, '/');
// }
// var_dump($account);
// }
?>
<div>
<label for="facebook">Facebook</label>
<input type="text" id="facebook" name="accounts[facebook]" value="<?php echo esc_attr( $accounts["facebook"] ) ?>" />
</div>
<div>
<label for="twitter">Twitter</label>
<input type="text" id="twitter" name="accounts[twitter]" value="<?php echo esc_attr( $accounts["twitter"] ) ?>" />
</div>
</div>
<?php }
When I var_dump($account)it gives me the correctly adjusted urls here.
function social_save_postdata( $post_id ) {
// verify if this is an auto save routine.
// If it is our form has not been submitted, so we dont want to do anything
// if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
// return;
// verify this came from the our screen and with proper authorization,
// because save_post can be triggered at other times
// if ( !isset( $_POST['menu_meta_box_nonce'] ) )
// return;
// if ( !wp_verify_nonce( $_POST['social_meta_box_nonce'], 'social_save' ) )
// return;
$accounts = $_POST["accounts"];
foreach ($accounts as $account) {
$parsed = parse_url($account);
if (empty($parsed['scheme'])) {
$account = 'http://' . ltrim($account, '/');
}
update_post_meta($post_id,'accounts',$accounts);
}
}
add_action( 'save_post', 'social_save_postdata' );
And using the same logic that works in the callback function above, this does not save the adjusted url in the db. My guess is that the data structure that I retrieve from $_POST["accounts"] is not the same as the serialized data I fetch from the callback function. Unfortunately I am not sure how to get a look at that data to determine the correct structure to parse the URL.
In your loop you are doing
$account = 'http://' . ltrim($account, '/');
This does not update the original value in array :)
As Hanky Panky has noted above, I forgot to update the value of the array. For completeness, here is what the functional foreach loop looks like:
$accounts = $_POST["accounts"];
foreach ($accounts as &$account) {
$parsed = parse_url($account);
if (empty($parsed['scheme'])) {
$account = 'http://' . ltrim($account, '/');
}
}
update_post_meta($post_id,'accounts',$accounts);
Please notice the subtle change of the added & in the foreach loop:
foreach ($accounts as &$account) {
Explained: http://php.net/manual/en/language.references.pass.php

Saving Post Meta in Wordpress Admin Menu w/ Foreach Loop

Here's the long and short:
I'm looking to add a global controller for post meta tags in Wordpress. I already have an established Wordpress custom admin page within our theme. I also already have added meta boxes to individual pages which store key value pairs in a more polished fashion. I have been able to call all key value pairs in a foreach loop so that they display in the administrative page. I'm having difficulty getting the input from these values on the admin panel page to properly update when the submit_button(); is clicked. I've gotten the update_post_meta function to outright erase the previous values but I have not been able to get the update_post_meta function to properly pass the $_POST value into the value at the database.
I know that the following code is not working as it's halfway through two attempts. Any help is appreciated:
$pages = get_pages();
foreach ( $pages as $page ) {
$post_id = $page->ID;
$meta = get_post_meta($post_id);
/* $value1 = get_post_meta( $post_id, 'value1', true );
$value2 = get_post_meta( $post_id, 'value2', true ); */
echo '<h3>' . $page->post_title . '</h3>';
echo '<label for="options_value1_' . $post_id . '">Value 1:</label>';
echo '<input type="text" id="options_value1_' . $post_id . '" name="options_value1" value="' . $meta['value1'][0] . '" size="25" /><br />';
echo '<label for="options_value2_' . $post_id . '">Value 2:</label>';
echo '<input type="text" id="options_value2_' . $post_id . '" name="options_value2" value="' . $meta['value2'][0] . '" size="25" /><hr />';
}
foreach ( $pages as $page ) {
update_post_meta($post_id, 'value1', $_POST('value1');
update_post_meta($post_id, 'value2', $_POST('value2');
}
Hope this helps:
$post_id is defined in the first loop, but not in the second loop.
Also you have a syntax error in the second loop. You're not closing the parenthesis of update_post_meta() and you're not using braces for $_POST. It should be $_POST[], not $_POST().
Also, the POST parameter you're looking for is options_value1 and options_value 2, because those are the names of the fields from the first loop.
Second loop should go like this:
foreach ( $pages as $page ) {
$post_id = $page->ID;
update_post_meta($post_id, 'value1', $_POST['options_value1']);
update_post_meta($post_id, 'value2', $_POST['options_value2']);
}
Hope it helps.

WordPress Meta Box - second field not saving

So I've been playing around with some custom metaboxes and following tutorials etc - I've got to the point where the top metabox field is saving correctly but the second one (width) doesn't save - is there anything obvious I'm doing wrong here? I've tried separating the second field's save in to a separate function to test but that also did not work.
add_action( 'add_meta_boxes', 'youtube_metaboxes' );
function youtube_metaboxes() {
add_meta_box('wpt_youtube', 'youtube URL', 'wpt_youtube', 'product', 'side', 'default');
}
function wpt_youtube() {
global $post;
echo '<input type="hidden" name="youtubemeta_noncename" id="youtubemeta_noncename" value="' .
wp_create_nonce( plugin_basename(__FILE__) ) . '" />';
$addyoutube = get_post_meta($post->ID, '_youtube', true);
echo '<input type="text" name="_youtube" value="' . $addyoutube . '" class="widefat" />';
$youtubeWidth = get_post_meta($post->ID, '_width', true);
echo 'Width: <br /><input type="text" name="_width" value="' . $youtubeWidth . '" class="widefat" />';
}
// Save the Metabox Data
function wpt_save_youtube_meta($post_id, $post) {
if ( !wp_verify_nonce( $_POST['youtubemeta_noncename'], plugin_basename(__FILE__) )) {
return $post->ID;
}
if ( !current_user_can( 'edit_post', $post->ID ))
return $post->ID;
$addyoutube_meta['_youtube'] = $_POST['_youtube'];
foreach ($addyoutube_meta as $key => $value) {
if( $post->post_type == 'revision' ) return;
$value = implode(',', (array)$value); // If $value is an array, make it a CSV (unlikely)
if(get_post_meta($post->ID, $key, FALSE)) {
update_post_meta($post->ID, $key, $value);
} else {
add_post_meta($post->ID, $key, $value);
}
if(!$value) delete_post_meta($post->ID, $key);
}
$addWidth_meta['_width'] = $_POST['_width'];
foreach ($addWidth_meta as $key => $value) {
if( $post->post_type == 'revision' ) return;
$value = implode(',', (array)$value); // If $value is an array, make it a CSV (unlikely)
if(get_post_meta($post->ID, $key, FALSE)) {
update_post_meta($post->ID, $key, $value);
} else {
add_post_meta($post->ID, $key, $value);
}
if(!$value) delete_post_meta($post->ID, $key);
}
}
add_action('save_post', 'wpt_save_youtube_meta', 1, 2); // save the custom fields
I had a look through this article:
http://wp.tutsplus.com/tutorials/reusable-custom-meta-boxes-part-1-intro-and-basic-fields/
Seems like a much better way of creating custom meta boxes.

Wordpress meta boxes only saving some of the values?

I´m woring on a costum meta-box for wordpress. Trouble is wordpress only seems to retain/save some of the values I enter in the fields.. I can´t really find a pattern either.. so here's the code:
<?php
function add_products_metaboxes() {
add_meta_box('sra_product_info', 'Product Information', 'sra_products_info', 'product', 'side', 'default');
}
// The Productinfo Metabox
function sra_products_info() {
//get access to the post object
global $post;
// Noncename needed to verify where the data originated
echo '<input type="hidden" name="productmeta_noncename" id="productmeta_noncename" value="' .
wp_create_nonce( plugin_basename(__FILE__) ) . '" />';
// Get the data from the field if its already been entered
$name = get_post_meta($post->ID, '_name', true);
$price = get_post_meta($post->ID, '_price', true);
$includes = get_post_meta($post->ID, '_includes', true);
$supports = get_post_meta($post->ID, '_supports', true);
$version = get_post_meta($post->ID, '_version' , true);
$extrainfo = get_post_meta($post->ID, '_extrainfo', true);
// Echo out the form
echo '<form>';
echo '<label for="_name">Name</label>' . '<input type="text" name="_name" value="' . $name . '"/>';
echo '<label for="_price">Price</label>' . '<input type="text" name="_price" value="' . $price . '"/>';
echo '<label for="_includes">Includes</label> <textarea name="_includes" rows="4" cols="10">' . $includes . '</textarea>';
echo '<label for="_supports">Supports</label> <input type="text" name="_supports" value="' . $supports . '"/>';
echo '<label for="_version">Version</label>' . '<input type="text" name="_version" value="' . $version . '"/>';
echo '<label for="_extrainfo">Extras</label> <textarea name="_extrainfo" rows="4" cols="10">' . $extrainfo . '</textarea>';
echo '</form>';
}
// Save the Metabox Data
function sra_save_product_meta($post_id, $post) {
// verify this came from the our screen and with proper authorization,
// because save_post can be triggered at other times
if ( !wp_verify_nonce( $_POST['productmeta_noncename'], plugin_basename(__FILE__) )) {
return $post->ID;
}
// Is the user allowed to edit the post or page?
if ( !current_user_can( 'edit_post', $post->ID ))
return $post->ID;
// OK, we're authenticated: we need to find and save the data
// check if the field exists in the posts array - if it does, then put cintent in $product_meta.
// this code needs to be refactored!
if (isset($_POST['_name'])) {
$product_meta['_name'] = $_POST['_name'];
}
if (isset($_POST['_price'])) {
$product_meta['_price'] = $_POST['_price'];
}
if (isset($_POST['_includes'])) {
$product_meta['_includes'] = $_POST['_includes'];
}
if (isset($_POST['_supports'])) {
$product_meta['_supports'] = $_POST['_supports'];
}
if (isset($_POST['_version'])) {
$product_meta['_version'] = $_POST['_version'];
}
if (isset($_POST['_extrainfo'])) {
$product_meta['_extrainfo'] = $_POST['_extrainfo'];
}
// Add values of $prpduct_meta as custom fields
foreach ($product_meta as $key => $value) { // Cycle through the $product_meta array!
if( $post->post_type == 'revision' ) return; // Don't store custom data twice
$value = implode(',', (array)$value); // If $value is an array, make it a CSL (unlikely)
if(get_post_meta($post->ID, $key, FALSE)) { // If the custom field already has a value
update_post_meta($post->ID, $key, $value);
} else { // If the custom field doesn't have a value
add_post_meta($post->ID, $key, $value);
}
if(!$value) delete_post_meta($post->ID, $key); // Delete if blank
}
}
add_action('save_post', 'sra_save_product_meta', 1, 2); // save the custom fields
Do you see any obvious mistakes? I think I've become a bit blind to my own mistakes in this code..
In general, I would advise to use prefixes for your field names. Values like _name have too much chances getting in conflict with other values with the same name elsewhere. Use things like _product_name, etc. Can you try that? If your code works with pages, it should have an impact.
And why not adding the 4th parameter with 'true' to add_post_meta() and previous value for update_post_meta()? See WordPress codex about these functions: http://codex.wordpress.org/Function_Reference/add_post_meta. So it would go:
if(get_post_meta($post->ID, $key, FALSE)) { // If the custom field already has a value
update_post_meta($post->ID, $key, $value, /***OLDVALUE***/ ); // See http://codex.wordpress.org/Function_Reference/update_post_meta for old value
} else { // If the custom field doesn't have a value
add_post_meta($post->ID, $key, $value, true);
}
I think it is clear you have a conflict with a metakey with the same name. Not in pages, but in posts. So try to use this 4th parameter to ensure you are referencing a unique key (and my advice, still, use clear prefixes to differenciate from anything else, be it plugins, core, etc.)

Categories