2

With Codeigniter 3 it was possible to use "trim" as a validation rule. It seems it is no more possible with Codeigniter 4. Then how can I trim input values before validating, in case the user left whitespaces at the beginning or the end of the input?

$validation->setRule('username', 'Username', 'trim|required|min_length[3]');

I thought using a custom rule but these functions can only return true or false. They can't modify the input. The other solution is using the php trim function but I can't see where to use it. Thanks for your help!

micthi
  • 21
  • 3

3 Answers3

2

I'm guessing you're validating the post request directly. For what you need I would validate your modified array instead of the post request directly.

One of the great things in codeigniter 4 validation is that your can actually validate anything. Unlike codeigniter 3 where you could only use it to validate the $_POST data.

Let's say you have two fields, username and password and want to trim the username.

In you controller that would get the post date you would do the following.

$validation =  \Config\Services::validation();
$validation->setRules([
   'username' => 'required',
   'password' => 'required|min_length[10]'
]);

$data = $this->request->getPost();
$data['username'] = trim($data['username']);

if (!$validation->run($data)) {
    // handle validation errors
}

If you're doing the validation in the model, I'm not sure if the validation is run before the callbacks but its worth a try. So You would define a function in your beforeInsert callback and handle the trim there.

More about callbacks here:

https://codeigniter.com/user_guide/models/model.html#specifying-callbacks-to-run

If that does not work you can even remove the username from your validation rules in your model and then in a beforeFind and beforeUpdate function validate the username yourself and trim it.

marcogmonteiro
  • 2,061
  • 1
  • 17
  • 26
  • Thank you for your answer. I decided to use a javascript function to automatically trim input values on change. – micthi Apr 09 '21 at 16:50
  • @micthi would advise against that, front end validation should not be a substitute to back end validation. They should complement each other. – marcogmonteiro Apr 09 '21 at 21:02
  • Javascript just trims values but on submit, validation is run by Codeigniter. – micthi Apr 10 '21 at 10:00
1

I had the exact same question. For me, it makes sense to trim most POST variables before any validation. Even some of the common validation rules are best executed with already-trimmed values.

As @micthi stated, CodeIgniter 3 offered an easy way to trim just before validation. CodeIgniter 4 makes it much less straightforward. A custom validation rule can't modify data for us, and the model event methods such as beforeInsert and beforeUpdate also don't help us in running callbacks as they all execute after validation.

Below is a CodeIgniter 4 solution that works to allow trimming of POST variables before any validation. In brief, a filter is created and then configured to run before any controller code is executed for any POST method. It loops thru the $request object to trim the POST variables and then allows the newly-trimmed version if the $request to proceed to the controller.

Create: app/Filters/TrimFilter.php

namespace App\Filters;

use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\Filters\FilterInterface;

class TrimFilter implements FilterInterface
{
    public function before(RequestInterface $request, $arguments = null) {
        
        $trimmed_post = [];
        
        foreach($request->getPost() as $var => $val) {
            $trimmed_post[$var] = trim($val); 
        }
        
        $request->setGlobal('post', $trimmed_post);
    }                
}

Modify: app/Config/Filters.php

// Add to the use statements
use App\Filters\TrimFilter;

// Add to the $aliases array
public $aliases = [
    'trim' => TrimFilter::class
];

// Add to the $methods array
public $methods = [
    'post' => ['trim']
];

ANOTHER OPTION: Instead of using the filter approach, you could instead perform the trimming loop within the BaseController.php file. In this case, remember to use $this-> to reference the request while within the BaseController.

MonsoonJoe
  • 13
  • 3
0

I will suggest a change to friend's answer @monsoonjoe

public function before(RequestInterface $request, $arguments = null)
{
    $trimmed_post = filter_var(request()->getPost(), \FILTER_CALLBACK, ['options' => 'trim']);
    request()->setGlobal('post', $trimmed_post);
}