Reputation: 903
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
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
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
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
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