Send get and post requests (Form) in CodeIgniter 4

Video thumbnail

We are going to learn how to make the typical submission of data from an HTML form with some HTML fields defined in it in CodeIgniter 4, be processed by a particular controller or function defined within the controller; for this we are going to need a couple of functions, an HTML view and a model that we already explained previously, in addition to having the connection to the database and the generated table; all these are concepts that we have already seen before and therefore you can visit the corresponding articles.

Remembering...

A very important point if we remember how we worked in Codeigniter 3, that is, the previous version of the framework, is that you have more flexibility when defining this type of process; that is, we could perfectly define the entire process of painting the view/form and processing it in a single function, but this in CodeIgniter 4 is not recommended and it is not the approach we should follow here; and this is a very important point, CodeIgniter 4 takes the organization of other frameworks such as Laravel to define resource-type controllers that we will address in another entry, but in a few words it allows us to create all CRUD routes.

Components needed to work with forms in CodeIgniter 4

  • A view that will only be consumed via get, a get type request and is the one that will be in charge of painting our view, specifically our form
  • Another view that will be in charge of processing the request of the form that will go via Post, which has been the type of recommended method to create resources (and CodeIgniter also uses this type of request to update records, but we will see this in another post.) .
  • An HTML view, which has been our form.
  • A model, which is simply the entity with which we are going to work to create a record based on the information or data received by the form.

Build the app

In this block we are going to go step by step building the application that we indicated previously.

Defining the Model

Let's work with the movies model:

<?php namespace App\Models;
 
use CodeIgniter\Model;
 
class PersonModel extends Model {
    protected $table = 'people';
    protected $primaryKey = 'id';
    protected $allowedFields = ['name', 'surname','age','description'];
}

Define controller

Now, we are going to create a controller that we are going to call as Person.php:

class Person extends Controller
{
}

Remember that the controller is the layer that is in charge of communicating the view with the model, and more than this, it is the one that has the logic and organization to carry out each of the processes indicated above, painting a view and processing a form.

Define CRUD resource routes

Como vamos a aprovechar este formulario para crear un completo CRUD en posteriores entradas, vamos a aprovechar a definir una ruta de tipo recurso, como la explicamos anteriormente:

$routes->resource('person');

With this, we now have to define in our controller some functions with corresponding names and parameters that are going to be in charge of carrying out our CRUD, although for now we are interested in simply creating a record; for that.

Function to paint a form get

The first function that we are going to see would be to paint a form, therefore we do not have to do anything else, remember that we are creating a route of resource type and therefore we have to create a function called new, which is what allows us to consumed via a get request and will simply return a view:

    public function new()
    {
        return view('person/new');
    }

Function to create a Post record

Now the most interesting function, the one that can only be consumed via a Post request and therefore is the one that receives the data from our form that travels based on a Post request:

    public function create()
    {
 
        $person = new PersonModel();
 
        $person->insert(
            [
                'name' => $this->request->getPost('name'),
                'surname' => $this->request->getPost('surname'),
                'age' => $this->request->getPost('age'),
                'description' => $this->request->getPost('description'),
            ]
        );
    }

The request to get the data

Let's remember that regardless of what you use, there is always something called request, which is the request of our user, here the data of our user travels, the data of the previous form, therefore, it is the mechanism that we have to use to obtain the data; in C4, to obtain data that goes via Post would be as follows:

this->request->getPost('key')

Where a key matches the name of the field; so to get each of the above form fields; for example, name:

$this->request->getPost('name')

And now we simply want to insert a record: for that we have to create an instance of our model, which in this case would be of some people, and the function called insert, which is the one that is in charge of inserting a record; It's that simple, and with this we have the complete process.

View for the form

Let's create a simple form in the app/Views folder of our application like the following and call it new.php to match the function name:

<!DOCTYPE html>
<html lang="en">
 
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Crear Persona</title>
</head>
 
<body>
 
    <h1>Crear Persona</h1>
 
    <form action="<?= base_url() ?>/person" method="post">
 
        <label for="name">Nombre</label>
        <input type="text" name="name" id="name" value="Andres">
 
        <br>
 
        <label for="surname">Apellido</label>
        <input type="text" name="surname" id="surname" value="Cruz">
 
        <br>
 
        <label for="age">Edad</label>
        <input type="text" name="age" id="age" value="29">
 
        <br>
 
        <label for="description">Descripción</label>
 
        <textarea name="description" id="description" cols="30" rows="10">Desarrollador</textarea>
 
        <br>
 
        <input type="submit" value="Enviar">
 
    </form>
 
</body>
 
</html>

Return to form view

Now at this point, if you try to create a record from: http://codeigniter4.test/person/new or the domain you have configured, you will see that at the end a blank screen remains, and this is because the create function returns nothing; here you could perfectly do something like the following to paint a view from create:

public function create()
    {
 
*** Resto del código
 
        return view('person/new');
    }

But in this way we are basically doing the same job as the new function and therefore we know that replicating code so that it stays the same is bad in any programming language and besides that, if at this point we try to refresh the page we will see an inside alert like the following:

white windows

And this is because we are sending or again a Post type request; and it doesn't look good; therefore, what we are going to do is simply return to the previous function, for this we can use the routes and we have a function called back that allows us to return to the previous function:

return redirect()->back(); 

It is as if you press back or go back from your browser

And with this now it works in a much better way.

Extra: Remember previous values with the old function in CodeIgniter 4

You are probably interested that C4 remembers the previous values in your form; for that, we can use a function called old that receives two parameters:

  1. Field Name
  2. Default value (which is the one we are going to establish when there is no previous value, for example, when we enter the new page for the first time.)

Now, so that the data can be taken from the redirection that we are doing, we have to use the function called withInput when doing the redirection:

return redirect()->back()->withInput();

And for the form fields, we have to define the function in question; for example:

<?=old('name',"")?>

Form validation rules

Performing validations on the data received by the user through a form is essential to guarantee the integrity and quality of the requested data; this is why form validations are used, indicating which fields are mandatory and what structure it must have; validations are particularly important in situations that depend on this data, since errors can be costly or even dangerous, since unvalidated forms can be used to perform SQL injection processes, among other types of attacks.

Validating forms in CodeIgniter is very easy; we just have to know what we want to validate; what are the rules that we are going to incorporate; for example, if we have the following form:

	<div class="form-group">
		<label>Nombre</label>
		<input type="text" value="<?php echo $name ?>" class="form-control" placeholder="Nombre" name="name" required>
		<?php echo form_error('name', '<div class="text-danger">', '</div>') ?>
	</div>

	<div class="form-group has-feedback">
		<label>Apellido</label>
		<input type="text" value="<?php echo $surname ?>" class="form-control" placeholder="Apellido" name="surname" required>
		<?php echo form_error('surname', '<div class="text-danger">', '</div>') ?>
	</div>
	<div class="form-group has-feedback">
		<label>Teléfono</label>
		<input type="text" value="<?php echo $phone1 ?>" class="form-control" placeholder="Teléfono" name="phone1" required>
		<?php echo form_error('phone1', '<div class="text-danger">', '</div>') ?>
	</div>
	<div class="form-group has-feedback">
		<label>Teléfono 2</label>
		<input type="text" value="<?php echo $phone2 ?>" class="form-control" placeholder="Teléfono 2" name="phone2" required>
		<?php echo form_error('phone2', '<div class="text-danger">', '</div>') ?>
	</div>

We are interested in all the fields being present except for phone 2 which is completely optional, we are interested in placing various maximum and minimum lengths in our form and we are also interested in some fields such as age only allowing integer data types; We can do all this and much more in CodeIgniter through form validation; among the most important we have:

ReglaParámetrosDescripciónEjemplo
requiredNoReturns true or false if the element is empty. 
min_lengthYesReturns FALSE if the form element has a shorter length than the one defined in the parameter.min_length[3]
max_lengthYesReturns FALSE if the form element has a length longer than the one defined in the parameter.max_length[12]
exact_lengthYesReturns FALSE if the form element has a length other than the length defined in the parameter.exact_length[8]
valid_emailNoReturns FALSE if the form element does not have a valid email. 
numericNoReturns FALSE if the form element contains something other than a number. 
integerNoReturns FALSE if the form element is not an integer 

As you can see, we have validation rules for many cases, data types, emails, decimals, required, and maximum and minimum amounts for String lengths; these are the ones I consider most important, but you can have all the validation rules from the official documentation.

So, to place validation rules in the previous form we must do the following:

$this->form_validation->set_rules('name', 'Nombre', 'max_length[100]|required');
$this->form_validation->set_rules('surname', 'Apellido', 'max_length[100]|required');
$this->form_validation->set_rules('phone1', 'Número de celular', 'min_length[9]|max_length[9]|required');
$this->form_validation->set_rules('phone2', 'Número de celular', 'min_length[9]|max_length[9]);

As you can see, we added multiple validation rules separated by pipes (|); in addition to this, note that phone 2 does not have the "required" validation type applied to it because it is completely optional; then when sending the POST (it can also be GET, just change POST to GET):

if ($this->form_validation->run()) {

	// datos a guardar
	$save = array(
		'name' => $this->input->post("name"),
		'surname' => $this->input->post("surname")
	);
}

Here simply when we detect that the form is a Post and it is valid, we simply compose an array to later save it in the database; but you can do what you want with the validated data.

Custom rules for the form in CodeIgniter

You may want to create your own custom validation rules for CodeIgniter; for that you simply have to create a function in your controller class and evaluate its condition; the important thing is that it returns either true or false:

function validate_passwd($password) {

	// At least one digit required
	// $regex = '(?=.*\d)';
	// At least one lower case letter required
	$regex = '(?=.*[a-z])';
	// At least one upper case letter required
	// $regex .= '(?=.*[A-Z])';
	// No space, tab, or other whitespace chars allowed
	$regex .= '(?!.*\s)';
	// No backslash, apostrophe or quote chars are allowed
	$regex .= '(?!.*[\\\\\'"])';

	if (preg_match('/^' . $regex . '.*$/', $password)) {
		return TRUE;
	}

	return FALSE;
}

And then you add it to your validation rules by placing the function created above with the callback_ prefix:

$crud->set_rules('passwd', 'Contraseña', 'min_length[8]|required|max_length[12]|callback_validate_passwd_admin');

Then go to your language file located at application\language\english\form_validation_lang.php and set the error message for your new rule:

$lang['validate_same_passwd'] = "La contraseña debe ser igual a la almacenada en el sistema.";

Here we are taking as an example that you are using English as the default language in your project, but if you change the language you simply change the folder.

Custom messages for validation rules:

In the previous file we can define the messages in case we want to customize them; but we can also do it from the controller:

$this->form_validation->set_message('min_length', '{field} must have at least {param} characters.');

Show form errors

Finally, to show the errors of the form we can use:

<?php echo form_error(name, '<div class="text-danger">', '</div>') ?>

This element is usually placed in the form view, next to the form element to which we apply the validation rule, which for this example is one called name.

Show all errors in a form

Many times it is useful to show the errors together, all the errors of the form from a single place from a single function, for that there is the following function:

validation_errors()

You can also define the element that will contain said error, which by default is simply a line of text, you can place it in a Bootstrap alert for example:

validation_errors('<div class="alert alert-danger" role="alert">', '</div>')

Complete example of a form element in Bootstrap 5:

<div class="form-group">
    <?php
    echo form_label('Título', 'name');
    ?>
    <?php
    $text_input = array(
        'name' => 'name',
        'minlength' => 10,
        'maxlength' => 100,
        'required' => 'required',
        'id' => 'name',
        'value' => $name,
        'class' => 'form-control input-lg',
    );

    echo form_input($text_input);
    ?>
    <?php echo form_error('name', '<div class="text-danger">', '</div>') ?>
</div>

Custom validations in CodeIgniter 4

Custom validations in CodeIgniter 4
Video thumbnail

Validations in CodeIgniter 4 are a fundamental point in any application and CodeIgniter 4 is no exception; to be able to validate our data in order to be sure that it is valid and secure; they are processes that we have to carry out in our applications; but surely there are validations that are a little more specific for your business and therefore you cannot use the generic ones that the framework offers us; in those cases, we have to create one ourselves; in CodeIgniter 4 we can do it easily and with them we avoid dirtying the controller too much, which is where we usually place them; we have to go to the file of:

config/Validation.php
En ella, veremos definidas una serie de clases:
public $ruleSets = [
\CodeIgniter\Validation\Rules::class,
\CodeIgniter\Validation\FormatRules::class,
\CodeIgniter\Validation\FileRules::class,
\CodeIgniter\Validation\CreditCardRules::class,
];

Which you can review and you will see that they are classes with functions, the names of the functions correspond to the validations that we can use and they receive an argument, which as you can suppose is the validation parameter; The framework already takes care of all this mapping for us; in my example (which is part of my complete course on CodeIgniter 4 that you can take on this platform) we are going to create a file inside:

app/validator/UserRules

We are going to create an extra folder that we call /app/Validation (it can have any name and inside it a file called UserRules (or whatever name you prefer):

<?php
namespace App\Validation;
use App\Models\UserModel;
class UserRules
{
}

And within this file and classes, we create our validation functions to which we apply our validations; logically, they have to return a boolean, true if validation passes and false otherwise:

    public function provider(string $userId): bool
    {
        return $this->checkType($userId, "provider");
    }
    public function customer(string $userId): bool
    {
        return $this->checkType($userId, "customer");
    }

To use them, just:

        $res = $this->validate([
            'user_id' => 'required|customer'
        ]);

Extra, create validations with parameter passing

We can also create more general validations in which we can pass one or more parameters by defining the validation:

$res = $this->validate([
            'user_id' => 'required|checkType[customer]',
        ]);

And in our class:

   public function checkType($userId, $type)
    {
        $userModel = new UserModel();
        $user = $userModel->asObject()->where("type", $type)->find($userId);
        return $user != null;
    }

Validations and print errors of forms in CodeIgniter 4 with Bootstrap 5 style

Video thumbnail

Validations are a fundamental mechanism that we use to show errors that occur in a form, therefore, in Codeigniter 4 we can quickly create validation rules from within the framework, in a configuration file of the same and configure it anywhere from our drivers.

We are going to see how we can use the validations on our form, for this we can basically do it in two ways, the first would be on the function that is in charge of receiving the data that we created previously, for example, the create function, to create a new element , in this case, a person:

    public function create(){
        $movie = new MovieModel();
        if($this->validate('movies')){
            $id = $movie->insert([
                'title' =>$this->request->getPost('title'),
                'description' =>$this->request->getPost('description'),
            ]);
            return redirect()->to("/movie/$id/edit")->with('message', 'Película creada con éxito.');
        }
        return redirect()->back()->withInput();
    }

Validation files

CodeIgniter from version 4 allows creating validation files, in which it would simply be an array, which we have to implement with the validations and we simply place the validations that we want to use; the file is located in app/Config/Validation and you simply have to define your validation rules:

    public $movies =[
        'title' => 'required|min_length[3]|max_length[255]',
        'description' => 'min_length[3]|max_length[5000]'
    ];

Basically very similar to the previous example, but in this way it is much more organized, more extensible and therefore more usable.

The point here is that you place as the key of the previous array the name of the field followed by the rules that you can see what types of rules you can place in the official documentation.

So now we have a schema that we can use to work with validations.

Show validation errors

We have to show the validation errors in the new view, for that we have to load a validation service from this file that we then pass to the view to show them:

  public function new()
    {
        $validation =  \Config\Services::validation();
        return view('person/new',['validation' => $validation]);
    }

And in the view we receive a collection, that is, a list of errors that we can print as follows:

<?= $validation->listErrors() ?>

To give a custom style for errors; You can go to the Config/Validation.php file and in the templates variable, indicate the reference to the file that must be used as a template to print the errors; for example:

    public $templates = [
        //'list'   => 'CodeIgniter\Validation\Views\list',
        'list'   => 'App\Views\Validations\list_bootstrap',
        'single' => 'CodeIgniter\Validation\Views\single',
    ];

Create template to display errors with Bootstrap

And we create such a file, for example, with the Bootstrap style:

<?php if (! empty($errors)) : ?>
    <div class="errors" role="alert">      
        <?php foreach ($errors as $error) : ?>
            <div class="alert alert-danger"><?= esc($error) ?></div>
        <?php endforeach ?>
    </div>
<?php endif ?>

But, as you can see, you can customize it 100% and include, for example, your style that you have for other CSS kits like Tailwind.css

Conclusions

So now you know how you can use custom validations and a bit more than that, pass parameters to custom validations.

I agree to receive announcements of interest about this Blog.

We are going to show the process to send forms in CodeIgniter 4, from the creation of routes, controller, functions and of course, the process of the request or request of our user.

| 👤 Andrés Cruz

🇪🇸 En español