SamC

General if/else structuring help

Recommended Posts

@SamC don't know if you just put a quick example here but in your case the checker class does not do anything more then the valitron class so it is nice for testing but actually quite useless :) do i miss anything?

btw: I don't know valitron, I only used https://doc.nette.org/en/2.4/forms#toc-standalone-forms since this is the only library I know that does client-side and server-side validaton in one go. maybe you want to have a look...

  • Like 1
  • Thanks 1

Share this post


Link to post
Share on other sites

Yeah, still working on it. I'll check that link out, looks interesting, thanks :) 

Share this post


Link to post
Share on other sites
10 hours ago, SamC said:

And behold, so far so good!

 

Wow, it's like Night & Day compared to your first iteration. Looking very good.

  • Thanks 1

Share this post


Link to post
Share on other sites
17 minutes ago, FrancisChung said:

Wow, it's like Night & Day compared to your first iteration. Looking very good.

That's kind of you to say, thanks. Was on it for quite a few hours today. At the present time, it looks like this, but I wanted to be able to get more of the logic into the class, still seems a bit of a mess to me.

<?php namespace ProcessWire;

class FormChecker {

  // array to hold feedback messages
  public $feedback = [];

  // 3rd party validator object
  private $validator;

  public function __construct($validator) {
    $this->validator = $validator;
  }

  public function checkForm() {
    return $this->validator->validate(); 
  }

  public function checkField($name) {
    return $this->validator->errors($name);
  }

  public function displayFeedback() {
    $str = "";

    if (count($this->feedback)) {
      $str = '<ul class="mb-0">';
      foreach ($this->feedback as $value) {
        $str .= '<li>' . $value . '</li>';
      }
      $str .= '<ul>';
    }

    return $str;
  }
}

// require Valitron class
require_once("./vendor/vlucas/valitron/src/Valitron/Validator.php");

// get recaptcha module
$captcha = $modules->get("MarkupGoogleRecaptcha");

// get sanitized variables
$name = $sanitizer->text($input->post->name);
$email = $sanitizer->email($input->post->email);
$message = $sanitizer->textarea($input->post->message);

// create new valitron
$v = new \Valitron\Validator(array(
  "name" => $name,
  "email" => $email,
  "message" => $message
  )
);

// create valitron rules
$v->rule("required", ["name", "email", "message"]);
$v->rule("email", "email");

// save as property on new $checker object
$checker = new FormChecker($v);

// has form been submitted?
$isSubmitted = $input->post->sendMe;

// default mail sent value
$isSent = false;

if ($isSubmitted) {
  // does form validate after submission
  $formValidates = $checker->checkForm();

  // recaptcha result
  $recaptcha = $captcha->verifyResponse();

  if (!$recaptcha) {
    array_push($checker->feedback, "Recaptcha must be complete.");
  }

  if (!$formValidates) {
    array_push($checker->feedback, "Please fill out the fields correctly.");
  }

  if ($recaptcha && $formValidates) {
    $msg = "
      <html>
        <body>
          <p><b>Name:</b> {$name}</p>
          <p><b>Email:</b> {$email}</p>
          <p><b>Message:</b></p>
          <p>{$message}</p>
        </body>
      </html>";

    $mail = wireMail();
    
    $mail->to("sam@woodenfoxdesign.com")
    ->from($email, $name)
    ->subject('Email from website...')
    ->bodyHTML($message);

    $isSent = $mail->send();

    if ($isSent) {
      array_push($checker->feedback, "Thanks for your message!");
    }
    else {
      array_push($checker->feedback, "Sorry, an error occured. Please try again.");
    }
  }
}
?>

<div id="form-top"></div>

<h2>Suggest a tutorial</h2>

  <?php if($isSubmitted):?>
    <div class="alert <?= ($isSent) ? 'alert-success' : 'alert-danger'?>" role="alert">
      <?= $checker->displayFeedback(); ?>
    </div>
  <?php endif;?>

  <form id="contact-form" method="post" action="#form-top">

    <div class="row">
        <div class="form-group col-sm-12 col-lg-6 py-2 <?= $checker->checkField('name') ? 'has-danger' : ''?>">
            <label for="name">Name (required)</label>
            <input class="form-control" name="name" id="name" type="text">
        </div>

        <div class="form-group col-sm-12 col-lg-6 py-2 <?= $checker->checkField('email') ? 'has-danger' : ''?>">
            <label for="email">Email (required)</label>
            <input class="form-control" name="email" id="email" type="text">
        </div>
    </div>

    <div class="form-group py-2 <?= $checker->checkField('message') ? 'has-danger' : ''?>">
        <label for="message">Message (required)</label>
        <textarea class="form-control" name="message" id="message" rows="8"></textarea>
    </div>

    <div>
        <label for="recaptcha">Recaptcha (required)</label>
        <!-- Google Recaptcha code START -->
        <?php echo $captcha->render(); ?>
        <!-- Google Recaptcha code END -->
    </div>

    <div class="form-group">
        <button type="submit" class="btn btn-primary mt-3" name="sendMe" value="1">Suggest tutorial <i class="fa fa-angle-right" aria-hidden="true"></i></button>
    </div>

  </form>

<?php
  echo $captcha->getScript();
?>

I think I'll have another crack over the weekend, I've learned a few new things about classes so that's good. My brain hurts.

  • Like 1

Share this post


Link to post
Share on other sites
5 hours ago, SamC said:

My brain hurts

Wait till you get to Factory Methods, Contravariance, Covariance, Builder + Specification patterns .... haha

 

5 hours ago, SamC said:

I wanted to be able to get more of the logic into the class, still seems a bit of a mess to me.

Ideally Classes should do one thing and only one thing.
So you should probably make multiple smaller classes that has a very distinct and easily identifiable singular purpose rather than 1 monolithic one that tries to do everything.
 

Share this post


Link to post
Share on other sites
4 hours ago, FrancisChung said:

Wait till you get to Factory Methods, Contravariance, Covariance, Builder + Specification patterns .... haha

Ouch

4 hours ago, FrancisChung said:

So you should probably make multiple smaller classes that has a very distinct and easily identifiable singular purpose rather than 1 monolithic one that tries to do everything.

Ok, that makes sense.

One underlying issue I have is what happens once the form is submitted. The form is on every blog post at the bottom, so when it's submitted, the user has nowhere to be redirected to, they need to stay on the same page, and once sent successfully, the form needs to:

1) Show feedback if there's a problem (field validation and recaptcha) - might ditch recaptcha because it's so annoying for users
2) Be empty if send was successful (with success feedback)
3) Be checked server side, not too fussed about client side validation right now

Currently, this kind of works, but because the page has not been refreshed, or redirected, the page can be refreshed in the browser and the form sends again, possibly a problem with the code itself, but this is why I was looking at ajax forms that could refresh just the form.

The blog pages are also cached which meant when the form was submitted, a cached version of the page is served, when you navigate away to another page, the success message is above the form on that page. Not ideal! Disabling caching works but I can't leave it off.

== EDIT ==

Caching is off at the moment (and the form appears to be working, I receive emails ok). It's at the bottom of each post:

https://www.pwtuts.com/processwire-tutorials/url-segments-and-the-page-reference-field/

Share this post


Link to post
Share on other sites

Hi @SamC,

One thing I find that helps me understand and better structure any classes I attempt to create is a UML tool. Personally, I learn best when I am shown how to do something and a UML diagram is the next best thing to having someone standing over my shoulder. :)

If you are using PhpStorm, you can read about the UML feature here.

  • Like 2

Share this post


Link to post
Share on other sites

I'll look into them, thanks @rick :) 

Using visual studio code at the mo.

  • Like 1

Share this post


Link to post
Share on other sites
4 minutes ago, SamC said:

Using visual studio code at the mo.

I have VSCode as well, but haven't used it since I purchased a license for storm. There are some UML plugins, such as this one available in the marketplace. I haven't used any of these, so I can't vouch for which is best.

Share this post


Link to post
Share on other sites

  • Recently Browsing   0 members

    No registered users viewing this page.