0

The other day I was given this huge set of arrays and told to make a HTML page with a bunch or selects/radio buttons so I wrote some simple functions to simplify things.

This is my function to generate very large HTML selects.

function genSelect($name) {
    $selectReturn = '<select name="'.$name.'">';
        foreach(${$name} as $value=>$text){
            $selectReturn .= '<option value="'.$value.'"';
            if($evalThis->loaded_settings[$name]['value']==$value)
                $selectReturn .= ' SELECTED ';
            $selectReturn .= '>'.$text.'</option>';
        }
    $selectReturn .= '</select>';
return $selectReturn;
}

This doesn't seem to work because ${$name} simply does not call anything / work like I expect it too. I already have a work around where I just pass the array though the function call but its been bugging me what I was doing wrong with the variable variables in this code.

Edit: To give some context this is being loaded in a joomla view to build the giant UI for entering in settings. This function is in a lib file and is loaded with a require_once along side another file containing all the arrays I use. The database holds only the current values of these settings and the arrays contain all the possible options for the various selects/radio/dropdown menus and are centralized in a separate file for language/translation reasons.

Clarifying some questions people asked, $name simply contains the name of the array used and also the name of the HTML select/radio/checkbox input. $evalThis is a array containing the values the database currently has.

3
  • can you give an example of what the data in $name looks like? Commented Jan 3, 2012 at 22:35
  • 1
    I just have to ask: what does $evalThis do? It sounds kinda evil. Commented Jan 3, 2012 at 22:38
  • Try this: $evalThis = new stdClass(); $evalThis->loaded_settings = array('abc' => array('value' => 1)); Commented Jan 3, 2012 at 22:49

2 Answers 2

1

it seems an array with name stored in $name is defined in global context, not in this function.

$somearr = array('x', 'y');
function genSelect($name) {
    $selectReturn = '<select name="'.$name.'">';

    foreach(${$name} as $value=>$text){
        $selectReturn .= '<option value="'.$value.'"';
        if($evalThis->loaded_settings[$name]['value']==$value)
            $selectReturn .= ' SELECTED ';
        $selectReturn .= '>'.$text.'</option>';
    }

    $selectReturn .= '</select>';
    return $selectReturn;
}
echo genSelect('somearr'); //doesnt work, somearr is global


$somearr = array('x', 'y');
function genSelect($name) {
    global $somearr;
    $selectReturn = '<select name="'.$name.'">';

    foreach(${$name} as $value=>$text){
        $selectReturn .= '<option value="'.$value.'"';
        if($evalThis->loaded_settings[$name]['value']==$value)
            $selectReturn .= ' SELECTED ';
        $selectReturn .= '>'.$text.'</option>';
    }

    $selectReturn .= '</select>';
    return $selectReturn;
}
echo genSelect('somearr'); //works, note 'global $somearr' line at the beginning of genSelect

Generally it is quite bad design to use variable names of functions/arrays when it is not necessary/at least justified. If I were you I would just rewrite the method to

function genSelect($array, $name) { ... }

echo genSelect($someArr, 'someArr');

It may seem like duplication of typying, but it's better to not have your methods depend on global scope. Btw, your $evalThis var is also out of function scope.

Sign up to request clarification or add additional context in comments.

3 Comments

Use the PHP DOM for creating HTML with PHP!
Forgive me if this is a stupid question I'm still new to PHP. Would that mean ${$name} would work if the require_once that loaded the file containing all the arrays was moved inside the function from its current location, directly above the require_once that loads the file containing this function?
I'm not sure which code you are referring to, but if you do a require_once from within a function, then anything that has 'global' scope in the included file will be in function scope. It is not recommended though to include from within a function; instead include functions and call them when needed. Also note that require_once (or include_once) will not do anything if the same file has already been included before, even in a different scope.
1

The problem is that ${$name} is not defined inside the function's scope. You would need to either reference the global variable like this:

$GLOBALS[$name]  // bad

Or add this at the top of the function:

global ${$name};  // worse

WARNING: This is horrible. Don't do it :-) I advise simply passing the array like you mentioned before.

3 Comments

First answer who gets it right (at least about the global part). haven't verified your answer though :)
If using globals is the chosen solution (one would hope not), you could also use $GLOBALS[$name] directly instead of defining ${$name} global first.
@Bart: You're absolutely correct. I'll modify my answer to reflect this. Thank you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.