Displaying and getting only the child categories - php

I have a section on my wordpress website that currently displays the child and parent categories of a listing. I would like for only the child categories to be displayed. I wasn't able to figure out the solution on my own, your help is appreciated.
Here is the current code I'm using for this (which also displays parent categories):
<?php
//NEW
$permalink = get_permalink( $id );
//NEW
$seo = get_the_title()." : ";
$Category_links = ' Found in the ';
$term_list_category = wp_get_post_terms(get_the_ID(), 'listings_categories', array("fields" => "ids"));
//THIS CODE REMOVES PARENTS FROM BEING DISPLAYED IN THE LISTING CATEGORIES
foreach ($term_list_category as $k=>$term) {
$children = get_term_children( $term, 'listings_categories');
if ($children)
unset($term_list_category[$k]);
}
$i = 0;
$count = count($term_list_category);
if ( $count > 0 ){
foreach ( $term_list_category as $term_category ) {
$thisCat = get_term_by( 'id', $term_category, 'listings_categories');
//NEW
$url = '<a id="'.$term_category.'" slug="'.$thisCat->{'slug'}.'" class="listing-links-cat" href="#" title="'.$thisCat->{'name'}.'" >'.$thisCat->{'name'}.'</a>';
$i ++;
$seo .= " " . $thisCat->{'name'} . "";
$Category_links .= " " . $url . "";
if($count-1 == $i){
$Category_links .= " and "; $seo .= ", ";
}elseif($count > 1 && $count !== $i){
$Category_links .= ", "; $seo .= ", ";
}
}
$Category_links .= " Categories";
?>
<? echo $Category_links; ?>
But I feel that the overall code can be improved for performance, so it doesn't search the database as much?

Your code is quite ineffecient and also have unnecessary parts to it. Your additional part makes your code even more ineffecient and causes you to hit the db hard.
FLAWS
You get plus 1 for only getting the term id's from the post terms, but unfortunately in this specific case, this tampers your code and this is the starting point of your ineffeciency as you then need to use get_term_by() on every iteration of your foreach loop. This means extra db calls on every iteration for something that should have already been there
The use of get_term_children() adds to the amount of db calls made on every iteration of your foreach loop. Again, you are making unnecessary db calls for something that should have been there in the first place
It is totally unnecessary to count the amount of terms returned by wp_get_post_terms. This adds extra ineffeciency to your code. wp_get_post_terms returns an empty array if no terms exists or a WP_Error object if the taxonomy does not exist. Keep this in mind for later on
SPEEDING IT UP AND STREAMLINING THE CODE
Lets look at what we can do to make your code more effecient
Remove the fields parameter from wp_get_post_terms. As we need more than just the ids of the terms, we need to return the complete term object. You might think that this is ineffecient, but this will save you a lot of db hits and most importantly, time, as you are getting rid of get_term_by() and get_term_children()
There is no proper way to remove parents from wp_get_post_terms(), so the best way will be to just loop over them and ignore/skip them with continue. I assume you are talking about top level terms which have 0 assigned to its $parent property, so you just need to check that the parent value is not 0
Always do proper failure checks. If you don't do that, and your code fails, php error and notices are returned, which is known as bugs. You would want to avoid that. Also, you would always want your code to fail in a controlled, expected manner without bugs. As I stated before, wp_get_post_terms() returns an empty array or a WP_Error object, so this is what you need to check for. If any of these cases occur, immediately halt execution and return the function to avoid bugs and unexpected output
PUTTING THE ABOVE IN CODE
I like to keep my template files short and sweet. For that reason, bulky code the above always goes into a function and I then just call the function in my template files where necessary. Also, just a tip, I have function specific functions files to keep my code organised and not to overload functions.php. my functions.php file is usually not more than 100 lines of code.
For example, this is part of your post's meta, so this will go into a file with other meta functions like displaying the autor name and post date.
function get_post_child_terms( $taxonomy = '' )
{
$current_post = get_queried_object_id();
$terms = wp_get_post_terms( $current_post, $taxonomy );
/*
* Check if $taxonomy has a value, also check for WP_Error or empty $terms. If any of these conditions
* are met, halt execution and return false
*/
if ( !$taxonomy || is_wp_error( $terms ) || empty( $terms ) )
return false;
/*
* We have made it to here safely, now iterate over the terms
*/
foreach ( $terms as $term ) {
/*
* Check for parent terms and ignore them
*/
if ( $term->parent == 0 )
continue;
/*
* Get an array of term names
*/
$term_names[] = $term->name;
}
/*
* Build our string of names
*/
if ( !isset( $term_names ) )
return false;
$string = 'Some text here maybe to start of: ' . implode( ',', $term_names ) . 'Maybe something at the end';
return $string;
}
USAGE
You can now simply call the function in your template as follow:
echo get_post_child_terms( 'listings_category' );
This will produce a list like this
Some text here maybe to start of: Term name 1, Term name 2, Term name 3 Maybe something at the end
FINAL NOTES
The code above is untested and might be a bit buggy.
The code above is the very least that you need. You can extend and misuse it as you see fit to fit your exact needs. A few ideas for extension might be to work in some arguments to where you can choose to display the parent terms or not, and whether the function should return a string of term names or an array of term names. The sky is the limit here
You can build in a cache system to cache your results to optimize these even further.
EDIT
The above code is now tested and is working as expected

Related

Check if product has specific attributes set to it, then show additional div if true

I am trying to create a function to show additional product information if requirements are met dependent on whether some attributes are set or not on specific products. For this I am using two attributes called 'pa_storlek' and 'pa_djurart'. Seems to me everything should be working but no matter what I do I just keep getting the else value (Inte X-Small).
I need to check the two attributes together, meaning that if I get both attributes values at the same time the statement should be valid, and - if not, it should show the else output.
Anyone has an idea? Been looking around alot but can't seem to find another question like mine..
// X-Small dogs list
add_action( 'woocommerce_single_product_summary', 'x_small_dogs', 90 );
function x_small_dogs() {
global $product;
$product_attributes = $product->get_attributes();
// Get the product attribute value
$size = $product->get_attribute('pa_storlek');
$animal = $product->get_attribute('pa_djurart');
// If product has attribute 'size = x-small' and 'animal = hund'
if( strpos($size, 'x-small') && strpos($animal, 'hund') ) {
echo '<div class="">X-Small</div>';
} else {
echo '<div class="">Inte X-small</div>';
}
}
If strpos find the string starting at the first character, return 0 (index position) and it is evaluated like false.
So try
if( strpos($size, 'x-small')!==false && strpos($animal, 'hund')!==false) {

Create WordPress gallery shortcode from Advanced Custom Fields

I am following the instructions set out in the ACF Gallery page at https://www.advancedcustomfields.com/resources/gallery/ in how to create a native Wordpress gallery using the shortcode and dynamically populating the item IDs from the data in the ACF Gallery field.
Example:
EDIT: I have slightly modified the code to include definition for $image_ids
<?php
// Load value (array of ids).
$images = get_field('product_images');
$image_ids = get_field('product_images', false, false);
if( $images ) {
// Generate string of ids ("123,456,789").
$images_string = implode( ',', $image_ids );
// Generate and do shortcode.
$shortcode = sprintf( '', $images_string );
echo do_shortcode( $shortcode );
}
Now my problem is that the an error returns saying that the value for $image_ids is undefined, and rightly so, can't see where that gets defined at all.
I've got some older code that I used to use:
<?php
// different product sizes (gallery)
if(get_field('product_images')) : ?>
<h3>Product Images</h3>
<?php
$image_ids = get_field('product_images', false, false);
$shortcode = '[' . 'gallery ids="' . implode(',', $image_ids) . '"]';
echo do_shortcode( $shortcode );
endif;
?>
This code does work but returns an error php notice array to string conversion in jetpack-carousel. Yes I am using the 'Tiled Galleries Carousel Without Jetpack' plugin.
https://wordpress.org/support/topic/php-notice-array-to-string-conversion-in-jetpack-carousel/page/2/
I really want to follow the recommended way set out in the ACF documentation but it does not work for me. What am I doing wrong?
I don't have ACF installed but after reading their manual, I see a few issues with your code.
Problem one: you are using both $images and $images_ids. Ultimately, both of them are doing the same job and that is to get back the ids array for you. Their data can be different from the last two arguments.
Nonetheless, when you check to see if there is something, you check and evaluation with $images, but then you use $images_ids for your short_code string composition. For the error, I think that is because the version without the optional arguments returned a value while the one($images_ids) that utilized the optional arguments did not return a value but was being utilized anyway by the if clause.
I think you kind of have to figure out, which get_field version you want to use. The one with 3 args or the one with 1 arg.
This was edited after I noticed something, for why you are not getting anything, you may want to contact ACF to update their manual. That sprintf() statement will not do anything. It just going to generate a blank string that all. You may need to alter that sprintf() like the below to follow your old statement, if it still shows array to string conversion error, you would need to debug that.
$image_ids = get_field('product_images', false, false);
if( $image_ids ) {
// Generate string of ids ("123,456,789").
$images_string = implode( ',', $image_ids );
// Generate and do shortcode.
$shortcode = sprintf( '[gallery ids="%s"]', $images_string );
echo do_shortcode( $shortcode );
}
As far as I've tried, the example on the ACF website (https://www.advancedcustomfields.com/resources/gallery/) isn't correct. Here's a less elegant method that worked for me.
<?php
// Get the Gallery Array created by ACF
$galleryarray = get_sub_field('gallery');
// Create an empty array to input the ID's in to
$galleryids = array();
// Loop through the Gallery array
foreach ( $galleryarray as $image ) {
// Grab the image ID
$imageid = $image['id'];
// Put the image ID in to the empty array
array_push($galleryids, $imageid);
}
// Convert the new array into a string, values separated by a comma
$images = implode(',', $galleryids);
// Run the default WordPress Gallery shortcode
echo do_shortcode( '[gallery ids="'.$images.'"]' );
?>

Searching a custom table in wordpress

I'm currently building a site for a client and they want a search feature that will search all of the products they supply.
I have created a new table in the database called sc_products and then tried the below code in a wordpress template page but I don't appear to be getting anywhere. If anyone knows how I can get this working that would be awesome!
<?php
/*
Template Name: myTemp
*/
function search_it() {
if ( is_search() && isset($_GET['s'])) {
global $wpdb;
$address_table = $wpdb->prefix . "sc_products";
$myrows = $wpdb->get_results( 'SELECT product FROM ' . $sc_products );
foreach ( $myrows as $single_row ) {
global $single_row;
}
$product = $single_row->product;
}
return $product;
}
$city = search_it();
echo $city;
get_search_form();
?>
There's a couple of things going on here, let's see if we can work them out.
Here's your modified function which should perform a search, with comments throughout to help explain what's going on.
NOTES:
1. You declare $address_table, but then use $sc_products. That can't be correct, as $sc_products is not defined.
2. This answer is based on the column names you provided in comments - IF they are not an exact match, you'll need to update them, INCLUDING matching case. If it's not Application, but instead application, you'll need to make that change.
function search_it() {
// If this is a search, and the search variable is set
if ( is_search() && isset( $_GET['s'] ) ) {
// Global in $wpdb so we can run a query
global $wpdb;
// Build the table name - glue the table prefix onto the front of the table name of "sc_products"
$address_table = $wpdb->prefix . "sc_products";
// Get the search term into a variable for convenience
$search = $_GET['s'];
// To use "LIKE" with the wildcards (%), we have to do some funny business:
$search = "%{$search}%";
// Build the where clause using $wpdb->prepare to prevent SQL injection attacks
// Searching ALL THREE of our columns: Product, Application, Sector
$where = $wpdb->prepare( 'WHERE Product LIKE %s OR Application LIKE %s OR Sector LIKE %s', $search, $search, $search );
// Execute the query with our WHERE clause
// NOTE: Your code originally used "$sc_products", but that variable was not defined - so have replaced to the proper $address_table here.
$results = $wpdb->get_results( "SELECT product FROM {$address_table} {$where}" );
// return the results. No need to put into an array, it's already an array
return $product;
}
// For consistency, return an empty array if not a search / no search term
return array();
}
// USAGE:
// Run the query
$cities = search_it();
// You can't echo an array!
// echo $city;
// var_dump to see the whole array
var_dump( $cities );
// More useful USAGE:
$cities = search_it();
// If there's any results
if ( ! empty( $cities ) ) {
// Output a title
echo '<h1>Product Search Results:</h1>';
// Loop over the results
foreach( $cities AS $city ) {
// $wpdb returns an array of objects, so output the object properties
echo '<h2>' . $city->Product . '</h2>';
echo '<p>' . $city->Application . '</p>';
echo '<p>' . $city->Sector . '</p>';
}
}
get_search_form();

PHP: Add translated tags to category list

I have a website made from a template in Wordpress, I've installed a translation plugin (qtranslate).
http://madebysylvie.be/collection
In my "photo album" page when I sort the items in the default language (english) everything works fine, however if I change to another translation (ex.french), the name of the category changes and the tagged items don't appear anymore.
Here is the PHP code that executes that function,
<ul class="filter_portfolio">
<?php
// Get the taxonomy
$terms = get_terms('filter', $args);
// set a count to the amount of categories in our taxonomy
$count = count($terms);
// set a count value to 0
$i=0;
// test if the count has any categories
if ($count > 0) {
// break each of the categories into individual elements
foreach ($terms as $term) {
// increase the count by 1
$i++;
// rewrite the output for each category
$term_list .= '<li class="segment-'.$i.'">' . $term->name . '</li>';
// if count is equal to i then output blank
if ($count != $i)
{
$term_list .= '';
}
else
{
$term_list .= '';
}
}
// print out each of the categories in our new format
echo $term_list;
}
?>
</ul>
I would like to change this block of code in order to identify the tags in the translated version. I know that the trigger is the ("data-value") parameter.
The following code let's me translate the taxonomies from the default language,
function qtranslate_edit_taxonomies(){
$args=array(
'public' => true ,
'_builtin' => false
);
$output = 'object'; // or objects
$operator = 'and'; // 'and' or 'or'
$taxonomies = get_taxonomies($args,$output,$operator);
if ($taxonomies) {
foreach ($taxonomies as $taxonomy ) {
add_action( $taxonomy->name.'_add_form', 'qtrans_modifyTermFormFor');
add_action( $taxonomy->name.'_edit_form', 'qtrans_modifyTermFormFor');
}
}
}
add_action('admin_init', 'qtranslate_edit_taxonomies');
?>
Thank you very much for helping!
i suspect you use the category name to filter your database records. So in your db there is only the "englsh" name and when you "translate" it your script is unable to work properly since it uses the new "french" name.
Can you try to convert the category name to engish before executing your query?
EDIT
What i actually think is for you to find a way to pass two variables to your php script. Whatever suits your needs.
For example, some possible scenarios are:
- category in english + language (fr) = based on your selected language you query your db and return proper results(based on english work thought)
- category id + language (fr) = same as above but more generic since you use an id to get data from table.
I am guessing you must change somewhat your html and you php script (one to pass correct data and the other to return correct format).

Query Database and Return the result

I am having a problem for a while now and I can´t seem to solve it on my own.
I have made a website, this website is multilingual and it was made in wordpress.
In my "photo album" page when I sort the items in the default language (English) everything works fine, however if I change to another translation (ex.french), the name of the category changes and the tagged items don't appear anymore.
http://madebysylvie.be/collection
In my database I manage to find the table and the rows of each category, I want to be able access it in a different language, each one has an unique ID.
I know I have to grab the ID from the database of each category and return it to my PHP script.
This is my code,
<ul class="filter_portfolio">
<?php
// Get the taxonomy
$terms = get_terms('filter', $args);
// set a count to the amount of categories in our taxonomy
$count = count($terms);
// set a count value to 0
$i=0;
// test if the count has any categories
if ($count > 0) {
// break each of the categories into individual elements
foreach ($terms as $term) {
// increase the count by 1
$i++;
// rewrite the output for each category
$term_list .= '<li class="segment-'.$i.'">' . $term->name . '</li>';
// if count is equal to i then output blank
if ($count != $i)
{
$term_list .= '';
}
else
{
$term_list .= '';
}
}
// print out each of the categories in our new format
echo $term_list;
}
?>
</ul>
However I am not good enough to do this on my own, and I would be very happy if someone could help me out on this one.
I don't know how to query my database, and I am not shore how to modify the php in order to print it in the other languages.
Thanks
Please refer to the Wordpress documentation, the "Codex":
Class Reference/wpdb – Interfacing With the Database
Displaying Posts Using a Custom Select Query
Class Reference/WP Query –
Custom Queries – how to modify queries using hooks
But remember »Most of the time you can find the information you want without actually dealing with the class internals and globals variables. There are a whole bunch of functions that you can call from anywhere that will enable you to get the information you need.«
WP_Query example from the docs:
<?php
// The Query
$the_query = new WP_Query( $args );
// The Loop
if ( $the_query->have_posts() ) {
while ( $the_query->have_posts() ) {
$the_query->the_post();
echo '<li>' . get_the_title() . '</li>';
}
} else {
// no posts found
}
/* Restore original Post Data */
wp_reset_postdata();

Categories