I'm trying to figure out the difference between $_data vs $this->_data
class ProductModel
{
var $_data = null; <--- defined here
function test()
{
$this->_data = <--- but it's accessed using $this
}
}
I know in PHP var is used to define class properties but Why is it accessed using $this. Shouldn't it be like $this->$_data ? What's OOP concept is being used here ? Is it a PHP specific?
PHP along with several other popular programming languages such as Java (it's important to note that PHP's Object Oriented choices were at least partially inspired by Java) refer to the current object instance in context as this. You can think of this, (or $this in PHP) as the "current object instance."
Inside of class methods, $this refers to the current object instance.
A very small example using what you have above:
$_data = 'some other thing';
public function test() {
$_data = 'something';
echo $_data;
echo $this->_data;
}
The above will output somethingsome other thing. Class members are stored along with the object instance, but local variables are only defined within the current scope.
No, it shouldn't. Since PHP can evaluate member names dynamically, the line
$this->$_data
refers to a class member, which name is specified in local $data variable. Consider this:
class ProductModel
{
var $_data = null; <--- defined here
function test()
{
$member = '_data';
$this->$member = <--- here you access $this->_data, not $this->member
}
}
var $_data defines a class variable, $this->_data accesses it.
If you do $this->$foo it means something else, just like $$foo : if you set $foo = 'bar', those two expressions are respectively evaluated as $this->bar and $bar
Related
New to php. I am writing a class and was wondering why some variable $variable does not need a $ when calling $this->variable?
In Object Oriented Programming when you declare variables like so
public $variable;
these are no more variables but are the properties of the object of the class.
So when we call these properties we reference these through $this->property Which means that we are calling the property of the present object. $this refers to the instance of the present class. Whenever you would call properties and methods within class you have to use $this->property-or-method.
It is not the variable. It means object oriented.
It's a reference to the current object, it's most commonly used in object oriented code.
Reference: http://www.php.net/manual/en/language.oop5.basic.php
Primer:http://www.phpro.org/tutorials/Object-Oriented-Programming-with-PHP.html
Example:
<?php
class Person {
public $name;
function __construct( $name ) {
$this->name = $name;
}
};
$jack = new Person('Jack');
echo $jack->name;
This stores the 'Jack' string as a property of the object created.
Because that variable is inside a larger variable called an Object and the object knows how to access it's inner variables / functions. Like a smart-variable.
Objects can be used to group data or similar functions (called method's when they are inside of an object)
For data/values, you could also use an array. It's common to see data stored in objects as well.
But you wouldn't store functions in an array. In PHP that's a no-go, but in JavaScript that's all good.
Back to objects, functions stored in objects are called methods. Objects can contain methods or properties.
Object Method / Function Example from: http://php.net/manual/en/language.types.object.php
<?php
class foo
{
function do_foo()
{
echo "Doing foo.";
}
}
$bar = new foo;
$bar->do_foo();
// also valid $bar::do_foo();
?>
Object Property / Variable Example From: http://php.net/manual/en/language.oop5.properties.php
<?php
class SimpleClass
{
// valid as of PHP 5.6.0:
public $var1 = 'hello ' . 'world';
// valid as of PHP 5.3.0:
public $var2 = <<<EOD
hello world
EOD;
// valid as of PHP 5.6.0:
public $var3 = 1+2;
// invalid property declarations:
public $var4 = self::myStaticMethod();
public $var5 = $myVar;
// valid property declarations:
public $var6 = myConstant;
public $var7 = array(true, false);
// valid as of PHP 5.3.0:
public $var8 = <<<'EOD'
hello world
EOD;
}
?>
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.
I've got a class Foo with public and protected properties. Foo needs to have a non-static method, getPublicVars() that returns a list of all the public properties of Foo (this is just an example, I know from outside the Foo object calling get_object_vars() will accomplish this and there is no need for my getPublicVars() method).
Note: This must also return dynamically declared properties assigned at runtime to the class instance (object) that aren't defined in the class's definition.
Here's the example:
class Foo{
private $bar = '123';
protect $boo = '456';
public $beer = 'yum';
//will return an array or comma seperated list
public function getPublicVars(){
// thar' be magic here...
}
}
$foo = new Foo();
$foo->tricky = 'dynamically added var';
$result = $foo->getPublicVars();
var_dump($result); // array or comma list with 'tricky' and 'beer'
What is the most concise way to get the only the public properties of an object from inside a class's own methods where both public and protected are visible?
I've looked at:
What is the best way to look inside a PHP class instance (object) to see all of its available public properties and methods?
But this doesn't seem to address my question as it points to using get_object_vars() from outside the object.
As you already realized, PHP's build in get_object_vars is scope-sensitive. You want the public object properties only.
So from that function to the public variant is not a large step:
function get_object_public_vars($object) {
return get_object_vars($object);
}
Calling this get_object_public_vars will give you only the public properties then because it is place out of scope of the current object.
If you need more fine-grained control, you can also make use of the ReflectionObject:
(new ReflectionObject($this))->getProperties(ReflectionProperty::IS_PUBLIC);
Which has the benefit that you don't need to introduce another function in the global namespace.
Does not work with php version >=7
As such, I can't really recommend solution any longer.
Use reflection instead
To get the public properties from within the class
$publicProperties = call_user_func('get_object_vars', $this);
the "trick" is that get_object_vars is being called from the scope of call_user_func and not the scope of the object
no need for reflection, stand-alone functions, closures, etc
Another (PHP 7.* compatible) way is to cast $this to an array and filter out any binary keys. This is a little less verbose than using Reflection.
return array_filter(
(array) $this,
static fn(string $key): bool => strpos($key, "\0") !== 0, ARRAY_FILTER_USE_KEY,
);
Using the ReflectionClass, you can do this easily. For example, below, I make an associative array of all the public properties.
$rc = new \ReflectionClass($this);
//get all the public properties.
$props = $rc->getProperties(\ReflectionProperty::IS_PUBLIC);
$ret = [];
foreach($props as $p) {
//get the name and value of each of the public properties.
$ret[$p->getName()] = $p->getValue($this);
}
You can wrap it into a closure and bind it to nowhere, then you'll have an outer scope view to the local public properties.
public function getPublicVars(){
return \Closure::bind(fn($obj) => get_object_vars($obj),null,null)($this);
}
According to this article (written by Vance Lucas), you can create a new call scope inside your "Foo" class definition using an "anonymous" function, and then you can call get_object_vars() from within. This allow you to get only the public properties from inside your class, even if these have been created dynamically later from the outside.
So adapted to your example it would be:
<?php
class Foo {
private $bar = '123';
protected $boo = '456';
public $beer = 'yum';
// return an array of public properties
public function getPublicVars(){
$publicVars = create_function('$obj', 'return get_object_vars($obj);');
return $publicVars($this);
}
}
$foo = new Foo();
$foo->tricky = 'dynamically added var';
$result = $foo->getPublicVars();
print_r($result);
and the output will be:
Array
(
[beer] => yum
[tricky] => dynamically added var
)
There is a second example in the article mentioned above that shows another way to do the same using the so-called "closures" (from php 5.3) but for some reason it doesn't work for me with php v5.4 so the private and protected properties remains included in the resulting array.
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.