0
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 !

4
  • Do you define a function (print_partners_scripts) inside another function (partners)? Why?! Do you actually call print_partners_scripts() anywhere? And do you call partners() first? Commented Oct 2, 2013 at 18:05
  • 1
    The use of globals is deprecated. You should either pass the information into the function or use a session to store the data. Commented Oct 2, 2013 at 18:05
  • 3
    @JacobS You got an official source for that claim? Globals is discouraged but not deprecated afaik. Commented Oct 2, 2013 at 18:07
  • 1
    @OIS -- Fair enough, I amend my comment to read "The use of globals is highly discouraged.". Commented Oct 2, 2013 at 18:12

2 Answers 2

1

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);
Sign up to request clarification or add additional context in comments.

2 Comments

"If you declare the variable global before running export, this will work, but I would strongly advise against using either feature." Worked ;) Thank you for you time and valuable advices !
@user2587741 I added that to the answer to explain why it was failing, but please don't write code like that! I've added an example to the answer of how to write the code without relying on the magic of export and global.
0

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;
    }
}

3 Comments

OOP may be beneficial (although it may be over-kill here), but this uses some pretty bad practices of its own: the get_partners function should be inside the class, possibly as a static function; it's still using extract unnecessarily; var should be replaced with public; and function names should generally be verbs, so additional_data should be get_additional_data, or preferably something more descriptive. Oh, and by "class element", I think you mean "instance".
In this example the get_partners function would not be inside the class/instance as it is the function that creates the class/instance. Although it is true that some of its logic could be moved into the class/instances itself. Are you suggesting that the class be created outside of a function?
That's why I suggested it be a static function, so you could run Partners::get_partners($data). Or it could be the constructor of the class, so that you would run $partners = new Partners($data); $partners->print_partners_scripts();. Chances are, this would be inside some other function anyway, containing all the function calls needed on the page.

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.