PHP accessing global variable set in class - php

I'm missing something fundamental here. We need to access the variable $myvar that is set in the function do_stuff. Here's a generalized snippet of the class where the function exists. The class and it's functions all work just fine.
class TestClass {
public function do_stuff() {
global $myvar;
$myvar= 'the value we want';
}
}
Now, later on here's where it goes wrong...
$TestClass = new TestClass();
$TestClass->do_stuff();
function get_var() {
global $myvar;
echo $myvar; // here the value does NOT exist
}
get_var();
echo $myvar; // but here the value DOES exist
So what am I missing as to why the variable exists when we access it outside of a function, but it does not exist when accessing inside a function?
Notes: This is a simplified version of what we're doing, so although this example is trivial, it illustrates the issue we're facing. I also understand that many people don't like global variables. Given the legacy code and framework being used, we need to solve this specific problem.
Thank you for you help!

class TestClass {
public function do_stuff() {
global $myvar;
$myvar= 'the value we want';
}
}
function get_var() {
global $myvar;
echo $myvar; // here the value does NOT exist
}
get_var();
echo $myvar; // but here the value DOES exist
Will be what you got, now if you actual use the class and execute it.
class TestClass {
public function do_stuff() {
global $myvar;
$myvar= 'the value we want';
}
}
function get_var() {
global $myvar;
echo $myvar; // here the value does NOT exist
}
$TestClass = new TestClass();
$TestClass->do_stuff();
get_var();
echo $myvar;
Should echo what you want. Order of operations still matter, just because something is placed in a class doesn't mean it get's magically executed.
For example this
get_var();
$TestClass = new TestClass();
$TestClass->do_stuff();
Is still unset
To be completely honest though, I would avoid using global at all because the main issue with that method is that you cannot trace where the value in it is from, For example using a class to hold the value, it is then very easy to find the class. To me use of code like that is just lazyness on the part of the developer.
UPDATE: that is odd then because running this:
class TestClass {
public function do_stuff() {
global $myvar;
$myvar= 'the value we want';
}
}
$TestClass = new TestClass();
$TestClass->do_stuff();
function get_var() {
global $myvar;
echo $myvar; // here the value does NOT exist
}
get_var();
echo $myvar;
ON WAMP with php 5.4 works fine and outputs
the value we wantthe value we want
Note though I ran it as a complete block, in the same file. But again I feel I have to say that you would be better off injecting the value into the function instead of mucking with global it's something that should be done away with IMO.
$TestClass = new TestClass();
get_var($TestClass->do_stuff());
What's the purpose of get_var, I know this is an example. But what are you trying to do that you need global for. There are other things that can be done such as throw and catch exceptions, debug_backtrace(), dependancy injection being the obvious one.
here is just one of may articles you can find on the subject.
http://c2.com/cgi/wiki?GlobalVariablesAreBad
As a professional web developer and a CIO, I have to agree with them.

The correct would declare the variable outside the function and then use global, or this to call the variable.
$myVar = null;
funcion get_var(){
global $myVar;
$myVar = 10;
for ($i = 0; i < $myVar; $i++){
var_dump($i);
}
}
Works fine for me.

Related

Access a class within a function

Using as an example the class defined here
class Testclass {
private $testvar = "default value";
public function setTestvar($testvar) {
$this->testvar = $testvar;
}
public function getTestvar() {
return $this->testvar;
}
function dosomething()
{
echo $this->getTestvar();
}
}
$Testclass = new Testclass();
$Testclass->setTestvar("another value");
$Testclass->dosomething();
I would like to add inside a function "one more value", like this:
function test_function() {
$Testclass->setTestvar("one more value");
}
But it doesn´t work. I gives the error message undefined variable Testclass. In order to make it work, I have to define the variable as global within the function, like this:
function test_function() {
global Testclass;
$Testclass->setTestvar("one more value");
}
I am quite new to PHP, but it seems rather strange to me this way of using it. From the main PHP file it´s already defined, but when I use it from a function I have to define again.Basically what I am trying to do is to create a class that creates a new file and adds strings to it from different functions. Is there not a better way? Any suggestions? Many thanks in advance.
One way is to use singleton
MyClass::getInstance()->doSomethingUsefull();
Sometimes you can use static method
MyClass::doIt();
Functions have their own private variable scope. So (for example) you can use $i in a function without worrying about it screwing up another $i somewhere else in the program. If you want to have a function perform actions on an already-existing object, just pass the object as a parameter to the function:
function test_function(Testclass $testclass)
{
$testclass->setTestvar("one more value");
}
Then call it with your object:
$Testclass = new Testclass();
test_function($Testclass);
Note: If the functions you're defining outside the class are tightly related to the class, then you probably want to define them as methods inside the class instead of separate stand-alone functions.

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;
?>

Modify the class property inside the class function

I got the code from php.net website:
<?php
class foo {
public $foo;
public $bar;
public function foo() {
$this->foo = 'Foo';
$this->bar = array('Bar1', 'Bar2', 'Bar3');
}
}
$foo = new foo();
echo <<<EOT
I am printing some $foo->foo.
Now, I am printing some {$foo->bar[1]}.
EOT;
?>
But I'm confused, what is every "foo" stand for? Can you really modify the properties(variables) inside a method(function) without calling the function?
I write a similar code but nothing happened
<?php
class page {
public $meta;
public $buttons;
public function show_meta() {
$this->meta = "I'm a website";
$this->buttons = array(
"home" => "index.php",
"about" => "about.php"
);
}
}
$index = new page();
echo $index->meta;
echo $index->buttons["home"];
?>
I'm a php learner, I need your help please :)
function foo is a PHP4-style constructor (note that the function has the same name as the class). In PHP5 you would write function __construct() instead.
new foo() actually calls the constructor, initilizing your variables.
On the first, yes, because your properties are public.
On the second case, you have reference with a string to remove the warning.
$index->buttons["home"];
You never call show_meta so the array is never populated.
this is the old php syntax for constructor methods. Constructors are Special methods, which are called, whenever a new object from the class is created. The new naming convention for constructors say, all constructors are named __construct.
To get the code above to work, you have to call show_meta, before accessing the two vars or make show_meta the constructor.
$index = new page();
$index->show_meta();
echo $index->meta;
echo $index->buttons["home"];
btw.. home is a string and should be inside "", or you raise at least a warning.

How to Pass a function to a class in php

I have a class that generates data based on a few things. I would like to format that data from the outside. So I am trying to pass a function into the class so that it would format that data. I have looked at many examples, but it seems this is unique.
Can anybody give an idea of how to do this? The following code gives an error.
<?php
class someClass {
var $outsideFunc; // placeholder for function to be defined from outside
var $somevar='Me'; // generated text
function echoarg($abc){
$outsideFunc=$this->outsideFunc; // bring the outside function in
call_user_func($outsideFunc,$abc); // execute outside function on text
echo $abc;
}
}
function outsidefunc($param){ // define custom function
$param='I am '.$param;
}
$someClass=new someClass();
$someClass -> outsideFunc = 'outsideFunc'; // send custom function into Class
$someClass -> echoarg($someClass->somevar);
$someClass -> outsidefunc = 'outsidefunc';
In PHP, function names are not case sensitive, yet object property names are. You need $someClass->outsideFunc, not $someClass->outsidefunc.
Note that good OOP design practice calls for the use of getter and setter methods rather than just accessing properties directly from outside code. Also note that PHP 5.3 introduced support for anonymous functions.
Yeah. You are right. Now there is no error. But it does not work either.
By default, PHP does not pass arguments by reference; outsidefunc() does not actually do anything useful. If you want it to set $param in the caller to something else, and do not want to just return the new value, you could change the function signature to look like this:
function outsidefunc(&$param) {
You would also need to change the way you call the function, as call_user_func() does not allow you to pass arguments by reference. Either of these ways should work:
$outsideFunc($abc);
call_user_func_array($outsideFunc, array(&$abc));
Why not pass your function as an argument?
<?php
class someClass {
public $somevar="Me";
public function echoarg($abc,$cb=null) {
if( $cb) $cb($abc);
echo $abc;
}
}
$someClass = new someClass();
$someClass->echoarg($someClass->somevar,function(&$a) {$a = "I am ".$a;});
i am not sure what exactly you are looking for, but what i get is, you want to pass object in a function which can be acheive by
Type Hinting in PHP.
class MyClass {
public $var = 'Hello World';
}
function myFunction(MyClass $foo) {
echo $foo->var;
}
$myclass = new MyClass;
myFunction($myclass);
OP, perhaps closures are what you're looking for?
It doesn't do EXACTLY what you're looking for (actually add function to class), but can be added to a class variable and executed like any normal anonymous function.
$myClass->addFunc(function($arg) { return 'test: ' . $arg });
$myClass->execFunc(0);
class myClass {
protected $funcs;
public function addFunc(closure $func) {
$this->funcs[] = $func;
}
public function execFunc($index) { $this->funcs[$index](); } // obviously, do some checking here first.
}

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();
}
?>

Categories