連結せずに文字列に定数を含める


166

PHPに、連結せずに文字列に定数を含める方法はありますか?

define('MY_CONSTANT', 42);

echo "This is my constant: MY_CONSTANT";

12
「これは私の定数です:{MY_CONSTANT}」が機能するはずです。そうではありません。念の誰かにここにこれを置くことはIと同じと考えて
ミカエルLindqvist

回答:


148

番号。

文字列では、PHPが文字列データと定数識別子を区別する方法はありません。これは、ヒアドキュメントを含め、PHPの文字列フォーマットのすべてに当てはまります。

constant() 定数を取得する別の方法ですが、関数呼び出しを連結せずに文字列にすることもできません。

PHPの定数に関するマニュアル


1
それは間違いなく正しい答えなので、とにかく+1します。最初に私はあなたと同じものを書きたかったが、あなたのものを読んだ後、私は何か違うものを提示しなければならないと思った;)
Felix Kling

3
へへー!しかし、創造性のために誰にとっても当然の+1。:)
Pekka

59
「関数呼び出しを文字列に入れることはできません」はい、それは可能です:define('ANIMAL','turtles'); $constant='constant'; echo "I like {$constant('ANIMAL')}";
raveren

1
@Raverenは、間接的なバリエーションを提供し、不必要に関数を作成するものもありますが、PHPの過小評価され、あまり使用されない機能である可変関数に依存するソリューションが最も短く、適切です。このスレッド全体のうち、私はあなたの特定の解決策を採用しました。2回以上+1できたらいいのに。
hndcrftd 2014年

4
私はそれが可能であると指摘しただけで、どちらの方法が優れているかについてはコメントしていません。
raveren

111

はい、そうです(ある意味で;)):

define('FOO', 'bar');

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

これはおそらくあなたが目指していたものではありませんが、技術的にはこれは連結ではなく置換であり、この仮定から、連結なしの文字列に定数が含まれていると思います。


5
@ペッカ:私は知っている:-D(今回だけ...;))
Felix Kling

1
:) @ juraj.blahunkaのアプローチはさらに卑劣です。それは手紙で質問に答えますが、その精神ではありません。:)
Pekka

2
@blahunka:いいモットー。私たちはおそらくそれを毎日使用しています
アルファブラボ2010

57

文字列内で定数を使用するには、次の方法を使用できます。

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

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


これはどのように作動しますか?

任意の文字列関数名と任意のパラメーターを使用できます

変数に任意の関数名を配置し、二重引用符で囲まれた文字列内にパラメーターを付けて呼び出すことができます。複数のパラメータでも機能します。

$fn = 'substr';

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

生産する

私は亀が好きです

匿名関数も

PHP 5.3以降を実行している場合は、無名関数を使用することもできます。

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

期待どおりに適切にエスケープされたhtmlを生成します。

コールバック配列は許可されていません!

これまでに、関数名が呼び出し可能である可能性があるという印象を受けている場合は、そうではありません。渡されたときにtrueを返す配列はis_callable、文字列内で使用すると致命的なエラーを引き起こします。

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

心に留めて

この方法は不適切ですが、コードが読みやすくなることもありますので、それはあなた次第です-可能性はあります。


1
これは素晴らしいトリックです!他の答えのように、努力と読みやすさの点で連結よりも大きな勝利ではありませんが、知っておくと便利です。のようなことをすると、さらにセクシーになります$_ = create_function('$a','return $a;'); $s = "I like {$_(ANIMAL)}"。Thetaikoのバージョンでは、引用符が不要になり、アンダースコアがかわいいです。
Beejor

2
これはテンプレートエンジンを構築するのに便利ですが、実際に使用するには卑劣すぎるようです。
Mnebuerquo

21
define( 'FOO', 'bar');  
$FOO = FOO;  
$string = "I am too lazy to concatenate $FOO in my string";

4
これは、作成するクレイジーなSQL文字列がたくさんあるときに、私が最もよく使用するものです。また...パッシブ・アグレッシブなものは?;-)
Beejor

2
これは、冗長に見えるという犠牲を払って、魔法の量が最も少ない
BrDaHa 2017年

素晴らしいソリューション。シンプルで高速。
ロジャーヒル

14
define('FOO', 'bar');
$constants = create_function('$a', 'return $a;');
echo "Hello, my name is {$constants(FOO)}";

13

連結せずに定数を本当にエコーしたい場合は、ここが解決策です:

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

:この例では、echoはいくつかのパラメーター(コンマを見てください)取るため、実際の連結ではありません。

Echoは関数として動作し、より多くのパラメーターを取り、連結よりも効率的です。連結してからエコーする必要がないため、新しい文字列連結オブジェクトを作成する必要なくすべてをエコーするだけです:))

編集

あなたが考える場合にも連結する、などpassings文字列の文字列をパラメータをか書くと全体の文字列を「(カンマ版)常に最速で、次行く(と連結"単一引用符)と最も遅い文字列の構築方法は、二重引用符を使用しています、この方法で記述された式は、宣言された変数および関数に対して評価される必要があるためです。


11

あなたがすることができます:

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']}";

6

最も簡単な方法は

define('MY_CONSTANT', 42);

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

別の使用方法 (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;

これは良い解決策だと思います。内部で直接定数を使用すると、接続文字列が機能しない場合があります。
kta 2017年

5

他の人が指摘したように、あなたはそれを行うことができません。PHPにはconstant()文字列から直接呼び出すことのできない関数がありますが、これは簡単に回避できます。

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

そしてその使用法の基本的な例:

define('FOO', 'Hello World!');
echo "The string says {$constant('FOO')}"; 

$constant = 'constant';別の関数を定義する代わりに行うことができ、その関数は既に存在するため、同じように機能します。
redreinard

2

ここでは、他の回答に対するいくつかの代替案を示します。これらは主に「{$}」トリックに焦点を当てているようです。速度は保証されていませんが、これはすべて純粋な構文糖です。これらの例では、以下の一連の定数が定義されていると想定します。

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

extract()を使用する
と、結果が変数と同じになるため、この方法が適しています。まず、再利用可能な関数を作成します。

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

次に、任意のスコープから呼び出します。

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

ここでは、定数を小文字にして指で簡単にしていますが、array_change_key_case()を削除して、そのままにしておくことができます。既に競合するローカル変数名がある場合、定数はそれらをオーバーライドしません。

文字列置換の使用
これはsprintf()に似ていますが、単一の置換トークンを使用し、無制限の数の引数を受け入れます。これを行うにはもっと良い方法があると私は確信していますが、私の不器用さを許し、その背後にあるアイデアに集中しようとします。

前と同様に、再利用可能な関数を作成します。

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

次に、任意のスコープから呼び出します。

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

%や#など、任意の置換トークンを使用できます。ここではスラッシュを使用しました。タイプするのが少し簡単だからです。


0

名前空間のポイ捨てを防ぐために、関数の名前としてキーワード 'const'を使用できるのは楽しいことです。

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

$ GLOBALSを使用して、 'const'関数をコード全体に伝達することもできます。

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

不明な点は、将来使用するのに安全です。そしてさらに悪いことに、それはまだ醜く見えます。


-2

これはOPの元の質問に対する答えだと思います。唯一のものは、グローバルインデックスキーが小文字としてのみ機能するように見えることです。

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

出力:

DB_USER=root

1
これは機能しないようです(大文字を続けて使用しても)$ GLOBALSは an associative array containing references to all variablesです。
har-wradim 2013年

この答えは間違っています。スクリプト内のどこかにあなたも持っている場合、これはおそらくその出力を生成することができることを唯一の方法です$db_user = 'root';
ジェフPuckett
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.