Incluir constante na string sem concatenar

166

Existe uma maneira no PHP de incluir uma constante em uma string sem concatenar?

define('MY_CONSTANT', 42);

echo "This is my constant: MY_CONSTANT";
Brian
fonte
12
A intuição me diz que "Esta é minha constante: {MY_CONSTANT}" deve funcionar. Não faz. Basta colocar isso aqui no caso de alguém pensa o mesmo que I.
Mikael Lindqvist

Respostas:

148

Não.

Com o Strings, não há como o PHP diferenciar os dados da string dos identificadores constantes. Isso vale para qualquer um dos formatos de string no PHP, incluindo o heredoc.

constant() é uma maneira alternativa de obter uma constante, mas uma chamada de função também não pode ser inserida em uma string sem concatenação.

Manual sobre constantes em PHP

Pekka
fonte
1
+1 de qualquer maneira, pois sem dúvida é a resposta certa. Primeiro, eu queria escrever da mesma forma que você, mas depois de ler a sua, pensei em apresentar algo diferente;)
Felix Kling
3
Ele Ele! Mas um bem merecido +1 para todos pela criatividade. :)
Pekka
59
"chamada de função não pode ser colocado em uma string" sim, pode:define('ANIMAL','turtles'); $constant='constant'; echo "I like {$constant('ANIMAL')}";
raveren
1
@Raveren, enquanto outros oferecem variações indiretas, criando funções desnecessariamente, a sua é a solução mais curta e direta que depende de funções variáveis, recurso subestimado e muito pouco usado do PHP. Fora de todo este segmento, fui com a sua solução específica. Gostaria de poder marcar com +1 mais de uma vez.
hndcrftd
4
Eu apenas apontei que é possível, não comentei de que maneira é melhor.
raveren
111

Sim, é (de alguma forma;)):

define('FOO', 'bar');

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

Provavelmente não é isso que você estava buscando, mas acho que tecnicamente isso não é concatenação, mas uma substituição e, a partir dessa suposição, inclui uma constante em uma string sem concatenar .

Felix Kling
fonte
5
@Pekka: Eu sei :-D (desta vez ...;))
Felix Kling
1
:) A abordagem de @ juraj.blahunka é ainda mais sorrateira. Responde à pergunta pela letra, mas não pelo espírito. :)
Pekka
2
@ blahunka: bom lema. Provavelmente o usamos diariamente
Alfabravo
57

Para usar constantes dentro de cadeias, você pode usar o seguinte método:

define( 'ANIMAL', 'turtles' ); 
$constant = 'constant';

echo "I like {$constant('ANIMAL')}";


Como é que isso funciona?

Você pode usar qualquer nome de função de string e parâmetros arbitrários

Pode-se colocar qualquer nome de função em uma variável e chamá-lo com parâmetros dentro de uma string de aspas duplas. Funciona com vários parâmetros também.

$fn = 'substr';

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

Produz

eu gosto de tartarugas

Funções anônimas também

Você também pode usar funções anônimas, desde que esteja executando o PHP 5.3 ou superior.

$escape   = function ( $string ) {
    return htmlspecialchars( (string) $string, ENT_QUOTES, 'utf-8' );
};
$userText = "<script>alert('xss')</script>";
echo( "You entered {$escape( $userText )}" );

Produz html com escape adequado conforme o esperado.

Matrizes de retorno de chamada não permitidas!

Se você já tem a impressão de que o nome da função pode ser chamado, esse não é o caso, pois uma matriz que retorna true quando transmitida is_callablecausa um erro fatal quando usado dentro de uma string:

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

Tenha em mente

Essa prática é desaconselhada, mas às vezes resulta em um código muito mais legível, então é com você - a possibilidade existe.

Raveren
fonte
1
Este é um ótimo truque! Como as outras respostas, não é realmente uma grande vitória sobre a concatenação em termos de esforço e legibilidade, mas é bom saber. É ainda mais sexy quando você faz algo assim $_ = create_function('$a','return $a;'); $s = "I like {$_(ANIMAL)}". A versão de Thetaiko elimina a necessidade de aspas, e um sublinhado é bonito.
Beejor
2
Eu pude ver isso sendo útil para criar um mecanismo de modelo, mas parece muito sorrateiro para realmente ser usado.
Mnebuerquo #
21
define( 'FOO', 'bar');  
$FOO = FOO;  
$string = "I am too lazy to concatenate $FOO in my string";
Macswork
fonte
4
Este é o que eu mais uso, quando tenho um monte de strings SQL malucas para compor. Também ... muito passivo-agressivo? ;-)
Beejor
2
Este tem a menor quantidade de magia, em detrimento da procura redundante
BrDaHa
Ótima solução. Simples e rápido.
Roger Hill
14
define('FOO', 'bar');
$constants = create_function('$a', 'return $a;');
echo "Hello, my name is {$constants(FOO)}";
thetaiko
fonte
13

Se você realmente deseja ecoar constante sem concatenação, aqui está a solução:

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

nota : neste exemplo, o echo usa vários parâmetros ( veja as vírgulas ), portanto não é uma concatenação real

O eco se comporta como uma função, requer mais parâmetros, é mais eficiente que a concatenação, porque não precisa concatenar e depois ecoar, apenas ecoa tudo sem a necessidade de criar um novo objeto concatenado String :))

EDITAR

Além disso, se você considerar concatenar strings, passings strings como parâmetros ou escrever strings inteiras com " , The , (versão de vírgula) será sempre mais rápida, a seguir será apresentada . (Concatenação com ' aspas simples) e o método mais lento de criação de strings usando aspas duplas " , porque as expressões escritas dessa maneira precisam ser avaliadas em relação a variáveis ​​e funções declaradas.

Juraj Blahunka
fonte
11

Você poderia fazer:

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

A maneira mais fácil é

define('MY_CONSTANT', 42);

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

Outra maneira de usar (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
fonte
Eu considero isso uma boa solução. Em alguns casos, a string de conexão não funcionará se usar CONSTANT direto dentro.
Kta
5

Como outros já apontaram, você não pode fazer isso. O PHP tem uma função constant()que não pode ser chamada diretamente em uma string, mas podemos facilmente contornar isso.

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

e um exemplo básico de uso:

define('FOO', 'Hello World!');
echo "The string says {$constant('FOO')}"; 
Yamiko
fonte
Você pode simplesmente fazer isso em $constant = 'constant';vez de definir outra função, e funcionaria de forma idêntica, pois essa função já existe.
Redreinard
2

Aqui estão algumas alternativas para as outras respostas, que parecem focadas principalmente no truque "{$}". Embora nenhuma garantia seja feita em sua velocidade; isso é todo açúcar sintático puro. Para esses exemplos, assumiremos que o conjunto de constantes abaixo foi definido.

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

Usando extract ()
Este é legal porque o resultado é idêntico às variáveis. Primeiro, você cria uma função reutilizável:

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

Em seguida, chame-o de qualquer escopo:

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

Aqui, as minúsculas são constantes para facilitar os dedos, mas você pode remover o array_change_key_case () para mantê-las como estão. Se você já possui nomes de variáveis ​​locais conflitantes, as constantes não os substituirão.

Usando a substituição de string
Este é semelhante ao sprintf (), mas usa um único token de substituição e aceita um número ilimitado de argumentos. Tenho certeza de que existem maneiras melhores de fazer isso, mas perdoe minha falta de jeito e tente se concentrar na idéia por trás disso.

Como antes, você cria uma função reutilizável:

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

Em seguida, chame-o de qualquer escopo:

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

Você pode usar qualquer token de substituição que desejar, como% ou #. Eu usei a barra aqui, pois é um pouco mais fácil de digitar.

Beejor
fonte
0

É divertido que você possa usar a palavra-chave 'const' como um nome para sua função, para evitar o lixo do espaço para nome:

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

Você também pode usar $ GLOBALS para propagar a função 'const' por todo o código:

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

Incerto é seguro para uso futuro. E o que é pior - ainda parece feio.

user619271
fonte
-2

Eu acredito que isso responde à pergunta original do OP. A única coisa é que a chave do índice global parece funcionar apenas como minúscula.

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

Resultado:

DB_USER=root
FattyPotatoes
fonte
1
Parece que não funciona (mesmo que você use maiúsculas consecutivamente). $ GLOBALS é an associative array containing references to all variables.
har-wradim
esta resposta está errada. a única maneira que isso poderia produzir essa saída é se em algum lugar em seu script você também tem$db_user = 'root';
Jeff Puckett