Recursive function does not return array [duplicate] - php

This question already has answers here:
How to use return inside a recursive function in PHP
(4 answers)
Closed 9 months ago.
I have written the function below to return parent id's of all categories in Worpress by category id. Everything works fine except it does not return the array... Any suggestions would be great! :-)
$current_category = (int) $_GET['current_category'];
$cat_ids = array($current_category);
function getParentCatIds($current_category,$cat_ids){
$child = get_category($current_category);
$parent_id = $child->parent;
if($parent_id !== 0){
array_push($cat_ids, $parent_id);
getParentCatIds($parent_id,$cat_ids);
}else{
var_dump($cat_ids); // <--- this returns the right array
return $cat_ids; // <--- this returns NULL
}
}
if($current_category){
$cat_ids = getParentCatIds($current_category,$cat_ids);
var_dump($cat_ids); // <--- this returns NULL
}

When you call getParentCatIds() (line 9), you didn't do anything with the return of the function. You should assign it or return it.

You should always sanitize input. A good starting point is filter_var(). Using the right flags for validation and sanitization and makes your input save(r). Keep in mind that FILTER_VALIDATE_* only tells you if something is valid, while FILTER_SANITIZE_* actually cleans your data from unwanted and potentially malicious data.
$currentCat = intval( $_GET['current_category'] );
$currentCat = filter_var( $currentCat, FILTER_SANITIZE_NUMBER_INT );
if ( empty( $currentCat ) ) {
// Abort – no valid data
return;
}
Then you can build an array, containing your original Category parent ID. This you can pass to array_walk(), with a callback as second parameter. The callback itself has assigned a collecting/ final array that is passed as reference and serves as target for your results. Now you can loop recursively over an indefineatly nested WordPress category hierarchy.
// Base array
$parents = [];
$callback = function( $index, $id ) use ( &$parent ) {
0 !== get_category( $id )->parent and $parents[] = $id;
};
array_walk( [ get_category( $currentCat )->parent ], $callback );

1) You should have asked at wordpress.stackexchange.com
2) I think solution is: on line 9 , instead of
getParentCatIds($parent_id,$cat_ids);
you should have
return getParentCatIds($parent_id,$cat_ids);

Related

PHP array_map and array_filter returning references instead of new arrays

These array functions are not returning new arrays but seem to be returning references to the original. I don't see this behavior in the PHP manual for the array functions. Why is this happening? Is there a way to keep it from happening? Is it a bug or just the way php works?
// create an array of posts with boolean completed
// use array_filter and vardump resulting arrays
$posts = [
new Post('My First Post', true),
new Post('My Second Post', false),
new Post('My Third Post', true),
new Post('My Fourth Post', false)
];
$unpublishedPosts = array_filter($posts, function ($post) {
return !$post->published;
});
$publishedPosts = array_filter($posts, function ($post) {
return $post->published;
});
var_dump('published', $publishedPosts);// correct shows post 1 and 3
var_dump('unpublished', $unpublishedPosts); // correct shows post 2 and 4
// now use array_map to get an array of posts with all set to true
$modified = array_map(function ($post) {
$post->published = true;
return $post;
}, $posts);
// var_dump modified, published, and unpublished
var_dump($modified);// correct all set to true
var_dump('published', $publishedPosts);// correct 1 and 3 set to true
var_dump('unpublished', $unpublishedPosts);// not correct still 2 and 4 but set to true
// now run foreach to set all to false and then var_dump again
foreach ($posts as $post) {
$post->published = false;
}
// all 3 arrays are set to false on all posts
var_dump($modified);
var_dump('published', $publishedPosts);
var_dump('unpublished', $unpublishedPosts);

Php filter object by key who contains a string [duplicate]

This question already has answers here:
Filter array to retain all elements that have a key containing a searched string
(3 answers)
Closed last year.
I'm not familiar with PHP and i met a problem to filter an object of array.
I have a function (get_post_meta_for_api) who return me an object of array but there're a lot of properties that i don't need ...
So i'd like to filter my object by key who contains "seopress"
function get_post_meta_for_api( $object ) {
$post_id = $object['id'];
return get_post_meta( $post_id );
}
Thanks in advance for your help :)
As per documentation, get_post_meta returns an array (https://developer.wordpress.org/reference/functions/get_post_meta/),
this should work:
function get_post_meta_for_api( $object ) {
return array_filter(
get_post_meta($object['id']),
function ($key) {
return preg_match('/_seopress_*/', $key) === 1;
},
ARRAY_FILTER_USE_KEY
);
}
Check get_post_meta for more information about how to use it.
get_post_meta comes with the option to retrieve a single meta value. Here's an example, using the meta value that you want to get.
get_post_meta($post_id, 'seopress', true);
The first argument is the post id, second is the meta key, third is if you want a single value.
get_post_meta without true in the third argument will return an array containing the value, with true it will return the value as is.

Wordpress get_option() with index key from string

--Edited--
I've made a admin form which adds some custom functions to my theme. Loading the settings page I first get the current settings from the database. For this I use get_option().
The setting field is called product_settings
To get all values from this setting you can call it with: $option = get_option('product_settings');
The result of this is equivalent to this:
$option = [
'product_01' => [
'style' => [
'color' => [
'primary' => '#ffffff'
]
]
]
];
Now, to get the value of index 'primary' I would call it like this:
From DB:
$optionColorPrimary = get_option('product_settings')['product_01']['style']['color']['primary'];
From array:
$optionColorPrimary = $option['product_01']['style']['color']['primary'];
Now, this work all fine and that. But now comes the tricky part. The index location is passed in a string value like this:
$get_option_srt = 'product_settings[product_01][style][color][primary]';
First part is the db field. And the part after it, separated by square brackets are the nested indexes.
My Question
How do I get to the nested value of this array based on the indexes from the string?
This is my attempt so far:
$get_option_srt = 'product_settings[product_01][style][color][primary]';
// split in two, to separate the field name from the indexes.
$get_option_srt = preg_split('/(\[.*\])/', $get_option_srt, 2, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);
// yes, this does not work...
// The part after get_option() is wrong. Here are the nested index locations needed
$option = get_option( $get_option_srt[0] )[ $get_option_srt[1] ];
Any help is welcome.
I would recommend not attempting to get it directly off the get_option() result, but rather get the value, then parse the path.
You can write your own function that accomplishes what you want. Something like so:
NOTE: This has many "Defensive" measures in place, so that if you ask for a path that doesn't exist, or use a malformed path, this will not throw PHP notices / errors:
function get_option_by_path( $path ) {
// get all the "keys" from within the square braces
preg_match_all( '/\[(.+?)\]/', $path, $matches );
// get the initial "key" (eg, 'product_settings')
$key = explode( '[', $path );
// ensure base key is set, in case there were no square braces
$key = ( ! empty( $key[0] ) ) ? $key[0] : $key;
// load the option value from the DB
$option = get_option( $key );
if ( ! $option || ! is_array( $option ) ) {
return FALSE;
}
// if the passed-in path didn't have any square-brace keys, return the option
if ( empty( $matches[1] ) ) {
return $option;
}
// loop over all the keys in the square braces
foreach ( $matches[1] AS $key ) {
// if $option is an array (still), and has the path, set it as the new $option value
if ( is_array( $option ) && array_key_exists( $key, $option ) ) {
$option = $option[ $key ];
} else {
// otherwise, can't parse properly, exit the loop
break;
}
}
// return the final value for the $option value
return $option;
}
Usage:
$get_option_srt = 'product_settings[product_01][style][color][primary]';
$value = get_option_by_path( $get_option_srt );
You could do this:
$value = 'product_settings[product_01][style][color][primary]';
// The below should result in: 'product_settings[product_01[style[color[primary'
$key_string = str_replace(']', '', $value);
//Create an array for all the values, using '[' as the delimiter
$key_array = explode('[', $key_string);
/* Remove first value (the option name), and save the
value (which is 'product_settings' in this case) */
$option_name = array_shift($key_array);
// Get the option value (an array) from the db:
$option_settings = get_option($option_name);
// Set $option_setting to be the entire returned array:
$option_setting = $option_settings;
/*
Iterate through your key array for as many keys as you have,
changing $option_setting to be more refined on each iteration
until you get the value you need:
*/
for ($i = 0; $i < count($key_array); $i++) {
$option_setting = $option_setting[$key_array[$i]];
}
$option setting should now contain the value you need.

php function returning null value

I am recursively searching a tree node for its parents, and then trying to return its parent categories in an array.
The function receives and passes itself an array of each parent which is finally returned.
Even though this array has elements, the statement before the return when viewed outside the function is nul.
To make it work, I just made the parameter by reference. But why is it always nul?
Here is my code:
function getParent($id,$parents){ // to work changed this to getParent($id,&$parents)
if($id < 2) { // 1 is the Top of the Tree , so job is done
return $string;
}
$child = DB::fetchExecute((object)array( // pdo query for category to get parents
'sql' => "category",
'values'=> array($id),
'single'=> 1,
'debug' => 0)
);
$parent = DB::fetchExecute((object)array( // pdo query for parents info
'sql' => "category",
'values'=> array($child->native_parent_category_id),
'single'=> 1,
'debug' => 0)
);
$string[]= "<li>$parent->name ($parent->native_category_id)</li>
";
getParent($parent->native_category_id , $parents);
}
// call function
$array = array();
$returnString = getParent($id,$string);
var_dump($returnString,$array); // will both be NULL, or if called by Reference $array has the goods
?>
Change:
function getParent($id,$parents){
To:
function getParent($id,$parents, $string){
And change:
getParent($parent->native_category_id , $parents);
To:
getParent($parent->native_category_id , $parents, $string);
The scope of $string only exists in the function as it runs - so, if you rerun the function, it will reset all the variables within it. You need to send the variable each time you rerun it.
I would declare $string before function, and inside function, use global $string; at top.

Save shortcode array with WordPress Options API then output in another function

Note: While this is probably a simple fix, I'm new to using arrays and am completely stumped.
I'm trying to save the data from a shortcode array via the Options API in WordPress, then call that array and use the data to create another array to hook into a plugin's function. It's a responsive slider plugin and I'm basically trying to attach a shortcode to it so I can create the slider on the backend and display it on the front end with a shortcode that looks like: [responsive_slider slider_name="imageslider"].
The implementation documentation can be found here, and here's my code:
function responsive_gallery_shortcode($atts, $content=null) {
extract(shortcode_atts( array('slider_name' => 'product_page') , $atts));
foreach ($slider_name as $value) {
update_option('_unique_slider_name', $value );
}
if(function_exists('show_flexslider_rotator'))
echo show_flexslider_rotator( $slider_name );
add_image_size( $slider_name , '550', '250', true );
}
add_shortcode('responsive_gallery', 'responsive_gallery_shortcode');
if (!function_exists('custom_set_flexslider_hg_rotators')) {
function custom_set_flexslider_hg_rotators() {
$slider_name = get_option('_unique_slider_name');
foreach ($slider_name as $value) {
$rotators = array();
$rotators[ $value ] = array( 'size' => $value );
return $rotators;
}
}
}
add_filter('flexslider_hg_rotators', 'custom_set_flexslider_hg_rotators', 9999);
I'm getting an "Invalid argument supplied for foreach()" error on both foreach functions. On the page where I have two shortcodes both errors show up twice. It seems as though $slider_name is a string instead of an array, but there's got to be a way to save it in the update_option() function so that it returns an array. I'm quite new to arrays, and I'm definitely struggling here. I've spent hours on this and have already received a little help on the WordPress side, but I'm not quite getting it.
As the shortcode attribute will arrive as a string, you need to convert it to an array first.
At the same time, as it has to be passed as a string, you'll need to use a separator so you can manage this.
And for all that, you'll need the PHP function explode.
$string = "one,two";
$array = explode( ',', $string );
var_dump( $array );
Results in:
array (size=2)
0 => string 'one' (length=3)
1 => string 'two' (length=3)
And
$string = "one";
$array = explode( ',', $string );
var_dump( $array );
Results in:
array (size=1)
0 => string 'one' (length=3)
PS: It's always worth to consult the PHP Manual and also the comments in each of its pages : http://www.php.net/manual/en/language.types.array.php
[update]
There are many issues with your original code, check the comments of this revised version:
function responsive_gallery_shortcode($atts, $content=null) {
extract(shortcode_atts( array('slider_name' => 'product_page') , $atts));
// Convert string into array
// Using comma as separator when writing the shortcode in the post
$array_slider = explode( ',', $slider_name );
// YOU DON'T NEED A `foreach` HERE
//foreach ($array_slider as $value) {
update_option('_unique_slider_name', $array_slider );
//}
// I DON'T KNOW WHAT THIS FUNCTIONS DOES
// But in any case, being $array_slider an array, maybe it should be inside a `foreach`
if(function_exists('show_flexslider_rotator'))
echo show_flexslider_rotator( $array_slider );
// THIS DOESN'T MAKE SENSE
// You're not supposed to be adding images sizes at each Shortcode call
// And you are dealing with an array
add_image_size( $slider_name , '550', '250', true );
}
add_shortcode('responsive_gallery', 'responsive_gallery_shortcode');
if (!function_exists('custom_set_flexslider_hg_rotators')) {
function custom_set_flexslider_hg_rotators() {
// The option was already saved as array, so we can work directly with it
$slider_name = get_option('_unique_slider_name');
// YOU DON'T WANT TO DECLARE THE VARIABLE AT EACH STEP OF THE LOOP
$rotators = array();
foreach ($slider_name as $value) {
$rotators[ $value ] = array( 'size' => $value );
}
// RETURN THE VALUE ONLY AFTER COMPLETING THE LOOP
return $rotators;
}
// PUT THE FILTER HOOK INSIDE if(!function_exists())
add_filter('flexslider_hg_rotators', 'custom_set_flexslider_hg_rotators', 9999);
}

Categories