Bonjour, bonsoir
J'ai récemment eu l'envie de crée une sorte de mini-framework pour m'aider dans mes créations de site, et aussi pour m'amuser, et apprendre.
J'ai alors entrepris une folle aventure pour reproduire quelques concepts de Laravel que j'adore. Je suis pas un expert en PHP, loin de là même, disons que je me trouve même débutant, je me débrouille certes, mais c'est loin d'être incroyable.
J'ai donc crée deux petites classes (qui n'ont aucune prétention) pour me permettre de générer des formulaires (rien d'extraordinaire, je pense que je ne l'utiliserais même jamais, mais c'était bien rigolo) et une classe pour gérer les validations de formulaires (celle-là par contre c'est ma petite chouchoute, c'est un truc que j'ai adoré dans Laravel).
Et donc, j'aimerais avoir vos avis là-dessus, par avis j'entends, savoir où il pourrait y avoir des problèmes, pourquoi j'ai fais comme ça au lieu de faire comme ci, comment je pourrais rendre la classe encore meilleur etc...
Enfin voilà, je demande juste des avis constructifs pour savoir si j'ai bien compris le concept de la POO, des normes etc..
FormBuilder :
/**
* Création de formulaires HTML avec ou sans boostrap
*/
class FormBuilder {
/**
* Url de la route (même url par défaut)
* @var string url route
*/
private $route_name = "";
/**
* Paramètres de la route
* @var array paramètres
*/
private $route_name_params = [];
/**
* Methode du formulaire, POST par défaut
* @var string methode
*/
private $method = 'POST';
/**
* Est-ce qu'il y a besoin d'un enctype ? (Gérer les fichiers)
* @var boolean enctype
*/
private $enctype = false;
/**
* Est-ce que le formulaire doit respecter la norme bootstrap ?
* @var boolean bootstrap
*/
private $bootstrap = true;
/**
* Contenu du formulaire
* @var array contenu
*/
private $content = [];
/**
* @param string nom de la route
* @param array paramètres de la route
*/
public function __construct($route_name = "", $route_name_params = [])
{
$this->setRouteName($route_name, $route_name_params);
}
/**
* Permet d'ajouter un input au contenu du formulaire
* @param string type de l'input
* @param string nom|id de l'input
* @param string nom du label
* @param array paramètres
*/
public function add($type, $name, $label = "", $params = []) {
$this->content[] = $this->createInput($type, $name, $label, $params);
return $this;
}
/**
* Crée un bouton de soumission
* @param string texte du bouton
* @param array paramètres
* @return this
*/
public function submit($text, $params = []) {
$this->content[] = "<button type=\"submit\"" . $this->addParams($params) . ">$text</button>";
return $this;
}
/**
* Crée le formulaire
*/
public function createForm() {
$content = "";
foreach ($this->content as $c) {
$content .= $c;
}
echo "<form action=\"$this->route_name\" method=\"$this->method\" " . ($this->enctype ? 'enctype="multipart/form-data">' : '>') . $content . '</form>';
}
/**
* Entoure un input par des div form-group pour bootstrap
* @param string input
* @return string
*/
private function surround($input) {
if ($this->bootstrap) {
return "<div class=\"form-group\">$input</div>";
}
}
/**
* Crée un input
* @param string type de l'input
* @param string nom|id de l'input
* @param string nom du label
* @param array paramètres
*/
private function createInput($type, $name, $label, $params) {
if ($type != "textarea") {
if (!empty($label)) {
if (!$this->bootstrap) {
return $this->createLabel($name, $label) . "<input type=\"$type\" name=\"$name\" id=\"$name\"" . $this->addParams($params) . ">";
} else {
return $this->surround($this->createLabel($name, $label) . "<input type=\"$type\" name=\"$name\" id=\"$name\" class=\"form-control\"" . $this->addParams($params) . ">");
}
} else {
if (!$this->bootstrap) {
return "<input type=\"$type\" name=\"$name\" id=\"$name\"" . $this->addParams($params) . ">";
} else {
return $this->surround("<input type=\"$type\" name=\"$name\" id=\"$name\" class=\"form-control\"" . $this->addParams($params) . ">");
}
}
} else if ($type === "textarea") {
if (!empty($label)) {
if (!$this->bootstrap) {
return $this->createLabel($name, $label) . "<textarea name=\"$name\" id=\"$name\"" . $this->addParams($params) . "></textarea>";
} else {
return $this->surround($this->createLabel($name, $label) . "<textarea name=\"$name\" id=\"$name\" class=\"form-control\"" . $this->addParams($params) . "></textarea>");
}
}
}
}
/**
* Ajoute les paramètres à l'input
* @param array paramètres
*/
private function addParams($params) {
$content = "";
if (!empty($params)) {
foreach ($params as $k => $v) {
$content .= "$k = \"$v\"";
}
}
return $content;
}
/**
* @param string id
* @param string name
* @return string label
*/
private function createLabel($id, $label) {
return "<label for=\"$id\">$label</label>";
}
/**
* Stocker l'url de la route donnée
* @param string nom de la route
* @param array paramètres de la route
*/
private function setRouteName($route_name, $route_name_params) {
$this->route_name = Router::url($route_name, $route_name_params);
return $this;
}
/**
* Modifier la méthode du formulaire (GET, POST, ...)
* @param string methode
*/
public function setMethod($method) {
$this->method = $method;
return $this;
}
/**
* Modifier si le formulaire doit utiliser les normes de bootstrap
* @param boolean bootstrap
*/
public function setBootstrap($bootstrap) {
$this->bootstrap = $bootstrap;
return $this;
}
/**
* Modifier si le formulaire a besoin d'un enctype
* @param boolean enctype
*/
public function setEnctype($enctype) {
$this->enctype = $enctype;
return $this;
}
}
Validator :
/**
* Permet de valider des données
*/
class Validator {
/**
* Tableau contenant les erreurs indexés par le nom du champ
* @var array erreurs
*/
public static $errors = [];
/**
* Valide le formulaire
* @param array données du formulaire
* @param array conditions du formulaire
* @return boolean valider ou non
*/
public static function validate($data, $conditions) {
if (count(array_intersect_key($data, $conditions)) === 0) {
throw new ValidatorException("No matching keys in posted data");
}
$is_valid = true;
foreach ($conditions as $input => $conds) {
$conds = explode('|', $conds);
foreach ($conds as $condition) {
if (strpos($condition, ':')) {
$cond = explode(':', $condition);
$action = $cond[0];
if (!self::$action($input, $data[$input], $cond[1])) {
$is_valid = false;
}
} else {
if (!self::$condition($input, $data[$input])) {
$is_valid = false;
}
}
}
}
return $is_valid;
}
/**
* Création d'une erreur
* @param string message de l'erreur
* @param string nom du champ
*/
private static function createError($message, $input) {
if (!array_key_exists($input, self::$errors)) {
self::$errors[$input] = $message;
}
}
/**
* Valide si le champ a été remplis
* @param string nom du champ
* @param string contenu du champ
* @return boolean valide ou pas ?
*/
private static function required($input, $input_content) {
if (empty($input_content)) {
self::createError("Le champ $input est requis.", $input);
return false;
}
return true;
}
/**
* Valide si le champ a bien le minimum de caractère indiqués
* @param string nom du champ
* @param string contenu du champ
* @param int longueur
* @return boolean valide ou pas ?
*/
private static function min($input, $input_content, $length) {
$len = strlen($input_content);
if ($len < $length) {
self::createError("Le champ $input doit faire minimum $length caractères", $input);
return false;
}
return true;
}
/**
* Valide si le champ ne dépasse pas le nombre de caractère indiqués
* @param string nom du champ
* @param string contenu du champ
* @param int longueur
* @return boolean valide ou pas ?
*/
private static function max($input, $input_content, $length) {
$len = strlen($input_content);
if ($len > $length) {
self::createError("Le champ $input doit faire maximum $length caractères", $input);
return false;
}
return true;
}
}
Merci beaucoup !!
Salut,
Il serait intéressant de voir un exemple d'utilisation :D :D
Sinon, je trouve que c'est pas mal écrit :D (y)
@plus
Pierre
Salut,
merci de votre retour ^^
Alors voici un exemple pour chaque classe :
FormBuilder :
$contactForm = new App\Library\FormBuilder\FormBuilder('contact.post');
$contactForm->add('text', 'name', 'Nom :', ['placeholder' => 'Nom'])
->add('text', 'subject', 'Sujet :', ['placeholder' => 'Sujet'])
->add('email', 'email', 'Email :', ['placeholder' => 'Votre Email'])
->add('textarea', 'message', 'Message :', ['placeholder' => 'Votre Message'])
->submit('Envoyer', ['class' => 'btn btn-primary']);
$contactForm->createForm();
Validator :
$is_valid = Validator::validate($_POST, [
'name' => 'required|min:3|alpha',
'subject' => 'required|min:5|max:12',
'email' => 'required|email'
]);
if ($is_valid) {
// Tout est ok !
} else {
// Un ou plusieurs champs ne sont pas valides
}
Quelque chose comme ça, bon le formbuilder, je pense pas que ce soit vraiment super utile de l'utiliser, à part dans des cas très basiques où il fera l'affaire, mais dès que l'on veut par exemple faire un formulaire un peu plus "beau" et pas juste avec des inputs qui se suivent les uns les autres bah là ça devient plus compliqué, et j'ai pas encore trouvé la meilleure façon d'optimiser mon FormBuilder pour faire ce genre de choses, peut-être que je réessayerais plus tard ^^
Bonne journée.
Salut,
J'ai pas tout regardé, mais ça semble correct.
Pour être à fond dans la POO remplace tous tes private
par protected
pour prévoir l'héritage, si un jour t'as envie de surcharger cette classe pour y ajouter un nouveau comportement.
Salut Balsakup,
En effet, je n'y avais pas pensé, c'est une bonne idée !
Merci de votre retour
Je ne suis pas du tout un expert PHP non plus, je trouve tes classes bien écrites ;)
En plus de remplacer private
par protected
, je changerai peut être le retour de ta fonction validate pour renvoyer un array d'erreurs et non pas juste un booléen pour être plus explicite concernant les erreurs que l'utilisateur a pu faire, et pas juste un : "une erreur est survenue"
En faite,
Je récupère dans la vue les erreurs après, j'ai pas totalement fini la class, je vais rajouter des méthodes pour savoir s'il y a des erreurs, pour les afficher dans la vue etc..
Salut,
Je me suis lancé dans une classe de formulaires un peu semblable à celle-ça dans le principe et le premier conseil que j'ai reçu c'est de morceler ma classe.
Tu as une class pour le formulaire et une classe pour chaque type de champ.
ça t'oblige a faire plus de class mais c'est au final plus modulable.
ça peut donner un truc du genre :
$form = new Formulaire("post", "/user/add");
$form->addField( new Formulaire_Input("name", "label", "value") );
$form->addField( new Formulaire_Textarea("name", "label", "value") );
echo $form->render();
Voici un principe de classes très rapide.
La classe de formulaire. Elle stocke les champs et ensuite les affiche.
class Formulaire
{
protected $_fields = array();
protected $_attributs = array();
public function __contruct($name, $action, $method)
{
$this ->setAttribute('name', $name)
->setAttribute('action', $action)
->setAttribute('method', $method);
}
public function setAttribute($name, $value, $overwrite = false)
{
//--> Si l'attribut est
if ( !isset($this->_attributs[$name]) ) {
$this->_attributs[$name] = $value;
return $this;
}
if ($overwrite == true) {
$this->_attributs[$name] = $value;
} else {
$this->_attributs[$name] .= " " . $value;
}
return $this;
}
public function addField($field)
{
$this->_fields[] = $field;
return $this;
}
public function render()
{
//--> Debut du form
$retVal = '<form ';
foreach ($this->_atributs AS $k => $v) {
$retVal .= $k . '="' . $v . '" ';
}
$retVal .= '>';
//--> Champs du formulaire
foreach ($this->_fields AS $field) {
$retVal .= $field->render();
}
//--> Fin du formulaire
$retVal .= '</form>';
return $retVal;
}
}
Ensuite tu as une class "standard" pour faire le rendu d'un champs car beaucoup sont très proches :
<input type="text" name="" value="" />
<input type="date" name="" value="" />
<input type="hidden" name="" value="" />
<input type="password" name="" value="" />
On a donc une classe de base et d'autres qui l'étendent
abstract class Formulaire_Input
{
$_type = "";
$_label = "";
$_value = "";
public function construct($name, $label, $value = "", $attributs = null)
{
$this->setAttribute("name", $name);
$this->_label = $label;
$this->_value = $value;
if ( $attributs !== null ) {
foreach ($attributs AS $k => $v) {
$this->setAttribute($k, $v);
}
}
}
public function setAttribute($name, $value, $overwrite = false)
{
//--> Si l'attribut n'existe pas
if ( !isset($this->_attributs[$name]) ) {
$this->_attributs[$name] = $value;
return $this;
}
if ($overwrite == true) {
$this->_attributs[$name] = $value;
} else {
$this->_attributs[$name] .= " " . $value;
}
return $this;
}
public function render()
{
$retVal = '<label>' . $this->_label . '</label>';
$retVal .= '<input type="' . $this->_type . '" value="' . $this->_value . '" ';
foreach ($this->_atributs AS $k => $v) {
$retVal .= $k . '="' . $v . '" ';
}
$retVal .= ' />';
return $retVal
}
}
class Formulaire_Input_Text extends Formulaire_Input {
$_type = "text";
}
class Formulaire_Input_Password extends Formulaire_Input {
$_type = "password";
}
class Formulaire_Input_Hidden extends Formulaire_Input {
$_type = "hidden";
}
Tu peux voir que les classes ne font que définir le type.
Pour le texarea le rendu est un peu différent donc dans sa classe on ré-écrit le méthode render();
class Formulaire_Input_Textarea extends Formulaire_Input {
$_type = "textarea";
public function render()
{
$retVal = '<label>' . $this->_label . '</label>';
$retVal .= '<textarea ';
foreach ($this->_atributs AS $k => $v) {
$retVal .= $k . '="' . $v . '" ';
}
$retVal .= '>' . $this->_value . '</textarea>';
return $retVal
}
}
Maintenant admettons que tu ai besoin d'ajouter une classe à tout tes champs en fonction d'un framework tu peux faire ça :
class FormulaireBootstrap extends Formulaire
{
public function addField($field)
{
$field->setAttribute("class", "control-form");
$this->_fields[] = $field;
return $this;
}
}
Et tu peux même ré-écrite la méthode render() si tu veux entourer chaque champ avec un div ou autre...
Mais comme ça si tu veux passer un un autre framework, Bulma, semantic-ui, autre tu as juste a créer un héritage de Formulaire pour adapter juste le rendu. Tout le code "métier" ne change pas.
En espérant t'avoir aidé.
Kaimite
Hey Kaimite,
Merci beaucoup pour ton retour, j'avais pensé à ça, mais je m'étais dit que ce devriendrais beaucoup trop complexe, mais finalement, ça va, merci beaucoup, je vais m'y atteler de suite, c'est une super idée la classe abstraite pour les inputs, je n'y avais pas songé. Je vais de ce pas tenter de creer un FormBuilder plus efficace!
Bonne journée.
Hey,
J'ai donc codé un FormBuilder comme me l'a suggéré Kaimite, voici à quoi cela ressemble, il me paraît plutôt pas mal et bien modulable et utilisable un peu à toutes les sauces.
Cette classe permet de crée le formulaire en lui-même
<?php
namespace App\Library\FormBuilder;
use App\Router\Router;
/**
* Création de formulaires HTML
* Le formulaire utilise par défaut la méthode POST
* Possibilité de changer les valeurs avec les méthodes :
* setMethod('POST/GET')
* setEnctype()
*/
class FormBuilder {
/**
* Url de la route (même url par défaut)
* @var string url route
*/
private $route_name = "";
/**
* Paramètres de la route
* @var array paramètres
*/
private $route_name_params = [];
/**
* Contient les attributs du formulaire (url, method, enctype)
* @var array attributs
*/
protected $attributs = [];
/**
* Les champs du formulaire
* @var array champs
*/
protected $fields = [];
/**
* @param string nom de la route
* @param array paramètres de la route
*/
public function __construct($route_name = "", $route_name_params = [])
{
$this->setRouteName($route_name, $route_name_params);
$this->attributs['method'] = 'POST';
}
/**
* Ajouter un champ au formulaire
* @param string $field_type type du champ (text, select etc...)
* @param string $field_name nom du champ, id aussi si label = true
* @param boolean $field_label utiliser un label ?
* @param string $field_label_value message du label
* @param array $field_attributs paramètres du champ
*/
public function add($field_type, $field_name, $field_label = false, $field_label_value = "", $field_attributs = []) {
$input = "App\\Library\\FormBuilder\\" . ucfirst($field_type);
$field = new $input($field_name, $field_label, $field_label_value, $field_attributs);
$this->fields[] = $field;
return $this;
}
/**
* Permet de garder dans l'input la valeur qui a été envoyé par l'utilisateur
* Utilisation : $form->add()->keepValue;
* @return this
*/
public function keepValue() {
$input = end($this->fields);
if (isset($_POST[$input->attributs['name']])) {
$input->attributs['value'] = $_POST[$input->attributs['name']];
}
return $this;
}
/**
* Ajouter un bouton submit
* @param string $message message du bouton
* @param array $attributs attributs du bouton
*/
public function submit($message, $attributs = []) {
$this->fields[] = $this->createSubmitButton($message, $attributs);
}
/**
* Crée le bouton de type submit
* @param string $message message du bouton
* @param array $attributs attributs du bouton
* @return html bouton en HTML
*/
private function createSubmitButton($message, $attributs) {
$button = "<button type=\"submit\" ";
foreach ($attributs as $k => $v) {
$button .= $k . '="' . $v . '" ';
}
$button .= ">";
$button .= $message;
$button .= "</button>";
return $button;
}
/**
* Crée le formulaire, remplis les attributs du formulaire
* et affiche les champs
*/
public function createForm() {
$form = '<form ';
// Attributs du formulaire
foreach ($this->attributs as $k => $v) {
$form .= $k . '="' . $v . '" ';
}
$form .= '>';
// Champs du formulaire
foreach ($this->fields as $input) {
if (is_object($input)) {
$form .= $input->render();
} else {
$form .= $input;
}
}
$form .= '</form>';
echo $form;
}
/**
* Stocker l'url de la route donnée
* @param string nom de la route
* @param array paramètres de la route
*/
private function setRouteName($route_name, $route_name_params) {
$this->attributs['action'] = Router::url($route_name, $route_name_params);
return $this;
}
/**
* Modifier la méthode du formulaire (GET, POST, ...)
* @param string methode
*/
public function setMethod($method) {
$this->attributs['method'] = $method;
return $this;
}
/**
* Modifier si le formulaire a besoin d'un enctype
*/
public function setEnctype() {
$this->attributs['enctype'] = "multipart/form-data";
return $this;
}
}
Cette classe va permettre de définir un style au formulaire, dans mon cas Bootstrap, il suffirais de crée une autre classe du même style, en changeant les mêmes fonctions que j'ai changé
<?php
namespace App\Library\FormBuilder;
/**
* Formulaire bootstrap, objet qui permet de définir comment les champs
* seront stylisés avec les normes bootstrap
*/
class FormBootstrap extends FormBuilder {
/**
* Crée le formulaire, remplis les attributs du formulaire
* et affiche les champs
* avec BOOTSTRAP
*/
public function createForm() {
$this->bootstrapFields();
$form = '<form ';
// Attributs du formulaire
foreach ($this->attributs as $k => $v) {
$form .= $k . '="' . $v . '" ';
}
$form .= '>';
// Champs du formulaire
foreach ($this->fields as $input) {
$form .= '<div class="form-group">';
if (is_object($input)) {
$form .= $input->render();
} else {
$form .= $input;
}
$form .= '</div>';
}
$form .= '</form>';
echo $form;
}
/**
* Changer le classe des champs par form-control pour
* correspondre à la norme bootstrap
*/
private function bootstrapFields() {
foreach($this->fields as $input) {
if (is_object($input)) {
if (isset($input->attributs['class'])) {
$input->attributs['class'] .= " " . 'form-control';
} else {
$input->attributs['class'] = 'form-control';
}
}
}
}
}
Cette classe permet d'avoir des champs inputs plus généraux
<?php
namespace App\Library\FormBuilder;
/**
* Classe qui va définir les bases d'un champ
*/
abstract class FormInput {
/**
* Message du label
* @var string
*/
public $field_label_value = "";
/**
* Est-ce que le champ doit avoir un label
* @var boolean
*/
public $field_label = false;
/**
* Paramètres du champ
* @var array
*/
public $attributs = [];
/**
* Création du champ
* @param string $field_name nom du champ (text, select, ...)
* @param boolean $field_label utilisation d'un label ?
* @param string $field_label_value valeur du label
* @param array $field_attributs paramètres du champ
*/
public function __construct($field_name, $field_label, $field_label_value, $field_attributs) {
$this->attributs['name'] = $field_name;
if ($field_label) {
$this->field_label = true;
$this->attributs['id'] = $field_name;
}
if (!empty($field_label_value)) {
$this->field_label_value = $field_label_value;
}
// Si l'attribut existe déjà, on le remplace
// ou, si l'attribut est la classe, on ajoute la classe
if (sizeof(array_intersect_key($field_attributs, $this->attributs)) != 0) {
foreach ($field_attributs as $k => $v) {
if ($k == $this->attributs[$k]) {
if ($k == "class") {
$this->attributs[$k] .= " " . $v;
} else {
$this->attributs[$k] = $v;
}
}
}
} else {
foreach ($field_attributs as $k => $v) {
$this->attributs[$k] = $v;
}
}
}
/**
* Crée le champ
* @return html retourne le champ en HTML
*/
public function render() {
if ($this->field_label) {
return $this->createLabelInput();
} else {
return $this->createInput();
}
}
/**
* Crée un champ avec un label
* @return html le champ en HTML
*/
private function createLabelInput() {
$input = "<label>$this->field_label_value</label>";
$input .= "<input ";
foreach ($this->attributs as $k => $v) {
$input .= $this->renderAttribute($k, $v);
}
$input .= ' />';
return $input;
}
/**
* Crée un champ sans label
* @return html le champ en HTML
*/
private function createInput() {
$input = "<input ";
foreach ($this->attributs as $k => $v) {
$input .= $this->renderAttribute($k, $v);
}
$input .= ' />';
return $input;
}
/**
* Renvoie les attributs sous forme HTML
* @param string $key clé de l'attribut
* @param string $value valeur de la clé
*/
protected function renderAttribute($key, $value) {
return $key . '="' . $value . '" ';
}
}
Cette classe permet de crée un input de type Text. Dans mon FormBuilder, je crée une instance de ce type d'objet grâce au "type" de l'input, si c'est un type email, je crée une classe Email avec le type qui change.
<?php
namespace App\Library\FormBuilder;
/**
* Champ de type text
*/
class Text extends FormInput {
public function __construct($field_name, $field_label, $field_label_value, $field_attributs) {
parent::__construct($field_name, $field_label, $field_label_value, $field_attributs);
$this->attributs['type'] = 'text';
}
}
Si c'est un textarea, je vais faire cela :
<?php
namespace App\Library\FormBuilder;
/**
* Champ de type textarea
*/
class Textarea extends FormInput {
/**
* Surcharge de la fonction render pour afficher le champ
* @return html
*/
public function render() {
if ($this->field_label) {
return $this->createLabelTextarea();
} else {
return $this->createTextarea();
}
}
/**
* Crée un textarea avec label
* @return html textarea avec label html
*/
private function createLabelTextarea() {
$textarea = "<label>$this->field_label_value</label>";
$textarea .= "<textarea ";
foreach ($this->attributs as $k => $v) {
$textarea .= $this->renderAttribute($k, $v);
}
$textarea .= '></textarea>';
return $textarea;
}
/**
* Crée un textarea sans label
* @return html textarea html
*/
private function createTextarea() {
$textarea = "<textarea ";
foreach ($this->attributs as $k => $v) {
$textarea .= $this->renderAttribute($k, $v);
}
$textarea .= '></textarea>';
return $textarea;
}
}
Et on peut en faire pleins comme ça ! C'est super, et surtout les mêttre à sa sauce. Je pense qu'il y a beaucoup de codes que j'aurais pu optimiser un peu mieux, beaucoup de codes redondants je trouve. J'aimerais avoir votre avis sur cela.
Voici un exemple de création de formulaire :
$form = new App\Library\FormBuilder\FormBootstrap('formbuilder');
$form->add('text', 'name', true, 'Nom :', ['placeholder' => 'Nom'])
->add('text', 'subject', true, 'Sujet :', ['placeholder' => 'Sujet'])->keepValue()
->add('email', 'email', true, 'Email :', ['placeholder' => 'Votre Email'])
->add('textarea', 'message', true, 'Message :', ['placeholder' => 'Votre Message'])
->submit('Envoyer', ['class' => 'btn btn-primary']);
$form->createForm();
Ici, on crée un nouveau fomulaire de type Bootstrap qui va poster sur la route 'formbuilder', on peut lui ajouter des méthodes comme :
$form->setEnctype() // Pour gérer les fichiers
$form->setMethod('GET') // Pour changer la méthode du formulaire (de base il est en post)
Par la suite, on ajoute au form des inputs grâce à la méthode add :
add(type de l'input, nom de l'input, besoin d'un label ?, message du label, ['class' => 'ma-super-class', 'placeholder' => 'mon-placeholder', etc..]
On peut accompagner add de la méthode "keepValue()" qui va permettre, lorsque le formulaire est posté, si l'utilisateur est renvoyé sur la page du formulaire car il y a une erreur par exemple de garder dans l'input la valeur que l'utilisateur a entré
Voilà voilà, j'aimerais avoir des avis sur cela! Je pense que c'est beaucoup mieux que le premier aha ^^
Merci bien :p
Quand j'ai fait la mienne j'ai commencé par faire une classe de base :
class Html
{
/**
* Liste des arrtibuts HTML du formulaire sous la
* forme d'un tableau associatif array("attribut" => "valeur")
*
* @var array
*/
protected $_attributs = array();
/**
* Defini un ou des attributs HTML du formulaire
*
* @param string $attribut
* @param string $valeur
* @param bolean $surcharge Definit s'il faut surcharger l'attribut
*
* @return void
* @see $_attributs
*/
public function setAttribut($attribut, $valeur, $surcharge = false)
{
if ( !empty($this->_attributs[$attribut]) AND $surcharge == true ) {
$this->_attributs[$attribut] .= " " . $valeur;
} else {
$this->_attributs[$attribut] = $valeur;
}
return $this;
}
/**
* Defini plusieurs attributs d'un coup
*
* @param array $listeAttributs La liste des attributs sous forme d'un tableau associatif
*
* @return void
* @see $_attributs
*/
public function setAttributs ( $listeAttributs ) {
foreach ( $listeAttributs AS $attribut => $valeur ) {
$this->setAttribut($attribut, $valeur);
}
return $this;
}
/**
* Supprimer un attribut
*
* @param string $attribut L'attribut a supprimer
*
* @return void
* @see $_attributs
*/
public function deleteAttribut ( $attribut ) {
if ( isset($this->_attributs[$attribut]) ) {
unset($this->_attributs[$attribut]);
}
return $this;
}
/**
* Renvoi un attribut demande
*
* @var string $attribut Le nom de l'attribut
*
* @return string
*/
public function getAttribut($attribut) {
if ( isset( $this->_attributs[$attribut] ) ) {
return $this->_attributs[$attribut];
} else {
return false;
}
}
}
Elle me sert a eviter de reprendre a chaque fois les setAttribute
et toutes mes autres classes etendent cette class.
Je ne suis pas sur que la méthode suivante soitr obligatoire.
protected function renderAttribute($key, $value) {
return $key . '="' . $value . '" ';
}
Dans ma méthode addElement j'ai ça :
if ( $element instanceof Myeo_Form_Element ) {
// ajout du champ
} else {
throw new Exeption("Ce type de champ n'est pas pris en compte");
}
D'autre part si j'ai un champ qui est de type file je modifie automatiquement le enctype
//--> Verification du le nouveau champ est un champ file
if ( $element->getType() == "file" || $element instanceof Myeo_Form_Element_File_JqueryFileUpload ) {
$this->setAttribut("enctype", "multipart/form-data");
}
Sinon j'ai utilise un template pour le rendu du champ. Je trouve ça plus simple.
Par exemple
$field->setTemplate('<div class="row"><div class="col-4-12">{{label}}</div><div class="col-8-12">{{input}}</div></div>');
Voilà !
Kaimite
Juste une petite remarque sur les label :
généralement on les lie à l'input par l'id mais si tu ne veux pas t'embéter avec l'id, tu peux encapsuler l'input dans le label
<label>Nom : <input type 'text' name='nom'></label>
Hey,
J'aime bien comment tu as fait Kaimite, c'est vrai que je pourrais pousser le truc un peu plus loin. Je verrais avec une utilisation réelle du formbuilder qu'est-ce que j'ai besoin ou pas.
Merci Huggy, je ne savais pas du tout que l'on pouvais faire ça ! Ca évite de se faire chier avec l'id aha !