I have the following simple code:
$a = 'hello';
function myfunc() {
echo 'in myfunc';
}
class myclass {
function __construct() {
myfunc();
echo $a;
}
}
$m1 = new myclass();
The echo $a within the method gives an error as you would expect since $a is in the global scope and cannot be accessed from within the class without first declaring it as global. That is documented in the PHP manual.
The call to myfunc() does work and I don't understand why. It is also declared in the global scope but the method can access it without first declaring it as global. I can't seem to find anything in the PHP manual that explains why this works.
Maybe I've been doing PHP for too long and this is something so simple I've forgotten how it works. Any insight or a link to where in the PHP manual it says you can access a global function from within a class method would be appreciated.
thanks in advance.
Functions aren't scoped (except if you use namespaces). Only methods are in classes and variables everywhere.
It's supposed to work; everything is correct: you can call functions, once defined, from everywhere.
I'm not sure if this is a new thing for namespaces...
http://www.php.net/manual/en/language.namespaces.fallback.php
Blockquote
For functions and constants, PHP will fall back to global functions or constants if a namespaced function or constant does not exist.
Related
I have six functions that require a global variable. In an attempt to reduce redundancy, I wrote a new function that is triggered rather than triggering all six. This one function has a global $var that is required by the other functions.
So, it looks like this
function one_function_for_the_rest() {
global $importantVar;
functionOne();
functionTwo();
functionThree();
}
but the global variable is not being seen by the called functions. Am I doing this incorrectly, or is this a limitation I was not aware of?
You're not doing it correctly as the variable is defined when on_function_for... is called. An easier way for this would be just to have $importantVar; at the start of the code.
Or wrap your functions inside a class and put the variable inside the class.
e: so basically do : function myFunc($important) { stuff } and when calling the function do myFunc($importantVar)
example :
$asd = "lol";
class myclass {
public function lol($asd) {
echo $asd;
}
}
$obj = new myclass;
$obj->lol($asd);
You're not doing it correctly. Each function either needs to use the global scope identifier, like global $importantVar;, or have $importantVar passed as a parameter. Otherwise, the other functions don't have $importantVar in their respective scopes.
Simply calling a function from within one_function_for_the_rest does not tell that other function anything about global variables or variables used in one_function_for_the_rest. In technical terms, your function calls do not bring $importantVar into the respective scopes of functionOne, functionTwo, or functionThree.
PHP does not have the same scoping rules as most other languages have. That is the downside to not having to declare variables with var as in JavaScript or other similar constructs.
Basically in PHP, every function used is only available in that function. There are three exceptions:
The global keyword
The $this variable inside objects. This one is also "magic" as it's also available inside anonymous functions defined inside a class.
When declaring an anonymous functions you can bind variables to it using use.
I thought that the use of the static keyword in the declaration of a class function meant that you could call the function without an instance of the class using the scope resolution operator (::).
For example:
class Foo
{
public static function static_function() {
return 'x';
}
public function non_static_function() {
return 'y';
}
}
// to call static_function:
echo Foo::static_function();
// to call non_static_function:
$foo = new Foo();
echo $foo->non_static_function();
The PHP.net documentation on static seems to support this idea.
I came across some code yesterday that someone had wrote accessing class functions using the scope resolution operator that had NOT been defined with the static keyword. I was surprised and confused to see this worked.
Given my class defined above, Foo, it turns out you can actually do:
echo Foo::static_function();
echo Foo::non_static_function();
Resulting in output xy without generating any errors or warnings.
If you can access non-static class functions without the static keyword, what is the point in it?
Resulting in output xy without generating any errors or warnings.
No way. The error reporting must have been turned off on that environment. That would have definitely produced a Strict Standards warning notice.
I am having an unexpected issue with scope. The include documentation (also applies to require_once) says the required file should have access to all variable at the line it was required.
For some reason I am not able to access a class instantiated with global scope inside a function that was required in.
Would anyone know why? I am obviously missing something.
I got it working through a reference to $GLOBALS[], but I still want to know why it is not working.
UPDATE:
The error I am getting is:
Fatal error: Call to a member function isAdmin() on a non-object in <path>.php on <line>
Code:
$newClass = new myClass();
require_once("path to my file");
----- inside required file -----
function someFunction() {
$newClass->someMethod(); // gives fatal error. (see above).
}
Functions define a new scope, so inside a function you cannot access variables in the global scope.
Variable Scope
within user-defined functions a local
function scope is introduced. Any
variable used inside a function is by
default limited to the local function
scope
About included files, the manual states:
When a file is included, the code it
contains inherits the variable scope
of the line on which the include
occurs.
So if you include something in a function, the included file's scope will be that of the function's.
UPDATE: Looking at your code example edited into the question, global $newClass; as the first line of the function should make it working.
$newClass = new myClass();
require_once("path to my file");
----- inside required file -----
function someFunction() {
global $newClass;
$newClass->someMethod();
}
Be aware though that using global can quickly make your code more difficult to maintain. Don't rely on the global scope, you can pass the object to the function as a parameter, or use a Singleton/Registry class (some tend to argue against the latter, but depending on the case it can be a cleaner solution).
The included code doesn't have a scope different than the code surrounding it. For example:
function a() {
echo $b;
}
This will fail even if echo $b is in an included file. If you replace the above with:
function a() {
include 'file.php';
}
... and file.php contains:
echo $b;
... then it's the same thing as if you wrote:
function a() {
echo $b;
}
Think of it this way: whenever you use include / require, the contents of the included file is going to replace the include / require statement, just as if you removed the statement and pasted the contents of the file in its place.
It doesn't do anything else as far as scope is concerned.
I was wondering if there is a shorter, better or cleaner way to assign and use class variables in PHP, then through $this->instance_variable ?
class Bar {
# internal variables
var $foo = "Hello World";
public function foo() {
return $this->foo;
}
}
I am not very familiar with all PHP's variable scoping, but from what I understood at the official docs, you can either define them global, or access them trough $this->?
Is there a keyword to define them as instance variable, so they are accessible like Rubys #variable?
There's a few key assumptions your'e bringing from ruby that don't translate well into PHP.
The correct way to declare and use object properties (equivalent to Ruby's instance variables) in PHP is
class Foo
{
//accesible from inside this objects of this class,
//objects that have this class as an ancestor, and from
//outside the object
//var $bar; is equivalent. "var" is PHP 4 syntax,
//when everything was public
public $bar;
//accesible from inside this objects of this class,
//objects that have this class as an ancestor
protected $baz;
//accesible from inside this objects only
private $fiz;
protected function example()
{
echo $this->bar . "\n";
echo $this->baz . "\n";
echo $this->fiz . "\n";
}
}
PHP's OO syntax is based on the Java/C# view of the world. However, because every PHP page/script/program starts off in the global score, the $this pseudo reference to the local object is needed. Without it, you'd create a large degree of ambiguity around situations like this
//In main.php
$foo = "bar";
include('example.php');
//in example.php
class Example
{
public $foo="baz";
public function scopeIsHardLetsGoShopping()
{
global $foo;
echo $foo;
}
}
So, in the method should the $foo referenced be the object variable, or the global variable? If you say it should be the object variable, how do you access the global foo from a method? If you say it should be the global variable how do you access the local property after declaring a variable with the same name global?
Ruby and python gave scoping some thoughts at the onset of the language, so these problems can be avoided. PHP started as a quick way to hack in some c-code to process forms and output HTML. Because PHP makes reasonable efforts to be backwards compatible, you end up with quirky work arounds like $this.
Coming form Ruby it seems a little verbose, but it's a fundamental part of PHP.
PHP instance properties are accessed via the $this->variable operator internally, and public properties as $object->property.
You can access a class variable internally via self::$variable, which is similar to Ruby's class variables. Discussion of self:: vs. $this-> in PHP
In general, you will find PHP much more verbose than Ruby, not least in terms of characters required to reference a variable.
If you have an instance variable (like your $foo) the only way to access it is through $this->foo.
You could, if desperate, write something like $foo =& $this->foo; so you have a local reference to the same variable, but the only benefit is saving a few characters at the cost of added confusion.
I was explaining to a Java developer why his method call wasn't working. He just needed to add $this->method_name();
He then asked me, "Why do I need to add $this to the method when it's declared in the same class?"
I didn't really know how to answer. Maybe it's because PHP has a global namespace and it you need to explicitly tell it that the method you are looking for belongs to the current class? But then why doesn't PHP check the current class for the method BEFORE looking at the global namespace?
The problem would also be that if you declared a function foo() and a method foo(), php would have a hard time figuring out which you meant - consider this example:
<?php
function foo()
{
echo 'blah';
}
class bar
{
function foo()
{
echo 'bleh';
}
function bar()
{
// Here, foo() would be ambigious if $this-> wasn't needed.
}
}
?>
So basically you can say that PHP - because of its "non-100%-object-orientedness" (meaning that you can also have functions outside classes) - has this "feature" :)
If I have to guess: Because it was easier than the alternatives. Object oriented support in PHP has always been very much of a hack. I vaguely remember reading a discussion about the upcoming closure support that will appear in PHP 5.3. Appearently it was really, really hard to implement lexical closures in PHP due to it's scoping rules. Probably because you can nest a class in a function in another class and stuff like that. All that freedom possibly makes stuff like this incredibly hard.
This is not unusual. Python, Javascript, Perl (and others) all make you refer to a this or self when dealing with objects.
That's just how scope works in PHP. $obj->f() refers to $foo in the function scope. If you want to get the class property $obj->foo within f(), it's $this->foo.
global $foo;
$foo = 99;
class myclass
{
public $foo;
function f()
{
$this->foo = 12;
$foo = 7;
// $this->foo != $foo != $GLOBALS['foo']
}
}
$this refers to the calling object. The PHP docs have good examples and further details.
Seems PHP hasn't been properly OOPed. In Java and C++, references to the current object ('this') are implicit, ie no explicit mention is needed, leaving the code much cleaner.
Perhaps there is some reason this is difficult with PHP implementation ?