How to call an object chain of function dynamically in php?

Viewed 231
$form = new Form();
return $form->addHiddenElement('somename', 'value')
     ->addTextInputElement('someothername', 'value')
     ->generate();

We have a simple form generator that works a little like above.

Is it possible to get this done with a config, eg a simple php array?

I know about: http://php.net/manual/en/function.call-user-func-array.php and other similar functions. But in the above we have an unknown qty of functions each with an unknown qty of params and each must chain onto the next...

For this array could potentially map correctly..

return [
   'addHiddenElement' => [
      'somename', 'value'
   ],
   'addTextInputElement' => [
      'someothername', 'value'
   ]
]

Is this possible in php?

(in javascript this could be done with evil eval ;) but i get the idea there might be a proper way to do this in php)

1 Answers

Yes you can do this in vanilla (wihout some kind of framework) PHP by returning $this in each of the functions. Consider this class

class Form{
    public function  addHiddenElement($name, $value)
    {
        /**Do some stuff**/
        return $this; //This will allow you to chain additional functions
    }
    public function addTextInputElement($name, $value)
    {
        /** Do some more stuff */
        return $this;
    }
}

In this way, since you are always returning $this you can chain additional methods from the class together (e.g. $form->addHiddenElement('name','value')->addTextInputElement('name','value');

Since you are always returning $this you should use exceptions for error handling.

EDIT: To use a config to generate a list of functions you could use a simple function like this:

function buildForm($config)
{
    $form = new Form(); //Create the form object
    foreach($config as $function=>$params){ //iterate over the requested functions
        if(method_exists($form, $function){ //Confirm the function exists before attemting execution
            /** Updating $form to the result of the function call is equivalent to chaining all the functions in the $config array */
            $form = call_user_func_array( array($form, $function), $params);
        }
    }
    return $form;
}

You would then call the function like this:

$config = [
   'addHiddenElement' => [
      'somename', 'value'
   ],
   'addTextInputElement' => [
      'someothername', 'value'
   ]
];
$form = buildForm($config);

This function is functionally equivalent to chaining your functions.

Note some caveats.

  1. The above function assumes that ALL methods included in $config return $this. If you wanted to, you could add some validation logic to account for methods that do not.
  2. This function will let you call ANY public method in Form, you may want to add some logic to validate $config before executing the function.
Related