ใน 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);
}
const
s จะ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
}
สรุป
หากคุณไม่ต้องการคำจำกัดความตามเงื่อนไขหรือนิพจน์ใด ๆ ให้ใช้const
s แทน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
const
define
เกี่ยวกับเวลาในการโหลดหน้าเว็บและการใช้หน่วยความจำ: ดูคำถามนี้และบทความนี้ ... ดูเพิ่มเติมบางอย่างเกี่ยวกับแคช opcode ที่นี่