ฟังก์ชัน Coalesce สำหรับ PHP?


131

ภาษาโปรแกรมจำนวนมากมีฟังก์ชันการรวมกัน (ส่งกลับค่าที่ไม่ใช่ค่า NULL ตัวแรกเช่น ) PHP น่าเศร้าในปี 2009 ไม่มี

อะไรจะเป็นวิธีที่ดีในการนำ PHP ไปใช้จนกว่า PHP จะได้รับฟังก์ชัน coalesce


11
ที่เกี่ยวข้อง: ตัวดำเนินการรวม null ใหม่??สำหรับ PHP 7
kojiro

สามารถดูข้อมูลเพิ่มเติมเกี่ยวกับตัวดำเนินการ coalesce ว่างได้ที่นี่ - stackoverflow.com/questions/33666256/…
ปีเตอร์

1
เพียงเพื่อทราบว่า PHP7 ใช้งานฟังก์ชันนี้
Grzegorz

@Grzegorz: ตัวดำเนินการไม่ใช่ฟังก์ชันหรือคุณพบฟังก์ชันนั้นใหม่ใน PHP 7
ที่ไหน

ตามฟังก์ชันฉันไม่ได้หมายถึงฟังก์ชัน;) คุณสมบัติ ฉันไม่แม่น ขอบคุณ :)
Grzegorz

คำตอบ:


194

มีตัวดำเนินการใหม่ใน php 5.3 ซึ่งทำสิ่งนี้: ?:

// A
echo 'A' ?: 'B';

// B
echo '' ?: 'B';

// B
echo false ?: 'B';

// B
echo null ?: 'B';

ที่มา: http://www.php.net/ChangeLog-5.php#5.3.0


25
สิ่งที่เกี่ยวกับทางลัด ternary หลาย ๆ อย่างเช่น "echo $ a?: $ b?: $ c?: $ d;" งาน?
ChrisR

5
ไม่ทำงานตามที่คาดไว้สำหรับอาร์เรย์ ตัวอย่างเช่นเมื่อพยายามตรวจสอบว่าองค์ประกอบอาร์เรย์ที่ไม่ได้กำหนดเป็นเท็จจะทำให้เกิดข้อผิดพลาด $input['properties']['range_low'] ?: '?'
Keyo

5
คุณควรได้รับการแจ้งดัชนีที่ไม่ได้กำหนดโดยไม่คำนึงถึงการใช้ตัวดำเนินการรวมกัน
Kevin

2
ข้อโต้แย้งหลาย falsey กลับอาร์กิวเมนต์ที่ผ่านมาผลตอบแทนarray() ?: null ?: false falseผู้ปฏิบัติงานมีสติ
Brad Koch

6
โปรดทราบว่าสิ่งนี้ไม่เพียงยอมรับการไม่เป็นโมฆะเหมือนการรวมกันในภาษาอื่น ๆ แต่ค่าใด ๆ ซึ่งจะถูกแปลงเป็นบูลีนโดยปริยาย ดังนั้นอย่าลืมทำความเข้าใจกฎการคัดเลือกประเภท
DanMan

65

PHP 7 แนะนำตัวดำเนินการเชื่อมต่อกันจริง:

echo $_GET['doesNotExist'] ?? 'fallback'; // prints 'fallback'

หากค่าก่อนหน้า??นี้ไม่มีอยู่หรือเป็นnullค่าหลังการ??ถ่าย

การปรับปรุงตัว?:ดำเนินการที่กล่าวถึงคือการ??จัดการกับตัวแปรที่ไม่ได้กำหนดโดยไม่ต้องทิ้งE_NOTICEไฟล์.


ในที่สุดก็ไม่มี isset () และว่าง () อีกต่อไปทั่วทุกที่!
George Kagan

7
@timeNomad คุณจะยังคงต้องว่างมันจะตรวจสอบค่าว่างเท่านั้น
Nabeel Khan

วิธีเดียวที่จะได้รับ "falsy-coalesce" อย่างปลอดภัยคือใช้ทั้งสองอย่าง:($_GET['doesNotExist'] ?? null) ?: 'fallback'
Nathan Baulch

อย่างไรก็ตามข้อดีของ?:over ??คือมันรวมค่าว่างด้วยซึ่ง??ไม่ได้ทำ คล้ายกับพฤติกรรมของตรรกะหรือผู้ประกอบการใน JavaScript (คือ$val || 'default') ผมจะพบว่า?:จะเป็นรูปแบบการปฏิบัติมากขึ้นของการรวมตัวกันถ้าในทางปฏิบัติของเราที่เราพบตัวเองในท้ายที่สุดการจัดการทั้งที่ว่างเปล่าและnullในลักษณะเดียวกัน (คือ$val ?: 'default') และหากคุณต้องการบังคับให้เกิดปัญหาต่อไปและกลืนE_NOTICEคุณสามารถโต้แย้งได้:echo @$val ?: 'default';
Matt Borja

29

Hit แรกสำหรับ "php coalesce" ใน Google

function coalesce() {
  $args = func_get_args();
  foreach ($args as $arg) {
    if (!empty($arg)) {
      return $arg;
    }
  }
  return NULL;
}

http://drupial.com/content/php-coalesce


9
บันทึก ram เล็กน้อยและอย่าทำซ้ำ args ในอาร์เรย์เพียงทำ foreach (func_get_args () เป็น $ arg) {}
TravisO

17
@ [Alfred, Ciaran] - คุณพูดไม่ถูก foreach () ประเมินอาร์กิวเมนต์แรกเพียงครั้งเดียวเพื่อรับอาร์เรย์แล้ววนซ้ำ
gahooa

6
การใส่ func_get_args () ไว้ใน foreach (ในที่นี้เป็น $ arg) จะไม่เปลี่ยนแปลงอะไรจากมุมมองด้านประสิทธิภาพ
Savageman

7
@Savageman ... เป๊ะ ... ถ้าคุณกำลังคิดที่จะบีบประสิทธิภาพในมิลลิวินาทีนี้หรือหน่วยความจำไม่กี่ไบต์ออกจากแอปพลิเคชันของคุณคุณอาจกำลังมองหาคอขวดของประสิทธิภาพ / หน่วยความจำที่ไม่ถูกต้อง
ChrisR

4
แดกดันตอนนี้เป็นเพลงฮิตแรกสำหรับ "php coalesce" ใน Google
Will Shaver

18

ฉันชอบตัวดำเนินการ?: น่าเสียดายที่ยังไม่ได้ใช้กับสภาพแวดล้อมการผลิตของฉัน ดังนั้นฉันจึงใช้สิ่งนี้เทียบเท่า:

function coalesce() {
  return array_shift(array_filter(func_get_args()));
}

1
นี่คือการรวมตัวกันแบบ 'truthy' โดยใช้ array_filter เพื่อกำจัดสิ่งที่ประเมินว่าเป็นเท็จ (รวมถึง null) ใน n อาร์กิวเมนต์ที่ส่งผ่านมาการคาดเดาของฉันใช้ shift แทนองค์ประกอบแรกในอาร์เรย์นั้นแข็งแกร่งกว่า แต่อย่างใด ส่วนฉันไม่รู้ ดู: php.net/manual/en/…
Adam Tolley

3
ผมชอบมัน แต่ได้เห็นด้วยกับ @hakre - coalesceควรจะกลับมาเป็นคนแรกที่ไม่ใช่ nullFALSEอาร์กิวเมนต์พบซึ่งจะรวมถึง ฟังก์ชั่นนี้จะทิ้งFALSEแม้ว่าอาจจะไม่ใช่สิ่งที่ op มีอยู่ในใจ (อย่างน้อยก็ไม่ใช่สิ่งที่ฉันต้องการจากcoalesceฟังก์ชัน)
Madbreaks

1
ควรส่งผ่านตัวแปรเท่านั้นโดยอ้างอิง
pronebird

10

เป็นที่น่าสังเกตว่าเนื่องจาก PHP ใช้ตัวแปรที่ไม่ได้กำหนดค่าและดัชนีอาร์เรย์ฟังก์ชันการรวมตัวกันจึงมีประโยชน์อย่าง จำกัด ฉันชอบที่จะทำสิ่งนี้ได้:

$id = coalesce($_GET['id'], $_SESSION['id'], null);

แต่ในกรณีส่วนใหญ่จะทำให้ PHP ผิดพลาดกับ E_NOTICE วิธีเดียวที่ปลอดภัยในการทดสอบการมีอยู่ของตัวแปรก่อนที่จะใช้คือการใช้มันโดยตรงในค่าว่าง () หรือ isset () ตัวดำเนินการด้านท้ายที่แนะนำโดย Kevin เป็นตัวเลือกที่ดีที่สุดหากคุณทราบว่าตัวเลือกทั้งหมดในการรวมตัวกันเป็นที่ทราบกันดีว่าเริ่มต้น


ในกรณีนี้สหภาพอาร์เรย์ทำงานได้ค่อนข้างดี ( $getstuff = $_GET+$_SESSION+array('id'=>null);$id=$getstuff['id'];)
Brilliand

@ พูดว่ามันหมายความว่ายังไง? คุณมีวิธีแก้ปัญหาที่แนะนำพร้อมข้อมูลอ้างอิงหรือไม่?
pronebird

PHP 7 ขอแนะนำตัวดำเนินการternary issetใหม่ที่น่ารัก??เพื่อให้การดำเนินการทั่วไปนี้กระชับมากขึ้น
botimer

6

ตรวจสอบให้แน่ใจว่าคุณระบุอย่างชัดเจนว่าคุณต้องการให้ฟังก์ชันนี้ทำงานกับบางประเภทอย่างไร PHP มีฟังก์ชันการตรวจสอบประเภทหรือฟังก์ชันที่คล้ายคลึงกันมากมายดังนั้นโปรดตรวจสอบให้แน่ใจว่าคุณทำงานอย่างไร นี่คือตัวอย่างการเปรียบเทียบ is_null () และว่าง ()

$testData = array(
  'FALSE'   => FALSE
  ,'0'      => 0
  ,'"0"'    => "0"  
  ,'NULL'   => NULL
  ,'array()'=> array()
  ,'new stdClass()' => new stdClass()
  ,'$undef' => $undef
);

foreach ( $testData as $key => $var )
{
  echo "$key " . (( empty( $var ) ) ? 'is' : 'is not') . " empty<br>";
  echo "$key " . (( is_null( $var ) ) ? 'is' : 'is not')  . " null<br>";
  echo '<hr>';
}

อย่างที่คุณเห็น empty () จะคืนค่าจริงสำหรับสิ่งเหล่านี้ทั้งหมด แต่ is_null () ทำเพียง 2 ตัวเท่านั้น


2

ฉันขยายตัวในคำตอบที่โพสต์โดยอีธานเคนต์ คำตอบนั้นจะละทิ้งอาร์กิวเมนต์ที่ไม่เป็นค่าว่างที่ประเมินว่าเป็นเท็จเนื่องจากการทำงานภายในของarray_filterซึ่งไม่ใช่สิ่งที่coalesceฟังก์ชันโดยทั่วไปทำ ตัวอย่างเช่น:

echo 42 === coalesce(null, 0, 42) ? 'Oops' : 'Hooray';

อ๊ะ

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

// "callable"
function not_null($i){
    return !is_null($i);  // strictly non-null, 'isset' possibly not as much
}

function coalesce(){
    // pass callable to array_filter
    return array_shift(array_filter(func_get_args(), 'not_null'));
}

คงจะดีไม่น้อยถ้าคุณสามารถผ่านissetหรือ'isset'เป็นข้อโต้แย้งที่ 2 ไปarray_filterได้ แต่ไม่มีโชคเช่นนั้น


0

ฉันกำลังใช้สิ่งนี้อยู่ แต่ฉันสงสัยว่ามันไม่สามารถปรับปรุงได้ด้วยคุณสมบัติใหม่บางอย่างใน PHP 5

function coalesce() {
  $args = func_get_args();
  foreach ($args as $arg) {
    if (!empty($arg)) {
    return $arg;
    }
  }
  return $args[0];
}

0

PHP 5.3+ พร้อมการปิด:

function coalesce()
{
    return array_shift(array_filter(func_get_args(), function ($value) {
        return !is_null($value);
    }));
}

การสาธิต: https://eval.in/187365


ควรส่งผ่านตัวแปรเท่านั้นโดยอ้างอิง
pronebird

ใช่ฉันฝ่าฝืนกฎที่เข้มงวดสำหรับการสาธิตเพียงเพื่อให้มันง่าย :)
Paulo Freitas
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.