Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Filtering for Rules #35

Closed
alganet opened this issue Oct 6, 2011 · 15 comments
Closed

Filtering for Rules #35

alganet opened this issue Oct 6, 2011 · 15 comments

Comments

@alganet
Copy link
Member

alganet commented Oct 6, 2011

This is a major feature that will require a lot of work.

I've added filtering support for the Int Rule to make some tests.

https://github.com/Respect/Validation/blob/develop/library/Respect/Validation/Filterable.php
https://github.com/Respect/Validation/blob/develop/library/Respect/Validation/Rules/AbstractComposite.php
https://github.com/Respect/Validation/blob/develop/library/Respect/Validation/Rules/Int.php

Filtering on rules will allow users to not just validate data, but filter it.

<?php

$myPureInt = v::int()->filter("12 pigs");
var_dump($myPureInt); //int(12)

For this, a lot of discussion may happen on how each current rule will filter data and how future rules will filter data. It is possible also to create filter-only rules that doesn't validate nothing, but filter data.

Filtering and validation must be called in separate steps for now:

<?php

$validator = v::string()->noWhitespace()->digits()->length(1,20);
$notDirtyAnymore = $validation->filter($someDirtyShit);
$isValid = $validation->validate($notDirtyAnymore);

However, it is desirable (yet-no-so-simple-to-do) to have a build in routine that allows filtering and validating to be chained:

<?php
v::int()->filter()->validate($input); //filter before
v::int()->validate()->filter($input); //filter after

I really need some feedback on this.

@ramon-to
Copy link

It's a nice feature!

But we already have a bug =P

<?php
  $myPureInt = v::int()->filter("OnlyWords"); // int(0)
  v::int()->validate($myPureInt); // true

I think will be better if we work in the other features, and release a stable version before we do this feature.

@alganet
Copy link
Member Author

alganet commented Oct 13, 2011

Not sure if its a bug yet, its behavior is currently not defined. What behavior do you expect with the sample you provided?

@ramon-to
Copy link

I expect the filter returns false:

<?php
  $myPureInt = v::int()->filter("OnlyWords"); // bool false
  v::int()->validate($myPureInt); // false

If the filter never returns false, what is the proposal of the validate function?

Maybe I not understand right the idea of the filter... =/

@alganet
Copy link
Member Author

alganet commented Oct 13, 2011

Perhaps the int was a bad idea for a first prototype.

I believe in filters as sanitizers. The validators are there just to tell if the data is right, but they don't alter anything. Filters are there to actively make the data right.

For example, The NoWhitespace as a validator returns false when it finds white space, NoWhitespace as a filter would probably strip out any whitespace it founds. Anything like that.

@ramon-to
Copy link

I get the concept, but if the filter can't make the data right?

<?php
$dirty = "Foo Bar"; 
$validator = v::string()->noWhitespace()->length(7,10);
$validator->filter($dirty);

And if the filter will make the data right, why we should validade?

<?php
   $myPureInt = v::int()->filter("12 pigs"); // int(12)
   (bool)$myPureInt; // true

   /* Invalid data  */

   $myPureInt = v::int()->filter("One pig"); // bool false
   (bool)$myPureInt; // false

@alganet
Copy link
Member Author

alganet commented Oct 13, 2011

Filtering is more like a "Fix whatever you can for me, I want clean data". Sometimes its impossible to make data right, thats why we should always validate it.

Perhaps some filters should always return null when they can't make things right, so the validator can catch those edge cases.

In some cases the filtering is before validation, in some cases its after validation. "12 " (twelve plus whitespace) is a valid integer number for the Int Rule, but isnt really a good practice to store this on a database with that trailing space. In this case, I would probably apply a post-validation filter before using that data.

Maybe we could split this feature into filters and sanitizers. Sanitizers would clean up data and filters would make them null if they don't follow the rules:

<?php
 $dirty = v::digits()->sanitize("12a34"); // string(4) "1234"
  v::digits()->validate($dirty); // true

 $dirty = v::digits()->filter("12a34"); // NULL
  v::digits()->validate($dirty); // false

@ramon-to
Copy link

Hm'...

I like the idea, but I guess it's better if filter work this way:

<?php
 $dirty = v::digits()->sanitize("12a34"); // string(4) "1234"
  v::digits()->validate($dirty); // true

  $dirty = v::digits()->filter("12a34"); // string(4) "1234"
  v::digits()->validate($dirty); // true


 $dirty = v::digits()->sanitize("foo"); // string(1) "0" 
  v::digits()->validate($dirty); // true

  $dirty = v::digits()->filter("foo"); // NULL
  v::digits()->validate($dirty); // false

The diference between filter and sanitize is:

  • Filter will always return a "valid" data
  • Sanitizers filter and validate the data

@alganet
Copy link
Member Author

alganet commented Oct 13, 2011

Didn't quite get your idea. Is the samples you provided right?

@ramon-to
Copy link

Sorry, I fix the sample...

@alganet
Copy link
Member Author

alganet commented Oct 13, 2011

The second sample could be:

<?php
 $dirty = v::digits()->sanitize("foo"); // string(0) "" 
  v::digits()->validate($dirty); // true

  $dirty = v::digits()->filter("foo"); // NULL
  v::digits()->validate($dirty); // false

The Digits rule accept an empty string as input.

The idea seems nice. Sanitizers could be implemented directly in AbstractRule. They're after all a standardized call to both filter() and validate().

We could raise up some real use cases for these guys, just to validate the concept a little further.

@ramon-to
Copy link

Prevent SQL Injection

Let's assume we have a product page, and we get a id parameter:

product.php?id=10

And some kid wanna hack our site:

product.php?id=10 some sql injection exploit --

Let's filter the parameter...

<?php
  $dirtyId = $_GET["id"];  // "10 some sql injection exploit --"
  $clearId = v::int()->filter($dirtyId); // int(10)
  if($clearId){
   /* Make a  Select in DB like:*/
   $sql = "SELECT title, price, photo FROM products WHERE id="+$clearId;
     /* Rest of the code */
   }else{
      echo "FBI will get you!";
  }

Help with parsing XML files

Get only the date of an node in a xml file:

<?xml version="1.0" encoding="utf-8" ?>
<post>
   <date>Posted in 13/10/2011</date>
   <title>FooBaar </title>
</post>
<?php
   $xml = simplexml_load_file('post.xml');
   $dirtyDate = $xml->date; // Posted in 13/10/2011
   $clearDate = v::date('d-m-Y')->sanitize($dirtyDate); // 13/10/2011

@alganet
Copy link
Member Author

alganet commented Oct 17, 2011

That seems enough for starting a better implementation. Gonna work on it soon!

@alganet
Copy link
Member Author

alganet commented Oct 18, 2011

Improved the current prototype here: 41286de

@alganet
Copy link
Member Author

alganet commented Mar 23, 2012

Me and @augustohp decided to drop this for now. Seems that no one used or needed. If you want this, please re-open the issue!

@septianw
Copy link

This is good feature, currently what i do is "filter it first and validate it." this feature will make my life simpler.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants