Wordpress search database values and return - wordpress

i'm have been searching for a code that will do some thing like this in WordPress and but it CANT call on woocommerce
nothing seems to work
if
get_post_meta( get_the_ID(), '_regular_price' is greater then 1)
do this
else
do this code

It depends on the place where you are using this function.
Imagine you are trying to edit a product page. In your woocommerce templates folder, you find for example: price.php
Usually there is one global variable available already, and if it's not available you can set it with global $product. With $product->get_id() you can get the product id then.
With the global variable the sale price is then available like this $price = $product->get_sale_price();
In order to make the if statement, you need the data so then the next step. Maybe your price is empty for some reason, which returns undefined, making it difficult to do the if statement
if (empty($price))
$price = 0;
if($price > 1))
// do your thing

$my_post_meta = get_post_meta( get_the_ID(), 'sale_price', true);
if ( ! empty ( $my_post_meta ) ) {
do code here
} else
do other code
this works for me

Related

How set value of existing product attribute in Wordpress?

My every product in WooCommerce has several attributes. One of them is named my-availability and I need to change its value dynamically depending on stock change and some condition logic. So when the amount of pieces on stock is changed (usually decreased by order), the value of my-availability attribute will change. It should not add any new attributes, just change the value of the existing one. I do not use product variations at all.
I am total beginner and trying to build this piece of code for few days using a lot of googling. Now I have something like this:
function changeatt( $order )
{
$items = $order->get_items();
foreach( $items as $item ) {
$value2 = get_field( "naceste", $item['product_id']); //need to get value of custom field "naceste"
$value = get_post_meta( $item['product_id'], '_stock', true ); //need to get how many pcs is on stock
if ($value == 0 && $value2 > 0)
{$avl = 'Coming soon';}
if ($value == 0 && $value2 == 0)
{ $avl = 'Not in stock';}
if ($value > 0)
{ $avl = 'In stock';}
// update_post_meta( $item['product_id'], 'my-availability', $avl );
wp_set_object_terms( $item['product_id'], $avl, 'pa_my-availability', false);
}
}
add_action( 'woocommerce_reduce_order_stock', changeatt );
This code actually creates new custom field my-availability with the correct value, but I need to save it to existing attribute named my-availability instead. What am I missing?
I found it! update_post_meta did not work for changing attributes, do not know why. wp_set_object_terms must be used instead and pa_ must be added to the name of the attribute. I have edited the code in the question to the working version. The previous not-working line has been removed by // for other beginners, who will be solving the same situation to learn from this one. It took me few days to solve this.
Now I am pretty curious, how to find out, which types of variables can be changed using update_post_meta and which types using wp_set_object_terms.

Custom Taxonomies and how to stay in them when the posts have multiple terms selected?

Wondering if anyone can help me think this one out?
Whilst in lock-down, I've been putting together a simple site to organise my collection of Retro Gaming Adverts covering systems from the Atari 2600 up to the N64. I've still got a few 1000 to add to the site (takes time) but i've come across an issue I'm not sure how to implement a fix for.
You can browse the adverts by system through their single post pages but if an advert covers multiple systems it messes up the previous and next posts link and will drop you into another system.
For Example: If you're using the next and previous post links to go through the "mega drive / genesis" section once you get to " Battletoads and Double Dragon " when you press the next post arrow this time you're suddenly going through adverts tagged as NES, due to the fact thats the first term associated with it.
See : https://www.retrogameads.com/system/mega-drive/ and click on the first advert, then keep pressing the next arrow and you'll see what i mean.
I guess I could post each advert multiple times for each system but I don't like the idea of that.
Anyone got any suggestions on how I could work out what Term the user was browsing and keep them in that one?
Bare in mind this site is a work in progress so the design is just something basic till i work out the best way to organise things.
Let me know your thoughts.
Update:
Current method for getting prev next posts...
<?php
$terms = get_the_terms( $post->ID, 'system' );
$i = 0;
$systems = array();
foreach ( $terms as $term ) {
$systems[$i] = $term->slug;
$i++;
}
$postlist_args = array(
'posts_per_page' => -1,
'post_type' => 'portfolio',
'system' => $systems[0],
'order' => 'ASC',
'orderby' => 'title'
);
$postlist = get_posts( $postlist_args );
$ids = array();
foreach ($postlist as $thepost) {
$ids[] = $thepost->ID;
}
$thisindex = array_search($post->ID, $ids);
$previd = $ids[$thisindex-1];
$nextid = $ids[$thisindex+1];
?>
<div class="prev_next">
<?php
if ( !empty($previd) ) {
echo '<div class="older"><a rel="prev" href="' . get_permalink($previd). '">‹</a></div>';
}
if ( !empty($nextid) ) {
echo '<div class="newer"><a rel="next" href="' . get_permalink($nextid). '">›</a></div>';
}
?>
When you click on an advert, you're essentially visiting the single page for that advert. At that moment, WP does not know/remember that the user only wants to see adverts from the system you clicked.
How are you rendering the previous/next links right now?
One possible solution could be to add a parameter to the URL and then take this into account in the PHP code when rendering the previous/next links. (/portfolio/advert-name/?system=mega-drive for example)
Edit: Of course the URL could also be made prettier... if you want to put in some extra work, you could register a permalink of the form /portfolio/mega-drive/advert-name/ for example. But this would require a bit more work.
Would that work? I think it would be the best solution considering the alternatives.
Update: For the actual implementation, the get_next_post_where and get_previous_post_where filters might prove to be very useful. You could make it so that it takes the system parameter into account for the previous/next links.
Another option: You could also set up a PHP session and remember the current system that way, but then you will require a PHP session, which is not a good thing, and it will also prevent you from using full page caching (performance optimization).
Yet another option would be to remember the current system client-side through a cookie. But in that case you have caching issues again unless you load the previous/next links through AJAX.
After reading the update on your question, I have the following notes:
system is not a valid argument and will be ignored on the get_posts() call.
the method you use to get the previous and next posts is very inefficient, because you query the whole database, and then you save everything in memory, and then you comb through the whole result set in memory, using a lot of unnecessary ram and CPU power
So how can we improve this?
Simple: Use the get_previous_post and get_next_post functions on the $post. It accepts three arguments. Here is the example for get_next_post (but get_previous_post is basically the same):
get_next_post( bool $in_same_term = false, array|string $excluded_terms = '', string $taxonomy = 'category' )
Now if you set $in_same_term to true then the next post will be of a post that shares at least one taxonomy term (system in our case).
You also have to set $taxonomy to system because that is the custom taxonomy.
And the other parameter is $excluded_terms. Too bad there is no $included_terms otherwise we could just put the system we want in there. But we can do it another way... We can filter out the current system (in the system GET parameter in our URL) and keep all other systems as systems to exclude.
So let's build what we need now.
global $post;
// What system did we come from?
$system = $_GET['system'] ?? null; // Set to null if nothing was specified (uses PHP's null coalescing operator available since PHP 7
// Exclude nothing by default
$excluded_term_ids = [];
// If we came here by clicking on a system, then exclude all other systems so the previous/next links will be of the same system only
if ($system) {
// Retrieve system terms for this post
$terms = get_the_terms( $post, 'system' );
// Filter the list of terms to remove the system we came from
// This way we can create a list of terms to exclude
$excluded_terms = array_filter( $terms, function ( $term ) use ( $system ) {
return $term->slug != $system;
} );
// The get_previous_post and get_next_post functions expect $excluded_terms to be an array of term IDs, so we must map the WP_Term objects into IDs
$excluded_term_ids = array_map( function ( $term ) {
return $term->term_id;
}, $excluded_terms );
}
// Retrieve previous and next post
$previous_post = $post->get_previous_post( true, $excluded_term_ids, 'system' );
$previous_post = $post->get_next_post( true, $excluded_term_ids, 'system' );
// Echo out the page links
// And don't forget to re-add the ?system= parameter to the URL
$url_suffix = $system ? ('?system=' . $system) : '';
if ( $previous_post ) {
echo '<div class="older"><a rel="prev" href="' . get_permalink($previous_post) . $url_suffix . '">‹</a></div>';
}
if ( $next_post ) {
echo '<div class="newer"><a rel="next" href="' . get_permalink($next_post) . $url_suffix . '">›</a></div>';
}
NOTE: Untested code.. So there might be a small bug somewhere.. Let me know if you encounter an issue with this code..
Important: On the page of a system, you must now also add '?system=current-system' to the URLs that you render.
Probably something like: echo get_permalink($advert) . '?system=' . $post->post_name (could be different depending on how your code is on that screen..)

WP Rest API get post by slug with special characters (ex: !&')

I have posts with slugs with special characters. One of them is the following:
http://localhost/wp-json/wp/v2/posts?slug=my-post!
Unfortunately, WP REST API not showing the content since it has (!) within the slug.
Is there any solution you guys would recommend?
I have found the solution (at least for my case), not sure if it'll work for you but may indicate you the way to go. We need to tap into the function used to sanitize the slugs, as I said in my comment, by default is wp_parse_slug_list. Looking at the code the function that actually sanitizes the slug is sanitize_title.
Looking at the source code, wp_parse_slug_list calls sanitize_title with only one argument, which means that the context used is save. This means that, for posts that were already saved without being sanitized by this function, the slug won't match and the post will be inaccessible through the API. The solution is to change the sanitizing function slightly by adding a filter:
add_filter('rest_post_collection_params', function($query_params) {
$query_params['slug']['sanitize_callback'] = 'sanitize_rest_api_slug';
return $query_params;
}, 20, 1);
function sanitize_rest_api_slug( $list ) {
if ( ! is_array( $list ) ) {
$list = preg_split( '/[\s,]+/', $list );
}
foreach ( $list as $key => $value ) {
$list[ $key ] = sanitize_title( $value, '', 'query' );
}
return array_unique( $list );
}
The filter is actually being applied on the function get_collection_params() on the class-wp-rest-posts-controller class, but if you look at the source code, the filter has a variable depending on the post_type, so if you have another special kind of posts defined (besides post) you need to add/change a filter for that kind as well.
I hope this helps somebody else like me, even if it's too late for your issue.

What's the difference between global var post and get_post?

I use the_posts filter to add an object to each queried post. When access the added object, I get different result by using $post or get_post.
This is the code to attach the object to posts:
add_filter( 'the_posts', 'populate_posts_obj', 10,2 );
function populate_posts_obj( $posts, $query ){
if ( !count( $posts ) || !isset($query->query['post_type']) )
return $posts;
if( in_array( $query->query['post_type'], get_valid_grade_types())){
foreach ( $posts as $post ) {
if ( $obj = new Gradebook( $post->ID ) )
$post->gradebook = $obj;
}
}
return $posts;
}
Then, access the obj via $post, sometimes get the obj, sometimes not (even when it's the same post):
function get_the_gradebook(){
global $post;
return isset($post->gradebook) ? $post->gradebook : null;
}
Access the obj via get_post(), always get the obj:
function get_the_gradebook(){
global $post;
$p = get_post($post->ID);
return isset($p->gradebook) ? $p->gradebook : null;
}
I can just use the get_post() version, but it would be useful if I know why the difference.
Additional info:
If you ask the reason I attach an obj to each post, I think WordPress may take care of the caching process at the first place. Then, other caching plugins can work on my obj as if working on standard WP posts.
Lets explain you with a little bit pseudo code. I am trying to be broad with my approach so that my answer is relevant to StackOverflow however I still don't know how many down votes I may be receiving for this.
The simple difference is $post is a variable and get_post() is a method that means you can expect a different output from get_post() due to several dependencies however $post will only change when you explicitly do that.
Lets assume something like this
function get_post() {
return rand(0, 5);
}
$post = get_post(); /* lets assume random
value that was generated
this time was "2" */
Now each time you call get_post() its value be keep changing however the value of $post is always 2.
Coming back to the context of wordpress, $post is set using get_post() within the Loop and corresponds to the object referring to default post ID for current URL where as get_post() will take post ID as an input and return the post object.
$post is what WordPress considers to be the current "post" (post/page/custom post type) and can quite often end up giving you data you didn't quite expect. This is especially true if you perform WP_Query's in your template or have a template that uses data from several "posts".
By using get_post() with the ID you want the data from, you can be assured that you are getting the data you really want.

wordpress plugin creation get_post_meta

I am building my first plugin, and I am using as a reference the following link.
http://www.sitepoint.com/create-a-voting-plugin-for-wordpress/
and I am trying to underestand the following part of the code:
function voteme_addvote()
{
$results = '';
global $wpdb;
$post_ID = $_POST['postid'];
$votemecount = get_post_meta($post_ID, '_votemecount', true) != '' ? get_post_meta($post_ID, '_votemecount', true) : '0';
$votemecountNew = $votemecount + 1;
update_post_meta($post_ID, '_votemecount', $votemecountNew);
$results.='<div class="votescore" >'.$votemecountNew.'</div>';
// Return the String
die($results);
}
I run the code and it works, but I just dont understand the following:
What is "get_post_meta" doing?
Does it create a custom meta field, the same as add_post_meta?, if it doesnt why there is not an add_post_meta?
I checked the DB, and it looks like it is creating a custom meta field... so in that order what is the difference between get_post_meta and add_post_meta?
Thanks very much for helping me understand this.
The first time your code runs, get_post_meta returns '' so $votemecount is set to 0. The following update_post_meta creates the new meta field as documented below. Values that start with _ are not displayed (are hidden meta fields).
The function, update_post_meta(), updates the value of an existing meta key (custom field) for the specified post.
This may be used in place of add_post_meta() function. The first thing this function will do is make sure that $meta_key already exists on $post_id. If it does not, add_post_meta($post_id, $meta_key, $meta_value) is called instead and its result is returned.

Resources