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.
Related
I'm trying to create a function, where all available colors (attributes/terms) gets attached to each product - on the category-page (product-listing). The code below works, however, the frontend-order is not identical with the backend-order. I really can't figure out, how I'm suppose to get the attributes sorted accordingly. Have tried changing menu_order to term_order aswell. This dosen't work either.
function ea_display_color_swatches_on_category() {
$html_swatch = '<div class="swatches-wrapper">';
$terms = wp_get_object_terms( get_the_ID(), 'pa_farve', array( 'orderby' => 'menu_order' ) );
foreach ( $terms as $term ) {
$hex_color = get_woocommerce_term_meta( $term->term_id, 'pa_farve_swatches_id_color', true );
$html_swatch .= '<a class="swatch-color-category tooltips"
title="' . $term->name . '"
style="background:' . $hex_color . '" ></a>';
}
// end color-swatches-wrapper
$html_swatch .= '</div>';
echo $html_swatch;
}
add_action( 'woocommerce_before_shop_loop_item', 'ea_display_color_swatches_on_category' );
Source
Have you tried with term_id? WordPress use to sort by creation date.
I explain my problem :
I needed to do a specific search bar for a client. Instead of giving the possibility to the user to type a search I need to put a dropdown with choices, make him select what he wants and then show every posts related to his choice.
I have one custom post type with two taxonomies for it.
My code for the select :
$pre_form = '<form role="search" method="get" class="search-form" id="searchform" action="' . esc_url(home_url('/')) . '">
<div>';
$taxonomies = 'aeronef';
$args = array('order' => 'ASC', 'hide_empty' => true);
function get_terms_dropdown_test($taxonomies, $args)
{
$myterms = get_terms($taxonomies, $args);
$output = "<select name='s'>";
foreach ($myterms as $term) {
$term_slug = $term->slug;
$term_name = $term->name;
$link = $term_slug;
$output .= "<option name='" . $link . "' value='" . $link . "'>" . $term_name . "</option>";
}
$output .= "</select>";
return $output;
}
echo $pre_form;
echo get_terms_dropdown_test($taxonomies, $args);
echo '<input type="submit" class="search-submit" value="' . esc_attr_x('Search', 'submit button') . '" />
</div>
</form>';
The problem is : It works perfectly fine when I use the taxonomy "gamme" (it shows me all the terms, i can select it, it shows me all the posts with this term and i can go on the detail of the post) but when i try with "aeronef" it shows me no terms. But I don't have an error. I checked everything, I have terms in it, WP recognize it as a taxonomy and can find terms if I put an ID to search, but with the "get_terms" function it finds the taxonomy but shows no terms.
Thx for helping !
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 .
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.)
So I'm trying to write a new plugin since I haven't been able to find one that does exactly what I want with the extensibility that I desire. The goal of the plugin is to be able to use a simple shortcode to display an image slider that automatically populates with your blog's latest posts.
I've got the basic plugin files ready and the shortcode implemented and tested. I had a snafu solved yesterday on SO but the solution highlighted a new problem. Here's the code:
function slyd( $category, $slydcount ) {
global $post;
$tmp_post = $post; // Create $tmp_post to empty $post once Slyd is done with it
$args = array(
'category' => $category,
'numberposts' => $slydcount
);
$slydposts = get_posts( $args );
foreach( $slydposts as $post ) : setup_postdata($post);
$post_title = get_the_title(); // Get the post's title
$post_content = get_the_content(); // Get the post's content - will write code to get excerpt later
$post_thumb = wp_get_attachment_image_src( get_post_thumbnail_id(), 'full' ); // Get the post's featured image's src
$post_permalink = get_permalink(); // Get the post's permalink
echo '<h2>' . $post_title . '</h2>'
. '<p>' . $post_content . '</p>'
. '<p>' . $post_thumb . '</p>';
endforeach;
$post = $tmp_post; // Empty $post once Slyd is done with it
}
// Create the shortcode
function slyd_shortcode( $atts ) {
// $atts ::= array of attributes
// examples: [slyd]
// [slyd category='slide']
// [slyd slydcount='5']
// [slyd theme='default']
/* Retrieve attributes set by the shortcode and set defaults for
unregistered attributes. */
extract( shortcode_atts( array(
'category' => 'slyd', // Which category(s) to display posts from
'slydcount' => '5', // How many Slyds to display
'theme' => 'default' // Which Slyd theme to use
), $atts ) );
return "<p>category = {$category}, count = {$slydcount}</p>"
. slyd( $category, $slydcount );
}
add_shortcode( 'slyd', 'slyd_shortcode' );
The issue is in the foreach loop in function slyd();. I was originally using a return where the echo is now to put the result on the screen. That worked to display the first post but it would, of course, escape the function. I need it to cycle through and display all of the posts.
From researching the PHP documentation I found that I could use print in place of echo or return but it's giving me the same result as echo. What's happening is the code seems to be executing twice. It places itself where it needs to be the first time, then it also echoes to the browser and places it just below the head of the page.
I suppose my question is whether there's an alternative to return, echo, or print that would solve my problem?
Thanks in advance.
Now I'm trying to get the plugin to pull in the blog's latest posts but I'm running into a bit of a snafu. When I use the_title() and the_permalink() they display outside of the code I'm trying to contain them in. Further, the_content() is displaying once with the_permalink() and the_title() and then a second time where it's supposed to.
You can see the behavior here.
return is what you want in this case. You want to return a value (i.e. html code) from the slyd function so you can use it (in this case append it) in the slyd_shortcode function. However, you need to first collect all output into an additional variable ($ret below), and then return that value:
function slyd( $category, $slydcount ) {
global $post;
$tmp_post = $post;
$args = array(
'category' => $category,
'numberposts' => $slydcount
);
$slydposts = get_posts( $args );
$ret = '';
foreach( $slydposts as $post ) {
setup_postdata($post);
$post_title = get_the_title();
$post_content = get_the_content();
$post_thumb = wp_get_attachment_image_src( get_post_thumbnail_id(), 'full' );
$post_permalink = get_permalink();
$ret .= '<h2>' . $post_title . '</h2>'
. '<p>' . $post_content . '</p>'
. '<p>' . $post_thumb . '</p>';
}
$post = $tmp_post;
return $ret;
}
As you see you should first initialize the $ret variable with an empty string, then append to it on each iteration of the foreach loop. return is used to return the whole string after the loop.