[PHP] static variables inside static methods

2011-07-06 Thread Дмитрий Степанов
Hello, everybody.

While working with static variables inside static class' methods, I have
found this very interesting (at least for me) behavior of PHP.

Consider the following class definitions (example #1):

class X {
public final static function test() {
static $i;
return ++$i;
}
}

class Y extends X {
}

By executing this code:

echo X::test();
echo Y::test(); // note Y class here

one would expect to see 12 as output, but apparently I get 11.

That's a bit confusing if you logically assume that static vars are tied
to the scope they're defined in. Since this static variable is
defined in a specific static method test(), that is NOT overloaded by class
Y, in my opinion it shoul've preserved it's value across static calls.

Let's look at another example (example #2):

class X {
public static $x =0;
public final static function test() {
return ++static::$x; // note static keyword here
}
}

class Y extends X {
}

If you run this code:

echo X::test();
echo Y::test();

you get 12 as output - the expected output. Notice that the ++static::$x
expr. is taking advantage of late static binding. Now, if you change
body of test() to the following code:

public final static function test() {
return ++self::$x;
}

then you also get 12 as output.

Is this a bug that static context of $i is not preserved in example #1 or do
I misunderstand something?

I could not find any hints on this in the PHP documentation.

Dmitry.


Re: [PHP] static variables inside static methods

2011-07-06 Thread Дмитрий Степанов
 The second case is referencing the varible of the class.
Maybe you are right. However, I don't really think that there is a true
reference to the class var in example #2.

PHP documentation of static keywords does not unambiguously explain behavior
of static variables inside methods in example #1. I believe that in
example #1 the exactly same instance of function (method) is used
irregarding of how you call it (X::test() or Y::test()), therefore I would
expect the same static var to be involved in both calls to test().

Is there anybody who can comment on this matter?

Thanks.

6 июля 2011 г. 11:05 пользователь Andrew Williams andrew4willi...@gmail.com
 написал:

I think you are confusing  scope visibility  level of the variable within
 method and the class.

 Variable within the method is going to 1 because it was declare within the
 test method and there no link to the one declared outside the test method.
 The second case is referencing the varible of the class.



 2011/7/6 Дмитрий Степанов dmit...@stepanov.lv

  Hello, everybody.
 
  While working with static variables inside static class' methods, I have
  found this very interesting (at least for me) behavior of PHP.
 
  Consider the following class definitions (example #1):
 
  class X {
  public final static function test() {
  static $i;
  return ++$i;
  }
  }
 
  class Y extends X {
  }
 
  By executing this code:
 
  echo X::test();
  echo Y::test(); // note Y class here
 
  one would expect to see 12 as output, but apparently I get 11.
 
  That's a bit confusing if you logically assume that static vars are
 tied
  to the scope they're defined in. Since this static variable is
  defined in a specific static method test(), that is NOT overloaded by
 class
  Y, in my opinion it shoul've preserved it's value across static calls.
 
  Let's look at another example (example #2):
 
  class X {
  public static $x =0;
  public final static function test() {
  return ++static::$x; // note static keyword here
  }
  }
 
  class Y extends X {
  }
 
  If you run this code:
 
  echo X::test();
  echo Y::test();
 
  you get 12 as output - the expected output. Notice that the
  ++static::$x
  expr. is taking advantage of late static binding. Now, if you change
  body of test() to the following code:
 
  public final static function test() {
  return ++self::$x;
  }
 
  then you also get 12 as output.
 
  Is this a bug that static context of $i is not preserved in example #1 or
  do
  I misunderstand something?
 
  I could not find any hints on this in the PHP documentation.
 
  Dmitry.
 




-- 
Dmitry Stepanov

E-mail: dmit...@stepanov.lv
Home: http://www.stepanov.lv
Skype: ninzjoo



-- 
Dmitry Stepanov

E-mail: dmit...@stepanov.lv
Home: http://www.stepanov.lv
Skype: ninzjoo


[PHP] Import symbol table into function' scope.

2011-06-15 Thread Дмитрий Степанов
Hello, everybody.

Consider the following code:

class DB {
public function query( $sql) {
// ... some magic of DB querying
}
}

class DBReader {
public $DB;// instance of DB
public function __call( $methodName, $args) {
return call_user_func_array( array( $this, $methodName), $args);
}
protected function readSomething() {
$sql ='SELECT ...';
$result =$this-DB-query( $sql);
}
protected function readSomethingElse() {
// ... very similar to DBReader::readSomething()
}
//  + other methods like DBReader::readSomething()
}

If you take a look at DBReader::readSomething(), you'll see that I am
referencing database object and performing query via $this-DB-query().
If you do a lot of database queries, your code becomes bloated with
$this-DB-... and usually gets not so well readable (at least for me).

Since I have a lot of methods, that are similar to DBReader::readSomething()
(which perform DB queries), I would like to optimize readability of the DB
querying code. Right now I would do it in the following way:

// 1) reference database object inside the method
$DB =$this-DB;

// 2) do whatever I need with the DB
$DB-query( $sql);
$DB-numRows();
// ... or whatever

This way the code looks nicer and is, in fact, shorter.

So I wonder if there is any way to import scope (symbol table) into the
method DBReader::readSomething()? By importing the variables into the
function body,
I would like to avoid the 1) reference database object inside the method
step so that $DB becomes instantly available:

protected function readSomething() {
$sql ='SELECT ...';
$result =$DB-query( $sql);// like this
}

AFAIK, there is no such call_user_func* function that would allow importing
of symbol table into the called fn.
What I would expect to be possible:

public function __call( $methodName, $args) {
$scope =array( 'DB' =$this-DB);
return call_user_func_array( array( $this, $methodName), $args, $scope);//
note the $scope array, that is being passed here
}

The effect of such call to call_user_func_array() I would expect to be
equivalent with same as regular call to call_user_func_array(), but with
additional
call to extract( $scope, EXTR_REFS) right at the top of the function's body.

Does anybody have some ideas how I can get this working?

If there is no way to get this working with current PHP feature set, then I
would like to propose to extend call_user_func_array() to support $scope
argument.
What do you think about this?

P.S.: don't ask why I don't just simply make DBReader::readSomething() to be
public method. That's not the case.

P.S.: a very similar scope importing technique I am using with the PHP
template files I use in my web projects. As you know, include() is,
literally, injecting code
from the file into the current scope, thus making current symbol available
to the included code:

index.php:

$x =5;
$y =10;
include(chart.php);

chart.php:

echo $x .',' .$y;

After processing index.php, the output would be 5,10.

P.S.: closures are capable of importing scope via use() statement:

$x =5;
$y =10;

$closure =function() use( $x, $y) {
  echo $x .',' .$y;
};

$closure();// would give output 5,10

so I suppose that technically importing scope is not a big deal from the PHP
internals perspective.

Dmitry.