90 votes

Faire en sorte que PHP cesse de remplacer les caractères '.' dans les tableaux $_GET ou $_POST ?

Si je passe des variables PHP avec . dans leur nom via $_GET PHP les remplace automatiquement par _ personnages. Par exemple :

<?php
echo "url is ".$_SERVER['REQUEST_URI']."<p>";
echo "x.y is ".$_GET['x.y'].".<p>";
echo "x_y is ".$_GET['x_y'].".<p>";

... produit les résultats suivants :

url is /SpShipTool/php/testGetUrl.php?x.y=a.b
x.y is .
x_y is a.b.

... ma question est la suivante : existe-t-il cualquier comment je peux arrêter ça ? Je n'arrive pas à comprendre ce que j'ai fait pour mériter ça.

La version de PHP que j'utilise est 5.2.4-2ubuntu5.3.

79voto

Jeremy Ruten Points 59989

Voici l'explication de PHP.net :

Points dans les noms de variables entrantes

Typiquement, PHP ne modifie pas les noms des variables lorsqu'ils sont passées dans un script. Cependant, il devrait être noté que le point (period, point) n'est pas un caractère valide dans un nom de variable PHP. Pour la raison suivante , regardez-le :

<?php
$varname.ext;  /* invalid variable name */
?>

Maintenant, que l'analyseur voit une variable nommée $varname, suivie de la chaîne de caractères suivi de l'opérateur de concaténation de chaînes de caractères, suivi de le barestring (c'est-à-dire une chaîne non citée) qui ne correspond à aucune clé connue ou mots réservés) 'ext'. Évidemment, ceci n'a pas le résultat escompté.

Pour cette raison, il est important de noter que PHP remplacera automatiquement automatiquement les points dans les noms par des underscores.

C'est de http://ca.php.net/variables.external .

En outre, selon ce commentaire ces autres caractères sont convertis en caractères de soulignement :

La liste complète des caractères de nom de champ que PHP convertit en _ (underscore) est la suivante (pas seulement le point) :

  • chr(32) ( ) (espace)
  • chr(46) (.) (point)
  • chr(91) ([) (crochet ouvert)
  • chr(128) - chr(159) (divers)

Il semble donc que vous soyez coincé avec cela, vous devrez donc reconvertir les underscores en points dans votre script à l'aide des éléments suivants suggestion de dawnerd (J'utiliserais simplement str_replace cependant.)

63voto

crb Points 4631

Question à laquelle on a répondu depuis longtemps, mais il existe en fait une meilleure réponse (ou solution de contournement). PHP vous permet, au niveau du flux d'entrée brut Vous pouvez donc faire quelque chose comme ça :

$query_string = file_get_contents('php://input');

qui vous donnera le tableau $_POST au format query string, les périodes comme il se doit.

Vous pouvez ensuite l'analyser si vous en avez besoin (comme indiqué dans l'exemple ci-dessous). Commentaire du POSteur )

<?php
// Function to fix up PHP's messing up input containing dots, etc.
// `$source` can be either 'POST' or 'GET'
function getRealInput($source) {
    $pairs = explode("&", $source == 'POST' ? file_get_contents("php://input") : $_SERVER['QUERY_STRING']);
    $vars = array();
    foreach ($pairs as $pair) {
        $nv = explode("=", $pair);
        $name = urldecode($nv[0]);
        $value = urldecode($nv[1]);
        $vars[$name] = $value;
    }
    return $vars;
}

// Wrapper functions specifically for GET and POST:
function getRealGET() { return getRealInput('GET'); }
function getRealPOST() { return getRealInput('POST'); }
?>

Très utile pour les paramètres OpenID, qui contiennent à la fois '.' et '_', chacun ayant une certaine signification !

31voto

scipilot Points 344

En mettant en évidence une réponse réelle de Johan dans un commentaire ci-dessus - j'ai juste enveloppé tout mon message dans un tableau de niveau supérieur qui contourne complètement le problème sans aucun traitement lourd requis.

Dans le formulaire, vous faites

<input name="data[database.username]">  
<input name="data[database.password]">  
<input name="data[something.else.really.deep]">  

au lieu de

<input name="database.username"> 
<input name="database.password"> 
<input name="something.else.really.deep">  

et dans le post handler, il suffit de le déballer :

$posdata = $_POST['data'];

Pour moi, il s'agissait d'un changement de deux lignes, car mes vues étaient entièrement modélisées.

FYI. J'utilise des points dans mes noms de champs pour éditer des arbres de données groupées.

19voto

Rok Kralj Points 11593

Vous voulez une solution qui est conforme aux normes, et travaille avec réseaux profonds (par exemple : ?param[2][5]=10 ) ?

Pour corriger toutes les sources possibles de ce problème, vous pouvez appliquer au tout début de votre code PHP :

$_GET    = fix( $_SERVER['QUERY_STRING'] );
$_POST   = fix( file_get_contents('php://input') );
$_COOKIE = fix( $_SERVER['HTTP_COOKIE'] );

Le fonctionnement de cette fonction est une idée soignée qui m'est venue pendant mes vacances d'été 2013. Ne vous laissez pas décourager par une simple regex, elle récupère simplement tous les noms de requêtes, les encode (afin que les points soient préservés), et utilise ensuite une fonction normale parse_str() fonction.

function fix($source) {
    $source = preg_replace_callback(
        '/(^|(?<=&))[^=[&]+/',
        function($key) { return bin2hex(urldecode($key[0])); },
        $source
    );

    parse_str($source, $post);

    $result = array();
    foreach ($post as $key => $val) {
        $result[hex2bin($key)] = $val;
    }
    return $result;
}

p.s. : Si vous utilisez cette solution dans votre projet, veuillez attribuer la fonction avec @author Rok Kralj .

7voto

Jack Points 88446

Cela se produit parce qu'un point est un caractère non valide dans le nom d'une variable, l'option raison pour lequel il n'existe pas de solution facile (pour l'instant), car il est profondément ancré dans l'implémentation de PHP.

En attendant, vous pouvez contourner ce problème en.. :

  1. L'accès aux données brutes de la requête se fait soit par php://input pour les données POST ou $_SERVER['QUERY_STRING'] pour les données GET
  2. Utilisation d'une fonction de conversion.

La fonction de conversion ci-dessous (PHP >= 5.4) encode les noms de chaque paire clé-valeur en une représentation hexadécimale, puis effectue un traitement régulier. parse_str() une fois fait, il rétablit les noms hexadécimaux dans leur forme originale :

function parse_qs($data)
{
    $data = preg_replace_callback('/(?:^|(?<=&))[^=[]+/', function($match) {
        return bin2hex(urldecode($match[0]));
    }, $data);

    parse_str($data, $values);

    return array_combine(array_map('hex2bin', array_keys($values)), $values);
}

// work with the raw query string
$data = parse_qs($_SERVER['QUERY_STRING']);

Ou :

// handle posted data (this only works with application/x-www-form-urlencoded)
$data = parse_qs(file_get_contents('php://input'));

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X