Apa metode terbaik untuk menggabungkan dua objek PHP?

Kami memiliki dua PHP5 benda-benda dan ingin menggabungkan konten dari satu ke yang kedua. Tidak ada gagasan dari subclass antara mereka sehingga solusi yang dijelaskan dalam topik berikut tidak berlaku.

Bagaimana anda copy PHP objek ke objek yang berbeda jenis

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

Keterangan:

  • Ini adalah objek, bukan kelas.
  • Benda-benda yang mengandung cukup banyak bidang sehingga a foreach akan menjadi cukup lambat.
  • Sejauh ini kami mempertimbangkan untuk mengubah benda A dan B ke dalam array kemudian menggabungkan mereka menggunakan array_merge() sebelum kembali berubah menjadi sebuah benda tapi kita bisa't mengatakan kami bangga jika ini.
Mengomentari pertanyaan (1)
Larutan

Jika anda benda-benda yang hanya berisi bidang (tidak ada metode), ini bekerja:

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

Ini sebenarnya juga bekerja ketika benda memiliki metode. (diuji dengan PHP 5.3 dan 5.6)

Komentar (8)

Jika anda benda-benda yang hanya berisi bidang (tidak ada metode), ini bekerja:

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

Anda bisa membuat benda lain yang mengirimkan panggilan ke metode sihir yang mendasari objek. Berikut ini's bagaimana anda'd handle __get, tapi untuk mendapatkan itu bekerja sepenuhnya anda'd harus mengesampingkan semua yang relevan metode sihir. Anda'mungkin akan menemukan kesalahan sintaks karena saya baru saja masuk dari atas kepala saya.

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

Good luck.

Komentar (6)
foreach($objectA as $k => $v) $objectB->$k = $v;
Komentar (3)

Saya memahami bahwa dengan menggunakan objek generik [stdClass()] dan casting mereka sebagai array menjawab pertanyaan, tapi saya pikir Compositor itu jawaban yang bagus. Namun saya merasa itu bisa menggunakan beberapa fitur tambahan dan mungkin berguna untuk orang lain.

Fitur:

  • Menentukan referensi atau clone
  • Menentukan entri pertama atau terakhir untuk didahulukan
  • Beberapa (lebih dari dua) objek penggabungan dengan sintaks kesamaan array_merge
  • Metode menghubungkan: $obj->f1()->f2()->f3()...
  • Dinamik komposit: $obj->menggabungkan(...) / bekerja di sini / $obj->menggabungkan(...)

Kode:

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

Penggunaan:

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

Contoh:

$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';
Komentar (8)

Solusi yang sangat sederhana mengingat anda memiliki objek A dan B:

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

Yang's semua. Anda sekarang memiliki objA dengan semua nilai-nilai dari objB.

Komentar (2)

solusi Untuk melestarikan,baik metode dan properti dari digabung onjects adalah untuk menciptakan sebuah combinator kelas yang dapat

  • mengambil sejumlah benda-benda di __construct
  • akses setiap metode menggunakan __call
  • accsess setiap properti menggunakan __dapatkan

class combinator{
function __construct(){       
    $this->melt =  array_reverse(func_get_args());
      // array_reverse is to replicate natural overide
}
public function __call($method,$args){
    forEach($this->melt as $o){
        if(method_exists($o, $method)){
            return call_user_func_array([$o,$method], $args);
            //return $o->$method($args);
            }
        }
    }
public function __get($prop){
        foreach($this->melt as $o){
          if(isset($o->$prop))return $o->$prop;
        }
        return 'undefined';
    } 
}

sederhana menggunakan

class c1{
    public $pc1='pc1';
    function mc1($a,$b){echo __METHOD__." ".($a+$b);}
}
class c2{
    public $pc2='pc2';
    function mc2(){echo __CLASS__." ".__METHOD__;}
}

$comb=new combinator(new c1, new c2);

$comb->mc1(1,2);
$comb->non_existing_method();  //  silent
echo $comb->pc2;
Komentar (2)

Untuk menggabungkan sejumlah baku benda-benda

function merge_obj(){
    foreach(func_get_args() as $a){
        $objects[]=(array)$a;
    }
    return (object)call_user_func_array('array_merge', $objects);
}
Komentar (0)

The \ArrayObject kelas memiliki kemungkinan untuk exchange saat ini array untuk memutuskan asli reference. Untuk melakukannya, ia datang dengan dua handy metode: exchangeArray() dan getArrayCopy(). Sisanya polos sederhana array_merge() yang diberikan objek dengan `ArrayObject umum sifat-sifat:

class MergeBase extends ArrayObject
{
     public final function merge( Array $toMerge )
     {
          $this->exchangeArray( array_merge( $this->getArrayCopy(), $toMerge ) );
     }
 }

Penggunaan yang sangat mudah seperti ini:

 $base = new MergeBase();

 $base[] = 1;
 $base[] = 2;

 $toMerge = [ 3,4,5, ];

 $base->merge( $toMerge );
Komentar (1)

Aku akan pergi dengan menghubungkan kedua objek ke properti dari objek pertama. Jika kedua objek merupakan hasil dari sebuah fungsi atau metode, menggunakan referensi. 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');
Komentar (0)

Let's keep it simple!

function copy_properties($from, $to, $fields = null) {
    // copies properties/elements (overwrites duplicates)
    // can take arrays or objects 
    // if fields is set (an array), will only copy keys listed in that array
    // returns $to with the added/replaced properties/keys
    $from_array = is_array($from) ? $from : get_object_vars($from);
    foreach($from_array as $key => $val) {
        if(!is_array($fields) or in_array($key, $fields)) {
            if(is_object($to)) {
                $to->$key = $val;
            } else {
                $to[$key] = $val;
            }
        }
    }
    return($to);
}

Jika itu doesn't menjawab pertanyaan anda, itu pasti akan membantu ke arah jawaban. Kredit untuk kode di atas berlaku untuk diri saya sendiri :)

Komentar (0)

Berikut ini adalah fungsi yang akan meratakan sebuah object atau array. Gunakan ini hanya jika anda yakin anda kunci yang unik. Jika anda memiliki tombol dengan nama yang sama mereka akan ditimpa. Anda akan perlu untuk menempatkan ini dalam kelas dan ganti "Fungsi" dengan nama kelas anda. Menikmati...

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;
}
Komentar (0)

Ini cuplikan kode akan secara rekursif mengkonversi data untuk satu jenis (array atau objek) tanpa nested loop foreach. Berharap itu membantu seseorang!

Setelah Obyek dalam format array dapat anda gunakan array_merge dan mengkonversi kembali ke Objek jika anda perlu untuk.

abstract class Util {
    public static function object_to_array($d) {
        if (is_object($d))
            $d = get_object_vars($d);

        return is_array($d) ? array_map(__METHOD__, $d) : $d;
    }

    public static function array_to_object($d) {
        return is_array($d) ? (object) array_map(__METHOD__, $d) : $d;
    }
}

Cara prosedural

function object_to_array($d) {
    if (is_object($d))
        $d = get_object_vars($d);

    return is_array($d) ? array_map(__FUNCTION__, $d) : $d;
}

function array_to_object($d) {
    return is_array($d) ? (object) array_map(__FUNCTION__, $d) : $d;
}

Semua kredit pergi ke: Jason Oakley

Komentar (0)