<?php
include_once $_SERVER['DOCUMENT_ROOT'] . '/include/shared-manual.inc';
$TOC = array();
$TOC_DEPRECATED = array();
$PARENTS = array();
include_once dirname(__FILE__) ."/toc/book.pdo.inc";
$setup = array (
  'home' => 
  array (
    0 => 'index.php',
    1 => 'PHP Manual',
  ),
  'head' => 
  array (
    0 => 'UTF-8',
    1 => 'fr',
  ),
  'this' => 
  array (
    0 => 'pdo.transactions.php',
    1 => 'Transactions et validation automatique (autocommit)',
    2 => 'Transactions et validation automatique (autocommit)',
  ),
  'up' => 
  array (
    0 => 'book.pdo.php',
    1 => 'PDO',
  ),
  'prev' => 
  array (
    0 => 'pdo.connections.php',
    1 => 'Connexions et gestionnaire de connexion',
  ),
  'next' => 
  array (
    0 => 'pdo.prepared-statements.php',
    1 => 'Requ&ecirc;tes pr&eacute;par&eacute;es et proc&eacute;dures stock&eacute;es',
  ),
  'alternatives' => 
  array (
  ),
  'source' => 
  array (
    'lang' => 'fr',
    'path' => 'reference/pdo/transactions.xml',
  ),
  'history' => 
  array (
  ),
);
$setup["toc"] = $TOC;
$setup["toc_deprecated"] = $TOC_DEPRECATED;
$setup["parents"] = $PARENTS;
manual_setup($setup);

contributors($setup);

?>
<div id="pdo.transactions" class="chapter">
 <h1 class="title">Transactions et validation automatique (autocommit)</h1>

 <p class="para">
  Maintenant que l&#039;on est connecté via PDO, il faut comprendre
  comment PDO gère les transactions avant d&#039;exécuter des requêtes. Si l&#039;on n&#039;a
  jamais utilisé les transactions, elles offrent 4 fonctionnalités majeures :
  Atomicité, Consistance, Isolation et Durabilité (ACID). En d&#039;autres termes,
  n&#039;importe quel travail mené à bien dans une transaction, même s&#039;il est effectué
  par étapes, est garanti d&#039;être appliqué à la base de données sans risque, et sans
  interférence pour les autres connexions, quand il est validé. Le travail des transactions
  peut également être automatiquement annulé à la demande (en supposant que
  l&#039;on n&#039;ait encore rien validé), ce qui rend la gestion des erreurs bien plus
  simple dans les scripts.
 </p>
 <p class="para">
  Les transactions sont typiquement implémentées pour appliquer
  toutes les modifications en une seule fois ; ceci a le bel effet d&#039;éprouver
  radicalement l&#039;efficacité des mises à jour. En d&#039;autres termes,
  les transactions rendent les scripts plus rapides et potentiellement plus
  robustes (il faut les utiliser correctement pour jouir de ces bénéfices).
 </p>
 <p class="para">
  Malheureusement, toutes les bases de données ne prennent pas en charge les transactions,
  donc PDO doit s&#039;exécuter en mode &quot;autocommit&quot; lorsque l&#039;on ouvre pour la première
  fois la connexion. Le mode &quot;autocommit&quot; signifie que toutes les requêtes que l&#039;on
  exécute ont leurs transactions implicites, si la base de données le prend en charge ou
  aucune transaction si la base de données ne les prend pas en charge. En cas de besoin
  d&#039;une transaction, il faut utiliser la méthode <span class="methodname"><a href="pdo.begintransaction.php" class="methodname">PDO::beginTransaction()</a></span>
  pour l&#039;initialiser. Si le pilote utilisé ne prend pas en charge les transactions, une
  exception PDO sera lancée (en accord avec le gestionnaire d&#039;erreurs : ceci est toujours
  une erreur sérieuse). Une fois que l&#039;on est dans une transaction, il faut utiliser
  la fonction <span class="methodname"><a href="pdo.commit.php" class="methodname">PDO::commit()</a></span> ou la fonction <span class="methodname"><a href="pdo.rollback.php" class="methodname">PDO::rollBack()</a></span>
  pour la terminer, suivant le succès du code durant la transaction.
 </p>
 <div class="warning"><strong class="warning">Avertissement</strong>
  <p class="para">
   PDO ne vérifie la possibilité d&#039;utiliser des transactions qu&#039;au niveau du pilote.
   Si certaines conditions à l&#039;exécution empêchent les transactions de fonctionner,
   <span class="methodname"><a href="pdo.begintransaction.php" class="methodname">PDO::beginTransaction()</a></span> retournera tout de même <strong><code><a href="reserved.constants.php#constant.true">true</a></code></strong>
   sans erreur si le serveur accepte de démarrer une transaction.
  </p>
  <p class="para">
   Un exemple serait d&#039;utiliser des transactions sur des tables au format MyISAM
   du serveur de base de données MySQL.
  </p>
 </div>
 <div class="warning"><strong class="warning">Avertissement</strong>
  <p class="para">
    <em>Commit implicite avec des déclarations DDL :</em>
    Certaines bases de données émettent automatiquement un
    <code class="literal">COMMIT</code> implicite lorsqu&#039;une déclaration de langage de définition de base de données (DDL),
    telle que <code class="literal">DROP TABLE</code> ou <code class="literal">CREATE TABLE</code>,
    est exécutée dans une transaction. Cela signifie que toutes les modifications précédentes effectuées dans la
    même transaction seront <em>automatiquement validées</em> et ne peuvent pas
    être annulées.
  </p>
  <p class="para">
    <code class="literal">MySQL</code> et <code class="literal">Oracle</code> sont des exemples de bases de données qui
    présentent ce comportement.
  </p>
  </div>
  <p class="para">
  <div class="example" id="example-1">
    <p><strong>Exemple #1 Exemple de Commit implicite</strong></p>
    <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br />$pdo</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">beginTransaction</span><span style="color: #007700">();<br /></span><span style="color: #0000BB">$pdo</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">exec</span><span style="color: #007700">(</span><span style="color: #DD0000">"INSERT INTO users (name) VALUES ('Rasmus')"</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">$pdo</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">exec</span><span style="color: #007700">(</span><span style="color: #DD0000">"CREATE TABLE test (id INT PRIMARY KEY)"</span><span style="color: #007700">); </span><span style="color: #FF8000">// Un COMMIT implicite se produit ici<br /></span><span style="color: #0000BB">$pdo</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">rollBack</span><span style="color: #007700">(); </span><span style="color: #FF8000">// Cela NE annulera PAS l'INSERT/CREATE pour MySQL ou Oracle<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
    </div>

  </div>
  </p>
  <p class="para">
  <em>Meilleure pratique :</em> Évitez d&#039;exécuter des déclarations DDL à l&#039;intérieur des transactions
  lors de l&#039;utilisation des bases de données qui imposent ce comportement. Si nécessaire, séparez les opérations DDL
  de la logique transactionnelle.
 </p>
 <p class="para">
  Lorsque le script se termine ou lorsque la connexion est sur le point de se fermer,
  si l&#039;on a une transaction en cours, PDO l&#039;annulera automatiquement.
  Ceci est une mesure de sécurité afin de garantir l&#039;intégrité des données
  dans le cas où le script se termine d&#039;une façon inattendue. Si on ne valide pas
  explicitement la transaction, alors, on présume que quelque chose s&#039;est mal passé
  et l&#039;annulation de la transaction intervient afin de garantir la sécurité des données.
 </p>
 <div class="warning"><strong class="warning">Avertissement</strong>
  <p class="para">
   L&#039;annulation automatique intervient si l&#039;on a initialisé la transaction via
   <span class="methodname"><a href="pdo.begintransaction.php" class="methodname">PDO::beginTransaction()</a></span>. Si l&#039;on a manuellement
   exécuté une requête qui commence une transaction, PDO n&#039;a aucun moyen de
   le savoir et donc, n&#039;annulera pas automatiquement cette transaction si quelque
   chose s&#039;est mal passé.
  </p>
 </div>
 <p class="para">
  <div class="example" id="example-2">
   <p><strong>Exemple #2 Exécution d&#039;un groupe dans une transaction</strong></p>
   <div class="example-contents"><p>
    Dans l&#039;exemple suivant, supposons que nous allons créer un jeu d&#039;entrées
    pour un nouvel employé, dont le numéro d&#039;ID sera 23.
    En plus des données de base sur cette personne, nous devons également
    lui enregistrer son salaire. Il est très simple d&#039;effectuer deux mises à jour
    séparées, mais en les enfermant dans les appels des fonctions
    <span class="methodname"><a href="pdo.begintransaction.php" class="methodname">PDO::beginTransaction()</a></span> et
    <span class="methodname"><a href="pdo.commit.php" class="methodname">PDO::commit()</a></span>, nous garantissons que personne
    ne pourra voir ces modifications tant qu&#039;elles ne seront pas complètes.
    Si quelque chose tourne mal, le bloc de capture annulera toutes les
    modifications effectuées depuis le début de la transaction et affichera
    un message d&#039;erreur.
   </p></div>
   <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /></span><span style="color: #007700">try {<br />  </span><span style="color: #0000BB">$dbh </span><span style="color: #007700">= new </span><span style="color: #0000BB">PDO</span><span style="color: #007700">(</span><span style="color: #DD0000">'odbc:SAMPLE'</span><span style="color: #007700">, </span><span style="color: #DD0000">'db2inst1'</span><span style="color: #007700">, </span><span style="color: #DD0000">'ibmdb2'</span><span style="color: #007700">,<br />      array(</span><span style="color: #0000BB">PDO</span><span style="color: #007700">::</span><span style="color: #0000BB">ATTR_PERSISTENT </span><span style="color: #007700">=&gt; </span><span style="color: #0000BB">true</span><span style="color: #007700">));<br />  echo </span><span style="color: #DD0000">"Connecté\n"</span><span style="color: #007700">;<br />} catch (</span><span style="color: #0000BB">Exception $e</span><span style="color: #007700">) {<br />  die(</span><span style="color: #DD0000">"Impossible de se connecter : " </span><span style="color: #007700">. </span><span style="color: #0000BB">$e</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">getMessage</span><span style="color: #007700">());<br />}<br /><br />try {  <br />  </span><span style="color: #0000BB">$dbh</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">setAttribute</span><span style="color: #007700">(</span><span style="color: #0000BB">PDO</span><span style="color: #007700">::</span><span style="color: #0000BB">ATTR_ERRMODE</span><span style="color: #007700">, </span><span style="color: #0000BB">PDO</span><span style="color: #007700">::</span><span style="color: #0000BB">ERRMODE_EXCEPTION</span><span style="color: #007700">);<br /><br />  </span><span style="color: #0000BB">$dbh</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">beginTransaction</span><span style="color: #007700">();<br />  </span><span style="color: #0000BB">$dbh</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">exec</span><span style="color: #007700">(</span><span style="color: #DD0000">"insert into staff (id, first, last) values (23, 'Joe', 'Bloggs')"</span><span style="color: #007700">);<br />  </span><span style="color: #0000BB">$dbh</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">exec</span><span style="color: #007700">(</span><span style="color: #DD0000">"insert into salarychange (id, amount, changedate) <br />      values (23, 50000, NOW())"</span><span style="color: #007700">);<br />  </span><span style="color: #0000BB">$dbh</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">commit</span><span style="color: #007700">();<br /><br />} catch (</span><span style="color: #0000BB">Exception $e</span><span style="color: #007700">) {<br />  </span><span style="color: #0000BB">$dbh</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">rollBack</span><span style="color: #007700">();<br />  echo </span><span style="color: #DD0000">"Failed: " </span><span style="color: #007700">. </span><span style="color: #0000BB">$e</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">getMessage</span><span style="color: #007700">();<br />}<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
   </div>

  </div>
 </p>
 <p class="para">
  On n&#039;est pas limités dans le nombre de mises à jour dans une transaction ;
  il est également possible d&#039;y effectuer des requêtes complexes et bien sûr, utiliser
  ces informations pour construire d&#039;autres mises à jour et requêtes ; durant l&#039;activité
  de la transaction, l&#039;on est sûrs que personne d&#039;autre ne peut effectuer des
  modifications alors que l&#039;on est au milieu des modifications.
  Pour plus d&#039;informations sur les transactions, se reporter à la documentation
  fournie par la base de données.
 </p>
</div>
<?php manual_footer($setup); ?>