begin process at 2012 02 11 01:08:16
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Astuces

 > EXÉCUTER UN SCRIPT AU-DELÀ DU TIMEOUT DE PHP

EXÉCUTER UN SCRIPT AU-DELÀ DU TIMEOUT DE PHP


 Information sur la source

Note :
Aucune note
Catégorie :Astuces Classé sous :time out, exécuter, temps exécution Niveau :Débutant Date de création :07/01/2008 Date de mise à jour :07/01/2008 21:25:27 Vu / téléchargé :14 095 / 362

Auteur : malik7934

Ecrire un message privé
Commentaire sur cette source (27)
Ajouter un commentaire et/ou une note

 Description

Cliquez pour voir la capture en taille normale
Ce script montre une méthode permettant d'exécuter un script au-delà du timeout de PHP.

J'en suis venu à cette idée ainsi: si je fais par exemple un export d'une grosse base de données avec un script PHP, je risque de dépasser les 30 secondes (le max_execution_time) autorisées par le serveur où je suis hébergé.

Alors comment faire? En associant AJAX à PHP!

Le principe: Ajax surveille que le script ne s'exécute que pendant un temps t<timeout et fait boucler le script jusqu'à ce que l'exécution soit terminée.

Le code présenté ici est un exemple. A vous de l'adapter si vous en avez l'intérêt!

Source

  • ############# FICHIER index.php
  • <html>
  • <head>
  • <title>Exécuter un script au-delà du timeout de PHP</title>
  • <!-- script mootools.js téléchargé sur http://mootools.net/download -->
  • <script type="text/javascript" src="mootools.js"></script>
  • <script type="text/javascript">
  • <?php
  • // temps maximal d'exécution du script autorisé par le serveur
  • $max_time = ini_get('max_execution_time');
  • // 30 secondes par défaut:
  • if ($max_time == '') $max_time = 30;
  • // on prend 10% du temps maximal comme marge de sécurité
  • $ourtime = ceil(0.9*$max_time);
  • // variable pour les tests, à retirer en production
  • $ourtime = 4;
  • // variable(s) devant être surveillée(s) - exemple
  • $i = 10;
  • ?>
  • window.addEvent('domready', function(){
  • $('start').addEvent('click', function(e) {
  • e = new Event(e).stop();
  • var url = "time.php?t=<?php echo $ourtime;?>&i=<?php echo $i;?>";
  • new Ajax(url, {method: 'get', evalScripts:true}).request();
  • });
  • });
  • </script>
  • </head>
  • <body>
  • <h3>Exécuter un script au-delà du timeout de PHP</h3>
  • <p><a id="start" href="#">Cliquez ici</a> pour lancer le test</p>
  • Timeout après: <b><?php echo $ourtime;?> secondes</b><br />
  • Temps d'une boucle: <b>environ 1 seconde</b><br /><br />
  • Résultat:<br /><div id="result"></div>
  • </body>
  • </html>
  • ############# FICHIER time.php
  • <?php
  • header('Content-type: text/html; charset=iso-8859-1');
  • echo '<script type="text/javascript">'."\n";
  • // récupération des variables;
  • $main_ourtime = $_GET['t'];
  • $i = $_GET['i'];
  • $temps_total = $_GET['tillnow'];
  • $ourtime = $main_ourtime;
  • function timer(){ //chronomètre - http://www.phpcs.com/code.aspx?ID=32471
  • $time=explode(' ',microtime());
  • return $time[1] + $time[2];
  • }
  • $rep = '';
  • $start_while=timer(); // début du chronométrage du while
  • while ($i>0 && $ourtime>0){
  • $start=timer(); // début du chronométrage de l'itération
  • sleep(1); // traitement - le sleep simule un temps de traitement de une seconde
  • $i--;
  • $ourtime -= (int)number_format(timer()-$start,7);
  • $rep .= $i.'... ';// texte de sortie
  • }
  • $end_while = number_format(timer()-$start_while,7);
  • $temps_total += $end_while;
  • echo '$(\'result\').innerHTML += \'<b>'.$rep.'(<font color="#00aa00">'.$end_while.' sec.</font>)</b><br />\';'."\n";
  • if($i>0){ // si l'exécution du script a été interrompue pour éviter le timeout, on reprend où on s'est arrêté
  • echo 'var url = "time.php?t='.$main_ourtime.'&i='.$i.'&tillnow='.$temps_total.'";
  • new Ajax(url, {
  • method: \'get\',';
  • if ($i>0)
  • echo 'evalScripts:true,';
  • echo '}).request();';
  • }
  • else
  • echo '$(\'result\').innerHTML += \'<b><font color="#0000aa">terminé en '.$temps_total.' secondes!</font></b><br />\';'."\n"; // traitement des donn&eacute;es
  • echo '</script>';
  • ?>
############# FICHIER index.php

<html>
	<head>
		<title>Exécuter un script au-delà du timeout de PHP</title>
		<!-- script mootools.js téléchargé sur http://mootools.net/download -->
		<script type="text/javascript" src="mootools.js"></script>
		<script type="text/javascript">
			<?php
			
				// temps maximal d'exécution du script autorisé par le serveur
				$max_time = ini_get('max_execution_time');
				// 30 secondes par défaut:
				if ($max_time == '') $max_time = 30;
				
				// on prend 10% du temps maximal comme marge de sécurité
				$ourtime = ceil(0.9*$max_time);
				
				// variable pour les tests, à retirer en production
				$ourtime = 4;
				
				// variable(s) devant être surveillée(s) - exemple
				$i = 10;
				
			?>
		
			window.addEvent('domready', function(){
				$('start').addEvent('click', function(e) {
					e = new Event(e).stop();
					var url = "time.php?t=<?php echo $ourtime;?>&i=<?php echo $i;?>";
					new Ajax(url, {method: 'get', evalScripts:true}).request();
				});
			}); 	
		</script>
	</head>
	<body>
		<h3>Exécuter un script au-delà du timeout de PHP</h3>
		<p><a id="start" href="#">Cliquez ici</a> pour lancer le test</p>
		Timeout après: <b><?php echo $ourtime;?> secondes</b><br />
		Temps d'une boucle: <b>environ 1 seconde</b><br /><br />
		Résultat:<br /><div id="result"></div>
	</body>
</html>

############# FICHIER time.php

<?php
header('Content-type: text/html; charset=iso-8859-1');

echo '<script type="text/javascript">'."\n";

// récupération des variables;
$main_ourtime = $_GET['t'];
$i = $_GET['i'];
$temps_total = $_GET['tillnow'];
$ourtime = $main_ourtime;

function timer(){ //chronomètre - http://www.phpcs.com/code.aspx?ID=32471
	$time=explode(' ',microtime());
	return $time[1] + $time[2];
}

$rep = '';

$start_while=timer(); // début du chronométrage du while
while ($i>0 && $ourtime>0){

	$start=timer(); // début du chronométrage de l'itération
	
	sleep(1); // traitement - le sleep simule un temps de traitement de une seconde
	
	$i--;
	
	$ourtime -= (int)number_format(timer()-$start,7);
	$rep .= $i.'... ';// texte de sortie
}
$end_while = number_format(timer()-$start_while,7);
$temps_total += $end_while;

echo '$(\'result\').innerHTML += \'<b>'.$rep.'(<font color="#00aa00">'.$end_while.' sec.</font>)</b><br />\';'."\n";

if($i>0){ // si l'exécution du script a été interrompue pour éviter le timeout, on reprend où on s'est arrêté
echo 'var url = "time.php?t='.$main_ourtime.'&i='.$i.'&tillnow='.$temps_total.'";

	new Ajax(url, {
			method: \'get\',';
if ($i>0)
	echo 'evalScripts:true,';
echo '}).request();';
}
else
	echo '$(\'result\').innerHTML += \'<b><font color="#0000aa">terminé en '.$temps_total.' secondes!</font></b><br />\';'."\n"; // traitement des donn&eacute;es
	
echo '</script>';
?>

 Conclusion

AJAX est traité ici avec l'excellente librairie mootools disponible sur http://www.mootools.net

Une condition sine qua none pour que cette astuce fonctionne est que le temps d'exécution d'une itération dans la boucle soit inférieur au time out.

L'exécution de l'exemple ci-dessus donne:

9... 8... 7... 6... (4.0000000 sec.)
5... 4... 3... 2... (4.0000000 sec.)
1... 0... (2.0000000 sec.)
terminé en 10 secondes!

 Fichier Zip

Les Membres Club peuvent télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !

Télécharger le zip


 Historique

07 janvier 2008 19:18:05 :
orthographe
07 janvier 2008 19:46:48 :
NE FONCTIONNE QU'AVEC FF! Pour une raison que j'ignore, Mootools que pourtant j'adore refuse de faire son boulot avec IE... damned, je m'y plonge!
07 janvier 2008 21:25:27 :
Ajout d'un zip contenant une version améliorée sans Mootools

 Sources du même auteur

Source avec une capture SAUVEGARDE AUTOMATISÉE DE VOS BASES DE DONNÉES
SAVOIR QUI CONNAÎT QUI DANS UN FORUM/CHAT/...
Source avec une capture CACHER UNE SIGNATURE DANS UNE IMAGE
NOUVEAUX MESSAGES SUR YAHOO MAIL
EXÉCUTER UNE FONCTION SI C'EN EST UNE

 Sources de la même categorie

Source avec Zip Source avec une capture GENERATEUR D'ONGLET DE NAVIGATION PHP par pos123
FORMATER UN LIEN YOUTUBE, DAILYMOTION OU VIMEO POUR L'UTILIS... par kgb93
Source avec Zip Source avec une capture PAGINATION + FICHIER CSS par profdi
Source avec Zip Source avec une capture SYSTEME D'AUTHENTIFICATION PHP AVEC PROTÉCTION KEYLOGGER par mtrix000
Source avec Zip Source avec une capture GENERATEUR DE BOUTONS DE PARTAGES POUR RESEAUX SOCIAUX par cod57

Commentaires et avis

Commentaire de malalam le 07/01/2008 19:51:20 administrateur CS

Hello Malik,

tss tss..
http://www.phpcs.com/codes/GENERER-VOLUME-IMPORTANT-DONNEES-SANS-HEURTER-TIMEOUT-PHP_39811.aspx
http://www.phpcs.com/codes/PHP5-NOTIMEOUT-PACKAGE_39866.aspx

Mais je ne peux qu'admettre que c'est une bonne idée, forcément ;-)

Commentaire de malik7934 le 07/01/2008 19:52:50

aie... j'avoue j'ai pas cherché avant :-/

Commentaire de malalam le 07/01/2008 20:08:28 administrateur CS

Bah c'est pas grave, ça remet au goût du jour cette astuce.
Elle est très pratique, je l'utilise régulièrement en environnement de production, ça marche très très bien!

Commentaire de coucou747 le 08/01/2008 03:36:13 administrateur CS

perso je prefere mettre un settimelimit, ca evite de faire plein de requetes pour une seule tache, mais c'est vrai que ca peut-etre bien pratique

Commentaire de malik7934 le 08/01/2008 08:12:30

le settimelimit, c'est pur mettre une durée inférieure au timeout. Là le but c'est d'aller au-delà de cette durée!

Commentaire de malalam le 08/01/2008 08:14:15 administrateur CS

Un avantage que ça a sur un set_time_limit() c'est que cela contre aussi les dépassements de mémoire allouée. Et puis c'est synchrone, tu peux effectuer plusieurs tâches en même temps, voire même laisser la main à l'utilisateur pendant ce temps.
Et pour ceux qui ont un serveur mutualisé, set_time_limit() ne sera sans doute pas disponible.
Mais bon c'est sûr, je n'utilise pas cette technique quand je peux me contenter d'un set_time_limit(), c'est moins contraignant quand même!

Commentaire de malalam le 08/01/2008 08:17:52 administrateur CS

Asynchrone, vous aurez compris...:-)

Commentaire de malalam le 08/01/2008 09:21:22 administrateur CS

@Malik => tu peux mettre une durée de vie supérieure aussi, ou infinie (set_time_limit(0)) ?

Commentaire de malik7934 le 08/01/2008 09:51:56

Si le serveur est configuré pour faire un time out au-delà de 30 secondes, tu peux mettre le set_time_limit à 45 secondes, il timeoutera après les 30 secondes! Non??

Dans la doc PHP il est dit: "Lorsqu'elle est appelée, set_time_limit() remet le compteur à zéro. En d'autres termes, si la limite par défaut est à 30 secondes, et qu'après 25 secondes d'exécution du script l'appel set_time_limit(20)  est fait, alors le script tournera pendant un total de 45 secondes avant de finir.", est-ce que cela veut dire qu'en faisant le petit code qui suit, on entrerait dans une boucle infinie?:

$i=0;
while(true){
  $i++;
  sleep(1);
  if ($i>= 20){
    $i=0;
    set_time_limit(30);
  }
}

J'ai l'impression que oui, si le safe_mode est off...

Commentaire de malalam le 08/01/2008 09:58:14 administrateur CS

Chez moi, le timeout respecte le set_time_limit() que je mets. Sur les 3 serveurs sur lesquels je le fais (en safe_mode à off pour tous).
Quant à ta boucle : c'est fort probable oui. Je ne vais pas tester ici parce que ça ne ferait pas plaisir à mon équipe ;-) Mais je pense que c'est bien une boucle infinie.

Commentaire de malik7934 le 08/01/2008 10:03:58

Quelles sont les conséquences d'avoir un safe_mode à off, c'est-à-dire de désactiver le mode sécurité?? Je suis un peu étonné d'apprendre que vous bossez ainsi, j'ai des copains providers pour qui mettre le safe_mode à off serait pire que de se faire couper les deux bras :-)

Commentaire de malalam le 08/01/2008 10:27:59 administrateur CS

Nous ne bossons pas sur des serveurs mutualisés, le safe_mode ne sert que dans ce cas. Nos serveurs web sont dédiés, et uniquement à du web, qui plus est.
Tes copains providers ne doivent faire que du mutualisé...ou sinon, il faut qu'ils m'expliquent à quoi leur sert de mettre un serveur dédié en safe_mode à On...?

Commentaire de malik7934 le 08/01/2008 10:29:53

Je crois que tu as répondu toi-même à ta question: les serveurs sont à eux (dédiés), mais ils ont des clients qu'ils host dessus...

Commentaire de malalam le 08/01/2008 10:41:03 administrateur CS

Ben vlà :-) Alors je suis d'accord, c'est nettement préférable, même si ce n'est pas une solution parfaite.

Commentaire de verdy_p le 17/01/2008 16:58:32

L'idée d'utiliser settimelimit() n'est pas nouvelle. D'ailleurs la fonction PHP a évolué pour qu'elle n'autoise plus d'augmenter la durée de timetout au delà de ce qui est configuré sur le serveur.

D'autre part, une option de compilation de PHP permet d'éviter le "reset à 0" du timer, même en "safe mode", afin d'éviter des scripts qui tournent indéfiniment sur le serveur PHP. De toute façon un script ne pourra continuer à tourner sur le serveur QUE TANT QUE la connection HTTP n'est pas interrompue, car dans ce cas c'est le serveur web qui demandera la fin d'exécution du thread au serveur PHP (dans une installation de type FastCGI: c'est le noyau FastCGI qui se charge d'interrompre le script).

De plus, de nombreux serveurs PHP mutualisés ne sont pas accessibles directement mais sont accessibles via un serveur proxy se chargeant de faire de l'équilibrage de charge et de maintenir un cache pour soulager les serveur PHP. Hors, ces serveurs proxy ont eux aussi des timeouts: si un script ne se termine pas à temps, le proxy interrompra la connexion au serveur, ce qui interrompra le script en cours qui ne peut plus retourner les résultats sur une socket de session qui a été fermée: le script se termine alors prématurément avec une erreur d'I/O.

L'astuce exposée ci-dessus n'est pas généralisable: il faut que le script soit modifié pour pouvoir reprendre une exécution interrompue sans avoir à tout recommencer depuis le début, et cela demande une gestion de session, et une modification des algorithmes. Ce n'est donc pas si simple.

Si un script doit réellement tourner longtemps sur un serveur, mieux vaut en faire un service séparé sur le serveur, tournant hors du contexte du serveur Apache et des serveurs esclaves PHP ou FastCGI. Mais la difficulté persistera sur les serveurs mutualisés où de tels services ne peuvent pas être installés et exécutés librement.

De toute façon, la plupart des services d'hébergement mutualisé ont modifié ces fonctions critiques de PHP (en plus d'activer le "safe mode") pour empêcher totalement qu'un script puisse tourner indéfiniment sur le serveur (car le risque sinon est bien de provoquer une attaque de déni de service (DoS) paralysant totalement le serveur si une page PHP héberbée est sollicitée un grand nombre de fois et toutes peuvent tourner indéfiniment: le serveur mutualisé ne remplirait plus sa fonction.

Maintenant, on peut toujours vouloir activer un fonctionnement Ajax pour effectuer des requêtes répétitives, cependant, si cela est déployé à grande échelle, le serveur mutualisé va commencer à décompter très rapidement la bande passante permise pour le service hébergé, et risque alors de faire dépasser votre quota autorisé poru l'hébergement.

Ce genre d'astuce est donc à utiliser avec précaution. Et en pratique, si vous avez besoin d'une telle fonction, cela devrait être pour faire effectuer par le serveur certaines opérations longues d'administration de contenu sur votre site web, et donc cette page hébergée devrait être protégée par un accès sécurisé, et vous devriez mettre en ½uvre un système d'authentification ou de limitation d'utilisation par utilisateur ou par période de temps (utiliser un système de ticket de réservation de ressource pour obtenir un droit d'utilisation) si la page est accessible a priori à tous (et surveillez alors vos stats ou logs pour détecter rapidement tout abus d'utilisation de cette page PHP critique).

Concernant la compatibilité, le script ci-dessus ne marche qu'avec Firefox, car il utilise un évènement non standardisé ("domready"). Généralement il vaut mieux se baser sur un évènement nettement mieux supporté ("onload") par les navigateurs.

Ajax est encore une technologie naissante, et on ne peut se passer de bonnes librairies bien maintenues et qui évoluent aussi en fonction des évolutions des navigateurs (dont les comportements en terme de javascript et DOM sont encore très différents d'un logiciel à l'autre et même d'une version à l'autre):

Même Wikipédia, par exemple, a du mal à s'adapter aux changements et assurer la compatibilité, alors même que c'est certainement le site le plus visité sur le web par des tonnes de visiteurs ayant des configurations différentes (OS, navigateur, version, options de sécurité, filtres divers).

Espérons que IE8 (publiquement annoncé comme supportant le test Acid2 pour HTML4+CSS1) améliorera aussi la situation en terme de compatibilité et d'adoption sur les sites, afin de réduire le travail de portage et maintenance de ces librairies Ajax, encore très compliquées! Et espérons que la standardisation d'Ajax avance un peu plus vite pour donner "plus de vie" et d'interactivité au web, sans avoir à dépendre de solutions propriétaires (et aussi couteuses en licence et compétences nécessaires, comme Adobe/Macromédia Flash).

Commentaire de LeFauve42 le 21/01/2008 11:52:11

Salut,

Si le traitement "long" ne necessite pas d'affichage, ne peut-on pas se passer d'Ajax ?
Je pensais a un truc comme ca:
<?php
$start=$_GET['s']*1;
for ($i=$s;$i<1000 && notimeout();$i++)
{
   dosometask();
}

if($i<1000)
{
   header("Location: $PHP_SELF&s=$i");
   exit;
}

print 'Fini';
?>

La fonction notimeout() determine si on a encore du temps pour la prochaine iteration.
La fonction dosometask() represente la tache a realiser (ici 1000 fois).

Est-ce que cette approche est bonne ?

Eric

NB: Ca m'etonnerai que ca fonctionne tel quel. Voyez plutot ce bout de code comme un "algo de principe" :o).

Commentaire de verdy_p le 21/01/2008 12:46:11

L'entête HTTP "Location:" ne réalise pas en lui même un rechargement de la page à l'adresse indiquée. Il faut pour cela que la réponse HTTP contiennt un code de redirection pour que cela ait un effet. L'entête lui-même ne modifie pas par exemple l'URL de la page courante dans le navigateur, et ne modifie pas non plus la cible des liens vers des ancres (comme href="#ancre") qui restent liés à la page inialement demandée et effectivement affichée.

L'autre problème est qu'une redirection exécutée par le navigateur peut être trop rapide et surcharger un serveur. Généralement on ajoute un délai dans la redirection HTTP.

Et cette redirection (si elle est effectuée!) provoque un effacement immédiat de la page affichée par le navigateur, donc on perd l'historique de ce qui a pu être obtenu et affiché depuis le navigateur, et chaque nouvelle requête doit regénérer cet historique (le serveur doit donc trouver le moyen de le garder pour pouvoir le réafficher, et ça peut entrainer un cout supplémentaire pour réaliser ce stockage, et donc la nécessité de gérer des sessions).

Ajax (ou plutôt XmlHttpRequest) évite cela: c'est le navigateur qui conserve les données déjà obtenue, puisqu'il va seulement mettre à jour la page courante sans l'invalider totalement, car les requêtes sont exécutées séparément dans un flux de requêtes en arrière-plan.

La façon de mettre à jour la page courante avec le résultat de la requête peut se faire de la façon qu'on veut, en javascript (ou dans un autre langage) en utilisant DOM si cette mise à jour se fait sur la partie affichée en HTML, ou toute autre méthode (par exemple celles offertes par un objet dans la page, ou bien à destination d'un fichier local sur l'hôte du navigateur qui peur proposer un dialogue de sauvegarde).

Tout ce qu'un navigateur peut faire en javascript à partir d'un évènement DHTML est possible dès lors que ce script a accès au contenu de la réponse dans l'objet XmlHttpRequest, au moment où il recevra l'évènement de complétion de la requête (ou d'échec de cette requête ou d'expiration de délai: le statut de complétion est dans l'objet XmlHttpRequest, accessible dans l'événement HTML qu'il génére et intercepté par votre javascript).

Commentaire de verdy_p le 21/01/2008 12:51:33

Pour être complet: s'il faut indiquer un code de redirection dans la réponse HTTP, cela ne peut se faire QUE avant la génération de toute autre chose dans la page retournée par le serveur: on renseigne le statut, PUIS on donne les entêtes ("Location:", et autres), PUIS on affiche le corps de la page. Dès que le premier caractère du corps de la page a été généré, c'est trop tard pour demander la redirection via le statut HTTP (cependant on pourrait le faire en générant dans la page un bout de javascript que le navigateur va exécuter; mais c'est trop moche et pas conforme aux normes, et il n'est même pas sûr que le navigateur puisse afficher et interpréter correctement une page incomplète, ni donc ce code javascript si le document HTML n'est pas conforme).

Commentaire de LeFauve42 le 21/01/2008 13:45:54

Merci de ces infos VERDY_P.

Mon probleme est surtout pour des scripts de consolidation de la base de donnees qui peuvent prendre quelques minutes.

Je n'ai donc pas de probleme d'affichage puisqu'il s'agit de scripts "back office" qui se contentent generalement d'afficher "OK" ou un message d'erreur.

Par contre, qu'entends-tu par changer le "statut" de la reponse. Je pense que tu fais allusion aux "200", "300", "404" et autres codes. J'utilise depuis de nombreuses annees des header("Location:...") et je n'ai jamais eu de probleme avec. Que me conseilles-tu d'ajouter pour etre conforme au protocole ? (meme si "Location" n'a pas ete concu pour recharger plusieurs fois la meme page).

Commentaire de verdy_p le 21/01/2008 20:41:07

Oui je parle bien du statut 200, etc... qui doit être positionné avec les entête AVANT d'afficher le moindre caractère dans la page des résultats (ne serait-ce que OK).

Généralement on peut générer les statuts dès le début, à partir du moment où la requête est bien formée et avant même d'exécuter ce qui est demandé sur le serveur. Dans ce cas le statut est 200 OK, et il n'est pas possible d'utiliser l'entête Location: pour faire une redirection.

Ensuite on peut afficher des messages de progression dans le corps HTML affiché dans le navigateur.
Avant d'interrompre, on peut générer un bout de javascript dans le corps, on forme la page avec </body></html> ce qui termine le script PHP et donne une page complète pour le navigateur.

Le navigateur va afficher les messages de progression en cours, et exécuter ensuite ton javascript, qui devrait:
* attendre une seconde
* demander le rechargement de la page en modifiant l'URL de la page courante

On peut aussi utiliser la méthode avec POST si l'URL nécessaire est trop compliquée ou trop longue, en codant en fin de page un formulaire HTML contenant les divers paramètres à poster et leur valeur, que le javascript va simplement reposter en utilisant la méthode submit() du formulaire que ton script PHP aura généré sous forme précomplétée (il n'est pas nécessaire d'afficher ces paramètres dans le formulaire HTML que ton script PHP génère: il peut les coder dans des paramètres de formulaire de type "hidden", par exemple:

<form name="xyz" method="POST">
<input type="hidden" name="start" value="<?php echo $i; ?>"/><!-- invisible -->
<input type="submit" name="dummy" value="Continuer..."/>
</form>

Pour les tests, tu peux rendre visibles les paramètres "hidden" en les transformant en type de contrôles de saisie, que tu peux en revanche protéger contre des modifs par inadvertance en utilisant les propriétés de mise en forme et désactivation comme disabled). Cela peut aussi être utile pour consulter les valeurs de variables internes de traitement.

Par prudence, commence d'abord en générant le formulaire avec un bouton submit (labellé "Continuer" par exemple) que tu cliqueras toi-même dans la page affichée par le navigateur.

Note qu'il te faut aussi paramétrer le format de soumission pour POST, puisque par défaut les formulaires HTML utilisent la méthode GET avec un format urlencoded, inapproprié en POST.

Si tout se passe bien, active le javascript qui soumettra le formulaire automatiquement après un petit délai (évite une soumission immédiate, ça peut éventuellement faire une boucle difficile à arrêter et provoquer une surcharge sur le serveur): le bouton submit n'est alors plus nécessaire puisque le javascript "déclenchera" lui même la soumission sans qu'il soit nécessaire de presser un bouton.

Commentaire de malalam le 21/01/2008 23:11:16 administrateur CS

@verdy_p

tes remarques sont très intéressantes. Néanmoins, quelques remarques :
- il y a d'autres moyens que domready pour gérer ce genre de scripts. Ici, nous avons simplement un exemple, qui peut facilement s'adapter. Le script que j'avais écrit ne s'utilise avec aucune librairie js et est compatible avec tous les navigateurs récents. C'est simplement une question d'écriture.
- je suis d'accord que sur les serveurs mutualisés ce n'est pas une bonne idée, sauf pour certaines utilisations : je m'explique...j'utilise cette technique dans 2 cas : il faut tout d'abord comprendre que je ne bosse que sur des serveurs dédiés; cette technique ne me sert pas tant à outrepasser le timeout de php (je peux très bien modifier ce timeout dans mes scripts ou sur le serveur) qu'à les temporiser; les temporiser sert aussi à éviter la limitation de la mémoire allouée à un script php. Cela sert aussi à afficher un résultat imposant progressivement (par exemple, aller chercher des 10aines d'images sur un serveur et les afficher 5 par 5, en laissant la mein à l'utilisateur). Dans ce cadre là, même sur un serveur mutualisé, cela passe (si tant est que le traitement ne prenne pas des heures évidemment).
- ajax n'est âs une technologie naissante, loin de là : elle existe depuis de très nombreuses années...elle est juste redécouverte depuis 3-4 ans. A vrai dire je suis étonné par ton commentaire à ce niveau là : espèrer que Flash ne soit pas préféré à Ajax de part son côté propriétaire...cela fait belle lurette que Flash cède du terrain à ce qu'on appelle par effet de mode le "web 2.0" et son utilisation poussée de javascript au travers de différentes librairies de type prototype, mootools, yahou ui, jquery et cie. Je pense qu'on est sur cette voie depuis un moment, et que ce n'est pas prêt de changer. La naissance d'un framework tel que ROR (Ruby On Rails) en est la preuve.

Ceci dit, je suis globalement d'accord avec toi. Cela reste une astuce...à utiliser en connaissance de cause.

Commentaire de verdy_p le 23/01/2008 15:50:53

"ajax n'est âs une technologie naissante" je suis d'accord pour le côté de sa définition, mais elle reste naissante du côté de son implémentation. C'est bien pour ça qu'il y a des navigateurs pour lesquels le script proposé ne marche pas encore (ne serait-ce encore que IE qui demande un objet par ActiveX (XmlHttpRequest) et non par une propriété de la frame courante ou du document.

Et dans les composants disponibles, tous ne supportent pas les mêmes évènements de complétion/erreur/timeout ou les mêmes propriétés pour récupérer ou envoyer les statuts, entêtes (types MIME, codages...), ou encore suivre les status de progression (type 100 à 199 en HTTP) avec une succession d'évènements, ou encore d'interrompre une requête en cours malgré le timeout indiqué. Quant au décodage de la réponse, elle n'est pas forcément en Xml, et "domready" ne s'applique pas aux réponses de type non XML ou compatible XML (on peut aussi bien faire n'importe quelle requête HTTP valide.

Qu'est-ce qu'Ajax? une norme minimale commune d'interopérabilité permettant de faire  des requêtes au format XML de base.

Cependant même dans ce cas, il peut y avoir des subtilités dans la réponse HTTP: support du format chunked (à priori obligatoire dans HTTP/1.1 mais optionnel en HTTP/1.0, signification différentes de certains entêtes d'interaction avec les caches locaux ou de proxies ou authentification pour HTTPS, et différentes options de sécurisation supportés, ainsi que de compression des requêtes et réponses). Ca en fait des tas de problèmes potentiels, pour lesquels Ajax s'appuie sur HTTP dans deux normes différentes (dont une est partiellement standardisée avec seulement des otions recommandées mais non obligatoires), mais pas seulement ce protocole.

Enfin le pluscritique est l'intégration au navigateur. La méthode ActiveX de Microsoft est totalement non standard, mais peut supporter des implémentations multiples et distinctes. L'autre méthode est intégrée mais ne supporte que la variante du navigateur (à défaut de toute autre implémentation). Résultat: la méthode Microsoft avec composant ActiveX de son choix, peut supporter différentes versions (ou niveaux) de compatibilité du protocole, ou même de compatibilité XML pour le codage des requêtes et réponses, et l'adaotation à différentes version d'évolution d'autres normes liées comme les services SOAP, les agents Corba, ou les moniteurs transactionnels: HTTP est vraiment très versatile et supporte plein d'usages autres que le simple chargement d'une page HTML, d'une image, d'une feuille de style ou un téléchargement de fichier binaire ou de données.

Et note que ton script nécessite bien une librairie. Qu'est-ce donc que "mootools.js" sinon une librairie chargé de gommer une partie des problèmes de compatibilité d'un navigateur à l'autre, en instanciant une nouvelle variable "Ajax"?

Commentaire de verdy_p le 23/01/2008 16:33:50

Ceci dit mootools.js est la concaténation de 3 scripts:
- un premier fournit des méthodes itératives pour les collections d'objets, de propriétés et de méthodes applicables aux objets ou chaines, et quelques méthodes numériques. Il essaye aussi de détecter le type de navigateur utilisé en consultant l'existence de certaines propriétés accessibles via le DOM en Javascript (à partir de "window" ou de "document").
- un second "XHR" fournit un wrapper simple pour XmlHttpRequest, mais s'arrête là. il ne réalise pas le décodage XML, mais permet de distinguer les réponses de type "text" ou "xml" (qui seront analysées plus tard). Il comporte le support du protocole HTTP (mais incomplet). Il dépend du premier script.
- le dernier fournit le décodage XML et les bindins en collections javascript, et des méthodes facilitant la construction d'objets HTML dans la page à partir des collections XML. C'est lui qui fournit l'objet "Ajax".

Il y a un problème dans le second objet (XHR). Il ne semble pas traiter correctement les réponses HTTP autres que 200 à 299 comme succès, et traite les réponses de progresssion 100 à 199 comme des erreurs alors qu'elles ne mettent pas fin à la requête en cours. Le wrapper ne semble pas prendre en compte non plus les redirections (300 à 399) pour aller chercher la réponse ailleurs: ce sont pour lui des erreurs; l'objet Ajax du 3e script supporte assez mal le traitement des erreurs HTTP, et partiellement les erreurs de conformité puis de validation XML (qui ne sont pas traitées); il ne gère pas non plus les réponses au format HTML (sauf ceux compatibles XHTML) qui ne peuvent être traitées que comme du texte.

Ce script mootools.js est peut être très bien écrit, mais c'est un vériable marteau pour écraser une mouche, de fait il est complexe d'en percevoir les limites s'il ne marche pas. Ici, je suggérerais plutôt de montrer le principe plus simple à partir de xmlHttpRequest (avec le traitement particulier demandé par IE). On peut ensuite référencer ce script mootools.js mais à condition d'avoir compris ce que fait XmlHttpRequest et ses possibilités et limitations.

Personnellement je n'ai jamais eu besoin d'utiliser un tel script, j'utilise XmlHttpRequest directement (avec quelques tests pour la compatibilité IE) sans toute cette surcouche, avec de bien meilleures performances (sachant qu'IE est relativement lent avec Javascript à cause de ses validations constantes via ActiveX qui est un goulot d'étranglement de la plupart des objets, même s'il est là pour fournir une couche de sécurité et d'isolation entre objets). Ce qui me permet aussi de faire plus facilement n'importe quel type de requête, pas seulement des requêtes XML bien structurées: je ne demande pas au navigateur de valider les plus petites données que génère le serveur, ou de les remettre en forme (blancs, capitalisation, notation Camel, etc...)

En Javascript souvent, plus c'est simple, et mieux ça marche.

Commentaire de malalam le 23/01/2008 18:22:56 administrateur CS

Hello,

déjà, ce n'est pas mon script :-) J'ai développé avant celui-ci (et posté sur CS) un concept similaire, sans utiliser de librairie JS.
L'utilisation d'une librairie JS se justifie dans le cas où on l'utilise réellement, dans un cadre plus global : Malik nous montre ici ujne astuce, qui peut s'intégrer dans un applicatif web; c'est un outil. Et en ce sens, il est vrai que l'utilisation d'une librairie JS est de plus en plus fréquente dans les applicatifs web. Malik a choisi mootools, bon, c'est son choix. Il est très simple de reprendre le concept qu'il montre avec ses propres outils, sa propre façon de coder. C'est même nécessaire : ce code-ci n'est qu'un exemple, une démonstration de l'astuce dont il nous fait part.

Pour ce qui est des particularités de l'objet xmlhttprequest en fonction du navigateur, c'est une réalité...qui n'est absolument pas propre à cet objet, mais au web en général : chaque navigateur propose SON implémentation des technologies web côté client, que ce soit pour cet objet, pour JS, html, css, xsl etc...c'est malheureusement comme ça.
Et pour une fois, je vais "défendre" Microsoft sur les objets xmlhttprequest : c'est Microsoft qui a créé cette méthode. Et commercialement parlant, comme svt avec Microsoft, ils ont fait le choix du "on offre une fonctionnalité géniale, mais si vous voulez en profiter, vous devez utiliser du Microsoft! C'est à nous...!". On en pensera ce que l'on veut...mais du coup, on peut aussi se faire l'avocat du diable et se dire : ils l'ont inventé, leut technologie passe par un ActiveX, c'était peut-être aux autres à s'adapter...
D'ailleurs, le W3C travaille depuis quelques temps à un "clone" de xmlhttprequest mais "standardisé" W3C. Une reco, quoi.  

Commentaire de verdy_p le 24/01/2008 10:03:51

Je n'ai pas attaqué Microsoft sur ce coup là. Justement j'ai écrit que la méthode choisie par Mirosoft était plus générale que celle utilisée dans d'autre navigateurs qui ont choisi d'intégrer une seule version des API d'interactivité asynchrone avec un serveur web.

Personnellement je trouve que la solution de Microsoft (XmlHttpRequest) est une réponse intelligente face au développement d'une autre technologie qui était, elle, totalement propriétaire: Macromédia Flash, devenu Adobe. Microsoft a démontré qu'on pouvait mettre à profit des standards interopérable (notamment HTTP qui est très versatile) pour créer la fonctionalité attendue. Il est naturel que Microsoft l'ait expérimenté d'abord dans un composant nécessaitnat ActiveX, avant de vouloir l'intégrer d'une façon plus ouverte (ce qu'il a fait depuis). XmlhttpRequest dans ses fonctionalités ne nécessite pas Activex puisqu'il n'a pas besoin d'obtenir des informations du navigateur mais se comporte comme un objet autonome. on doit pouvoir l'instancier de n'importe quel moyen, l'objet lui-même nepouvant interagir qu'à l'aide d'évènements qu'il appartient à l'outil voulant l'intégrer, d'intercepter. ActiveX est une méthode possible d'intégration d'un objet, mais on peut évidemment faire la même chose avec toute autre méthode (DCOM chez Microsoft aussi, ou Corba, ou des bindings spécifiques en Javascript, ou en Java dand un objet Applet, etc. voire même dans d'autres systèmes propiétaires y compris en Flash, ou VB...)

L'important est de comprendre son API, en traitant l'objet comme une boite noire également en dehors de son utilisation (Ajax par exemple n'en est qu'une application d'une toute petite partie de ses fonctionalités), et de comprendre que pour fonctionner, son hôte doit supporter la création de threads (ou processus) séparés, et la transmission asynchrone d'évènements d'un thread (ou processus) dédié à l'objet à un autre, celui spécifié par l'application ; hors il se trouve que XmlHttpRequest n'est qu'une formalisation des fonctionalités de HTTTP (pas de XML) et que donc c'est une façon d'exposer HTTP (un standard international) au travers d'une API. L'objet en lui même n'a rien de propriétaire (ce qui l'est, c'est son intégration via ActiveX). Ce qui peut tromper ici est le nom de l'objet "XmlHttpRequest" qui en fait devrait n'être que "HttpRequest", puisqu'il ne fait absolument rien en XML lui-même (la partie XML est faite par l'application cliente utilisant l'objet, c'est à dire ici la librairie Ajax).

Commentaire de arnotw le 28/05/2008 20:25:44

Bonjour,

Désolé de reveiller ce post, mais ça m'interesse.
Je cherche à éviter le time out car j'ai un script PHP avec une boucle qui doit générer des images à la volée (pas loin de 1200).
Si cela est toutefois possible, je ne vois pas où insérer mon script dans ce code.

merci !

arno

Commentaire de LeFauve42 le 29/05/2008 09:28:40

> Si cela est toutefois possible, je ne vois pas o? ins?rer mon script dans ce code.

Je dirais a la place du sleep(1);

Le code a inserer doit pouvoir generer une image d'apres le numero de la variable $i, que tu initialiseras a 1200.

Bonne chance.

 Ajouter un commentaire


Discussions en rapport avec ce code source dans le forum

Exécuter un lien sans charger la page [ par Siffly ] Je m'explique, je souhaite me faire un petit script d'auto - référencement dans certains moteur de recherche.Dans ce script, il y aurai une url par mo Exécuter du PHP dans un OnClick [ par camouille ] Bonjour !J'ai vu ton message avec le coup d'afficher en javascript, et moi aussi j'essaie d'excuter du code PHP dans un OnClick d'un bouton.J'ajoute q exécuter un fichier exe avec php [ par skmancuso ] Exécuter un programme externe bis [ par fredo35m ] Bonjour, je reviens vers vous car j'ai toujours un soucis pour lancer un ex&#233;cutable !! A priori &#231;a lance le programme je l'ai dans mon gesti Exécuter un .BAT en PHP [ par poulbert ] Je cherche &#224; &#233;x&#233;cuter un .bat dans mon code mais je ne sais pas comment faire.Ou faut il placer le .bat?N'h&#233;sitez pas &#224; etre Exécuter un script a une date précise [ par Tipingouin ] Bonjour Je voudrais savoir si il serait possible d'executer un script PHP &#224; une date pr&#233;cise.... Merci d'avance pas besoin de recharger la page pour exécuter un script php?? [ par Linuss ] Bonjour &#224; tous, J'ai parfois vu quelques sites qui n'avaient pas besoin de recharger une page web pour ex&#233;cuter un script php... quelqu'un s crontab pour windows? [ par Erick007 ] Salut, je cherche un petit logiciel qui pourrait faire comme le fichier crontab de linux. Pour ceux qui ne connaissent pas crontab, c'est un petit fic Exécuter une fonction sur un autre serveur [ par Yapas ] Bonjour,Voila je sais pas si c'est possible mais j' aimerai appeller une fonction sur un autre serveur (dans mon cas lycos) et y faire tourner la fonc Exécuter une page PHP à une date et une heure précise [ par Drazounet ] Bonjour à tous,Je suis en train de créer un site de vente aux enchères. Sur mon site, un vendeur peut sélectionner la liste de ses acheteurs potentiel


Nos sponsors


Sondage...

Comparez les prix

CalendriCode

Février 2012
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
272829    

Consulter la suite du CalendriCode

Photothèque

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,593 sec (4)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales