Should PHP have namespace variables?

Heya,

I am the founder of Type-Safe PHP (http://tsphp.ch) and would like to have some PHP user feedback on a certain feature I am considering to add to TSPHP.

Variables defined at the namespace level (top level) of your PHP script are automatically global which might cause trouble when a certain global variable is used by several scripts ($i, $j are good candidates). Consider the following:

index.php

<?php namespace your\company; ?>
<html>
<body>
<?php
$newsList = DB::getNewsEntries();
for($i = 0; $i < count($newsList); ++$i){
   if(someCondition){
     $news = $newsList[$i];
     include 'news.php';
   }
}
?>
</body>
</html>

news.php

<?php namespace your\company\templates; ?>
<div><?php echo $news->getTitle(); ?> 
<!-- Further output -->
<?php
$links = $news->getLinks();
for($i = 0; $i < count($links); ++$i){
  $link = $links[$i];
  include 'link.php';
}
?>
</div>

Here the $i in news.php will conflict with the $i in index.php but you won’t notice it until you run your script and suddenly certain news are not shown or something similar strange happens.

Due to this scenario I came up with an idea. Why not introducing namespace level variables which are only available in the current namespace scope. Be aware, I am talking now about introducing it in TSPHP but of course, the same idea could be adopted by PHP as well (yet there it would mean a BC break).

For the above scenario it would mean that one can define somehow that only $news and $links are global (maybe with the global keyword) other variables in the namespace scope ($i, $newsList, and $links in this case) are only available in the namespace. To better illustrate what I mean an example:

index.php

<?php
namespace your\company;
  $a = 1; //only available in this namespace
  global $b = 2; //globally available
  include 'inc.php';
  echo $d; // output 3
}
?>

inc.php

<?php 
namespace your\company\templates;
echo $b; // output : 2
$c = 1; //only available in this namespace scope
global $d = 3; //globally available
?>

How does this idea sound to you?

Cheers,
Robert

like it was already in PHP in the idea of function scope? That instead of including news.php repeatedly you would call a function named getNews()?

Kind of yes. But without the need of functions (and function calls, which some people see as unnecessary performance penalty and prefer to use includes instead)
Using function calls instead is possible as well of course. Just a matter of taste what kind of programming style one prefers no? I do not really see much need for global variables anyway other than in the above scenario

Does it not replace one kind of scope-mistake with another?

It goes from “Oh I used $i in the outer loop… right” to “Oh, $i isnt what i thought it was anymore because i’m not in the namespace.”

In every other language with namespaces, variables scope is controlled by them. It would be nice if PHP followed suit, but I don’t think implementing that will be easy. In PHP variables are off on their own symbol table separate from constants, function names, class names and namespace names. My understanding was this was to help parsing speed back in the late 90’s. These days its not as useful.

Just be sure that I get you right. What would you expect of the following code:

<?php
namespace test{
  $a = 1;
}
namespace test{
  echo $a;
}
?>

would you expect that $a is known in the second namespace scope or not? Would it make a difference for you if the second namespace was in a different file?

I think it is an improvement because the difference would be that the user has more power over what will be leaked into the global scope with my idea in place. Somewhat like using private or protected for class properties. Wouldn’t you agree?

I see what you mean though, the user would need to change the way he/she thinks. That is certainly a drawback. Maybe it would be better to say it needs an additional modifier in order that variables are not global? Maybe something like the following:

<?php
namespace{
  private $a = 1; // only in this namespace scope
  protected $b = 2; //in all default namespace scopes
  $c = 3; //implicitly defined global
  public $d; //explicit defined global
}
namespace{
  echo $a; //would emit an error, $a was private
  echo $b; //that's fine, $b was defined protected
}
namespace a{
  echo $b; //would emit an error, only available in default namespace scopes
  echo $c; //that's fine
}
?>

What do you think?

I think that that point you’ve re-written classes.

What do you mean by that? That one should use classes if one want’s to achieve that? Wouldn’t be possible at the moment since PHP does not have an access modifier which defines that something can be accessed in the same namespace only (as internal in C#)

<?php
namespace{
  private $a = 1; // only in this namespace scope // You mean an Instance of this class. Right.
  protected $b = 2; //in all default namespace scopes // You mean a class member.
  $c = 3; //implicitly defined global //Unneeded, since you'd just reference it outside the class.
  public $d; //explicit defined global // Ditto.
}

Probably a misunderstanding. I meant the variables as such, there are not classes involved - I just used the analogy to class properties as argument why information hiding also makes sense in terms of global variables.

But my response to your analogy is that you seem to have effectively said with your proposal “Let’s make namespaces classes.” not that you can make an analogy to them, but that you can make a direct relation.

I see what you mean now. Behind the scene it could be implemented as a class I suppose but for the user it wouldn’t be a class. Anyway, I am more interested in the idea rather than implementation detail. I mean sure, the direct relation to classes seems beneficial to me since the user is already familiar with classes and thus understands the concept of private, protected and global namespace variables easily.

But back to my initial question, do you still think it is just another scope mistake considering that one could define variables as namespace scope private, as namespace protected and as namespace public (thus global)? And if so, where do you see problems?

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.