আমি কীভাবে পিএইচপি-তে কোনও সামগ্রীর অনুলিপি তৈরি করব?


168

এটি পিএইচপি অবজেক্টে রেফারেন্স দ্বারা পাস করা হয় যে প্রদর্শিত হয়। এমনকি অ্যাসাইনমেন্ট অপারেটররা অবজেক্টের একটি অনুলিপি তৈরি করতে উপস্থিত হয় না।

এখানে একটি সহজ, স্বীকৃত প্রমাণ:

<?php

class A {
    public $b;
}


function set_b($obj) { $obj->b = "after"; }

$a = new A();
$a->b = "before";
$c = $a; //i would especially expect this to create a copy.

set_b($a);

print $a->b; //i would expect this to show 'before'
print $c->b; //i would ESPECIALLY expect this to show 'before'

?>

দুটি মুদ্রণের ক্ষেত্রেই আমি 'পরে' পাচ্ছি

সুতরাং, আমি পাস না একটি $ থেকে set_b () মান দ্বারা, রেফারেন্স দ্বারা না?


2
খুব কম কেসই রয়েছে, যেখানে আপনি আসলে এই আচরণটি চান। সুতরাং আপনি যদি নিজেকে এটি প্রায়শই ব্যবহার করে দেখতে পান তবে সম্ভবত আপনার কোডটি লেখার ক্ষেত্রে আরও কিছু মৌলিক ভুল রয়েছে?
Troelskn

1
না, এখনও এটি ব্যবহার করার প্রয়োজন নেই।
নিক স্টিনিমেটস

(object) ((array) $objectA)এর পরে আরও ভাল পারফরম্যান্সের সাথে আপনার একই কাঙ্ক্ষিত ফলাফলের ফলাফল clone $objectAবা ব্যবহার করতে পারে new stdClass
বিনিয়ামিন

উত্তর:


284

পিএইচপি 5+ অবজেক্ট রেফারেন্স দ্বারা পাস করা হয়। পিএইচপি 4 এ তারা মান দ্বারা পাস হয় (এ কারণেই এটি রেফারেন্স অনুসারে রানটাইম পাস করেছিল, যা অবমানিত হয়েছিল)।

আপনি পিএইচপি 5 এ 'ক্লোন' অপারেটরটি অবজেক্টগুলি অনুলিপি করতে ব্যবহার করতে পারেন:

$objectB = clone $objectA;

এছাড়াও, এটি কেবল এমন বস্তু যা রেফারেন্স দ্বারা পাস করা হয়, আপনি নিজের প্রশ্নে যা বলেছিলেন তা সবকিছু নয় ...


যে কেউ এই পড়ছেন তাকে কেবল যুক্ত করতে চান, ক্লোনিংটি আসল অবজেক্টের রেফারেন্স রাখবে। ক্লোনযুক্ত বস্তুটি ব্যবহার করে মাইএসকিউএল কোয়েরিগুলি চালনার অনাকাঙ্ক্ষিত ফলাফল হতে পারে, কারণ কার্যকর করা একটি রৈখিক ফ্যাশনে না ঘটে।
অ্যালেক্স

20
একটি সাধারণ ভুল ধারণাটি সংশোধন করতে (আমার মনে হয় এমনকি পিএইচপি ডক্সও এটি ভুল করে!) পিএইচপি 5 এর অবজেক্টগুলি "রেফারেন্স দ্বারা পাস করা হয় না"। জাভা হিসাবে তাদেরও ইন্ডিয়ারেশনের একটি অতিরিক্ত স্তর রয়েছে - একটি "অবজেক্ট পয়েন্টার" এর ভেরিয়েবল পয়েন্ট এবং এটি কোনও বস্তুর দিকে নির্দেশ করে। সুতরাং দুটি ভেরিয়েবল একই মানের উল্লেখ না করে একই বস্তুকে নির্দেশ করতে পারে। এই এই উদাহরণে থেকে দেখা যায়: $a = new stdClass; $b =& $a; $a = 42; var_export($b);এখানে $bএকটি রেফারেন্স পরিবর্তনশীল $a ; আপনি যদি =&কোনও স্বাভাবিকের সাথে প্রতিস্থাপন করেন তবে =এটি কোনও রেফারেন্স নয় এবং এখনও মূল অবজেক্টের দিকে নির্দেশ করে।
আইএমএসওপি

রেফারেন্স দ্বারা রানটাইম পাস একটি খারাপ ধারণা, কারণ এটি কোনও ফাংশন কলের প্রভাব নির্দিষ্টকরণের পরিবর্তে ফাংশন বাস্তবায়নের উপর নির্ভর করে। এটি ডিফল্ট হিসাবে মান দ্বারা পাসের সাথে কিছুই করার নেই।
ওসওয়াল্ড

1
@ অ্যালেক্স আপনি কি নিজের মন্তব্যে বিস্তারিত বলতে পারবেন? (হয় এখানে বা অন্য কোথাও)) আপনার বক্তব্যটি কিছুটা অস্পষ্ট আইএমও থেকে আসে।
ক্রিস মিডলটন

@ ক্রিসমিল্টন সি বা সি ++ এর শর্তাবলী সম্পর্কে ভাবেন: আপনি যদি এমন কোনও বিষয়টির জন্য রেফারেন্স ক্লোন করে থাকেন যা নিখরচায়, সুযোগের বাইরে বা প্রকাশিত হয়, তবে আপনার ক্লোনড রেফারেন্সটি অবৈধ। সুতরাং আপনি ক্লোনিংয়ের মাধ্যমে কোনও রেফারেন্স ধরে রাখলে আসল অবজেক্টটির সাথে কী ঘটেছিল তার উপর নির্ভর করে আপনি অপরিজ্ঞাত আচরণ পেতে পারেন
ইলেক্স

103

উত্তরগুলি সাধারণত জাভা বইগুলিতে পাওয়া যায়।

  1. ক্লোনিং: আপনি ক্লোন পদ্ধতিটি ওভাররাইড না করলে ডিফল্ট আচরণটি অগভীর অনুলিপি হয়। যদি আপনার অবজেক্টে কেবল আদিম সদস্যের পরিবর্তনশীল থাকে তবে এটি সম্পূর্ণ ঠিক। তবে সদস্যের ভেরিয়েবল হিসাবে অন্য কোনও অবজেক্টের সাথে টাইপহীন ভাষায় এটি মাথা ব্যথা।

  2. ধারাবাহিকতাতে / deserialization

$new_object = unserialize(serialize($your_object))

এটি বস্তুর জটিলতার উপর নির্ভর করে ভারী ব্যয়ের সাথে গভীর অনুলিপি অর্জন করে।


4
+1 দুর্দান্ত, দুর্দান্ত, দুর্দান্ত উপায় পিএইচপি-তে একটি ডিইপিপি অনুলিপি করা খুব সহজ easy পরিবর্তে আমি আপনাকে পিএইচপি ক্লোন কীওয়ার্ড দ্বারা প্রদত্ত স্ট্যান্ডার্ড অগভীর অনুলিপি সম্পর্কে কিছু জিজ্ঞাসা করব, আপনি বলেছিলেন যে কেবল আদিম সদস্যের ভেরিয়েবলগুলি অনুলিপি করা হয়: পিএইচপি অ্যারে / স্ট্রিংগুলি কি আদিম সদস্য ভেরিয়েবল হিসাবে বিবেচিত হয়, তাই তারা অনুলিপি পেয়েছে, আমি ঠিক আছি?
মার্কো ডেমাইও

3
যে কোনও ব্যক্তি এটি গ্রহণ করছেন: একটি "অগভীর" অনুলিপি ( $a = clone $bকোনও __clone()খেলায় কোনও যাদু পদ্ধতি ছাড়াই ) $bশব্দটি অবজেক্টের প্রতিটি বৈশিষ্ট্যের দিকে তাকানোর সমান এবং একই শ্রেণীর নতুন সদস্য হিসাবে একই সম্পত্তিকে বরাদ্দ করার সমতুল্য =। বস্তুযুক্ত বৈশিষ্ট্যগুলি cloneডি পাবেন না , বা কোনও অ্যারের অভ্যন্তরেও বস্তুগুলি পাবেন না ; একই রেফারেন্স দ্বারা আবদ্ধ পরিবর্তনশীল জন্য যায়; বাকি সমস্ত কিছুই একটি মূল্য, এবং কোনও অ্যাসাইনমেন্টের মতো অনুলিপি করা হয়।
আইএমএসওপি

3
পারফেক্ট! json_decode (json_encode ($ obj)); ব্যক্তিগত / সুরক্ষিত বৈশিষ্ট্য এবং যে কোনও পদ্ধতি ক্লোন নয় ... আনসিরিয়ালাইজ করুন (পদ্ধতিগুলিও ক্লোন করবেন না সিরিয়ালাইজ করুন ...
zloctb

অসাধারণ! আমি শেষ পর্যন্ত পিএইচপিস্টোরমের ত্রুটি থেকে মুক্তি পেয়েছি; Call to method __clone from invalid context:)
numeiaweb

বন্ধু এই জাতীয় কাজ করার সময় পিএইচপি পার্স ত্রুটি পাচ্ছে: $new_date = (clone $date_start)->subDays(1);এটির সাথে ব্যর্থ হয় (), আমি যদি সেগুলি সরিয়ে ফেলি তবে আমি একটি ভিন্ন ত্রুটি পাই। জিনিসটি হ'ল, আমরা ঠিক একই পিএইচপি 7.2.3 ব্যবহার করছি এবং খনিটি ভাল কাজ করে। কোন ধারনা? সর্বত্র অনুসন্ধান করা হয়েছে ..
ইমোলেটিভিটি

21

পূর্ববর্তী মন্তব্য অনুসারে, সদস্য ভেরিয়েবল হিসাবে আপনার যদি অন্য কোনও অবজেক্ট থাকে তবে নিম্নলিখিতটি করুন:

class MyClass {
  private $someObject;

  public function __construct() {
    $this->someObject = new SomeClass();
  }

  public function __clone() {
    $this->someObject = clone $this->someObject;
  }

}

এখন আপনি ক্লোনিং করতে পারেন:

$bar = new MyClass();
$foo = clone $bar;


4

পিএইচপি কেবল লেখার অনুলিপি ব্যবহার করে তা স্পষ্ট করে বলতে গেলে, যতক্ষণ না আপনি এটি সংশোধন না করা পর্যন্ত মূলত সবকিছুই একটি রেফারেন্স হয় তবে অবজেক্টের জন্য আপনাকে গ্রহণযোগ্য উত্তরের মতো ক্লোন এবং __ ক্লোন () ম্যাজিক পদ্ধতি ব্যবহার করতে হবে।


1

এই কোডটি ক্লোন পদ্ধতিগুলিতে সহায়তা করে

class Foo{

    private $run=10;
    public $foo=array(2,array(2,8));
    public function hoo(){return 5;}


    public function __clone(){

        $this->boo=function(){$this->hoo();};

    }
}
$obj=new Foo;

$news=  clone $obj;
var_dump($news->hoo());

এই কোডটি কিছুটা অকেজো, আপনি __ক্লোন পদ্ধতিটি সরিয়ে দিলেও এটি কার্যকর হবে :)
amik

1

আমি কিছু পরীক্ষা করছিলাম এবং এটি পেয়েছি:

class A {
  public $property;
}

function set_property($obj) {
  $obj->property = "after";
  var_dump($obj);
}

$a = new A();
$a->property = "before";

// Creates a new Object from $a. Like "new A();"
$b = new $a;
// Makes a Copy of var $a, not referenced.
$c = clone $a;

set_property($a);
// object(A)#1 (1) { ["property"]=> string(5) "after" }

var_dump($a); // Because function set_property get by reference
// object(A)#1 (1) { ["property"]=> string(5) "after" }
var_dump($b);
// object(A)#2 (1) { ["property"]=> NULL }
var_dump($c);
// object(A)#3 (1) { ["property"]=> string(6) "before" }

// Now creates a new obj A and passes to the function by clone (will copied)
$d = new A();
$d->property = "before";

set_property(clone $d); // A new variable was created from $d, and not made a reference
// object(A)#5 (1) { ["property"]=> string(5) "after" }

var_dump($d);
// object(A)#4 (1) { ["property"]=> string(6) "before" }

?>

1

এই উদাহরণে আমরা আইফোন ক্লাস তৈরি করব এবং ক্লোনিং করে এটি থেকে সঠিক কপি তৈরি করব

class iPhone {

public $name;
public $email;

    public function __construct($n, $e) {

       $this->name = $n;
       $this->email = $e;

    }
}


$main = new iPhone('Dark', 'm@m.com');
$copy = clone $main;


// if you want to print both objects, just write this    

echo "<pre>"; print_r($main);  echo "</pre>";
echo "<pre>"; print_r($copy);  echo "</pre>";

-1

আপনি যদি অন্য কোনও উপায়ে কোনও সামগ্রীর বৈশিষ্ট্য সম্পূর্ণরূপে অনুলিপি করতে চান তবে আপনি এই কৌশলটি ব্যবহার করতে পারেন:

এটি JSON এ সিরিয়ালাইজ করুন এবং তারপরে এটিকে অবজেক্টে ডি-সিরিয়ালাইজ করুন।


7
হুম আমি এটাকে জাহান্নামের মতো এড়িয়ে চলতাম।
জিমি কেন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.