I try to use namespaces with included files:
<?php
namespace MyNamespace;
function foo() {
echo 'Test';
}
include( 'otherfile.php' );
?>
Inside otherfile.php is a <?php foo(); ?>; and I would like too see "Test" as output of it.
Is there any chance to realize that, without modifying that other file?
My wish: I would like to replace an existing file inside the code of an external library. I don't want to modify that code, since I expect to get further updates there.
No, it's not possible. You're defining the function MyNamespace\foo. The included file is calling the function foo. There's no way to change the meaning of what foo() refers to without altering the code in that file. If you want to replace the function foo, your only real hope is to define your own function foo (no namespace) and avoid loading the other implementation of that function. If not this, it's things like runkit, which you don't really want to have to resort to.
Related
I'm new to PHP, so for example if I have a parent file that include the 2 child files:
include_once('includes/child1.php');
include_once('includes/child2.php');
If child2.php have a class Test with a function test_function:
class Test
{
static function test_function() {
}
}
then can we access this test_function in child1.php like this?
public static function initialize() {
Test::test_function()
}
and if it can, why does it not produce an error since child1.php is included before child2.php(note: I'm coming from Javascript perspective)
No code in child1 or child2 is actually being called. You're just defining some classes and functions, but nothing is calling any of these functions. Test::test_function() is never ever being evaluated, hence it cannot throw any error.
In general: yes, order matters. Everything you're trying to call needs to be defined before you call it. In this case, you're not calling anything, hence it's irrelevant.
Each file should take care of its own dependencies. I.e., child1.php should include (or better: require) child2.php itself if its code depends on it. Don't put the burden of including dependencies on the eventual user of child1.php, this just makes things extremely complicated.
In fact, you should be using autoloading, which will include all necessary files just in time as needed without you having to worry about the complexities of multiple include statements.
You can think of the include family ( include_once, require, require_once ) as a cut and paste type operation. If you follow just envision php creating one big file, pasting the content from each include call ( in the top down order of execution ).
So you might have
index.php
includes.php
functions.php
And if you do this in index
include 'includes.php'
some_function();
And then in includes.php
include 'functions.php'
And then in functions php you have a function some_function(){} you can use this in the index file after the include, php will see it like this
include 'includes.php'
include 'functions.php'
some_function(){}
some_function();
In your example above you would not be able to call the class because you are calling it before including it. Like this
//include_once('includes/child1.php');
Test::test_function();
//include_once('includes/child2.php');
class Test
{
static function test_function() {
}
}
However that said I notice you defined a "method" around your call to Test::test_function() that method would need to be wrapped in a class to work, if that was the intended way then it depends when you instantiate that class, you must do that after the Test class is defined. So for that case we will assume that that method is in a class
class Test2{
public static function initialize() {
Test::test_function()
}
}
Now if you use this class back inside of the parent file or anywhere after the include of child2.php then it will work, so in the parent file if you do this.
include_once('includes/child1.php');
include_once('includes/child2.php');
Test2::initialize();
You would think of this as a big file like this
class Test2{
public static function initialize() {
Test::test_function()
}
}
class Test
{
static function test_function() {
}
}
Test2::initialize();
It should be fine. You just cant call it before it is defined. Make sense?
All that said, I would strongly suggest looking into a PSR autoloader, that is the standard way of including classes these days.
Here is a good post on the topic
http://www.sitepoint.com/autoloading-and-the-psr-0-standard/
Update explination
I'll try to make this as simple as I can. The way PHP works is it loads a file and parses the code, this basically means it just checks the formatting for syntax errors or typos and any new functions or class definitions ( it only registers the names of that new stuff and checks the syntax ). Once that is done and passes it starts to execute the code from top to bottom.
Now when including a file it can't parse it right away because it needs to execute the includes, which it does not do during the initial parsing. After it runs the include it parses the new chunk of code, and then continues executing that new code from top to bottom until the end of the included file at which point it returns to the original file and continues on from the include deceleration.
So while it seems different that you can run a function before defining it in the same file, but not in an included file, it is actually the same behavior. This is because it needs to execute the file to know the functions or code that is in it. So if you call the function before the include, PHP hasn't had a chance to even look in the file yet. Some of this is because you could put an include in an if statement and then PHP would not need to include the file.
What it doesn't do is, parse the file run all the includes and then run the code. I hope that clarified how the process flow works.
I have an index.php file that has 3 includes
<?php
require_once('mod.php');
$mod = new Mod();
require_once('start.php');
require_once('tools.php');
....some code....
?>
I need to be able to reference the $mod object inside the start.php and tools.php.
How do I pass that object to be referenced by those 2 other require files?
Basically the mod.php is a class that has an array list generated in its __construct(). I want to use that array list data inside the startup.php and tools.php file but not sure how to pass in the existing one without calling "new" inside both of those files separately which doesn't do what I need since it resets everything.
Thanks!
It looks like you're using require() calls not for dynamic functionality loading (get a class definition in), but as something like a function call. Don't. Avoid global variables like a plague.
Side note: Instead of worrying about doing the require() calls in the right order to get your classes defined, I'd encourage you to look at Autoload functionality in PHP 5. It allows you to define which classes are defined in which file, and load those files on-demand when the classes are requested.
First of all use some autoloader. Dozens of require on the top of the file are annoying and needless.
You don't have to pass any references to other files. require works like "copy-paste-execute" so $mod will be available in that file.
#index.php
$mod = new Mod();
include 'file.php';
#file.php
$mod->doSth(); // works file!
Your problem is probably variable scope. If you need to use $mod inside another object (the fact that its source (class) is in another file doesn't matter) pass reference to $mod as a constructor argument, pass it using a special setter ($obj->setMod($mod); $obj->doSth();) or use more complex but better solution like Dependency Injection Container (sample implementation).
Doing require (or require_once, include, or include_once), simply includes and evaluates the code. The variable scope is inherited from the point at which the code is imported.
As an example, using your code:
<?php // index.php
require_once('mod.php');
$mod = new Mod();
require_once('start.php');
And the include:
<?php // start.php
$mod->arrayList(); // $mod is the object created in index.php
The mod should be available in those other files...if you need it in a function or class, use the global keyword, like:
function test() {
global $mod;
print $mod->list;
}
I have a few files like below:
index.php:
require_once("foo.php");
require_once("bar.php");
foo.php:
class foo {
function1() {
}
}
bar.php:
class bar {
?????
}
My question is, is there any way of accessing function1 from the foo class in the bar class, without having to include the foo.php file in the bar.php file, as it has already been loaded in index.php?
Thanks in advance
When including a file, in PHP, you are not including anything into the current file, but into the current execution
Once a file has been included, it's content is known by the PHP interpreter -- and will remain known until the end of the execution of the current script.
It's a bit like copy-pasting : with your current index.php file, it's like if you had taken the code from foo.php and bar.php and copy-pasted into index.php.
So, yes, once foo.php has been loaded once, you can access what's defined by it from bar.php -- even if those two are included by index.php.
(What you means by access is a bit vague, though : you'll have to declare some methods as static, or instanciate the foo class, ... But all that will be possible from inside the body on a method declared in bar)
As a sidenote : you should be careful with your file inclusions : if you include twice a file that declares a class, for example, you'll get a fatal error, because it's forbidden to define two classes with the same name.
Remember the copy-pasting idea I wrote about earlier ? Includind a file twice, even from two distinct files, is like copy-pasting the same code twice...
To avoid that problem, we often use include_once which, as its name indicates, makes sure that a given file can only be included only once.
If foo.php has already been loaded, then the real question to ask yourself is, "Am I accessing function1() in a static or instance manner?"
If function1() is a static function (which in your example, is not):
class bar{
function function2(){
return foo::function1();
}
}
Otherwise, you will have to instantiate an instance of foo, making it a local- or class-scope variable, e.g.
class bar{
/*
* #var foo
*/
private $foo;
function __construct(){
$this->foo = new foo();
}
function function2(){
return $this->foo->function1();
}
}
Read this too: http://php.net/manual/en/language.oop5.static.php
By the way, like what Pascal MARTIN has explained, you do not need to do another include(), but usually for a large application, you will prefer auto-class-loading.
You should try to move away from including files manually, and instead work towards a solution where you can use autoloading.
Autoloading will allow you to lazy load, or only load the files that you need in each request - rather than making a spider web of included files.
You can do this either with __autoload or spl_autoload, read more on the subject here: http://php.net/manual/en/language.oop5.autoload.php
Small example of autoload below:
function __autoload($class_name) {
require_once $class_name . '.php';
}
$obj = new MyClass1();
$obj2 = new MyClass2();
Using autoloading php can automatically try to load files when a class is not found, in this example there is no reason to include the class files for MyClass1 or MyClass2, php falls back to the __autoload function if it cannot find definitions for them.
Using this will mean you dont have to include either foo or bar in your examples, nor include them in index.php
You could do it statically, though there are limitations and this is an atrocious practice, since that function isn't actually static.
foo::function1();
The better approach would be to have the class bar take foo as a parameter. Depending on the uses, this could be done in the constructor or the particular method.
i want to have a class that includes all files for me.
eg.
Loader::loadZend // loads all zend libraries
Loader::loadSymfony // loads all symfony components
if i include a file in a method, does this become globally available?
it seems that it doesnt work.
maybe i have done something wrong, or is there a workaround for this?
thanks
From http://uk.php.net/manual/en/function.include.php (emphasis mine)
When a file is included, the code it contains inherits the variable scope of the line on which the include occurs. Any variables available at that line in the calling file will be available within the called file, from that point forward. However, all functions and classes defined in the included file have the global scope.
Having a loader that loads all classes of Zend, Symfony or whatever at once is a bad idea. Both have their own autoloader, so all you need to do is make the libraries available on the include path and then spl_autoload_register the framework's own autoloader.
If no global scope variables are defined, you should be fine. Otherwise, the globals will be lost.
For example,
a.php:
<?php
$a = "global a";
class c {
public $b = "member b";
}
?>
b.php
<?php
function inc() {
include 'a.php';
}
inc();
echo $a;
$class = new c;
echo $class->b;
?>
If you run b.php, you will find out $a is gone and class c or any function will still be available.
If you just include a class inside another class it is only available in the class you inserted the include.
So the solution is to create an autoloader that automaticly includes the classes needed on demmand. Here you have the info you need:
http://php.net/manual/es/language.oop5.autoload.php
It is basic programming for PHP5 OOP.
EDIT
Seeing your inquiry about a file. Neither. The file (to be processed via php functions) will only be available inside the function where it is called/used for, not globally in the whole application / website.
from my understanding, require pastes code into the calling php file.
what if you were requiring from inside a method...it would paste the entire code/class inside the method, blocking the next statement in the method.
eg.
function test() {
require 'pathtosomeclasscode';
somestatement; // any code after the require is blocked.
}
how do i get around this, to be able to require code where-ever, without it being pasted in that exact spot?
Somewhat surprisingly, this appears to work just fine. The included code will execute inside the scope of Baz::bork() -- but the the code simply defines a class, and classes are global. So you end up with a defined class.
File: Foo.php:
<?PHP
class Foo{
function bar(){
echo "Hello from Foo::bar()!\n";
}
}
File: Baz.php:
<?PHP
class Baz{
function bork(){
require_once "Foo.php";
$f = new Foo();
$f->bar();
}
}
echo "testing internal definition:\n";
$b = new Baz();
$b->bork();
echo "\ntesting in global scope:\n";
$f = new Foo();
$f->bar();
echo "\nall done\n";
Output:
$ php Baz.php
testing internal definition:
Hello from Foo::bar()!
testing in global scope:
Hello from Foo::bar()!
all done
Now, I can't think of many places where you'd want to do things this way. People typically require_once() any possible dependencies at the top of their class file, outside of the class definition.
Calling require, require_once, include or include_once will not stop the execution of code within your function unless there is a problem with the included script. The code within the included file is executed in the same scope as the function (with defined functions and classes being global), not inserted into it, replacing what else is there.
The other answers recommend using one of alternatives to require as a solution -- these solutions may work for you if the error in your scripts is to do with a conflict in naming (i.e. an attempt at redefining a class or function), otherwise you may wish to give us more details of what has occurred (or not occurred) to make you think that there is a problem so that we can help you solve the real cause.
On a further note, these file inclusion methods do not paste code into your script. Pasting is a tool that people use to maintain text. I suggest that you read the PHP manual to try and further your understanding of how these functions work:
require
require_once
include
include_once
Post again if you've got further questions on their working after looking into them.
try require_once? Just incase your including it elsewhere.
If you use include_once('script.php') you won't run into errors about classes being redeclared.
I haven't tried the following myself, but I'm thinking this setup might also work if you don't want to include_once() redundantly:
class Whatever {
protected $classObject;
public function __construct( /*...*/ ) {
include('anotherClass.php');
$this->classObject = new anotherClass();
}
public function someFunction( /*...*/ ) {
$this->classObject->classObjectFunction();
}
public function anotherFunction( /*...*/ ) {
$this->classObject->classObjectFunction();
}
}
You could then call the following code which would each call a function in the same shared class object:
$Whatever = new Whatever();
$Whatever->someFunction();
$Whatever->anotherFunction();
I think what you're saying is that you don't want the code to execute right away. If that is correcty, you have several options:
You can move the require.
You can also read the file using fopen(), then parse it. (You can't call eval because it won't understand the HTML, but you can do it with a parser)
As I see, you're using external files for loading classes, am I correct? Why don't you use Autoloading Classes. I know it won't work when you want to load different class bodies in different circumstances, but I really don't know if it's a good practice.