How php parse and interpret function scope - php

Example 1: Here I expect that function hello must be in the global scope.
But as per my expectation it does not behave same.It does not put function hello into global scope. at run time php must put function hello into global scope. It says undefined function hello().
$fruit=true;
foo();
hello();
function foo()
{
echo "you are in the foo<br/>";
}
if($fruit)
{
function hello()
{
echo "you are in the hello<br/>";
}
}
Example 2 : Now as after example 1 , i supposed the below script must also work as example 1. i supposed it will give also error undefined function bar(). But now here it behave differently and execute bar.
foo();
bar();
function foo()
{
function bar()
{
echo "I don't exist until foo() is called.\n";
}
}
So i am unable to get the concept how php interpreter behave internally. How does it parse the program, and does it execute the step one by one , or whole program at once?

I quote a manual for you:
When a function is defined in a conditional manner .... Its definition must be processed prior to being called.
And more:
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.

Example One:
You do not define the function hello() until a part of the script has run, its in an IF and therefore does not get defined until after you attempt to call it
Like this you get no errors as the IF is run before the now defined funtion hello is called. And of corse either way it is in the GLOBAL scope. But your way it didnt exist anywhere until after you called it.
<?php
$fruit=true;
if($fruit)
{
function hello()
{
echo "you are in the hello<br/>";
}
}
foo();
hello();
function foo()
{
echo "you are in the foo<br/>";
}

Related

get a variable from the scope where the function used not Global

how to access the variable X in Function Func1 not in global Scope
$X='hi';
function Func1(){
global $X;
echo $X;
}
function Func2(){
$X='hello';
Func1(); // I want to echo "hello" not "hi"
}
(First of all, good job trying to avoid using a global. They are almost never the right answer.)
Variables in PHP functions are locally scoped - they don't inherit anything from where they're called. Func1 has no idea about any variables or anything else that happens in Func2, it only knows about itself.
If you want a variable available in a function, then you need to pass it in as an argument:
function Func1($X){
echo $X;
}
function Func2(){
$X='hello';
Func1($X);
}
It would be worth reading http://php.net/manual/en/language.variables.scope.php to get a basic grounding in scope in PHP.
Give this a try
$x = 'hi';
function func1(){
echo func2();
}
function func2(){
return $x = 'hello';
}
The x variable will get overridden and the function will return the variable data.
Next, the func2 will be called in func1 and the returned value will be printed on the screen.
Just tried to minimize the number of lines.

Do I need to declare a variable before initialise it in PHP constructor

I have a question about variable declare in PHP, I know this question may be little bit stupid. I have the following code
<?php
Class Test{
function __construct(){
$this->test = 'helloworkd';
}
function test(){
echo $this->test;
}
}
$test = new Test();
$test->test();
It seems like I can use the test variable without declaring it. My question is why the test() method can access the test variable? Is the test a global variable?
Thanks for your help!
My question is why the test() method can access the test variable?
PHP unlike some other languages allows you to assign values to variables without first declaring them. The interpreter will initialize them for you. This is poor practice because it makes code harder to read and debug, and because it can cause errors if you try to read a variable that was never declared:
<?php
$nonexistentArray['key'] = 7; //Bad practice, but PHP won't complain
$a = $fakeArray['key']; //Undefined variable error
Even in the second case, PHP will continue to execute the rest of the script, but it will complain.
Is the test a global variable?
No. It lives in the local scope.
<?php
function myFunc(){
//$arr was never declared, but PHP won't complain
$arr['key'][]=7;
}
myFunc();
//Undefined var error. The $arr that was initialized in myFunc is not global
print_r($arr);
A good IDE will complain if you try to use a variable that you never declared. In your case, when in the constructor you do:
$this->test = 'helloworkd';
PHP will initialize this class property for you. Now the rest of your code can use it, including the test() method. If it seems like a global var, it's not. It's a class property. If you tried to access it as just test from outside the class, you would not be able to. You'd have to use the accessor operator -> in $test->test or $this->test.
Many "test"! You have asign test="helloworld" in the contructor, so it takes a value for every new Test() is made.
$x = new Test();
$y = new Test();
echo $x->test(); //"helloworld"
echo $y->test(); //"helloworld"
I would declare your variable. This makes the code more readable for yourself any any others that see your code.
For example:
<?php
Class Test {
public $test;
function __construct($test){
$this->test = $test;
}
function test(){
echo $this->test;
}
So now we have a public variable that is accessible through an instance of this class by calling
$instance->test;
If you do not want this then you can change public to private or protected
You can read about this here: http://php.net/manual/en/language.variables.scope.php
Whatever you pass as an argument when creating an instance of this class will be assigned to the $test variable.
My question is why the test() method can access the test variable?
It can't. It is trying to access a constant test, if you want to access the class variable, use $this->test.
For example:
<?php
echo foo;
Will echo out a string "foo" and also spits out a notice: Use of undefined constant foo - assumed 'foo' in ...
<?php
class test{
public $test;
public function __construct(){
$this->test = 'helloworkd';
}
$newtest = new Test();
echo $newtest->test;
?>

Scope loss in included files in php

There are a few posts relevant to this but I'm not seeing anything near to the situation I'm struggling with.
I've inherited a rather large codebase which the original designer has taken some interesting methods of design. I'm attempting to call a method of a class that's defined. The class file itself has some global variables set. I call this method from a function, where also, I've included this file. When the method runs, the global variables are no longer defined. See below:
My File:
<?php //myScript.php
echo("Calling foo(): ");
foo();
function foo() {
include '../../php/class.bar.php';
$bar = new bar();
$bar->doSomething();
}
?>
../../php/class.bar.php:
$GLOBAL_ARRAY_ONE[0] = 'Here I am';
$GLOBAL_ARRAY_ONE[1] = 'JT';
class bar {
public $itsFoo = array();
public $itsBar = array();
public function doSomething() {
global $GLOBAL_ARRAY_ONE;
$this->itsFoo[0] = $GLOBAL_ARRAY_ONE[0];
$this->itsFoo[1] = $GLOBAL_ARRAY_ONE[1];
var_dump($this->itsFoo);
}
}
So, when I run "myScript.php" The output is: calling foo(): NULL
I personally wouldn't declare global arrays in a script like that but, I see no reason why I shouldn't have access to them.
Any ideas? Thanks!
Since you include the file inside a function - GLOBALS cannot be defined there (neither a class). What you probably want to do is to include class.bar.php outside (of foo()):
<?php //myScript.php
include '../../php/class.bar.php';
echo("Calling foo(): ");
foo();
function foo() {
$bar = new bar();
$bar->doSomething();
}
?>

How can I use a callback function which is stored as a class member in PHP?

Consider the following code, which is a scheme of storing a callback function as a member, and then using it:
class MyClass {
function __construct($callback) {
$this->callback = $callback;
}
function makeCall() {
return $this->callback();
}
}
function myFunc() {
return 'myFunc was here';
}
$o = new MyClass(myFunc);
echo $o->makeCall();
I would expect myFunc was here to be echoed, but instead I get:
Call to undefined method MyClass::callback()
Can anyone explain what's wrong here, and what I can do in order to get the desired behaviour?
In case it matters, I am using PHP 5.3.13.
You can change your makeCall method to this:
function makeCall() {
$func = $this->callback;
return $func();
}
Pass it as a string and call it by call_user_func.
class MyClass {
function __construct($callback) {
$this->callback = $callback;
}
function makeCall() {
return call_user_func($this->callback);
}
}
function myFunc() {
return 'myFunc was here';
}
$o = new MyClass("myFunc");
echo $o->makeCall();
One important thing about PHP is that it recognises the type of a symbol with the syntax rather than the contents of it, so you need to state explicitly what you refer to.
In many languages you just write:
myVariable
myFunction
myConstant
myClass
myClass.myStaticMethod
myObject.myMethod
And the parser/compiler knows what each of the symbols means, because it's aware of what they refer to simply by knowing what's assigned to them.
In PHP, however, you need to use the syntax to let the parser know what "symbol namespace" you refer to, so normally you write:
$myVariable
myFunction()
myConstant
new myClass
myClass::myStaticMethod()
$myObject->method()
However, as you can see these are calls rather than references. To pass a reference to a function, class or method in PHP, combined string and array syntax is used:
'myFunction'
array('myClass', 'myStaticMethod')
array($myObject, 'myMethod')
In your case, you need to use 'myFunc' in place of myFunc to let PHP know that you're passing a reference to a function and not retrieving the value the myFunc constant.
Another ramification is that when you write $myObject->callback(), PHP assumes callback is a method because of the parentheses and it does not attempt to loop up a property.
To achieve the expected result, you need to either store a copy of/reference to the property callback in a local variable and use the following syntax:
$callback = $this->callback;
return $callback();
which identifies it as a closure, because of the dollar sign and the parentheses; or call it with the call_user_func function:
call_user_func($this->callback);
which, on the other hand, is a built-in function that expects callback.

Defining a function inside a conditional

Snippet 1 works. Snippet 2 doesn't. Why?
1.
foo();
function foo()
{
// do soemething
}
2.
foo();
if(!function_exists("foo"))
{
function foo()
{
// do soemething
}
}
See http://www.php.net/manual/en/functions.user-defined.php:
Functions need not be defined before
they are referenced, except when a
function is conditionally defined [...]
Its definition must be processed prior
to being called.
You're trying to execute foo() before testing to see whether it's defined or not (and subsequently defining it)
if(!function_exists("foo"))
{
function foo()
{
// do soemething
}
}
foo();

Categories