How to Cast Objects in PHP

后端 未结 12 1897
轮回少年
轮回少年 2020-11-27 04:24

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

相关标签:
12条回答
  • 2020-11-27 04:27

    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);
    
    0 讨论(0)
  • 2020-11-27 04:28

    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.

    0 讨论(0)
  • 2020-11-27 04:28

    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)
    
    0 讨论(0)
  • 2020-11-27 04:31

    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;
        }
      }
    }
    
    0 讨论(0)
  • 2020-11-27 04:35

    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.

    0 讨论(0)
  • 2020-11-27 04:38

    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.

    0 讨论(0)
提交回复
热议问题