Bonjour, j'ai suivi le tuto sur la programmation objet : http://fr.openclassrooms.com/informatique/cours/programmez-en-oriente-objet-en-php et je l'adapte pour faire un quizz

Pour cela j'ai repris l'API dans le tp du tuto que je voudrai adapter en formulaire de type radio.

Dans le tuto, le champ name est associé à sa valeur dans la bibliothèque mysql par la méthode add dans Form comme ceci :

public function add(Field $field)
  {
    // On récupère le nom du champ.
    $attr = $field->name();
    $field->setValue($this->entity->$attr()); // On assigne la valeur correspondante au champ.
     
     
    $this->fields] = $field; // On ajoute le champ passé en argument à la liste des champs.
    return $this;
  }

Pour des champs de type text il n'y a pas de problème mais pour des champs de type radio, je peux définir qu'une seule et même valeur.

voici la class Field

<?php
namespace Library;
 
abstract class Field
{
  protected $errorMessage;
  protected $label;
  protected $name;
  protected $name2;
  protected $validators = array();
  protected $value;
  protected $value_choix1;
   
  public function __construct(array $options = array())
  {
    if (!empty($options))
    {
      $this->hydrate($options);
    }
  }
   
  abstract public function buildWidget();
   
  public function hydrate($options)
  {
    foreach ($options as $type => $value)
    {
      $method = 'set'.ucfirst($type);
       
      if (is_callable(array($this, $method)))
      {
        $this->$method($value);
      }
    }
  }
   
  public function isValid()
  {
    foreach ($this->validators as $validator)
    {
      if (!$validator->isValid($this->value))
      {
        $this->errorMessage = $validator->errorMessage();
        return false;
      }
    }
     
    return true;
  }
   
  public function label()
  {
    return $this->label;
  }
   
  public function length()
  {
    return $this->length;
  }
   
  public function name()
  {
    return $this->name;
  }
   
   public function name2()
  {
    return $this->name2;
  }
   
  public function validators()
  {
    return $this->validators;
  }
   
  public function value()
  {
    return $this->value;
  }
   
  public function value_choix1()
  {
    return $this->value_choix1;
  }
   
   
  public function setLabel($label)
  {
    if (is_string($label))
    {
      $this->label = $label;
    }
  }
   
  public function setLength($length)
  {
    $length = (int) $length;
     
    if ($length > 0)
    {
      $this->length = $length;
    }
  }
   
  public function setName($name)
  {
    if (is_string($name))
    {
      $this->name = $name;
    }
  }
   
  public function setName2($name2)
  {
    if (is_string($name2))
    {
      $this->name2 = $name2;
    }
  }
   
  public function setValidators(array $validators)
  {
    foreach ($validators as $validator)
    {
      if ($validator instanceof Validator && !in_array($validator, $this->validators))
      {
        $this->validators] = $validator;
      }
    }
  }
   
  public function setValue($value)
  {
    if (is_string($value))
    {
      $this->value = $value;
    }
  }
   
  public function setValue1($value_choix1)
  {
    if (is_string($value_choix1))
    {
      $this->value_choix1 = $value_choix1;
    }
  }
   
}

La classe QuizzFormBuilder

<?php
namespace Library\FormBuilder;
 
class QuizzFormBuilder extends \Library\FormBuilder
{
  public function build()
  {
    $this->form->add(new \Library\StringField(array(
        'label' => 'Question',
        'name' => 'question',
        'maxLength' => 99,
        'validators' => array(
          new \Library\MaxLengthValidator('La question que vous avez proposé est trop longue', 100),
          new \Library\NotNullValidator('Merci de spécifier votre question'),
        ),
       )))
       ->add(new \Library\RadioField(array(
        'label' => 'Propositions',
        'name' => 'choix1',
        'name2' => 'choix2',
        'value2' => '5',
        'value3' => '6',
        'maxLength' => 49,
        'validators' => array(
          new \Library\MaxLengthValidator('Le choix1 que vous avez proposé est trop long', 50),
          new \Library\NotNullValidator('Merci de spécifier votre choix1'),
        ), 
       )))
       ->add(new \Library\StringField(array(
        'label' => 'Reponse',
        'name' => 'reponse',
        'maxLength' => 49,
        'validators' => array(
          new \Library\MaxLengthValidator('La reponse que vous avez proposé est trop longue', 50),
          new \Library\NotNullValidator('Merci de spécifier votre reponse'),
        ), 
       )));
  }
}

et la classe RadioField

public function buildWidget()
{
  $widget = '';
   
  if (!empty($this->errorMessage))
  {
    $widget .= $this->errorMessage.'<br />';
  }
   
  $widget .= '
                  <label>'.$this->label.'</label>
                  <input type = "radio" name = "'.$this->name.'" value=""/> '.htmlspecialchars($this->value_choix1).' </br>
                  <input type = "radio" name = "'.$this->name.'" value=""/> '.htmlspecialchars($this->value).'  </br>
                  <input type = "radio" name = "'.$this->name.'" value=""/> '.htmlspecialchars($this->value).'
            ';
   
  return $widget;
}

J'aimerai associer dans la fonction add() de la classe Form, name2 que j'ai définit dans Field, de la même maniere que name

Merci de m'éclairer

7 réponses


Xen0risDEV
Réponse acceptée

Bonsoir, pour les Quizz seul deux table suffise:

  • Question
    • id_question
    • id_reponse
    • name_question
    • text_question
    • choise_reponse (séparé par des virgule pour simplifier et faire un explode, puis un foreach.)

Exemple:

<?php
$text_ question = "Qui mange des bananes ?";
$choise_reponse = "lapin;canard;requin;singe";
$choise_reponse = explode(';', $choise_reponse);
foreach($choise_reponse as $k => $v) {
    print($v); 
}
  • Réponse
    • id_reponse
    • id_question
    • reponse_reponse
    • reponse_correct

Ensuite vous lié ses deux table ensemble pour ne faire qu'une SELECT, et le reponse_correct et la pour faire un test entre la vrai réponse.

Exemple: (voir n°1), Qui mange des bananes ? Xen0ris à posté un lapin. La réponse et fausse !

$reponse_correct = "singe";
$reponse_send = $_POST'reponse'];
if($reponse_correct != $reponse_send) {
    print('Perdu !');
}

Ensuite à vous d'adapter ses exemple.

Cordialement.

Bonjour, pourriez vous expliquer plus précisément ce que vous souhaiter

Cordialement.

jeanmaki
Auteur

Dans mon quizzformbuilder j'ai :

'name' => 'choix1',

Or à l'affichage, cela n'affiche pas "choix1" mais cela affiche la valeur correspondant au champ-->choix1-->dans ma base de données--> soit dans mon exemple "carole"

Ce paramètre est définit dans la class Form

Comment faire pour ajouter des méthodes de la même manière que name dans Form

Imaginons avec un name2 par exemple.. il faut faire un array ?

public function add(Field $field)
  {
    // On récupère le nom du champ.
    $attr = $field->name();
    $field->setValue($this->entity->$attr()); // On assigne la valeur correspondante au champ.

    $this->fields] = $field; // On ajoute le champ passé en argument à la liste des champs.
    return $this;

     // On récupère le nom du champ.

  }

Merci

Bonjour (pardonnez du retard de réponse), si je comprends bien vous souhaiter créer un "Quizz" ?

Si oui : Vous pourriez faire plus simple que ce grand code :)

Cordialement.

jeanmaki
Auteur

En fait je veux créer un quizz avec une seule question à la fois par page, ou les questions viennent d'une base de données et que les réponses soient envoyées dans une autre base de données

Pour le controller j'ai cette fonction executeShow() :

public function executeShow(\Library\HTTPRequest $request)

{
    $manager = $this->managers->getManagerOf('Questions');
    $questions = $manager->getQuestion($request->getData('id'));

      if ($request->method() == 'POST')
  {

    $reponse = new \Library\Entities\Reponse(array(
      'questions' => $request->getData('id'),
      'auteur' => $request->getData('id'),
      'reponse' => $request->postData('reponse')
    ));
  }
  else
  {
    $reponse = new \Library\Entities\Reponse;
  }

   $formBuilder = new \Library\FormBuilder\QuestionsFormBuilder($questions);
   $formBuilder->build();

   $form = $formBuilder->form();

  if($request->method() == 'POST' && $form->isValid())
  {
    $this->managers->getManagerOf('Reponses')->save($reponse);
    $this->app->user()->setFlash('Le commentaire a bien été ajouté, merci !');
    $this->app->httpResponse()->redirect('questions-'.$request->getData('questions2').'.html');

  }

  $this->page->addVar('questions', $questions);
  $this->page->addVar('form', $form->createView());
  $this->page->addVar('title', '1ere question');
}

je récupère les questions par la fonction getQuestion () :

public function getQuestion($id)

      {
        $requete = $this->dao->prepare('SELECT id, laquestion, choix1, choix2, choix3, dateAjout, reponse, dateModif FROM nombres WHERE id = 1');

        $requete->bindValue('1', (int) $id, \PDO::PARAM_INT);
        $requete->execute();

        $requete->setFetchMode(\PDO::FETCH_CLASS | \PDO::FETCH_PROPS_LATE, '\Library\Entities\Questions');

        if ($questions = $requete->fetch())
        {

          return $questions;
        }

        return null;
      }

et je sauvegarde la réponse dans add() :

protected function add(Reponse $reponse)
  {
    $q = $this->dao->prepare('INSERT INTO comments_nombres SET questions = :questions, reponse = :reponse, auteur = :auteur, date = NOW()');

    $q->bindValue(':questions', $reponse->questions(), \PDO::PARAM_INT);
    $q->bindValue(':auteur', $reponse->auteur());
    $q->bindValue(':reponse', $reponse->reponse());

    $q->execute();

    $reponse->setId($this->dao->lastInsertId());
  }

par l'intermédiaire de la fonction save() :

public function save(Reponse $reponse)
  {

    if ($reponse->isValid())
    {
        $reponse->isNew() ? $this->add($reponse) : $this->modify($reponse);

    }
    else
    {
      throw new \RuntimeException('Le commentaire doit être validé pour être enregistré');
    }

  }

Pour éviter de réécrire à chaque fois un formulaire pour une nouvelles question j'ai repris l'API qu'il y avait dans le tuto et je l'ai modifié pour faire le formulaire du quizz qui se construit de cette manière :

QuestionFormBuilder :

<?php
namespace Library\FormBuilder;

class QuestionsFormBuilder extends \Library\FormBuilder
{
  public function build()
  {
    $this->form->add(new \Library\PropositionsField(array(
        'label' => 'Propositions',
        'name' => 'reponse',
        'choix' => 'choix1',
        'validators' => array(
          new \Library\NotNullValidator('Merci de spécifier votre choix'),
        ),
       )))
       ->add(new \Library\PropositionsField(array(
        'name' => 'reponse',
        'choix' => 'choix2',
        'validators' => array(
          new \Library\NotNullValidator('Merci de spécifier votre choix'),
        ),
       )))
       ->add(new \Library\PropositionsField(array(
        'name' => 'reponse',
        'choix' => 'choix3',
        'validators' => array(
          new \Library\NotNullValidator('Merci de spécifier votre choix'),
        ),
       )));
  }
}

La construction des Fields : PropositionsField

<?php
namespace Library;

class PropositionsField extends Field
{

  public function buildWidget()
  {
    $widget = '';

    if (!empty($this->errorMessage))
    {
      $widget .= $this->errorMessage.'<br />';
    }

    $widget .= '<label>'.$this->label.'</label><input type="radio" name="reponse"';

    if (isset($this->value))
    {
      $widget .= ' value="'.htmlspecialchars($this->value).'"';
    }

    return $widget .= ' /> '.htmlspecialchars($this->value).'';
  }
}

A chaque champs "choix "du QuestionFormBuilder, j'associe une valeur que je récupère dans ma base de données par l'intermediaire de la fonction add(Field $field) :

// On récupère le nom du champ.
   $attr = $field->choix();
   $field->setValue($this->entity->$attr()); // On assigne la valeur correspondante au champ.

   $this->fields] = $field; // On ajoute le champ passé en argument à la liste des champs.
   return $this;

    // On récupère le nom du champ.

J'arrive a récupérer la question, les valeurs des choix respectifs, tout s'affiche comme il faut!

Lorsque je clique sur un des choix et que je submit, celui-ci s'ajoute à ma base de données.

J'aimerai maintenant avoir un message d'erreur lorsque je valide sans appuyer sur un des boutons choix, genre 'veuillez choisir une proposition svp'

Sur l'api du tuto cela marche très bien avec NotNullValidator :

<?php
namespace Library;

class NotNullValidator extends Validator
{
  public function isValid($value)
  {
    return $value != '';
  }
}

Cette méthode marche car lorsque les champs sont vides et bien le message d'erreur apparait....

Or vu que moi je récupère des valeurs existantes (questions + propositions de réponses) dans une base de données et bien mes champs sont jamais vide et le message d'erreur n’apparaît jamais

Merci de m'éclairer

jeanmaki
Auteur

Merci je vais essayer de faire ainsi ;-)

Bonsoir, pas de soucis.

Cordialement.