İki PHP nesneleri birleştirmek için en iyi yöntemi nedir?

8 Cevap php

Biz iki PHP5 nesneleri ve ikinci içine birinin içeriğini birleştirmek istiyorum. Aralarında alt sınıflara hiçbir kavramı vardır bu nedenle aşağıdaki konuda anlatılan çözümler uygulayamazsınız.

How do you copy a PHP object into a different object type

//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;

Remarks:

  • Bu nesneler değil, sınıflardır.
  • Nesneler böylece foreach oldukça yavaş olacağını alanlarda oldukça bir sürü içerir.
  • Şimdiye kadar array_merge() bir nesnenin içine yeniden dönüştüren önce kullanarak onları birleştirme sonra diziler içine nesneleri A ve B dönüşüm düşünün ama biz eğer bu gurur duyuyoruz diyemeyiz.

8 Cevap

Lütfen nesneleri yalnızca alanları (hiçbir yöntem) içeriyorsa, bu işleri:

$ Obj_merged = (object) array_merge ((array) $ obj1, (array) $ nesne2);

Nesneleri yöntemleri var, bu gerçekten de çalışıyor. (Php 5.3 ile test edilmiştir)

Sen plandaki nesneleri sihirli yöntemleri aramaları gönderir başka bir nesne oluşturabilir. İşte __get idare ediyorum nasıl, ama tüm ilgili sihirli yöntemlerini geçersiz olurdu tam çalışma almak için. Ben sadece kafamın üst kapalı girilmiş beri muhtemelen sözdizimi hataları bulacaksınız.

class Compositor {
  private $obj_a;
  private $obj_b

  public function __construct($obj_a, $obj_b) {
    $this->obj_a = $obj_a;
    $this->obj_b = $obj_b;
  }

  public function __get($attrib_name) {
    if ($this->obj_a->$attrib_name) {
       return $this->obj_a->$attrib_name;
    } else {
       return $this->obj_b->$attrib_name;
    }
  }
}

İyi şanslar.

Lütfen nesneleri yalnızca alanları (hiçbir yöntem) içeriyorsa, bu işleri:

$obj_merged = (object) array_merge((array) $obj1, (array) $obj2);

Ben genel nesneler [stdClass ()] kullanılarak ve diziler gibi onları döküm soru cevaplar anlıyorum, ama ben Compositor büyük bir cevap olduğunu düşündüm. Yine Ben bazı özellik geliştirmeleri kullanabilirsiniz ve bir başkası için yararlı olabilir hissetti.

Özellikler:

  • Başvuru veya klon belirtin
  • Öncelik almak için birinci veya sonuncu girişi belirtin
  • Çoklu (ikiden fazla) nesne array_merge sözdizimi benzerliği ile birleşiyor
  • Yöntem bağlama: $ obj-> f1 () -> f2 () -> f3 (...)
  • Dynamic kompozitler: $ obj-> birleştirme (...) / * Burada çalışmak * / $ obj-> birleştirme (...)

Kod:

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;
    }
}

Kullanımı:

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

Örnek:

$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';

Eğer nesne A ve B var düşünen bir çok basit bir çözüm:

foreach($objB AS $var=>$value){
    $objA->$var = $value;
}

Hepsi bu. Artık objB tüm değerleri ile objA var.

Ben ilk nesnenin bir özellik haline ikinci nesne bağlama ile gitmek istiyorum. Ikinci nesne bir işlev veya yöntemin sonucu ise, başvuruları kullanabilirsiniz. Ex:

//Not the result of a method
$obj1->extra = new Class2();

//The result of a method, for instance a factory class
$obj1->extra =& Factory::getInstance('Class2');

İşte bir nesne veya dizi dümdüz olacak bir fonksiyondur. Eğer anahtarlar benzersiz olduğundan emin iseniz bu sadece kullanın. Eğer aynı isimde anahtarlar varsa onlar yazılır. Eğer bir sınıfta, bu yer ve sınıfın adı ile "Fonksiyonlar" değiştirmeniz gerekir. Enjoy ...

function flatten($array, $preserve_keys=1, &$out = array(), $isobject=0) {
    	# Flatten a multidimensional array to one dimension, optionally preserving keys.
    	#
    	# $array - the array to flatten
    	# $preserve_keys - 0 (default) to not preserve keys, 1 to preserve string keys only, 2 to preserve all keys
    	# $out - internal use argument for recursion
    	# $isobject - is internally set in order to remember if we're using an object or array
    	if(is_array($array) || $isobject==1)
    	foreach($array as $key => $child)
    		if(is_array($child))
    			$out = Functions::flatten($child, $preserve_keys, $out, 1); // replace "Functions" with the name of your class
    		elseif($preserve_keys + is_string($key) > 1)
    			$out[$key] = $child;
    		else
    			$out[] = $child;

    	if(is_object($array) || $isobject==2)
    	if(!is_object($out)){$out = new stdClass();}
    	foreach($array as $key => $child)
    		if(is_object($child))
    			$out = Functions::flatten($child, $preserve_keys, $out, 2); // replace "Functions" with the name of your class
    		elseif($preserve_keys + is_string($key) > 1)
    			$out->$key = $child;
    		else
    			$out = $child;

    	return $out;
}
class SomeClass extends ArrayObject
{
     public final function merge($array)
     {
          $this->exchangeArray(array_merge($this->getArrayCopy(), $array));
     }
 }

kullanımı:

 $obj = new SomeClass();

 $obj[] = 1;
 $obj[] = 2;

 $array = array(3,4,5);

 $obj->merge($array);