{"id":2418,"date":"2021-08-04T06:56:44","date_gmt":"2021-08-04T06:56:44","guid":{"rendered":"https:\/\/phptutorial.net\/?page_id=2418"},"modified":"2021-08-04T09:05:31","modified_gmt":"2021-08-04T09:05:31","slug":"php-prg","status":"publish","type":"page","link":"https:\/\/www.phptutorial.net\/php-tutorial\/php-prg\/","title":{"rendered":"PHP PRG (Post-Redirect-Get)"},"content":{"rendered":"\n<p><strong>Summary<\/strong>: in this tutorial, you&#8217;ll learn how to use the PHP PRG (Post-Redirect-Get) technique to prevent the double form submission problem.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id='the-double-submit-problem'>The double submit problem <a href=\"#the-double-submit-problem\" class=\"anchor\" id=\"the-double-submit-problem\" title=\"Anchor for The double submit problem\">#<\/a><\/h2>\n\n\n\n<p>To change data on the server via a <a href=\"https:\/\/phptutorial.net\/php-tutorial\/php-form\/\">form<\/a>, you often use the post method. When a form is submitted, you <a href=\"https:\/\/phptutorial.net\/php-tutorial\/php-form-validation\/\">validate the data<\/a>, update the database, and display the output.<\/p>\n\n\n\n<p>However, if you click the Refresh (or Reload) button of the browser after the form is submitted, the browser will submit the form again. <\/p>\n\n\n\n<p>Since the form uses the POST method, the browser will prompt for confirmation like this:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"532\" height=\"188\" src=\"https:\/\/phptutorial.net\/wp-content\/uploads\/2021\/08\/php-prg-resubmit-the-form-1.png\" alt=\"PHP PRG - Form Resubmission Problem\" class=\"wp-image-2423\" srcset=\"https:\/\/www.phptutorial.net\/wp-content\/uploads\/2021\/08\/php-prg-resubmit-the-form-1.png 532w, https:\/\/www.phptutorial.net\/wp-content\/uploads\/2021\/08\/php-prg-resubmit-the-form-1-300x106.png 300w\" sizes=\"auto, (max-width: 532px) 100vw, 532px\" \/><\/figure>\n\n\n\n<p>If you click the Continue button, the browser will actually submit the form a second time. It&#8217;s a notorious double submit problem that may cause many issues. <\/p>\n\n\n\n<p>For example, you may have duplicate records in the database. If the form processes the payment, it&#8217;ll charge the customer twice.<\/p>\n\n\n\n<p>The following diagram illustrates the double submit problem:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"565\" height=\"297\" src=\"https:\/\/phptutorial.net\/wp-content\/uploads\/2021\/08\/PHP-PRG-Double-Submit-Problem.png\" alt=\"\" class=\"wp-image-2428\" srcset=\"https:\/\/www.phptutorial.net\/wp-content\/uploads\/2021\/08\/PHP-PRG-Double-Submit-Problem.png 565w, https:\/\/www.phptutorial.net\/wp-content\/uploads\/2021\/08\/PHP-PRG-Double-Submit-Problem-300x158.png 300w\" sizes=\"auto, (max-width: 565px) 100vw, 565px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" id='introduction-to-the-php-prg-post-redirect-get-technique'>Introduction to the PHP PRG (post-redirect-get) technique <a href=\"#introduction-to-the-php-prg-post-redirect-get-technique\" class=\"anchor\" id=\"introduction-to-the-php-prg-post-redirect-get-technique\" title=\"Anchor for Introduction to the PHP PRG (post-redirect-get) technique\">#<\/a><\/h2>\n\n\n\n<p>The PRG (post-redirect-get) technique helps you solve the double submit problem. The post-redirect-get works as follows:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>First, the form is submitted using the HTTP POST method.<\/li><li>Second, the server does something, e.g., updates the database, processes a payment, sends an email, and redirects the browser to the result page.<\/li><li>Third, the browser makes the second request to the result page using HTTP GET method.<\/li><li>Finally, the server returns the result page and the browser displays it.<\/li><\/ul>\n\n\n\n<p>If the user refreshes the web browser, the browser will request the result page using the HTTP GET method. <\/p>\n\n\n\n<p class=\"note\">Note that the result page and the page that contains the form can be the same.<\/p>\n\n\n\n<p>The following diagram illustrates how the PRG works:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"666\" height=\"415\" src=\"https:\/\/phptutorial.net\/wp-content\/uploads\/2021\/08\/php-prg-post-redirect-get.png\" alt=\"\" class=\"wp-image-2429\" srcset=\"https:\/\/www.phptutorial.net\/wp-content\/uploads\/2021\/08\/php-prg-post-redirect-get.png 666w, https:\/\/www.phptutorial.net\/wp-content\/uploads\/2021\/08\/php-prg-post-redirect-get-300x187.png 300w\" sizes=\"auto, (max-width: 666px) 100vw, 666px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" id='illustrating-the-double-submit-problem'>Illustrating the double submit problem <a href=\"#illustrating-the-double-submit-problem\" class=\"anchor\" id=\"illustrating-the-double-submit-problem\" title=\"Anchor for Illustrating the double submit problem\">#<\/a><\/h2>\n\n\n\n<p>We&#8217;ll create a simple donation form that illustrates the double submit problem:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-meta\">&lt;?php<\/span>\n\n\n<span class=\"hljs-keyword\">const<\/span> MIN_DONATION = <span class=\"hljs-number\">1<\/span>;\n\n$errors = &#91;];\n$inputs = &#91;];\n$valid = <span class=\"hljs-keyword\">false<\/span>;\n\n<span class=\"hljs-keyword\">if<\/span> ($_SERVER&#91;<span class=\"hljs-string\">'REQUEST_METHOD'<\/span>] === <span class=\"hljs-string\">'POST'<\/span>) {\n\n    <span class=\"hljs-comment\">\/\/ sanitize &amp; validate amount<\/span>\n    $amount = filter_input(INPUT_POST, <span class=\"hljs-string\">'amount'<\/span>, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION);\n    $inputs&#91;<span class=\"hljs-string\">'amount'<\/span>] = $amount;\n    <span class=\"hljs-keyword\">if<\/span> ($amount !== <span class=\"hljs-keyword\">false<\/span> &amp;&amp; $amount !== <span class=\"hljs-keyword\">null<\/span>) {\n        $amount = filter_var($amount, FILTER_VALIDATE_FLOAT, &#91;<span class=\"hljs-string\">'options'<\/span> =&gt; &#91;<span class=\"hljs-string\">'min_range'<\/span> =&gt; MIN_DONATION]]);\n        <span class=\"hljs-keyword\">if<\/span> ($amount === <span class=\"hljs-keyword\">false<\/span>) {\n            $errors&#91;<span class=\"hljs-string\">'amount'<\/span>] = <span class=\"hljs-string\">'The minimum donation is $1'<\/span>;\n        } <span class=\"hljs-keyword\">else<\/span> {\n            $valid = <span class=\"hljs-keyword\">true<\/span>;\n        }\n    } <span class=\"hljs-keyword\">else<\/span> {\n        $errors&#91;<span class=\"hljs-string\">'amount'<\/span>] = <span class=\"hljs-string\">'Please enter a donation amount'<\/span>;\n    }\n}\n<span class=\"hljs-meta\">?&gt;<\/span>\n\n&lt;!DOCTYPE html&gt;\n&lt;html lang=<span class=\"hljs-string\">\"en\"<\/span>&gt;\n\n&lt;head&gt;\n    &lt;meta charset=<span class=\"hljs-string\">\"UTF-8\"<\/span>&gt;\n    &lt;meta name=<span class=\"hljs-string\">\"viewport\"<\/span> content=<span class=\"hljs-string\">\"width=device-width, initial-scale=1.0\"<\/span>&gt;\n    &lt;link rel=<span class=\"hljs-string\">\"stylesheet\"<\/span> href=<span class=\"hljs-string\">\"css\/style.css\"<\/span>&gt;\n    &lt;title&gt;PHP - without PRG&lt;\/title&gt;\n&lt;\/head&gt;\n\n&lt;body&gt;\n    &lt;main&gt;\n        &lt;form action=<span class=\"hljs-string\">\"index.php\"<\/span> method=<span class=\"hljs-string\">\"post\"<\/span>&gt;\n            &lt;h1&gt;Donation&lt;\/h1&gt;\n            <span class=\"hljs-meta\">&lt;?php<\/span> <span class=\"hljs-keyword\">if<\/span> ($valid) : <span class=\"hljs-meta\">?&gt;<\/span>\n                &lt;div <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span>=\"<span class=\"hljs-title\">alert<\/span> <span class=\"hljs-title\">alert<\/span>-<span class=\"hljs-title\">success<\/span>\"&gt;\n                    <span class=\"hljs-title\">Thank<\/span> <span class=\"hljs-title\">you<\/span> <span class=\"hljs-title\">for<\/span> <span class=\"hljs-title\">your<\/span> <span class=\"hljs-title\">donation<\/span> <span class=\"hljs-title\">of<\/span> $&lt;?= $<span class=\"hljs-title\">inputs<\/span>&#91;'<span class=\"hljs-title\">amount<\/span>'] ?? '' ?&gt;\n                &lt;\/<span class=\"hljs-title\">div<\/span>&gt;\n            &lt;?<span class=\"hljs-title\">php<\/span> <span class=\"hljs-title\">endif<\/span> ?&gt;\n            &lt;<span class=\"hljs-title\">div<\/span>&gt;\n                &lt;<span class=\"hljs-title\">label<\/span> <span class=\"hljs-title\">for<\/span>=\"<span class=\"hljs-title\">amount<\/span>\"&gt;<span class=\"hljs-title\">Amount<\/span>:&lt;\/<span class=\"hljs-title\">label<\/span>&gt;\n                &lt;<span class=\"hljs-title\">input<\/span> <span class=\"hljs-title\">type<\/span>=\"<span class=\"hljs-title\">text<\/span>\" <span class=\"hljs-title\">name<\/span>=\"<span class=\"hljs-title\">amount<\/span>\" <span class=\"hljs-title\">value<\/span>=\"&lt;?= $<span class=\"hljs-title\">inputs<\/span>&#91;'<span class=\"hljs-title\">amount<\/span>'] ?? '' ?&gt;\" <span class=\"hljs-title\">id<\/span>=\"<span class=\"hljs-title\">amount<\/span>\" <span class=\"hljs-title\">placeholder<\/span>=\"<span class=\"hljs-title\">Minimum<\/span> <span class=\"hljs-title\">donation<\/span> $&lt;?= <span class=\"hljs-title\">MIN_DONATION<\/span> ?&gt;\"&gt;\n                &lt;<span class=\"hljs-title\">small<\/span>&gt;&lt;?= $<span class=\"hljs-title\">errors<\/span>&#91;'<span class=\"hljs-title\">amount<\/span>'] ??  '' ?&gt;&lt;\/<span class=\"hljs-title\">small<\/span>&gt;\n            &lt;\/<span class=\"hljs-title\">div<\/span>&gt;\n            &lt;<span class=\"hljs-title\">button<\/span> <span class=\"hljs-title\">type<\/span>=\"<span class=\"hljs-title\">submit<\/span>\"&gt;<span class=\"hljs-title\">Donate<\/span>&lt;\/<span class=\"hljs-title\">button<\/span>&gt;\n        &lt;\/<span class=\"hljs-title\">form<\/span>&gt;\n    &lt;\/<span class=\"hljs-title\">main<\/span>&gt;\n&lt;\/<span class=\"hljs-title\">body<\/span>&gt;\n&lt;\/<span class=\"hljs-title\">html<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>How it works.<\/p>\n\n\n\n<p>The form contains one input field that accepts a positive amount with a value greater than 1.<\/p>\n\n\n\n<p>The <code>MIN_DONATION<\/code> <a href=\"https:\/\/phptutorial.net\/php-tutorial\/php-constants\/\">constant<\/a> specifies the minimum value of the amount field:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-keyword\">const<\/span> MIN_DONATION = <span class=\"hljs-number\">1<\/span>;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>When the form is submitted using the post method, we <a href=\"https:\/\/phptutorial.net\/php-tutorial\/php-form-validation\/\">sanitize and validate<\/a> the amount using the <code><a href=\"https:\/\/phptutorial.net\/php-tutorial\/php-filter_input\/\">filter_input()<\/a><\/code> and <code><a href=\"https:\/\/phptutorial.net\/php-tutorial\/php-filter_var\/\">filter_var()<\/a><\/code> functions. <\/p>\n\n\n\n<p>The following sanitizes the amount value from the <code>INPUT_POST<\/code>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">$amount = filter_input(INPUT_POST, <span class=\"hljs-string\">'amount'<\/span>, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION); <\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Notice that if you don&#8217;t specify the <code>FILTER_FLAG_ALLOW_FRACTION<\/code> flag, the function will remove the decimal point (<code>.<\/code>) from the entered value.<\/p>\n\n\n\n<p>If the amount doesn&#8217;t exist in the <code>INPUT_POST<\/code>, the <code>filter_input()<\/code> returns <code>null<\/code>. If the amount is not a valid float, the <code>filter_input()<\/code> function returns <code>false<\/code>.<\/p>\n\n\n\n<p>The following checks if the amount is a valid float and greater than or equal to 1:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">$amount = filter_var($amount, FILTER_VALIDATE_FLOAT, &#91;<span class=\"hljs-string\">'options'<\/span> =&gt; &#91;<span class=\"hljs-string\">'min_range'<\/span> =&gt; MIN_DONATION]]);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>If the amount is valid, we set the <code>$valid<\/code> variable to <code>true<\/code>. Otherwise, we add the error messages to the <code>$errors<\/code> array. Also, we add the filtered value to the <code>$inputs<\/code> array.<\/p>\n\n\n\n<p><\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-keyword\">if<\/span> ($_SERVER&#91;<span class=\"hljs-string\">'REQUEST_METHOD'<\/span>] === <span class=\"hljs-string\">'POST'<\/span>) {    \n    <span class=\"hljs-comment\">\/\/ sanitize &amp; validate amount<\/span>\n    $amount = filter_input(INPUT_POST, <span class=\"hljs-string\">'amount'<\/span>, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION);\n    $inputs&#91;<span class=\"hljs-string\">'amount'<\/span>] = $amount;\n    <span class=\"hljs-keyword\">if<\/span> ($amount !== <span class=\"hljs-keyword\">false<\/span> &amp;&amp; $amount !== <span class=\"hljs-keyword\">null<\/span>) {\n        $amount = filter_var($amount, FILTER_VALIDATE_FLOAT, &#91;<span class=\"hljs-string\">'options'<\/span> =&gt; &#91;<span class=\"hljs-string\">'min_range'<\/span> =&gt; MIN_DONATION]]);\n        <span class=\"hljs-keyword\">if<\/span> ($amount === <span class=\"hljs-keyword\">false<\/span>) {\n            $errors&#91;<span class=\"hljs-string\">'amount'<\/span>] = <span class=\"hljs-string\">'The minimum donation is $1'<\/span>;\n        } <span class=\"hljs-keyword\">else<\/span> {\n            $valid = <span class=\"hljs-keyword\">true<\/span>;\n        }\n    } <span class=\"hljs-keyword\">else<\/span> {\n        $errors&#91;<span class=\"hljs-string\">'amount'<\/span>] = <span class=\"hljs-string\">'Please enter a donation amount'<\/span>;\n    }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>In the form, we show a success message if the amount field is valid. Otherwise, we show the entered value with an error message.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">form<\/span> <span class=\"hljs-attr\">action<\/span>=<span class=\"hljs-string\">\"index.php\"<\/span> <span class=\"hljs-attr\">method<\/span>=<span class=\"hljs-string\">\"post\"<\/span>&gt;<\/span>\r\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h1<\/span>&gt;<\/span>Donation<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h1<\/span>&gt;<\/span>\r\n    <span class=\"php\"><span class=\"hljs-meta\">&lt;?php<\/span> <span class=\"hljs-keyword\">if<\/span> ($valid) : <span class=\"hljs-meta\">?&gt;<\/span><\/span>\r\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"alert alert-success\"<\/span>&gt;<\/span>\r\n            Thank you for your donation of $<span class=\"php\"><span class=\"hljs-meta\">&lt;?<\/span>= $inputs&#91;<span class=\"hljs-string\">'amount'<\/span>] ?? <span class=\"hljs-string\">''<\/span> <span class=\"hljs-meta\">?&gt;<\/span><\/span>\r\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\r\n    <span class=\"php\"><span class=\"hljs-meta\">&lt;?php<\/span> <span class=\"hljs-keyword\">endif<\/span> <span class=\"hljs-meta\">?&gt;<\/span><\/span>\r\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span>&gt;<\/span>\r\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">label<\/span> <span class=\"hljs-attr\">for<\/span>=<span class=\"hljs-string\">\"amount\"<\/span>&gt;<\/span>Amount:<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">label<\/span>&gt;<\/span>\r\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">input<\/span> <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"text\"<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"amount\"<\/span> <span class=\"hljs-attr\">value<\/span>=<span class=\"hljs-string\">\"&lt;?= $inputs&#91;'amount'] ?? '' ?&gt;\"<\/span> <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"amount\"<\/span> <span class=\"hljs-attr\">placeholder<\/span>=<span class=\"hljs-string\">\"Minimum donation $&lt;?= MIN_DONATION ?&gt;\"<\/span>&gt;<\/span>\r\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">small<\/span>&gt;<\/span><span class=\"php\"><span class=\"hljs-meta\">&lt;?<\/span>= $errors&#91;<span class=\"hljs-string\">'amount'<\/span>] ??  <span class=\"hljs-string\">''<\/span> <span class=\"hljs-meta\">?&gt;<\/span><\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">small<\/span>&gt;<\/span>\r\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\r\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">button<\/span> <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"submit\"<\/span>&gt;<\/span>Donate<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">button<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">form<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>To demonstrate the double submit problem, you can enter a valid value and click the Donate button. Once you see the success message, you can click the Refresh button on the web browser.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id='fix-the-double-form-submit-problem-using-the-prg-technique'>Fix the double form submit problem using the PRG technique <a href=\"#fix-the-double-form-submit-problem-using-the-prg-technique\" class=\"anchor\" id=\"fix-the-double-form-submit-problem-using-the-prg-technique\" title=\"Anchor for Fix the double form submit problem using the PRG technique\">#<\/a><\/h2>\n\n\n\n<p>The following illustrates how to use the PRG technique to fix the double submit problem:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-meta\">&lt;?php<\/span>\n\nsession_start();\n\n<span class=\"hljs-keyword\">const<\/span> MIN_DONATION = <span class=\"hljs-number\">1<\/span>;\n\n$errors = &#91;];\n$inputs = &#91;];\n$valid = <span class=\"hljs-keyword\">false<\/span>;\n\n$request_method = strtoupper($_SERVER&#91;<span class=\"hljs-string\">'REQUEST_METHOD'<\/span>]);\n\n<span class=\"hljs-keyword\">if<\/span> ($request_method === <span class=\"hljs-string\">'POST'<\/span>) {\n    <span class=\"hljs-comment\">\/\/ sanitize &amp; validate amount<\/span>\n    $amount = filter_input(INPUT_POST, <span class=\"hljs-string\">'amount'<\/span>, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION);\n    $inputs&#91;<span class=\"hljs-string\">'amount'<\/span>] = $amount;\n    <span class=\"hljs-keyword\">if<\/span> ($amount !== <span class=\"hljs-keyword\">false<\/span> &amp;&amp; $amount !== <span class=\"hljs-keyword\">null<\/span>) {\n        $amount = filter_var($amount, FILTER_VALIDATE_FLOAT, &#91;<span class=\"hljs-string\">'options'<\/span> =&gt; &#91;<span class=\"hljs-string\">'min_range'<\/span> =&gt; MIN_DONATION]]);\n        <span class=\"hljs-keyword\">if<\/span> ($amount === <span class=\"hljs-keyword\">false<\/span>) {\n            $errors&#91;<span class=\"hljs-string\">'amount'<\/span>] = <span class=\"hljs-string\">'The minimum donation is $1'<\/span>;\n        } <span class=\"hljs-keyword\">else<\/span> {\n            $valid = <span class=\"hljs-keyword\">true<\/span>;\n        }\n    } <span class=\"hljs-keyword\">else<\/span> {\n        $errors&#91;<span class=\"hljs-string\">'amount'<\/span>] = <span class=\"hljs-string\">'Please enter a donation amount'<\/span>;\n    }\n    <span class=\"hljs-comment\">\/\/ process the payment<\/span>\n    <span class=\"hljs-comment\">\/\/ ...<\/span>\n\n    <span class=\"hljs-comment\">\/\/ place variables to sessions<\/span>\n    $_SESSION&#91;<span class=\"hljs-string\">'valid'<\/span>] = $valid;\n    $_SESSION&#91;<span class=\"hljs-string\">'errors'<\/span>] = $errors;\n    $_SESSION&#91;<span class=\"hljs-string\">'inputs'<\/span>] = $inputs;\n\n    <span class=\"hljs-comment\">\/\/ redirect to the page itself<\/span>\n    header(<span class=\"hljs-string\">'Location: index2.php'<\/span>, <span class=\"hljs-keyword\">true<\/span>, <span class=\"hljs-number\">303<\/span>);\n    <span class=\"hljs-keyword\">exit<\/span>;\n} <span class=\"hljs-keyword\">elseif<\/span> ($request_method === <span class=\"hljs-string\">'GET'<\/span>) {\n    <span class=\"hljs-keyword\">if<\/span> (<span class=\"hljs-keyword\">isset<\/span>($_SESSION&#91;<span class=\"hljs-string\">'valid'<\/span>])) {\n        <span class=\"hljs-comment\">\/\/ get the valid state from the session<\/span>\n        $valid = $_SESSION&#91;<span class=\"hljs-string\">'valid'<\/span>];\n        <span class=\"hljs-keyword\">unset<\/span>($_SESSION&#91;<span class=\"hljs-string\">'valid'<\/span>]);\n    }\n\n    <span class=\"hljs-keyword\">if<\/span> (<span class=\"hljs-keyword\">isset<\/span>($_SESSION&#91;<span class=\"hljs-string\">'errors'<\/span>])) {\n        $errors = $_SESSION&#91;<span class=\"hljs-string\">'errors'<\/span>];\n        <span class=\"hljs-keyword\">unset<\/span>($_SESSION&#91;<span class=\"hljs-string\">'errors'<\/span>]);\n    }\n\n    <span class=\"hljs-keyword\">if<\/span> (<span class=\"hljs-keyword\">isset<\/span>($_SESSION&#91;<span class=\"hljs-string\">'inputs'<\/span>])) {\n        $errors = $_SESSION&#91;<span class=\"hljs-string\">'inputs'<\/span>];\n        <span class=\"hljs-keyword\">unset<\/span>($_SESSION&#91;<span class=\"hljs-string\">'inputs'<\/span>]);\n    }\n}\n<span class=\"hljs-meta\">?&gt;<\/span>\n&lt;!DOCTYPE html&gt;\n&lt;html lang=<span class=\"hljs-string\">\"en\"<\/span>&gt;\n\n&lt;head&gt;\n    &lt;meta charset=<span class=\"hljs-string\">\"UTF-8\"<\/span>&gt;\n    &lt;meta name=<span class=\"hljs-string\">\"viewport\"<\/span> content=<span class=\"hljs-string\">\"width=device-width, initial-scale=1.0\"<\/span>&gt;\n    &lt;link rel=<span class=\"hljs-string\">\"stylesheet\"<\/span> href=<span class=\"hljs-string\">\"css\/style.css\"<\/span>&gt;\n    &lt;title&gt;PHP PRG&lt;\/title&gt;\n&lt;\/head&gt;\n\n&lt;body&gt;\n    &lt;main&gt;\n        <span class=\"hljs-meta\">&lt;?php<\/span> <span class=\"hljs-keyword\">if<\/span> ($valid) : <span class=\"hljs-meta\">?&gt;<\/span>\n            &lt;div <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span>=\"<span class=\"hljs-title\">alert<\/span> <span class=\"hljs-title\">alert<\/span>-<span class=\"hljs-title\">success<\/span>\"&gt;\n                <span class=\"hljs-title\">Thank<\/span> <span class=\"hljs-title\">you<\/span> <span class=\"hljs-title\">for<\/span> <span class=\"hljs-title\">your<\/span> <span class=\"hljs-title\">donation<\/span> <span class=\"hljs-title\">of<\/span> $&lt;?= $<span class=\"hljs-title\">inputs<\/span>&#91;'<span class=\"hljs-title\">amount<\/span>'] ?? '' ?&gt;\n            &lt;\/<span class=\"hljs-title\">div<\/span>&gt;\n        &lt;?<span class=\"hljs-title\">php<\/span> <span class=\"hljs-title\">endif<\/span> ?&gt;\n\n        &lt;<span class=\"hljs-title\">form<\/span> <span class=\"hljs-title\">action<\/span>=\"<span class=\"hljs-title\">index<\/span>.<span class=\"hljs-title\">php<\/span>\" <span class=\"hljs-title\">method<\/span>=\"<span class=\"hljs-title\">post<\/span>\"&gt;\n            &lt;<span class=\"hljs-title\">h1<\/span>&gt;<span class=\"hljs-title\">Donation<\/span>&lt;\/<span class=\"hljs-title\">h1<\/span>&gt;\n            &lt;<span class=\"hljs-title\">div<\/span>&gt;\n                &lt;<span class=\"hljs-title\">label<\/span> <span class=\"hljs-title\">for<\/span>=\"<span class=\"hljs-title\">amount<\/span>\"&gt;<span class=\"hljs-title\">Amount<\/span>:&lt;\/<span class=\"hljs-title\">label<\/span>&gt;\n                &lt;<span class=\"hljs-title\">input<\/span> <span class=\"hljs-title\">type<\/span>=\"<span class=\"hljs-title\">text<\/span>\" <span class=\"hljs-title\">name<\/span>=\"<span class=\"hljs-title\">amount<\/span>\" <span class=\"hljs-title\">value<\/span>=\"&lt;?= $<span class=\"hljs-title\">inputs<\/span>&#91;'<span class=\"hljs-title\">amount<\/span>'] ?? '' ?&gt;\" <span class=\"hljs-title\">id<\/span>=\"<span class=\"hljs-title\">amount<\/span>\" <span class=\"hljs-title\">placeholder<\/span>=\"<span class=\"hljs-title\">Minimum<\/span> <span class=\"hljs-title\">donation<\/span> $&lt;?= <span class=\"hljs-title\">MIN_DONATION<\/span> ?&gt;\"&gt;\n                &lt;<span class=\"hljs-title\">small<\/span>&gt;&lt;?= $<span class=\"hljs-title\">errors<\/span>&#91;'<span class=\"hljs-title\">amount<\/span>'] ?? '' ?&gt;&lt;\/<span class=\"hljs-title\">small<\/span>&gt;\n            &lt;\/<span class=\"hljs-title\">div<\/span>&gt;\n            &lt;<span class=\"hljs-title\">button<\/span> <span class=\"hljs-title\">type<\/span>=\"<span class=\"hljs-title\">submit<\/span>\"&gt;<span class=\"hljs-title\">Donate<\/span>&lt;\/<span class=\"hljs-title\">button<\/span>&gt;\n        &lt;\/<span class=\"hljs-title\">form<\/span>&gt;\n    &lt;\/<span class=\"hljs-title\">main<\/span>&gt;\n\n&lt;\/<span class=\"hljs-title\">body<\/span>&gt;\n\n&lt;\/<span class=\"hljs-title\">html<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>How it works.<\/p>\n\n\n\n<p>First, call the <code>session_start()<\/code> to access the <code>$_SESSION<\/code> data:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">session_start();<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Second, sanitize and validate the amount like the previous example; Also, add the variables <code>$valid<\/code>, <code>$errors<\/code>, and <code>$inputs<\/code> to the session to be able to access them in the subsequent request.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-comment\">\/\/ add variables to session<\/span>\n$_SESSION&#91;<span class=\"hljs-string\">'valid'<\/span>] = $valid;\n$_SESSION&#91;<span class=\"hljs-string\">'errors'<\/span>] = $errors;\n$_SESSION&#91;<span class=\"hljs-string\">'inputs'<\/span>] = $inputs;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Third, <a href=\"https:\/\/phptutorial.net\/php-tutorial\/php-redirection\/\">redirect the browser<\/a> to the same page with the <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/HTTP\/Status\/303\" target=\"_blank\" rel=\"noreferrer noopener\">HTTP status code 303<\/a> using the <code>header()<\/code> function:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-comment\">\/\/ redirect to the page itself<\/span>\nheader(<span class=\"hljs-string\">'Location: index.php'<\/span>, <span class=\"hljs-keyword\">true<\/span>, <span class=\"hljs-number\">303<\/span>);\n<span class=\"hljs-keyword\">exit<\/span>;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Fourth, get the variables from the session if the HTTP request method is the GET and remove them from the session immediately:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-keyword\">if<\/span> (<span class=\"hljs-keyword\">isset<\/span>($_SESSION&#91;<span class=\"hljs-string\">'valid'<\/span>])) {\n    $valid = $_SESSION&#91;<span class=\"hljs-string\">'valid'<\/span>];\n    <span class=\"hljs-keyword\">unset<\/span>($_SESSION&#91;<span class=\"hljs-string\">'valid'<\/span>]);\n}\n\n<span class=\"hljs-keyword\">if<\/span> (<span class=\"hljs-keyword\">isset<\/span>($_SESSION&#91;<span class=\"hljs-string\">'errors'<\/span>])) {\n    $errors = $_SESSION&#91;<span class=\"hljs-string\">'errors'<\/span>];\n    <span class=\"hljs-keyword\">unset<\/span>($_SESSION&#91;<span class=\"hljs-string\">'errors'<\/span>]);\n}\n\n<span class=\"hljs-keyword\">if<\/span> (<span class=\"hljs-keyword\">isset<\/span>($_SESSION&#91;<span class=\"hljs-string\">'inputs'<\/span>])) {\n    $errors = $_SESSION&#91;<span class=\"hljs-string\">'inputs'<\/span>];\n    <span class=\"hljs-keyword\">unset<\/span>($_SESSION&#91;<span class=\"hljs-string\">'inputs'<\/span>]);\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The remaining code is the same as the previous example.<\/p>\n\n\n\n<p>If you click the Refresh button after submitting the form, the browser won&#8217;t submit the form again. Instead, the browser loads the form using the GET method.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id='summary'>Summary <a href=\"#summary\" class=\"anchor\" id=\"summary\" title=\"Anchor for Summary\">#<\/a><\/h2>\n\n\n\n<ul class=\"wp-block-list\"><li>PRG stands for Post-Redirect-Get.<\/li><li>PRG helps prevent the double form submit problem.<\/li><\/ul>\n<div class=\"helpful-block-content\" data-title=\"\">\n\t<header>\n\t\t<div class=\"wth-question\">Did you find this tutorial useful?<\/div>\n\t\t<div class=\"wth-thumbs\">\n\t\t\t<button\n\t\t\t\tdata-post=\"2418\"\n\t\t\t\tdata-post-url=\"https:\/\/www.phptutorial.net\/php-tutorial\/php-prg\/\"\n\t\t\t\tdata-post-title=\"PHP PRG (Post-Redirect-Get)\"\n\t\t\t\tdata-response=\"1\"\n\t\t\t\tclass=\"wth-btn-rounded wth-yes-btn\"\n\t\t\t>\n\t\t\t\t<svg\n\t\t\t\t\txmlns=\"http:\/\/www.w3.org\/2000\/svg\"\n\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\tfill=\"none\"\n\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\tstroke-width=\"2\"\n\t\t\t\t\tstroke-linecap=\"round\"\n\t\t\t\t\tstroke-linejoin=\"round\"\n\t\t\t\t\tclass=\"feather feather-thumbs-up block w-full h-full\"\n\t\t\t\t>\n\t\t\t\t\t<path\n\t\t\t\t\t\td=\"M14 9V5a3 3 0 0 0-3-3l-4 9v11h11.28a2 2 0 0 0 2-1.7l1.38-9a2 2 0 0 0-2-2.3zM7 22H4a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2h3\"\n\t\t\t\t\t><\/path>\n\t\t\t\t<\/svg>\n\t\t\t\t<span class=\"sr-only\"> Yes <\/span>\n\t\t\t<\/button>\n\n\t\t\t<button\n\t\t\t\tdata-response=\"0\"\n\t\t\t\tdata-post=\"2418\"\n\t\t\t\tdata-post-url=\"https:\/\/www.phptutorial.net\/php-tutorial\/php-prg\/\"\n\t\t\t\tdata-post-title=\"PHP PRG (Post-Redirect-Get)\"\n\t\t\t\tclass=\"wth-btn-rounded wth-no-btn\"\n\t\t\t>\n\t\t\t\t<svg\n\t\t\t\t\txmlns=\"http:\/\/www.w3.org\/2000\/svg\"\n\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\tfill=\"none\"\n\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\tstroke-width=\"2\"\n\t\t\t\t\tstroke-linecap=\"round\"\n\t\t\t\t\tstroke-linejoin=\"round\"\n\t\t\t\t>\n\t\t\t\t\t<path\n\t\t\t\t\t\td=\"M10 15v4a3 3 0 0 0 3 3l4-9V2H5.72a2 2 0 0 0-2 1.7l-1.38 9a2 2 0 0 0 2 2.3zm7-13h2.67A2.31 2.31 0 0 1 22 4v7a2.31 2.31 0 0 1-2.33 2H17\"\n\t\t\t\t\t><\/path>\n\t\t\t\t<\/svg>\n\t\t\t\t<span class=\"sr-only\"> No <\/span>\n\t\t\t<\/button>\n\t\t<\/div>\n\t<\/header>\n\n\t<div class=\"wth-form hidden\">\n\t\t<div class=\"wth-form-wrapper\">\n\t\t\t<div class=\"wth-title\"><\/div>\n\t\t\t\n\t\t\t<textarea class=\"wth-message\"><\/textarea>\n\n\t\t\t<button class=\"btn btn-primary wth-btn-submit\">Send<\/button>\n\t\t\t<button class=\"btn wth-btn-cancel\">Cancel<\/button>\n\t\t\n\t\t<\/div>\n\t<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>In this tutorial, you&#8217;ll learn how to use the PHP PRG (Post-Redirect-Get) technique to prevent the double form submission problem.<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":15,"menu_order":93,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-2418","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.phptutorial.net\/wp-json\/wp\/v2\/pages\/2418","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.phptutorial.net\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.phptutorial.net\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.phptutorial.net\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.phptutorial.net\/wp-json\/wp\/v2\/comments?post=2418"}],"version-history":[{"count":4,"href":"https:\/\/www.phptutorial.net\/wp-json\/wp\/v2\/pages\/2418\/revisions"}],"predecessor-version":[{"id":2430,"href":"https:\/\/www.phptutorial.net\/wp-json\/wp\/v2\/pages\/2418\/revisions\/2430"}],"up":[{"embeddable":true,"href":"https:\/\/www.phptutorial.net\/wp-json\/wp\/v2\/pages\/15"}],"wp:attachment":[{"href":"https:\/\/www.phptutorial.net\/wp-json\/wp\/v2\/media?parent=2418"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}