Включить константу в строку без объединения

166

Есть ли в PHP способ включить константу в строку без объединения?

define('MY_CONSTANT', 42);

echo "This is my constant: MY_CONSTANT";
Брайан
источник
12
Интуиция говорит мне, что «Это моя константа: {MY_CONSTANT}» должно работать. Это не так. Просто поместите это здесь на случай, если кто-то думает так же, как я.
Микаэль Линдквист,

Ответы:

148

Нет.

В случае Strings PHP не может отличить строковые данные от константных идентификаторов. Это относится к любому из строковых форматов в PHP, включая heredoc.

constant() это альтернативный способ получить константу, но вызов функции не может быть помещен в строку без конкатенации.

Руководство по константам в PHP

Пекка
источник
1
+1 в любом случае, так как это, несомненно, правильный ответ. Сначала я хотел написать то же самое, что и вы, но после прочтения вашего, я подумал, что должен представить что-то другое;)
Феликс Клинг
3
Хехе! Но заслуженный +1 для всех за творчество. :)
Pekka
60
"вызов функции не может быть помещен в строку" да, это может быть:define('ANIMAL','turtles'); $constant='constant'; echo "I like {$constant('ANIMAL')}";
raveren
1
@Raveren, в то время как другие предлагают косвенные варианты, создавая ненужные функции, ваше самое короткое и конкретное решение, которое опирается на переменные функции, недооцененную и очень редко используемую функцию PHP. Из всей этой цепочки я пошел с ВАШИМ конкретным решением. Я хотел бы +1 это больше, чем один раз.
hndcrftd
4
Я просто указал, что это возможно, но не комментировал, какой путь лучше.
Раверен
111

Да, это так (в некотором роде;))

define('FOO', 'bar');

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

Вероятно, это не то, к чему вы стремились, но я думаю, что технически это не конкатенация, а подстановка, и из этого предположения она включает константу в строку без конкатенации .

Феликс Клинг
источник
5
@Pekka: Я знаю :-D (как раз на этот раз ...;))
Феликс Клинг
1
:) Подход @ juraj.blahunka еще более подлый. Он отвечает на вопрос буквой, но не его духом. :)
Pekka
2
@blahunka: хороший девиз. Мы, вероятно, используем его ежедневно
Alfabravo
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 )}" ); 

Иметь ввиду

Эта практика опрометчива, но иногда приводит к гораздо более читабельному коду, так что решать вам - возможность есть.

raveren
источник
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";
Macswork
источник
4
Это тот, который я использую чаще всего, когда у меня есть куча сумасшедших строк SQL для создания. Также ... пассивно-агрессивно много? ;-)
Beejor
2
У этого есть наименьшее количество волшебства, за счет того, что он выглядит излишним
BrDaHa
Отличное решение. Просто и быстро.
Роджер Хилл
14
define('FOO', 'bar');
$constants = create_function('$a', 'return $a;');
echo "Hello, my name is {$constants(FOO)}";
thetaiko
источник
13

Если вы действительно хотите отображать константу без конкатенации, вот решение:

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

примечание : в этом примере echo принимает несколько параметров ( посмотрите на запятые ), поэтому это не настоящая конкатенация

Echo ведет себя как функция, он принимает больше параметров, он более эффективен, чем конкатенация, потому что ему не нужно конкатенировать и затем эхо, он просто повторяет все без необходимости создания нового объекта String сцепленного :))

РЕДАКТИРОВАТЬ

Кроме того, если вы считаете , конкатенация струнными, обгоны строки в качестве параметров или писать целые строки с «The , (запятая версия) всегда быстро, рядом идет . (Конкатенация с ' одинарных кавычками) и медленный строка метода построения использует двойные кавычки » , потому что выражения, написанные таким образом, должны сравниваться с объявленными переменными и функциями ..

Юрай Блахунка
источник
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;
Jekis
источник
Я считаю это хорошим решением. В некоторых случаях строка подключения не будет работать, если использовать прямой CONSTANT внутри.
КТА
5

Как уже отмечали другие, вы не можете этого сделать. В PHP есть функция, constant()которую нельзя вызывать непосредственно в строке, но мы можем легко обойти это.

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

и базовый пример его использования:

define('FOO', 'Hello World!');
echo "The string says {$constant('FOO')}"; 
Yamiko
источник
Вы можете просто сделать это $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 );

Вы можете использовать любой заменяющий токен, например,% или #. Я использовал косую черту здесь, потому что это немного легче набирать.

Beejor
источник
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;};

Не уверен, что это безопасно для будущего использования. И что еще хуже - все равно выглядит некрасиво.

user619271
источник
-2

Я считаю, что это отвечает на оригинальный вопрос ОП. Единственное, что глобальный индексный ключ, похоже, работает только в нижнем регистре.

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

Вывод:

DB_USER=root
FattyPotatoes
источник
1
Это, похоже, не работает (даже если вы используете заглавные буквы последовательно) $ GLOBALS an associative array containing references to all variables.
har-wradim
этот ответ неверный. единственный способ, которым это могло бы привести к получению этого результата, - это если где-то в вашем сценарии у вас тоже есть$db_user = 'root';
Джефф Пукетт,