234 votes

Quelle est la meilleure méthode pour fusionner deux objets PHP ?

Nous avons deux PHP5 objets et souhaitez fusionner le contenu de l'un dans la seconde. Il n'y a pas de notion de sous-classes entre elles de manière à les solutions décrites dans la rubrique suivante ne peut pas s'appliquer.

Comment avez-vous copier un objet PHP dans un autre type d'objet

//We have this:
$objectA->a;
$objectA->b;
$objectB->c;
$objectB->d;

//We want the easiest way to get:
$objectC->a;
$objectC->b;
$objectC->c;
$objectC->d;

Remarques:

  • Ce sont des objets, et non des classes.
  • Les objets contiennent beaucoup de champs, pour un foreach serait assez lent.
  • Jusqu'à présent, nous envisager de transformer les objets A et B dans des tableaux, puis de les fusionner à l'aide de array_merge() avant de re-transformer en un objet, mais nous ne pouvons pas dire que nous en sommes fiers.

460voto

flochtililoch Points 2081
<blockquote> <p>Si vos objets contiennent uniquement des champs (pas de méthodes), cela fonctionne :</p> <blockquote> <p>$obj_merged = array_merge((array) (objet) $obj1, (array) $obj2) ;</p> </blockquote> </blockquote> <p>Ce réellement fonctionne aussi quand les objets ont des méthodes. (testé avec php 5.3)</p>

30voto

porneL Points 42805
foreach($objectA as $k => $v) $objectB->$k = $v;

28voto

Allain Lalonde Points 28717

Vous pouvez créer un autre objet qui répartit les appels aux méthodes magiques aux objets sous-jacents. Voici comment vous traiterait `` , mais faire fonctionner pleinement, vous devez substituer toutes les méthodes magiques pertinentes. Vous trouverez probablement des erreurs de syntaxe étant donné que je suis juste entré au large du haut de ma tête.

Bonne chance.

11voto

Ryan Schumacher Points 1046

Je comprends que l'utilisation du générique des objets [stdClass()] et de la coulée comme des matrices de réponses à la question, mais je pensais que le Compositeur a été une grande réponse. Pourtant, j'ai senti qu'il pourrait utiliser certaines des améliorations de fonctionnalités et peut être utile pour quelqu'un d'autre.

Caractéristiques:

  • Spécification de la référence ou clone
  • Spécifiez la première ou la dernière entrée à l'emporter
  • Plusieurs (plus de deux) objet de la fusion avec la syntaxe similitude avec array_merge
  • La méthode de la liaison: $obj->f1()->f2()->f3()...
  • Dynamique de composites: $obj->fusionner les(...) /* travailler ici */ $obj->fusionner les(...)

Code:

class Compositor {

    protected $composite = array();
    protected $use_reference;
    protected $first_precedence;

    /**
     * __construct, Constructor
     *
     * Used to set options.
     *
     * @param bool $use_reference whether to use a reference (TRUE) or to copy the object (FALSE) [default]
     * @param bool $first_precedence whether the first entry takes precedence (TRUE) or last entry takes precedence (FALSE) [default]
     */
    public function __construct($use_reference = FALSE, $first_precedence = FALSE) {
        // Use a reference
        $this->use_reference = $use_reference === TRUE ? TRUE : FALSE;
        $this->first_precedence = $first_precedence === TRUE ? TRUE : FALSE;

    }

    /**
     * Merge, used to merge multiple objects stored in an array
     *
     * This is used to *start* the merge or to merge an array of objects.
     * It is not needed to start the merge, but visually is nice.
     *
     * @param object[]|object $objects array of objects to merge or a single object
     * @return object the instance to enable linking
     */

    public function & merge() {
        $objects = func_get_args();
        // Each object
        foreach($objects as &$object) $this->with(&$object);
        // Garbage collection
        unset($object);

        // Return $this instance
        return $this;
    }

    /**
     * With, used to merge a singluar object
     *
     * Used to add an object to the composition
     *
     * @param object $object an object to merge
     * @return object the instance to enable linking
     */
    public function & with(&$object) {
        // An object
        if(is_object($object)) {
            // Reference
            if($this->use_reference) {
                if($this->first_precedence) array_push($this->composite, &$object);
                else array_unshift($this->composite, &$object);
            }
            // Clone
            else {
                if($this->first_precedence) array_push($this->composite, clone $object);
                else array_unshift($this->composite, clone $object);
            }
        }

        // Return $this instance
        return $this;
    }

    /**
     * __get, retrieves the psudo merged object
     *
     * @param string $name name of the variable in the object
     * @return mixed returns a reference to the requested variable
     *
     */
    public function & __get($name) {
        $return = NULL;
        foreach($this->composite as &$object) {
            if(isset($object->$name)) {
                $return =& $object->$name;
                break;
            }
        }
        // Garbage collection
        unset($object);

        return $return;
    }
}

Utilisation:

$obj = new Compositer(use_reference, first_precedence);
$obj->merge([object $object [, object $object [, object $...]]]);
$obj->with([object $object]);

Exemple:

$obj1 = new stdClass();
$obj1->a = 'obj1:a';
$obj1->b = 'obj1:b';
$obj1->c = 'obj1:c';

$obj2 = new stdClass();
$obj2->a = 'obj2:a';
$obj2->b = 'obj2:b';
$obj2->d = 'obj2:d';

$obj3 = new Compositor();
$obj3->merge($obj1, $obj2);
$obj1->c = '#obj1:c';
var_dump($obj3->a, $obj3->b, $obj3->c, $obj3->d);
// obj2:a, obj2:b, obj1:c, obj2:d
$obj1->c;

$obj3 = new Compositor(TRUE);
$obj3->merge($obj1)->with($obj2);
$obj1->c = '#obj1:c';
var_dump($obj3->a, $obj3->b, $obj3->c, $obj3->d);
// obj1:a, obj1:b, obj1:c, obj2:d
$obj1->c = 'obj1:c';

$obj3 = new Compositor(FALSE, TRUE);
$obj3->with($obj1)->with($obj2);
$obj1->c = '#obj1:c';
var_dump($obj3->a, $obj3->b, $obj3->c, $obj3->d);
// obj1:a, obj1:b, #obj1:c, obj2:d
$obj1->c = 'obj1:c';

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