วิธีที่ดีที่สุดในการให้ตัวแปรเป็นค่าเริ่มต้น (จำลอง Perl ||, || =)


134

ฉันรักการทำเรียงลำดับของสิ่งนี้ใน Perl: $foo = $bar || $bazเพื่อกำหนด$bazไป$fooถ้า$barว่างเปล่าหรือไม่ได้กำหนด คุณยังมี$foo ||= $bletchเท่านั้นที่จะกำหนด$bletchไป$fooถ้า$fooไม่ได้กำหนดไว้หรือว่างเปล่า

ผู้ดำเนินการที่เกี่ยวข้องในสถานการณ์นี้น่าเบื่อและน่าเบื่อ แน่นอนว่ามีวิธีที่เรียบง่ายและสวยงามใน PHP?

หรือคำตอบเดียวคือฟังก์ชันกำหนดเองที่ใช้ isset ()?


1
ที่เกี่ยวข้องกับCode Review : codereview.stackexchange.com/q/12722/31433
Palec

1
BTW ตัวดำเนินการ Perl ที่มีฟังก์ชันการทำงานที่ต้องการ//และ//=มีอยู่ใน Perl v5.10.0 ต้นฉบับ||และ||=ทดสอบค่าตรรกะไม่ใช่สำหรับการกำหนด
Palec

@Palec ทำไมคำถามอายุ 4 ปีที่มีการโหวต 29 ครั้งจึงถูกระบุว่าซ้ำกับคำถามอายุ 1 ปีที่มีการโหวต 6 ครั้ง (ซึ่งตัวเองถูกทำเครื่องหมายว่าซ้ำกับคำถามอื่น) ฉันคิดว่ามีคุณค่ามากในการรักษาสิ่งนี้ไว้ คำถามเนื่องจากชื่อเรื่องมีความกว้างมากขึ้น (ไม่ได้อ้างอิงคำตอบเช่น isset ())
Tom Auger

มีความชัดเจนและซ้ำกันทุกประการ ยอมรับว่าฉันไม่ได้คิดมากว่าอันไหนควรจะเป็นต้นฉบับฉันอยู่ตรงกลางของอย่างอื่นการเชื่อมโยงระหว่างทั้งสองคือเป้าหมาย การถอน VTC ของฉัน
Palec

ซ้ำกันทุกประการทำเครื่องหมาย (IMO ผิดพลาด) ว่าซ้ำกับคำถามอื่น: PHP ชวเลขสำหรับ isset ()?
Palec

คำตอบ:


131

ใน PHP 7 เราก็มีวิธีทำสิ่งนี้อย่างสวยงาม มันถูกเรียกว่าผู้ประกอบการหลอมรวม Null คุณสามารถใช้งานได้ดังนี้:

$name = $_GET['name'] ?? 'john doe';

ซึ่งเทียบเท่ากับ

$name = isset($_GET['name']) ? $_GET['name']:'john doe';

14
ฉันขอยืนยันว่าผู้ประกอบการยานอวกาศก็มีบุญเช่นกัน
Mariano

3
ฉันคิดว่า Mariano กำลังดึงขาของเรา แต่ไม่มันเป็นเรื่องที่<=>แม่นยำและค่อนข้างแม่นยำในการบูต!
HPWD

1
โปรดสังเกตว่าตัวดำเนินการการรวมกันเป็นโมฆะทำงานแตกต่างจากตัวดำเนินการตามเงื่อนไขเนื่องจากเป็นค่าเฉพาะสำหรับnullค่า ตัวอย่างเช่นถ้า$_GET['name']มีการตั้งค่าเป็นสตริงว่างบรรทัดแรกจะกลับมาเป็นสตริงว่าง แต่เราจะกลับมา "จอห์นโด" $_GET['name'] ? $_GET['name'] : 'john doe'โดยใช้
VPhantom

211

PHP 5.3 มีตัว?:ดำเนินการชวเลข:

$foo = $bar ?: $baz;

ซึ่งกำหนด$barหากไม่ใช่ค่าว่าง (ฉันไม่รู้ว่าสิ่งนี้จะแตกต่างใน PHP จาก Perl อย่างไร) มิฉะนั้น$bazจะเหมือนกับสิ่งนี้ใน Perl และ PHP เวอร์ชันเก่ากว่า:

$foo = $bar ? $bar : $baz;

แต่ PHP ไม่มีตัวดำเนินการกำหนดแบบผสมสำหรับสิ่งนี้ (นั่นคือไม่เทียบเท่ากับ Perl ||= )

นอกจากนี้ PHP จะส่งเสียงดังหาก$barไม่ได้ตั้งค่าเว้นแต่คุณจะปิดการแจ้งเตือน นอกจากนี้ยังมีความแตกต่างระหว่างความหมายและisset() อดีตกลับเท็จถ้าตัวแปรไม่อยู่หรือมีการตั้งค่าempty() NULLผลตอบแทนหลังจริงถ้ามันไม่ได้อยู่หรือมีการตั้งค่า0, '', หรือfalseNULL


2
+1 สำหรับการแนะนำให้ฉันรู้จักคุณสมบัติที่ยอดเยี่ยมอีกอย่างของ 5.3 ที่ฉันพลาดในเซิร์ฟเวอร์ RHEL5 / PHP5.1.2 ของฉัน
Michael Berkowski

ฉันเดาว่าคุณหมายถึงThe first returnsแทนที่จะเป็นThe secondประโยคสุดท้ายของคุณ
Toto

21
โปรดทราบว่าหากไม่ได้กำหนดตัวแปรของคุณ PHP จะแจ้งให้ทราบล่วงหน้า น่าเสียดายที่สิ่งนี้ไม่สามารถแทนที่ได้$var = isset($var) ? $var : 'default value'; มันบอกว่าในคำตอบ ... เพียงแค่ชี้ให้เห็นอีกครั้งสำหรับใครก็ตามที่อ่านมัน :-D
Brad

6
การทำ $ var = @ $ var ไม่ดีหรือไม่: 'default value'; ถ้าเป็นเช่นนั้นทำไม? ระบุว่า "ข้อผิดพลาด" เพียงข้อเดียวอาจเป็นเพราะไม่ได้ตั้งค่า $ var และเราไม่สนใจว่าจะไม่ได้ตั้งค่า $ var หรือไม่ ...
Codemonkey

8

ขอบคุณสำหรับคำตอบที่ยอดเยี่ยม!

สำหรับใครก็ตามที่มาที่นี่เพื่อหาทางเลือกอื่นที่เป็นไปได้นี่คือฟังก์ชั่นบางอย่างที่ช่วยขจัดความน่าเบื่อหน่ายจากสิ่งเหล่านี้

function set_if_defined(&$var, $test){
    if (isset($test)){
        $var = $test;
        return true;
    } else {
        return false;
    }
}

function set_unless_defined(&$var, $default_var){
    if (! isset($var)){
        $var = $default_var;
        return true;
    } else {
        return false;
    }
}

function select_defined(){
    $l = func_num_args();
    $a = func_get_args();
    for ($i=0; $i<$l; $i++){
        if ($a[$i]) return $a[$i];
    }
}

ตัวอย่าง:

// $foo ||= $bar;
set_unless_defined($foo, $bar);

//$foo = $baz || $bletch
$foo = select_defined($baz, $bletch);

ฉันแน่ใจว่าสิ่งเหล่านี้สามารถปรับปรุงได้


7

สำนวนทั่วไปที่ใช้งานร่วมกับ PHP เวอร์ชันเก่าได้คือ:

 $var = $bool   or   $var = "default";
 // If I use it, then only with excessive spaces for clarity.

สิ่งนี้ใช้ได้กับค่าที่สามารถประเมินได้ในบริบทบูลีน ข้อดีก็คือมันยังช่วยให้คุณได้กล่าวว่าการแก้ปัญหา e_notice ควรไม่ได้กำหนดตัวแปร


ไม่มีการแจ้งเตือน$bool ? $bool : "default"หาก$boolไม่ได้กำหนดไว้หรือไม่?
BoltClock

แน่นอนว่าเหมือนกัน ผมถือว่า OP isset($var) ? $var : DEFAULTจะหมายถึง แต่ดูเหมือนว่าเขาต้องการที่จะหลีกเลี่ยงพวกเขาอยู่ดี
มาริโอ

6

ใน PHP ก่อนหน้า 7. * อาจใช้?: สำหรับตัวแปรที่ไม่ได้กำหนดซึ่งมีข้อผิดพลาดถูกระงับในเครื่องด้วย@:

$foo = @$bar ?: $baz;

0

นี่เป็นอีกรูปแบบที่ดีสำหรับissetกรณีนี้

isset($foo) || $foo= $bar;

อีกวิธีง่ายๆและจะทำให้คุณควบคุมได้มากขึ้นเนื่องจากคุณสามารถเพิ่มเงื่อนไขและกำหนดให้กับตัวแปรอื่นได้ในเวลาเดียวกัน

$foo = (isset($oData['foo']))?$bar['foo']:'default value';


0

ทางออกที่เป็นไปได้: defaultFor ()

เว้นแต่เราจะมีโซลูชันจากโรงงาน (ซึ่งน่ารำคาญมาก) ฉันขอแนะนำผู้ช่วยตัวน้อยต่อไปนี้ มันทำงานในกรณีส่วนใหญ่:


    function defaultFor(&$x,$default=null) {
        if(!isset($x)) $x = $default;
    }

    //--------------------  Now you can do this: --------------

    defaultFor($a,"Jack");  // if $a is not set, it will be "Jack"
    defaultFor($x);         // no more notices for $x but keep it !isset

ฉันหวังว่านี่จะใกล้เคียงกับสิ่งที่คุณต้องการบรรลุ มันจะไม่แจ้งให้คุณทราบหากคุณใช้กับตัวแปรที่ไม่มีอยู่จริงและมันค่อนข้างสะดวก แน่นอนว่ามันมีข้อเสียเปรียบ: ค่าเริ่มต้นจะได้รับการคำนวณล่วงหน้าเสมอดังนั้นอย่าใช้กับสิ่งที่หนักเป็นพารามิเตอร์ที่สองเช่น file_get_contents หรือบางอย่าง ในกรณีเหล่านี้คุณควรตั้งเป้าหมายไว้ก่อนดีกว่า


0

ฉันคิดว่าโดยทั่วไปแล้วการทำสิ่งนี้:

$foo = $bar || $baz;

เป็นความคิดที่ไม่ดีเว้นแต่$barและ$bazเป็นทั้งบูลีน ถ้าพวกเขาไม่:

$bar = 10;
$baz = 11;

คำถามจะกลายเป็นสิ่งที่กำหนดว่าบางสิ่งเป็นจริงหรือเท็จ? คนส่วนใหญ่อาจคาดหวังว่าศูนย์จะเป็นเท็จและทุกอย่างจะเป็นจริง แต่มีบางภาษา (เช่น Ruby) เท่านั้นfalseและnilเป็นเท็จซึ่งหมายความว่าทั้งสองอย่าง0และ1จะเป็นจริง เนื่องจากความคลุมเครือข้ามภาษานี้ฉันคิดว่าควรอธิบายให้ชัดเจนในกรณีเหล่านี้:

if ($bar !== 0) {
   $foo = $bar;
} else {
   $foo = $baz;
}

หรือ:

$foo = $bar !== 0 ? $bar : $baz;
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.