Nustatykite () vs const

Gana paprastas klausimas: PHP, kai naudojate

 define('FOO', 1); 

ir kai naudojate

 const FOO = 1; 

Kokie yra pagrindiniai šių dviejų skirtumai?

516
15 марта '10 в 17:23 2010-03-15 17:23 nustatė danjarvis kovo 15 d. 10 val. 17:23 2010-03-15 17:23
@ 9 atsakymai

PHP 5.3 yra du būdai apibrėžti konstantas : arba naudojant raktinį žodį, arba naudojant define() :

 const FOO = 'BAR'; define('FOO', 'BAR'); 

Pagrindinis skirtumas tarp dviejų metodų yra tas, kad const apibrėžia konstantus kompiliavimo metu, o apibrėžimas juos apibrėžia vykdymo metu. Tai veda prie daugumos const . Kai kurie „ const “ trūkumai yra tokie:

  • const negali būti naudojamas sąlyginai apibrėžti sąlyginai. Norint nustatyti pasaulinę konstantą, ji turi būti naudojama atokiausiame domene:

     if (...) { const FOO = 'BAR'; // invalid } // but if (...) { define('FOO', 'BAR'); // valid } 

    Kodėl tai darote? Vienas bendras prašymas yra patikrinti, ar yra apibrėžta konstanta:

     if (!defined('FOO')) { define('FOO', 'BAR'); } 
  • const priima statinį skalarą (skaičių, eilutę arba kitą pastovią, pvz., true , false , null , __FILE__ ), o define() priima bet kurią išraišką. Kadangi PHP 5.6 pastovios išraiškos taip pat yra leidžiamos:

     const BIT_5 = 1 << 5; // valid since PHP 5.6, invalid previously define('BIT_5', 1 << 5); // always valid 
  • const priima paprastos konstanta pavadinimą, o define() bet kokią išraišką kaip pavadinimą. Tai leidžia daryti tokius dalykus:

     for ($i = 0; $i < 32; ++$i) { define('BIT_' . $i, 1 << $i); } 
  • const visada const didžiosios ir mažosios raidės, tuo tarpu define() leidžia nustatyti atvejų nejautrias konstantas, kurios atitinka true kaip trečiąjį argumentą:

     define('FOO', 'BAR', true); echo FOO; // BAR echo foo; // BAR 

Taigi tai buvo bloga dalykų pusė. Dabar apsvarstykite priežastį, kodėl aš visada naudoju const , jei neįvyksta viena iš šių situacijų:

  • const tiesiog skaityti geriau. Tai yra kalbos konstrukcija, o ne funkcija, ir ji taip pat sutinka su tuo, kaip apibrėžiate konstantas klasėse.
  • const apibrėžia konstantą dabartinėje vardų erdvėje, ir define() turi būti perduodamas visas vardų vardo pavadinimas:

     namespace A\B\C; // To define the constant A\B\C\FOO: const FOO = 'BAR'; define('A\B\C\FOO', 'BAR'); 
  • Kadangi PHP 5.6 const taip pat gali būti matricos, define() dar nepalaiko masyvų. Tačiau matricos bus palaikomos abiem atvejais PHP 7.

     const FOO = [1, 2, 3]; // valid in PHP 5.6 define('FOO', [1, 2, 3]); // invalid in PHP 5.6, valid in PHP 7.0 
  • Kadangi const yra kalbos konstrukcijos ir jie yra apibrėžti kompiliavimo metu, jie yra šiek tiek greičiau nei define() s.

    Yra gerai žinoma, kad PHP define() lėtas, kai naudojamas didelis skaičius konstantų. Žmonės netgi sugalvojo tokius dalykus kaip apc_load_constants() ir hidef kad galėtumėte tai apeiti.

    const , kad konstantų apibrėžimas būtų maždaug dvigubai didesnis (plėtros mašinose su XDebug įtraukta dar daugiau). Kita vertus, paieškos laikas nesikeičia (nes abu pastovūs tipai naudoja tą pačią paieškos lentelę): Demo .

Galiausiai, atkreipkite dėmesį, kad const taip pat gali būti naudojamas klasėje arba sąsajoje, kad būtų galima nustatyti klasės konstantą arba sąsajos konstantą. define negalima naudoti šiuo tikslu:

 class Foo { const BAR = 2; // valid } // but class Baz { define('QUX', 2); // invalid } 

Santrauka

Jei nereikia jokių sąlyginių ar išraiškingų apibrėžimų, naudokite „ const o ne define() - tik skaitymui!

834
07 июля '10 в 12:59 2010-07-07 12:59 atsakymą pateikė „ NikiC “ liepos 07 d. 10 val. 12:59 2010-07-07 12:59

Nors PHP 5.3, const negali būti naudojami visame pasaulyje. Jį galite naudoti tik iš klasės. Tai turėtų būti naudojama, jei norite nustatyti bet kokį pastovų parametrą arba parametrą, susijusį su šia klasė. Arba galbūt norėsite sukurti tam tikrus džemperius.

define gali būti naudojamas tuo pačiu tikslu, tačiau jį galima naudoti tik pasaulinėje srityje. Jis turėtų būti naudojamas tik visuotiniams nustatymams, kurie turi įtakos visai programai.

Gero const naudojimo pavyzdys - atsikratyti magiškų numerių. Pažvelkite į SKVN konstantas . Jei reikia nurodyti pavyzdžio tipą, pvz., PDO::FETCH_ASSOC . Jei nesinaudojate minėjimais, galų gale įvesite kažką panašaus į 35 (arba kitą FETCH_ASSOC apibrėžta kaip). Skaitytojui tai nėra prasminga.

Gero naudojimosi define pavyzdys gali būti nurodant jūsų programos šaknies kelią arba bibliotekos versijos numerį.

185
15 марта '10 в 17:26 2010-03-15 17:26 atsakymas, pateiktas „ ryeguy“ kovo 15 d., 17:26, 2010-03-15 17:26

Žinau, kad tai jau buvo atsakyta, tačiau nė vienas iš dabartinių atsakymų nenurodo pavadinimų ir kaip jis veikia konstantas ir apibrėžia jas.

Kaip ir PHP 5.3, daugeliu atvejų konstantos ir apibrėžimai yra panašūs. Tačiau yra keletas svarbių skirtumų:

  • Konstansai negali būti nustatyti iš išraiškos. const FOO = 4 * 3; neveikia, bet define('CONST', 4 * 3); tai daro.
  • Nustatytam pavadinime turi būti vardų sritis, kuri turi būti apibrėžta šioje vardų erdvėje.

Šie kodai turėtų parodyti skirtumus.

 namespace foo { const BAR = 1; define('BAZ', 2); define(__NAMESPACE__ . '\\BAZ', 3); } namespace { var_dump(get_defined_constants(true)); } 

Vartotojo submatricos turinys bus ['foo\\BAR' => 1, 'BAZ' => 2, 'foo\\BAZ' => 3] .

=== UPDATE ===

Artėjantis PHP 5.6 leis šiek tiek daugiau lankstumo su const . Dabar galite apibrėžti išraiškas išraiškos požiūriu, jei šios išraiškos susideda iš kitų konstantų ar literatūrų. Tai reiškia, kad turėtų būti tiesa: 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; 

Jūs vis dar negalėsite apibrėžti konstantų kintamųjų atžvilgiu arba funkcija grąžina

 const RND = mt_rand(); const CONSTVAR = $var; 

bus vis dar trūksta.

33
26 сент. atsakymą pateikė GordonM 26 sep . 2011-09-26 15:20 '11 prie 15:20 2011-09-26 15:20

Manau, kad naudojant PHP 5.3, galite naudoti const už klasės ribų, kaip parodyta antrajame pavyzdyje:

http://www.php.net/manual/en/>

 <?php // Works as of PHP 5.3.0 const CONSTANT = 'Hello World'; echo CONSTANT; ?> 
30 июня '10 в 4:16 2010-06-30 04:16 atsakymas suteikiamas mojui birželio 30 d. 10 val. 4:16 2010-06-30 04:16

define aš naudoju pasaulinėms konstantoms.

const Aš naudoju klasių konstantoms.

Klasės lauke negalite define , bet naudodami const . Žinoma, negalite naudoti išorinės klasės const regiono.

Be to, su const jis iš tikrųjų tampa klasės nariu, o define bus perkeltas į pasaulinę sritį.

13
15 марта '10 в 17:24 2010-03-15 17:24 atsakymą pateikė Jacobas Relkinas kovo 15 d., 17:24, 2010-03-15 17:24

„NikiC“ atsakymas yra geriausias, tačiau leiskite man pridėti nepagrįstą rezervaciją, kai naudojatės vardų erdvėmis, kad netaptumėte netikėtu elgesiu. Atminkite, kad apibrėžtys visada yra pasaulinėje vardų erdvėje, nebent jūs aiškiai įtraukėte vardų erdvę kaip apibrėžties identifikatoriaus dalį. Neaišku, kad identifikatorius su pavadinimais perima pasaulinį identifikatorių. Taigi:

 <?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); } ?> 

suteikia:

 What kind of bar is a cheers bar? What kind of bar is a wonka bar? willy wonka three cheers 

Kuris man daro visą sąvoką const nenaudingas ir painus, nes idėja const dešimtys kitų kalbų yra tai, kad jis visada tas pats visur esate savo kodą, ir PHP tikrai ne tai garantuoja.

12
17 мая '12 в 23:21 2012-05-17 23:21 atsakymas pateikiamas slartibartfast gegužės 17, 12, 23:21 2012-05-17 23:21

Dauguma šių atsakymų yra neteisingi arba pasakoja tik pusę istorijos.

  • Galite sujungti savo konstantas naudodami vardų vietas.
  • Jūs galite naudoti raktinį žodį „const“, išskyrus klasių apibrėžimus. Tačiau, kaip ir klasėse, reikšmės, priskirtos raktiniam žodžiui "const", turi būti pastovios.

Pavyzdžiui:

 const AWESOME = 'Bob'; // Valid 

Blogas pavyzdys:

 const AWESOME = whatIsMyName(); // Invalid (Function call) const WEAKNESS = 4+5+6; // Invalid (Arithmetic) const FOO = BAR . OF . SOAP; // Invalid (Concatenation) 

Norėdami sukurti kintamas konstantas, naudokite apibrėžti () taip:

 define('AWESOME', whatIsMyName()); // Valid define('WEAKNESS', 4 + 5 + 6); // Valid define('FOO', BAR . OF . SOAP); // Valid 
12
07 февр. atsakymas pateikiamas AwesomeBobX64 07 vasaris 2013-02-07 12:49 '13, 12:49, 2013-02-07 12:49

Taip, konstantos nustatomos kompiliavimo metu, ir kadangi jokiai būsenai negalima priskirti tokios sąvokos kaip apibrėžimas (). Tačiau const negali būti sąlyginai paskelbta (dėl tos pačios priežasties). tai yra. Negalite to padaryti:

 if () { const WHIZZ = true; // CANNOT DO THIS! } 

Nors galite su apibrėžti (). Taigi jis tikrai neatitinka asmeninių pageidavimų, yra teisingas ir neteisingas būdas naudoti abu.

Kaip nuošalyje ... norėčiau pamatyti tam tikrą const, kuris gali būti priskirtas išraiška, tam tikra apibrėžtis (), kuri gali būti skiriama klasėms?

5
08 июля '10 в 1:40 2010-07-08 01:40 atsakymas buvo pateiktas J.White'ui liepos 8 d. 10 d. 1:40 2010-07-08 01:40

Pridėti atsakymą į „NikiC“. const gali būti naudojamas tokiomis klasėmis:

 class Foo { const BAR = 1; public function myMethod() { return self::BAR; } } 

Negalite to padaryti su define() .

2
05 апр. Atsakymą pateikė Marcus Lind 05 Bal. 2017-04-05 10:57 '17 at 10:57 2017-04-05 10:57

Kiti klausimai apie žymes arba užduoti klausimą