【问题标题】:Include constant in string without concatenating在字符串中包含常量而不连接
【发布时间】:2011-01-13 07:41:57
【问题描述】:

在 PHP 中有没有一种方法可以在字符串中包含一个常量而不连接?

define('MY_CONSTANT', 42);

echo "This is my constant: MY_CONSTANT";

【问题讨论】:

  • 直觉告诉我“这是我的常数:{MY_CONSTANT}”应该可以工作。它没有。只是把它放在这里以防有人和我有同样的想法。

标签: php string constants concatenation


【解决方案1】:

没有。

使用字符串,PHP 无法将字符串数据与常量标识符区分开来。这适用于 PHP 中的任何字符串格式,包括 heredoc。

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

Manual on constants in PHP

【讨论】:

  • "函数调用不能放入字符串"是的,它可以:define('ANIMAL','turtles'); $constant='constant'; echo "I like {$constant('ANIMAL')}";
  • @Raveren 您应该正确提交答案,而不是作为评论。我相信这以最有效和最优雅的方式回答了 OOP 问题(和我的问题)。谢谢。
  • 我很高兴它有所帮助,但是自从我的评论重复我所说的之后,已经添加了多个答案,添加另一个没有意义。
  • @Raveren,虽然其他人提供间接变化,不必要地创建函数,但你的解决方案是最短且最重要的解决方案,它依赖于可变函数,被低估且非常不常用的 PHP 功能。在整个线程中,我选择了您的特定解决方案。我希望我能不止一次 +1。
  • 我只是指出这是可能的,没有评论哪种方式更好。
【解决方案2】:

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

define('FOO', 'bar');

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

这可能不是您的目标,但我认为,从技术上讲,这不是连接而是替换,并且根据这个假设,它在字符串中包含一个常量而不连接

【讨论】:

    【解决方案3】:

    如果你真的想在不连接的情况下回显常量,这里是解决方案:

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

    注意:在此示例中,echo 带有许多参数(请看逗号),因此它不是真正的串联

    Echo 表现得像一个函数,它需要更多的参数,它比串联更有效,因为它不必串联然后回显,它只是回显所有内容,而无需创建新的字符串串联对象 :))

    编辑

    此外,如果您考虑 连接 字符串、将字符串作为 参数 传递或使用 " 编写整个字符串,则 (逗号版本)总是最快的,接下来是 . (用 ' 单引号连接),最慢的字符串构建方法是使用双引号 ",因为以这种方式编写的表达式必须针对已声明的变量和函数进行评估..

    【讨论】:

      【解决方案4】:

      你可以这样做:

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

      【讨论】:

        【解决方案5】:
        define('FOO', 'bar');
        $constants = create_function('$a', 'return $a;');
        echo "Hello, my name is {$constants(FOO)}";
        

        【讨论】:

          【解决方案6】:
          define( 'FOO', 'bar');  
          $FOO = FOO;  
          $string = "I am too lazy to concatenate $FOO in my string";
          

          【讨论】:

          • 这是我最常用的一个,当我有一堆疯狂的 SQL 字符串要编写时。还...被动攻击性多? ;-)
          • 这个魔法最少,代价是看起来多余
          【解决方案7】:

          正如其他人指出的那样,您不能这样做。 PHP 有一个函数 constant() 不能直接在字符串中调用,但我们可以轻松解决这个问题。

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

          及其用法的基本示例:

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

          【讨论】:

          • 你可以只做$constant = 'constant';而不是定义另一个函数,因为这个函数已经存在,所以它的工作原理是一样的。
          【解决方案8】:

          我相信这回答了 OP 的原始问题。唯一的问题是全局索引键似乎只能作为小写字母。

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

          输出:

          DB_USER=root
          

          【讨论】:

          【解决方案9】:

          您可以使用关键字“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;};
          

          不确定将来使用是否安全。更糟糕的是 - 它仍然看起来很丑。

          【讨论】:

            【解决方案10】:

            要在字符串中使用常量,您可以使用以下方法:

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

            记住

            这种做法是不明智的,但有时会产生更易读的代码,所以这取决于你 - 可能性是存在的。

            【讨论】:

            • 这是一个绝妙的技巧!像其他答案一样,在努力和可读性方面并没有真正超越串联,但很高兴知道。当您执行$_ = create_function('$a','return $a;'); $s = "I like {$_(ANIMAL)}" 之类的操作时,它会更加性感。 Thetaiko 的版本不需要引号,下划线很可爱。
            • 我可以看到这对于构建模板引擎很有用,但实际使用起来似乎太偷偷摸摸了。
            【解决方案11】:

            以下是其他答案的一些替代方法,它们似乎主要集中在“{$}”技巧上。尽管不能保证它们的速度;这都是纯语法糖。对于这些示例,我们假设定义了以下常量集。

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

            您可以使用任何您想要的替换标记,例如 % 或 #。我在这里使用了斜线,因为它更容易输入。

            【讨论】:

              【解决方案12】:

              最简单的方法是

              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,连接字符串将不起作用。
              【解决方案13】:

              我经常需要它来打印换行符,主要是在编写脚本时。 从浏览器运行脚本时,换行符应为&lt;br&gt;,从终端执行时应为PHP_EOL

              所以,我会这样做:

              $isCLI = ( php_sapi_name() == 'cli' );
              $eol = $isCLI ? PHP_EOL : '<br>'; 
              echo "${eol} This is going to be printed in a new line";
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2013-08-18
                • 1970-01-01
                • 2019-10-06
                • 1970-01-01
                • 1970-01-01
                • 2018-05-27
                相关资源
                最近更新 更多