Inclure la constante dans la chaîne sans concaténation

166

Existe-t-il un moyen en PHP d'inclure une constante dans une chaîne sans concaténation?

define('MY_CONSTANT', 42);

echo "This is my constant: MY_CONSTANT";
Brian
la source
12
L'intuition me dit que "Ceci est ma constante: {MY_CONSTANT}" devrait fonctionner. Ce n'est pas le cas. Juste mettre ceci ici au cas où quelqu'un pense la même chose que moi
Mikael Lindqvist

Réponses:

148

Non.

Avec les chaînes, il n'y a aucun moyen pour PHP de distinguer les données de chaîne des identifiants constants. Cela vaut pour tous les formats de chaînes en PHP, y compris heredoc.

constant() est une autre façon de récupérer une constante, mais un appel de fonction ne peut pas non plus être placé dans une chaîne sans concaténation.

Manuel sur les constantes en PHP

Pekka
la source
1
+1 de toute façon car c'est sans aucun doute la bonne réponse. Je voulais d'abord écrire la même chose que vous, mais après avoir lu le vôtre, j'ai pensé que je devais présenter quelque chose de différent;)
Felix Kling
3
Hehe! Mais un +1 bien mérité pour tout le monde pour la créativité. :)
Pekka
60
"l'appel de fonction ne peut pas être mis dans une chaîne" oui il peut:define('ANIMAL','turtles'); $constant='constant'; echo "I like {$constant('ANIMAL')}";
raveren
1
@Raveren, tandis que d'autres proposent des variantes indirectes, créant inutilement des fonctions, la vôtre est la solution la plus courte et la plus précise qui repose sur des fonctions variables, fonctionnalité sous-estimée et très rarement utilisée de PHP. De tout ce fil, je suis allé avec VOTRE solution particulière. J'aimerais pouvoir attribuer +1 plus d'une fois.
hndcrftd
4
Je viens de souligner que c'est possible, je n'ai pas commenté la meilleure façon de procéder.
raveren le
111

Oui c'est (d'une certaine manière;)):

define('FOO', 'bar');

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

Ce n'est probablement pas ce que vous visiez, mais je pense que, techniquement, ce n'est pas une concaténation mais une substitution et à partir de cette hypothèse, il inclut une constante dans une chaîne sans concaténation .

Félix Kling
la source
5
@Pekka: Je sais :-D (juste cette fois ...;))
Felix Kling
1
:) L'approche de @ juraj.blahunka est encore plus sournoise. Il répond à la question par la lettre, mais pas par son esprit. :)
Pekka
2
@blahunka: belle devise. Nous l'utilisons probablement quotidiennement
Alfabravo
57

Pour utiliser des constantes dans des chaînes, vous pouvez utiliser la méthode suivante:

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

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


Comment cela marche-t-il?

Vous pouvez utiliser n'importe quel nom de fonction de chaîne et des paramètres arbitraires

On peut placer n'importe quel nom de fonction dans une variable et l'appeler avec des paramètres dans une chaîne entre guillemets. Fonctionne également avec plusieurs paramètres.

$fn = 'substr';

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

Produit

J'aime les tortues

Fonctions anonymes aussi

Vous pouvez également utiliser des fonctions anonymes à condition que vous exécutiez PHP 5.3+.

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

Produit un code HTML correctement échappé comme prévu.

Les tableaux de rappel ne sont pas autorisés!

Si à présent vous avez l'impression que le nom de la fonction peut être appelable, ce n'est pas le cas, car un tableau qui renvoie true lorsqu'il est passé à is_callableprovoquerait une erreur fatale lorsqu'il est utilisé dans une chaîne:

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

Gardez à l'esprit

Cette pratique est peu judicieuse, mais aboutit parfois à un code beaucoup plus lisible, c'est donc à vous - la possibilité est là.

Raveren
la source
1
C'est une super astuce! Comme les autres réponses, pas vraiment une grande victoire sur la concaténation en termes d'effort et de lisibilité, mais bon à savoir. C'est encore plus sexy quand vous faites quelque chose comme $_ = create_function('$a','return $a;'); $s = "I like {$_(ANIMAL)}". La version de Thetaiko supprime le besoin de citations, et un trait de soulignement est mignon.
Beejor
2
Je pourrais voir que cela est utile pour créer un moteur de modèle, mais cela semble trop sournois pour être utilisé.
Mnebuerquo
21
define( 'FOO', 'bar');  
$FOO = FOO;  
$string = "I am too lazy to concatenate $FOO in my string";
Macswork
la source
4
C'est celui que j'utilise le plus, quand j'ai un tas de chaînes SQL folles à composer. Aussi ... passif-agressif beaucoup? ;-)
Beejor
2
Celui-ci a le moins de magie, au détriment de l'air redondant
BrDaHa
Excellente solution. Simple et rapide.
Roger Hill
14
define('FOO', 'bar');
$constants = create_function('$a', 'return $a;');
echo "Hello, my name is {$constants(FOO)}";
thetaiko
la source
13

Si vous voulez vraiment faire écho à une constante sans concaténation, voici la solution:

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

note : dans cet exemple, echo prend un certain nombre de paramètres ( regardez les virgules ), donc ce n'est pas une vraie concaténation

L'écho se comporte comme une fonction, il prend plus de paramètres, il est plus efficace que la concaténation, car il n'a pas besoin de concaténer puis d'écho, il fait juste écho à tout sans avoir besoin de créer un nouvel objet concaténé String :))

ÉDITER

De plus, si vous envisagez de concaténer des chaînes, de passer des chaînes en tant que paramètres ou d'écrire des chaînes entières avec " , The , (version virgule) est toujours le plus rapide, ensuite . (Concaténation avec ' guillemets simples) et la méthode de construction de chaînes la plus lente utilise des guillemets doubles " , car les expressions écrites de cette façon doivent être évaluées par rapport aux variables et fonctions déclarées.

Juraj Blahunka
la source
11

Vous pourriez faire:

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
la source
6

Le moyen le plus simple est

define('MY_CONSTANT', 42);

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

Une autre façon d'utiliser (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
la source
Je considère cela comme une bonne solution. Dans certains cas, la chaîne de connexion ne fonctionnera pas si vous utilisez Direct CONSTANT à l'intérieur.
kta
5

Comme d'autres l'ont souligné, vous ne pouvez pas faire cela. PHP a une fonction constant()qui ne peut pas être appelée directement dans une chaîne, mais nous pouvons facilement contourner ce problème.

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

et un exemple de base sur son utilisation:

define('FOO', 'Hello World!');
echo "The string says {$constant('FOO')}"; 
Yamiko
la source
Vous pouvez simplement le faire $constant = 'constant';au lieu de définir une autre fonction, et cela fonctionnerait de la même manière puisque cette fonction existe déjà.
redreinard
2

Voici quelques alternatives aux autres réponses, qui semblent se concentrer principalement sur l'astuce "{$}". Bien qu'aucune garantie ne soit faite sur leur vitesse; tout cela est du sucre syntaxique pur. Pour ces exemples, nous supposerons que l'ensemble de constantes ci-dessous a été défini.

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

Utiliser extract ()
Celui-ci est sympa car le résultat est identique aux variables. Commencez par créer une fonction réutilisable:

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

Puis appelez-le depuis n'importe quelle portée:

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

Ici, il minuscule les constantes pour être plus facile sur vos doigts, mais vous pouvez supprimer le array_change_key_case () pour les garder telles quelles. Si vous avez déjà des noms de variables locales en conflit, les constantes ne les remplaceront pas.

Utilisation du remplacement de chaîne
Celui-ci est similaire à sprintf (), mais utilise un seul jeton de remplacement et accepte un nombre illimité d'arguments. Je suis sûr qu'il existe de meilleures façons de le faire, mais pardonnez ma maladresse et essayez de vous concentrer sur l'idée derrière cela.

Comme avant, vous créez une fonction réutilisable:

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

Puis appelez-le depuis n'importe quelle portée:

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

Vous pouvez utiliser n'importe quel jeton de remplacement de votre choix, comme un% ou un #. J'ai utilisé la barre oblique ici car c'est un peu plus facile à taper.

Beejor
la source
0

Il est amusant que vous puissiez utiliser le mot-clé 'const' comme nom pour votre fonction pour éviter les déchets d'espace de noms:

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

Vous pouvez également utiliser $ GLOBALS pour propager la fonction 'const' dans tout le code:

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

Je ne sais pas s'il est sans danger pour une utilisation future. Et ce qui est pire, c'est toujours moche.

user619271
la source
-2

Je pense que cela répond à la question initiale du PO. La seule chose est que la clé d'index global semble ne fonctionner qu'en minuscules.

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

Production:

DB_USER=root
Pommes de terre grasses
la source
1
Cela ne semble pas fonctionner (même si vous utilisez des majuscules consécutivement) $ GLOBALS est an associative array containing references to all variables.
har-wradim
cette réponse est fausse. la seule façon dont cela pourrait éventuellement produire cette sortie est si quelque part dans votre script vous avez également$db_user = 'root';
Jeff Puckett