How to Copy an Object in PHP?
I have a simple 'dimensions' class containing a width/height property and a constructor to set them.
I have a function (to re-size dimensions) that takes two dimensions objects -- one to be re-sized, and one containing the max si开发者_开发百科ze. It should reduce the dimensions in the first parameter such that they 'fit into' the second parameter.
Then it returns the first, newly resized one.
The caller passes the dimensions object in and gets the return value into a different one -- because it has to preserve the original object. But the one that is passed into the function gets modified.
This was surprising since I didn't take it by reference:
private function scale_image_dimensions(Dimensions $dimensions, Dimensions $max_size) {
if( $dimensions->width > $max_size->width ) {
$dimensions->height = $dimensions->height / ($dimensions->width / $max_size->width);
$dimensions->width = $max_size->width;
}
if( $dimensions->height > $max_size->height ) {
$dimensions->width = $dimensions->width / ($dimensions->height / $max_size->height);
$dimensions->height = $max_size->height;
}
return $dimensions;
}
How do I specify that I want the function to make a copy of the objects passed into it, and then return one of them?
update
It seems something else is fishy -- I changed the argument from $dimensions
to $adimensions
, and put $dimensions = $adimensions
at the beginning of the function.
But the caller's variable still gets modified! Does assignment work by reference also? I mean... There's non way to make an assignment operator overload, or a copy constructor so... what do I do? If I want a copy I have to explicitly initialize one every time?
Thought many people are totally against cloning, I am all for it.
Edit: Object are assigned by reference and passed by reference as well.
If you need a deep clone of an object, use the clone keyword as in $cloned = clone $dimensions
and also define the magic method __clone()
in your Dimensions
class to ensure that the any object references inside Dimensions
are actually cloned as well.
All objects are, by default, referred to as references. In order to make a copy of the object, you must clone it using the clone keyword.
private function scale_image_dimensions(Dimensions $dimensions, Dimensions $max_size) {
$old_dimensions = $dimensions;
$dimensions = clone $dimensions;
if( $dimensions->width > $max_size->width ) {
$dimensions->height = $dimensions->height / ($dimensions->width / $max_size->width);
$dimensions->width = $max_size->width;
}
if( $dimensions->height > $max_size->height ) {
$dimensions->width = $dimensions->width / ($dimensions->height / $max_size->height);
$dimensions->height = $max_size->height;
}
return $dimensions;
}
This keeps PHP from making large amounts of objects, and generally people want objects to be passed by reference anyway.
PHP Classes are not very often used as a 'Data Storage' utility, because arrays often work just as well.
But, if you are coming for another language that does use many classes to store data, I can see that it would be a big problem.
Might the clone keyword be what you're looking for?
$return_dimensions = clone $dimensions;
PHP5 automatically handles params as references. You could clone the object using the clone keyword.
$newObject = clone $originalObject;
One thing you should be concerned about is the difference between a full copy and a shallow copy when cloning. By default, clone will only make a shallow copy.
The parameters are, in a sense, passed by value, since you can reassign $dimensions without affecting the original.
But object variables are just pointers to the actual object, so you're correct that changing their member variables will affect the original object.
If you want to avoid this, you'll need to clone the objects. PHP has a cloning feature, but keep in mind that it makes shallow copies by default. So if your objects contain other objects, you won't get clones of those; just references to the originals. You may just want to manually create new objects and copy their values yourself.
精彩评论