Russell Parrott
Russell Parrott

Reputation: 903

How can I make different methods in my form-builder class?

If I create a new PHP class e.g. to simplify form building (yes I know there are some out there) but I am also trying to learn about classes so pls. be patient - thanks ...

OK I create a new class in the usual way

class newform { class details in here }

add a construct function

public function __construct() { function in here }

I can then call that class again in the usual way

$newform = new newform();

so far so good .... (for me anyhow).

Now I can add some args to the function like so

public function __construct($args) { function in here }

and inside the function "go through" the args - which in my case is an array so written like this

$newform = new newform($args = array('arg1'=>'arg1 val','arg2'=>'arg2 val'));

I can do all that but how do I "add further functions" What I mean here is at the moment I have to declare a new class for every input: i.e.

$newform = new newform($args = array('arg1'=>'arg1 val','arg2'=>'arg2 val'));
$newform->textarea;

$newform = new newform($args = array('arg1'=>'arg1 val','arg2'=>'arg2 val'));
$newform->textinput;

That seems "very" long winded to me and therefore wrong.

How do you do something like this (syntax I know is wromg) where textarea and textinput are created in the class a bit like this (but without the args) $this->textarea = '<textarea></textarea>';

$newform = new newform();
$newform->textarea($args);
$newform->textinput($args);
$newform->textarea($args);

What I mean is what additional function/s do you put into the class to allow you to firstly declare the class ($newform = new newform();) then pass $args to items within the class so you can do "something" like above?

Hope I am explaining myself.

Upvotes: 1

Views: 243

Answers (4)

Stephen
Stephen

Reputation: 18964

If the arguments in the parameter array are related to individual form elements, move the parameter to a new function instead of the passing it to the class constructor. Like so:

class newform {
    public function __construct() { }
    public function make_textarea(array $args) {
        /* do stuff here */
        return $formatted_textarea; // a string like '<textarea></textarea>'
    }
    public function make_input(array $args) {
        /* do stuff here */
        return $formatted_input; // a string like '<input />'
    }
}

Then in your template:

$form = new newForm;
echo $form->make_textarea(array('arg1' => 'val1', 'arg2' => 'val2'));
echo $form->make_input(array('arg1' => 'val3', 'arg2' => 'val4'));

Note: I'm not doing ($args = array('arg1'=> when calling the method. Assigning the array to a variable is not necessary.

Note: Notice the array type hinting: make_textarea(array $args). That's only there to make sure an array is passed to the method. If anything else is passed to the method--a string for example--a Fatal Error will be thrown.

Update - How to use a private method

class Example {
    public function do_something(array $args) {
        $result = $this->private_method($args);
        return $result;
    }
    private function private_method(array $args) {
        /* do stuff here */
        return $formatted_args;
    }
}

Upvotes: 3

user229044
user229044

Reputation: 239312

It isn't long-winded to declare functions for each type of tag you want to generate. There are a finite number of tags, and rather than relying on dynamically intercepting function calls via __call you're better off simply defining the methods.

Move most of the internal implementation for each type of tag can be moved to a private method for generating generic HTML tags. Not all form elements share any internal implementation though; tags like <input type="password" /> and <input type="text" /> are obvious candidates for a shared implementation, while <select> elements will require special handling.

The following should give you an idea. When you build your own, don't forget to escape htmlspecialchars where appropriate:

class Form_helper {

  // pass boolean false for $contents to build a self-closing "<input />"-style tag
  private function html_tag($name, $contents, array $attributes = array() {
    $tag = "<$name";

    foreach ($attributes as $key => $value) {
      $tag .= " $key=\"$value\"";
    }

    if ($contents === false) { 
      // self-closing
      $tag .= " />"; 
    } else {
      $tag .= ">$contents</$name>";
    }

    return $tag;
  }


  public function textarea($contents, array $attributes = array()) {
    return $this->html_tag('textarea', $contents, $attributes);
  }

  public function input(array $attributes = array()) {
    return $this->html_tag('input', false, $attributes);
  }

  public function select(array $options) {
     // options contains "value"=>"contents" mappings, for production
     // option tags in the form <option value="value">contents</option>
     $option_tags = '';
     foreach ($options as $value => $content) {
       $option_tags .= $this->html_tag('option', $content, array('value' => $value));
     }

     return $this->html_tag('select', $option_tags);
  }
}

Upvotes: 2

netcoder
netcoder

Reputation: 67715

First of all, you don't have to do this:

$newform = new newform($args = array('arg1'=>'arg1 val','arg2'=>'arg2 val'));

This will suffice:

$newform = new newform(array('arg1'=>'arg1 val','arg2'=>'arg2 val'));

That is, if you want to pass an array as the first argument. Normally, you would do something like this instead:

class newform {
   public function __construct($arg1, $arg2) {
      // method body here
   }
}

$form = new newform('arg1 val', 'arg2 val');

Now, you must keep in mind that a constructor (__construct) is just like another method. So you can do this:

class newform {
   public function __construct() {
      // method body here
   }

   public function textarea($name) {
       echo '<textarea name="'.$name.'"></textarea>';
   }

   public funciton textinput($name) {
       echo '<input type="text" name="'.$name.'"/>';
   }
}

$form = new newform;
$form->textarea('foo');
$form->textinput('bar');

Outputs:

<textarea name="foo"></textarea>
<input type="text" name="bar"/>

Upvotes: 1

Raffael
Raffael

Reputation: 20045

I'm not sure what you mean, but my guts tell me that what you need are so-called magic methods:

magic methods / overloading / manual

Best

Raffael

Upvotes: 0

Related Questions