librelist archives

« back to archive

Dynamic clean methods for a form

Dynamic clean methods for a form

From:
Loic d'Anterroches
Date:
2012-03-19 @ 20:15
Hello,

here is a patch I applied today and which is available on master:

$ git diff
diff --git a/src/photon/form.php b/src/photon/form.php
index 82c03f5..ed38dcb 100644
--- a/src/photon/form.php
+++ b/src/photon/form.php
@@ -143,8 +143,8 @@ class Form implements \Iterator, \ArrayAccess
                                                        $this->data);
             try {
                 $this->cleaned_data[$name] = $field->clean($value);
-                if (in_array('clean_' . $name, $form_methods)) {
-                    $m = 'clean_' . $name;
+                $m = 'clean_' . $name;
+                if (in_array($m, $form_methods) || isset($this->$m)) {
                     $this->cleaned_data[$name] = $this->$m();
                 }
             } catch (Invalid $e) {
@@ -363,6 +363,18 @@ class Form implements \Iterator, \ArrayAccess
     }

     /**
+     * Magic call for the clean methods.
+     *
+     */
+    public function __call($method, $args)
+    {
+        if ( $this->$method instanceof \Closure) {
+            return call_user_func_array($this->$method, $args);
+        }
+        throw new \Exception($method . ' is undefined.');
+    }
+
+    /**
      * Get a given field by key.
      */
     public function field($key)


If you wonder what it means, it means you can do this in the initFields
method when creating a form:

$this->clean_dynamic_field = function () use ($this) {
return validate_field($this->cleaned_data['dynamic_field']);
};

If you are using PHP before 5.4, put use ($that) and $that = $this; just
before. You can of course use a dynamic name for the method:

            $m = 'clean_team_' . $steam;
            $that = $this;
            $this->$m = function() use ($that, $steam) {
                return
CollabForm::getUserList($that->cleaned_data['team_' . $steam]);
            };

In my case, $steam comes from an array iterated over with foreach. This
makes validating forms with a variable number of elements elegant
because the error in the form will nicely be reported at the right place
for the field. In my example, I use it when validating all the teams in
Baregit. The number of teams is variable...

Simple, nice, elegant. I like it.

loïc