Bonjour,

J'ai créer une class pour facilité la création de mes formulaires.

$form->start();
$form->name('test_')->label('Mon titre')->add();
$form->name('test_01_')->add();
$form->name('test_2_')->type('submit')->value('valide')->add();
$form->end();

Tous fonctionne sauf que... quand je mais pas par exemple un label sur le 2eme champs $form->name('test01')->add(); le label du 1er champ se mais automatiquement dans le 2eme champ. ($form est la variable de l'instance de la class Form)

$form->name('test_')->label('Mon titre')->add();
$form->name('test_01_')->add();                         <--- prend le label du 1er (Mon titre).

Les actions ressemble à ca :

public function name($name) {
        $this->name = $name;
        return $this;
    }

    public function label($label) {
        $this->label = $label;
        return $this;
    }

    public function type($type) {
        $this->type = $type;
        return $this;
    }

    public function value($value) {
        $this->value = isset($this->data[$value]) ? $this->data[$value] : $value;
        return $this;
    }

    public function placeholder($placeholder) {
        $this->placeholder = $placeholder;
        return $this;
    }

Je recherche un moyen de faire que chaque ligne est ces propriétés.

le 1er champs

$form->name('test_')->label('Mon titre')->add();
<label for="test_">Mon titre</label>
<input type="text" name="test_" id="test_" value="" placeholder="">

et le 2eme champ :

$form->name('test_01_')->add();
<input type="text" name="test_01_" id="test_01_" value="" placeholder="">

Merci d'avance pour vos réponse ! =)

11 réponses


Kenor
Réponse acceptée

+1, ta méthode name devrait créer une nouvelle instance de classe "champ".
Ou, tu devrais pouvoir injecter à une class "form" tes champs par type, du genre $form->add(new TextField())->label('Mon premier champ'));

Personnelement, j'ai opté pour ça :

$fields->text('name_of_field')->label('Mon champ')->otherMethod(...);

Ou "text" correspond à un champ text (et là, j'ai tout une variété de type, que ce soit "date" ou "group" ou "editor" etc.)

La méthode "text" renvoi une instance de la class "new TextField" qui est une abstraction de AbstractField (cette dernière créera les méthodes par défaut commune à tous les types de champ, tel que "label")
Et par exemple, la class DateField pourra définir une méthode avec la date minimum et maximum du champ date.

Kenor
Réponse acceptée

Suppose que tu as 2 classes :
FormClass et ChampClass

FormClass va contenir une méthode "name" qui va retourner simplement une instance de ChampClass

public function name($name) {
   $instanceChamp = new ChampClass($name);
   $this->instanceChamps[] = $instanceChamp;

   return $instanceChamp;
}

Tu auras ensuite plus qu'à parcourir ton tableau "instanceChamps" pour appeler une méthode qui buildera ton formulaire en HTML

public function getHtml()
{
  $html = '';
   foreach ($this->instanceChamps as $instanceChamp)
   {
      $html .= $instanceChamp->getHtmlDuChamp();
   }

   return $html;
}

En mode basique, ChampClass pourrait ressemble à ça

class ChampClass {
protected $name;
 public function __constructor($name)
 {
    $this->name = $name;
    }

    public function getHtmlDuChamp()
    {
        return '<input name="' . $this->name . '">';
    }
    }

Bonsoir,
Puis-je avoir la méthode add ? ou la classe complète si elle n'est pas trop longue ?
Merci

Alexe
Auteur

@Carouge10 La class complete ressemble à ça :

class Form {

    private $data;
    private $action = '/';
    private $method = 'post';
    private $enctype = 'multipart/form-data';
    private $autocomplete = 'off';

    private $label = null;
    private $name;
    private $type = 'text';
    private $value = '';
    private $placeholder = '';

    /**
     * Form constructor.
     * @param array $data
     */
    public function __construct(array $data = []) {
        $this->data = $data;
    }

    /**
     * @return string
     */
    public function start() {
        return '<form action="'.$this->action.'" method="'.$this->method.'" class="form" enctype="'.$this->enctype.'" autocomplete="'.$this->autocomplete.'"><div class="form_main">';
    }

    /**
     * @param string $action
     * @return Form
     */
    public function action(string $action) {
        $this->action = $action;
        return $this;
    }

    /**
     * @param string $method
     * @return Form
     */
    public function method(string $method) {
        if(in_array($method, ['get', 'post'])):
            $this->method = $method;
        endif;

        return $this;
    }

    /**
     * @param string $enctype
     * @return Form
     */
    public function enctype(string $enctype) {
        if(in_array($enctype, ['multipart/form-data', 'application/x-www-form-urlencoded'])):
            $this->enctype = $enctype;
        endif;

        return $this;
    }

    /**
     * @param bool $autocomplete
     * @return Form
     */
    public function autocomplete(bool $autocomplete) {
        if(is_bool($autocomplete)):
            if($autocomplete == true):
                $this->autocomplete = 'on';
            else:
                $this->autocomplete = 'off';
            endif;
        endif;

        return $this;
    }

    /**
     * @return string
     */
    public function end() {
        return '</div></form>';
    }

    public function name($name) {
        $this->name = $name;
        return $this;
    }

    public function label($label = null) {
        $this->label = is_null($label) ? '' : $label;
        return $this;
    }

    public function type($type) {
        $this->type = $type;
        return $this;
    }

    public function value($value) {
        $this->value = isset($this->data[$value]) ? $this->data[$value] : $value;
        return $this;
    }

    public function placeholder($placeholder) {
        $this->placeholder = $placeholder;
        return $this;
    }

    public function add(string $class = 'form_field') {
        return $this->surround($this->labelHtml().$this->inputHtml(), $class);
    }

    private function surround($input, $class = 'form_field') {
        return '<div class="'.$class.'">'.$input.'</div>';
    }

    private function labelHtml() {
        return $this->label == '' ? '' : '<label for="'.$this->name.'">'.$this->label.'</label>';
    }

    private function inputHtml() {
        return '<input type="'.$this->type.'" name="'.$this->name.'" id="'.$this->name.'" value="'.$this->value.'" placeholder="'.$this->placeholder.'">';
    }
}

Elle n'est pas terminer, il reste des choses a ajouter et à retirer aussi... ^^'

Oui, je vois le gros de la chose.
Théoriquement après chaque appel de la méthode "add()", tu devrais avoir quelque chose qui "vide" les variables de la classe que tu n'as plus besoin (label, name.......), non ?

Alexe
Auteur

En gros c'est ca, c'est a dire que si le champs 1 à un label et qu'il est de type select et que le champs 2 n'a pas de label et qu'il utilise le type par défaut (text) bh que je n'ais pas a répéter le type ou ajouter un label vide

Un tuto sur la création des helpers (form) qui pourrais t'aider et te simplifier la tache

Alexe
Auteur

Je l'avais vu ce tuto ^^ mais il est assez vieux, 8ans lol
du coup c'est pas trop ce que je souhaite faire ^^

Alexe
Auteur

J'ai refais la class enfin pour faire des testes, mais j'ai le même souci avec un singleton @Balsakup ^^

La class

class Form {
    private $label;
    private $name;
    private static $_instance;

    public static function getInstance() {
        if(is_null(self::$_instance)):
            self::$_instance = new Form();
        endif;

        return self::$_instance;
    }

    public function name($name) {
        $this->name = $name;
        return $this;
    }

    public function label($label = null) {
        $this->label = is_null($label) ? '' : $label;
        return $this;
    }
}

Appel de la class

var_dump(Form::getInstance()->name('test')->label('test'));
var_dump(Form::getInstance()->name('test01'));

Ce que ca retourne

object(Src\Utils\Form\Form)#44 (2) {
  ["label":"Src\Utils\Form\Form":private]=>
  string(4) "test"
  ["name":"Src\Utils\Form\Form":private]=>
  string(4) "test"
}
object(Src\Utils\Form\Form)#44 (2) {
  ["label":"Src\Utils\Form\Form":private]=>
  string(4) "test"
  ["name":"Src\Utils\Form\Form":private]=>
  string(6) "test01"
}

@Kenor je suis d'accord avec ce que tu dis mais je vois pas comment je pourrais le faire, enfin comment je peu dire que quand je fais $form->name('untruc') cela me créer une nouvelle instance ? puis pouvoir appeller chaque methode en fonction de cette methode name ^^

Merci en tous cas pour vos retours !! :D

Alexe
Auteur

@Kenor ta methone fonctionne, mais je ne vois pas comment ajouter le reste, enfin le label, le type, etc.. à la suite $form->name()->label->type()... enfin selon les besoins ^^'

Merci pour cette réponse !

Alexe
Auteur

Non enfaite tous fonctionne et c'est bien ce que je souhaitais ! ^^

Si sa intéresse des personnes, je partagerais cette Class terminer sur GitHub !
Encore merci a toi @Kenor =D