198

Is there a way in PHP to include a constant in a string without concatenating?

define('MY_CONSTANT', 42);

echo "This is my constant: MY_CONSTANT";
silkfire
  • 24,585
  • 15
  • 82
  • 105
Brian
  • 26,662
  • 52
  • 135
  • 170
  • 18
    Intuition tells me that "This is my constant: {MY_CONSTANT}" should work. It doesn't. Just putting this here in case someone thinks the same as I. – Mikael Lindqvist Apr 12 '17 at 14:49

15 Answers15

164

No.

With Strings, there is no way for PHP to tell string data apart from constant identifiers. This goes for any of the string formats in PHP, including heredoc.

constant() is an alternative way to get hold of a constant, but a function call can't be put into a string without concatenation either.

Manual on constants in PHP

Matt G
  • 1,332
  • 2
  • 13
  • 25
Pekka
  • 442,112
  • 142
  • 972
  • 1,088
  • 74
    "function call can't be put into a string" yes it can: `define('ANIMAL','turtles'); $constant='constant'; echo "I like {$constant('ANIMAL')}";` – raveren Apr 27 '12 at 14:49
  • 3
    @Raveren you should have submitted your answer properly, not as a comment. I believe this answers OOP question (and mine) in the most efficient and elegant way. Thank you. – hndcrftd Mar 13 '14 at 15:11
  • 1
    I'm glad it helped, but there's been multiple answers added since my comment repeating what I said, there's no point in adding another one. – raveren Mar 13 '14 at 15:28
  • 2
    @Raveren, while others offer indirect variations, unnecessarily creating functions, yours is the shortest and to the point solution that relies on variable functions, underrated and very infrequently used feature of PHP. Out of this whole thread I went with YOUR particular solution. I wish I could +1 it more than once. – hndcrftd Mar 13 '14 at 23:30
  • 1
    I provided an answer as requested, adding more info about why it works to make the answer more relevant to newcomers. http://stackoverflow.com/a/22407812/179104 – raveren Mar 14 '14 at 14:28
  • @Raveren if you're going to do ```$constant='constant';``` just to do this: ```echo "I like {$constant('ANIMAL')}";``` .. isn't it better to just do: ```$animal = ANIMAL; echo "I like $animal";``` instead? – designcise Jul 13 '14 at 09:15
  • 4
    I just pointed out it's possible, not commented on which way is better. – raveren Jul 14 '14 at 10:12
127

Yes it is (in some way ;) ):

define('FOO', 'bar');

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

This is probably not what you were aiming for, but I think, technically this is not concatenation but a substitution and from this assumption, it includes a constant in a string without concatenating.

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
82

To use constants inside strings you can[1] use the following method:

define( 'ANIMAL', 'turtles' ); 
$constant = constant(...);
echo "I like {$constant('ANIMAL')}!";

[1] "can" does not mean you "should", practically I advise you actually do this:

sprintf('I like %s!', ANIMAL);



How does {$constant('ANIMAL')} work?

The {} brackets inside string allow us to invoke any callable as long as it starts with $!

I.e. "I like {constant('ANIMAL')}"; without $ will not trigger variable substitution so we have to put the callable in a variable.

By the way: the constant(...) syntax is called first class callable syntax.

You can also use string function names - and arbitrary parameters

One can place any function name in a variable and call it with parameters inside a double-quoted string. Works with multiple parameters too.

$fn = 'substr';

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

Produces

I like turtles

Also anonymous functions, arrays etc

$escape = fn( $string ) => htmlspecialchars( (string) $string, ENT_QUOTES, 'utf-8' );
$userText = "<script>alert('xss')</script>";

echo "You entered {$escape( $userText )}";

Produces:

You entered &lt;script&gt;alert(&#039;xss&#039;)&lt;/script&gt;

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

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

Produces:

I like turtles!

Try it yourself on 3v4l.org and notice - most the callable types (except string) would not work pre-php5.3 (at the original time this post was written) - now updated to php7+++ era

Keep in mind

This practice is ill-advised, but the possibility is there.

raveren
  • 17,799
  • 12
  • 70
  • 83
  • 2
    This is a great trick! Like the other answers, not really a big win over concatenation in terms of effort and readability, but nice to know. It's even sexier when you do something like `$_ = create_function('$a','return $a;'); $s = "I like {$_(ANIMAL)}"`. Thetaiko's version removes the need for quotes, and an underscore is cute. – Beejor Jun 05 '15 at 01:12
  • 4
    I could see this being useful for building a template engine, but it seems too sneaky to actually use. – Mnebuerquo Apr 20 '16 at 15:48
  • Pretty common for me to convert callable arrays into strings before using them in string interpolations. `$fn = implode('::', array( 'Arr', 'get' ));` should work as long as the method is public. I have seen others go for the anonymous function wrapper that calls `call_user_func` instead but I think it's sloppy; – NeoVance Dec 11 '22 at 08:07
  • more sneaky would be defining `$_c = 'constant';` where it would be a bit shorter but more visible: `echo( "hello {$_c(NAME)}, how are you?";`. But the advantage over `echo( "hello ".NAME." how are you?" );` is debateable. In webdev one could consider `Hello =NAME?> hru?` in this case. – theking2 Mar 29 '23 at 14:44
29
define( 'FOO', 'bar');  
$FOO = FOO;  
$string = "I am too lazy to concatenate $FOO in my string";
Macswork
  • 299
  • 3
  • 2
  • 9
    This is the one I use most, when I have a bunch of crazy SQL strings to compose. Also... passive-aggressive much? ;-) – Beejor Jun 05 '15 at 03:23
  • 2
    This one has the least amount of magic, at the expense of looking redundant – BrDaHa Jun 29 '17 at 01:36
14
define('FOO', 'bar');
$constants = create_function('$a', 'return $a;');
echo "Hello, my name is {$constants(FOO)}";
thetaiko
  • 7,816
  • 2
  • 33
  • 49
13

If you really want to echo constant without concatenation here is solution:

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

note: in this example echo takes a number of parameters (look at the commas), so it isn't real concatenation

Echo behaves as a function, it takes more parameters, it is more efficient than concatenation, because it doesn't have to concatenate and then echo, it just echoes everything without the need of creating new String concatenated object :))

EDIT

Also if you consider concatenating strings, passings strings as parameters or writing whole strings with " , The , (comma version) is always fastest, next goes . (concatenation with ' single quotes) and the slowest string building method is using double quotes ", because expressions written this way have to be evaluated against declared variables and functions..

Juraj Blahunka
  • 17,913
  • 6
  • 34
  • 52
12

You could do:

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']}";
arlomedia
  • 8,534
  • 5
  • 60
  • 108
Simon
  • 388
  • 3
  • 9
8

The easiest way is

define('MY_CONSTANT', 42);

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

Another way using (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
  • 4,274
  • 2
  • 36
  • 42
  • I regard this as a good solution. In some cases, connect string won't work if use direct CONSTANT inside. – kta May 01 '17 at 21:26
5

As others have pointed out you can not do that. PHP has a function constant() which cant be called directly in a string but we can easily work around this.

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

and a basic example on its usage:

define('FOO', 'Hello World!');
echo "The string says {$constant('FOO')}"; 
Yamiko
  • 5,303
  • 5
  • 30
  • 52
  • You can just do `$constant = 'constant';` instead of defining another function, and it would work identically since that function already exists. – redreinard Mar 01 '19 at 01:48
2

Here are some alternatives to the other answers, which seem to be focused mostly on the "{$}" trick. Though no guarantees are made on their speed; this is all pure syntactic sugar. For these examples, we'll assume the set of constants below were defined.

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

Using extract()
This one is nice because the result is identical to variables. First you create a reusable function:

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

Then call it from any scope:

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

Here, it lowercases the constants to be easier on your fingers, but you can remove the array_change_key_case() to keep them as-is. If you already have conflicting local variable names, the constants won't override them.

Using string replacement
This one is similar to sprintf(), but uses a single replacement token and accepts an unlimited number of arguments. I'm sure there are better ways to do this, but forgive my clunkiness and try to focus on the idea behind it.

Like before, you create a reusable function:

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

Then call it from any scope:

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

You can use any replacement token you want, like a % or #. I used the slash here since it's a bit easier to type.

Dom
  • 2,240
  • 16
  • 22
Beejor
  • 8,606
  • 1
  • 41
  • 31
1

Late to the party but here's my solution in case you don't like (s)printf :

// Can of course be replaced with the const syntax
define("FOO", "bar");
$replace_pairs = ["%myConstant" => FOO];
// Output : "My constant : bar"
echo strtr("My constant : %myConstant", $replace_pairs);
aym
  • 123
  • 1
  • 6
0

It is fun that you can use keyword 'const' as a name for your function to prevent namespace littering:

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

You can also use $GLOBALS to propagate 'const' function all over the code:

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

Unsure is it safe for future using. And what is worse - it's still looks ugly.

user619271
  • 4,766
  • 5
  • 30
  • 35
0

I need it pretty frequently, mostly while writing scripts, to print new line characters. When running the script from browser, the newline should be <br> and while executing it from terminal it should be PHP_EOL

So, I do something like:

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

This is an old question but for those searching here is another way to do it

<?php
define( 'MY_CONSTANT', 'world' );

echo "Hello {${$constant = 'constant'}('MY_CONSTANT')}";
-4

I believe this answers the OP's original question. The only thing is the globals index key seems to only work as lower case.

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

Output:

DB_USER=root
FattyPotatoes
  • 823
  • 1
  • 9
  • 14
  • 1
    This doesn't seem to work (even if you use uppercase consecutively) $GLOBALS is [`an associative array containing references to all variables`](http://www.php.net/manual/en/reserved.variables.globals.php). – alephreish Oct 15 '13 at 10:10
  • this answer is wrong. the only way that this could possibly produce that output is if somewhere in your script you also have `$db_user = 'root';` – Jeff Puckett Jul 24 '16 at 21:12