8722 sujets

Développement web côté serveur, CMS

Modérateur
Salut tout le monde,

En voulant faire une requête ajax en post avec fetch, $_POST reste vide ! Au départ, je pensais que j'avais mal codé mon fetch. Mes données partent bien. PHP n'interprète pas le fetch :
content-type application/json. Avec Jquery, aucun souci (j'ai fait un petit test).

Je viens de tester en python (avec Flask), aucun souci !
Savez-vous d'où ça peut provenir ? La version de mon php est : 7.4.33


<?php
    define('ROOT', dirname($_SERVER['PHP_SELF']));
?>
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Bootstrap demo</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/css/bootstrap.min.css" rel="stylesheet">
    <style>
        main{
            margin-top: 50px;
            margin-bottom: 50px;
        }
        button{
            width: 100%;
        }
    </style>
  </head>
  <body>
    <main class="container">
    <form class="row" method="post" action="<?= htmlspecialchars(ROOT.'/controller.php') ?>">
            <div class="mb-3 col-lg-3">
                <label for="civility" class="form-label">Civilité</label>
                <select required id="civility" name="civility" class="form-select">
                    <option value="">Choisir</option>
                    <option value="1">Mademoiselle</option>
                    <option value="2">Madame</option>
                    <option value="3" selected="selected">Monsieur</option>
                </select>
            </div>
            <div class="mb-3 col-lg-3">
                <label for="firstname" class="form-label">Prénom</label>
                <input type="text" required class="form-control" id="firstname" name="firstname" value="Claude" />
            </div>
            <div class="mb-3 col-lg-3">
                <label for="lastname" class="form-label">Nom</label>
                <input type="text" required class="form-control" id="lastname" name="lastname" value="Vindigni" />
            </div>
            <div class="mb-3 col-lg-3">
                <label for="email" class="form-label">Email</label>
                <input type="email" required class="form-control" name="email" id="email" value="cvindigni@gmail.com" />
            </div>
            <div class="col-lg-12">
                <button type="submit" class="btn btn-primary">Envoyer</button>
            </div>
        </form>
    </main>
    <script src="./app.js?v=<?= time() ?>"></script>
  </body>
</html>



<?php
    // header('Content-Type: application/json');
    if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] === 'XMLHttpRequest'){
        print_r($_POST); // VIDE !!
        $arr = ['one' => 'un'];
        echo json_encode($arr);
        die;
    }




window.addEventListener('DOMContentLoaded', ()=>{
    document.querySelector('form').addEventListener('submit', e =>{
        let headers = new Headers({
                "X-Requested-With": "XMLHttpRequest",
                "Accept": "application/json",
                "Content-Type": 'application/json'
            }),
            $form = e.target,
            object = {},
            formData = new FormData($form)
        formData.forEach((value, key) => object[key] = value)

        let params = {
            method: $form.method,
            headers,
            cache: 'no-cache',
            redirect: 'follow',
            referrerPolicy: 'no-referrer',
            mode: "same-origin",
            body: JSON.stringify(object)
        }
        e.preventDefault()
        fetch($form.action, params).then(resp =>{
            if(resp.ok === true) 
                return resp.json()
        }).then(d => console.table(d))
    })
})


En python (où il n'y a pas de souci):

import json
from flask import Flask, render_template, request, jsonify

app = Flask(__name__)

@app.route('/', methods=['GET', 'POST'])
def index():
    c = [
        'Mademoiselle',
        'Madame',
        'Monsieur'
    ]
    if request.method == 'POST' and request.headers.get('X-Requested-With') == 'XMLHttpRequest':
        data = json.loads(request.data)
        data['civility'] = c[int(data['civility']) - 1]
        data = {k : v.upper() for k, v in data.items()}
        return jsonify(data)
    return render_template('index.html')

if __name__ == '__main__':
    app.run(debug=True, port=8000)

Modifié par niuxe (07 Aug 2023 - 05:13)
Modérateur
J'ai trouvé une solution annexe.

Apparemment, php ne comprend pas ce header. Il faut lui passer un autre. J'avais remarqué qu'avec la valeur "application/x-www-form-urlencoded", j'obtenais quelque chose. J'ai dû formater les données pour que php comprenne correctement. Cela dit, j'aimerais bien savoir pourquoi avec jQuery, ça passe et ça ne passe pas avec fetch. Si vous avez une idée ?

Pour ceux que ça intéresse :

window.addEventListener('DOMContentLoaded', ()=>{
    document.querySelector('form').addEventListener('submit', e =>{
        let headers = new Headers({
                "X-Requested-With": "XMLHttpRequest",
                "Accept": "application/json",
                "Content-Type": "application/x-www-form-urlencoded"
            }),
            $form = e.target,
            object = {},
            formData = new FormData($form)
        formData.forEach((value, key) => object[key] = value)

        let data = Object.entries(object).map(([k,v]) => `${k}=${v}`).join('&'),
            params = {
                method: $form.method,
                headers,
                cache: 'no-cache',
                redirect: 'follow',
                referrerPolicy: 'no-referrer',
                mode: "same-origin",
                body: data
            }
        e.preventDefault()
        fetch($form.action, params).then(resp =>{
            if(resp.ok === true) 
                return resp.json()
        }).then(d => console.table(d))
    })
})

Modifié par niuxe (07 Aug 2023 - 05:30)
Meilleure solution