Scope of variables with a function within a function? - php

In Python you can have the following:
def foo(param1, param2):
def bar():
print param1 + param2
bar()
I am having some difficulties with this behaviour in PHP though.
I expect this to work in the following way:
function foo($param1, $param2)
{
function bar()
{
echo $param1 + $param2;
}
bar();
}
But that fails. So I read some about closures (this is called a closure is it not? It is in Python, that I know). And in the php documentation about anonymous functions (which they said to have been implemented as closures) they tell you to use the use() expression in the following manner:
function foo($param1, $param2)
{
function bar() use($param1, $param2)
{
echo $param1 + $param2;
}
bar();
}
But that still fails. So I changed it to the PHP-anonymous function a-like like this:
function foo($param1, $param2)
{
$bar = function() use($param1, $param2)
{
echo $param1 + $param2;
};
$bar();
}
That does work, however it just looks really ugly. Am I missing something? Can I improve this in any way? Or will I just have to use the 'ugly' way?
(I am not looking for a discussion about if closures are useful)

I couldn't find the function bar() use($param1, $param2) syntax on the manual page you linked to, just the "ugly" version that works (which is truly anonymous). I guess you'll have to use that.
On your second example, bar is not a closure. To create a closure in PHP you have to use the ugly use, or the Closure class. Every function will create its own local scope, but closures are not automatic.
PHP seems to have an odd definition for the term "closure", as you probably noted when you read the manual. They define it as a synonym for "anonymous function":
Anonymous functions, also known as closures (...)
Confusing, right? Later, they explain you need the use keyword if you want to inherit the parent scope:
Closures may also inherit variables from the parent scope. Any such variables must be declared in the function header.
The PHP Wiki rfc page on closures gives us some hints on why closures were implemented this way:
PHP's notion of scope is quite different than the notion of scope other languages define. Combine this with variable variables ($$var) and it becomes clear that automatically detecting which variables from the outer scope are referenced inside are closure is impossible. Also, since for example global variables are not visible inside functions either by default, automatically making the parent scope available would break with the current language concept PHP follows.

In PHP, you can't access intermediate scopes. You only have your local scope, and the global scope. This is an artefact of the perverse scope rules of PHP, which are the complete opposite of any sane language's scope rules.

In PHP, a named function declaration (function bar ()) declares a function in the global scope. So in your first example, when you run your foo function, it will define a bar function in the global scope, and then everybody can access the bar function as if you declared it outside of foo. Functions and variables are separate in PHP. There is just one scope for named functions: global; whereas you have local variables, there is no such thing as locally-scoped functions.
In other words, putting it inside of foo is an illusion; named function declaration always declares it globally; putting it inside foo simply delays the time when the declaration is run (thus delaying when it is defined) to the execution of foo.
A closure is what you need. Other answers have showed you how to do that.

Related

Defining a global variable, and including functions that require it?

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.

PHP and Static Variables in Object Member Functions

Up until today, I thought I had a fairly good grasp of how the static modifier worked. I know that (in laymans terms) a static variable in a function does not 'reset' across calls to that function, and I know that static variables and functions on a class are accessible by calling upon them through the class itself (not an instantiation of the class).
My problem is this: today I found that if I declare a static variable inside of a non-static function on a class, all instantiations of that class share that static variable in separate calls to the member function.
For example:
class A {
public function GetValue() {
static $value = 0;
$value++;
return $value;
}
}
$instance_1 = new A();
$instance_2 = new A();
echo $instance_1->GetValue();
echo $instance_1->GetValue();
echo $instance_2->GetValue();
echo $instance_2->GetValue();
echo $instance_1->GetValue();
echo $instance_1->GetValue();
Notice that the GetValue function is neither declared as static or used in a static way (as in, called on the class itself).
Now, I always assumed that this would output: 121234
Instead, I find that it will output: 123456
Like I say, I would understand this if the static variable $value was inside of a static function. However, with it being inside a non-static function I just assumed that it would only be 'tied' to the function 'within' each individual instantiation.
I guess my question is twofold, then... 1) is this a bug or expected behaviour? 2) do other languages treat these 'static inside non-static' variables the same way, or is this unique to PHP?
This is expected.
This is also the case in C++ (and probably others as well).
You should think of non-static class member functions as if they were just like ordinary functions, but with an implicit $this argument that is automatically provided by the interpreter. (That's exactly how they're implemented in most languages.)
I've copied the following information from this article by Josh Duck: http://joshduck.com/blog/2010/03/19/exploring-phps-static-scoping/
Static variables have been available since PHP 4 and allow you to define a persistent variable that is only accessible from the current function. This allows you to encapsulate state into a function or method and can eliminate the need for classes where a single function will suffice.
When a static variable is defined inside a class method they will always refer to the class on which the method was called. In doing this they act almost like properties referenced through static, though there are subtle differences.
Static variables can’t preserve the calling class scope. This can be potentially problematic if you have an inherited method containing a static variable that is called from both inside and outside its class.
As far as I know, all languages with static variables treat them this way. Think of static variables as global variables that can only be accessed from a certain scope.

Accessing a function from within a function in php?

How does scope work for functions in PHP? Can I use function A (defined outside function B) from within function B?
From php manual:
All functions and classes in PHP have the global scope - they can be called outside a function even if they were defined inside and vice versa.
So yes, you can.
Yes, you can do it like this:
function A()
{
...
}
function B()
{
A();
}
B();
Variable scope if for variables.
There is no "scope" for functions... except when using namespaces.
Quoting the User-defined functions section of the manual :
All functions and classes in PHP have
the global scope - they can be called
outside a function even if they were
defined inside and vice versa.

PHP Equivalent to Ruby's #instance_variable?

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.

Why is the usage of $this in PHP necessary when referencing methods or variables in the same class?

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 ?

Categories