Maison > interface Web > tutoriel CSS > Construire un formulaire en PHP à l'aide de DomDocument

Construire un formulaire en PHP à l'aide de DomDocument

Christopher Nolan
Libérer: 2025-03-20 11:01:12
original
953 Les gens l'ont consulté

Construire un formulaire en PHP à l'aide de DomDocument

Modèle pour faire fonctionner le réseau. Contenu de synthèse des données et de la structure. Pour les développeurs, c'est notre superpuissance la plus cool - obtenez des données, puis faites-les fonctionner pour nous, en les rendant sous la forme dont nous avons besoin. Un tableau d'objets peut être transformé en table, une liste de cartes, un graphique ou tout ce que nous pensons est le plus utile à l'utilisateur. Que les données soient un article de blog dans notre propre fichier Markdown ou le dernier taux de change global, le balisage et l'expérience utilisateur ultime nous rendent les développeurs frontaux.

PHP est un langage puissant pour les modèles qui fournit de nombreuses façons de fusionner les données avec des balises. Examinons un exemple d'utilisation des données pour créer des formulaires HTML.

Vous voulez commencer maintenant? Sautez dans la section de mise en œuvre.

Dans PHP, nous pouvons informer la variable en un littéral de chaîne en utilisant des devis doubles, donc si nous avons une variable $name = 'world' nous pouvons écrire echo "Hello, {$name}" qui imprime le "bonjour, le monde" attendu. Pour des modèles plus complexes, nous pouvons toujours concaténer les chaînes, par exemple: echo "Hello, " . $name . "."

Pour les anciens programmeurs, il y a aussi printf("Hello, %s", $name) . Pour les chaînes multi-lignes, Heredoc peut être utilisé (similaire à Hello, = $name ?> ). Toutes ces options sont excellentes, mais les choses peuvent devenir désordonnées lorsque beaucoup de logique en ligne est nécessaire. Si nous devons construire des chaînes HTML composites, telles que les formulaires ou la navigation, la complexité peut être infinie, car les éléments HTML peuvent être imbriqués les uns avec les autres.

Ce que nous essayons d'éviter

Avant de continuer à faire ce que nous voulons faire, cela vaut une minute de réfléchir à ce que nous ne voulons pas faire. Considérez l'extrait de la ligne 170-270 de WordPress Core Code class-walker-nav-menu.php :

  php // class-walker-nav-men.php
// ...
$ sortie. = $
Copier après la connexion
  • ';; // ... $ item_output = $ args-> avant; $ item_output. = ' '; $ item_output. = $ args-> link_before. $ item_output. = ' '; $ item_output. = $ args-> After; // ... $ output. = application_filters ('walker_nav_menu_start_el', $ item_output, $ item, $ Depth, $ args); // ... $ output. = "{$ n}";

    Pour construire la navigation, dans cette fonction, nous utilisons une $output , qui est une très longue chaîne, et nous continuons à y ajouter du contenu. Ce type de code a un ordre de fonctionnement très spécifique et limité. Si nous voulons<a></a> Ajoutez une propriété que nous devons accéder $attributes avant son exécution. Si nous voulons<a></a> Nidé éventuellement un<span></span> Ou un<img alt="Construire un formulaire en PHP à l'aide de DomDocument" > , nous devons écrire un tout nouveau bloc de code, en remplaçant la partie médiane de la ligne 7 par environ 4 à 10 nouvelles lignes de code, selon ce que nous voulons ajouter. Imaginez maintenant que vous devez éventuellement ajouter<span></span> , puis ajouter éventuellement<img alt="Construire un formulaire en PHP à l'aide de DomDocument" > , ou dans<span></span> Ajouter en interne ou ultérieure. Ceci est lui-même trois instructions, ce qui rend le code plus difficile à lire. Lorsque vous concaténez des cordes comme celle-ci, il est facile de se retrouver avec des pâtes à cordes, ce qui est amusant à dire mais douloureux à maintenir.

    L'essence du problème est que lorsque nous essayons de déduire des éléments HTML, nous ne pensons pas aux chaînes . Le navigateur consomme simplement des chaînes et PHP sortira des chaînes. Mais notre modèle mental ressemble plus à un dom - les éléments sont disposés dans une structure en forme d'arbre, et chaque nœud a de nombreuses propriétés potentielles, caractéristiques et nœuds enfants.

    Ne serait-ce pas génial s'il existe un moyen structuré et hautement expressif de construire un arbre?

    entrer……

    Classe DomDocument

    PHP 5 ajoute des modules Dom à sa gamme non typique non strictement. Son principal point d'entrée est la classe DomDocument, qui est destinée à être similaire au DOM JavaScript de l'API Web. Si vous avez déjà utilisé document.createElement , ou pour certains de nos âges, utilisez $(' Salut!

    ') Syntaxe, qui peut sembler très familière. Nous initialisons d'abord un nouveau domDocument:
     $ dom = new DomDocument ();
    Copier après la connexion

    Maintenant, nous pouvons y ajouter un domestique:

     $ p = $ Dom-> CreateElement ('p');
    Copier après la connexion

    La chaîne «P» représente le type d'élément que nous voulons, de sorte que d'autres chaînes valides peuvent être «div», «img», etc.

    Une fois que nous avons un élément, nous pouvons définir ses propriétés:

     $ p-> setAttribute ('Class', 'Headline');
    Copier après la connexion

    Nous pouvons y ajouter des nœuds enfants:

     $ span = $ Dom-> CreateElement ('Span', 'Ceci est un titre');
    $ p-> appenchild ($ span);
    Copier après la connexion

    Enfin, obtenez la chaîne HTML complète à la fois:

     $ DOM-> APPENDCHILD ($ P);
    $ htmlString = $ dom-> savehtml ();
    echo $ htmlstring;
    Copier après la connexion

    Notez que ce style de codage permet à notre code d'être organisé en fonction de notre modèle mental - le document contient des éléments; La partie "HTML est juste une chaîne" apparaît à la fin, une fois que notre structure est en place. Le "document" est légèrement différent du DOM réel ici, car il n'a pas besoin de représenter l'ensemble du document, mais n'est qu'un bloc HTML. En fait, si vous avez besoin de créer deux éléments similaires, vous pouvez enregistrer une chaîne HTML à l'aide de saveHTML() , modifier davantage le "document" DOM, puis enregistrer une nouvelle chaîne HTML en appelant à nouveau saveHTML() .

    Obtenir des données et définir la structure

    Supposons que nous devons créer un formulaire sur le serveur à l'aide de données du fournisseur CRM et de nos propres balises. La réponse de l'API de CRM ressemble à ceci:

     {
      "soumis_button_label": "Soumettre maintenant!",
      "champs": [
        {
          "id": "premier nom",
          "type": "texte",
          "étiquette": "prénom",
          "requis": vrai,
          "Validation_Message": "Le prénom est requis.",
          "max_length": 30
        },
        {
          "id": "catégorie",
          "type": "multiple_choice",
          "Label": "Choisissez toutes les catégories qui s'appliquent",
          "requis": faux,
          "field_metadata": {
            "Multi_select": true,
            "valeurs": [
              {"Value": "Travel", "Label": "Travel"},
              {"valeur": "marketing", "étiquette": "marketing"}
            ]]
          }
        }
      ]]
    }
    Copier après la connexion

    Cet exemple n'utilise pas la structure de données exacte d'un CRM particulier, mais il est assez représentatif.

    Et supposons que nous voulons que nos balises ressemblent à ceci:

    <label>
      <input type="text" placeholder=" " id="first-name" required maxlength="30">
      Prénom
      <em>Le prénom est requis.</em>
    </label>
    <label>
      </label>
        <div>
          <input type="checkbox" value="travel" id="category-travel" name="category">
          <label for="category-travel">Voyage</label>
        </div>
        <div>
          <input type="checkbox" value="marketing" id="category-marketing" name="category">
          <label for="category-marketing">Commercialisation</label>
        </div>
      
      Choisissez toutes les catégories qui s'appliquent
    
    Copier après la connexion

    Quel est l'espace réservé ""? C'est une petite astuce qui nous permet de suivre si le champ est vide dans CSS sans utiliser JavaScript. Tant que l'entrée est vide, elle correspond à input:placeholder-shown , mais l'utilisateur ne verra aucun texte visible. C'est exactement ce que nous pouvons faire lorsque nous contrôlons le balisage!

    Maintenant que nous savons ce que nous voulons réaliser, voici le plan de match:

    1. Obtenez des définitions de champ et d'autres contenus de l'API
    2. Initialiser DomDocument
    3. Itérer sur les champs et construire chaque champ au besoin
    4. Obtenez la sortie HTML

    Alors construisons notre processus et résolvons quelques problèmes techniques:

      PHP Fonction RenderForm ($ endpoint) {
      // Obtenez des données de l'API et convertissez-les en un objet PHP $ formResult = file_get_contents ($ endpoint);
      $ formContent = json_decode ($ formResult);
      $ formFields = $ formContent-> champs;
    
      // commence à construire le dom
      $ dom = new DomDocument ();
      $ form = $ Dom-> createElement ('form');
    
      // itérer sur les champs et construire chaque champ foreach ($ formFields comme $ champ) {
        // TODO: effectuez des opérations sur les données sur le terrain}
    
      // Obtenez la sortie HTML $ DOM-> APPENDCHILD ($ form);
      $ htmlString = $ dom-> savehtml ();
      echo $ htmlstring;
    }
    Copier après la connexion

    Jusqu'à présent, nous avons récupéré et analysé les données, initialisé notre domDocument et écho à sa sortie. Que voulons-nous faire avec chaque champ? Tout d'abord, construisons l'élément de conteneur, dans notre exemple, il devrait être<label></label> et tags communs à tous les types de champs:

      Php // ...
    // itérer sur les champs et construire chaque champ foreach ($ formFields comme $ champ) {
      // Construire <label>un conteneur'` '
      $ element = $ Dom-> CreateElement ('Label');
      $ element-> setAttribute ('class', 'champ');
    
      // Réinitialise la valeur d'entrée $ label = null;
    
      // Si une balise est définie, ajoutez `` <span>'
      if ($ field-> étiquette) {
        $ label = $ Dom-> CreateElement ('Span', $ field-> label);
        $ label-> setAttribute ('class', 'label');
      }
    
      // Ajouter une balise à `` <label>'
      if ($ étiquette) $ element-> appendchild ($ label);
    }</label></span></label><p> Étant donné que nous sommes dans une boucle et que PHP n'étend pas les variables dans la boucle, nous réinitialisons l'élément <code>$label</code> sur chaque itération. Ensuite, si le champ a une étiquette, nous construisons l'élément. Enfin, nous l'ajoutons à l'élément de conteneur.</p><p> Veuillez noter que nous utilisons la méthode <code>setAttribute</code> pour définir la classe. Contrairement à l'API Web, malheureusement, il n'y a pas de traitement spécial pour les listes de classe. Ils ne sont qu'un autre attribut. Si nous avons une logique de classe très complexe, car c'est juste PHP ™, nous pouvons créer un tableau et l'installer: <code>$label->setAttribute('class', implode($labelClassList))</code> .</p><h3> Entrée unique</h3><p> Étant donné que nous savons que l'API ne renverra que des types de champs spécifiques, nous pouvons changer de type et écrire du code spécifique pour chaque type:</p><pre class="brush:php;toolbar:false">  Php // ...
    // itérer sur les champs et construire chaque champ foreach ($ formFields comme $ champ) {
      // Construire <label>un conteneur'` '
      $ element = $ Dom-> CreateElement ('Label');
      $ element-> setAttribute ('class', 'champ');
    
      // Réinitialise la valeur d'entrée $ input = null;
      $ label = null;
    
      // Si une balise est définie, ajoutez `` <span>'
      // ...
    
      // Créer un commutateur d'élément d'entrée ($ field-> type) {
        case «texte»:
        Cas «e-mail»:
        Cas «Téléphone»:
          $ input = $ dom-> createElement ('input');
          $ input-> setAttribute ('placeholder', '');
          if ($ field-> type === 'e-mail') $ input-> setAttribute ('type', 'e-mail');
          if ($ field-> type === 'téléphone') $ input-> setAttribute ('type', 'tel');
          casser;
      }
    }</span></label><p> Passons maintenant aux zones de texte, aux cases uniques et aux champs cachés:</p><pre class="brush:php;toolbar:false">  Php // ...
    // itérer sur les champs et construire chaque champ foreach ($ formFields comme $ champ) {
      // Construire <label>un conteneur'` '
      $ element = $ Dom-> CreateElement ('Label');
      $ element-> setAttribute ('class', 'champ');
    
      // Réinitialise la valeur d'entrée $ input = null;
      $ label = null;
    
      // Si une balise est définie, ajoutez `` <span>'
      // ...
    
      // Créer un commutateur d'élément d'entrée ($ field-> type) {
        // ...
        case 'text_area':
          $ input = $ dom-> createElement ('textArea');
          $ input-> setAttribute ('placeholder', '');
          if ($ lignes = $ field-> field_metadata-> lignes) $ input-> setAttribute ('lignes', $ lignes);
          casser;
    
        case 'cochebox':
          $ element-> setAttribute ('class', 'field single-checkbox');
          $ input = $ dom-> createElement ('input');
          $ input-> setAttribute ('Type', 'Checkbox');
          if ($ field-> field_metadata-> initialement_checked === true) $ input-> setAttribute ('checked', 'checked');
          casser;
    
        cas «caché»:
          $ input = $ dom-> createElement ('input');
          $ input-> setAttribute ('type', 'caché');
          $ input-> setAttribute ('value', $ field-> field_metadata-> valeur);
          $ element-> setAttribute ('Hidden', 'Hidden');
          $ element-> setAttribute ('style', 'affiche: aucun;');
          $ label-> textContent = '';
          casser;
      }
    }</span></label><p> Remarquez de nouvelles actions que nous avons faites avec des cases à cocher et des situations cachées? Nous avons non seulement créé<code><input></code> élément; nous changeons toujours <em>le conteneur</em><code><label></label></code> élément! Pour un champ à cocher unique, nous voulons modifier la classe du conteneur afin que nous puissions aligner horizontalement les cases et les étiquettes;<code><label></label></code> Le conteneur doit également être complètement caché.</p><p> Maintenant, si nous connectons simplement la chaîne, cela ne peut pas être modifié à ce stade. Nous devons ajouter un tas de déclarations IF sur les types d'éléments et leurs métadonnées en haut du bloc. Ou, peut-être pire, nous commençons à changer plus tôt et à copier-coller beaucoup de code public entre chaque branche.</p><p> Et c'est le véritable avantage de l'utilisation d'un constructeur comme DomDocument - tout est toujours modifiable et tout est toujours structuré jusqu'à ce que nous cliquons sur <code>saveHTML()</code> .</p><h3> Éléments de boucle imbriqués</h3><p> Ajoutons<code><select></select></code> La logique de l'élément:</p><pre class="brush:php;toolbar:false">  Php // ...
    // itérer sur les champs et construire chaque champ foreach ($ formFields comme $ champ) {
      // Construire <label>un conteneur'` '
      $ element = $ Dom-> CreateElement ('Label');
      $ element-> setAttribute ('class', 'champ');
    
      // Réinitialise la valeur d'entrée $ input = null;
      $ label = null;
    
      // Si une balise est définie, ajoutez `` <span>'
      // ...
    
      // Créer un commutateur d'élément d'entrée ($ field-> type) {
        // ...
        case «SELECT»:
          $ element-> setAttribute ('class', 'champ sélectionné');
          $ input = $ dom-> createElement ('select');
          $ input-> setAttribute ('requis', 'requis');
          if ($ field-> field_metadata-> multi_select === true)
            $ input-> setAttribute ('multiple', 'multiple');
    
          $ options = [];
    
          // Suivre s'il y a une option présélectionnée $ optionselected = false;
    
          foreach ($ field-> field_metadata-> valeurs en tant que valeur $) {
            $ option = $ dom-> createElement ('option', htmlSpecialChars ($ value-> label));
    
            // S'il n'y a pas de valeur, sautez si (! $ Value-> value) Continuez;
    
            // Définir les options présélectionnées si ($ valeur-> selected === true) {
              $ option-> setAttribute ('sélectionné', 'sélectionné');
              $ optionselected = true;
            }
            $ option-> SetAttribute ('Value', $ Value-> Value);
            $ Options [] = $ Option;
          }
    
          // S'il n'y a pas d'option présélectionnée, créez une option d'espace réservée vide si ($ optionselected === false) {
            $ videOption = $ dom-> createElement ('option');
    
            // Définir les options pour masquer, désactiver et sélectionner ForEach ([«Hidden», «Disabled», «Selected»] comme $ attribut)
              $ videOption-> setAttribute ($ attribut, $ attribut);
            $ input-> appenchild ($ videOption);
          }
    
          // ajouter des options dans le tableau à ` <select>`
          foreach ($ Options as $ option) {
            $ input-> appenchild (Option $);
          }
          casser;
      }
    }</select></span></label><p> OK, il y a beaucoup à faire ici, mais la logique sous-jacente est la même. Paramètres externes<code><label></label></code> Après cela, nous créons un<code><option></option></code> Arraie, ajoutez-le.</p><p> Nous en avons fait ici aussi<code><select></select></code> Trick spécial: s'il n'y a pas d'option présélectionnée, nous ajouterons une option d'espace réservée vide déjà sélectionnée, mais l'utilisateur ne peut pas le sélectionner. L'objectif est d'utiliser CSS pour transférer notre<code><label></label></code> En tant que "place d'espace réservé", mais cette technologie peut être utilisée dans une variété de conceptions. En l'appuyant sur <code>$input</code> avant d'ajouter d'autres options, nous nous assurons qu'il s'agit de la première option de la balise.</p><p> Traitons-y maintenant<code><fieldset></fieldset></code> Boutons radio et cocher les cases dans:</p><pre class="brush:php;toolbar:false">  Php // ...
    // itérer sur les champs et construire chaque champ foreach ($ formFields comme $ champ) {
      // Construire <label>un conteneur'` '
      $ element = $ Dom-> CreateElement ('Label');
      $ element-> setAttribute ('class', 'champ');
    
      // Réinitialise la valeur d'entrée $ input = null;
      $ label = null;
    
      // Si une balise est définie, ajoutez `` <span>'
      // ...
    
      // Créer un commutateur d'élément d'entrée ($ field-> type) {
        // ...
        case 'multiple_choice':
          $ ChoiceType = $ field-> field_metadata-> multi_select === true?
          $ element-> setAttribute ('class', "field {$ ChoiceType} -group");
          $ input = $ dom-> createElement ('fieldset');
    
          // construire une sélection `` pour chaque option du champ</span></label>
          foreach ($ field-> field_metadata-> valeurs comme $ choixvalue) {
            $ ChoiceField = $ Dom-> CreateElement ('div');
            $ ChoiceField-> SetAttribute ('Class', 'Choice');
    
            // Utilisez l'ID de champ pour sélectionner l'ID pour définir un ID unique
            $ ChoiceId = "{$ field-> id} - {$ ChoiceValue-> value}";
    
            // build`<input> `Élément $ choix = $ dom-> createElement ('entrée');
            $ Choice-> SetAttribute ('Type', $ ChoiceType);
            $ Choice-> SetAttribute ('Value', $ ChoiceValue-> Value);
            $ Choice-> SetAttribute ('ID', $ ChoiceId);
            $ choix-> setAttribute ('name', $ field-> id);
            $ ChoiceField-> APPENDCHILD ($ Choice);
    
            // construire ` <label>` `Element $ choiceLabel = $ dom-> createElement ('label', $ choixValue-> label);
            $ ChoiceLabel-> setAttribute ('for', $ choixid);
            $ ChoiceField-> APPENDCHILD ($ ChoiceLabel);
    
            $ input-> appenchild ($ ChoiceField);
          }
          casser;
      }
    }</label><p> Ainsi, nous déterminons d'abord si l'ensemble de champs doit être une case à cocher ou un bouton radio. Ensuite, nous définissons la classe de conteneurs en conséquence et construisons<code><fieldset></fieldset></code> . Après cela, nous réduisons les options disponibles et en créons une pour chaque option<code><div> , qui contient un<code><input></code> Et un<code><label></label></code> . Notez que nous définissons la classe de conteneur sur la ligne 21 en utilisant une interpolation de chaîne PHP régulière et créons un ID unique dans la ligne 30 pour chaque option.<h3> Fragment</h3>
    <p> Le dernier type que nous devons ajouter est un peu plus complexe qu'il n'y paraît. De nombreux formulaires contiennent des champs de description qui ne sont pas des entrées, mais juste un HTML que nous devons imprimer entre les autres champs.</p>
    <p> Nous devons utiliser une autre méthode DomDocument <code>createDocumentFragment()</code> . Cela nous permet d'ajouter un HTML arbitraire sans utiliser la structure DOM:</p>
    <pre class="brush:php;toolbar:false">  Php // ...
    // itérer sur les champs et construire chaque champ foreach ($ formFields comme $ champ) {
      // Construire <label>un conteneur'` '
      $ element = $ Dom-> CreateElement ('Label');
      $ element-> setAttribute ('class', 'champ');
    
      // Réinitialise la valeur d'entrée $ input = null;
      $ label = null;
    
      // Si une balise est définie, ajoutez `` <span>'
      // ...
    
      // Créer un commutateur d'élément d'entrée ($ field-> type) {
        // ...
        cas «instruction»:
          $ element-> setAttribute ('class', 'champ de champ');
          $ fragment = $ Dom-> CreateDocumentFragment ();
          $ fragment-> appendxml ($ field-> text);
          $ input = $ dom-> createElement ('p');
          $ input-> appenchild ($ fragment);
          casser;
      }
    }</span></label><p> À ce stade, vous vous demandez peut-être comment nous obtenons un objet nommé <code>$input</code> qui représente en fait un statique<code><p> élément. L'objectif est d'utiliser un nom de variable commun pour chaque itération de la boucle de champ, donc à la fin, nous pouvons toujours l'ajouter avec <code>$element->appendChild($input)</code> quel que soit le type de champ réel. Donc, oui, nommer les choses est difficile.</p>
    <h3> vérifier</h3>
    <p> L'API que nous utilisons fournit un message de vérification distinct pour chaque champ requis. Si une erreur de validation se produit, nous pouvons afficher l'erreur en ligne avec le champ au lieu d'afficher un message "Oups, votre mauvais" mauvais "en bas.</p>
    <p> Ajoutons le texte de validation à chaque élément:</p>
    <pre class="brush:php;toolbar:false">  Php // ...
    // itérer sur les champs et construire chaque champ foreach ($ formFields comme $ champ) {
      // Construire <label>un conteneur'` '
      $ element = $ Dom-> CreateElement ('Label');
      $ element-> setAttribute ('class', 'champ');
    
      // Réinitialise la valeur d'entrée $ input = null;
      $ label = null;
      $ validation = null;
    
      // Si une balise est définie, ajoutez `` <span>'
      // ...
    
      // Si un message de vérification est défini, ajoutez `` <em>'
      if (isset ($ field-> validation_message)) {
        $ validation = $ Dom-> CreateElement ('em');
        $ fragment = $ Dom-> CreateDocumentFragment ();
        $ fragment-> appendxml ($ field-> validation_message);
        $ validation-> appenchild ($ fragment);
        $ validation-> setAttribute ('class', 'validation-message');
        $ validation-> setAttribute («caché», «caché»);
    
      // Créer un commutateur d'élément d'entrée ($ field-> type) {
        // ...
      }
    }</em></span></label><p> C'est tout! Pas besoin de gérer la logique du type de champ - il suffit de créer conditionnellement un élément pour chaque champ.</p><h3> Intégrer tout le contenu</h3><p> Alors, que se passe-t-il après avoir construit tous les éléments de terrain? Nous devons ajouter <code>$input</code> , <code>$label</code> et <code>$validation</code> à l'arbre Dom que nous construisons. Nous pouvons également profiter de cette occasion d'ajouter des propriétés publiques, telles que <code>required</code> . Nous ajouterons ensuite le bouton Soumettre, qui est distinct des champs de cette API.</p><pre class="brush:php;toolbar:false">  PHP Fonction RenderForm ($ endpoint) {
      // Obtenez des données de l'API et convertissez-la en objet PHP // ...
    
      // commence à construire le dom
      $ dom = new DomDocument ();
      $ form = $ Dom-> createElement ('form');
    
      // itérer sur les champs et construire chaque champ foreach ($ formFields comme $ champ) {
        // Construire <label>un conteneur'` '
        $ element = $ Dom-> CreateElement ('Label');
        $ element-> setAttribute ('class', 'champ');
    
        // Réinitialise la valeur d'entrée $ input = null;
        $ label = null;
        $ validation = null;
    
        // Si une balise est définie, ajoutez `` <span>'
        // ...
    
        // Si un message de vérification est défini, ajoutez `` <em>'
        // ...
    
        // Créer un commutateur d'élément d'entrée ($ field-> type) {
          // ...
        }
    
        // Ajouter un élément d'entrée if ($ input) {
          $ input-> setAttribute ('id', $ field-> id);
          if ($ field-> requis)
            $ input-> setAttribute ('requis', 'requis');
          if (isset ($ field-> max_length)))
            $ input-> setAttribute ('maxLength', $ field-> max_length);
          $ element-> appenchild ($ entrée);
    
          if ($ étiquette)
            $ element-> appenchild ($ étiquette);
    
          if ($ validation)
            $ element-> appenchild ($ validation);
    
          $ form-> appenchild ($ élément);
        }
      }
    
      // Créez le bouton Soumettre $ soumebuttonLabel = $ formContent-> soumid_button_label;
      $ soumibuttonfield = $ dom-> createElement ('div');
      $ soumibuttonfield-> setAttribute ('class', 'field soumed');
      $ soumibutton = $ Dom-> CreateElement ('Button', $ soumibuttonLabel);
      $ soumibuttonfield-> appendchild ($ soumebutton);
      $ form-> appendchild ($ soumibuttonfield);
    
      // Obtenez la sortie HTML $ DOM-> APPENDCHILD ($ form);
      $ htmlString = $ dom-> savehtml ();
      echo $ htmlstring;
    }</em></span></label><p> Pourquoi vérifions-nous si <code>$input</code> est vraie? Puisque nous le réinitialisons à Null en haut de la boucle et le construisons uniquement si le type correspond au cas de commutateur que nous attendons, cela garantit que nous n'incluons pas accidentellement des éléments inattendus que notre code ne peut pas gérer correctement.</p><p> Regardez, un formulaire HTML personnalisé!</p><h3> Contenu supplémentaire: lignes et colonnes</h3><p> Comme vous le savez, de nombreux constructeurs de formulaires permettent aux auteurs de définir des lignes et des colonnes pour les champs. Par exemple, une ligne peut contenir des champs de prénom et de famille, chacun dans une colonne de largeur de 50% distincte. Alors, vous pourriez demander, comment pouvons-nous y parvenir? Bien sûr, illustrons la convivialité en boucle de DomDocument en donnant des exemples!</p><p> Notre réponse API contient des données de grille comme indiqué ci-dessous:</p><pre class="brush:php;toolbar:false"> {
      "soumis_button_label": "Soumettre maintenant!",
      "champs": [
        {
          "id": "premier nom",
          "type": "texte",
          "étiquette": "prénom",
          "requis": vrai,
          "Validation_Message": "Le prénom est requis.",
          "max_length": 30,
          "Row": 1,
          "colonne": 1
        },
        {
          "id": "catégorie",
          "type": "multiple_choice",
          "Label": "Choisissez toutes les catégories qui s'appliquent",
          "requis": faux,
          "field_metadata": {
            "Multi_select": true,
            "valeurs": [
              {"Value": "Travel", "Label": "Travel"},
              {"valeur": "marketing", "étiquette": "marketing"}
            ]]
          },
          "Row": 2,
          "colonne": 1
        }
      ]]
    }
    Copier après la connexion

    Nous supposons que l'ajout data-column est suffisant pour définir la largeur, mais chaque ligne nécessite son propre élément (c'est-à-dire sans grille CSS).

    Avant de creuser plus profondément, considérons ce dont nous avons besoin pour ajouter des lignes. La logique de base est la suivante:

    1. Suivez les dernières lignes rencontrées.
    2. Si la ligne actuelle est plus grande, c'est-à-dire que nous passons à la ligne suivante, créons un nouvel élément de ligne et commençons à y ajouter du contenu, plutôt que de l'ajouter à la ligne précédente.

    Maintenant, que devons-nous faire si nous concatérons les cordes? Ajoutant probablement une chaîne similaire à <div>' '</div> chaque fois qu'une nouvelle ligne est atteinte. Cette "chaîne HTML inversée" est toujours très déroutante pour moi, donc je ne peux qu'imaginer ce que ça fait d'être mon IDE. Plus important encore, parce que le navigateur ferme automatiquement les étiquettes ouvertes, une faute simple peut conduire à d'innombrables imbriquées<div> . C'est comme si c'était amusant, mais c'est le contraire. Alors, quelle est l'approche structurée pour faire face à ce problème? Merci pour votre question. Tout d'abord, ajoutons des traces de ligne avant la boucle et construisons un élément de conteneur de ligne supplémentaire. Nous nous assurerons ensuite d'ajouter chaque <code>$element à son $rowElement au lieu de constituer directement le $form .

      PHP Fonction RenderForm ($ endpoint) {
      // Obtenez des données de l'API et convertissez-la en objet PHP // ...
    
      // commence à construire le dom
      $ dom = new DomDocument ();
      $ form = $ Dom-> createElement ('form');
    
      // initialiser le suivi des lignes $ row = 0;
      $ rowelement = $ dom-> createElement ('div');
      $ rowelement-> setAttribute ('class', 'field-row');
    
      // itérer sur les champs et construire chaque champ foreach ($ formFields comme $ champ) {
        // Construire <label>un conteneur'` '
        $ element = $ Dom-> CreateElement ('Label');
        $ element-> setAttribute ('class', 'champ');
        $ element-> setAttribute ('Data-Row', $ field-> row);
        $ element-> setAttribute ('data-column', $ field-> colonne);
    
        // Ajouter un élément d'entrée à la ligne if ($ input) {
          // ...
          $ ROWELlement-> APPENDCHILD ($ élément);
          $ form-> appenchild ($ rowelement);
        }
      }
      // ...
    }</label><p> Jusqu'à présent, nous venons d'en ajouter un autre sur le terrain<code><div> . Construisons un <em>nouvel</em> élément de ligne pour chaque ligne dans la boucle:<pre class="brush:php;toolbar:false">  Php // ...
    // initialiser le suivi des lignes $ row = 0;
    $ rowelement = $ dom-> createElement ('div');
    $ rowelement-> setAttribute ('class', 'field-row');
    
    // itérer sur les champs et construire chaque champ foreach ($ formFields comme $ champ) {
      // ...
      // Si nous atteignons une nouvelle ligne, créez un nouveau $ ROWELlement
      if ($ field-> row> $ row) {
        $ row = $ field-> row;
        $ rowelement = $ dom-> createElement ('div');
        $ rowelement-> setAttribute ('class', 'field-row');
      }
    
      // Créer un commutateur d'élément d'entrée ($ field-> type) {
        // ...
        // Ajouter un élément d'entrée à la ligne if ($ input) {
          // ...
          $ ROWELlement-> APPENDCHILD ($ élément);
    
          // déduplique automatiquement $ form-> appendChild ($ rowelement);
        }
      }
    }
    Copier après la connexion

    Nous avons juste besoin de remplacer l'objet $rowElement en tant qu'élément DOM, que PHP traite comme un nouvel objet unique. Ainsi, à la fin de chaque boucle, nous ajoutons simplement le $rowElement actuel - si c'est le même élément que l'itération précédente, le formulaire est mis à jour;

    Étapes suivantes

    Les formulaires sont un excellent cas d'utilisation pour les modèles orientés objet. Compte tenu des extraits du code de base WordPress, il peut être considéré que les menus imbriqués sont également un bon cas d'utilisation. Toute tâche que les marques suivent la logique complexe sont un bon candidat pour cette approche. DomDocument peut sortir n'importe quel XML, vous pouvez donc également l'utiliser pour construire des flux RSS à partir des données du post.

    Voici l'extrait de code complet de notre formulaire. N'hésitez pas à l'ajuster à toute API de formulaire sur laquelle vous vous trouvez à travailler. Il s'agit de la documentation officielle et il est utile de comprendre les API disponibles.

    Nous n'avons même pas mentionné que DomDocument peut analyser HTML et XML existants. Vous pouvez ensuite utiliser l'API XPATH pour trouver des éléments, ce qui est quelque peu similaire à Cheerio sur document.querySelector ou Node.js. La courbe d'apprentissage est un peu abrupte, mais c'est une API très puissante pour gérer le contenu externe.

    Fait amusant: les fichiers Microsoft Office se terminant par X (tels que .xlsx) sont des fichiers XML. Ne dites pas au service marketing, mais vous pouvez analyser les documents Word sur le serveur et sortir HTML.

    La chose la plus importante est de se rappeler que les modèles sont des superpuissances. Être capable de construire le bon balisage pour la bonne situation peut être la clé pour obtenir une excellente expérience utilisateur.

  • Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

    Article précédent:"Vent arrière désambiguë" Article suivant:Superchargement des éléments intégrés avec des composants Web "est" plus facile que vous ne le pensez
    Déclaration de ce site Web
    Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
    Derniers numéros
    Rubriques connexes
    Plus>
    Recommandations populaires
    Tutoriels populaires
    Plus>
    Derniers téléchargements
    Plus>
    effets Web
    Code source du site Web
    Matériel du site Web
    Modèle frontal