Lots of ways to do, that's for sure.
I use an adapter for each data type (i.e., integer, or foreign key or an array).
I have a validate, filter and escape for each adapter.
There are two reasons I combined these into one package:
1. Many times, the code is the same -- often, a validate method will execute the filter method and then compare the results to the input value. If it's the same, it's valid. As a second example, filtering and "escaping" an integer is the same. Tried to keep it simple and DRY.
2. Wanted to enable chaining. In a single call, one could validate 1) the value is an integer and 2) the value is a foreign key value. I've hooked it up to my "ORM light" so that these functions are automated on forms and during display.
Lots of ways to do it though.