Jump to content
Marek

Form Validation With Valitron Library

Recommended Posts

firstly, note that this my first attempt to make something using php after course in codecadamy.com, also that English is not my first language and I am new to PW

i am new to back end web dev and i want to know how to make some basic websites. so i started to play with PW and tried to make some basic things work (btw PW is great).

First more problematic thing that i found was how to make forms. like contact forms and so on.

here are the problems that i wrote down and tried to find solutions for them:

  • how to make some fields required
  • how to validate some of the inputs if they meet the conditions
  • how to return error message in normal language
  • how to make these errors render like it should in foundation 5 framework ( http://foundation.zurb.com/docs/components/forms.html ) and make it easy
  • how to make some text stay in an input as a value if there was an error somewhere in form. for example if there is a long form and you make mistake in just one field you dont want to make the user type everything again.

since i am php newbie it surprised me there actually are php libraries for form validation ... 

i found valitron 

http://vancelucas.com/blog/valitron-the-simple-validation-library-that-doesnt-suck/

https://github.com/vlucas/valitron

so i thought that it could help. I tried to make it work with PW and here is what i made ... it seems it work

it is form.php template...

<?php 
include("./init.inc");
include("./valitron-master/src/Valitron/Validator.php"); // at first i include Valitron. as you can see i copied what i downloaded from github in templates directory...

// then i make subclass pwValitron to add some features
class PwValitron extends Valitron\Validator {

  // this function will return 'error' if the field cannot be validated. I use put it in class of particular container. it is bassed on foundation 5 error states
  public function error_class($field)
  {
    if ($this->errors($field)) {
      return "error";
    }
    return "";
  }

  // this will render error messages. in nice foundation5 style.
  // $this->errors($field) returns an array of error messages for particular field.
  public function render_errors($field)
  {
    if ($this->errors($field)) {
      return "<small class='error'>" . implode($this->errors($field), "<br>") . "</small>" ;
    }
    return "";
  }

  // this will return a value of particular field only if form caanot be validated because there is some error
  public function value($field)
  {
    if (!empty($this->_errors)) {
      return $this->_fields[$field];
    }
    return "";
  }
}

// this is how we send data for valitron to validate
$v = new PwValitron(array(
  'title' => $sanitizer->text($input->post->title),
  'email' => $sanitizer->email($input->post->email),
  'website' => $sanitizer->url($input->post->website),
  'budget' => $sanitizer->text($input->post->budget), 
  )
);

// then we define rules
$v->rule('required', ['title', 'email', 'budget']);
$v->rule('lengthMin', 'title', 5);
$v->rule('email', 'email');
$v->rule('url', 'website');
$v->rule('numeric', 'budget');
$v->rule('min', 'budget', 500);

if ($input->post->submit) {
  if($v->validate()) { // if form is walidated
      $bodycopy .= "Yay! We're all good!";
      //do something with data here
  } 
}

// now we can write html of whole form 
// note how I use these ... 
// {$v->error_class('title')} - will return 'error' and thus add error class only if there is some error
// {$v->value('title')} - will return value of field what user wrote if there is an error in form and the form was not submitted
// {$v->render_errors('title')} - will render error messages
$out = "
<form method='post' action='./'>
  <div class='row'>
    <div class='medium-8 large-6 medium-centered columns'>
      <div class='row'>
        <div class='large-12 columns {$v->error_class('title')}'>
          <label for='title'>Choose a title</label>
          <small>it must be 5 or more characters in length</small>
          <input type='text' placeholder='title' name='title' id='title' value='{$v->value('title')}'/>
          {$v->render_errors('title')}
        </div>
      </div>

      <div class='row'>
        <div class='large-12 columns {$v->error_class('email')}'>
          <label for='email'>What's your email address?</label>
          <input type='text' placeholder='john@gmail.com' name='email' id='email' value='{$v->value('email')}'/>
          {$v->render_errors('email')}
        </div>
      </div>

      <div class='row'>
        <div class='large-12 columns {$v->error_class('website')}'>
          <label for='website'>Your website</label>
          <input type='text' placeholder='www.example.com' name='website' id='website' value='{$v->value('website')}'/>
          {$v->render_errors('website')}
        </div>
      </div>

      <div class='row'>
        <div class='large-12 columns {$v->error_class('budget')}'>
          <label for='budget'>What's your budget? (USD)</label>
          <input type='text' placeholder='750' name='budget' id='budget' value='{$v->value('budget')}'/>
          {$v->render_errors('budget')}
        </div>
      </div>

      <div class='row'>
        <div class='large-12 columns'>
          <div class='text-right'>
            <input value='submit' type='submit' name='submit' class='button'/>
          </div>
        </div>
      </div> 
    </div>
  </div>
</form>";


$bodycopy .= $out;
include("./main.inc");  

I would like to know what do you think about it. can it be useful for pw community? is there a better way to do it? can it be made as a module? is there anything wrong? what should be added? 

Thanks

Marek

  • Like 3

Share this post


Link to post
Share on other sites

Hello Marek, welcome to the forums.

Very nice, your first post and you are contributing!  :) 

I cannot say much to your validation solution because I don't use forms very often besides a simple contact form. I only know that one can build forms with the PW API and that there is a ProTool for forms.

In the modules directory there is a proof of concept module from Ryan what maybe of interest to inspect.

Share this post


Link to post
Share on other sites

thanks jordanlev and horst,

i have read topic Create simple forms using API earlier, but i found it to be a lot of work for simple forms.

I wanted to be able to write html markup manually. that's why i tried different approach. it also renders error states like you want. It works easily with css frameworks.

for anyone who would like to try it (i would love to see someone to take a look at it) ...

you just need to download Valitron library https://github.com/vlucas/valitron

then put it in templates directory so you can include it with include("./valitron-master/src/Valitron/Validator.php");

and then make new page using template with the code in my first post...

thanks,

Marek

  • Like 1

Share this post


Link to post
Share on other sites

Hi @Marek,

I understand what you are trying to do, and I too like to have full control over my form markup (this is a frustration of mine with almost every framework / CMS / form helper -- they always want to output the form markup in their own way and it is always different than I want it :)

One idea you might try is this module: http://modules.processwire.com/modules/form-template-processor/

...it lets you use piggyback on the PW admin interface for building a template and uses the template as a form (because really a ProcessWire template is a form if you think about it -- it has a bunch of fields). The two limitations on that are:

1) By default, it automatically outputs the form markup.

2) It only has 1 kind of validation possible ("required").

Problem #1 can be solved by not calling the $form->render() function as described in the documentation, but instead outputting the individual form fields yourself. I have a post about this here: https://processwire.com/talk/topic/1894-how-to-render-a-simpelt-inputfield-markup/?p=73109 

You will see that the response to that post was basically "you should not do that because then other processwire modules cannot extend your form"... but that is not a concern in this case because you are not building an admin module, but instead just a custom form for the front-end of your site :)

Problem #2 cannot be solved by using built-in ProcessWire functionality (because that kind of validation does not seem to exist in processwire), so you should just go ahead and include your valitron library to handle that.

I hope that helps!

Share this post


Link to post
Share on other sites

Thanks for this Marek, this is one of the few areas where I feel "frameworks" have a slight edge over PW. 

A nice validation library looks good.

  • Like 1

Share this post


Link to post
Share on other sites

I've rewritten all the forms in my current project from pw's internal form handling to manual. It's so easy to just write the markup yourself – a bit repetitive, but still easier – and valitron is a great library. The syntax is super readable and you can define own rules. I'll put some examples after this. The function duplication is, that I can use the functions without the library, too.
 

use Valitron\Validator as V;

//------------------------------------------------------------------------------
//  hasContent
//------------------------------------------------------------------------------

function textHasContent($text){
	$content = str_replace(array("\n", "\r", "\t", " ", "\o", "\xOB"), '', strip_tags($text));
	return strlen($content) ? true : false;
}

function ruleHasContent($field, $value){
	return textHasContent($value);
}

V::addRule('hasContent', "ruleHasContent", 'No valid Content entered');

//------------------------------------------------------------------------------
//  isUser
//------------------------------------------------------------------------------
 
function isUser($id){
$id = (int)$id;
$u = wire('users')->get("id=$id");
if($u->id) return true;
else return false;
}
 
function ruleIsUser($field, $value){
return isUser($value);
}
 
V::addRule('isUser', "ruleIsUser", 'Invalid User given.');
  • Like 2

Share this post


Link to post
Share on other sites

You can always use client side validation, but server side is a must. You can't rely on validated data being sent to your server, as everyone how can read your form can potentially send whichever data he wants to your server. Even if it's not a security risk per se, would you want users to be able to save a 10 star rating on the server side, when there should be a maximum of 5 stars possible. 

  • Like 2

Share this post


Link to post
Share on other sites

Why not to use js client side for form validation ?

What happens when the user disblaes JavaScript ?, I do it on several site (only when my evil side wakes up). Never Trust user input and frontend security mechanism. That being said truly this is where frameworks have an advantage however you can use Valitron and PW Form together, I used Valitron alot and its the one Validation lib that doesn't suck after Yii and Zend 2, all you need to do is create the rules and validate the rules against the values from the form and all is good to go. 

  • Like 3

Share this post


Link to post
Share on other sites

Just to add to the client-side/server-side thing: Since my first PW site, I've created a simple module (only for contact forms) that makes use of SwiftMailer (I should probably be using wireMail, but I haven't even looked at that yet) and Laravel's Validation package. The form itself works with JavaScript, but validation occurs on the server-side. All well and good, that's good practice. But I specifically ensure that the form doesn't work when JS is not available.

Just my 2cents on the matter.

:-)

  • Like 2

Share this post


Link to post
Share on other sites

Same here i'm facing the same issue and its quite limiting am going to extend the Form and add a tight coupling with Valitron and override processinputfields not really a fan of PW's Form Handling it has only required.

Oops after re-evaluation not worth it this is the best way to go about it

I've rewritten all the forms in my current project from pw's internal form handling to manual.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...