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 :)