Say that I have a class like this:
class MyClass {
public $variable;
public function __construct($variable) {
$this->variable = $variable;
}
}
and I call it like this (without initializing it, or as far as php is concerned it's not even a class):
$my_class = null;
$v = $my_class->variable;
Is this allowed in php? It would give a big fat null pointer exception in most other languages. If it works, what's the value of variable?
It is "sort of" allowed - you will get a Notice: Trying to get property of non-object and the result will be NULL.
I anyway don't see a point of doing that.
That doesn't make sense...
If you declare a variable $my_class, and makes it NULL, every attribute given to that variable is null.
Of course, for php you're not doing anything wrong. You're just declaring that a variable is null.
This would be different if you declare $my_class as an object of your class MyClass, because you must give an attribute, even if this is null
class MyClass
{
public static $variable;
public function __construct($variable)
{
$this->variable = $variable;
}
}
\MyClass::$variable = null;
echo \MyClass::$variable;
Related
I have the following code in my User class:
class User {
public int $id = 0;
public string $code;
public string $name;
}
When assigning $code from the database, I need to find out what type the var is before I can assign it, so I use gettype(), in the __construct function for User:
foreach($data as $key => $val) {
settype($val, gettype($this->$key));
$this->$key = $val;
}
However it returns this error:
Fatal error: Uncaught Error: Typed property User::$code must not be accessed before initialization
I understand what the error message means.
Is there a way to find out the casted type of the variable before its been set?
I'm not sure what exactly you are attempting to do, and without knowing more about the whole thing I won't risk an opinion about the logic of it.
Putting that aside, using gettype() on an uninitialized typed property won't work, because the property has effectively no value at that point.
But, since the property is typed, you could get the property defined type via reflection:
class User {
public int $id = 0;
public string $code;
public string $name;
public function __construct() {
$reflect = new ReflectionClass($this);
$props = $reflect->getProperties();
foreach ($props as $prop) {
echo $prop->getType()->getName(), "\n";
}
}
}
new User();
The above would output:
int
string
string
Doing this on the fly seems like a lot of overhead, so please make sure that there is no better tool at your disposal. Doing this kind of thing on the __construct() method does not look very wise at first sight, but of course I do not know your specific constraints.
If you create a variable as
$foo;
then it is null until it is successfully initialized, so it has no type.
If it is a typed property, then it is simply uninitialized, not null. The rest of my answer contains some experiments conducted based on the information received in the comment-section. So, a variable or property is null before it is initialized, with the exception of typed properties, which are simply uninitialized.
In the comment section it was suggested that the uninitialized variable does not equal to null. So I have written this test code:
<?php
$foo;
echo var_dump($foo === null);
and executed it
It gives a warning and evaluates to true, so the uninitialized variable was indeed null.
Since yivi pointed out that the question refers to a property, I have conducted another experiment:
<?php
class Foo {
public $foo;
public function __construct() {
echo var_dump($this->foo === null);
}
}
new Foo();
and the result is
I get an error saying unexpected '(' when trying to do this in a class:
private $doglist = file_get_contents('dogdropdown.html');
Is that not allowed for some reason?
I also tried using a function like this:
public function getDogList(){
$list = file_get_contents('dogdropdown.html');
return $list;
}
which also didnt work. if I used include it does but doesnt inlcude it in the right place.
When you declare a class property you can only assign basic scalar values or null for variables that should reference objects. If the property needs to hold the result of some operation you either make it static or assign the result either in the constructor or a method of the class.
In order to do what you are trying to do you need the following:
class MyClass {
private $doglist;
function __construct() {
$this->doglist = file_get_contents('dogdropdown.html');
}
}
I have a class
Class MyClass{
private $prop1;
private $prop2; // this contains an array object
public function __construct(){ }
public function set_prop2($prop2)
{
$this->prop2= $prop2; // value coming from other class that returns array object
}
public function func1()
{
global $prop1;
global $prop2;
$var1 = // some value;
$var2 = $prop1;
$var3 = // some value;
$obj = new SomeClass($prop2);
$json = $obj->setVar2($var2)
->someMethod($var1, $otherMethod)
->method();
}
}
using global properties inside method, the class above works for me by calling
obj1 = new MyClass();
obj1->func1(); // I want to call it like this (without parameters)
I know declaring global inside the method is not a good thing but its the only way I can make the method works!
any ideas how I can better the syntax so I can call the method without parameters like obj1->func1(); is greatly appreciated.
NOTE: tried to declare as
$this->prop1;
$this->prop2;
but it gives me a Catchable fatal error: Argument 1 passed to... because $prop2 was not passed properly if using $this->prop2;
Class MyClass{
public $prop1;
public $prop2; // this contains an array object
public function __construct(){ }
public function set_prop2($prop2)
{
$this->prop2= $prop2; // value coming from other class that returns array object
}
public function func1()
{
$var1 = // some value;
$var2 = $this->prop1;
$var3 = // some value;
$obj = new SomeClass($this->prop2);
$json = $obj->setVar2($var2)
->someMethod($var1, $otherMethod)
->method();
}
}
You are confusing 3 different things here:
Global variables, which exist outside any function, class, or object, have to be "imported" into the current scope with the global keyword. They are generally considered bad practice as they lead to code which "magically" transports data from one place to another, making reuse, testing, and debugging more difficult.
Object properties are declared in a class definition, and belong to an instance of that class (or to the class itself, in the case of static variables). They are accessed with the syntax $object->property. The private keyword means the variable can only be seen inside the class, by using the special variable $this, meaning "this object I am inside", e.g. echo $this->prop1;
Function arguments are passed in when you call a function. Inside the function, they are local variables with the names given in the function definition, so do not need to be imported or prefixed in any way. Object methods are basically just functions "attached to" a particular object, and work in the same way.
In your example, you have a comment against an object property here...
private $prop2; // this contains an array object
...but you then say that using that variable (with $this->prop2) gave an error (which you haven't actually shown us properly yet) suggesting that it was not an array. (As mentioned in the comments, "array object" is an odd choice of words. I'm going to assume you just meant "array" for now.)
You then "solve" this by instead using a global variable...
global $prop2;
$obj = new SomeClass($prop2);
...which is a completely different variable.
You also show a definition of a method for setting your private property...
public function set_prop2($prop2)
...but you never show us where you're calling it.
You've annotated it with a comment suggesting where you think it's being called...
// value coming from other class that returns array object
...but the entire question hinges on where that function argument comes from.
One of the things that makes your code hard to read is that the object property, the global variable, and the function argument all have the same name. This doesn't make them the same variable.
What you could try is separating out the different variables, and looking at each in turn:
class MyClass {
private $private_property;
public function set_prop2($new_value_for_prop2) {
var_dump($new_value_for_prop2); // what's the value passed in?
$this->private_property = $new_value_for_prop2;
}
public function func1() {
var_dump($this->private_property); // what value is it now?
}
}
$function_return = some_function();
var_dump($function_return); // is it an array?
$obj = new MyClass;
$obj->set_prop2($function_return); // should show you the value being set
$obj->func1(); // should show the same value again
You can use session functions but I'm not sure that is a good idea for the security... Depend the critical of the parametres...
<?php
Class MyClass{
private $prop1;
private $prop2; // this contains an array object
public function __construct(){ }
public function set_prop2($prop2)
{
$this->prop2= $prop2; // value coming from other class that returns array object
}
private function func1()
{
$prop1 = $_SESSION['prop1'];
$prop2 = $_SESSION['prop2'];
$var1 = // some value;
$var2 = $prop1;
$var3 = // some value;
$obj = new SomeClass($prop2);
$json = $obj->setVar2($var2)
->someMethod($var1, $otherMethod)
->method();
}
}
?>
And for calling :
<?php
session_start();
$_SESSION['prop1'] = $prop1;
$_SESSION['prop2'] = $prop2;
obj1 = new MyClass();
obj1->func1();
?>
I'm new to PHP and practicing using static variables. I decided to grab an example that I learnt from C++ and re-write it for PHP (example from the bottom of this article).
There's a class with two private variables (one static), a constructor and a get-method. The constructor assigns the static variable's value to the second private variable, and then increments.
<?php
class Something
{
private static $s_nIDGenerator = 1;
private $m_nID;
public function Something() {
$m_nID = self::$s_nIDGenerator++;
echo "m_nID: " . $m_nID . "</br>"; //for testing, can comment this out
}
public function GetID() {
return $m_nID;
}
}
// extra question:
// static variable can be assigned a value outside the class in C++, why not in PHP?
// Something::$s_nIDGenerator = 1;
$cFirst = new Something();
$cSecond = new Something();
$cThird = new Something();
echo $cFirst->GetID() . "</br>";
echo $cSecond->GetID() . "</br>";
echo $cThird->GetID() . "</br>";
?>
Using the echo test in line 9 to see if m_nID is getting a value I see:
m_nID: 1
m_nID: 2
m_nID: 3
But these values are not being returned by the "->GetID()" calls. Any ideas why?
Edit: both replies so far have solved this, I wish I could "check" them both, so thank you! I'll leave the original code in the question as-is for any future people who have a similar problem
Your background in C++ led up to this issue, which is an easy mistake to make. In PHP, all instance (or object) variables are referenced using $this->, and static (or class) variables with self::. Based on your code:
public function GetID() {
return $m_nID;
}
Access to the private variable $m_nID should be scoped like this:
public function GetID() {
return $this->m_nID;
}
And inside your constructor:
$m_nID = self::$s_nIDGenerator++;
It should have been:
$this->m_nID = self::$s_nIDGenerator++;
Q & A
Why is there no need to put $ before m_nID when using $this->
The above two ways of referencing instance and class variables come with a very different kind of syntax:
$this is the instance reference variable and any properties are accessed using the -> operator; the $ is not repeated for the property names themselves, although they're present in the declaration (e.g. private $myprop).
self:: is synonymous to Something:: (the class name itself); it doesn't reference an instance variable and therefore has no $ in front of it. To differentiate static variables from class constants (self::MYCONST) and class methods (self::myMethod()) it's prefixed with a $.
Extra
That said, $this->$myvar is accepted too and works like this:
private $foo = 'hello world';
function test()
{
$myvar = 'foo';
echo $this->$foo; // echoes 'hello world'
}
class Something{
private static $s_nIDGenerator = 1;
private $m_nID;
public function Something() {
$this->m_nID = self::$s_nIDGenerator++;
}
public function GetID() {
return $this->m_nID;
}
}
It is interesting to note the difference between using self::$s_nIDGenerator on a static variable vs using $this->s_nIDGenerator on a static variable, whereas $this-> will not store anything.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
To pass value of a variable in one function to another function in same class
Can a value of a variable in one function be made available in another function on the same class using "GLOBAL" in PHP. If so please suggest how can this be achieved using Global.
You don't need to make a variable GLOBAL if you're within an object.
class myClass {
public $myVar = "Hello";
function myFunction() {
echo $this->$myVar;
}
}
This is one of the main points of objects - that you can assign different values to variables and get/set those variables within the different methods. And also that you can create multiple instances of objects each holding different information within the same structure and with the same methods available.
Additionally to what #Codecraft said (about using public properties), you can use:
indeed global variable (which is really something you should avoid doing),
passing values in parameters,
static variable within class,
Below is the example of using static variable (private), because I think this suits your needs best:
class MyClass {
private static $_something;
public function write() {
static::$_something = 'ok';
}
public function read() {
return static::$_something;
}
}
$x = new MyClass();
$x->write();
var_dump($x->read());
which outputs:
string(2) "ok"
This is in fact something like a global, but available only from inside your class (because of the keyword "private") and common among every instance of the class. If you use setting some non-static property, it will change across different instances of the class (one object may have different value stored in it than the other object has).
Comparison of solutions based on static and non-static variables:
Solution based on static variable will give you really global-like behaviour (value passed across different instances of the same class):
class MyClass {
private static $_something;
public function write() {
static::$_something = 'ok';
}
public function read() {
return static::$_something;
}
}
// first instance
$x = new MyClass();
$x->write();
// second instance
$y = new MyClass();
var_dump($y->read());
which outputs:
string(2) "ok"
And the solution based on non-static variables will look like:
class MyClass {
private $_something;
public function write() {
$this->_something = 'ok';
}
public function read() {
return $this->_something;
}
}
// first instance
$x = new MyClass();
$x->write();
// second instance
$y = new MyClass();
var_dump($y->read());
but will output:
NULL
which means that in this case the second instance has no value assigned for the variable you wanted to behave like "global".
Yes, a value of a variable in one function can be made available in another function on the same class using "GLOBAL". The following code prints 3:
class Foo
{
public function f1($arg) {
GLOBAL $x;
$x = $arg;
}
public function f2() {
GLOBAL $x;
return $x;
}
}
$foo = new Foo;
$foo->f1(3);
echo $foo->f2();
However, the usage of global variables is usually a sign of poor design.
Note that while keywords in PHP are case-insensitive, it is custom to use lower case letters for them. Not also that the superglobal array that contains all global variables is called $GLOBALS, not GLOBAL.