Ive some classes that share some attributes, and i would like to do something like:
$dog = (Dog) $cat;
is it possible or is there any gener
You can use above function for casting not similar class objects (PHP >= 5.3)
/**
* Class casting
*
* @param string|object $destination
* @param object $sourceObject
* @return object
*/
function cast($destination, $sourceObject)
{
if (is_string($destination)) {
$destination = new $destination();
}
$sourceReflection = new ReflectionObject($sourceObject);
$destinationReflection = new ReflectionObject($destination);
$sourceProperties = $sourceReflection->getProperties();
foreach ($sourceProperties as $sourceProperty) {
$sourceProperty->setAccessible(true);
$name = $sourceProperty->getName();
$value = $sourceProperty->getValue($sourceObject);
if ($destinationReflection->hasProperty($name)) {
$propDest = $destinationReflection->getProperty($name);
$propDest->setAccessible(true);
$propDest->setValue($destination,$value);
} else {
$destination->$name = $value;
}
}
return $destination;
}
EXAMPLE:
class A
{
private $_x;
}
class B
{
public $_x;
}
$a = new A();
$b = new B();
$x = cast('A',$b);
$x = cast('B',$a);
There is no built-in method for type casting of user defined objects in PHP. That said, here are several possible solutions:
1) Use a function like the one below to deserialize the object, alter the string so that the properties you need are included in the new object once it's deserialized.
function cast($obj, $to_class) {
if(class_exists($to_class)) {
$obj_in = serialize($obj);
$obj_out = 'O:' . strlen($to_class) . ':"' . $to_class . '":' . substr($obj_in, $obj_in[2] + 7);
return unserialize($obj_out);
}
else
return false;
}
2) Alternatively, you could copy the object's properties using reflection / manually iterating through them all or using get_object_vars().
This article should enlighten you on the "dark corners of PHP" and implementing typecasting on the user level.
PHP provides a very simple way of doing this by using:
(object) ['id'=>1,'name'=>'cat']
https://www.php.net/manual/en/language.types.object.php
In your case you try this:
$dog = json_encode($dog);
$cat = (object) json_decode($dog)
If the object you are trying to cast from or to has properties that are also user-defined classes, and you don't want to go through reflection, you can use this.
<?php
declare(strict_types=1);
namespace Your\Namespace\Here
{
use Zend\Logger; // or your logging mechanism of choice
final class OopFunctions
{
/**
* @param object $from
* @param object $to
* @param Logger $logger
*
* @return object
*/
static function Cast($from, $to, $logger)
{
$logger->debug($from);
$fromSerialized = serialize($from);
$fromName = get_class($from);
$toName = get_class($to);
$toSerialized = str_replace($fromName, $toName, $fromSerialized);
$toSerialized = preg_replace("/O:\d*:\"([^\"]*)/", "O:" . strlen($toName) . ":\"$1", $toSerialized);
$toSerialized = preg_replace_callback(
"/s:\d*:\"[^\"]*\"/",
function ($matches)
{
$arr = explode(":", $matches[0]);
$arr[1] = mb_strlen($arr[2]) - 2;
return implode(":", $arr);
},
$toSerialized
);
$to = unserialize($toSerialized);
$logger->debug($to);
return $to;
}
}
}
You do not need casting. Everything is dynamic.
I have a class Discount.
I have several classes that extends this class:
ProductDiscount
StoreDiscount
ShippingDiscount
...
Somewhere in the code I have:
$pd = new ProductDiscount();
$pd->setDiscount(5, ProductDiscount::PRODUCT_DISCOUNT_PERCENT);
$pd->setProductId(1);
$this->discounts[] = $pd;
.....
$sd = new StoreDiscount();
$sd->setDiscount(5, StoreDiscount::STORE_DISCOUNT_PERCENT);
$sd->setStoreId(1);
$this->discounts[] = $sd;
And somewhere I have:
foreach ($this->discounts as $discount){
if ($discount->getDiscountType()==Discount::DISCOUNT_TYPE_PRODUCT){
$productDiscount = $discount; // you do not need casting.
$amount = $productDiscount->getDiscountAmount($this->getItemTotalPrice());
...
}
}// foreach
Where getDiscountAmount is ProductDiscount specific function, and getDiscountType is Discount specific function.
I think that the best approach is to just create a new instance of a class and than assign the object. Here's what I would do:
public function ($someVO) {
$someCastVO = new SomeVO();
$someCastVO = $someVO;
$someCastVO->SomePropertyInVO = "123";
}
Doing this will give you code hinting in most IDEs and help ensure you are using the correct properties.