Can you pass values to included files in PHP without using globals?
A pattern I tend to use often in PHP is setting a few globals (such as $page
, $user
, $db
, etc), and then including a file which uses those globals. I've never liked the idea of using globals for this, though, so I'm looking for a better way.
The obvious solution is to define a class or function in the subfile, and call it after the file is included. There are cases where that can't work though, such as this:
// Add entries to a URI table from each section of the site
global $router;
$router = new VirtualFileSystem();
$sections = array('store', 'forum', 'blog');
foreach($sections as $section)
include dirname(__FILE__) . $section . '/routing.php';
// Example contents of 'forum/routing.php'
// implicitly receive $router from caller
$router->add('fourm/topic/', 'topi开发者_Go百科c.php');
$router->add('forum/topic/new/', 'new_topic.php');
// etc
If I tried to wrap each routing.php
in a function and call them each with $router
as an argument, the same function name would clash after being defined in multiple files.
I'm out of ideas. Is there a better way to pass variables to included files without polluting the global namespace?
include
and its siblings are basically just copy-paste helpers, and the code inside them shares scope with the calling block - as if you'd copy & paste it just where the include
statement is. The sane way of using them is to think of them the same way you'd use #include
in C or using
in C# or import
in Java: import some code to be referenced later on. If you have code in the included file that needs parameters, then wrap it in a function, put the parameters in the function arguments, use include_once
at the top of the including file, and call the function with the parameters you want, wherever you need to. No globals required. As a rule of thumb, in regular operation, putting any code that "does" something (executes statements in the global scope) in an included file is best avoided IMO.
No, there is not. You're not passing variables to included files anyway. The code that is included behaves as if it was written where the include
statement is written. As such, you're not passing variables into the included file, the code in the file can simply use the variables that are in scope wherever the include
statement is located.
In your case the contents of forum/routing.php
are not really standalone code, they're code snippets that depend on a very specifically set up scope to function correctly. That's bad. You should write your includable files in a way that does not couple them to the including code. For example, you could make your Router a static class and call it statically in forum/routing.php
:
require_once 'virtual_file_system.class.php';
VirtualFileSystem::add('forum/topic/', 'topic.php');
As long as there is a class VirtualFileSystem
in your app, this will work, and won't pollute the namespace any more than it already is anyway.
just isolate includes in a function:
function add_entries_to_router($router, $sections) {
foreach($sections as $section)
include dirname(__FILE__) . $section . '/routing.php';
}
$router = new VirtualFileSystem();
add_entries_to_router($router, array('store', 'forum', 'blog'));
You can try an OOP way by making a Configuration class as a singleton and retrieving it when you need it.
You could define magic methods for __get and __set to add them to an private array var and make the constructor private.
I usually define as constant only the path to my src project in order to load class files quickly and properly (and use some SPL too).
But I agree with @tdammers about the fact that an include keep the environment variables like if you were on the caller file (the one who makes the include).
精彩评论