user2587741
user2587741

Reputation: 199

Nested functions, variables - PHP

function partners($atts ) {
    extract(shortcode_atts(array(  
            'ids' => null,
            'extra_options' => 'something' <----------------- in wordpress I can read this value using local $extra_options 
    ), $atts));  
global $extra_options; <----------------- trying to change local var to global

function print_partners_scripts() {
    global $extra_options; <----------------- reading above variable
    echo '<script type="text/javascript">' . "\n";
    echo 'jQuery(document).ready( function() {'. "\n";
    echo '  $(".partners-slider").bxSlider({
        slideWidth: 924,
        auto: 0,
        autoStart: 0,
        moveSlides: 1,
        minSlides: 3,
        maxSlides: 8,
        pager: false,
        controls: false,
        slideMargin: 5,
        ' . $extra_options . ' <----------------- var is empty
     });' . "\n";
    echo '});' . "\n";
    echo '</script>' . "\n";
} 
    add_action( 'wp_footer', 'print_partners_scripts' );

    $ids = explode( ',', $ids );
    $output = '<div class="ps-wrap"><div class="partners-slider">';
    foreach($ids as $id) {    
    $img_attr = wp_get_attachment_image_src( $id, 'full' );
    $output .= '<div class="pslide"><img src="' . $img_attr[0] . '" /></div>';    
}
    $output .= '</div></div>';

    return $output;  
}  

Hi, I'm trying to read var $extra_options inside print_partners_scripts(). The variable is set in the partners() function. I've tried to make it global and simply use it in certain place but I guess I'm doing something wrong ;)

Thanks in advance !

Upvotes: 0

Views: 1352

Answers (2)

IMSoP
IMSoP

Reputation: 97648

Firstly, PHP doesn't support nested functions in the way you are trying to use them.

You can write this:

function outer() { function inner() {} }
outer();

But all that happens is that when outer(); is executed, the inner() function is declared as a normal function. So the code is exactly the same as this:

function outer() {}
function inner() {}
outer();

Secondly, variables in PHP (unless prefixed, with a class or object name) are always scoped to the current function. The global keyword imports a reference to a global variable into the current function's scope; it cannot be used to export a variable which was already defined.

It is generally best to only use the global keyword at the very beginning of a function, to import all the global variables needed by that function. Even better, do not use global variables, since they lead to "spaghetti code" which is hard to understand and debug.

If you declare the variable global before running extract, this will work, but I would strongly advise against using either feature.

function foo_with_too_much_magic()
{
    // Import global variable. Very hard to track where this came from.
    global $some_var;
    // Let's assume this array comes from somewhere and isn't hard-coded
    $some_array = array('some_var' => 'some_value');
    // Export variables from an array. This is like telling PHP to write different code each time it runs, with different variable names.
    extract( $some_array );
}
foo_with_too_much_magic();
var_dump($some_var);

Here is a version of the above without the discouraged features:

function foo_with_no_magic()
{
    // Let's assume this array comes from somewhere and isn't hard-coded
    $some_array = array('some_var' => 'some_value');
    // You know which variable you want, so don't need the magic "export"
    // Note that you don't have to call it $some_var
    $some_var = $some_array['some_var'];

    // Now you have the variable, you can manipulate it, pass it to another function, or return it
    // In fact, you could also return $some_array['some_var'] directly, without the extra assignment
    return $some_var;
}

// This variable name no longer needs to be the same as what was used in the foo_with_no_magic() function
$some_var = foo_with_no_magic();
var_dump($some_var);

Upvotes: 1

AJames
AJames

Reputation: 64

Here is an example of putting the code into a class format which the direction I would go FYI, it may be useful to learn a bit more of the OOP practices for PHP (http://php.net/manual/en/language.oop5.php):

#1) Get the data you wish to pass into your function.
$data = "TEST";  
get_partners($data);

#2) Call your function.
function get_partners($atts) {
    //Extract using ($att) passed in from your call.
    //The shortcode_atts function should be accessible by the file containing this function.
    extract(shortcode_atts(array(
    'ids' => null,
    'extra_options' => 'something' //in wordpress I can read this value using local $extra_options
    ), $atts));
    //Create a new class element that will build your data for your and allow you to pass in your variable on the fly.
    $p = new partners();
    $p->extra_options= $atts; //Pass the variable here.
    $p->print_partners_scripts();
}

#3) Define Class here.
class partners {
    var $extra_options;

    public function print_partners_scripts()
    {
        $output = '<script type="text/javascript">' . "\n";
        $output .= 'jQuery(document).ready( function() {'. "\n";
        $output .= '  $(".partners-slider").bxSlider({
        slideWidth: 924,
        auto: 0,
        autoStart: 0,
        moveSlides: 1,
        minSlides: 3,
        maxSlides: 8,
        pager: false,
        controls: false,
        slideMargin: 5,
        ' . $this->extra_options . '
        });' . "\n";
        $output .= '});' . "\n";
        $output .= '</script>' . "\n";            
        $output .= $this->additional_data();
        echo $output;
    }

    protected function additional_data()
    {
        add_action( 'wp_footer', 'print_partners_scripts' );
        $ids; #Where is this defined?
        $ids = explode( ',', $ids );
        $output = '<div class="ps-wrap"><div class="partners-slider">';

        foreach($ids as $id)
        {
            $img_attr = wp_get_attachment_image_src( $id, 'full' );
            $output .= '<div class="pslide"><img src="' . $img_attr[0] . '" /></div>';
        }

        $output .= '</div></div>';
        return $output;
    }
}

Upvotes: 0

Related Questions