WHOA... KEEP IT SIMPLE!
In regards to secure_admin's note: You've used OOP to simplify PHP's ability to create and use object references. Now use PHP's static keyword to simplify your OOP.
<?php
class DataModelControl {
protected static $data = 256; // default value;
protected $name;
public function __construct($dmcName) {
$this->name = $dmcName;
}
public static function setData($dmcData) {
if(is_numeric($dmcData)) {
self::$data = $dmcData;
}
}
public function __toString() {
return "DataModelControl [name=$this->name, data=" . self::$data . "]";
}
}
# create several instances of DataModelControl...
$dmc1 = new DataModelControl('dmc1');
$dmc2 = new DataModelControl('dmc2');
$dmc3 = new DataModelControl('dmc3');
echo $dmc1 . '<br>';
echo $dmc2 . '<br>';
echo $dmc3 . '<br><br>';
# To change data, use any DataModelControl object...
$dmc2->setData(512);
# Or, call setData() directly from the class...
DataModelControl::setData(1024);
echo $dmc1 . '<br>';
echo $dmc2 . '<br>';
echo $dmc3 . '<br><br>';
?>
DataModelControl [name=dmc1, data=256]
DataModelControl [name=dmc2, data=256]
DataModelControl [name=dmc3, data=256]
DataModelControl [name=dmc1, data=1024]
DataModelControl [name=dmc2, data=1024]
DataModelControl [name=dmc3, data=1024]
... even better! Now, PHP creates one copy of $data, that is shared amongst all DataModelControl objects.
Objects and references
One of the key-point of PHP5 OOP that is often mentioned is that "objects are passed by references by default" This is not completely true. This section rectifies that general thought using some examples.
A PHP reference is an alias, which allows two different variables to write to the same value. As of PHP5, an object variable doesn't contain the object itself as value anymore. It only contains a object identifier which allows object accessors to find the actual object. When an object is sent by argument, returned or assigned to another variable, the different variables are not aliases: they hold a copy of the identifier, which points to the same object.
Example #1 References and Objects
<?php
class A {
public $foo = 1;
}
$a = new A;
$b = $a; // $a and $b are copies of the same identifier
// ($a) = ($b) = <id>
$b->foo = 2;
echo $a->foo."\n";
$c = new A;
$d = &$c; // $c and $d are references
// ($c,$d) = <id>
$d->foo = 2;
echo $c->foo."\n";
$e = new A;
function foo($obj) {
// ($obj) = ($e) = <id>
$obj->foo = 2;
}
foo($e);
echo $e->foo."\n";
?>
The above example will output:
2 2 2
Objects and references
30-Sep-2008 09:57
30-Sep-2008 07:38
USE OOP to ACCESS OBJECT REFERENCES
The PHP language itself offers a slew of nifty operators that can copy, clone, and alias objects and references in many ways. But that kind of syntax looks rather fearsome. Here, I use OOP to get the same results, but with cleaner and more practical code. Below, one DataModel object is instantiated so that many instances of DataControl can use and alter it. Regardless of how PHP works, the OOP styled setup keeps all DataControl instances "on the same page" because they are all looking at the "same model" - which this code clearly shows.
<?php
class DataModel {
protected $name, $data;
public function __construct($dmName, $dmData) {
$this->name = $dmName;
$this->setData($dmData);
}
public function setData($dmData) {
if(is_numeric($dmData)) {
$this->data = $dmData;
}
}
public function __toString() {
return "DataModel [name=$this->name, data=$this->data]";
}
}
class DataControl {
protected $name, $model;
public function __construct($dcName, $dcModel) {
$this->name = $dcName;
$this->model = $dcModel;
}
public function setData($dmData) {
$this->model->setData($dmData);
}
public function __toString() {
return "DataController [name=$this->name, model=" . $this->model->__toString() . "]";
}
}
# create one instance of DataModel...
$model = new DataModel('dm1', 128);
echo $model . '<br><br>';
# create several instances of DataControl, passing $model to each one...
$dc1 = new DataControl('dc1', $model);
$dc2 = new DataControl('dc2', $model);
$dc3 = new DataControl('dc3', $model);
echo $dc1 . '<br>';
echo $dc2 . '<br>';
echo $dc3 . '<br><br>';
# To change data, use any $dataControl->setData()...
$dc3->setData(512);
echo $dc1 . '<br>';
echo $dc2 . '<br>';
echo $dc3 . '<br><br>';
?>
* * * output * * *
DataModel [name=dm1, data=128]
DataController [name=dc1, model=DataModel [name=dm1, data=128]]
DataController [name=dc2, model=DataModel [name=dm1, data=128]]
DataController [name=dc3, model=DataModel [name=dm1, data=128]]
DataController [name=dc1, model=DataModel [name=dm1, data=512]]
DataController [name=dc2, model=DataModel [name=dm1, data=512]]
DataController [name=dc3, model=DataModel [name=dm1, data=512]]
30-Sep-2008 04:23
A BIT DILUTED... but it's alright!
In the PHP example above, the function foo($obj), will actually create a $foo property to "any object" passed to it - which brings some confusion to me:
$obj = new stdClass();
foo($obj); // tags on a $foo property to the object
// why is this method here?
Furthermore, in OOP, it is not a good idea for "global functions" to operate on an object's properties... and it is not a good idea for your class objects to let them. To illustrate the point, the example should be:
<?php
class A {
protected $foo = 1;
public function getFoo() {
return $this->foo;
}
public function setFoo($val) {
if($val > 0 && $val < 10) {
$this->foo = $val;
}
}
public function __toString() {
return "A [foo=$this->foo]";
}
}
$a = new A();
$b = $a; // $a and $b are copies of the same identifier
// ($a) = ($b) = <id>
$b->setFoo(2);
echo $a->getFoo() . '<br>';
$c = new A();
$d = &$c; // $c and $d are references
// ($c,$d) = <id>
$d->setFoo(2);
echo $c . '<br>';
$e = new A();
$e->setFoo(16); // will be ignored
echo $e;
?>
- - -
2
A [foo=2]
A [foo=1]
- - -
Because the global function foo() has been deleted, class A is more defined, robust and will handle all foo operations... and only for objects of type A. I can now take it for granted and see clearly that your are talking about "A" objects and their references. But it still reminds me too much of cloning and object comparisons, which to me borders on machine-like programming and not object-oriented programming, which is a totally different way to think.
