Includi costante nella stringa senza concatenare


166

C'è un modo in PHP di includere una costante in una stringa senza concatenare?

define('MY_CONSTANT', 42);

echo "This is my constant: MY_CONSTANT";

12
L'intuizione mi dice che "Questa è la mia costante: {MY_CONSTANT}" dovrebbe funzionare. Non Se lo metto qui nel caso qualcuno la pensi allo stesso modo di me.
Mikael Lindqvist,

Risposte:


148

No.

Con Stringhe, PHP non può distinguere i dati delle stringhe da identificatori costanti. Questo vale per qualsiasi formato di stringa in PHP, incluso heredoc.

constant() è un modo alternativo per ottenere una costante, ma neanche una chiamata di funzione può essere inserita in una stringa senza concatenazione.

Manuale sulle costanti in PHP


1
+1 comunque in quanto indubbiamente la risposta giusta. Prima volevo scrivere lo stesso di te, ma dopo aver letto il tuo, ho pensato di dover presentare qualcosa di diverso;)
Felix Kling

3
Hehe! Ma un meritato +1 per tutti per la creatività. :)
Pekka,

59
"La funzione non può essere inserita in una stringa" sì, può:define('ANIMAL','turtles'); $constant='constant'; echo "I like {$constant('ANIMAL')}";
raveren,

1
@Raveren, mentre altri offrono variazioni indirette, creando inutilmente funzioni, la tua è la soluzione più breve e puntuale che si basa su funzioni variabili, funzionalità sottovalutate e utilizzate raramente di PHP. Da tutto questo thread sono andato con la TUA soluzione particolare. Vorrei poterlo fare +1 più di una volta.
hndcrftd,

4
Ho appena sottolineato che è possibile, non commentato in che modo sia meglio.
Raveren,

111

Sì lo è (in qualche modo;)):

define('FOO', 'bar');

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

Probabilmente questo non è ciò a cui stavi mirando, ma penso che tecnicamente non si tratti di concatenazione ma di una sostituzione e da questo presupposto include una costante in una stringa senza concatenare .


5
@Pekka: lo so MrGreen (solo questa volta ...;))
Felix Kling

1
:) L'approccio di @ juraj.blahunka è ancora più subdolo. Risponde alla domanda con la lettera, ma non con il suo spirito. :)
Pekka,

2
@blahunka: bel motto. Probabilmente lo usiamo ogni giorno
Alfabravo

57

Per usare le costanti all'interno delle stringhe puoi usare il seguente metodo:

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

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


Come funziona?

È possibile utilizzare qualsiasi nome di funzione stringa e parametri arbitrari

Si può inserire qualsiasi nome di funzione in una variabile e chiamarlo con parametri all'interno di una stringa tra virgolette doppie. Funziona anche con più parametri.

$fn = 'substr';

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

produce

Mi piacciono le tartarughe

Anche funzioni anonime

Puoi anche usare funzioni anonime a condizione che tu stia eseguendo PHP 5.3+.

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

Produce html con escape corretto come previsto.

Array di callback non consentiti!

Se ormai hai l'impressione che il nome della funzione possa essere richiamabile, non è così, poiché un array che restituisce true quando viene passato is_callablecauserebbe un errore irreversibile se utilizzato all'interno di una stringa:

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

Tieni a mente

Questa pratica è sconsiderata, ma a volte si traduce in un codice molto più leggibile, quindi dipende da te - la possibilità è lì.


1
Questo è un grande trucco! Come le altre risposte, non è proprio una grande vittoria sulla concatenazione in termini di sforzo e leggibilità, ma è bello da sapere. È ancora più sexy quando fai qualcosa del genere $_ = create_function('$a','return $a;'); $s = "I like {$_(ANIMAL)}". La versione di Thetaiko elimina la necessità di virgolette e un carattere di sottolineatura è carino.
Beejor,

2
Ho potuto vedere che questo è utile per la creazione di un motore modello, ma sembra troppo subdolo per essere effettivamente utilizzato.
Mnebuerquo,

21
define( 'FOO', 'bar');  
$FOO = FOO;  
$string = "I am too lazy to concatenate $FOO in my string";

4
Questo è quello che uso di più, quando ho un sacco di pazze stringhe SQL da comporre. Inoltre ... passivo-aggressivo molto? ;-)
Beejor,

2
Questo ha la minima quantità di magia, a scapito di sembrare ridondante
BrDaHa,

Ottima soluzione Semplice e veloce.
Roger Hill,

14
define('FOO', 'bar');
$constants = create_function('$a', 'return $a;');
echo "Hello, my name is {$constants(FOO)}";

13

Se vuoi davvero echeggiare costante senza concatenare, ecco la soluzione:

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

nota : in questo esempio echo accetta un numero di parametri ( guarda le virgole ), quindi non è concatenazione reale

L'eco si comporta come una funzione, richiede più parametri, è più efficiente della concatenazione, perché non deve concatenare e quindi fare eco, fa semplicemente eco a tutto senza la necessità di creare un nuovo oggetto concatenato String :))

MODIFICARE

Anche se si considera concatenare stringhe, scomparse le stringhe come parametri o la scrittura di stringhe intere con "The , (versione virgola) è sempre più veloce, va prossimo . (Concatenamento con ' apici) e la stringa più lento metodo di costruzione sta usando le virgolette doppie " , perché le espressioni scritte in questo modo devono essere valutate rispetto a variabili e funzioni dichiarate.


11

Potresti fare:

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

Il modo più semplice è

define('MY_CONSTANT', 42);

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

Un altro modo di usare (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;

Considero questa una buona soluzione. In alcuni casi, la stringa di connessione non funzionerà se si utilizza direttamente CONSTANT all'interno.
kta,

5

Come altri hanno sottolineato, non puoi farlo. PHP ha una funzione constant()che non può essere chiamata direttamente in una stringa, ma possiamo facilmente aggirare il problema.

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

e un esempio di base sul suo utilizzo:

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

Puoi semplicemente fare $constant = 'constant';invece di definire un'altra funzione, e funzionerebbe in modo identico poiché quella funzione esiste già.
redreinard

2

Ecco alcune alternative alle altre risposte, che sembrano concentrarsi principalmente sul trucco "{$}". Sebbene non vengano fornite garanzie sulla loro velocità; questo è tutto puro zucchero sintattico. Per questi esempi, supponiamo che siano state definite le seguenti costanti.

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

Uso di extract ()
Questo è carino perché il risultato è identico alle variabili. Per prima cosa crei una funzione riutilizzabile:

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

Quindi chiamalo da qualsiasi ambito:

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

Qui, minuscole le costanti per essere più facili con le dita, ma è possibile rimuovere array_change_key_case () per mantenerle così come sono. Se hai già nomi variabili locali in conflitto, le costanti non li sovrascriveranno.

Uso della sostituzione della stringa
Questo è simile a sprintf (), ma utilizza un singolo token di sostituzione e accetta un numero illimitato di argomenti. Sono sicuro che ci sono modi migliori per farlo, ma perdona la mia confusione e cerca di concentrarmi sull'idea alla base.

Come prima, crei una funzione riutilizzabile:

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

Quindi chiamalo da qualsiasi ambito:

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

Puoi utilizzare qualsiasi token sostitutivo desiderato, ad esempio% o #. Ho usato la barra qui perché è un po 'più facile da scrivere.


0

È divertente usare la parola chiave 'const' come nome per la tua funzione per prevenire la sporcizia dello spazio dei nomi:

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

Puoi anche usare $ GLOBALS per propagare la funzione 'const' in tutto il codice:

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

Non sono sicuro che sia sicuro per un utilizzo futuro. E quel che è peggio, sembra ancora brutto.


-2

Credo che questo risponda alla domanda originale del PO. L'unica cosa è che la chiave dell'indice globale sembra funzionare solo in minuscolo.

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

Produzione:

DB_USER=root

1
Questo non sembra funzionare (anche se si usano maiuscole consecutive) $ GLOBALS lo è an associative array containing references to all variables.
Har-Wradim,

questa risposta è sbagliata. l'unico modo in cui questo potrebbe produrre quell'output è se anche tu da qualche parte nella tua sceneggiatura hai$db_user = 'root';
Jeff Puckett,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.