For a metering project, I have a class MeterReadings, with a constructor that takes a previous reading as basis for all of its property values except the timestamp. In the example, the Object has only 3 properties, in real life there are many more. I could line by line for each property X do
$this->propertyX=$prevMS->propertyX
but that quickly becomes tedious.
What is best practice for copying all property values from the $prevMS
object?
<?php class MeterReadings{
function __construct($prevMS=NULL){
if($prevMS===NULL){
$this->gas=0;
$this->water=0;
$this->electricity=0;
}else{
//PHP can duplicate an object by assignment,
//so I expected to be able to create a copy of $prevMS
//but cannot $this=$prevMS;
//and cannot $this= clone $that;
//which both throw error 'Cannot re-assign $this'
foreach($prevMS as $key => $value){
//logs "Undefined property: MeterReadings::$0"
print "$key => $value\n";
$this->$key = $prevMS->$value;
}
}
$this->date=time();//set timestamp for this object
}
}
$test= new MeterReadings();
$test2 = new MeterReadings($test);
print_r($test);
print_r($test2);
?>gets me
gas => 0
water => 0
electricity => 0
date => 1434448706
MeterReadings Object
(
[gas] => 0
[water] => 0
[electricity] => 0
[date] => 1434448706
)
MeterReadings Object
(
[gas] =>
[water] =>
[electricity] =>
[date] => 1434448706
)
答案 0 :(得分:2)
You can use clone
and the __clone
Magic Method to manage what get's cloned.
For example:
class Test
{
public $value1;
public $value2;
public $timestamp;
public function __clone()
{
$this->timestamp = null;
}
}
$test = new Test();
$test->value1 = 1;
$test->value2 = 2;
$test->timestamp = time();
$test2 = clone $test;
print_r($test2);
// Test Object
// (
// [value1] => 1
// [value2] => 2
// [timestamp] =>
// )
Alternative:
To keep things as in the __constuct
as specified the comment below:
class Test
{
public $value1;
public $value2;
public $timestamp;
public function __construct (Test $copy = null)
{
if($copy) {
foreach ($copy as $key => $value) {
$this->$key = $value;
}
}
$this->timestamp = 'whoop';
}
}
$test = new Test();
$test->value1 = 1;
$test->value2 = 2;
$test->timestamp = 'whatev\'s';
$test2 = new Test($test);
print_r($test2);
// Test Object
// (
// [value1] => 1
// [value2] => 2
// [timestamp] => 'whoop'
// )
This will work for objects that are not itterable and for properties that are protected (but not private). For objects that are itterable and return something else, you can use get_object_vars()
, documentation here. For stuff that's private (are you sure you need private, that's unusual) you'll need to create getters. They can be protected if you don't want them externally available.