Apparently $pid is out of scope here. Shouldn't it be "closed" in with the function? I'm fairly sure that is how closures work in javascript for example.
According to some articles php closures are broken, so I cannot access this?
So how can $pid be accessed from this closure function?
class MyClass {
static function getHdvdsCol($pid) {
$col = new PointColumn();
$col->key = $pid;
$col->parser = function($row) {
print $pid; // Undefined variable: pid
};
return $col;
}
}
$func = MyClass::getHdvdsCol(45);
call_user_func($func, $row);
Edit I have gotten around it with use: $col->parser = function($row) use($pid). However I feel this is ugly.
You need to specify which variables should be closed in this way:
function($row) use ($pid) { ... }
You can use the bindTo method.
class MyClass {
static function getHdvdsCol($pid) {
$col = new PointColumn();
$col->key = $pid;
$parser = function($row) {
print $this->key;
};
$col->parser = $parser->bindTo($parser, $parser);
return $col;
}
}
$func = MyClass::getHdvdsCol(45);
call_user_func($func, $row);
I think PHP is very consistent in scoping of variables. The rule is, if a variable is defined outside a function, you must specify it explicitly. For lexical scope 'use' is used, for globals 'global' is used.
For example, you can't also use a global variable directly:
$n = 5;
function f()
{
echo $n; // Undefined variable
}
You must use the global keyword:
$n = 5;
function f()
{
global $n;
echo $n;
}
Related
I have a small PHP snippet.
How can I assign a new value to my global from within a main class?
Example:
$GlobalValue = 0;
class SampleModuleController extends SampleController {
public function doSomething() {
$NewValue = 1;
$GlobalValue = $NewValue
}
}
echo $GlobalValue;
//This always echo's 0, When I try to output or print outside the class or use somewhere above in the php code.
//I need to be able to assign the new value from within my class
//and the function doSomething so it should be 1
You can pass parameter as reference in the method doSomething() and then call that function passing your variable $GlobalValue. However it's not very recommended to have global variables. You should consider change your code to more OOP.
$GlobalValue = 0;
class SampleModuleController {
private $newValue = 3;
public function doSomething(&$variable) {
$variable = $this->newValue;
}
}
$ModuleController = new SampleModuleController();
$ModuleController->doSomething($GlobalValue);
echo $GlobalValue; //print 1
If i understood it right what you are trying to do can be achieved quite easily with this:
global $GlobalValue;
$GlobalValue = 0;
class SampleModuleController {
public function doSomething() {
global $GlobalValue;
$NewValue = 1;
$GlobalValue = $NewValue;
}
}
$ModuleController = new SampleModuleController();
$ModuleController->doSomething();
echo $GlobalValue; //print 1
They key is in the "global" keyword (which is the same as accessing the $GLOBAL["your_var_name"] container.
Beside this, as others said relying on global variables should be discouraged.
How can I use class instance inside independent method?
I some file have:
global $l;
$l = new l('bg');
include('second.php');
In second.php I have:
function a() {
print_r($l);
}
$l is coming like NULL;
class l declaration:
class l {
var $lang = array();
function l($lang) {
}
function g($string) {
}
}
My question - how can I use $l instance inside of my function a.
Thanks.
In function a $l is not defined.
Either you pass it in as a parameter or you use global.
function a($l) {
print_r($l);
}
global is not like var. It does not define a variable to be used as a global. Instead, global allows you to pull variables from the global scope, like:
$l = new l();
function a() {
global $l;
print_r($l);
}
I should also add that the use of global is heavily frowned upon, it breaks dependency expectations. This means that if you look at your function a you can't see that it needs $l. If it's a parameter then you know it needs $l.
I've been looking at Magic Constants and Reflection in PHP to see if the following is possible:
function one() {
setVars();
// $node would be in scope
print_r($node);
}
function setVars() {
return $node = '2';
}
Is this a classical programming concept? Reflection seems to be the closest thing. Basically, I just want to define variables in a different scope (the scope/context of the function that called the setVars() function).
For more than one variable try to store them in a array and return the array.
function one() {
$nodeArray = setVars();
print_r($nodeArray );
}
function setVars() {
$nodeArray[] = 1;
$nodeArray[] = 1;
$nodeArray[] = 1;
return $nodeArray;
}
Take a look at extract().
function one() {
$vars = setVars();
extract($vars);
// $node1 would be in scope
print_r($node1);
}
function setVars() {
$node1 = '1';
$node2 = '2';
return compact('node1','node2');
}
It should be said, although this is possible, it often leads to terrible architecture and problems down the line.
is any way to return reference at class parameter or global variable? I try this
class test{
public static $var;
public static function get(&$ref){
$ref = self::$var;
}
}
test::get($ref);
$ref = 'test';
var_dump(test::$var);
it's a basic example, i know, then this example can be use another way, but i need to keep principle
this is my function, where is problem with reference to variable
class mySession{
public static function issetKeys(){
$keys = func_get_args();
$session = &$_SESSION;
$c = 0;
if (is_array($keys)){
foreach ($keys as $val){
if (isset($session[$val])){
$session = &$session[$val];
$c++;
}
else break;
}
}
return $c == count($keys);
}
public static function &get(){
$keys = func_get_args();
$session = &$_SESSION;
if (is_array($keys)){
foreach ($keys as $val){
if (!isset($session[$val])) $session[$val] = Array();
$session = &$session[$val];
}
}
return $session;
}
}
function getValue(){
if (!mySession::issetKeys('p1', 'p2')){
$session = mySession::get('p1', 'p2');
$session = 'string';
}
return mySession::get('p1', 'p2');
}
print_r($_SESSION);
but no variable save in to $_SESSION
No, and why would you ever do such a thing?
If you want to access a public static variable, you'll just write
test::$var = "Hello there handsome";
In the case above you're not passing the reference of this::$var onto $ref, you're letting a reference to $ref contain the value of this::$var. PHP is not C, and references should generally be avoided when not necessary in PHP.
In the general case, a parameter only exists for the duration of the function to which it was passed; when the function returns, the call stack is unwound and the parameter disappears, which means that any reference to a variable that lived in the call stack will no longer be valid (since it points to memory which has been freed and now quite possibly contains something else entirely.)
That said, it is possible to return a reference to a parameter, although this will not work if you try to return a reference to a variable that actually lives in the stack (that is, one that was not passed by reference):
$myGlobal = 10;
// Note the & before the function name
function &returnReference(&$x) {
return $x;
}
// Note the & before the function call
$someValue = &derp($myGlobal);
echo $myGlobal;
$someValue = 0;
echo $myGlobal;
Ok I've got a unique problem. I have a function being called, and I need this to work with how it's already being called. I've put together some code that shows as close as I can get to the answer:
class some_class {
private $_some_stuff = array();
public function some_method()
{
$args = func_get_args();
foreach($args as &$name)
{
$this->_some_stuff[] =& $name;
}
}
public function other_method()
{
for ($i = 0; $i < count($this->_some_stuff); $i++)
{
$this->_some_stuff[$i] = 'somevalue';
}
}
}
$some_object = new some_class();
$one = 'firstever';
$two = 'secondever';
$some_object->some_method(&$one, &$two);
$some_object->other_method(&$one, &$two);
echo $one;
echo '<br>...<br>';
echo $two;
I need $one and $two at the end to output 'somevalue'. If it's not clear, I need to be able to pass by reference some values into one method of an object and later have a separate method of the object still be able to access those values;
I believe that this works:
public function some_method()
{
$backtrace = debug_backtrace();
$args = $backtrace[0]['args'];
foreach($args as &$name)
{
$this->_some_stuff[] =& $name;
}
}
but as others have said, "how it's already being called" is call-time pass by reference, which is deprecated
Call-time pass-by-reference has been deprecated, because the result is a hard code.
Try to reorganize your application
You can't use func_get_args() because as the manual says it does not return by reference:
Returns an array in which each element is a copy of the corresponding member of the current user-defined function's argument list.
It appears from testing that func_get_arg() has the same behavior.
The only way to instruct PHP to provide an argument by reference to a function is with the & in the function argument list. Since you don't have an argument list, what you want is impossible.
It's also hideous! Pass-by-reference in PHP is fraught with problems and should be avoided.
However, if you are willing to change your some_method() signature, you can do the following:
class some_class {
private $_some_stuff = array();
public function some_method(&$args) // notice we accept a single arg by reference
{
foreach ($args as &$arg) {
$this->_some_stuff[] =& $arg;
}
}
public function other_method()
{
for ($i = 0; $i < count($this->_some_stuff); $i++)
{
$this->_some_stuff[$i] = 'somevalue';
}
}
}
$some_object = new some_class();
$one = 'firstever';
$two = 'secondever';
// now whenever you call this method, use this EXACT PATTERN:
$args = array(&$one, &$two); // this MUST be its own statement on its own line, and MUST have referenced elements!
$some_object->some_method($args); // CANNOT do $some_object->some_method(array(&$one, &$two)); !!!
$some_object->other_method();
var_dump($some_object);
var_dump($args);
var_dump($one);
var_dump($two);
That will do what you want.
Also note that call-time pass-by-reference (thefunc(&$foo);) is depreciated and may not work anymore.