How would the code below (which is in a foreach loop) sometimes return something and sometimes return nothing when passed the same variables:
$term_id = 76;
$term_parent = 75;
if($term_id != 114 && $term_id != 115 && $term_parent != 83){
$term_link_content = 'something';
} else {
$term_link_content = 'nothing';
}
-- Based on responses so far, the full code is below. I'm basically after the first term that isn't equal to any of the ids listed. And I've checked the loop by outputting the $term_id and $term_parent for different posts which have the same terms so I can see that the if statement is being passed the same values but sometimes the $term_link_content variable has content and other times it's empty.
$posts = get_posts('post_type=products&product_categories=Best Sellers');
foreach($posts as $post){
$post_ID = $post->ID;
$terms = get_the_terms( $post_ID, "product_categories" );
$i = 0;
foreach($terms as $term){
$term_id = $term->term_id;
$term_parent = $term->parent;
$term_name = $term->name;
$term_slug = $term->slug;
if($term_id != 114 && $term_id != 115 && $term_parent != 83){
// only get the first
if(++$i > 1) break;
$term_text = $term_name;
$term_link = $url.'/shop/'.$term_slug;
$term_link_content = '<span class="term_text"><a class="'.$card_colour.'" href="'.$term_link.'">'.$term_text.'</a></span>';
} else { $term_link_content = ''; }
}
}
I presume you define $term_id and / or $term_parent before entering your foreach loop, and perform the rest of the code in the body of the loop.
However, when you do something like this:
foreach (getTerms() as $term) {
// perform an if-statement
}
This might change the variables you defined, eg.:
function getTerms() {
global $term_id, $term_parent;
// probably some database-connection that changes $term_id and $term_parent.
}
Correct me if I'm wrong, but I'm pretty sure Wordpress's functions work this way, so you shouldn't trust generic global variables when you're using Wordpress, when you're developing plugins or when you're using functional-oriented (instead of object-oriented) framework.
Related
I'm trying to replace the product title on the WooCommerce product catalog by some product information, based on product attributes.
I've been able to create a working snippet for one attribute, with this code:
if(!function_exists('replace_title_custom_attribute')):
function replace_title_custom_attribute( $title, $id ){
$taxonomy = 'pa_model-number';
$terms = get_the_terms($id, $taxonomy);
if( ! is_wp_error($terms) && ! empty($terms) && ($term = $terms[0]) ){
return $term->name;
}
return $title;
}
add_action('woocommerce_before_shop_loop_item', function(){
add_filter('the_title', 'replace_title_custom_attribute', 10, 2);
}, 10);
add_action('woocommerce_after_shop_loop_item', function(){
remove_filter('the_title', 'replace_title_custom_attribute', 10);
}, 10);
endif;
But now, I want to show extra information based on another pa_another_attribute. I think I'll need something like an array here, but can't seem to figure out how to do this.
Such that in the end the information looks like this in the front-end
"pa_modelnumber" - "pa_another_attribute"
Hope you can help me in the right direction here, thanks!
I revised your code. Try the below code.
if(!function_exists('replace_title_custom_attribute')):
function replace_title_custom_attribute( $title, $id ){
$taxonomy = 'pa_color'; // replace with your attribute name
$terms = get_the_terms($id, $taxonomy);
if( ! is_wp_error($terms) && ! empty($terms) && ($term = $terms[0]) ){
$title1 = $term->name;
}
$taxonomy = 'pa_size'; // replace with your attribute name
$terms = get_the_terms($id, $taxonomy);
if( ! is_wp_error($terms) && ! empty($terms) && ($term = $terms[0]) ){
$title2 = $term->name;
}
if( $title1 != '' && $title2 != '' ){
$title = $title1.' - '.$title2;
}elseif ( $title1 != '' ) {
$title = $title1;
}elseif ( $title2 != '' ) {
$title = $title2;
}else{
$title = $title;
}
return $title;
}
add_action('woocommerce_before_shop_loop_item', function(){
add_filter('the_title', 'replace_title_custom_attribute', 10, 2);
}, 10);
add_action('woocommerce_after_shop_loop_item', function(){
remove_filter('the_title', 'replace_title_custom_attribute', 10);
}, 10);
endif;
Tested and works.
I have an array $categories and I would like to check if either 'computers' or 'laptops' are in the array.
I can do
$terms = wp_get_post_terms($post_id, 'product_cat');
foreach ($terms as $term) {
$categories[] = $term->slug;
}
if (in_array( 'computers', $categories)) {
//run a lot of code
}
if (in_array('laptops', $categories)) {
//run a lot of code
}
but is there a way to combine with an OR so I don't have to write out the code twice?
something like
if ((in_array( 'computers', $categories)) OR (in_array('computers-he', $categories))) {
//run a lot of code
}
I tried it but it doesn't work I get.
PHP Warning: in_array() expects parameter 2 to be array, null
1. Define
$categories = array();
before-
$terms = wp_get_post_terms( $post_id, 'product_cat' );
2. Use || like this:-
if(in_array('computers',$categories) || in_array('laptops',$categories)) {
//run a lot of code
}
Now full code will be:-
$categories= array();
$terms = wp_get_post_terms( $post_id, 'product_cat' );
foreach($terms as $term) {
$categories[] = $term->slug;
}
if(in_array('computers',$categories) || in_array('laptops',$categories)) {
//run a lot of code
}
a different approach:
$terms = wp_get_post_terms($post_id, 'product_cat');
foreach ($terms as $term)
{
if(in_array($term->slug, ['computers', 'laptops']))
{
//run a lot of code
break; //run the code once
}
}
I usually do this:
if (array_intersect($categories, ['computers', 'laptops'])) {
//run a lot of code
}
If one or both terms are in $categories, it returns the array with those terms, if none are in it, it returns an empty array which is falsy.
From you question, I guess you need to run code if there is at least one term of particular category. In such case you can use array_reduce and take advantage of short-circuit evaluation:
$criteria = [
'computers' => true,
'laptops' => true
];
$test = function ($carry, $term) use ($criteria) {
return $carry || isset($criteria[$term->slug]);
};
if (array_reduce($terms, $test, false)) {
echo 'Run a lot of code.';
}
Here is working demo.
I want to show on the site the parent of the selected taxonomy. For that I have the above code but the problem with this is that it is showing all the selected taxonomy in a list with now structure.
global $post;
$features = get_the_terms( $post->ID, 'property-feature' );
if ( !empty( $features ) && is_array( $features ) && !is_wp_error( $features ) ) {
?>
<div class="property-features">
<?php
global $inspiry_options;
$property_features_title = $inspiry_options[ 'inspiry_property_features_title' ];
if( !empty( $property_features_title ) ) {
?><h4 class="fancy-title"><?php echo esc_html( $property_features_title ); ?></h4><?php
}
?>
<ul class="property-features-list clearfix">
<?php
foreach( $parent_term as $single_feature ) {
echo '<li>'. $single_feature->name . '</li>';
}
?>
</ul>
</div>
<?php
}
Example:
Parent: option 1, option 2
Parent 2 : option 3, option 4
If I select option 2 and option 3 I want to see
Parent: option 2
Parent 2 : option 3
Updare 2
global $post;
$features = get_the_terms( $post->ID, 'property-feature' );
$featuresss = get_the_terms( $post->ID, 'property-feature' );
// determine the topmost parent of a term
function get_term_top_most_parent($term_id, $taxonomy){
// start from the current term
$parent = get_term_by( 'id', $term_id, $taxonomy);
// climb up the hierarchy until we reach a term with parent = '0'
while ($parent->parent != '0'){
$term_id = $parent->parent;
$parent = get_term_by( 'id', $term_id, $taxonomy);
}
return $parent;
}
// so once you have this function you can just loop over the results returned by wp_get_object_terms
function hey_top_parents($taxonomy, $results = 1) {
// get terms for current post
$terms = wp_get_object_terms( get_the_ID(), $taxonomy );
$y = get_the_terms($terms->term_id, $taxonomy);
// set vars
$top_parent_terms = array();
foreach ( $terms as $term ) {
//get top level parent
$top_parent = get_term_top_most_parent( $term->term_id, $taxonomy );
//check if you have it in your array to only add it once
if ( !in_array( $top_parent, $top_parent_terms ) ) {
$top_parent_terms[] = $top_parent;
}
}
// build output (the HTML is up to you)
foreach( $top_parent_terms as $single_feature ) {
echo '<li>'. $single_feature->name . '</li>';
foreach( $terms as $single ) {
echo '<ul><li>'. $single->name . '</li></ul>';
}
}
//return $top_parent_terms;
}
I managed to display the top parent for the selected taxonomy but now the problem is that I need now to display in the top parent anly the selected taxonomy from that parent
global $post;
$taxonomy = "property-feature";
// determine the topmost parent of a term
function get_term_top_most_parent($term_id, $taxonomy){
// start from the current term
$parent = get_term_by( 'id', $term_id, $taxonomy);
// climb up the hierarchy until we reach a term with parent = '0'
while ($parent->parent != '0'){
$term_id = $parent->parent;
$parent = get_term_by( 'id', $term_id, $taxonomy);
}
return $parent;
}
// so once you have this function you can just loop over the results returned by wp_get_object_terms
function hey_top_parents($taxonomy, $results = 1) {
// get terms for current post
$terms = wp_get_object_terms( get_the_ID(), $taxonomy );
// set vars
$top_parent_terms = array();
foreach ( $terms as $term ) {
//get top level parent
$top_parent = get_term_top_most_parent( $term->term_id, $taxonomy );
//check if you have it in your array to only add it once
if ( !in_array( $top_parent, $top_parent_terms ) ) {
$top_parent_terms[] = $top_parent;
}
}
// build output (the HTML is up to you)
foreach( $top_parent_terms as $single_feature )
{
echo '<li>'. $single_feature->name . '</li>';
foreach( $terms as $single ) {
if( $single_feature->term_id == $single->parent ) {
echo '<ul><li>'. $single->name . '</li></ul>';
}
}
}
//return $top_parent_terms;
}
CHANGES:
1) Moved taxonomy name to variable (used in echo's).
$taxonomy = "property-feature";
2) Added if condition to the code responsible for displaying sub terms.
if( $single_feature->term_id == $single->parent ) {
echo '<ul><li>'. $single->name . '</li></ul>';
}
REMOVED (not used lines of codes):
1)
$features = get_the_terms( $post->ID, 'property-feature' );
$featuresss = get_the_terms( $post->ID, 'property-feature' );
2)
$y = get_the_terms($terms->term_id, $taxonomy);
CONSIDER:
1) Removing $results variable from:
function hey_top_parents($taxonomy, $results = 1) {
it is not used anywhere or maybe should be to determine if results should be returned or displayed by the function.
I'm working on something on wordpress + woocommerce.
I've inputed some 'filter' attributes value for some products.
So if the value of the attribute for this product includes a "Wood Grains" value, i want to echo an Woodgrains.jpg on the front end.
Therefore if the value = Texture, i want to echo Texture.jpg icon.
the code below is what i've mustered so far, but this only echoes out all the values tagged to a product, i can't figure out what to change to get the 'if' statement in it.
$terms = get_the_terms( $product->id, 'pa_filter');
foreach ( $terms as $term ) {
echo $term->name;
}
here's a screenshot of what the code above does on the front end:
http://edleuro.com/new/wp-content/themes/mystile/img/1.png
If this returns an array of terms for the said product:
$terms = get_the_terms( $product->id, 'pa_filter');
You can check if the returned result array has what you are looking for by doing this:
if (in_array("Wood Grains", $terms))
{
// has it
}
else
{
// doesn't have it
}
Update
Based in your reply to my answer, I have came up with the following:
Create a helper function like this:
function termExists($myTerm, $terms)
{
if (is_array($terms)) {
foreach ($terms as $id => $data) {
if ($data->name == $myTerm)
return true;
}
}
return false;
}
Then you use it like this:
if (termExists('Wood Grains', get_the_terms($product->id, 'pa_filter')))
{
// term exists
}
else
{
// does not exists
}
i found a better way to resolve my problem. i had this in my content-product.php woocommerce template.
<?php
$terms = get_the_terms( $product->id, 'pa_filter');
foreach($terms as $term){
if($term->name == 'Wood Grains'){
echo '<img src="icon_woodgrains.gif">';
}
}
?>
do take note that the term name is case sensitive.
foreach prints Warning: invalid argument supplied for foreach()…
This works for me "on a purely":
if ( is_product() && has_term( 'Wood Grains', 'pa_filter' )) {
echo '<img src="Texture.jpg">';
}
Good morning, I'm trying to change the header depending on the category of the single product. i am using Wordpress & WooCommerce
My product categories look like this
- the-lawn-store
- - turf
- - grass-seed
- - wildflower-turf
- the-oak-store
- - railway-sleepers
- - pergolas
Basically when viewing an item which falls under the parent category of the-lawn-store I need the header to be <?php get_header('lawn'); ?> and when the parent category is the-oak-store I need the header to be <?php get_header('oak'); ?>, the difference between headers is the styling of the over all page! what is the best way to go about this?
Well, what you need is the category parent. In order to do that, first of all you can get the parent ID with this:
global $wp_query;
$cat_obj = $wp_query->get_queried_object();
if($cat_obj) {
//print_r($cat_obj);
$category_ID = $cat_obj->term_id;
$category_parent = $cat_obj->parent;
$category_taxonomy = $cat_obj->taxonomy;
$category_parent_term = get_term_by( 'id', absint( $category_ID ), $category_taxonomy );
$category_parent_slug = $category_parent_term->slug;
get_header( $category_parent_slug );
}else{
get_header();
}
Uncomment the print_r to see the rest of available vars. Tested on my local woo and works.
You can't filter the get_header() function so you will have to override WooCommerce's single-product.php template. From there you can modify the beginning of the file:
get_header( 'shop' ); ?>
I created the following function to get the top-level product category for any product:
function kia_get_the_top_level_product_category( $post_id = null ){
$product_cat_parent = null;
if( ! $post_id ){
global $post;
$post_id = $post->ID;
}
// get the product's categories
$product_categories = get_the_terms( $product_id, 'product_cat' );
if( is_array( $product_categories ) ) {
// gets complicated if multiple categories, so limit to one
// on the backend you can restrict to a single category with my Radio Buttons for Taxonomies plugin
$product_cat = array_shift( $product_categories);
$product_cat_id = $product_cat->term_id;
while ($product_cat_id) {
$cat = get_term($product_cat_id, 'product_cat'); // get the object for the product_cat_id
$product_cat_id = $cat->parent; // assign parent ID (if exists) to $product_cat_id
// the while loop will continue whilst there is a $product_cat_id
// when there is no longer a parent $product_cat_id will be NULL so we can assign our $product_cat_parent
$product_cat_parent = $cat->slug;
}
}
return $product_cat_parent;
}
Then in your theme's single-product.php you could do:
$parent = kia_get_the_top_level_product_category();
if( $parent == 'oak' ){
get_header('oak');
} elseif( $parent == 'lawn' ){
get_header('lawn');
} else {
get_header('shop');
}
If you don't have a specific header-shop.php then you could technically also do:
$parent = kia_get_the_top_level_product_category();
get_header( $parent );
Overriding this template might put you at risk when WooCommerce upgrades. As an alternative I would suggest filtering the body class.
function wpa_22066003_body_class($c){
if( function_exists('is_product') && is_product() && $parent = kia_get_the_top_level_product_category() ){
$c[] = $parent . '-product-category';
}
return $c;
}
add_filter( 'body_class', 'wpa_22066003_body_class' );