Page 1 of 1
How do we keep the namespace clean with multiple PHP files?
Posted: Sat Dec 17, 2005 2:59 pm
by BlindMan
PHP seems to have serious namespace issues when scripts are broken into multiple files. For instance, if I have an HTML file that needs to run functions or read variables from a PHP file, I can’t treat the PHP file as a class with member functions/variables. I have to run the PHP files and then make assumptions about the names of the functions/variables (as globals). What’s more, PHP doesn’t seem to object if globals are overwritten by other PHP files.
Am I missing something here (I'm very newbie)?
Posted: Sun Dec 18, 2005 12:39 am
by Jenk
If I read that right.. you are saving a class (for example MyClass) in the file MyClass.php then trying to call the class without including it? ala Java - PHP does not do this, you must use
require/
include functions to use the file (and it's contents as PHP script)
And are you also using the
Variable Scope incorrectly?
PHP is a scripting language that has aspects of OOP. You must "gather" all the relevant bits of PHP script that you need as at run time to form a big script in memory. So all your class definitions, function definitions etc. need to be included before you can use them.
As for the globals problem.. well, using global $var; in a class can be problematic if you are not careful with the naming of said variables/properties. An example for a weak name:
Code: Select all
class MyClass
{
function MyClass ()
{
global $result; // contains .. oh I dunno, a setting for the format of a result.
//do something with $result;
}
}
$result = mysql_query("SELECT * FROM `table`");
MyClass::MyClass(); //error - $result no longer contains the value of the setting.
A better example:
Code: Select all
class MyClass
{
function MyClass ()
{
global $MyClassResultFormat; // contains .. oh I dunno, a setting for the format of a result.
//do something with $MyClassResultFormat;
}
}
$result = mysql_query("SELECT * FROM `table`");
MyClass::MyClass(); //no error - $MyClassResultFormat is not likely to be used by coincidence.
or even better, use a constant so that even if done by coincidence, you or future developers will know immediately by means of a "constant already defined" error.
Sorry if this is not what you refer to.. I don't fully understand what you mean.
Re: How do we keep the namespace clean with multiple PHP fil
Posted: Sun Dec 18, 2005 12:03 pm
by Chris Corbyn
Just to back Jenk up since I read what you've said the same way Jenk has.
BlindMan wrote:PHP seems to have serious namespace issues when scripts are broken into multiple files. For instance, if I have an HTML file that needs to run functions or read variables from a PHP file, I can’t treat the PHP file as a class with member functions/variables. I have to run the PHP files and then make assumptions about the names of the functions/variables (as globals).
This is how PHP works yes... it's not like C or Java, the contents of the files are pulled into the scripts inline.
BlindMan wrote:What’s more, PHP doesn’t seem to object if globals are overwritten by other PHP files.
Am I missing something here (I'm very newbie)?
Correct, that's why it's *usually* ideal to minimize globals as much as possible by factorising into many classes etc. As Jenk says, constants will error if you try to overwrite. You can use define() for globally accessible constants, or the "const" keyword for static constants in PHP5 OOP.
If you really want to prevent overriding your globals you can always do some checking before you assign values to them too.
Posted: Sun Dec 18, 2005 5:26 pm
by BlindMan
I believe I found a solution, but first let me clarify the problem...
I do understand that files are run in-line and that's how you get data/function definitions from other files.
The problem is that the code in one file must make assumptions about the names of variables/functions in order to use code in other files, and I thought that these assumptions applied to the global namespace. In the example provided, “MyClassResultFormat” is a good name because it ‘seems unique enough’ to prevent a namespace collision. I dislike situations like this where there’s nothing to protect us but convention—especially when global variables can be overwritten by subsequently included PHP files.
Solution...?
If we include a PHP file from within the scope of a function, and the variables within the file are not “global”, these variable will not affect any of the global variables of our main file (protects our global namespace).
For Example...
Code: Select all
<!-- File: PersonIndex.html -->
<?php
$person = new Person("foo");
// if we wrap the 'include' with a function, we prevent the included file
// from affecting the global variables ('$person')
function LoadPerson1()
{
include("Person1.php");
return $person;
}
function LoadPerson2()
{
include("Person2.php");
return $person;
}
$person1 = LoadPerson1();
$person2 = LoadPerson2();
// $person is still "foo"
?>
<!-- File: Person1.html -->
<?php
$person = new Person("one");
?>
<!-- File: Person2.html -->
<?php
$person = new Person("two");
?>
Given this solution, it seems that PHP files should interface with each other through variables, not functions, when possible. Function names have only one, global namespace.
Posted: Sun Dec 18, 2005 5:30 pm
by BlindMan
BTW, thanks for the feedback guys.

Posted: Mon Dec 19, 2005 4:52 am
by Maugrim_The_Reaper
IMO - not sure what the above was intended to accomplish (besides confusing me

). The repitition in your script suggests there's a better solution... But hey, if it works...

Posted: Mon Dec 19, 2005 9:41 pm
by Jenk
In your given example, the seperation of files is not necessary, it can be condensed to:
Code: Select all
<?php
$person = new Person("foo");
$person1 = new Person("one");
$person2 = new Person("two");
?>
I know it's only an example, but maybe this is an indication of where you might be doing things wrong and not need to execute the instantiation of an object in a serperate file like that.
(also, a pedantic and worthless point, you have include("person1/2.php"); but have <!-- File person1/2.html --> :p)
BTW, this next suggestion I am not sure about, but try returning $person by reference, I know PHP now does this "by default" but it's worth a try..
Code: Select all
<?php
function & LoadPerson1 () {
include("person1.php");
return $person;
}
$person1 =& LoadPerson1();
?>
It's also probably not a good idea to contain class definitions or object instantiations inside a function. Don't quote me on it though.