Using $GLOBALS[] variable in PHP class function - php

I'm trying to assign $GLOBALS['a'] variable in function from class, but haven't succeeded.
Here is my code:
<?php
$GLOBALS['a'] = "alter";
class db_data
{
public $a;
function __construct()
{
$this->a = $GLOBALS['a'];
}
}
$db = new db_data;
echo $db->$a;
?>
And produced this error:
Notice: Undefined property: db_data::$alter.....
I tried to search on SO for this, but all questions were different and it did not resolve my problem.

Answers are in the question comments, but here's why it's happening
You're accidentally using the variable variables feature of PHP. When you call $thing->$a, you're actually getting the value of $a (which defined by the $GLOBALS['a'] = "alter"; line), and then getting the property of $thing with that value.
As stated in your comments, you should simply echo $db->a, as that's how PHP properties are accessed
Also, Watch out!, if the value of $a is changed elsewhere in the global scope, your db_data class will reflect that change, which you probably don't want.

Related

Cannot initialize an uninitialized variable inside a class method

I have just started practicing OO programming using PHP. Recently I have encountered a problem.
I am trying to declare a variable inside a class, but leaving it uninitialized. Later inside a method of the class when I try to initialize the variable it shows the following errors:
Undefined variable: a in C:\wamp\www\sample.php on line 6
Fatal error: Cannot access empty property in C:\wamp\www\sample.php on line 6
Here is the code that I am trying to execute:
<?php
class Sample{
public $a;
function call($b){
$this->$a = $b;
echo $a;
}
}
$sam = new Sample();
$sam->call(5);
?>
How do I fix this?
In the function call, $a does not exist. Only $this->a (without $ before the a), which is the property of your "sam" object, and $b, which is an input parameter.
Plus when you set the property, you must not use $a. Use $this->a.
If you would have a variable which contains a property name of the class, you should use $this->$a, which would mean $this->asdf, if $a = 'asdf';
The correct syntax is $this->a, not $this->$a.

error when using variable class name and static method

Running PHP 5.4, so I wasn't expecting this, but I'm encountering the following error:
Parse error: syntax error, unexpected '::' (T_PAAMAYIM_NEKUDOTAYIM)
Assume you have a variable of stdClass setup as follows:
$this->variable = new stdClass();
$this->variable->other = array('class' => 'helloworld');
Now, assume you want to access a static method of class helloworld:
// Standard call
$x = helloworld::my_static_method();
// Call with variable class name
$x = $this->variable->other['class']::my_static_method();
When calling the above using the variable class name, I receive the parsing error. What's odd, is that if I do the following, no error is presented:
$class = $this->variable->other['class'];
$x = $class::my_static_method();
To me this seems very odd, can anyone think of a reason why the class name isn't resolving correctly when using the first example versus the second?
can anyone think of a reason why the class name isn't resolving correctly when using the first example versus the second?
The PHP parser does not support such a syntax, and that's merely all. This is because the parser has grown historically. I can't give more reason than that.
It will be that with PHP 7 you can see some changes on these syntax details working more into your expected direction Uniform Variable Syntax:
($variable->other['class'])::my_static_method();
But until then, you can go around that with the help of call_user_func:
call_user_func([$variable->other['class'], 'my_static_method']);
call_user_func($variable->other['class'] . '::my_static_method');
Or as you wrote your own, by creating a variable:
$class = $variable->other['class'];
$class::my_static_method();
Or even a variable that looks like something different:
${(int)!${0}=$variable->other['class']}::my_static_method();
Related Material:
Interpolation (double quoted string) of Associative Arrays in PHP
This doesn't work ($this->variable->other['class']::my_static_method()) as it's essentially using a string as the class name directly. It works when you assign it to a variable first, as it's then being evaluated out as the class name instead.
You can also look into using ReflectionMethod invocation in order to call the method, in which case you wouldn't have to store the class name in a variable before using it. Here's the docs on that: http://php.net/manual/en/class.reflectionmethod.php and on the invoke method (you pass in NULL to indicate a static method) http://php.net/manual/en/reflectionmethod.invoke.php
Here are a couple examples of ways to invoke your function:
class helloworld{
public static function my_static_method($i = 0){
echo "Here: ".$i;
}
}
class Foo{
private $variable;
public function __construct(){
//Create a new class
$this->variable = new stdClass();
//Create a new property of the class, storing an array
$this->variable->other = array('class' => 'helloworld');
//Call function statically
$x = helloworld::my_static_method(1); //Outputs: "Here: 1"
//Store class name in a variable before use
$class = $this->variable->other['class'];
$y = $class::my_static_method(2); //Outputs: "Here: 2"
//Using a ReflectionMethod, you can call the function this way, too
$z = new ReflectionMethod($this->variable->other['class'], 'my_static_method');
$z->invoke(null, 3); //Outputs: "Here: 3"
}
}
//Instantiate new Foo class
new Foo();

PHP returning by reference not working with normal functions but working with OOP

If I try this code :
<?php
class ref
{
public $reff = "original ";
public function &get_reff()
{
return $this->reff;
}
public function get_reff2()
{
return $this->reff;
}
}
$thereffc = new ref;
$aa =& $thereffc->get_reff();
echo $aa;
$aa = " the changed value ";
echo $thereffc->get_reff(); // says "the changed value "
echo $thereffc->reff; // same thing
?>
Then returning by reference works and the value of the object property $reff gets changed as the variable $aa that references it changes too.
However, when I try this on a normal function that is not inside a class, it won't work !!
I tried this code :
<?php
function &foo()
{
$param = " the first <br>";
return $param;
}
$a = & foo();
$a = " the second <br>";
echo foo(); // just says "the first" !!!
it looks like the function foo() wont recognize it returns by reference and stubbornly returns what it wants !!!
Does returning by reference work only in OOP context ??
That is because a function's scope collapses when the function call completes and the function local reference to the variable is unset. Any subsequent calls to the function create a new $param variable.
Even if that where not the case in the function you are reassigning the variable to the first <br> with each invocation of the function.
If you want proof that the return by reference works use the static keyword to give the function variable a persistent state.
See this example
function &test(){
static $param = "Hello\n";
return $param;
}
$a = &test();
echo $a;
$a = "Goodbye\n";
echo test();
Echo's
Hello
Goodbye
Does returning by reference work only in OOP context ??
No. PHP makes no difference if that is a function or a class method, returning by reference always works.
That you ask indicates you might have not have understood fully what references in PHP are, which - as we all know - can happen. I suggest you read the whole topic in the PHP manual and at least two more sources by different authors. It's a complicated topic.
In your example, take care which reference you return here btw. You set $param to that value - always - when you call the function, so the function returns a reference to that newly set variable.
So this is more a question of variable scope you ask here:
Variable scope

PHP Basics: Can't deal with scope within classes

i got some trouble to understand scope in OOP. What i want is that $foo->test_item() prints "teststring"...Now it just fails with:
Warning: Missing argument 1 for testing::test_item()
Thanks a lot!
<?php
class testing {
public $vari = "teststring";
function test_item($vari){ //$this->vari doesn't work either
print $vari;
}
}
$foo = new testing();
$foo->test_item();
?>
test_item() should be:
function test_item() {
print $this->vari;
}
There is no need to pass $vari as a parameter.
Well, you've declared a method which expects an argument, which is missing. You should do:
$foo->test_item("Something");
As for the $this->, that goes inside of the class methods.
function test_item(){
print $this->vari;
}
function parameters can not be as "$this->var",
change your class like
class testing {
public $vari = "teststring";
function test_item(){ //$this->vari doesn't work either
print $this->vari;
}
}
$foo = new testing();
$foo->test_item();
And read this Object-Oriented PHP for Beginners
What's happening there is that $foo->test_item() is expecting something passed as an argument, so for example
$foo->test_item("Hello");
Would be correct in this case. This would print Hello
But, you may be wondering why it doesn't print teststring. This is because by calling
print $vari;
you are only printing the variable that has been passed to $foo->test_item()
However, if instead you do
function test_item(){ //notice I've removed the argument passed to test_item here...
print $this->vari;
}
You will instead be printing the value of the class property $vari. Use $this->... to call functions or variables within the scope of the class. If you try it without $this-> then PHP will look for that variable within the function's local scope

I have a require("config.php") with arrays, but still get Undefined variable error

I hava a function that looks something like this:
require("config.php");
function displayGta()
{
(... lots of code...)
$car = $car_park[3];
}
and a config.php that look something like this:
<?php
$car_park = array ("Mercedes 540 K.", "Chevrolet Coupe.", "Chrysler Imperial.", "Ford Model T.", "Hudson Super.", "Packard Sedan.", "Pontiac Landau.", "Duryea.");
(...)
?>
Why do I get Notice: Undefined variable: car_park ?
Try adding
global $car_park;
in your function. When you include the definition of $car_park, it is creating a global variable, and to access that from within a function, you must declare it as global, or access it through the $GLOBALS superglobal.
See the manual page on variable scope for more information.
Even though Paul describes what's going on I'll try to explain again.
When you create a variable it belongs to a particular scope. A scope is an area where a variable can be used.
For instance if I was to do this
$some_var = 1;
function some_fun()
{
echo $some_var;
}
the variable is not allowed within the function because it was not created inside the function. For it to work inside a function you must use the global keyword so the below example would work
$some_var = 1;
function some_fun()
{
global $some_var; //Call the variable into the function scope!
echo $some_var;
}
This is vice versa so you can't do the following
function init()
{
$some_var = true;
}
init();
if($some_var) // this is not defined.
{
}
There are a few ways around this but the simplest one of all is using $GLOBALS array which is allowed anywhere within the script as they're special variables.
So
$GLOBALS['config'] = array(
'Some Car' => 22
);
function do_something()
{
echo $GLOBALS['config']['some Car']; //works
}
Also make sure your server has Register globals turned off in your INI for security.
http://www.php.net/manual/en/security.globals.php
You could try to proxy it into your function, like:
function foo($bar){
(code)
$car = $bar[3];
(code)
}
Then when you call it:
echo foo($bar);
I had the same issue and have been tearing my hair out over it - nothing worked, absolutely nothing - until in desperation I just copied the contents of config.php into a new file and saved it as config2.php (without changing anything in its contents at all), changed the require_once('config.php'); to require_once('config2.php'); and it just started working.

Categories