<?xml version="1.0" encoding="ISO-8859-1"?>

<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
	<channel>
		<title>Forum du club des développeurs et IT Pro - Blogs - Architectures web hautes performances en bases de données épaisses par tse_jc</title>
		<link>https://www.developpez.net/forums/blogs/384137-tse_jc/</link>
		<description>Developpez.com, le Club des Développeurs et IT Pro</description>
		<language>fr</language>
		<lastBuildDate>Sat, 02 May 2026 08:29:38 GMT</lastBuildDate>
		<generator>vBulletin</generator>
		<ttl>15</ttl>
		<image>
			<url>https://forum.developpez.be/images/misc/rss.jpg</url>
			<title>Forum du club des développeurs et IT Pro - Blogs - Architectures web hautes performances en bases de données épaisses par tse_jc</title>
			<link>https://www.developpez.net/forums/blogs/384137-tse_jc/</link>
		</image>
		<item>
			<title><![CDATA[[PHP] Comment gérer correctement les sessions applicatives en PHP et le problème des cookies]]></title>
			<link>https://www.developpez.net/forums/blogs/384137-tse_jc/b9708/php-gerer-correctement-sessions-applicatives-php-probleme-cookies/</link>
			<pubDate>Tue, 14 Jul 2020 15:13:26 GMT</pubDate>
			<description>*1. Le problème des cookies...</description>
			<content:encoded><![CDATA[<blockquote class="blogcontent restore"><b>1. Le problème des cookies dans la gestion des sessions applicatives PHP<br />
<br />
</b>Pour aller droit au but, placer les cookies au centre de votre stratégie de gestion des sessions PHP pour vos applications web est une très mauvaise idée et reste à proscrire. En voici les principales raisons.<br />
- Un cookie est stocké au niveau client applicatif et donc à l'extérieur de l'environnement de gestion d'une application web qui se situe côté serveur.<br />
- Étant dans un environnement n tiers, chaque tiers ne peut faire confiance à ce qu'il reçoit de l'autre. C'est la règle fondamentale à appliquer au niveau sécuritaire.<br />
En conséquence, ce qui est placé du côté navigateur client relève du domaine &quot;public&quot; pour votre application, ce qui ne peut être décemment considéré comme source de confiance pour authentifier un utilisateur au sein de votre applicatif.<br />
<br />
<b>Rappel :</b> Un serveur PHP utilise déjà un cookie en gestion interne pour authentifier un utilisateur sur le serveur web. C'est une obligation technique, il reste incontournable et reste transparent pour tout le monde. Il ne sert à rien à rajouter un cookie applicatif qui reste une aberration à la vue de ce qui précède.<br />
<br />
Utilisez des cookies sur vos sites, à des fins marketing et de prospection, en respectant la réglementation, est une façon justifiée d'utiliser des cookies, et je vous recommande vivement de vous en tenir à cette utilisation professionnellement parlant.<br />
<br />
<b>2. Les besoins techniques</b><div style="margin-left:40px"><b>a. Une session PHP ne doit pas être trop longue</b></div><div style="margin-left:80px">Plusieurs raisons à cela. Comme il est expliqué dans la documentation PHP, le module de sessions PHP n'est pas protégé naturellement contre les attaques au niveau des sessions, notamment via javascript. Plus une session est longue, plus elle a de chances d'être interceptée et utilisée pour accéder à des informations normalement protégées.</div><div class="bbcode_container">
	<div class="bbcode_quote">
		<div class="quote_container">
			<div class="bbcode_quote_container"></div>
			
				<div style="margin-left:40px"><b>Principe n°1<br />
La première chose donc pour limiter la surface d'attaque de nos applications en PHP, consistera à faire en sorte d'avoir des sessions relativement restreintes dans la durée.</b></div>
			
		</div>
	</div>
</div><div style="margin-left:80px">Seulement dans une application web d'entreprise, les utilisateurs détestent devoir se reconnecter 50 fois dans la même journée, surtout si le mot de passe est compliqué. Idéalement, il faut éviter de le faire plus de 2 fois par jour. Le plus généralement constaté, après discussion avec des responsables en entreprise sur les enjeux au niveau sécurité, il est généralement souhaité une période de session sans interruption comprise entre 3 et 4h.<br />
<br />
Une des premières solutions se présentant à nous pour résoudre ce problème et atteindre ce minima de 3 à 4 heures est de jouer sur la configuration de PHP au niveau du serveur afin de repousser le timeout de connexion PHP et la période du Garbage collector à cette limite. Le seul avantage est la simplicité de gestion ici, mais voilà : les désavantages sont très nombreux. Parmi les principaux, citons :</div><br />
<ul><li style="margin-left: 80px">La réduction de la capacité de monter en charge du serveur HTTP, et la réduction drastique du nombre de connexions concurrentes pouvant être gérées par le serveur. En effet l’optimisation d’un serveur web passe avant tout par la réduction optimale du temps de réponse d’un serveur à une requête HTTP/HTTPS afin d’en libérer les ressources au plus tôt et permettre à une autre requête de se présenter. <br /></li><li style="margin-left: 80px">On ne respecte pas le principe n°1 pour réduire la surface d’attaque de notre application. </li></ul><br />
<div class="bbcode_container">
	<div class="bbcode_quote">
		<div class="quote_container">
			<div class="bbcode_quote_container"></div>
			
				<div style="margin-left:40px"><b>Principe n°2<br />
Les vieilles sessions doivent être maintenues jusqu'à leur prise en charge par le gc (garbage collector)<br />
</b>Ne pas faire ainsi s'est s'exposer à des comportements instables voire erratiques dans un contexte concurrentiel.</div>
			
		</div>
	</div>
</div><div class="bbcode_container">
	<div class="bbcode_quote">
		<div class="quote_container">
			<div class="bbcode_quote_container"></div>
			
				<div style="margin-left:40px"><b>Principe n°3<br />
session_regenerate_id(true) et session_destroy() ne doivent jamais être utilisées ensemble pour une session active.<br />
</b>Ce principe est directement issu du principe précédent.</div>
			
		</div>
	</div>
</div><div style="margin-left:40px"><b>b. Gérer les sessions via un double axe au minimum : PHP + Base de données et idéalement sur un axe triple : PHP + DB + Cache Redis<br />
</b>Une fois éliminé la solution précédente qui fait le travail certes, mais qui n'est pas satisfaisante techniquement (dans un contexte d'optimisation d'infrastructure) et surtout au niveau sécurité, il s'impose de suite la gestion selon un axe double.<br />
<br />
<b>Axe double : PHP + DB<br />
</b>Si on souhaite garder des sessions PHP à durée standard dans une configuration standard par défaut pour le moins d’un côté et satisfaire à notre clientèle, en leur permettant de ne pas se reconnecter avant 3 à 4 heures de travail, tout en ne travaillant pas sur leur poste de travail en mode continu, mais permettre un travail effectué par intermittence et donc avec des périodes d’inactivité incluses dans ce laps de temps imparti, on n’a pas le choix :<br />
<br />
=&gt;<b> On gère la durée de connexion applicative en base de données et on gère les sessions techniques pour traiter les requêtes clients sur le serveur applicatif du côté PHP.<br />
</b><br />
On peut donc déduire d'un tel scénario les évènements suivants :</div><br />
<ul><li style="margin-left: 40px">Une session applicative aura plusieurs id de session PHP différentes au cours de sa vie. <br /></li><li style="margin-left: 40px">Le gc va intervenir plusieurs fois au cours de la vie de notre session applicative. <br /></li><li style="margin-left: 40px">A chaque intervention du gc on va devoir maintenir le contenu de la session PHP <br /></li><li style="margin-left: 40px">le gc va intervenir sur des sessions passées et obsolètes ( pas de problème de transmission de session), et peut intervenir aussi sur la session en cours en cas de période d'inactivité trop longue de l'utilisateur (problème de transmission de session). </li></ul><br />
<div style="margin-left:40px"><br />
<b>Gestion du problème de transmission du contenu de session<br />
</b>En cas de période d'inactivité trop longue de l'utilisateur, il y a un risque de perte de contenu de session, et ce, d'autant plus que la période du gc fixé est faible. Il faut donc stocker le contenu sérialisé des informations de session ailleurs que dans le système de gestion de sessions de PHP et ailleurs que dans un cookie bien évidemment. Une des meilleures pratique qui est recommandée dans la documentation de PHP est de l'écrire dans un fichier sur disque hors dossier de sessions donc.<br />
<br />
<b>=&gt; L'endroit ou l'on va sauvegarder ces informations de session constitue donc le 3e axe de gestion.<br />
<br />
</b>Si l'on reste ici sur un paradigme PHP+DB, on devra stocker l'information en DB.<br />
<br />
<b>Rappel de ce qui est stocké au niveau session<br />
<br />
</b></div><br />
<ul><li style="margin-left: 40px">Il n'y a pas de variable globale stockée directement en session pour préserver les principes de la POO. <br /></li><li style="margin-left: 40px">On recommande donc d'y stocker des objets sérialisés. En général, comme on l'a vu dans un précédent billet, il y a en a au moins 3 : une classe utilisateur, une classe connexion et une classe module applicatif. </li></ul><br />
<div style="margin-left:40px"><br />
Les données de type utilisateur et connexion sont limitées et peuvent être restituées par la base de données. Il s'agit tout au plus d'une dizaine de variables selon l'applicatif concerné. <br />
Les données de type module applicatif, quant à elles, sont spécifiques à la navigation de l'utilisateur et de ce qu'il a fait au cours de sa session de travail. Il y aura donc dans ce type de données des données calculées spécifiques mises en cache. Elles sont de nature non prédictive et il peut être très coûteux de les recharger à partir de la base de données. Pour le moins, l'expérience utilisateur s'en ferait sentir dans un contexte de charge au niveau des performances applicatives, si l'on décidait de ne pas maintenir ces données dans ce contexte de transmission de session.<br />
<br />
On pourrait bien évidemment scinder la gestion des deux premiers types de données avec le troisième. Dans un tel scénario qui obligerait à stocker en variable globale cette fois un tableau sérialisé des modules consultés par l'utilisateur et à gérer spécifiquement leur contenu à part hors db pour éviter de la solliciter et garder une capacité de montée en charge applicative optimisée, il y aurait un surcoût de gestion applicatif au prix de quelques efforts, mais cela resterait à prototyper au niveau performances pour se faire une bonne idée de la chose. Toujours dans un tel scénario, le rechargement des deux premiers types de données à partir de la base, bien que très limité et localisé, provoquerait une augmentation de charge préjudiciable à l'applicatif.<br />
<br />
<b>Préférer/Privilégier une gestion à trois axes<br />
</b>Du plus performant au moins performant, voici les choix à privilégier dans un tel contexte de gestion de session.<br />
</div><br />
<ul><li style="margin-left: 40px"><b>Sauvegarde de l'intégralité du cache de session (3 types de données) dans REDIS</b> </li></ul><br />
<div style="margin-left:80px">Le cache étant très rapide et géré en mémoire, il n'y aura pas plus performant. Attention cependant, gérer les sessions PHP directement dans REDIS n'a rien à voir avec ce qui est exposé ici, puisque le cache de session PHP dans REDIS serait soumis aux mêmes règles du gc que s'il était géré de façon traditionnelle. Cette solution à l'avantage en plus, d'être transparent techniquement dans le cloud.</div><br />
<ul><li style="margin-left: 40px"><b>Sauvegarde de l'intégralité du cache de session (3 types de données) sur disque</b> </li></ul><br />
<div style="margin-left:80px">Solution à privilégier par défaut donc surtout lorsqu'on est pas encore à l'aise avec la gestion d'un cache spécifique comme REDIS.</div><div style="margin-left:40px"><br />
<b>Note<br />
</b>Que cela soit avec REDIS ou directement sur Disque, rien n'empêche d'utiliser un plugin PHP de binarisation de données sérialisées (plugin compilé sur serveur) qui apporte un gain de performances notable dans un contexte de forte charge applicative et qui a fait ses preuves, même si cela ajoute un traitement supplémentaire des données concernées. Un tel système est implémentable sur Microsoft Azure.</div><br />
<b>2. Algorithme d'implémentation<br />
</b>Je recommande de diviser votre algorithme en deux parties distinctes. La première concerne la connexion initiale de l'utilisateur, lorsqu'il se connecte à l'application. La seconde concerne le ping de connexion au moment où une requête utilisateur est envoyée au serveur (rafraichissement du navigateur, requête ajax, ...). On préfèrera travailler ainsi en mode passif (pull) sur action de l'utilisateur pour optimiser la capacité de montée en charge du serveur (on libère les ressources au plus tôt) plutôt qu'en push, qui consomme des ressources en permanence et limite potentiellement le nombre d'accès concurrentiels à l'applicatif beaucoup plus vite.<br />
<br />
Il est probable voire fortement probable (je ne l'espère pas) que vous soyez obligé de mettre en place des variables de gestion qui n'existaient pas jusqu'à maintenant dans votre environnement de gestion de sessions applicatif.<br />
Voici celles que j'implémente dans mes solutions et qui me paraissent incontournables et minimales.<br />
<br />
<ul><li style="">datetime de connexion</li><li style="">datetime dernière requête serveur</li><li style="">session_id() PHP</li><li style="">Informations navigateur utilisateur ayant initié la connexion</li><li style="">Adresse IP utilisateur connecté ayant initié la connexion</li><li style="">Id technique de l'utilisateur connecté</li><li style="">Les données sérialisées à maintenir</li><li style="">La durée maximale de session applicative</li><li style="">La durée de vie configurée de votre gc </li></ul><br />
<br />
<b>Remarques / Conseils<br />
</b>Essayez de ne conserver et de gérer au niveau des variables de gestion que le strict nécessaire pour offrir un service de qualité et sécurisé, tout en ayant la possibilité d'auditer sereinement vos sessions en cas d'anomalie constatée. Trop de volumétrie au niveau de la base a aussi ses conséquences et ne reste pas anodine.<br />
<br />
À vous d'implémenter vos algorithmes :)</blockquote>

]]></content:encoded>
			<dc:creator>tse_jc</dc:creator>
			<guid isPermaLink="true">https://www.developpez.net/forums/blogs/384137-tse_jc/b9708/php-gerer-correctement-sessions-applicatives-php-probleme-cookies/</guid>
		</item>
		<item>
			<title><![CDATA[SQL SERVER 2012+ : Récupération paramètre OUTPUT d'une procédure stockée avec PDO en PHP]]></title>
			<link>https://www.developpez.net/forums/blogs/384137-tse_jc/b3330/sql-server-2012p-recuperation-parametre-output-d-procedure-stockee-pdo-php/</link>
			<pubDate>Sat, 08 Jul 2017 14:32:31 GMT</pubDate>
			<description>Bonjour à tous, 
La question...</description>
			<content:encoded><![CDATA[<blockquote class="blogcontent restore"><font color="#3A3A3A">Bonjour à tous,</font><br />
<font color="#3A3A3A">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.<br />
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.<br />
</font><font color="#ffa500"><br />
</font><font color="#ff8c00"><b>L’argument universel des Injections SQL</b></font><font color="#3A3A3A"><br />
Ceci est un très mauvais argument, car comme je l’ai déjà <a href="http://www.developpez.net/forums/d1243430-3/php/php-sgbd/php-mysql/securite-php-mysql-injections-sql/" target="_blank">expliqué ici sur développez.net</a> <b>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.<br />
</b><br />
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.<br />
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.<br />
<br />
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.<br />
</font><br />
<font color="#3A3A3A">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.</font><br />
<font color="#3A3A3A">Voici la procédure stockée qui va nous servir d’exemple<br />
<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code T-SQL :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:204px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="33"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br /></div></td><td valign="top"><pre style="margin: 0">
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</pre></td></tr></table></pre>
</div></font><br />
<font color="#3A3A3A">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.</font><br />
<font color="#3A3A3A">Voici un exemple de comment procéder pour récupérer l’information qui nous intéresse.<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code PHP :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:84px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="26"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br />4<br /></div></td><td valign="top"><pre style="margin: 0">&nbsp;
<span style="color: #0000ff;">function</span> get_informations<span class="br0">&#40;</span><span style="color: #339933;">$user_id</span><span class="br0">&#41;</span><span class="br0">&#123;</span>
<span style="color: #339933;">$PDOInstance</span>=<span style="color: #0000ff;">new</span> PDO<span class="br0">&#40;</span>DSN_infos, USER_login, PWD_user<span class="br0">&#41;</span>;
<span style="color: #339933;">$PDOInstance</span>-&gt;setAttribute<span class="br0">&#40;</span>PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION<span class="br0">&#41;</span>; <span style="color: #808080;">// facultatif selon vos pr&eacute;f&eacute;rences</span></pre></td></tr></table></pre>
</div></font><div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code PHP :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:192px;"><table cellspacing="0" cellpadding="0"><tr><td valign="top" width="33"><div style="border: 1px dashed gray; padding-left: 5px; padding-right: 5px; margin-right: 5px; text-align: right; font-family: monospace">1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br /></div></td><td valign="top"><pre style="margin: 0">
<font color="#3A3A3A">$user_id=intval($user_id);
$query=&quot;DECLARE @last_infos varchar(250)
             EXEC MON_SCHEMA.P_PROCEDURE_EXEMPLE $user_id,@last_infos=@last_infos OUTPUT
             SELECT @last_infos&quot;;
try{
   $db_result = $PDOInstance-&gt;query($query)-&gt;fetchAll(PDO::FETCH_NUM);
} catch (Exception $e){
   if (strpos($e-&gt;getMessage(),'SQLSTATE[IMSSP]')!==false){return $db_result;}
  print ' @Err:[GET_informations] '.$e-&gt;getmessage();exit;
}
return $db_result;
}
</font></pre></td></tr></table></pre>
</div><font color="#3A3A3A">Voilà. Vous voyez, il n’y a rien de difficile.</font><br />
<font color="#3A3A3A">Bonne journée à vous.</font></blockquote>

]]></content:encoded>
			<dc:creator>tse_jc</dc:creator>
			<guid isPermaLink="true">https://www.developpez.net/forums/blogs/384137-tse_jc/b3330/sql-server-2012p-recuperation-parametre-output-d-procedure-stockee-pdo-php/</guid>
		</item>
		<item>
			<title>AJAX : Comment structurer son code et créer un contrôleur spécifique en PHP</title>
			<link>https://www.developpez.net/forums/blogs/384137-tse_jc/b593/ajax-structurer-code-creer-controleur-specifique-php/</link>
			<pubDate>Mon, 29 Jun 2015 12:42:56 GMT</pubDate>
			<description>Bonjour à tous, 
 
Sujet un...</description>
			<content:encoded><![CDATA[<blockquote class="blogcontent restore">Bonjour à tous,<br />
<br />
Sujet un peu vaste que j'aborde ici, mais qui me semble fondamental tant pour assurer une bonne structure applicative web que pour sa maintenabilité dans le temps. J'ai vu en effet trop de code de sites ou d'applications web, dans lesquels la bonne organisation et structuration de leur code dans un contexte de gestion d'appels Ajax, était vraiment absente. Ce que je trouve assez regrettable.<br />
Aujourd'hui,<b> l'Ajax est une technologie incontournable dans les applications web</b> pour plusieurs raisons dont voici à mon sens les principales :<br />
 <br />
<ul><li style="">la qualité de l'expérience utilisateur ;</li><li style="">une meilleure segmentation et répartition de charge applicative sur le réseau ;</li><li style="">la gestion des caches client et serveur optimisée, plus fine et plus efficace.</li></ul><br />
<br />
Avant d'entrer dans le vif du sujet, je tiens à préciser que je ne vais pas parler dans ce billet du côté client et donc de la partie JavaScript de la gestion Ajax. Ce n'est pas l'objet de ce billet d'une part, et, d'autre part, j'estime qu'une telle structuration de code et d'optimisation est étroitement dépendante de l'architecture et des technologies spécifiques choisies et utilisées pour une application web côté client. Je dirai également pour finir, que malgré cette diversité de choix possibles côté client, tant au niveau architecture logicielle que de la structure et gestion des divers processus à ce niveau, il reste possible de définir des &quot;constantes&quot; de gestion qui peuvent se standardiser quel que soit le contexte. J'aurais l'occasion d'y revenir plus en détail dans un autre billet.<br />
<br />
<b>1) Pourquoi est-il important de structurer son code côté serveur dans un contexte Ajax ?<br />
</b>Sans vouloir jouer les rabats-joie, et revenir sur les fondements de la programmation orientée objet ou sur l'intérêt du patron MVC dans la programmation pour justifier de cette importance, voici à mon avis le pourquoi de ne pas négliger cette structuration dans une application web.<br />
<br />
Dans une application web il est commun de considérer deux types de contrôleurs : le Front Controller, qui gère les requêtes utilisateurs passées au niveau de l'URL et le contrôleur applicatif qui gère de façon générale les interactions entre la vue et le modèle. <br />
Dans les anciennes applications web et encore parmi certaines d'aujourd'hui qui ne sont pas conçues autour d'Ajax, toutes les requêtes utilisateurs passent par l'url et donc par un Front Controller qui centralise tout. Dans un contexte Ajax, ce Front Controller n'est plus seul dans la gestion de ces requêtes utilisateur. Il les partage avec ce que j'appelle tout simplement un Controleur Ajax, qui consistue de fait et de façon générale un Front Controller asynchrone. <br />
En résumé donc, dans une application web Ajax, on peut affirmer que l'on a non plus un Front Controller unique et global mais deux Front Controller : Un Front Controller synchrone et un Front Controller Asynchrone, qui se partagent à eux deux l'ensemble des requêtes utilisateur sur le serveur.<br />
En tant que controleur, le code s'y trouvant, se doit donc d'être structuré de façon logique et claire, je pense que tout le monde en conviendra.<br />
<br />
<b>2) Comment créer un contrôleur Ajax spécifique en PHP ?<br />
</b>Tout d'abord, je rappelle de la nécessité de bien séparer le controleur applicatif du Front Controller dans un contexte MVC. Le client / la vue ne doit pas accéder au contrôleur applicatif directement ne serait-ce que par sécurité. On valide la requête et ses paramètres en type et en nature. Et lorsque les données reçues sont conformes, on les transmet au contrôleur applicatif en charge de la requête à traiter. Il est important dans une architecture n-tiers, que chaque tiers applicatif ne fasse pas confiance au premier abord à ce qu'il reçoit de l'autre. C'est d'ailleurs la responsabilité primaire du serveur objet dans une architecture web en bases de données épaisses, que de valider et de mettre en forme les requêtes et données du client auprès du SGBDR qui va les traiter. <br />
Il est important également de ne pas faire du contrôleur Ajax et du contrôleur applicatif correspondant, un seul et unique controleur, même si la tentation peut être grande pour certains. En effet un controleur applicatif spécifique à la responsabilité de gestion du cache des données associées à cette spécificité, responsabilité qu'un Front Controller n'a pas et ne doit pas avoir.<br />
<br />
Voici donc la solution que je vous propose et que je vous recommande pour structurer un tel contrôleur au sein de votre application. Même si après lecture la solution paraîtra évidente à certains, elle ne l'est pas toujours.<br />
<br />
<img src="https://www.developpez.net/forums/attachments/p181754d1435526930/autres-langages/autres-langages/corba/recherche-exemple-simple-corba-cpp/controlleur-ajax.png/" border="0" alt="Nom : controlleur ajax.PNG
Affichages : 4605
Taille : 68,4 Ko"  style="float: CONFIG" /><br />
<br />
Beaucoup de choses à dire sur ce code :<br />
<br />
<ol class="decimal"><li style=""><b>c'est une classe statique</b> qui a l'avantage d'être légère, minimale niveau mémoire (pas d'instanciation, d'abstraction ni autre) et se prête bien au contexte d'exécution Ajax, on imprime le résultat de la requête pour l'envoyer au client ;</li><li style=""><b>la gestion d'erreur est spécifique: </b>on imprime directement l'erreur et on fait un exit(). =&gt; Le retour d'erreur est standardisé pour le navigateur et laissé à JavaScript pour le rendre à l'utilisateur. Cela n'empêche aucunement de loguer au niveau du SGBDR si cela est souhaité ;</li><li style=""><b>on bloque automatiquement les requêtes non gérées grâce au switch. </b>Et plutôt que de retourner un message &quot;requête non gérée&quot; vous pouvez si vous le souhaitez, générer une erreur 404 ;</li><li style=""><b>on oblige à standardiser les requêtes Ajax. </b>Il faut ici que le paramètre <font color="#ff0000"><b><i>action</i></b> </font>soit toujours présent, c'est-à-dire, dans toutes les requêtes pour que la requête soit examinée. On libère ainsi au plus tôt le serveur d'une requête non désirée, et rien n'empêche encore une fois de loguer les tentatives avant de renvoyer une erreur. (Attention au log ici pour ne pas vous faire saturer votre SGBDR ou votre disque dur par des logs intempestifs).</li><li style=""><b>la classe joue son rôle de Front Controller</b>. Elle filtre les requêtes acceptables avant de les transmettre / faire suivre au contrôleur applicatif dont elle dépend.</li></ol><br />
<br />
Voilà j'espère que ce petit tutoriel vous sera utile et vous aidera à faire progresser vos applications vers un code plus standard, optimisé et plus sûr.<br />
<br />
A bientôt.</blockquote>

]]></content:encoded>
			<dc:creator>tse_jc</dc:creator>
			<guid isPermaLink="true">https://www.developpez.net/forums/blogs/384137-tse_jc/b593/ajax-structurer-code-creer-controleur-specifique-php/</guid>
		</item>
		<item>
			<title>Le Singleton et le Dependency Injection pattern en PHP</title>
			<link>https://www.developpez.net/forums/blogs/384137-tse_jc/b586/singleton-dependency-injection-pattern-php/</link>
			<pubDate>Thu, 25 Jun 2015 00:02:40 GMT</pubDate>
			<description>Bonjour, 
 
 
Voici un vaste...</description>
			<content:encoded><![CDATA[<blockquote class="blogcontent restore">Bonjour,<br />
<br />
<br />
Voici un vaste sujet auquel je m'attaque ici, sujet qui fait débat surtout sur les blogs anglophones, parfois houleux, j'ai même lu un développeur qui disait &quot;je ne parle plus aux développeurs qui n'utilisent pas d'injecteur de dépendance dans leur développements, pour moi c'est une nécessité professionnelle de progression.&quot; (cf: <a href="http://code.tutsplus.com/tutorials/dependency-injection-in-php--net-28146" target="_blank">Exposé en anglais sur l'injecteur de dépendance et le singleton, source de cette déclaration</a>)<br />
<br />
<br />
Avant de commenter un tel propos et de recadrer et pondérer les choses de la manière la plus objective que possible et sans parti pris, voici ce que la communauté professionnelle a à reprocher au design pattern singleton de manière générale et récurrente:<br />
- Il a un scope global un peu comme une variable globale;<br />
- Il rends les tests unitaires difficiles voire impossibles.<br />
- Il oblige à utiliser un couplage fort avec ses dépendances, les cache même fortement, limitant l'évolutivité et l'extensibilité de ces dépendances, rendant une telle tâche ardue et difficilement maintenable.<br />
- Certains pensent même qu'il n'y a aucune utilité à n'avoir qu'une seule instance d'une classe possible dans une application PHP.<br />
<br />
<br />
Donc juste avant de répondre et d'argumenter, je pense qu'il est important de préciser qu'il n'y a pas de bon ou de mauvais pattern de développement. Ils ont en effet tous leur utilité et leur spécificité ainsi que leur avantages et leur inconvénients (il n'existe pas de solution universelle parfaite).<br />
Comment faire ses choix dans un tel contexte? La réponse doit d'abord être issue de la maîtrise d'ouvrage, qui elle seule est en mesure d'établir l'architecture applicative adaptée au cahier des charges lui même défini en fonction des prérequis métiers et des contextes d'exploitation. Il se doit d'être objectif et neutre (sans parti pris) pour rester efficace et pertinent.<br />
<br />
<br />
A partir de ces bases, il nous paraît déjà évident que les objections citées en début de billet, restent subjectives car hors d'un tel contexte. Mais ne nous contentons pas d'une telle observation et allons un peu plus loin dans l'étude des besoins d'une application web.<br />
<br />
<br />
Tout d'abord, <b>une application web</b> est avant tout une application dite <b>n-tiers</b>, c'est-à-dire <b>répartie</b> sur au moins 3 &quot;supports&quot; ou plus : de façon minimaliste on a de façon usuelle et générale:<br />
1) Le serveur base de données, qui est un <b>serveur relationnel et transactionné</b>, capable de traiter de l'information en parrallèle et qui sait tirer profit <b>automatiquement</b> des ressources (CPU,RAM,Disque) dont il dispose.<br />
2) Le serveur tiers, en général un serveur (objet) gérant les requêtes client http/https (apache,IIS,...). Son rôle étant &lt;strong&gt;à minima&lt;/strong&gt;, en plus de gérer les requêtes http/https clientes, d'identifier le client, de gérer et sécuriser son accès à l'applicatif, de mettre en mémoire cache des données, et de délivrer au client les données demandées mises en forme conformément au cahier des charges.<br />
3) Le client, lieu où réside l'IHM de l'applicatif et où l'homme peut interagir avec les données qui sont mises à sa disposition.<br />
<br />
<br />
<b>Que peut-on dire d'une telle architecture?</b> <br />
1) <b>Sa définition sémantique &quot;n-tiers&quot; oblige à dire que c'est une application dont les éléments constitutifs sont répartis et donc décentralisés, contrairement à une application classique compilée (comme le serait par exemple une application Windows : word,etc..)</b><br />
2) Ainsi respecter une telle architecture afin d'optimiser ses spécificités c'est aussi décentraliser les compétences et spécialiser les tâches applicatives au niveau de chaque tiers : gestion et pilotage des données au niveau SGBDR, contrôle des accès et des requêtes applicatives au niveau de apache,IIS et PHP (ou autre) et donc au niveau du serveur objet, gestion de l'interface au niveau client.<br />
3) rendre performant une telle architecture c'est rendre autonome chaque tiers applicatif de manière à ce que la seule dépendance restante existante entre chaque tiers soit celle des données, et de faire en sorte d'optimiser la bande passante en ne requêtant pas des données qui ont déjà été délivrées.<br />
4) Respecter l'ensemble des points précédents, c'est s'assurer de la bonne capacité de montée en charge d'une telle architecture d'application.<br />
<br />
<br />
<b>Observations sur cette structure</b><br />
- Le développement en base de données épaisses est à ma connaissance aujourd'hui le seul à répondre à l'ensemble de ces exigences structurellement parlant.<br />
- L'ensemble des CMS et frameworks du marché ne le respectent pas et centralisent l'ensemble de la gestion applicative au niveau du serveur tiers et donc objet (PHP/Apache, etc...), utilisent le SGBDR comme un lieu dénormalisé (au sens des bases de données relationnelles) en faisant de la persistance de classe essentiellement. Là est la cause principale de leur difficulté à gérer la montée et la tenue de charge applicative.<br />
<br />
<br />
<b>Au niveau du serveur tiers en PHP, toujours dans l'esprit de monopoliser le moins de ressources possibles, quelles sont les entités minimales de gestion pour faire tourner une application web?</b><br />
Avant de répondre à cela, il est important de préciser ici qu'il n'y a que deux contextes généraux applicatifs :<br />
- Le mode non connecté (ou anonyme) qui corresponds à la consultation d'un site internet normal<br />
- Le mode connecté, qui corresponds à <b>l'accès sécurisé</b> à un back office, front office, extranet, intranet,... représentant le contexte d'étude de ce billet.<br />
<br />
<br />
En mode connecté donc, les entités minimales sont au nombre de 2 et peuvent être représentées par deux classes : utilisateur et connection. Ces deux classes ont les particularités suivantes:<br />
- Elles restent indépendantes du modèle de données (qui peut être plus complexe comme dans un ERP par exemple).<br />
- Elles sont indispensables au bon fonctionnement applicatif et ont besoin d'être chargées systématiquement.<br />
- Elles ont un besoin à la fois d'être sécuritaire et de posséder une emprunte mémoire minimale, cahier des charges garanti en ne pouvant les instancier qu'une seule fois dans l'application, et en respectant une encapsulation totale de l'information.<br />
- Elles représentent deux classes contrôleur dans un modèle MVC.<br />
- Elles doivent jouer un rôle de cache pour les données qu'elles gèrent pour solliciter toujours à minima la base de données.<br />
<b>Conclusion =&gt; Le Singleton offre tous ces avantages et peut garantir ce cahier des charges.</b><br />
<br />
<br />
Nous nous retrouvons donc dans un contexte tout autre que celui exposé dans le lien du début de ce post, lien qui expose le pourquoi et le côté incontournable du pattern d'injecteur de dépendances, dont le contexte présenté reste celui de l'architecture d'une application compilée et donc centralisée et qui se retrouve pour &quot;une petite application&quot; avec un registre de plus de 20 dépendances à charger au démarrage pour fonctionner avec des noms aussi long que le bras, dépendances qui peuvent dépasser les 200 sur de grosses applications, alors qu'ici on en a besoin que de deux +1 voire 2 (grosses applications) pour la gestion du module courant de consultation.<br />
<br />
<br />
La différence est déjà démesurée, les ressources monopolisées non comparables...<br />
<br />
<br />
<b>En ce qui concerne les dépendances cachées par le singleton.</b><br />
Dans une telle architecture web lorsque le modèle MVC est utilisé, les dépendances &quot;cachées&quot; par le contrôleur singleton ne sont pas un mystère : il ne peut y en avoir que 2 types possibles : une dépendance de vue et une dépendance de modèle. Ni plus, ni moins. L'argument qu'elles soient &quot;cachées&quot; n'en est de plus pas un, car il est très facile de les isoler au sein du contrôleur:<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:36px;">$reponse=$this-&gt;MODEL('udpate_sales_permonth',$params);</pre>
</div>L'approche est déterministe et reste affectée dynamiquement à l'exécution, ce qui reste très facilement maintenable et extensible à souhait sans modification ni mise à jour structurelle du code. Dès qu'une nouvelle fonctionnalité doit être implémentée, il suffit de créer la classe modèle correspondante et de l'appeler via le contrôleur lorsque applicable. Tout reste isolé et facilement maintenable.<br />
<br />
<br />
<b>Le maître mot est de savoir adapter l'architecture de son application à ses contraintes d'exploitation et métier, et non pas faire de la technique pour de la technique, ni de vouloir imposer un modèle applicatif lorsque celui-ci n'est pas pertinent pour le besoin et les contraintes exprimées, pour une quelconque raison hors contexte.</b><br />
<br />
<br />
<b>Concernant le scope global du singleton</b><br />
Pour commencer, contrairement à une variable globale qui est déclarée et qui monopolise des ressources d'une manière permanente, le singleton ne l'est que si il est instancié.<br />
Concernant l'exploitation du singleton dans le contexte exposé dans ce billet, c'est-à-dire pouvant servir de cache, il est légitime que celui-ci puisse être accessible globalement dans l'application. Il faudra donc éviter pour cet usage de rendre la méthode publique __wakeup du singleton privée sous peine de désactiver la possibilité de l'utiliser comme cache pour les données qu'il contrôle, comme je l'ai déjà aperçu dans certains billets sur le net. Ensuite, je rappelle qu'un singleton peut être défini dans un namespace donné ce qui peut réduire son scope de définition, et bien qu'étant global à l'applicatif, il préserve l'encapsulation, ce qui reste essentiel pour un contrôleur.<br />
Pour les développeurs issus du C, Java, etc... qui continuent à penser que d'avoir des objets globaux à l'application c'est pas propre, ou qui ont d'autres qualificatifs en tête, je trouve bizarre qu'ils tiennent de tels propos lorsqu'il sont les premiers (et à juste titre) à compiler leur bibliothèques de fonctions ou certains contrôleurs dans une dll et à déclarer celle-ci comme dépendance globale au sein de leur projet. Je reste à votre disposition pour en discuter plus en détail.<br />
<br />
<br />
<b>Concernant l'aspect &quot;abstraction à la couche de données&quot;</b><br />
J'ai vu certains qui utilisent le pattern DI (Dependency Injection) pour créer une couche d'abstraction aux données, et qui par exemple font un code pour accéder aux données via PDO, un autre via mysqli, un autre via ODBC etc... C'est du n'importe quoi pour une seule raison :<br />
=&gt; PDO, mysqli, etc... représentent déjà à eux seuls une couche d'abstraction aux données. Il ne sert à rien de créer une abstraction sur de l'abstraction.<br />
S'il est recommandé d'utiliser PDO avec PHP, certains en font fi. Pourtant on peut travailler avec PDO sur du SQL Server en installant le driver natif pour SQLServer, idem pour postgreSQL, pareil pour MySQL, etc...<br />
<br />
<br />
De plus, Certains font comme tous les CMS et frameworks openSource du marché leur ont montré, et tuent les performances de leur application (en centralisant la gestion données au niveau tiers) en faisant/utilisant soit :<br />
- un ORM pour accéder à leur données<br />
- en développant eux-même un niveau d'abstraction idiot en construisant des requêtes génériques via des objets<br />
<div class="bbcode_container">
	<table width="100%" border="0" cellspacing="0" cellpadding="0"><tr>
	<td style="border: 0; padding: 0; text-align: left">Code  :</td>
	<td style="border: 0; padding: 0; text-align: right"><a href="#" onclick="return ano_selectionnerCode(this);">Sélectionner tout</a> -
	<a href="#" onclick="return ano_etendreCode(this);">Visualiser dans une fenêtre à part</a></td></tr></table>
	<pre class="bbcode_code" style="height:36px;">$GET_ARTICLES-&gt;query('SELECT * FROM articles');</pre>
</div><br />
=&gt; au lieu de le faire des bibliothèques métier par SGBDR appelant des procédures stockées ou vues sur le SGBDR, et en optimisant la mise en forme des paramètres en fonction du SGBDR ciblé (utilisation d'arrays sur postgreSQL, etc...) et en ne requêtant seulement les données demandées.<br />
<br />
Voilà j'espère que ce petit tour d'horizon vous aura aidé à y voir plus clair.<br />
Alors le Pattern Dependency Injector a ses raisons d'être, et dans une architecture web n-tiers de type MVC, reste à utiliser au cas par cas lorsque les contraintes l'exigent.<br />
<br />
<br />
Bonne lecture à vous :)</blockquote>

]]></content:encoded>
			<dc:creator>tse_jc</dc:creator>
			<guid isPermaLink="true">https://www.developpez.net/forums/blogs/384137-tse_jc/b586/singleton-dependency-injection-pattern-php/</guid>
		</item>
	</channel>
</rss>
