Last active
March 11, 2016 21:43
-
-
Save Deathnerd/22bc289a343f472de825 to your computer and use it in GitHub Desktop.
A rough example of what using annotations to control form validation and rendering could look like
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Must annotate as a Form. This can also hold | |
* metadata about the form later on. In this example, if csrf is | |
* set to true, it enables csrf protection automatically. | |
* | |
* It's also very trivial to implement localization and have it automatically | |
* localize things such as Label texts at render time | |
* | |
* See https://github.com/Deathnerd/php-wtforms/tree/master/src for work I've already done | |
* @Form(csrf=true) | |
*/ | |
class RegistrationForm extends Form | |
{ | |
/** | |
* This property is annotated as a <select> field and will render | |
* with the given choices. If multiple is true, will render as <select multiple> | |
* @Fields\Select(label="Prefix", choices=["Mr.", "Mrs.", "Ms."], multiple=false) | |
*/ | |
public $prefix; | |
/** | |
* This will render according to the __call() method defined on \My\Custom\Widget | |
* @Fields\StringField(label="First Name", widget="\My\Custom\Widget") | |
* This validator will trigger if the input length goes over 25 characters, and will | |
* have the message defined available for echoing to the user | |
* @Validator\Length(max=25, message="Your first name is too long. Got a nickname?") | |
* @Validator\InputRequired(message="What is your first name?") | |
*/ | |
public $first_name; | |
/** | |
* This will default to rendering as an <input type="text"> element | |
* @Fields\StringField(label="Last Name") | |
*/ | |
public $last_name; | |
/** | |
* This will render as an <input type="email"> and may also have some special rules | |
* associated with it | |
* @Fields\HTML5\EmailField(label="Your Email") | |
* @Validator\Email(message="Please use a valid email") | |
*/ | |
public $email; | |
/** | |
* @Validator\InputRequired(message="You must be over 18 to use this site") | |
* @Fields\BooleanField(label="Are you over 18?") | |
*/ | |
public $over_18; | |
/** | |
* @Fields\StringField(label="Username") | |
* @Validator\Length(min=4, max=25, message="Your user name must be between 4 and 25 characters long") | |
*/ | |
public $username; | |
/** | |
* @Fields\PasswordField(label="Password") | |
*/ | |
public $password; | |
/** | |
* @Fields\PasswordField(label="Confirm Password") | |
* @Validator\EqualTo(field="password", message="Passwords must match!") | |
*/ | |
public $confirm_password; | |
/** | |
* @Fields\HTML5\DateTimeField(label="Your Birthday", format="m-d-Y") | |
*/ | |
public $birthday; | |
} | |
// Assuming such method exists, get a user object from the DB | |
$user = DB::getUser(); | |
// First argument is an associative array of data corresponding to | |
// fields on the form object. Options array (supporting more than you see here) | |
// may contain an `obj` element containing an object with data that | |
// can be used as data for fields if it is not found in the first | |
// argument | |
$form = new RegistrationForm($_POST, ["obj" => $user]); | |
// Default method Form::validate will find each Field annotated property | |
// and check against a validator if it was annotated with it. Returns | |
// true if no validation errors occurred, otherwise returns false and | |
// holds validation error messages in the $errors array on the form | |
if ($_POST && $form->validate()) { | |
$form->populate_object($user); | |
$user->save(); | |
header("Location: index.php"); | |
exit; | |
} | |
// Takes the model and converts all properties that are annotated as fields | |
// and associated labels into actual objects that can be manipulated on the | |
// view. Also carries over the errors array | |
$view_form = Form::createViewForm($form); | |
// Render-time overriding of default attributes | |
$view_form->setDefaultLabelAttr(['class' => "form-label"]); | |
// Supporting Callable functions as well | |
$view_form->setDefaultFieldAttr(['class' => "form-control", "data-form-stuff" => function ($field) { | |
return "foobar: " . $field->name; | |
}]); | |
?> | |
<!doctype html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<title>Example Form</title> | |
</head> | |
<body> | |
<ul id="form-errors"> | |
<? foreach ($view_form->errors as $error) { ?> | |
<li><?= $error ?></li> | |
<? } ?> | |
</ul> | |
<form action="<?= $_SERVER['PHP_SELF'] ?>"> | |
<!-- Automatically generated if the Form is set to enable CSRF in the class annotation --> | |
<?= $view_form->csrf_token ?> | |
<!-- Echoing each property generates valid, escaped HTML --> | |
<?= $view_form->prefix->label ?><!--<label class="form-label">Prefix</label>--> | |
<?= $view_form->prefix ?><!--<input type="text" name="prefix" data-form-stuff="foobar">--> | |
<!-- or calling properties as methods allows for HTML attribute overriding at render time --> | |
<?= $view_form->prefix->label(["for" => "prefix_input"]) ?><!--<label for="prefix_input" class="form-label">Prefix</label>--> | |
<?= $view_form->prefix(["id" => "prefix_input"]) ?><!--<input type="text" name="prefix" id="prefix_input" data-form-stuff="foobar">--> | |
<!-- Fields also available through an iterator --> | |
<? foreach ($view_form->fields as $field) { | |
echo $field->label . " " . $field; | |
} ?> | |
<button type="submit">Register!</button> | |
</form> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment