Konstante ohne Verkettung in String einfügen

166

Gibt es in PHP eine Möglichkeit, eine Konstante in eine Zeichenfolge aufzunehmen, ohne sie zu verketten?

define('MY_CONSTANT', 42);

echo "This is my constant: MY_CONSTANT";
Brian
quelle
12
Die Intuition sagt mir, dass "Dies ist meine Konstante: {MY_CONSTANT}" funktionieren sollte. Das tut es nicht. Setzen Sie dies hier nur für den Fall, dass jemand das gleiche denkt wie ich.
Mikael Lindqvist

Antworten:

148

Nein.

Mit Strings gibt es für PHP keine Möglichkeit, String-Daten von konstanten Bezeichnern zu unterscheiden. Dies gilt für alle Zeichenfolgenformate in PHP, einschließlich Heredoc.

constant() ist eine alternative Möglichkeit, eine Konstante zu erhalten, aber ein Funktionsaufruf kann auch nicht ohne Verkettung in eine Zeichenfolge eingefügt werden.

Handbuch zu Konstanten in PHP

Pekka
quelle
1
+1 sowieso, da es zweifellos die richtige Antwort ist. Zuerst wollte ich dasselbe schreiben wie du, aber nachdem ich deins gelesen hatte, dachte ich, ich muss etwas anderes präsentieren;)
Felix Kling
3
Hehe! Aber eine wohlverdiente +1 für alle für Kreativität. :)
Pekka
59
"Funktionsaufruf kann nicht in eine Zeichenfolge define('ANIMAL','turtles'); $constant='constant'; echo "I like {$constant('ANIMAL')}";
eingefügt werden
1
@Raveren, während andere indirekte Variationen anbieten und unnötig Funktionen erstellen, ist Ihre Lösung die kürzeste und auf den Punkt gebrachte Lösung, die auf variablen Funktionen, unterschätzten und sehr selten verwendeten Funktionen von PHP beruht. Aus diesem ganzen Thread ging ich mit IHRER speziellen Lösung. Ich wünschte, ich könnte es mehr als einmal +1 geben.
hndcrftd
4
Ich habe nur darauf hingewiesen, dass es möglich ist, nicht kommentiert, welcher Weg besser ist.
Raveren
111

Ja, das ist es (irgendwie;)):

define('FOO', 'bar');

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

Dies ist wahrscheinlich nicht das, was Sie angestrebt haben, aber ich denke, technisch gesehen ist dies keine Verkettung, sondern eine Substitution, und von dieser Annahme aus enthält es eine Konstante in einer Zeichenfolge ohne Verkettung .

Felix Kling
quelle
5
@ Pekka: Ich weiß :-D (nur dieses Mal ...;))
Felix Kling
1
:) @ juraj.blahunkas Ansatz ist noch hinterhältiger. Es beantwortet die Frage mit dem Brief, aber nicht mit seinem Geist. :)
Pekka
2
@blahunka: schönes Motto. Wir benutzen es wahrscheinlich täglich
Alfabravo
57

Um Konstanten in Zeichenfolgen zu verwenden, können Sie die folgende Methode verwenden:

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

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


Wie funktioniert das?

Sie können einen beliebigen String-Funktionsnamen und beliebige Parameter verwenden

Man kann einen beliebigen Funktionsnamen in eine Variable einfügen und ihn mit Parametern in einer Zeichenfolge in doppelten Anführungszeichen aufrufen. Funktioniert auch mit mehreren Parametern.

$fn = 'substr';

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

Produziert

Ich mag Schildkröten

Anonyme Funktionen auch

Sie können auch anonyme Funktionen verwenden, sofern Sie PHP 5.3+ ausführen.

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

Produziert wie erwartet ordnungsgemäß entkommenes HTML.

Rückruf-Arrays nicht erlaubt!

Wenn Sie jetzt den Eindruck haben, dass der Funktionsname beliebig aufrufbar sein kann, ist dies nicht der Fall, da ein Array, das bei Übergabe an true zurückgibt, is_callablebei Verwendung in einer Zeichenfolge einen schwerwiegenden Fehler verursachen würde:

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

Merken Sie sich

Diese Vorgehensweise ist schlecht beraten, führt aber manchmal zu viel besser lesbarem Code. Es liegt also an Ihnen - die Möglichkeit ist vorhanden.

Raveren
quelle
1
Das ist ein toller Trick! Wie die anderen Antworten auch kein großer Gewinn für die Verkettung in Bezug auf Aufwand und Lesbarkeit, aber gut zu wissen. Es ist noch sexier, wenn Sie so etwas tun $_ = create_function('$a','return $a;'); $s = "I like {$_(ANIMAL)}". Thetaikos Version macht Zitate überflüssig und ein Unterstrich ist süß.
Beejor
2
Ich konnte sehen, dass dies nützlich ist, um eine Template-Engine zu erstellen, aber es scheint zu hinterhältig, um es tatsächlich zu verwenden.
Mnebuerquo
21
define( 'FOO', 'bar');  
$FOO = FOO;  
$string = "I am too lazy to concatenate $FOO in my string";
Macswork
quelle
4
Dies ist die, die ich am häufigsten benutze, wenn ich ein paar verrückte SQL-Strings zum Komponieren habe. Auch ... passiv-aggressiv viel? ;-)
Beejor
2
Dieser hat die geringste Menge an Magie, auf Kosten der Redundanz
BrDaHa
Tolle Lösung. Einfach und schnell.
Roger Hill
14
define('FOO', 'bar');
$constants = create_function('$a', 'return $a;');
echo "Hello, my name is {$constants(FOO)}";
Thetaiko
quelle
13

Wenn Sie wirklich eine Konstante ohne Verkettung wiedergeben möchten, ist hier die Lösung:

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

Hinweis : In diesem Beispiel verwendet Echo eine Reihe von Parametern ( siehe Kommas ), sodass es sich nicht um eine echte Verkettung handelt

Echo verhält sich wie eine Funktion, es benötigt mehr Parameter, es ist effizienter als die Verkettung, da es nicht verkettet und dann wiedergegeben werden muss. Es gibt einfach alles wieder, ohne dass ein neues verkettetes String-Objekt erstellt werden muss :))

BEARBEITEN

Auch wenn man bedenkt , verketten Strings, passings Strings als Parameter oder Schreiben ganze Strings mit „The , (Komma - Version) wird immer am schnellsten, nächsten geht . (Verkettung mit ' einfachen Anführungszeichen) und die langsamsten String - Methode Aufbau wird mit doppelten Anführungszeichen , weil auf diese Weise geschriebene Ausdrücke gegen deklarierte Variablen und Funktionen ausgewertet werden müssen.

Juraj Blahunka
quelle
11

Du könntest es tun:

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
quelle
6

Der einfachste Weg ist

define('MY_CONSTANT', 42);

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

Ein anderer Weg mit (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
quelle
Ich halte das für eine gute Lösung. In einigen Fällen funktioniert die Verbindungszeichenfolge nicht, wenn direkt CONSTANT verwendet wird.
kta
5

Wie andere darauf hingewiesen haben, kann man das nicht tun. PHP hat eine Funktion, constant()die nicht direkt in einem String aufgerufen werden kann, aber wir können dies leicht umgehen.

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

und ein grundlegendes Beispiel für seine Verwendung:

define('FOO', 'Hello World!');
echo "The string says {$constant('FOO')}"; 
Yamiko
quelle
Sie können dies einfach tun, $constant = 'constant';anstatt eine andere Funktion zu definieren, und dies würde identisch funktionieren, da diese Funktion bereits vorhanden ist.
Redreinard
2

Hier sind einige Alternativen zu den anderen Antworten, die sich hauptsächlich auf den Trick "{$}" zu konzentrieren scheinen. Es werden jedoch keine Garantien für ihre Geschwindigkeit gegeben; Das ist alles reiner syntaktischer Zucker. Für diese Beispiele nehmen wir an, dass die folgenden Konstanten definiert wurden.

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

Verwenden von extract ()
Dies ist hilfreich, da das Ergebnis mit Variablen identisch ist. Zuerst erstellen Sie eine wiederverwendbare Funktion:

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

Rufen Sie es dann aus einem beliebigen Bereich auf:

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

Hier werden die Konstanten in Kleinbuchstaben geschrieben, um Ihre Finger zu schonen. Sie können jedoch das array_change_key_case () entfernen, um sie unverändert zu lassen. Wenn Sie bereits widersprüchliche lokale Variablennamen haben, werden diese von den Konstanten nicht überschrieben.

Verwenden der Zeichenfolgenersetzung
Diese Option ähnelt sprintf (), verwendet jedoch ein einzelnes Ersetzungstoken und akzeptiert eine unbegrenzte Anzahl von Argumenten. Ich bin mir sicher, dass es bessere Möglichkeiten gibt, dies zu tun, aber verzeihen Sie meine Unbeholfenheit und versuchen Sie, sich auf die Idee dahinter zu konzentrieren.

Wie zuvor erstellen Sie eine wiederverwendbare Funktion:

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

Rufen Sie es dann aus einem beliebigen Bereich auf:

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

Sie können jedes gewünschte Ersatz-Token verwenden, z. B.% oder #. Ich habe den Schrägstrich hier verwendet, da er etwas einfacher zu tippen ist.

Beejor
quelle
0

Es macht Spaß, dass Sie das Schlüsselwort 'const' als Namen für Ihre Funktion verwenden können, um Namespace-Abfall zu vermeiden:

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

Sie können auch $ GLOBALS verwenden, um die Funktion 'const' im gesamten Code zu verbreiten:

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

Unsicher ist, ob es für die zukünftige Verwendung sicher ist. Und was noch schlimmer ist - es sieht immer noch hässlich aus.

user619271
quelle
-2

Ich glaube, dies beantwortet die ursprüngliche Frage des OP. Das einzige ist, dass der globale Indexschlüssel nur in Kleinbuchstaben zu funktionieren scheint.

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

Ausgabe:

DB_USER=root
FattyPotatoes
quelle
1
Dies scheint nicht zu funktionieren (auch wenn Sie nacheinander Großbuchstaben verwenden). $ GLOBALS ist an associative array containing references to all variables.
Har-Wradim
Diese Antwort ist falsch. Der einzige Weg, wie dies möglicherweise zu dieser Ausgabe führen könnte, ist, wenn Sie irgendwo in Ihrem Skript auch haben$db_user = 'root';
Jeff Puckett