Utiliser superglobals directement bon ou mauvais en PHP?
donc, je ne viens pas d'un énorme fond PHP-et je me demandais si dans un code bien formé, on devrait utiliser les 'superglobaux' directement, par exemple au milieu d'une certaine fonction dire $_SESSION['x'] = 'y';
ou si, comme je le ferais normalement avec des variables, il est préférable de les envoyer comme arguments qui peuvent être utilisés à partir de là, E. g:
class Doer {
private $sess;
public function __construct(&$sess) {
$this->sess =& $sess;
}
}
$doer = new Doer($_SESSION);
et puis utiliser la version Doer->sess
de l'intérieur de Doer et tel. (L'avantage de cette méthode est qu'elle indique clairement que Doer
utilise $ _SESSION.)
Quelle est l'approche de conception PHP acceptée pour ce problème?
5 réponses
je fais comme pour l'envelopper $_SESSION
, $_POST
, $_GET
, et $_COOKIE
dans la programmation orientée objet structures.
j'utilise cette méthode pour centraliser le code qui gère l'assainissement et la validation, tous les contrôles nécessaires isset ()
, les nonces, les paramètres setcookie
, etc. Il permet également au code client d'être plus lisible (et me donne l'illusion qu'il est plus maintenable).
il peut être difficile d'imposer l'utilisation de ce type de structure, surtout s'il y a plusieurs codeurs. Avec $_GET
, $_POST
, et $_COOKIE
(je crois), votre code d'initialisation peut copier les données, puis détruire le superglobal. Peut-être qu'un destructeur intelligent pourrait rendre cela possible avec $_SESSION (essuyer $_SESSION sur le chargement, l'écrire à nouveau dans le destructeur), bien que je n'ai pas essayé.
Je n'utilise généralement aucune de ces techniques d'exécution, cependant. Après s'être habitué, voir $_SESSION
en code à l'extérieur le cours a l'air bizarre, et je travaille surtout en solo.
MODIFIER
Voici un exemple de code client, au cas où ça aiderait quelqu'un. Je suis sûr que regarder l'un des cadres principaux vous donnerait de meilleures idées...
$post = Post::load ();
$post->numeric ('member_age');
$post->email ('member_email');
$post->match ('/regex/','member_field');
$post->required ('member_first_name','member_email');
$post->inSet ('member_status',array('unemployed','retired','part-time','full-time'));
$post->money ('member_salary');
$post->register ('member_last_name'); // no specific requirements, but we want access
if ($post->isValid())
{
// do good stuff
$firstName = $post->member_first_name;
}
else
{
// do error stuff
}
Post et ses amis dérivent tous d'une classe de base qui implémente le code de validation de base, en ajoutant leur propre fonctionnalité spécifique comme les tokens de forme, cookie de session configuration, peu importe.
à l'interne, la classe contient une collection de données valides extraites de $_POST
comme les méthodes de validation sont appelées, puis les retourne comme propriétés en utilisant une méthode magique __get
. Les champs défectueux ne sont pas accessibles de cette façon. Mes méthodes de validation (sauf required
) n'échouent pas sur les champs vides, et beaucoup d'entre elles utilisent func_get_args
pour leur permettre d'opérer sur plusieurs champs à la fois. Certaines des méthodes (comme money
) traduisez automatiquement les données en types de valeur personnalisés.
dans le cas d'erreur, j'ai un moyen de transformer les données dans un format qui peut être enregistré dans la session et utilisé pour pré-remplir le formulaire et mettre en évidence les erreurs après avoir redirigé vers le formulaire original.
une façon d'améliorer cela serait de stocker les informations de validation dans une classe de formulaire qui est utilisée pour rendre la validation côté client de forme et de puissance, ainsi que le nettoyage des données après soumission.
modifier le contenu du superglobal est considéré comme une mauvaise pratique. Bien qu'il n'y ait rien de mal à cela, surtout si le code est 100% sous votre contrôle, il peut conduire à des effets secondaires inattendus, surtout lorsque vous considérez le code source mixte. Par exemple, si vous faites quelque chose comme ceci:
$_POST['someval'] = mysql_real_escape_string($_POST['someval']);
vous pourriez vous attendre à ce que partout où PHP rend cette 'someval' disponible soit également modifié, mais ce n'est pas le cas. La copie en $_REQUEST['someval']
sera inchangé et toujours la version originale" non sécuritaire". Cela pourrait conduire à une vulnérabilité d'injection involontaire si vous faites tout votre échappatoire sur $_POST, mais une bibliothèque ultérieure utilise $_REQUEST et suppose qu'elle a déjà été échappée.
en tant Que tel, même si vous pouvez les modifier, il est préférable de traiter les superglobales en lecture seule. Si vous devez modifier les valeurs, maintenez vos propres copies parallèles et faites toutes les méthodes d'enrubannage/accès nécessaires pour maintenir cette copie.
je sais que cette question est vieux, mais j'aimerais ajouter une réponse.
les classes de mario pour gérer les entrées est génial.
je préfère envelopper les superglobales d'une façon ou d'une autre. Il peut rendre votre code beaucoup plus facile à lire et conduire à une meilleure maintenabilité.
par exemple, il y a un code à mon travail actuel que je déteste! Les variables de session sont tellement utilisées que vous ne pouvez pas changer l'implémentation de façon réaliste sans affecter radicalement l'ensemble du site.
par exemple,
disons que vous avez créé une classe de Session spécifique à votre application.
class Session
{
//some nice code
}
vous pourriez écrire quelque chose comme ce qui suit
$session = new Session();
if( $session->isLoggedIn() )
{
//do some stuff
}
par opposition à ce
if( $_SESSION['logged'] == true )
{
//do some stuff
}
cela semble un peu anodin mais c'est important pour moi. Dire que dans le futur je décide que je veux changer la nom de l'index de "logged" à "loggedIn".
je dois maintenant aller à chaque endroit dans l'application que la variable session est utilisée pour changer cela. Ou, je peux le laisser et trouver un moyen de maintenir les deux variables.
ou si je veux vérifier que cet utilisateur est un utilisateur administrateur et est connecté? Je pourrais vérifier deux variables différentes dans la session pour cela. Mais, à la place je pourrais l'encapsuler dans une méthode et raccourcir mon code.
cela aide les autres programmeurs à regarder votre code parce qu'il devient plus facile à lire et ils n'ont pas à 'penser' autant quand ils regardent le code. Ils peuvent aller de la méthode et de voir qu'il n'y a qu'UNE seule façon d'avoir un utilisateur connecté. Il vous aide aussi car si vous vouliez faire de la "enregistrées" dans un contrôle plus complexe, vous n'avez qu'à aller à un endroit pour changer au lieu d'essayer de faire mondial trouve avec votre IDE et d'essayer de changer cette façon.
Encore une fois, c'est un exemple trivial, mais selon la façon dont vous utilisez la session, cette voie d'utilisation des méthodes et des classes pour protéger l'accès pourrait rendre votre vie beaucoup plus facile.
Je ne recommande absolument pas de passer superglobal par référence. Dans votre classe, il n'est pas clair que ce que vous modifiez est une variable de session. Aussi, gardez à l'esprit que $_SESSION est disponible partout en dehors de votre classe. C'est tellement mal du point de vue orienté objet de pouvoir modifier une variable à l'intérieur d'une classe à partir de l'extérieur de cette classe en modifiant une variable qui n'est pas liée à la classe. Ayant attribut public est considéré comme une mauvaise pratique, c'est encore pire.
ce N'est pas une bonne utilisation de PHP.
$_SESSION variables directement:
$id = $_SESSION['id'];
$hash = $_SESSION['hash'];
etc.