109 votes

Convertir / convertir un objet stdClass en une autre classe

Je suis à l'aide d'un tiers du système de stockage qui ne retourne me stdClass objets, peu importe ce que je nourris pour une raison obscure. Donc, je suis curieux de savoir si il existe un moyen de cast/convertir un objet stdClass en à part entière un objet d'un type donné.

Par exemple, quelque chose le long des lignes de:

//$stdClass is an stdClass instance
$converted = (BusinessClass) $stdClass;

Je suis juste un moulage de la stdClass dans un tableau et de le nourrir à la BusinessClass constructeur, mais peut-être il ya un moyen de restaurer la classe initiale que je ne suis pas au courant.

Note: je ne suis pas intéressé par " le Changement de votre système de stockage de type de réponses, car il n'est pas le point d'intérêt. Veuillez considérer qu'il est plus une question purement théorique sur la langue des capacités.

Cheers

98voto

Gordon Points 156415

Voir le manuel sur le Type de Jonglage sur possible de moulages.

La jette autorisées sont:

  • (int), (entier) - cast en entier
  • (bool), (boolean) - fonte d'boolean
  • (float), (double), (réel) - fonte à flotteur
  • (string) - le casting de la chaîne
  • (array) - fonte de matrice
  • (objet) - fonte d'objet
  • (unset) - fonte à NULL (PHP 5)

Vous devez écrire un Mappeur qui ne le casting de stdClass à l'autre de la classe de béton. Ne devrait pas être trop dur à faire.

Ou, si vous êtes dans un hackish humeur, vous pouvez adapter le code suivant:

function arrayToObject(array $array, $className) {
    return unserialize(sprintf(
        'O:%d:"%s"%s',
        strlen($className),
        $className,
        strstr(serialize($array), ':')
    ));
}

qui pseudocasts un tableau à un objet d'une certaine classe. Cela fonctionne d'abord la sérialisation de la matrice et ensuite de changer les données sérialisées de sorte qu'il représente une certaine classe. Le résultat est désérialisé à une instance de cette classe. Mais comme je l'ai dit, c'est hackish, donc s'attendre à des effets secondaires.

Pour un objet à un autre, le code serait

function objectToObject($instance, $className) {
    return unserialize(sprintf(
        'O:%d:"%s"%s',
        strlen($className),
        $className,
        strstr(strstr(serialize($instance), '"'), ':')
    ));
}

59voto

Adam Puza Points 451

Vous pouvez utiliser la fonction ci-dessus pour la conversion d'objets de classe non similaires (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;
}
 

EXEMPLE:

 class A 
{
  private $_x;   
}

class B 
{
  public $_x;   
}

$a = new A();
$b = new B();

$x = cast('A',$b);
$x = cast('B',$a);
 

20voto

hakre Points 102271

Pour déplacer toutes les propriétés existantes d'un stdClass vers un nouvel objet du nom de classe spécifié:

 /**
 * recast stdClass object to an object with type
 *
 * @param string $className
 * @param stdClass $object
 * @throws InvalidArgumentException
 * @return mixed new, typed object
 */
function recast($className, stdClass &$object)
{
    if (!class_exists($className))
        throw new InvalidArgumentException(sprintf('Inexistant class %s.', $className));

    $new = new $className();

    foreach($object as $property => &$value)
    {
        $new->$property = &$value;
        unset($object->$property);
    }
    unset($value);
    $object = (unset) $object;
    return $new;
}
 

Usage:

 $array = array('h','n');

$obj=new stdClass;
$obj->action='auth';
$obj->params= &$array;
$obj->authKey=md5('i');

class RestQuery{
    public $action;
    public $params=array();
    public $authKey='';
}

$restQuery = recast('RestQuery', $obj);

var_dump($restQuery, $obj);
 

Sortie:

 object(RestQuery)#2 (3) {
  ["action"]=>
  string(4) "auth"
  ["params"]=>
  &array(2) {
    [0]=>
    string(1) "h"
    [1]=>
    string(1) "n"
  }
  ["authKey"]=>
  string(32) "865c0c0b4ab0e063e5caa3387c1a8741"
}
NULL
 

Ceci est limité à cause de l'opérateur new car on ne sait pas quels paramètres il aurait besoin. Pour votre cas, probablement approprié.

12voto

user651028 Points 87

J'ai un problème très similaire. La solution de réflexion simplifiée a bien fonctionné pour moi:

 public static function cast($destination, \stdClass $source)
{
    $sourceReflection = new \ReflectionObject($source);
    $sourceProperties = $sourceReflection->getProperties();
    foreach ($sourceProperties as $sourceProperty) {
        $name = $sourceProperty->getName();
        $destination->{$name} = $source->$name;
    }
    return $destination;
}
 

5voto

Jadrovski Points 21

Fonction modifiée pour la coulée profonde (en utilisant la récursivité)

 /**
 * Переводит тип
 * @param $destination Объект назначения
 * @param stdClass $source Источник
 */
private static function Cast(&$destination, stdClass $source)
{
    $sourceReflection = new \ReflectionObject($source);
    $sourceProperties = $sourceReflection->getProperties();
    foreach ($sourceProperties as $sourceProperty) {
        $name = $sourceProperty->getName();
        if (gettype($destination->{$name}) == "object") {
            self::Cast($destination->{$name}, $source->$name);
        } else {
            $destination->{$name} = $source->$name;
        }
    }
}
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X