forcing access to __PHP_Incomplete_Class object properties

前端 未结 8 1857
夕颜
夕颜 2020-11-30 06:43

I\'m writing a module for a php cms. In a function (a callback) I can access an object that comes from the framework code.

This object is of type __PHP_Incomp

相关标签:
8条回答
  • 2020-11-30 06:52

    This issue appends when you un serialize an object of a class that hasn't been included yet. For exemple, if you call session_start before include the class.

    A PHPIncompleteClass object can't be accessed directly, but it's ok with foreach, serialize and gettype. Calling is_object with an PHPIncompleteClass object will result false.

    So, if you find a '__PHP_Incomplete_Class' object in your session and you've included your class after the session_load, you can use this function :

    function fixObject (&$object)
    {
      if (!is_object ($object) && gettype ($object) == 'object')
        return ($object = unserialize (serialize ($object)));
      return $object;
    }
    

    This will results a usable object :

    fixObject($_SESSION['member']);
    
    0 讨论(0)
  • 2020-11-30 06:59

    None of the above answers actually worked for me, except this solution:

    $object = unserialize(serialize($object));

    $object->function();

    Hope it helps someone

    0 讨论(0)
  • 2020-11-30 07:00

    I've read a lot of suggestions on how to fix incomplete classobjects and I actually needed to fix those problems myself, in a ecommerce-project.

    One suggestion I've found is to simply use json_decode/json_encode to convert incomplete classes without preloading anything. However, I didn't want to take the risk using this, if there are older PHP versions that are dependent in for example PECL, that is described at http://php.net/manual/en/function.json-encode.php - so I finally succeeded to make my own solution.

    However, the code is a way to get the data out of the object properly, so it may not fit all needs - and it will primarily, use the json-solution first, if it is available in the environment and fail over to manual handling if needed.

    It also works recursively, which in my own case is required, to save the whole array.

    /**
     * Convert a object to a data object (used for repairing __PHP_Incomplete_Class objects)
     * @param array $d
     * @return array|mixed|object
     */
    function arrayObjectToStdClass($d = array())
    {
        /**
         * If json_decode and json_encode exists as function, do it the simple way.
         * http://php.net/manual/en/function.json-encode.php
         */
        if (function_exists('json_decode') && function_exists('json_encode')) {
            return json_decode(json_encode($d));
        }
        $newArray = array();
        if (is_array($d) || is_object($d)) {
            foreach ($d as $itemKey => $itemValue) {
                if (is_array($itemValue)) {
                    $newArray[$itemKey] = (array)$this->arrayObjectToStdClass($itemValue);
                } elseif (is_object($itemValue)) {
                    $newArray[$itemKey] = (object)(array)$this->arrayObjectToStdClass($itemValue);
                } else {
                    $newArray[$itemKey] = $itemValue;
                }
            }
        }
        return $newArray;
    }
    
    0 讨论(0)
  • 2020-11-30 07:02

    Put the session_start() after your require to the class of the object you are trying to read from the SESSION

    0 讨论(0)
  • 2020-11-30 07:07

    If you just need to access raw data (like class variables) from a PHP_Incomplete_Class object, you can use the foreach hack, or you can also do:

    $result_array = (array)$_SESSION['incomplete_object_index'];
    echo $result_array['desired_item'];
    
    0 讨论(0)
  • 2020-11-30 07:09

    I tried the answer of Tom Haigh here, but discovered 2 problems.

    1. when you have other "Incomplete_Class" objects as properties of the top-level-class they stay untouched as __PHP_Incomplete_Class Object
    2. if you have private properties, they will still be private in your stdClass object

    So I rewrote the function handle this:

    /**
     * @see: https://stackoverflow.com/a/965704/2377961
     *
     * @param  object  $object  The object that should be casted
     * @param  String  $class   The name of the class
     * @return mixed   The new created object
     */
    function casttoclass($object, $class = 'stdClass')
    {
      $ser_data = serialize($object);
      # preg_match_all('/O:\d+:"([^"]++)"/', $ser_data, $matches); // find all classes
    
      /*
       * make private and protected properties public
       *   privates  is stored as "s:14:\0class_name\0property_name")
       *   protected is stored as "s:14:\0*\0property_name")
       */
      $ser_data = preg_replace_callback('/s:\d+:"\0([^\0]+)\0([^"]+)"/',
        function($prop_match) {
          list($old, $classname, $propname) = $prop_match;
          return 's:'.strlen($propname) . ':"' . $propname . '"';
      }, $ser_data);
    
      // replace object-names
      $ser_data = preg_replace('/O:\d+:"[^"]++"/', 'O:' . strlen($class) . ':"' . $class . '"', $ser_data);
      return unserialize($ser_data);
    }
    

    I switch tha function arguments too, so that you can use

    $obj = casttoclass($incompleteObject);
    

    And you get an stdClass object with only public properties. Even if you have objects in childclasses they are converted to stdClass with public properties too.

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