在字符串中包含常量而不进行串联


166

PHP中有没有一种方法可以在字符串中包含常量而不进行串联?

define('MY_CONSTANT', 42);

echo "This is my constant: MY_CONSTANT";

12
直觉告诉我“这是我的常数:{MY_CONSTANT}”应该起作用。没有。只是把这个在这里情况下,有人认为一样一
的Mikael林奎斯特

Answers:


148

没有。

使用字符串,除了常量标识符外,PHP无法分辨字符串数据。这适用于PHP中的任何字符串格式,包括heredoc。

constant() 是获取常量的另一种方法,但是如果没有连接,也不能将函数调用放入字符串中。

PHP常量手册


1
无论如何+1无疑是正确的答案。首先,我想写和你一样的书,但是读完你的书后,我想我必须介绍一些与众不同的东西;)
Felix Kling 2010年

3
呵呵!但是每个人都应该为自己的创造力+1。:)
Pekka 2010年

59
“函数调用不能放入字符串中”是的,它可以:define('ANIMAL','turtles'); $constant='constant'; echo "I like {$constant('ANIMAL')}";
raveren 2012年

1
@Raveren,而其他提供间接的变体,则不必要地创建函数,而您的函数则是最短且最关键的解决方案,它依赖于可变函数,被低估且很少使用的PHP功能。在整个主题中,我使用了您的特定解决方案。我希望我可以不止一次对其+1。
hndcrftd 2014年

4
我只是指出了可能,没有评论哪种方法更好。
raveren 2014年

111

是的(以某种方式;)):

define('FOO', 'bar');

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

这可能不是您要的目的,但我认为,从技术上讲,这不是串联,而是替换,从这个假设出发,它在字符串中包含一个常量而没有串联


5
@Pekka:我知道:-D(这一次...;))
Felix Kling 2010年

1
:) @ juraj.blahunka的方法更加狡猾。它通过字母回答问题,但不回答其精神。:)
Pekka

2
@blahunka:座右铭。我们可能每天都
Alfabravo 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。

不允许使用回调数组!

如果到现在为止,您印象中函数名可以是任何可调用的,则不是这种情况,因为在传递给is_callable字符串时返回true的数组在字符串中使用时将导致致命错误:

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 2015年

2
我可以看到这对于构建模板引擎很有用,但实际上很难使用。
Mnebuerquo '16

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

4
当我有一堆疯狂的SQL字符串组成时,这是我使用最多的。还...被动进取吗?;-)
Beejor 2015年

2
这只
魔咒

很好的解决方案。简单快捷。
罗杰·希尔

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表现为一个函数,它需要更多的参数,比并置更为有效,因为它不必先进行并置然后进行回显,它只回显所有内容,而无需创建新的String并置对象:))

编辑

另外,如果您考虑串联字符串,将字符串作为参数传递或使用“编写整个字符串,那么(逗号版本)总是最快的,下一步是(与'单引号串联),而最慢的字符串构建方法是使用双引号,因为以这种方式编写的表达式必须根据声明的变量和函数求值。


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;

我认为这是一个很好的解决方案。在某些情况下,如果在内部使用直接CONSTANT,则连接字符串将不起作用。
kta

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的原始问题。唯一的是,globals索引键似乎只能小写。

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

这个答案是错误的。可能产生该输出的唯一方法是,如果您在脚本中的某个位置也有$db_user = 'root';
Jeff Puckett
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.