Включайте константу в рядок без сполучення


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

59
"виклик функції не можна вводити в рядок" так, це може:define('ANIMAL','turtles'); $constant='constant'; echo "I like {$constant('ANIMAL')}";
raveren

1
@Raveren, в той час як інші пропонують непрямі зміни, без необхідності створюючи функції, ваше є найкоротшим і точним рішенням, яке покладається на змінні функції, занижену і дуже рідко використовувану функцію PHP. З усієї цієї теми я пішов із ВАШИМ конкретним рішенням. Я хотів би, щоб я міг поставити +1 ще раз.
hndcrftd

4
Я просто зазначив, що це можливо, не коментуючи, який шлях краще.
raveren

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

Пам'ятай

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


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 для складання. Також ... пасивно-агресивне багато? ;-)
Bejjor

2
Цей має найменший об’єм магії, за рахунок того, щоб виглядати зайвим
BrDaHa

Прекрасне рішення. Просто і швидко.
Роджер Хілл

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

зауважте : у цьому прикладі ехо приймає ряд параметрів ( дивіться на коми ), тому це не реальна конкатенація

Ехо поводиться як функція, він приймає більше параметрів, він більш ефективний, ніж конкатенація, тому що він не повинен об'єднуватися, а потім лунати, він просто повторює все без необхідності створення нового об'єднаного об'єкта String :))

EDIT

Крім того, якщо ви розглядаєте об'єднання рядків, рядків передачі як параметри або записування цілих рядків з " ," , (версія кома) завжди найшвидший, наступний наступний . (Об'єднання з " одинарними лапками") і найповільніший метод побудови рядків використовує подвійні лапки " , тому що вирази, написані таким чином, повинні бути оцінені відповідно до оголошених змінних та функцій.


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

Я вважаю, що це відповідає на оригінальне запитання ОП. Єдине, що індекс глобальних ключів, здається, працює лише в нижньому регістрі.

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.