Foreach loop not listing all items - php

I'm trying to loop through all the items inside an array and add it to a variable. However, i'm seeing only one item is displaying from the array after looping through.
The process below ithat i'm trying to use is to exclude pages from cache on WordPress.
Instead of seeing the three items when i echo the result i'm seeing only the last item which is /welcome/
I want all three items to be displayed to exclude all three pages instread of just one.
$pages = "/become-a-teacher/, /term-conditions/, /welcome/";
$delimiter = ' ';
$page_views = explode($delimiter, $pages);
foreach ($page_views as $page_view) {
$uri = strtok( $_SERVER["REQUEST_URI"], '?' );
if ( in_array( $uri, [ $page_view ] ) ) {
cancel();
}
}
echo "$page_view <br>";
Can anyone lead me towards how to fix this issue.

You have to add the echo inside the foreach:
foreach ($page_views as $page_view) {
$uri = strtok( $_SERVER["REQUEST_URI"], '?' );
if ( in_array( $uri, [ $page_view ] ) ) {
cancel();
}
echo "$page_view <br>";
}

Related

How do I compare a string to multiple, but separate, arrays in PHP?

I am trying to write a script that I can implement into WordPress. The purpose of this doesn't really matter.
What I am trying to get is the script to detect the URL, see if any part of the URL contains a string from one of 4 different arrays, and then include the correct file.
This is what I currently have:
<?php
//Detect URL and remove slashes and ".php"
$url = $_SERVER["REQUEST_URI"];
$find = array( '/', '.php');
$clear = array( ' ', ' ');
//Arrays to detect from
$region1 = array( 'LosAngeles', 'SantaMonica', 'Hollywood' );
$region2 = array( 'Houston', 'Dallas' );
$region3 = array( 'Las Vegas', 'SaltLakeCity' );
//Assign a region
if ( in_array( $url, $region1 ) ) {
$region = "California";
}
elseif ( in_array( $url, $region2 ) ) {
$region = "Texas";
}
elseif ( in_array( $url, $region3 ) ) {
$region = "Nevada";
}
//Load file based on region
if ( $region = "California"; ) {
include "file1.php";
}
elseif ( $region = "Texas" ) {
include "file2.php";
}
elseif ( $region = "Nevada" ) {
include "file3.php";
}
?>
I have already tried foreach, but that doesn't let you run a loop for more than 1 array. I am also not trying to do an array_intersect. Just checking that the URL matches at least one of the arrays.
All your guys' help is appreciated!
Thank you!
You already name foreach and array in your question and that points into the right direction.
But first I'd like to point out this variable naming:
//Arrays to detect from
$region1 = array( ... );
$region2 = array( ... );
$region3 = array( ... );
These three variable actually can be easier represented by an array which again makes that variable then compatible with foreach as you can use it to iterate (traverse over) an array:
$regions = [
"California" => [ ... ],
"Texas" => [ ... ],
"Nevada" => [ ... ],
];
foreach ($regions as $region => $cities) {
...
}
Now what you only need is a map from regions to file-names to include:
$files = [
"California" => "file1",
"Texas" => "file2",
...
]
Then you can map it within the foreach easily:
if (!isset($files[$region])) {
throw new UnexpectedValueException(sprintf("File for region %s missing", var_export($region, true))));
}
$file = sprintf("%s.php", $files[$region]);
include($file);
return;
This mini-program will check if there is a file defined for a region and then include it. It's different to your example as it does not use an if clause but just returns if there is a region match. Even though, a matching reason is even expected in the first place.
So you need to wire this within the loop to find that one case that matches the region based on cities:
foreach ($regions as $region => $cities) {
if (!in_array($url, $cities))
continue;
}
if (!isset($files[$region])) {
throw new UnexpectedValueException(
sprintf("File for region %s missing", var_export($region, true)));
}
$file = sprintf("%s.php", $files[$region]);
include($file);
return;
}
throw new UnexpectedValueException(
sprintf("No region found for URL %s", var_export($url, true))
);
Take-aways:
Do not number variables -> nearly always this is a sign you can take an array instead.
If there is one case out of many it's often a single if within a loop.
Arrays in PHP are also a hash-map. You can ask if something exists (e.g. by it's key). Use maps to your benefit.

Want to insert a logo as the middle menu item in Wordpress theme

EDIT: I adjusted my parameters to insert the logo directly into the menu, instead of padding a specific menu item. The padding method can easily drive a centered menu off-center. This insertion method should resolve that issue.
I'm working on a theme, and want to create a menu split by a logo. I realize I could just create two menus, but I want this to be as streamlined for the user as possible. I've already been able to get the number of items and target the menu item I want, but I'm not sure how to use my functions.php file to add the class "pad-item" to the <li>.
Here is what I have to find and target the specified item. All it's returning, though, is an index number of top level items.
$locations = get_nav_menu_locations();
$menu = wp_get_nav_menu_object($locations['primary']);
$items = wp_get_nav_menu_items($menu->term_id);
$top_level = 0;
foreach ($items as $val) {
if ($val->menu_item_parent === '0') {
$top_level++;
}
}
$index = round($top_level / 2) - 1;
return $index;
Any help would be greatly appreciated. Thanks.
I was able to figure out the issue, and I wanted to post my solution in case someone else was looking for the same answer.
function main( $items, $args ) {
// Checks to see if the menu passed in is the primary one, and creates the logo item for it
if ( $args->theme_location == 'primary' ) {
$logo_item = '<li class="menu-item">' . get_logo() . '</li>';
}
//Gets the location of the menu element I want to insert the logo before
$index = round( count_top_lvl_items() / 2 ) + 1;
//Gets the menu item I want to insert the logo before
$menu_item = get_menu_item( $index );
$insert_before = '<li id="menu-item-' . $menu_item->ID;
$menu_update = substr_replace( $items, $logo_item, strpos( $items, $insert_before ), 0 );
return $new_menu;
}
//Counts the number of top level items in the menu
function count_top_lvl_items() {
$items = get_menu_items();
$counter = 0;
foreach ( $items as $val ) {
if ( $val->menu_item_parent === '0' ) {
$counter++;
{
return $counter;
}
//Returns the menu item to insert the logo before
function get_menu_item( $index ) {
$items = get_menu_items();
$counter = 0;
foreach ( $items as $val ) {
if ( $val->menu_item_parent === '0' ) {
$counter++;
}
if ( $counter == $index ) {
return $val;
}
}
}
//Returns the logo menu item. I have it separated because my theme allows for varied logos
function get_logo() {
$home = get_option( 'home' );
$logo = get_option( 'logo' );
$logo_item = <<<EOD
<div id="logo">
<a href="$home">
<img src="$logo" id="logo-img" alt=""/>
</a>
</div>
EOD;
return $logo_item;
}
function get_menu_items() {
$locations = get_nav_menu_locations();
$menu = wp_get_nav_menu_object( $locations['primary'] );
$items = wp_get_nav_menu_items( $menu );
return $items;
}
Please feel free to tell me if I missed something, or if this could be done in a different way.
Thanks!
Your function name might be used by other plugins or themes and may cause a problem.
I suggest you either change the function name or use function_exists within if else statement.
Here is the manual > http://php.net/manual/bg/function.function-exists.php
Quick suggestion:
`
if(!function_exists('main'){
function main(){
$do_stuff = 'Currently doing';
return $do_stuff;
}
}
`
I am using the theme Page Builder Framework, then when you customize the appearance you can choose a centered menu where the logo is in the middle and the menu is split.

show an array inside of an array in a csv file using php

I have created an array using
$processed[$y] = array('source' => $source,
'check total' => number_format($checkTotal, 2, '.', ''),//($rows['total'], 2, '.', ''),
'check number' => $num,
'table' => $invTable,
'skus' => $skuArray,
'check amount' => number_format($amount, 2, '.', '')
);
$y++;
My $skuArray is an array that contains all of the sku's that are associated with a specific check number. I am attempting to have it displayed like:
source check total check number table skus check amount
MNC 152.32 649 inv_temp 10198547 152.32
10195874
so it will list all of the sku's attached to a specific check nuimber before it lists the next item.
Here is my function to convert $processed to a csv file:
function to_csv( $array ) {
$csv = "";
if (count($array) == 0) return "No Processed checks found";
## Grab the first element to build the header
$arr = array_pop( $array );
$temp = array();
foreach( $arr as $key => $data ) {
$temp[] = $key;
}
$csv = implode( ',', $temp ) . "\r\n";
## Add the data from the first element
$csv .= to_csv_line( $arr );
## Add the data for the rest
foreach( $array as $arr ) {
$csv .= to_csv_line( $arr );
}
return $csv;
}
function to_csv_line( $array ) {
$temp = array();
foreach( $array as $elt ) {
$temp[] = '"' . addslashes( $elt ) . '"';
}
$string = implode( ',', $temp ) . "\r\n";
return $string;
}
How can I accomplish this? I have tried using array('skus=>$skuArray), but it just gave me "Array" in the results.
UPDATE: Here is what the array looks like when I do a var_dump($skuArray)
array(1075) { [0]=> string(8) "10182997" [1]=> string(8) "10190313" [2]=> string(8) "10190314" [3]=> string(8) "10190315" etc.
I've provided a solution that is untested, so use at your own discretion.
I've done my best to explain everything through comments in the code.
Remove the first sku value from the sku array, assign it to the first line.
Add additional skus to a temporary array based on the line keys.
Check for temporary sku array, and create the additional lines from it.
Your final to_csv function will look something like this:
function to_csv( $array ) {
$csv = "";
if (count($array) == 0) return "No Processed checks found";
## Grab the first element to build the header
$arr = $array[0];
$temp = array();
foreach( $arr as $key => $data ) {
$temp[] = $key;
}
$csv = implode( ',', $temp ) . "\r\n";
## Process each line
foreach( $array as $arr ) {
## Check for multiple sku values. Create a temporary array for them to add them after this line.
if(isset($arr['skus']) && is_array($arr['skus']))
{
//Remove the first value (since we only need it for the actual line item)
$sku_value = $arr['skus'][0];
unset($arr['skus'][0]);
//Create temporary lines for each sku
$temp_sku_arrays = array();
foreach($arr['skus'] as $sku)
{
$sku_array = array();
foreach($arr as $key => $value)
{
//Set only the sku key with a value.
$sku_array[$key] = ($key == 'skus' ? $sku : '');
}
$temp_sku_arrays[] = $sku_array;
}
//Set the first line to the first sku value.
$arr['skus'] = $sku_value;
}
$csv .= to_csv_line( $arr );
//Check for additional sku lines, then add them
if(isset($temp_sku_arrays) && is_array($temp_sku_arrays))
{
foreach($temp_sku_arrays as $sku_array)
{
$csv .= to_csv_line( $sku_array );
}
unset($temp_sku_arrays);
}
}
return $csv;
}
I think CSV is not well suited for what you are about to do. I would use json or xml. However, you could choose a separator different from the csv sepator to represent an array, Like this:
foo,bar1;bar2;bar3,...
what would represent the following record:
$record = array (
'foo',
array ('bar1', 'bar2', 'bar3')
);

If array value begins with

I have an array of values.
My crawler scans the web page and inserts all the links, the links' titles and description is a multidimensional array.
But now I have a new array and I only want the links, descriptions and titles etc. if they begin with any value in the array ($bbc_values)
But I don't really know how to do this. I have have gotten pretty far in terms of the actual code but can anyone give me any ideas a) why my code isn't working b) suggestions for my problem?
$bbc_values = array('http://www.bbc.co.uk/news/health-', 'http://www.bbc.co.uk/news/politics-', 'http://www.bbc.co.uk/news/uk-', 'http://www.bbc.co.uk/news/technology-', 'http://www.bbc.co.uk/news/england-', 'http://www.bbc.co.uk/news/northern_ireland-', 'http://www.bbc.co.uk/news/scotland-', 'http://www.bbc.co.uk/news/wales-', 'http://www.bbc.co.uk/news/business-', 'http://www.bbc.co.uk/news/education-', 'http://www.bbc.co.uk/news/science_and_enviroment-', 'http://www.bbc.co.uk/news/entertainment_and_arts-', 'http://edition.cnn.com/');
foreach ($links as $link) {
$output = array(
"title" => Titles($link), //dont know what Titles is, variable or string?
"description" => getMetas($link),
"keywords" => getKeywords($link),
"link" => $link
);
if (empty($output["description"])) {
$output["description"] = getWord($link);
}
}
$data = implode( " , ", $output['link']);
foreach ($output as $new_array) {
if (in_array($output, $bbc_values)) {
$news_stories[] = $new_array;
}
var_dump($news_stories);
}
Okay, I don't completely understand the code here.
But I think $output array should be declared outside the first foreach loop and each array should be appended to it?
Because from the code you're writing, only the details of last $link will be stored inside the $output
Also, what is $data here? what are you using it for?
Turn $bbc_values into a regex:
$bbc_re = '/^('.implode('|', array_map('quotemeta', $bbc_values)).')/';
Then use this regex to filter the links.
foreach ($links as $link) {
if (preg_match($bbc_re, $link)) {
/* Do stuff with $link */
}
}
I assume you what you want is to have an array with links that starts with of the links in the bbc_values and additionally a string $data with a comma separated list of all links. Try something this :
<?php
$bbc_values = array('http://www.bbc.co.uk/news/health-', 'http://www.bbc.co.uk/news/politics-', 'http://www.bbc.co.uk/news/uk-', 'http://www.bbc.co.uk/news/technology-', 'http://www.bbc.co.uk/news/england-', 'http://www.bbc.co.uk/news/northern_ireland-', 'http://www.bbc.co.uk/news/scotland-', 'http://www.bbc.co.uk/news/wales-', 'http://www.bbc.co.uk/news/business-', 'http://www.bbc.co.uk/news/education-', 'http://www.bbc.co.uk/news/science_and_enviroment-', 'http://www.bbc.co.uk/news/entertainment_and_arts-', 'http://edition.cnn.com/');
$news_stories = array();
$all_links = array();
$news_links = array();
foreach ($links as $link) {
$item = array(
"title" => Titles($link),
"description" => getMetas($link),
"keywords" => getKeywords($link),
"link" => $link
);
if (empty($item["description"])) {
$item["description"] = getWord($link);
}
foreach($bbc_values as $bbc_value) {
// note the '===' . this is important
if(strpos($item['link'], $bbc_value) === 0) {
$news_stories []= $item;
$news_links []=$item['link'];
break;
}
}
$all_links[] = $item['link'];
}
$data_all_links = implode(' , ', $all_links);
$data_news_links = implode(' , ', $news_links);
var_dump($news_stories);

PHP Dynamically adding dimensions to an array using for loop

Here is my dilemma and thank you in advance!
I am trying to create a variable variable or something of the sort for a dynamic associative array and having a hell of a time figuring out how to do this. I am creating a file explorer so I am using the directories as the keys in the array.
Example:
I need to get this so I can assign it values
$dir_list['root']['folder1']['folder2'] = value;
so I was thinking of doing something along these lines...
if ( $handle2 = #opendir( $theDir.'/'.$file ))
{
$tmp_dir_url = explode($theDir);
for ( $k = 1; $k < sizeof ( $tmp_dir_url ); $k++ )
{
$dir_list [ $dir_array [ sizeof ( $dir_array ) - 1 ] ][$tmp_dir_url[$k]]
}
this is where I get stuck, I need to dynamically append a new dimension to the array durring each iteration through the for loop...but i have NO CLUE how
I would use a recursive approach like this:
function read_dir_recursive( $dir ) {
$results = array( 'subdirs' => array(), 'files' => array() );
foreach( scandir( $dir ) as $item ) {
// skip . & ..
if ( preg_match( '/^\.\.?$/', $item ) )
continue;
$full = "$dir/$item";
if ( is_dir( $full ) )
$results['subdirs'][$item] = scan_dir_recursive( $full );
else
$results['files'][] = $item;
}
}
The code is untested as I have no PHP here to try it out.
Cheers,haggi
You can freely put an array into array cell, effectively adding 1 dimension for necessary directories only.
I.e.
$a['x'] = 'text';
$a['y'] = new array('q', 'w');
print($a['x']);
print($a['y']['q']);
How about this? This will stack array values into multiple dimensions.
$keys = array(
'year',
'make',
'model',
'submodel',
);
$array = array();
print_r(array_concatenate($array, $keys));
function array_concatenate($array, $keys){
if(count($keys) === 0){
return $array;
}
$key = array_shift($keys);
$array[$key] = array();
$array[$key] = array_concatenate($array[$key], $keys);
return $array;
}
In my case, I knew what i wanted $keys to contain. I used it to take the place of:
if(isset($array[$key0]) && isset($array[$key0][$key1] && isset($array[$key0][$key1][$key2])){
// do this
}
Cheers.

Categories