Sertakan konstan dalam string tanpa menyatukan

166

Apakah ada cara di PHP untuk memasukkan konstanta dalam string tanpa menyatukan?

define('MY_CONSTANT', 42);

echo "This is my constant: MY_CONSTANT";
Brian
sumber
12
Intuition memberi tahu saya bahwa "Ini adalah konstanta saya: {MY_CONSTANT}" harus berfungsi. Tidak. Hanya menempatkan ini di sini kalau-kalau ada yang berpikir sama dengan saya.
Mikael Lindqvist

Jawaban:

148

Tidak.

Dengan Strings, tidak ada cara bagi PHP untuk membedakan data string dari pengidentifikasi konstan. Ini berlaku untuk semua format string dalam PHP, termasuk heredoc.

constant() adalah cara alternatif untuk mendapatkan konstanta, tetapi pemanggilan fungsi tidak dapat dimasukkan ke dalam string tanpa penggabungan.

Manual tentang konstanta dalam PHP

Pekka
sumber
1
+1 bagaimanapun juga karena itu adalah jawaban yang tepat. Pertama saya ingin menulis yang sama seperti Anda, tetapi setelah membaca milik Anda, saya pikir saya harus menyajikan sesuatu yang berbeda;)
Felix Kling
3
Hehe! Namun +1 layak untuk semua orang karena kreativitas. :)
Pekka
59
"function call tidak dapat dimasukkan ke dalam string" ya itu bisa:define('ANIMAL','turtles'); $constant='constant'; echo "I like {$constant('ANIMAL')}";
raveren
1
@Raveren, sementara yang lain menawarkan variasi tidak langsung, membuat fungsi yang tidak perlu, milik Anda adalah solusi terpendek dan langsung ke titik yang bergantung pada fungsi variabel, fitur yang diremehkan dan sangat jarang digunakan dari PHP. Dari seluruh utas ini saya pergi dengan solusi khusus ANDA. Saya berharap saya bisa memberi +1 lebih dari satu kali.
hndcrftd
4
Saya hanya menunjukkan itu mungkin, tidak mengomentari mana yang lebih baik.
raveren
111

Ya itu (dalam beberapa cara;)):

define('FOO', 'bar');

$test_string = sprintf('This is a %s test string', FOO);

Ini mungkin bukan apa yang Anda tuju, tapi saya pikir, secara teknis ini bukan gabungan tetapi substitusi dan dari asumsi ini, itu termasuk konstanta dalam string tanpa menyatukan .

Felix Kling
sumber
5
@Pekka: Saya tahu :-D (hanya kali ini ...;))
Felix Kling
1
:) @ Pendekatan juraj.blahunka bahkan lebih licik. Ia menjawab pertanyaan dengan surat, tetapi tidak semangatnya. :)
Pekka
2
@blahunka: moto yang bagus. Kami mungkin menggunakannya setiap hari
Alfabravo
57

Untuk menggunakan konstanta di dalam string Anda dapat menggunakan metode berikut:

define( 'ANIMAL', 'turtles' ); 
$constant = 'constant';

echo "I like {$constant('ANIMAL')}";


Bagaimana cara kerjanya?

Anda dapat menggunakan nama fungsi string apa saja dan parameter arbitrer

Satu dapat menempatkan nama fungsi apa pun dalam variabel dan menyebutnya dengan parameter di dalam string yang dikutip ganda. Bekerja dengan beberapa parameter juga.

$fn = 'substr';

echo "I like {$fn('turtles!', 0, -1)}";

Menghasilkan

saya suka kura-kura

Fungsi anonim juga

Anda juga dapat menggunakan fungsi anonim asalkan Anda menjalankan PHP 5.3+.

$escape   = function ( $string ) {
    return htmlspecialchars( (string) $string, ENT_QUOTES, 'utf-8' );
};
$userText = "<script>alert('xss')</script>";
echo( "You entered {$escape( $userText )}" );

Menghasilkan html lolos dengan benar seperti yang diharapkan.

Array panggilan balik tidak diizinkan!

Jika saat ini Anda berada di bawah kesan bahwa nama fungsi dapat dipanggil apa saja, itu tidak terjadi, karena array yang mengembalikan true ketika diteruskan is_callableakan menyebabkan kesalahan fatal ketika digunakan di dalam string:

class Arr
{

    public static function get( $array, $key, $default = null )
    {
        return is_array( $array ) && array_key_exists( $key, $array ) 
            ? $array[$key] 
            : $default;
    }
}

$fn = array( 'Arr', 'get' );
var_dump( is_callable( $fn ) ); // outputs TRUE

// following line throws Fatal error "Function name must be a string"
echo( "asd {$fn( array( 1 ), 0 )}" ); 

Mengingat

Praktek ini keliru, tetapi terkadang menghasilkan kode yang lebih mudah dibaca, jadi terserah Anda - kemungkinan ada di sana.

gua
sumber
1
Ini trik yang bagus! Seperti jawaban yang lain, tidak benar-benar kemenangan besar dalam hal upaya dan keterbacaan, tetapi menyenangkan untuk diketahui. Bahkan lebih seksi ketika Anda melakukan sesuatu seperti $_ = create_function('$a','return $a;'); $s = "I like {$_(ANIMAL)}". Versi Thetaiko menghilangkan kebutuhan akan tanda kutip, dan garis bawah itu lucu.
Beejor
2
Saya bisa melihat ini berguna untuk membangun mesin templat, tetapi tampaknya terlalu licik untuk digunakan.
Mnebuerquo
21
define( 'FOO', 'bar');  
$FOO = FOO;  
$string = "I am too lazy to concatenate $FOO in my string";
Macswork
sumber
4
Ini adalah yang paling saya gunakan, ketika saya memiliki banyak string SQL gila untuk menulis. Juga ... pasif-agresif banyak? ;-)
Beejor
2
Yang ini memiliki jumlah sihir paling sedikit, dengan mengorbankan penampilan yang berlebihan
BrDaHa
Solusi bagus Sederhana dan cepat.
Roger Hill
14
define('FOO', 'bar');
$constants = create_function('$a', 'return $a;');
echo "Hello, my name is {$constants(FOO)}";
thaiko
sumber
13

Jika Anda benar - benar ingin menggemakan konstanta tanpa penggabungan berikut ini solusinya:

define('MY_CONST', 300);
echo 'here: ', MY_CONST, ' is a number';

Catatan : dalam contoh ini gema mengambil sejumlah parameter ( lihat koma ), jadi itu bukan penggabungan nyata

Echo berperilaku sebagai fungsi, dibutuhkan lebih banyak parameter, lebih efisien daripada penggabungan, karena tidak harus menyatukan dan kemudian menggema, itu hanya menggemakan semuanya tanpa perlu membuat objek gabungan String baru :))

EDIT

Juga jika Anda mempertimbangkan string rangkaian , string string sebagai parameter atau menulis string keseluruhan dengan " , The , (versi koma) selalu tercepat, selanjutnya . (Gabungan dengan ' tanda kutip tunggal) dan metode pembuatan string paling lambat menggunakan tanda kutip ganda " , karena ekspresi yang ditulis dengan cara ini harus dievaluasi terhadap variabel dan fungsi yang dideklarasikan.

Juraj Blahunka
sumber
11

Anda bisa melakukannya:

define( 'FOO', 'bar' );

$constants = get_defined_constants(true); // the true argument categorizes the constants
$constants = $constants[ 'user' ]; // this gets only user-defined constants

echo "Hello, my name is {$constants['FOO']}";
Simon
sumber
6

Cara termudah adalah

define('MY_CONSTANT', 42);

$my_constant = MY_CONSTANT;
echo "This is my constant: $my_constant";

Cara lain menggunakan (s)printf

define('MY_CONSTANT', 42);

// Note that %d is for numeric values. Use %s when constant is a string    
printf('This is my constant: %d', MY_CONSTANT);

// Or if you want to use the string.

$my_string = sprintf('This is my constant: %d', MY_CONSTANT);
echo $my_string;
Jekis
sumber
Saya menganggap ini sebagai solusi yang baik. Dalam beberapa kasus, hubungkan string tidak akan berfungsi jika menggunakan KONSTAN langsung di dalam.
kta
5

Seperti yang orang lain tunjukkan, Anda tidak bisa melakukan itu. PHP memiliki fungsi constant()yang tidak dapat dipanggil secara langsung dalam sebuah string tetapi kita dapat dengan mudah mengatasi ini.

$constant = function($cons){
   return constant($cons);
};

dan contoh dasar tentang penggunaannya:

define('FOO', 'Hello World!');
echo "The string says {$constant('FOO')}"; 
Yamiko
sumber
Anda bisa melakukan $constant = 'constant';alih - alih mendefinisikan fungsi lain, dan itu akan bekerja secara identik karena fungsi itu sudah ada.
redreinard
2

Berikut adalah beberapa alternatif untuk jawaban lain, yang sepertinya lebih difokuskan pada trik "{$}". Meskipun tidak ada jaminan atas kecepatan mereka; ini semua adalah gula sintaksis murni. Untuk contoh-contoh ini, kita asumsikan seperangkat konstanta di bawah ini didefinisikan.

define( 'BREAD', 'bread' ); define( 'EGGS', 'eggs' ); define( 'MILK', 'milk' );

Menggunakan ekstrak ()
Yang ini bagus karena hasilnya identik dengan variabel. Pertama, Anda membuat fungsi yang dapat digunakan kembali:

function constants(){ return array_change_key_case( get_defined_constants( true )[ 'user' ] ); }

Kemudian panggil dari ruang lingkup apa pun:

extract( constants() );
$s = "I need to buy $bread, $eggs, and $milk from the store.";

Di sini, ini menurunkan konstanta agar lebih mudah di jari Anda, tetapi Anda dapat menghapus array_change_key_case () agar tetap seperti semula. Jika Anda sudah memiliki nama variabel lokal yang saling bertentangan, konstanta tidak akan menimpanya.

Menggunakan penggantian string
Yang ini mirip dengan sprintf (), tetapi menggunakan token pengganti tunggal dan menerima jumlah argumen yang tidak terbatas. Saya yakin ada cara yang lebih baik untuk melakukan ini, tetapi maafkan kekonyolan saya dan cobalah untuk fokus pada ide di baliknya.

Seperti sebelumnya, Anda membuat fungsi yang dapat digunakan kembali:

function fill(){
    $arr = func_get_args(); $s = $arr[ 0 ]; array_shift( $arr );
    while( strpos( $s, '/' ) !== false ){
        $s = implode( current( $arr ), explode( '/', $s, 2 ) ); next( $arr );
    } return $s;
}

Kemudian panggil dari ruang lingkup apa pun:

$s = fill( 'I need to buy /, /, and / from the store.', BREAD, EGGS, MILK );

Anda dapat menggunakan token pengganti apa pun yang Anda inginkan, seperti% atau #. Saya menggunakan slash di sini karena sedikit lebih mudah untuk mengetik.

Beejor
sumber
0

Sangat menyenangkan bahwa Anda dapat menggunakan kata kunci 'const' sebagai nama untuk fungsi Anda untuk mencegah pengotoran namespace:

define("FOO","foo");
${'const'} = function($a){return $a;};
echo "{$const(FOO)}"; // Prints "foo"
echo const(FOO); // Parse error: syntax error, unexpected T_CONST

Anda juga dapat menggunakan $ GLOBALS untuk menyebarkan fungsi 'const' di seluruh kode:

$GLOBALS['const'] = function($a){return $a;};

Tidak yakin apakah aman untuk digunakan di masa mendatang. Dan apa yang lebih buruk - masih terlihat jelek.

pengguna619271
sumber
-2

Saya percaya ini menjawab pertanyaan awal OP. Satu-satunya hal adalah kunci indeks global tampaknya hanya berfungsi sebagai huruf kecil.

define('DB_USER','root');
echo "DB_USER=$GLOBALS[db_user]";

Keluaran:

DB_USER=root
Kentang Lemak
sumber
1
Ini sepertinya tidak berhasil (bahkan jika Anda menggunakan huruf besar secara berurutan) $ GLOBAL adalah an associative array containing references to all variables.
har-wradim
jawaban ini salah. satu-satunya cara agar ini dapat menghasilkan output adalah jika di suatu tempat dalam skrip Anda, Anda juga memiliki$db_user = 'root';
Jeff Puckett