IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

CodeGear et MySQL AB collaborent pour intégrer MySQL aux produits Delphi

Le , par tse_jc

0PARTAGES

Bonjour à tous,
La question est pourtant simple, mais j’ai pu constater qu’aucune réponse n’était disponible sur aucun forum à cette question à part dans un contexte de requête préparée.
Il est triste de constater de l’utilisation généralisée des requêtes préparées en programmation web, et ce, pour plusieurs raisons.
L’argument universel des Injections SQL
Ceci est un très mauvais argument, car comme je l’ai déjà expliqué ici sur développez.net Lorsque l’on effectue un contrôle systématique de type de contenu et de définition de chaque variable publique de son application, l’injection n’y est plus possible. (…) Donc à partir du moment où on vérifie soit même, pas besoin de PDO pour le faire quand surtout il n’est pas capable de contrôler la pertinence des données reçues vis-à-vis du modèle.

Il faut rappeler également que la mise en place d’une requête préparée est coûteuse en terme de ressources et le faire de plus au niveau d’un driver externe au SGBDR est moins pertinent que de le faire au sein du SGBDR lui-même (qui est le plus apte à en gérer les ressources associées) dans une procédure stockée par exemple.
De plus, à moins de devoir exécuter cette requête un grand nombre de fois avec des paramètres différents, il n’y a aucun intérêt technique à privilégier cette approche.

Un argument supplémentaire à cela: j'ai été surpris et déçu de constater sur les drivers PDO PHP 7 natifs pour SQL Server 2014 et 2016 qu'une requête appelant une procédure stockée sans utiliser de requête préparée au niveau PHP, avait recours à une requête préparée au niveau du driver. Ce constat à été fait au niveau du SQL Profiler dans SSMS.

Ceci étant dit, voyons comment récupérer notre variable de type OUTPUT de notre procédure stockée dans PDO d’une manière « normale » ou « classique » si vous préférez.
Voici la procédure stockée qui va nous servir d’exemple

Code T-SQL : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 
USE MY_DATABASE; 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
IF OBJECT_ID('MON_SCHEMA.P_PROCEDURE_EXEMPLE') IS NOT NULL 
DROP PROCEDURE MON_SCHEMA.P_PROCEDURE_EXEMPLE; 
GO 
CREATE PROCEDURE MON_SCHEMA.P_PROCEDURE_EXEMPLE 
  @user_id int = 0, 
  @last_infos [varchar](50)='' OUTPUT 
AS 
BEGIN 
  SET NOCOUNT ON; 
  SELECT @last_infos=ma_colonne FROM MON_SCHEMA.MA_TABLE WHERE user_id=@user_id; 
  IF @last_infos IS NULL  
     RETURN 0; 
 RETURN 1; 
END 
GO

Vous l’aurez compris ici, le but étant de récupérer la valeur de la variable @last_infos dans PDO. Pour rappel, on ne peut ici la placer au niveau du RETURN car seul un entier peut être retourné par une procédure stockée sous SQL SERVER.
Voici un exemple de comment procéder pour récupérer l’information qui nous intéresse.
Code PHP : Sélectionner tout
1
2
3
4
  
function get_informations($user_id){ 
$PDOInstance=new PDO(DSN_infos, USER_login, PWD_user); 
$PDOInstance->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION); // facultatif selon vos préférences
Code PHP : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
 
$user_id=intval($user_id); 
$query="DECLARE @last_infos varchar(250) 
             EXEC MON_SCHEMA.P_PROCEDURE_EXEMPLE $user_id,@last_infos=@last_infos OUTPUT 
             SELECT @last_infos"; 
try{ 
   $db_result = $PDOInstance->query($query)->fetchAll(PDO::FETCH_NUM); 
} catch (Exception $e){ 
   if (strpos($e->getMessage(),'SQLSTATE[IMSSP]')!==false){return $db_result;} 
  print ' @Err:[GET_informations] '.$e->getmessage();exit; 
} 
return $db_result; 
} 
Voilà. Vous voyez, il n’y a rien de difficile.
Bonne journée à vous.

Une erreur dans cette actualité ? Signalez-nous-la !