5

This more a question about the why then 'how-to', yet it has been annoying me for some days now. Currently I am doing some work with CodeIgniter and going back to PHP temporarily from Ruby, bugs me about the following scoping magic.

<?php $query = $this->db->get('articles', 2);
        if ($query->num_rows() > 0)
        {
           foreach ($query->result_array() as $row)
           {
              $data[] = $row; # <-- first appearance here
           }
        return $data; # <--- :S what?!
        } 

As you can see, I am not exactly a PHP guru, yet the idea of local scope bugs me that outside the foreach loop the variable is 'available'. So I tried this out inside a view:

<?php

    if($a==1)
    {
    $b = 2;
    }
    echo $b;
?>

Which result in an error message:

Message: Undefined variable: b

The PHP manual tells about the local scoping, yet I am still wondering why this happens and if there are special rules I do not know about. And it scares me :)

Thanks for sharing ideas,

Pacerier
  • 86,231
  • 106
  • 366
  • 634
Shyam
  • 2,357
  • 8
  • 32
  • 44
  • 3
    You create the variable in your second example only if $a is 1. Since $a doesn't exist (PHP actually raises an error here), $b won't be created. In the first example, all the conditions have been met so $data is created and used as return value. – Michael J.V. Apr 21 '11 at 11:21
  • The second example is more a clarification/oversimplification that $b outside the curly braces is accessible - as other answers state out, curly braces do not define the scope of variables. And that, I didn't knew :) – Shyam Apr 21 '11 at 12:30
  • I think this is outdated now, or a matter of STRICTness perhaps. Your second example works for me and prints 2. I am working with 5.4.16 with STRICT off – Dennis Feb 18 '14 at 18:18
  • @Dennis, It doesn't work. You think it works because Shyam has corrected the code that all of the other guys had been talking about. I've made a rollback so that everyone is on the same page. – Pacerier Sep 02 '15 at 06:35
  • Also see http://stackoverflow.com/a/14971155/632951 – Pacerier Sep 02 '15 at 07:08
  • and if you want to create a local scope http://stackoverflow.com/a/33460057/3160597 – azerafati Nov 01 '15 at 07:19

6 Answers6

12

Only functions create a new local scope. Curly braces by themselves do not. Curly braces are just an auxillary construct for other language structures (if, while or foreach).

And whereever you access any variable in a local scope doesn't matter. The local scope is an implicit dictionary behind the scenes (see get_defined_vars). You might get a debug notice by accessing previously undefined variables, but that's about it.

In your specific example it seems, you are even just operating in the global scope.

mario
  • 144,265
  • 20
  • 237
  • 291
  • 1
    That first sentence makes understand it crystal clear! Thanks! – Shyam Apr 21 '11 at 12:20
  • Cool. There is also a formal language semantics term for that, but I can't remember. :/ – mario Apr 21 '11 at 12:23
  • @mario, [Citation needed](http://xkcd.com/285) for "*Curly braces are just an **auxillary construct** for other language structures*".... – Pacerier Sep 02 '15 at 06:32
7

foreach does not create any variable scope in PHP so it is natural if variable is available outside foreach

for the second question the $a is not equal to the 1 hence $b is not initialized and throw notice when you access outside. If you assign value 1 to $a and test it you will wonder the notices will gone.

Here is nothing like scope.

Shakti Singh
  • 84,385
  • 21
  • 134
  • 153
  • The second example is not a question, more like a perspective as I would expect behavior (my inexperience with the PHP language). As other answers state out, that curly braces do not define the variable scope. Even though, thanks for your answer :) – Shyam Apr 21 '11 at 12:26
3

See: http://php.net/manual/en/language.variables.scope.php

In php curly braces don't necessarily define a new scope for variables. (your first example)

In your 2nd example, $b is only set on a specific condition. So it is possible to be 'undefined' if this condition is not met.

Yoshi
  • 54,081
  • 14
  • 89
  • 103
1

Shyam, you are using a scripting language, not C++. It is typical for scripting languages like PHP or JavaScript not to have different scopes for each code block. Instead there is one scope for the whole function. This is actually quite handy if you consider your first example, but you obviously need to be careful as can be seen in your second one.

NikiC
  • 100,734
  • 37
  • 191
  • 225
  • 1
    It's good design for PL to include scoping mechanisms (besides the ugly `call_user_func(function(){ })`). Why is it "typical for scripting languages not to have different scopes for each code block"? – Pacerier Sep 02 '15 at 08:38
1

is $a equals to 1? If not $b=2 will never be evaluated!

ufucuk
  • 475
  • 9
  • 21
1

Actually your first method should be giving you an error too.

You're using a variable that hasn't been declared as an array. I can't understand why you didn't get an error for that.

PHP doesn't have block scope, so whether it's inside IF or FOREACH is irrelevant. If it's available inside the method, you can use it inside the method.

JohnP
  • 49,507
  • 13
  • 108
  • 140