We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

Clear the filled data of form in Phalcon Framework

I am new to phalcon and trying to learn this framework. I have created a simple form. Now, When I fill up the form, I am able to store the data in database. After submitting the form I want to be on the same page. Now the issue is, form is still have the filled data it is not clearing up. I have googled and found the clear() method to clear the form data but it seems that its not working. What to do?

Here is my code //Controller

use Phalcon\Mvc\Controller;
class ProfileController extends Controller
{
    public function indexAction()
    {

        // Add some local CSS resources
        $this->assets->addCss("css/styles.css");
        $this->assets->addCss("css/bootstrap.min.css");

        // And some local JavaScript resources
        $this->assets->addJs("js/jquery.js");
        $this->assets->addJs("js/bootstrap.min.js");

    }

    public function createAction(){

        //create object of model class
        $profile = new Tbl_profile();

        $profile->fname= $this->request->getPost('firstname');
        $profile->lname= $this->request->getPost('lastname');
        $profile->email= $this->request->getPost('email');
        $success=$profile->save();

        if($success) {
            $this->flash->success("Profile created!");
            //redirect to same page.

            $this->dispatcher->forward(['action' => 'index']);
        }else {

        }

    }
}

//views


<html>
<head>
    <title>Title</title>
    <?php $this->assets->outputCss(); ?>
</head>
<body>
        <h4 class="ml-5 mt-2"> Create Profile</h4>
        <?php echo $this->getContent(); ?>
        <?php echo $this->tag->form("profile/create") ?>
        <table class="table">
            <tbody>
                <tr scope="row">
                    <td>First Name</td>
                    <td><?php echo $this->tag->textField("firstname"); ?></td>
                </tr>
                <tr scope="row">
                    <td>Last Name</td>
                    <td><?php echo $this->tag->textField("lastname"); ?></td>
                </tr>
                <tr scope="row">
                    <td>Email</td>
                    <td><?php echo $this->tag->textField("email"); ?></td>
                </tr>
                <tr scope="row">
                    <td></td>
                    <td><?php echo  $this->tag->submitButton("Create");?></td>
                </tr>
            </tbody>

        </table>
</form>
</body>
</html>```


85.5k
edited May '18

its jsut before your $_POST is filled with data otherwise this wont happen.

I use $this->response->redicrect("/home/index/register");//for ex in this cases to clear $_POST fields

otherwise if you F5 after submit, a new record will be created



4.5k
edited Jun '18

Lets give you an example of how I handle forms in my applications nowadays.

Assume we have the following structure

\
|-> app
|   |-> controllers
|   |   |-> TestController.php
|   |-> models
|   |   |-> Test.php
|   |-> forms
|   |   |-> TestForm.php
|   |-> views
|       |-> index.volt
|-> config
|   |-> .....
|-> public
|   |-> index.php

The file TestController.php

<?php
  namespace Controllers;

  use Models\Test;
  use Forms\TestForm;
  use Phalcon\Mvc\Controller;

  class TestController extends Controller
  {
    public function indexAction()
    {
      // Create a new and clean form object
      $form =new TestForm();

      // Check to see if we have a post submit
      if( $this->request->isPost( ))
      {
        // Create a new instance of the test model
        $model =new Test();

        // Bind the data from the $_POST into the form and model alike
        // The models set functions are used to set the files that can be set
        $form->bind( $this->request->getPost(), $model );

        // Validate the input
        if( $form->isValid( ))
        {
          // Save the model
          $result =$model->create();
          if( $result )
          {
            // If we get here then the instance of the test model was saved
            // Set you flash messages and redirect to another page
          }
          else
          {
            // Something went wrong when creating the test model.
            // Use $model->getMessages() to see what went wrong
            // var_dump( $model->getMessages())
          }
        }
        else
        {
          // The form could not be validated for some reason.
          // You can use the $form->getMessages() to see why that is the case
          // var_dump( $form->getMessages())
        }
      }

      // This sets a volt variable form so that you can use it in the index.volt template
      $this->view->setVar( 'form', $form );
    }
  }

The content for the model Test.php

<?php
  namespace Models;

  use Phalcon\Mvc\Model;

  class Test extends Model
  {
    protected $id;
    protected $name;
    protected $surname;

    public function initialize()
    {
      $this->setSource( 'test' );
    }

    // =================
    // = Get Functions =
    // =================
    public function getId()
    {
      return $this->id;
    }

    public function getName()
    {
      return $this->name;
    }

    public function getSurname()
    {
      return $this->surname;
    }

    // =================
    // = Set Functions =
    // =================
    public function setName( $value )
    {
      $this->name =$value;
    }

    public function setSurname( $value )
    {
      $this->surname =$value;
    }
  }

The file TestForm.php

<?php
  namespace Forms;

  use Phalcon\Forms\Form;
  use Phalcon\Forms\Element\Text;
  use Phalcon\Forms\Element\Hidden;
  use Phalcon\Forms\Element\TextArea;
  use Phalcon\Validation\Validator\PresenceOf;

  class TestForm extends Form
  {
    public function initialize( $entity=null, $options=null )
    {
      parent::initialize( $entity, $options );

      // Id
      $this->add(( new Hidden( 'id' )));

      // Csrf
      $this->add(
        ( new Hidden( 'csrf' ))
          ->addValidators([
            new Identical([ 'value' => $this->security->getSessionToken() ]),
            new PresenceOf([ 'message' => 'csrf is required' ]),
          ]));

      // Name
      $this->add(
        ( new Text( 'name' ))
          ->setLabel( 'Name' )
          ->addValidators([
            new PresenceOf([ 'message' => 'Name is required' ]),
          ]));

      // Surname
      $this->add(
        ( new TextArea( 'surname' ))
          ->setLabel( 'Surname' )
          ->addValidators([
            new PresenceOf([ 'message' => 'Surname is required' ]),
          ]));
    }

    public function getValidationErrors( $field )
    {
      $output =[];

      foreach( $this->getMessagesFor( $field ) as $error ) $output[] =$error->getMessage();

      return $output;
    }
  }

The file index.volt

{# new.volt #}
<div id="new" class="panel grid">

  {{ form( 'id':'test-form', 'name':'test-form', 'class': 'grid col-1-2' ) }}

    {{ form.render( "id" ) }}
    {#{{ form.render( "csrf", [ 'value': security.getToken() ]) }}#}

    <div class="form-group row">
      {{ form.label( 'name', [ 'class': 'col-4 col-form-label' ]) }}
      <div class="col-8">
        {{ form.render( "name", [ 'class': 'form-control' ]) }}
        <div class="errors">
          {% for error in form.getValidationErrors( "name" ) %}
            <span>{{ error }}</span>
          {% endfor %}
        </div>
      </div>
    </div>

    <div class="form-group row">
      {{ form.label( 'surname', [ 'class': 'col-4 col-form-label' ]) }}
      <div class="col-8">
        {{ form.render( "surname", [ 'class': 'form-control' ]) }}
        <div class="errors">
          {% for error in form.getValidationErrors( "surname" ) %}
            <span>{{ error }}</span>
          {% endfor %}
        </div>
      </div>
    </div>

    <div class="form-block col right">
      <button type="submit">Create</button>
    </div>

  {{ end_form() }}

</div>

I have disabled the csrf line in the template. Every form you use must have a csrf in it to protected it. If you like I can give you my base form class that I use in all my projects.

This is a just a simple set-up to handle a simple form. All the action is in the controller.

A few things of notice:

  • The names that I give to my input fields match the names I use in the model. Doing it this way can save you a lot of time and huge pieces of code. The bind function in the controller will take care of the assignments in the model as wel as it will set the post data into the form. The set functions in the model are used to populate the fields and if a set function does not exist the public propererty with the same name is set.
  • I would advice you to never use public properties for a class always use protected if you plan on extending the class and the extended class should be able to access the properties or use private to make sure that the set/get functions are used instead.

  • I have added an extra function to the form so that I have an easy way to get the the errors messages for the various elements if they occur. And when they do I print them below the form field in the volt file so the user can see what he did wrong.

  • The form will always be void of data because it will only be populated when you have a post action. See the bind function in the controller.

I hope this is of use to you. If you have any questions regarding the above, feel free to ask them :)

edited Jun '18

A good practice is to redirect the user after a form submission. You're almost doing that, but you're forwarding instead. Forwarding doesn't make a new HTTP request, it just causes the request to be handled by the action you're forwarding to. You need that new HTTP request to clear out the form data both on your side and the browser side.

In createAction(), change this:

$this->dispatcher->forward(['action' => 'index']);

to this:

$this->response->redirect('profile/index');

Maybe I'm missing something, but if I don't need to redirect and I can achieve everything I want in that single request, issuing a HTTP redirect just to reset the form would be opposite of good practice.

The benefit of redirecting after successful form input would be, I guess, to prevent duplicate submissions on refresh?

A good practice is to redirect the user after a form submission. You're almost doing that, but you're forwarding instead. Forwarding doesn't make a new HTTP request, it just causes the request to be handled by the action you're forwarding to. You need that new HTTP request to clear out the form data both on your side and the browser side.

In createAction(), change this:

$this->dispatcher->forward(['action' => 'index']);

to this:

$this->response->redirect('profile/index');