Jump to content

Archived

This topic is now archived and is closed to further replies.

smashingred

foreach in function in library returns invalid argument when called.

Recommended Posts

I have been hacking away slowly at php as a fairly green noob. I have created a menu list using an array and foreach to build the meny which includes a conditional for the section of a website. I have decided to place turn all such sets into functions by creating a function library and calling the function but I am getting an "Invalid argument supplied for foreach(): error.

I tried using the "globals $foo" and '$GLOBALS ['foo']" but neither seemed to change the outcome. Here is the original code:

[code]
<?php

//This array defines the links and the site_section names for the links list created by the foreach

$links = array(''=>'home','blog/'=>'blog','about/'=>'about','contact/'=>'contact');

// This foreach statement creates a menu with as many links as $values in the array and converts text to first letter uppercase
foreach($links as $key => $value){
echo '<li';
if ($site_section == $value)
{ echo ' class="active"'; }
else { echo '';} echo '><a';
if ($site_section == $value){ echo ' id="current"'; }
else { echo '';} echo ' href="'.SITE_TOP_PATH.$key.'">'.ucfirst($value).'</a></li>'."\n";}

?>
[/code]

Here is the function library snippet:

[code]
<?php
function menu_display() {
global $links, $site_section, $key, $value;
   
foreach($links as $key => $value){
    echo '<li';
    if ($site_section == $value)
    { echo ' class="active"'; }
    else { echo '';} echo '><a';
    if ($site_section == $value){ echo ' id="current"'; }
    else { echo '';} echo ' href="'.SITE_TOP_PATH.$key.'">'.ucfirst($value).'</a></li>'."\n";
}
    }?>
[/code]

Here is what the array file looks like with the function call:
[code]
<?php

//This array defines the links and the site_section names for the links list created by the foreach

$links = array(''=>'home','blog/'=>'blog','about/'=>'about','contact/'=>'contact');

//This function generates the menu bar
menu_display();
?>
[/code]

It is the last one that won't work in conjunciton with the called function. Wheras the first sample file works fine while the foreach is executed in the same file as the array $links.

Please let me know, a true noob, what I am doing wrong here to make this not work.

All the best,

Jay

Share this post


Link to post
Share on other sites
Instead of using globals, pass the variables $links and $site_section to the function. You don't need $key & $value as globals or as passed variables, since they are local to the function:
[code]<?php
$links = array(''=>'home','blog/'=>'blog','about/'=>'about','contact/'=>'contact');

functioin menu_display($links,$site_section) {
    foreach($links as $key=>$value) {
        $class = '';
        $id = '';
    if ($site_section == $value) {
          $class = ' class="active"';
          $id = ' id="current"'; }
  echo '<li' . $class . '><a' . $id . ' href="'.SITE_TOP_PATH.$key.'">'.ucfirst($value).'</a></li>'."\n";
    }
}
//
//
//  other code
//
//
menu_display($links,$site_section);
?>[/code]

I also tightened up your code.

Ken

Share this post


Link to post
Share on other sites
Ken thanks for the code and the cleanup. I had read about passing variables in the function call in a couple of books but I really didn't understand the context for usage. I will have to look into this more.

ATB,

Jay

Share this post


Link to post
Share on other sites
So the function now calls but the conditional no longer works. I don't know how to pass $site_section variable to the function as it comes from a file that calls all the includes.

Here is the scenario:

I have a php file that calls all the other code called index.php. It requires a file called page_start.inc.php that requires the function library--functions.php (and some other files--contstants and config files).

In functions.php I have functions that create the whole top section of the page, the main_menu and the other elements of the page.

On the index.php I create the variable "$site_section". Prior to my moving the above function to the functions.php file the variable was passed into the foreach loop without issue. Now that I have multiple functions calling and cascading is there something that I need to do to make sure that $site_section continues to pass to the function?

I have tried adding "$site_section" to the functions that are called as was done in the code above but it still doesn't work?

What am I missing??

Share this post


Link to post
Share on other sites
Please post all of your code. Without it we can't help you.

Ken

Share this post


Link to post
Share on other sites
Sorry Ken, Here Goes:

index.php
[code]
<?php
REQUIRE $_SERVER['DOCUMENT_ROOT'].'/_sandbox/_includes/page_start.inc.php';
   
//This is the site section that at the top level of this site.
//It is used to control the state of navigation and breadcrumbs etc.
$site_section = 'about';

//Title to be displayed in the title bar of this page in the browser.
$page_title = 'Page Title'. ': ';
   
// Keywords to be displayed in the headers of this page.
$page_keywords = '';
   
// Description to be displayed in the headers of this page.
$page_description = '';
   
// Links Specific to this section of the site.
$page_section_links = '';

// Sets whether subcontent is shown or not.
$omit_subcontent = false;  //true omits subcontent; false includes subcontent

// Place The Page Top

place_top($site_section);

# Place Content Below This #
?>
[/code]

page_start.inc.php
[code]
<?php
// Get Main Config File
REQUIRE $_SERVER['DOCUMENT_ROOT'].'/_sandbox/_includes/conf/config.inc.php';

    // Get Site Constants
    REQUIRE $_SERVER['DOCUMENT_ROOT'].'/_sandbox/_includes/lib/constants.php';

    // Get Function Library
    REQUIRE $_SERVER['DOCUMENT_ROOT'].'/_sandbox/_includes/lib/functions.php';
?>
[/code]

functions.php
[code]
<?php
//This function controls the stylesheet display of either one_column or two.
function style_select() {
if ($omit_subcontent == true)
{ echo '@import url('.SITE_TOP_PATH.'_styles/one_column.css);';
}
else { echo '';
}
}
//This function controls whether Subcontent bar is shown based one_column option
function subcontent_display() {
if ($omit_subcontent == true) { echo ''; }
else {INCLUDE INCLUDE_PATH.'subcontent.inc.php'; };
}

// Template Include Functions

function place_site_name() {
echo TAGLINE." ".SITE_NAME;
}

function place_top_meta() {
INCLUDE INCLUDE_PATH.'page_top_meta.inc.php';
}

function place_top_content($site_section) {
INCLUDE INCLUDE_PATH.'page_top_content.inc.php';
}
function place_site_path() {
echo SITE_TOP_PATH;
}
function place_top() {
place_top_meta();
place_top_content($site_section);
}

function place_header() {
INCLUDE INCLUDE_PATH.'header.inc.php';
}

function place_menu($site_section) {
INCLUDE INCLUDE_PATH.'main_menu.inc.php';
}

function place_footer() {
INCLUDE INCLUDE_PATH.'footer.inc.php';
}

function place_copyright() {
echo "&copy;".date(Y).' '.ORG_NAME.'. All Rights Reserved';
}

function place_srlink() {
INCLUDE INCLUDE_PATH.'sr_link.inc.php';
}

function place_bottom() {
INCLUDE INCLUDE_PATH.'bottom.inc.php';
}
// Main Navigation List Generator

function menu_display($links, $site_section) {
   
foreach($links as $key=>$value) {
        $class = '';
        $id = '';
    if ($site_section == $value) {
          $class = ' class="active"';
          $id = ' id="current"'; }
  echo '<li' . $class . '><a' . $id . ' href="'.SITE_TOP_PATH.$key.'">'.ucfirst($value).'</a></li>'."\n";
    }
    }
?>
[/code]

page_top_content.inc.php
[code]

<body>
<div id="page_wrapper">

<?php 
# Place Header
place_header();
# Place Main Menu
place_menu($site_section);
?>

<div id="content_wrapper">
<div id="content">

[/code]

main_menu_inc.php
[code]
<div id="menu">
<ul id="navigation">
<?php

//This array defines the links and the site_section names for the links list created by the foreach

$links = array(''=>'home','blog/'=>'blog','about/'=>'about','contact/'=>'contact');

// Display the menu

menu_display($links, $site_section);
?>

</ul>
</div>
[/code]

I hope this all makes sense. This references thing also makes me wonder if the $omit_subcontent == true will trigger correctly as it is in the functions lib now as well.

Thanks for all the help now and in the future.

All the best,

Jay

Share this post


Link to post
Share on other sites
Okay, Ken and other readers. I sortof figured out the use of globals to expand the scope of variables into library functions and now everything seems to be working now. After reading more on php.net in the user examples something seems to have clicked and I have added the globals where needed. See changed functions.php below:

[code]
<?php


//This function controls the stylesheet display of either one_column or two.
function style_select() {
global $omit_subcontent;
if ($omit_subcontent == true)
{ echo '@import url('.SITE_TOP_PATH.'_styles/one_column.css);';
}
else { echo '';
}
}
//This function controls whether Subcontent bar is shown based one_column option

function subcontent_display() {
global $omit_subcontent;
if ($omit_subcontent == true) { echo ''; }
else {INCLUDE INCLUDE_PATH.'subcontent.inc.php'; };
}

// Template Include Functions

function place_site_name() {
echo TAGLINE." ".SITE_NAME;
}

function place_top_meta() {
global $page_title, $page_keywords, $page_description;
INCLUDE INCLUDE_PATH.'page_top_meta.inc.php';
}

function place_top_content() {
INCLUDE INCLUDE_PATH.'page_top_content.inc.php';
}
function place_site_path() {
echo SITE_TOP_PATH;
}
function place_top() {
place_top_meta();
place_top_content();
}

function place_header() {
INCLUDE INCLUDE_PATH.'header.inc.php';
}

function place_menu() {
global $site_section;
INCLUDE INCLUDE_PATH.'main_menu.inc.php';
}

function place_footer() {
INCLUDE INCLUDE_PATH.'footer.inc.php';
}

function place_copyright() {
echo "&copy;".date(Y).' '.ORG_NAME.'. All Rights Reserved';
}

function place_srlink() {
INCLUDE INCLUDE_PATH.'sr_link.inc.php';
}

function place_bottom() {
INCLUDE INCLUDE_PATH.'bottom.inc.php';
}
// Main Navigation List Generator

function menu_display($links) {
global $site_section;
foreach($links as $key=>$value) {
        $class = '';
        $id = '';
    if ($site_section == $value) {
          $class = ' class="active"';
          $id = ' id="current"'; }
  echo '<li' . $class . '><a' . $id . ' href="'.SITE_TOP_PATH.$key.'">'.ucfirst($value).'</a></li>'."\n";
    }
    }
?>
[/code]

Now I have learned that I have to call the global within the function before the operation. Phew. I am glad nobody had come to the rescue yet because I wouldn't have been able figure this out on my own.

Now the only issue is that I want ot make sure that I am not allowing security vulnerabilities with the use of the "global" keyword.

All the best,

Jay

Share this post


Link to post
Share on other sites

×

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.