PHP object class variable - php

I have built a class in PHP and I must declare a class variable as an object. Everytime I want to declare an empty object I use:
$var=new stdClass;
But if I use it to declare a class variable as
class foo
{
var $bar=new stdClass;
}
a parse error occurs. Is there a way to do this or must I declare the class variable as an object in the constructor function?
PS: I'm using PHP 4.

You can only declare static values this way for class members, i.e. ints, strings, bools, arrays and so on. You can't do anything that involves processing of any kind, like calling functions or creating objects.
You'll have to do it in the constructor.
Relevant manual section:
In PHP 4, only constant initializers for var variables are allowed. To initialize variables with non-constant values, you need an initialization function which is called automatically when an object is being constructed from the class. Such a function is called a constructor (see below).

Classes and Objects (PHP 4). A good read everytime!

You should not create your object here.
You should better write setter and getter
<?php
class foo
{
var $bar = null;
function foo($object = null)
{
$this->setBar($object);
}
function setBar($object = null)
{
if (null === $object)
{
$this->bar = new stdClass();
return $this;
}
$this->bar = $object;
return $this;
}
}
By the way, you should use PHP5 to work with OOP, which is more flexible...

Related

Unset all instances of an object PHP

I have a class with a method that returns a new instance of itself.
This allows me to use one single object without having to declare new ones over and over with the same values. For those wondering why not extending the class or something else, it just makes my life easier and it works like a charm, but my final purpose is to remove them all in one line.
for example:
$foo = new myClass('name1','ab','cd');
$bar = $foo->duplicate();
//duplicate() saves the new object in itself in an array:
array_push($this->instance,new myClass('name1','ab','cd'));
//and returns a pointer to the saved instance.
return end($this->instance);
$foo and $bar now share the same methods and values but those values can be modified separately.
$foo->changeName('newName');
$bar->changeName('newName2');
My question here is, if I unset the first class created unset($foo) will PHP automatically unset the other instances ($bar) or will the garbage collector remove them eventually?
I have tested it by unsettling $foo and gives me an error when I call $foo but not when I call $bar.
What I am trying to do is to unset all the instances of that class at once.
Thanks.
Automatic cleanup?
No, PHP isn't awared about your architecture. It will not remove objects "cascade", they are independent entities - and, more, can belong to different scopes, for example. Simple code:
class Test
{
protected $id = null;
protected $uniqid = null;
public function __construct($id)
{
$this->id = $id;//user-passed variable
$this->uniqid = uniqid();//internal: to identify instance
}
public function getCopy()
{
return new self($this->id);
}
public function getIdentity()
{
return $this->uniqid;
}
}
$foo = new Test(3);
$bar = $foo->getCopy();
var_dump($foo->getIdentity());//valid
unset($foo);
//still valid: bar has nothing to do with foo
var_dump($bar->getIdentity());
By the way, for copying you can use clone in PHP (that, however, will result in object cloning, obviously)
Simple way
Most simple way to resolve a matter is to iterate through $GLOBALS, checking it with instanceof. This has serious weakness: inner function/method scopes would not be affected:
//static since doesn't belong to any instance:
public static function cleanup()
{
foreach($GLOBALS as $name=>$var)
{
if($var instanceof self)
{
unset($GLOBALS[$name]);
}
}
}
-and
$foo = new Test(3);
$bar = $foo->getCopy();
var_dump($foo->getIdentity(), $bar->getIdentity());//valid
Test::cleanup();
//2 x notice:
var_dump($foo, $bar);
Note, that is has nothing to do with "child" mechanics (i.e. it will clean all instances in global scope - no matter which was copied from which).
Common case
Sample above will not do the stuff in common case. Why? Imagine that you'll have holder class:
class Holder
{
protected $obj = null;
public function __construct($obj)
{
$this->obj = $obj;
}
public function getData()
{
return $this->obj;
}
}
and you'll pass instance to it:
$foo = new Test(3);
$bar = $foo->getCopy();
$baz = new Holder($bar);
-so then you'll have no chances to handle even this simple situation in common case. And with more complex situations you will also be stuck.
What to do?
I'd recommend: destroy objects explicitly when you need to do that. Implicit unset is a side-effect, and even if you'll maintain that somehow (I can imagine Observer pattern + some global registry for that) - it will be horrible side-effect, that will kill readability for your code. And same is about code, that uses $GLOBALS I've written above - I do not recommend to act such way in any case.
Try the below code to clear all php objects.
public function clearAllVars()
{
$vars = get_object_vars($this);
foreach($vars as $key => $val)
{
$this->$key = null;
}
}
}
From what I understand from the PHP reference here :
http://www.php.net/manual/en/features.gc.refcounting-basics.php
destroying the main instance will not automatically destroy all other instances since they do not ultimately point to the same 'zval'.
However the garbage collection will eventually destroy all instances if they are not referenced anymore. Since in your example $bar still references the second instance, it will not be destroyed.
What you could do if you want to unset them all at the same time :
Use a static array referencing all the instances of your object
Every time you create a new object add a reference to this object in the static array of the class
Use a static function unsetAll() which loops through this array and unset one by one all instances

$_data vs $this->_data - PHP

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

php passing an object back from a class function

I have a set of PHP functions that I want to move into a new class. One of the functions is using &$obj in an argument to modify the original object:
function process_new_place_names(&$obj)
any changes made to $obj in this function are passed back to the script.
Question is, can I do this inside a PHP class too? Also, what is the terminology of this approach?
You can absolutely do this inside of classes. It's known as passing by reference.
Further reading:
http://php.net/manual/en/language.references.php
http://php.net/manual/en/language.oop5.references.php
As SomeKittens says, this is perfectly possible inside a class. However, if $obj is itself an instance of a class, and all you need to do is modify its member variables (known as mutating the object) then there's no need to pass it by reference.
For example, the following code will output baz;
class Foo
{
public $bar;
}
function process_new_place_names($obj)
{
$obj->bar = 'baz';
}
$obj = new Foo();
$obj->bar = 'bar';
process_new_place_names($obj);
echo $obj->bar;
Pass-by-reference is only necessary when you want to change the value of the variable itself; for example, re-assigning the object reference:
function process_new_place_names(&$obj)
{
$obj = new Foo();
$obj->bar = 'baz';
}

Using Global Variable [duplicate]

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.

member variable and member function have the same name

class test {
public $isNew;
public function isNew(){}
}
$ins = new test();
$ins->isNew
Here,how does php parse $ins->isNew?
PHP is not a functional programming language where functions are also data. So $ins->isNew wouldn’t be ambiguous to either refer to the method isNew or the attribute isNew. $ins->isNew is always an attribute and $ins->isNew() a method call.
$ins->isNew is the variable.
$ins->isNew() is the function.
See the chapter on Class Basic in the PHP manual:
$ins->isNew // class member
$ins->isNew() // class method
Used a, b, c for easier differentiation. As you can see, you call each of them in a different way, and that is how PHP knows which one you want. You can rename c() to a() or b(), but you cannot rename $b to $a, because multiple properties with the same variable names are not allowed.
class Class
{
public $a = true;
public $b = function () {return true;};
public function c() {return true;}
}
$class = new Class();
$class->a;
($class->b)();
$class->c();
That being said, I wouldn't name methods and properties with the same name, unless the method is the actual getter for the property.
class Class
{
private string $name;
public function name() {
// Null coalesce assignment operator is available since PHP 7.4
$this->name ??= $this->fetchNameFromSender();
$this->name ??= $this->fetchNameFromDocument();
$this->name ??= $this->fetchNameFromWhatever();
return $this->name ?? '[Could not fetch name]';
}
...
}
$class = new Class();
$class->name();
See the following section, Variable functions, in the PHP manual.
PHP supports the concept of variable functions. This means that if a variable name has parentheses appended to it, PHP will look for a function with the same name as whatever the variable evaluates to, and will attempt to execute it. Among other things, this can be used to implement callbacks, function tables, and so forth.

Categories