echo 'test';
class createdclass {
public $name;
}
class testc {
function &testm(){
$myvar =& new createdclass();
return $myvar;
}
}
$testo = new testc();
$a =& $testo->testm();
$a->name = 'Douglas';
$b =& $testo->testm();
$b->name = 'Scott';
echo $a->name;
echo $b->name;
myvar is a reference to an object
a and b are references to the same object
I changed a, then I changed b, but a wasn't changed by b
Why?
In your code each call to testm() creates a new instance of createdclass. So $a and $b aren't the same object.
Ok, first off, you shouldn't use $myvar =& new .... It's a deprecated syntax and is completely unnecessary (Since there's nothing to reference to)...
Secondly, you don't need the =& operator in the lines $a =& $testo->testm(). The fact that the method returns a reference is good enough. Not to mention that objects are passed by reference by default anyway, so you really don't need those lines anyway. I put them in the method signature function &foo() mainly for readability (to show that we're expecting the return to be a reference)...
Third, the problem is what you're referencing. References bind to a variable. When you leave the scope, since $myvar is a local variable (and as such is garbage collected -- it is deleted -- when the method exits), the bound reference disappears. So if you want that to work, you need to persist that variable.
Here's one example that works:
class testc {
protected $createdclass = null;
public function __construct() {
$this->createdclass = new CreatedClass();
}
public function &testm() {
return $this->createdclass;
}
}
$tester = new testc;
$a = $tester->testm();
$a->name = 'foo';
$b = $tester->testm();
echo $b->name; //displays "foo"...
in your example, a and b do not reference the same object because you create a new one in the testm() function.
here is a short example that might clarify things a little:
<?php
class createdclass {
public $name;
}
$a = new createdclass();
$a->name = 'Douglas';
// make $b reference the same as $a, i.e. let $p point to the same content as $a
$b = &$a;
$b = new createdclass();
$b->name = 'Scott';
echo $a->name;
echo $b->name;
?>
this will output ScottScott
if you want to learn more about references in php i'd recommend to read References Explained in the php manual
Related
I was looking at OOP Basics and saw a code like this (simplified it a bit)
You can see this class and the output
class Test{}
$a = new Test();
$b = new $a;
var_dump($b == $a); // true
What I don't understand is the $b = new $a but $a is already an object, so how/why does this work? If I do vardump $a the output is:
object(Test)#1 (0) {
}
So, how can that variable work with new keyword. I thought we could only use new with a class that is defined already, or with a string that points to a class ex:
$var = 'Test';
new $var; // ok
but in this case, $var is a string, not an another object.
It is a shortcut for creating new object. Before PHP 5.3.0 you have to do this:
$class = get_class($instance);
$newInstance = new $class;
As of PHP 5.3.0 you can do the same thing with this:
$newInstance = new $instance;
Very useful, in my opinion, because it eliminates the need for a temporary variable.
To clarify, this creates new object.
It is not cloning.
In other words, __construct() will be called instead of __clone().
I am a new in terms of PHP OOP programming, i don't understand when and how the following class names are and when shall i use them :
$a = new Classname();
$a = new Classname;
$a = ClassName::function();
$a = ClassName::getInstance();
Many thanks and sorry for silly question:
These are identical.
$a = new Classname();
$a = new Classname;
You can use them interchangeably when the class constructor does not take, or does not require other parameters.
Example:
class Classname
{
public function __construct($var = null)
{
// ..
}
static public function getInstance()
{
// ..
}
}
In this case you can use $a = new Classname; and $var will take the default value, or $a = new Classname('hello') and $var will be equal to the value passed.
These are both static method calls.
$a = ClassName::function();
$a = ClassName::getInstance();
One calls a method called "function" (which cannot exist - it is a reserved word), the other calls a method named "getInstance". When you use them really depends on what the methods do.
Static methods can be called without creating an object instance.
I.e.
Classname::staticMethod();
versus
$obj = new Classname;
$obj->method;
As for
$a = new Classname();
$a = new Classname;
No difference if __construct() has no arguments to receive.
As for
$a = ClassName::function();
$a = ClassName::getInstance();
this is just normal call of static methods
For:
$a = new Classname();
$a = new Classname;
These are just 2 different ways of saying the same thing: Create a new reference to class "Classname" without any parameters (php is more lenient in regards to if () and parameters must be given or not than many other programming languages).
For:
$a = ClassName::function();
$a = ClassName::getInstance();
These two are static calls of the functions "function()" and "getInstance()", thus $a would be set to the appropriate return value of these function. Static means that you can use the
functions without referening the class itself (thus $b=ClassName(); $a=$b->function() is not needed instead you can just write it as you did above).
$a = true;
1,new test($a);
2,new test(true);
Is there a difference between them(1,2), if have,what's of it? thank you,.
Well the other one uses a variable and the other one doesn't. This causes a fatal error in this case:
class test {
public function __construct( &$a )
{
}
}
$a = true;
new test($a);
new test(true); //Fatal error because this cannot be passed by reference
Strictly speaking, it depends on how test is defined.
If test is defined such that input parameters are passed by reference, then 2 would raise a fatal error, since true is a literal value.
Also, test could have side effects that mean that the order in which you execute lines 1 and 2 matter.
It depends on the constructor of the test class. In a regular pass-by-value constructor they are exactly the same:
class test {
public $b;
function __construct($a) { $this->b = $a; }
}
Here, $obj->b will be true for both your statements, as expected.
If, on the other hand, you are passing by reference you may get different results if you change the global $a later on. Example:
class test {
public $b;
function __construct( &$a ) { $this->b = &$a; }
}
$a = true;
$obj = new test($a);
$a = false;
$obj->b will be false in this case because it is a reference to $a! With references, you can also do it the other way around, changing $a from within the constructor:
class test {
function __construct( &$a ) { $a = false; }
}
$a = true;
$obj = new test($a);
$a will now be false even in the global scope!
In addition, new test(true) is not possible to do when passing by reference because you cannot have a reference to a literal value, only to other variables.
I have:
class A{
public $name = 'A';
public $B;
public function B_into_A($b)
{
$this->B = $b;
}
}
class B{
public $name = 'B';
public $A;
public function new_A_into_B($a)
{
$this->A = new $a;
}
}
$a = new A;
$b = new B;
$a->B_into_A($b);
$b->new_A_into_B('A');
Is this a good way to insert another class inside a "main" class at the beginning of the runtime?
Should I use references?
(Background: I currently work on a MVC framework in which I have to handle many classes within some main classes e.g. bootstrapper, wrapper, modules, adapter etc.)
Yes and No...
Your first function call was fine, I would just use a more standard name:
$a = new A;
$b = new B;
$a->setB($b); // B_into_A is a little bit of a whacky function name
Your second call, it doesn't really make sense to pass a string and then create the object (Unless you're looking for some sort of factory). If you want B to own A:
$b->new_A_into_B( new A );
public function new_A_into_B($a)
{
$this->A = $a;
}
Again i don't like the name.. Id probably go with setA() there as well.
Passing an object instead of its class name makes sense because then it is easier for the garbage collector to guess when it is not needed anymore.
<?php
class A {
public $B;
}
class B {
public $A;
}
$a = new A;
$b = new B;
$a->B = $a;
$b->A = $b;
Furthermore, I'd try to get rid of the setter methods. In practice the only benefit they provide is to validate input. Since it's not the case here, I'd advise you to directly assign the classes.
You asked "Should I use references?". Actually all objects are passed by reference since PHP5. The only way to get an exact copy of them is to use the clone keyword.
By the way, you do not need to store the class name within each object. Just use get_class().
In the minutes php6 developer meeting, i came across a point where it said that call-time-pass-by-reference is no longer there in PHP6. For example, following both are incorrect for PHP6:
<?php
$foo =& new StdClass();
?>
<?php
function &foo()
{
return new StdClass();
}
$f = foo();
?>
If we can't use something like this in PHP6:
$foo =& new StdClass();
What is the alternative to that, is there any way to mimic that?
EDIT:
Ans what about variables in PHP6, can we do that for variables eg:
$this->data =& $_SESSION;
You don't pass parameters by reference, but you still can/must declare your function/method as receiving parameters by reference.
i.e., you don't do this (passing parameters by reference) :
my_function(& $my_var);
function my_function($a) {
// ...
}
But you can do this (declaring the function as receiving parameters by reference) :
my_function($my_var);
function my_function(& $a) {
// ...
}
And... The code examples you gave are not related to call-time-pass-by-reference, but are related to return-by-reference.
For that second thing, what if you just remove the & ? The instance of the object that's been created inside the function will be returned, and you'll still be able to work with it, won't you ?
Objects are always passed by reference since PHP5, so this:
$foo =& new StdClass();
is the same as:
$foo = new StdClass();
.
Ans what about variables in PHP6, can we do that for variables eg:
$this->data =& $_SESSION;
I see no reason why not -- PHP will not be removing references, as they are far too useful. There is no other way to create a reference to a variable.
Call-time pass-by-reference has been deprecated for a while. It just means that instead of doing this:
function foo($a) { return ++$a; }
foo(&$my_a);
You would do this:
function foo(&$a) { return ++$a; }
foo($my_a);
This leads to a much cleaner and easier-to-understand programming style, and it also ensures that variables are always referenced when you expect, and not when you don't.
Dealing with objects is a special case -- they are always passed by reference, and the only way to simulate pass-by-value is to use clone:
$a = new StdClass();
$a->foo = 'bar';
$b = $a;
$a->foo = 'qux';
// $b->foo is 'qux' too
$a = new StdClass();
$a->foo = 'bar';
$b = clone $a;
$a->foo = 'qux';
// $a->foo is 'qux' but $b->foo is 'bar'
Hope that helps!