$30 off During Our Annual Pro Sale. View Details »

Forms make the web

Kevin Dees
April 20, 2017

Forms make the web

Web design and PHP OOP best practices for web forms.

Kevin Dees

April 20, 2017
Tweet

More Decks by Kevin Dees

Other Decks in Design

Transcript

  1. Forms make the web
    "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  2. Forms
    Best Practices
    Twitter @kevindees
    "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  3. Design Details
    "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  4. Forms must be fast.
    "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  5. "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  6. "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  7. Forms must be clear
    "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  8. "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  9. "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  10. ☠ Placeholder Text
    "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  11. "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  12. "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  13. "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  14. Forms must be mobile.
    "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  15. "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  16. Think Differently !
    "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  17. Code Considerations
    "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  18. 1. Use UTF-8
    2. CSRF
    3. POST as array data
    4. REST Hacking
    5. Data Injection Order
    6. Feedback
    "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  19. UTF-8? Really !
    "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide



  20. CREATE TABLE `users` (
    `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
    `first` varchar(60) DEFAULT '',
    `last` varchar(60) DEFAULT '',
    `email` varchar(60) DEFAULT '',
    PRIMARY KEY (`id`)
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
    "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  21. CSRF
    "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  22. "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  23. session_start();
    // check for submit
    if( !empty($_POST['_csrf']) && !empty($_SESSION['_csrf']) ) {
    if( $_POST['_csrf'] != $_SESSION['_csrf']){
    die('CSRF Block!');
    }
    }
    // new key
    $form_access_key = uniqid('_csrf_');
    $_SESSION['_csrf'] = $form_access_key;
    ?>



    "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  24. POST as array data
    "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide



  25. First Name
    Last Name
    Email


    "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  26. "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  27. REST Hacking
    "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide




  28. ....
    "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  29. function rest_method($actual = false) {
    if($actual) { return $_SERVER['REQUEST_METHOD']; }
    return ! empty($_POST['_method']) ? strtoupper($_POST['_method']) : $_SERVER['REQUEST_METHOD'];
    }
    "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  30. $user_controller = new \App\UserController;
    $rest_method = rest_method();
    if( method_exists($user_controller, $rest_method) ) {
    $user_controller->{$rest_method}();
    }
    "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  31. Data Injection Order
    "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  32. 1. Old Data If Errors
    2. Model Data If Present
    "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  33. Email
    name="user[email]"
    value=""
    />

    "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  34. function load_value( $name, $model = false ) {
    if( !empty($_SESSION['old'][$name]) ) {
    return $_SESSION['old'][$name];
    }
    if( $model instanceof Model) {
    return $model->{$name};
    }
    return '';
    }
    "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  35. if( $errors = has_form_errors() ) {
    $_SESSION['old'] = $_POST['user'];
    }
    "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  36. Feedback
    "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  37. Words
    1. Verbose
    2. Vague
    "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  38. Your email address and password are wrong.
    or
    Your login is not working out.
    "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  39. Placement
    1. Inline with field
    2. Flash on top
    3. Alert by overlay
    "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  40. "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  41. "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  42. "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  43. Emotional
    1. Life
    2. Language
    "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  44. "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  45. "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  46. function has_form_errors() {
    $errors = [];
    if( is_not_email( $_POST['user']['email'] ) ) {
    $errors['user']['email'] = 'Opps! Check that email for us.'
    }
    if( empty($errors) ) {
    return false;
    }
    return $errors;
    }
    "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  47. Email
    name="user[email]"
    value=""
    />




    "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  48. Add emotion little effort
    "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  49. "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  50. Email
    name="user[email]"
    value=""
    />
    class=""
    style="display: inline-block;"
    >



    "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide








  51. "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  52. "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  53. Code for humans !
    "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  54. ... What about coders? !
    "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  55. namespace App;
    class Form
    {
    public $model;
    public $method;
    public $action;
    public $group;
    public $errors;
    function __construct( $model, $method, $action, $group, $errors )
    {
    $this->model = $model;
    $this->method = $method;
    $this->action = $action;
    $this->group = $group;
    $this->errors = $errors;
    }
    }
    "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  56. class Form
    {
    ....
    function open() {
    $csrf = $_SESSION['_csrf'];
    $str = "action}\" method=\"POST\" accept-charset=\"utf-8\">";
    $str .= "";
    $str .= "method\">";
    return $str;
    }
    function close() {
    return '';
    }
    function text($name) {
    return new \App\Field($name, $this);
    }
    }
    "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  57. echo $form->text('email')->label('Email Address');
    "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  58. namespace App;
    class Field
    {
    public $form;
    public $name;
    public $value;
    public $label;
    function __construct($name, $form)
    {
    $this->name = $name;
    $this->form = $form;
    $this->value = load_value($name, $this->form->model);
    }
    }
    "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  59. class Field
    {
    ....
    function label($label) {
    $this->label = $label;
    return $this;
    }
    function __toString()
    {
    $group = $this->form->group;
    $name = $this->name;
    $errors = $this->form->errors;
    ob_start();
    // echo HTML
    return ob_get_clean();
    }
    }
    "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  60. // echo HTML
    ?>
    label; ?>
    name=""
    value="value); ?>"
    />
    class=""
    style="display: inline-block;"
    >



    "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  61. $form = new \App\Form($model, 'POST', 'user.php', 'user', $errors);
    echo $form->open();
    echo $form->text('email')->label('Email Address');
    echo $form->close();
    "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide

  62. ! Make YOUR forms
    amazing !
    "Forms: Best Practices" by Kevin Dees // TypeRocket // Robojuice

    View Slide