ใน PHP คุณใช้งานเมื่อใด
define('FOO', 1);
และเมื่อไหร่ที่คุณจะใช้
const FOO = 1;
?
อะไรคือความแตกต่างที่สำคัญระหว่างสองสิ่งนี้?
ใน PHP คุณใช้งานเมื่อใด
define('FOO', 1);
และเมื่อไหร่ที่คุณจะใช้
const FOO = 1;
?
อะไรคือความแตกต่างที่สำคัญระหว่างสองสิ่งนี้?
คำตอบ:
ในฐานะของ PHP 5.3 มีสองวิธีในการกำหนดค่าคงที่ : อาจใช้constคำหลักหรือใช้define()ฟังก์ชั่น:
const FOO = 'BAR';
define('FOO', 'BAR');
ความแตกต่างพื้นฐานระหว่างทั้งสองวิธีคือการconstกำหนดค่าคงที่ในเวลารวบรวมในขณะที่defineกำหนดไว้ในเวลาทำงาน สิ่งนี้ทำให้เกิดconstข้อเสียส่วนใหญ่ ข้อเสียบางประการconstคือ:
constไม่สามารถใช้เพื่อกำหนดค่าคงที่แบบมีเงื่อนไข เพื่อกำหนดค่าคงที่ส่วนกลางนั้นจะต้องมีการใช้ในขอบเขตด้านนอก:
if (...) {
const FOO = 'BAR'; // Invalid
}
// but
if (...) {
define('FOO', 'BAR'); // Valid
}
ทำไมคุณถึงต้องการทำเช่นนั้น? แอปพลิเคชันทั่วไปอย่างหนึ่งคือการตรวจสอบว่ามีการกำหนดค่าคงที่แล้ว:
if (!defined('FOO')) {
define('FOO', 'BAR');
}
constยอมรับเกลาคงที่ (จำนวนสตริงหรือคงที่อื่น ๆ เช่นtrue, false, null, __FILE__) ในขณะที่define()ใช้เวลาการแสดงออกใด ๆ เนื่องจาก PHP 5.6 นิพจน์คงที่ได้รับอนุญาตในconstเช่นกัน:
const BIT_5 = 1 << 5; // Valid since PHP 5.6 and invalid previously
define('BIT_5', 1 << 5); // Always valid
constใช้ชื่อค่าคงที่ธรรมดาในขณะที่define()ยอมรับการแสดงออกใด ๆ เป็นชื่อ สิ่งนี้อนุญาตให้ทำสิ่งนี้:
for ($i = 0; $i < 32; ++$i) {
define('BIT_' . $i, 1 << $i);
}
consts จะdefine()คำนึงถึงขนาดตัวพิมพ์เสมอในขณะที่อนุญาตให้คุณกำหนดค่าคงที่ที่ไม่คำนึงถึงขนาดตัวพิมพ์โดยการส่งผ่านtrueเป็นอาร์กิวเมนต์ที่สาม (หมายเหตุ: การกำหนดค่าคงที่ที่ไม่ต้องคำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ถูกคัดค้านเมื่อ PHP 7.3.0)
define('FOO', 'BAR', true);
echo FOO; // BAR
echo foo; // BAR
นั่นคือสิ่งที่ไม่ดี ตอนนี้เรามาดูเหตุผลว่าทำไมฉันจึงใช้ส่วนตัวเป็นการส่วนตัวconstเว้นแต่จะมีเหตุการณ์ใดเหตุการณ์หนึ่งข้างต้นเกิดขึ้น:
constเพียงแค่อ่านดีกว่า มันเป็นโครงสร้างภาษาแทนฟังก์ชั่นและยังสอดคล้องกับวิธีที่คุณกำหนดค่าคงที่ในคลาสconstเป็นโครงสร้างภาษาสามารถวิเคราะห์แบบคงที่โดยใช้เครื่องมืออัตโนมัติconstกำหนดค่าคงที่ในเนมสเปซปัจจุบันในขณะdefine()ที่ต้องผ่านชื่อเนมสเปซแบบเต็ม:
namespace A\B\C;
// To define the constant A\B\C\FOO:
const FOO = 'BAR';
define('A\B\C\FOO', 'BAR');
เนื่องจากconstค่าคงที่PHP 5.6 ยังสามารถเป็นอาร์เรย์ในขณะที่define()ยังไม่รองรับอาร์เรย์ อย่างไรก็ตามอาร์เรย์จะรองรับทั้งสองกรณีใน PHP 7
const FOO = [1, 2, 3]; // Valid in PHP 5.6
define('FOO', [1, 2, 3]); // Invalid in PHP 5.6 and valid in PHP 7.0
สุดท้ายโปรดทราบว่าconstสามารถใช้ภายในคลาสหรือส่วนต่อประสานเพื่อกำหนดค่าคงที่ของคลาสหรือค่าคงที่ส่วนต่อประสาน defineไม่สามารถใช้เพื่อจุดประสงค์นี้:
class Foo {
const BAR = 2; // Valid
}
// But
class Baz {
define('QUX', 2); // Invalid
}
สรุป
หากคุณไม่ต้องการคำจำกัดความตามเงื่อนไขหรือนิพจน์ใด ๆ ให้ใช้consts แทนdefine()s - เพื่อความสะดวกในการอ่าน!
constภาษา - ดูwiki.php.net/rfc/const_scalar_exprs
constคือการไม่มีเครื่องหมายคำพูดหมายความว่ามันถูกจัดรูปแบบเหมือนกับที่ใช้ใน IDE ของคุณ
define('a', $_GET['param']);, const b = a;การทำงานอย่างสมบูรณ์และได้รับความคุ้มค่าในขณะที่const c = $_GET['param'];ไม่ถูกต้อง คือconstรวบรวมเวลาจริงๆ? ฉันแทบจะไม่คิดอย่างนั้น ... (ทดสอบบน PHP 7.0.7)
จนถึง PHP 5.3 constไม่สามารถใช้งานได้ในขอบเขตส่วนกลาง คุณสามารถใช้สิ่งนี้จากภายในชั้นเรียนเท่านั้น ควรใช้เมื่อคุณต้องการตั้งค่าตัวเลือกคงที่หรือการตั้งค่าที่เกี่ยวข้องกับคลาสนั้น หรือบางทีคุณต้องการสร้าง enum บางชนิด
defineสามารถใช้เพื่อจุดประสงค์เดียวกัน แต่สามารถใช้ได้ในขอบเขตส่วนกลางเท่านั้น ควรใช้สำหรับการตั้งค่าทั่วไปที่มีผลกับแอปพลิเคชันทั้งหมดเท่านั้น
ตัวอย่างของconstการใช้งานที่ดีคือกำจัดตัวเลขเวทย์มนตร์ ลองดูที่ค่าคงที่ของ PDO เมื่อคุณต้องการระบุประเภทการดึงข้อมูลคุณจะต้องพิมพ์PDO::FETCH_ASSOCเช่น หาก consts ไม่ได้ใช้คุณจะจบลงด้วยการพิมพ์สิ่งที่ต้องการ35(หรือสิ่งที่FETCH_ASSOCถูกกำหนดให้เป็น) สิ่งนี้ไม่สมเหตุสมผลสำหรับผู้อ่าน
ตัวอย่างของdefineการใช้งานที่ดีอาจเป็นการระบุรูทพา ธ ของแอปพลิเคชันของคุณหรือหมายเลขเวอร์ชันของไลบรารี
constกับ namespaces
ฉันรู้ว่าคำตอบนี้ได้ตอบไปแล้ว แต่ไม่มีคำตอบใด ๆ ในปัจจุบันที่กล่าวถึงการกำหนดชื่อและวิธีการที่มีผลต่อค่าคงที่และการกำหนด
ในฐานะของ PHP 5.3, const และการกำหนดจะคล้ายกันในส่วนใหญ่ อย่างไรก็ตามยังมีความแตกต่างที่สำคัญบางประการ:
const FOO = 4 * 3;ไม่ทำงาน แต่ทำงานdefine('CONST', 4 * 3);ได้ defineต้องมีเนมสเปซที่จะกำหนดภายในเนมสเปซนั้นรหัสด้านล่างควรแสดงถึงความแตกต่าง
namespace foo
{
const BAR = 1;
define('BAZ', 2);
define(__NAMESPACE__ . '\\BAZ', 3);
}
namespace {
var_dump(get_defined_constants(true));
}
['foo\\BAR' => 1, 'BAZ' => 2, 'foo\\BAZ' => 3]เนื้อหาของผู้ใช้ย่อยอาร์เรย์จะเป็น
=== UPDATE ===
ที่จะเกิดขึ้น PHP 5.6 constจะช่วยให้มีความยืดหยุ่นมากขึ้นอีกนิดด้วย ตอนนี้คุณจะสามารถกำหนด consts ในรูปของนิพจน์โดยที่นิพจน์เหล่านั้นประกอบด้วย const อื่นหรือตัวอักษร ซึ่งหมายความว่าข้อมูลต่อไปนี้ควรมีผลตั้งแต่ 5.6:
const FOOBAR = 'foo ' . 'bar';
const FORTY_TWO = 6 * 9; // For future editors: THIS IS DELIBERATE! Read the answer comments below for more details
const ULTIMATE_ANSWER = 'The ultimate answer to life, the universe and everything is ' . FORTY_TWO;
คุณยังคงไม่สามารถกำหนด const ในรูปของตัวแปรหรือฟังก์ชันส่งคืนได้ดังนั้น
const RND = mt_rand();
const CONSTVAR = $var;
จะยังคงออก
FORTY_TWOเป็น 54 หรือไม่?
ฉันเชื่อว่าใน PHP 5.3 คุณสามารถใช้constนอกคลาสได้ดังที่แสดงในตัวอย่างที่สอง:
http://www.php.net/manual/en/language.constants.syntax.php
<?php
// Works as of PHP 5.3.0
const CONSTANT = 'Hello World';
echo CONSTANT;
?>
define ฉันใช้ค่าคงที่ทั่วโลก
const ฉันใช้ค่าคงที่ของคลาส
คุณไม่สามารถdefineเข้าสู่ขอบเขตการเรียนได้และconstสามารถทำได้ คุณไม่สามารถใช้constขอบเขตนอกชั้นเรียนได้
นอกจากนี้เมื่อconstมันกลายเป็นสมาชิกของคลาสและด้วยdefineจะถูกส่งไปยังขอบเขตทั่วโลก
คำตอบของ NikiC นั้นดีที่สุด แต่ให้ฉันเพิ่มข้อแม้ที่ไม่ชัดเจนเมื่อใช้ namespaces เพื่อที่คุณจะได้ไม่ติดกับพฤติกรรมที่ไม่คาดคิด สิ่งที่ต้องจำคือการกำหนดให้อยู่ในเนมสเปซส่วนกลางเสมอเว้นแต่คุณจะเพิ่มเนมสเปซเป็นส่วนหนึ่งของตัวระบุกำหนดอย่างชัดเจน สิ่งที่ไม่ชัดเจนเกี่ยวกับสิ่งนั้นคือตัวระบุเนมที่มีค่ามากกว่าตัวระบุทั่วโลก ดังนั้น:
<?php
namespace foo
{
// Note: when referenced in this file or namespace, the const masks the defined version
// this may not be what you want/expect
const BAR = 'cheers';
define('BAR', 'wonka');
printf("What kind of bar is a %s bar?\n", BAR);
// To get to the define in the global namespace you need to explicitely reference it
printf("What kind of bar is a %s bar?\n", \BAR);
}
namespace foo2
{
// But now in another namespace (like in the default) the same syntax calls up the
// the defined version!
printf("Willy %s\n", BAR);
printf("three %s\n", \foo\BAR);
}
?>
ผลิต:
What kind of bar is a cheers bar?
What kind of bar is a wonka bar?
willy wonka
three cheers
สิ่งที่ฉันทำให้ความคิด const ทั้งหมดสับสนโดยไม่จำเป็นเนื่องจากความคิดของ const ในหลายภาษาอื่น ๆ คือว่ามันจะเหมือนกันทุกที่ที่คุณอยู่ในรหัสของคุณและ PHP ไม่รับประกันจริง ๆ ว่า
BARและ\foo\BARเป็นเพียงการไม่ได้ค่าคงที่เดียวกัน ฉันเห็นมันจริงๆสับสน แต่ถ้าคุณยังพิจารณาสิ่งที่ต้องการตรรกะ namespacing เป็นที่สอดคล้องกันด้วยวิธีนี้และว่าไม่ว่าจะconstมิได้define()เป็นเช่น C มาโคร ( #define) แล้ว PHP สามารถมีข้ออ้างบาง
คำตอบส่วนใหญ่ผิดหรือบอกเพียงครึ่งเดียวเท่านั้น
ตัวอย่างเช่น:
const AWESOME = 'Bob'; // Valid
ตัวอย่างที่ไม่ดี:
const AWESOME = whatIsMyName(); // Invalid (Function call)
const WEAKNESS = 4+5+6; // Invalid (Arithmetic)
const FOO = BAR . OF . SOAP; // Invalid (Concatenation)
ในการสร้างค่าคงที่ตัวแปรให้ใช้ define () ดังนี้:
define('AWESOME', whatIsMyName()); // Valid
define('WEAKNESS', 4 + 5 + 6); // Valid
define('FOO', BAR . OF . SOAP); // Valid
ใช่ const ถูกกำหนดในเวลารวบรวมและเป็นรัฐนิกิกไม่สามารถกำหนดนิพจน์ได้ดังที่ define () สามารถทำได้ แต่ยังไม่สามารถประกาศ const ได้ตามเงื่อนไข (ด้วยเหตุผลเดียวกัน) กล่าวคือ คุณไม่สามารถทำสิ่งนี้:
if (/* some condition */) {
const WHIZZ = true; // CANNOT DO THIS!
}
ในขณะที่คุณสามารถกำหนด () ดังนั้นมันไม่ได้ลงไปที่การตั้งค่าส่วนตัวมีวิธีที่ถูกต้องและผิดที่จะใช้ทั้งสอง
นอกเหนือจาก ... ฉันต้องการเห็นกลุ่มคลาสบางกลุ่มที่สามารถกำหนดนิพจน์ได้ประเภท define () ที่สามารถแยกออกเป็นคลาสได้หรือไม่
เพื่อเพิ่มคำตอบของ NikiC constสามารถใช้ภายในชั้นเรียนในลักษณะดังต่อไปนี้:
class Foo {
const BAR = 1;
public function myMethod() {
return self::BAR;
}
}
define()คุณไม่สามารถทำเช่นนี้กับ
ไม่มีใครพูดอะไรเกี่ยวกับ php-doc แต่สำหรับฉันนั่นก็เป็นข้อโต้แย้งที่สำคัญมากสำหรับการตั้งค่าของconst:
/**
* My foo-bar const
* @var string
*/
const FOO = 'BAR';
ด้วยการกำหนดค่าคงที่คำหลักคุณจะได้รับสิ่งอำนวยความสะดวกของตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ แต่ด้วยคำหลัก const ที่คุณไม่ได้ทำ
define("FOO", 1, true);
echo foo; //1
echo "<br/>";
echo FOO; //1
echo "<br/>";
class A {
const FOO = 1;
}
echo A::FOO; //valid
echo "<br/>";
//but
class B {
define FOO = 1; //syntax error, unexpected 'define'
}
echo B::FOO; //invalid
constdefineเกี่ยวกับเวลาในการโหลดหน้าเว็บและการใช้หน่วยความจำ: ดูคำถามนี้และบทความนี้ ... ดูเพิ่มเติมบางอย่างเกี่ยวกับแคช opcode ที่นี่