ตัวแปร PHP ถูกส่งผ่านโดยค่าหรืออ้างอิง?
ตัวแปร PHP ถูกส่งผ่านโดยค่าหรืออ้างอิง?
คำตอบ:
มันเป็นตามมูลค่าตามเอกสาร PHP
โดยค่าเริ่มต้นอาร์กิวเมนต์ของฟังก์ชันจะถูกส่งผ่านตามค่า (เพื่อให้หากค่าของอาร์กิวเมนต์ภายในฟังก์ชันนั้นเปลี่ยนไปจะไม่ได้รับการเปลี่ยนแปลงนอกฟังก์ชัน) เพื่อให้ฟังก์ชั่นสามารถแก้ไขข้อโต้แย้งของมันพวกเขาจะต้องผ่านการอ้างอิง
หากต้องการให้อาร์กิวเมนต์ของฟังก์ชันผ่านการอ้างอิงเสมอให้ใส่เครื่องหมายแอมเปอร์แซนด์ ( & ) กับชื่ออาร์กิวเมนต์ในนิยามฟังก์ชัน
<?php
function add_some_extra(&$string)
{
$string .= 'and something extra.';
}
$str = 'This is a string, ';
add_some_extra($str);
echo $str; // outputs 'This is a string, and something extra.'
?>
$str = add_some_extra($str);
ว่าฉันไม่ได้ใช้การอ้างอิงใช่มั้ย แล้วมูลค่าเพิ่มที่แท้จริงของมันคืออะไร?
$str
จะมีการกำหนด null ในกรณีของคุณ
ใน PHP โดยวัตถุเริ่มต้นจะถูกส่งผ่านเป็นสำเนาอ้างอิงไปยังวัตถุใหม่
ดูตัวอย่างนี้ .............
class X {
var $abc = 10;
}
class Y {
var $abc = 20;
function changeValue($obj)
{
$obj->abc = 30;
}
}
$x = new X();
$y = new Y();
echo $x->abc; //outputs 10
$y->changeValue($x);
echo $x->abc; //outputs 30
ตอนนี้ดู ..............
class X {
var $abc = 10;
}
class Y {
var $abc = 20;
function changeValue($obj)
{
$obj = new Y();
}
}
$x = new X();
$y = new Y();
echo $x->abc; //outputs 10
$y->changeValue($x);
echo $x->abc; //outputs 10 not 20 same as java does.
ตอนนี้ดู ..............
class X {
var $abc = 10;
}
class Y {
var $abc = 20;
function changeValue(&$obj)
{
$obj = new Y();
}
}
$x = new X();
$y = new Y();
echo $x->abc; //outputs 10
$y->changeValue($x);
echo $x->abc; //outputs 20 not possible in java.
ฉันหวังว่าคุณจะเข้าใจสิ่งนี้
$y
ไม่จำเป็น - ไม่มีสิ่งใดfunction changeValue
ที่ต้องการให้อยู่ข้างในclass Y
ดังนั้นแนวคิดที่ไม่เกี่ยวข้องสองอย่างเข้าด้วยกัน ผมจะย้ายไปยังขอบเขตนอกเหนือfunction changeValue
ลบการอ้างอิงถึง$x = new X();
$y
ตอนนี้มันง่ายที่จะเห็นว่าทั้งสองตัวอย่างแรกออกจาก $ x new Y()
คนเดียวและหนึ่งในสามการเปลี่ยนแปลงเนื้อหาไป ซึ่งจะง่ายต่อการดูว่าคุณทิ้งtype
ของ$x
- ความจริงที่ว่าทั้งสองX
และY
เกิดขึ้นรวมถึง$abc
เขตข้อมูลที่ไม่เกี่ยวข้องกับสิ่งที่แสดง
ดูเหมือนว่าผู้คนจำนวนมากสับสนด้วยวิธีที่วัตถุถูกส่งผ่านไปยังฟังก์ชั่นและความหมายของการส่งผ่านโดยการอ้างอิง ตัวแปรออบเจคต์ยังคงถูกส่งผ่านตามค่าเพียงค่าที่ส่งผ่านใน PHP5 เป็นตัวอ้างอิง เป็นหลักฐาน:
<?php
class Holder {
private $value;
public function __construct($value) {
$this->value = $value;
}
public function getValue() {
return $this->value;
}
}
function swap($x, $y) {
$tmp = $x;
$x = $y;
$y = $tmp;
}
$a = new Holder('a');
$b = new Holder('b');
swap($a, $b);
echo $a->getValue() . ", " . $b->getValue() . "\n";
ขาออก:
a, b
ในการผ่านการอ้างอิงหมายถึงเราสามารถปรับเปลี่ยนตัวแปรที่ผู้โทรเห็น ซึ่งชัดเจนรหัสข้างต้นไม่ได้ทำ เราจำเป็นต้องเปลี่ยนฟังก์ชั่นสลับเป็น:
<?php
function swap(&$x, &$y) {
$tmp = $x;
$x = $y;
$y = $tmp;
}
$a = new Holder('a');
$b = new Holder('b');
swap($a, $b);
echo $a->getValue() . ", " . $b->getValue() . "\n";
ขาออก:
b, a
เพื่อที่จะผ่านการอ้างอิง
swap
ฟังก์ชัน กล่าวอีกนัยหนึ่งถ้าวัตถุ "ผ่านตามตัวอักษร" ในทางกลับกันก็เป็นสิ่งที่คุณคาดหวังหากมีการส่งวัตถุไปยังฟังก์ชันซึ่งเป็นสิ่งที่เกิดขึ้นจริง รหัสของคุณไม่แยกความแตกต่างระหว่างสองกรณีนี้
http://www.php.net/manual/en/migration5.oop.php
ใน PHP 5 มี Object Model ใหม่ การจัดการวัตถุของ PHP ได้รับการเขียนใหม่อย่างสมบูรณ์ทำให้มีประสิทธิภาพที่ดีขึ้นและมีคุณสมบัติมากขึ้น ใน PHP เวอร์ชันก่อนหน้านี้วัตถุได้รับการจัดการเหมือนประเภทดั้งเดิม (เช่นจำนวนเต็มและสตริงตัวอย่าง) ข้อเสียของวิธีนี้คือความหมายวัตถุทั้งหมดถูกคัดลอกเมื่อตัวแปรถูกกำหนดหรือส่งผ่านเป็นพารามิเตอร์ไปยังวิธีการ ในวิธีการใหม่วัตถุจะถูกอ้างอิงโดยหมายเลขอ้างอิงและไม่ใช่ตามค่า (หนึ่งสามารถคิดว่าหมายเลขอ้างอิงเป็นตัวระบุของวัตถุ)
ตัวแปร PHP ถูกกำหนดโดยค่าส่งผ่านไปยังฟังก์ชันตามค่าและเมื่อมี / แสดงวัตถุถูกส่งผ่านโดยการอ้างอิง คุณสามารถบังคับให้ตัวแปรผ่านการอ้างอิงโดยใช้ &
มอบหมายโดยค่า / ตัวอย่างอ้างอิง:
$var1 = "test";
$var2 = $var1;
$var2 = "new test";
$var3 = &$var2;
$var3 = "final test";
print ("var1: $var1, var2: $var2, var3: $var3);
จะส่งออก
var1: ทดสอบ, var2: การทดสอบขั้นสุดท้าย, var3: การทดสอบขั้นสุดท้าย
ผ่านค่า / ตัวอย่างอ้างอิง:
$var1 = "foo";
$var2 = "bar";
changeThem($var1, $var2);
print "var1: $var1, var2: $var2";
function changeThem($var1, &$var2){
$var1 = "FOO";
$var2 = "BAR";
}
จะส่งออก:
var1: foo, var2 BAR
ตัวแปรวัตถุที่ส่งผ่านโดย exampe อ้างอิง:
class Foo{
public $var1;
function __construct(){
$this->var1 = "foo";
}
public function printFoo(){
print $this->var1;
}
}
$foo = new Foo();
changeFoo($foo);
$foo->printFoo();
function changeFoo($foo){
$foo->var1 = "FOO";
}
จะส่งออก:
FOO
(ตัวอย่างสุดท้ายนั้นน่าจะดีกว่า ... )
$foo
เป็นตัวชี้ไปยังวัตถุ $foo
จะผ่านค่าไปยังฟังก์ชันchangeFoo()
เช่นไม่ได้ประกาศพารามิเตอร์ด้วยchangeFoo()
&
คุณสามารถส่งตัวแปรไปยังฟังก์ชันโดยการอ้างอิง ฟังก์ชั่นนี้จะสามารถแก้ไขตัวแปรเดิมได้
คุณสามารถกำหนดเนื้อเรื่องโดยอ้างอิงในนิยามฟังก์ชั่น:
<?php
function changeValue(&$var)
{
$var++;
}
$result=5;
changeValue($result);
echo $result; // $result is 6 here
?>
คุณสามารถทำได้ทั้งสองทาง
ใส่สัญลักษณ์ '&' ไว้ข้างหน้าและตัวแปรที่คุณส่งผ่านจะเป็นหนึ่งเดียวกับต้นกำเนิดของมัน เช่น: คุณสามารถส่งต่อโดยการอ้างอิงแทนที่จะทำสำเนา
ดังนั้น
$fred = 5;
$larry = & $fred;
$larry = 8;
echo $fred;//this will output 8, as larry and fred are now the same reference.
ตัวแปรที่มีประเภทดั้งเดิมจะถูกส่งผ่านโดยค่าใน PHP5 ตัวแปรที่มีวัตถุถูกส่งผ่านโดยการอ้างอิง มีบทความที่น่าสนใจจาก Linux Journal จากปี 2006 ที่กล่าวถึงสิ่งนี้และความแตกต่าง OO อื่น ๆ ระหว่าง 4 และ 5
&
ถ้าพารามิเตอร์ของฟังก์ชันไม่มี
วัตถุถูกส่งผ่านโดยการอ้างอิงใน PHP 5 และตามค่าใน PHP 4 ตัวแปรจะถูกส่งผ่านตามค่าเริ่มต้น!
อ่านที่นี่: http://www.webeks.net/programming/php/ampersand-operator-used-for-assigning-reference.html
&
ตัวแปรทั้งหมดจะถูกส่งผ่านโดยค่าถ้าพารามิเตอร์ของฟังก์ชันที่ส่งผ่านไปไม่ได้
&
ด้านหน้าพารามิเตอร์ในคำจำกัดความ - ถ้าพวกเขาถูกส่งผ่านด้วยค่าวัตถุที่อยู่ในขอบเขตที่เรียกว่าฟังก์ชั่นเป็นพารามิเตอร์จะ ไม่ได้รับผลกระทบ
class Holder
{
private $value;
public function __construct( $value )
{
$this->value = $value;
}
public function getValue()
{
return $this->value;
}
public function setValue( $value )
{
return $this->value = $value;
}
}
class Swap
{
public function SwapObjects( Holder $x, Holder $y )
{
$tmp = $x;
$x = $y;
$y = $tmp;
}
public function SwapValues( Holder $x, Holder $y )
{
$tmp = $x->getValue();
$x->setValue($y->getValue());
$y->setValue($tmp);
}
}
$a1 = new Holder('a');
$b1 = new Holder('b');
$a2 = new Holder('a');
$b2 = new Holder('b');
Swap::SwapValues($a1, $b1);
Swap::SwapObjects($a2, $b2);
echo 'SwapValues: ' . $a2->getValue() . ", " . $b2->getValue() . "<br>";
echo 'SwapObjects: ' . $a1->getValue() . ", " . $b1->getValue() . "<br>";
แอตทริบิวต์ยังคงสามารถแก้ไขได้เมื่อไม่ผ่านการอ้างอิงดังนั้นโปรดระวัง
เอาท์พุท:
SwapObjects: b, a SwapValues: a, b
สำหรับทุกคนที่เจอสิ่งนี้ในอนาคตฉันต้องการแบ่งปันอัญมณีนี้จากเอกสาร PHP ที่โพสต์โดยผู้ใช้ที่ไม่ระบุชื่อ :
ดูเหมือนจะมีความสับสนบางอย่างที่นี่ ความแตกต่างระหว่างพอยน์เตอร์และการอ้างอิงไม่เป็นประโยชน์อย่างยิ่ง พฤติกรรมในตัวอย่าง "ครอบคลุม" บางส่วนที่โพสต์แล้วสามารถอธิบายได้ด้วยคำศัพท์รวมที่ง่ายกว่า ตัวอย่างเช่นโค้ดของ Hayley กำลังทำสิ่งที่คุณควรคาดหวัง (ใช้> = 5.3)
หลักการแรก: ตัวชี้เก็บที่อยู่หน่วยความจำเพื่อเข้าถึงวัตถุ ทุกครั้งที่มีการกำหนดวัตถุตัวชี้จะถูกสร้างขึ้น (ฉันยังไม่ได้เจาะลึกเกินไปในเครื่องมือ Zend แต่เท่าที่ฉันเห็นนี่ใช้)
หลักการที่สองและแหล่งที่มาของความสับสนมากที่สุด: การส่งผ่านตัวแปรไปยังฟังก์ชันทำโดยค่าเริ่มต้นเป็นค่าผ่านเช่นคุณกำลังทำงานกับสำเนา "แต่วัตถุถูกส่งผ่านโดยการอ้างอิง!" ความเข้าใจผิดทั่วไปทั้งที่นี่และในโลก Java ฉันไม่เคยพูดถึงสำเนาของอะไร การส่งผ่านเริ่มต้นจะทำตามค่า เสมอ. สิ่งที่จะถูกคัดลอกและส่งผ่าน แต่เป็นตัวชี้ เมื่อใช้ "->" แน่นอนว่าคุณจะสามารถเข้าถึง internals เช่นเดียวกับตัวแปรดั้งเดิมในฟังก์ชั่นผู้โทร เพียงแค่ใช้ "=" จะเล่นกับสำเนาเท่านั้น
หลักการที่สาม: "&" โดยอัตโนมัติและถาวรตั้งชื่อตัวแปร / ตัวชี้ไปยังที่อยู่หน่วยความจำเดียวกันกับสิ่งอื่นจนกว่าคุณจะแยกออก มันถูกต้องที่จะใช้คำว่า "นามแฝง" ที่นี่ คิดว่ามันเป็นการเข้าร่วมสองตัวชี้ที่สะโพกจนถูกบังคับด้วย "unset ()" ฟังก์ชันนี้มีอยู่ทั้งในขอบเขตเดียวกันและเมื่อมีการส่งอาร์กิวเมนต์ไปยังฟังก์ชัน บ่อยครั้งที่อาร์กิวเมนต์ที่ส่งผ่านถูกเรียกว่า "การอ้างอิง" เนื่องจากมีความแตกต่างบางอย่างระหว่าง "การส่งผ่านค่า" และ "การส่งผ่านตามการอ้างอิง" ที่ชัดเจนใน C และ C ++
เพียงจำไว้ว่า: พอยน์เตอร์ไปยังวัตถุต่าง ๆ จะถูกส่งผ่านไปยังฟังก์ชั่น ตัวชี้เหล่านี้เป็นสำเนาของต้นฉบับเว้นแต่คุณจะใช้ "&" ในรายการพารามิเตอร์ของคุณเพื่อส่งต้นฉบับ เฉพาะเมื่อคุณขุดลงไปใน internals ของวัตถุต้นฉบับจะเปลี่ยน
และนี่คือตัวอย่างที่พวกเขาให้:
<?php
//The two are meant to be the same
$a = "Clark Kent"; //a==Clark Kent
$b = &$a; //The two will now share the same fate.
$b="Superman"; // $a=="Superman" too.
echo $a;
echo $a="Clark Kent"; // $b=="Clark Kent" too.
unset($b); // $b divorced from $a
$b="Bizarro";
echo $a; // $a=="Clark Kent" still, since $b is a free agent pointer now.
//The two are NOT meant to be the same.
$c="King";
$d="Pretender to the Throne";
echo $c."\n"; // $c=="King"
echo $d."\n"; // $d=="Pretender to the Throne"
swapByValue($c, $d);
echo $c."\n"; // $c=="King"
echo $d."\n"; // $d=="Pretender to the Throne"
swapByRef($c, $d);
echo $c."\n"; // $c=="Pretender to the Throne"
echo $d."\n"; // $d=="King"
function swapByValue($x, $y){
$temp=$x;
$x=$y;
$y=$temp;
//All this beautiful work will disappear
//because it was done on COPIES of pointers.
//The originals pointers still point as they did.
}
function swapByRef(&$x, &$y){
$temp=$x;
$x=$y;
$y=$temp;
//Note the parameter list: now we switched 'em REAL good.
}
?>
ฉันเขียนโพสต์บล็อกที่ละเอียดและละเอียดเกี่ยวกับเรื่องนี้สำหรับ JavaScriptแต่ฉันเชื่อว่ามันใช้ได้ดีกับ PHP, C ++ และภาษาอื่น ๆ ที่ผู้คนดูเหมือนจะสับสนเกี่ยวกับ pass by value และ pass by reference
เห็นได้ชัดว่า PHP เช่น C ++ เป็นภาษาที่รองรับการส่งผ่านโดยอ้างอิง โดยค่าเริ่มต้นวัตถุจะถูกส่งผ่านตามค่า เมื่อทำงานกับตัวแปรที่เก็บวัตถุมันจะช่วยให้เห็นตัวแปรเหล่านั้นในฐานะตัวชี้ (เพราะเป็นสิ่งพื้นฐานในระดับแอสเซมบลี) หากคุณผ่านตัวชี้ตามค่าคุณยังสามารถ "ติดตาม" ตัวชี้และปรับเปลี่ยนคุณสมบัติของวัตถุที่ถูกชี้ไป สิ่งที่คุณไม่สามารถทำได้คือให้ชี้ไปที่วัตถุอื่น เฉพาะในกรณีที่คุณประกาศพารามิเตอร์อย่างชัดเจนว่าถูกส่งผ่านโดยการอ้างอิงคุณจะสามารถทำเช่นนั้นได้
จริงๆแล้วทั้งสองวิธีนี้ใช้ได้ แต่ขึ้นอยู่กับความต้องการของคุณค่าของรหัสผ่านมักจะทำให้สคริปต์ของคุณช้า ดังนั้นจึงเป็นการดีกว่าที่จะส่งผ่านตัวแปรตามค่าโดยพิจารณาจากเวลาในการดำเนินการ การไหลของรหัสนั้นสอดคล้องกันมากขึ้นเมื่อคุณส่งตัวแปรตามค่า
ใช้สิ่งนี้สำหรับฟังก์ชั่นเมื่อคุณต้องการที่จะเปลี่ยนตัวแปรดั้งเดิมและกลับไปที่ชื่อตัวแปรเดียวกันกับค่าใหม่ที่ได้รับมอบหมาย
function add(&$var){ // The & is before the argument $var
$var++;
}
$a = 1;
$b = 10;
add($a);
echo "a is $a,";
add($b);
echo " a is $a, and b is $b"; // Note: $a and $b are NOT referenced
ขึ้นอยู่กับเวอร์ชัน 4 คือตามค่า 5 คืออ้างอิง