I am trying to add an apply_filters function to a property of a class so that the form fields could be added to from another plugin or functions.php but I just can't get the $filter_fields to set. Can anyone tell me what I'm doing wrong? When I echo out $form_fields I get the h4 and the submit button but no fields.
class-registration-form.php
class RegForm {
// Properties
private $fields;
private $filter_fields;
// Constructor
function __construct(){
$this->fields = array(
'name' => '<label>Name.</label><br>
<input type="text" name="name"><br>',
'business name' => '<label>Business Name.</label><br>
<input type="text" name="business_name"><br>',
'email' => '<label>Email.</label><br>
<input type="email" required="required" name="email"><br>',
'password' => '<label>Password.</label><br>
<input type="password" required="required" name="password"><br>'
);
add_shortcode('registerform', array($this, 'create_reg_form'));
}
// Methods
public function init (){
$filter_fields = apply_filters('tbg_reg_fields', $this->fields);
}
public function create_reg_form ($filter_fields){
$form_fields = implode($this->filter_fields);
?>
<h4>Register as a New Store Owner</h4>
<form method="post" class="tbg_reg_form" action="' . admin_url( 'admin-ajax.php' ) . '">
<?php echo $form_fields; ?>
<input type="hidden" name="action" value="tbg_form_submit">
<input type="submit" value="Start Selling Now">
</form>
<?php
}
}
$newForm = new RegForm;
add_action ('plugins_loaded', [$newForm, 'init']);
and in the themes functions.php file I have
// Registration Fields
function add_age_field($new_fields) {
$new_fields[] = '<label>Website.</label><br><input type="text" name="website"><br>';
return $new_fields;
}
add_filter('tbg_reg_fields', 'add_age_field');
I am trying to add an apply_filters function to a property of a class so that the form fields could be added to from another plugin or functions.php but I just can't get the $filter_fields to set. Can anyone tell me what I'm doing wrong? When I echo out $form_fields I get the h4 and the submit button but no fields.
class-registration-form.php
class RegForm {
// Properties
private $fields;
private $filter_fields;
// Constructor
function __construct(){
$this->fields = array(
'name' => '<label>Name.</label><br>
<input type="text" name="name"><br>',
'business name' => '<label>Business Name.</label><br>
<input type="text" name="business_name"><br>',
'email' => '<label>Email.</label><br>
<input type="email" required="required" name="email"><br>',
'password' => '<label>Password.</label><br>
<input type="password" required="required" name="password"><br>'
);
add_shortcode('registerform', array($this, 'create_reg_form'));
}
// Methods
public function init (){
$filter_fields = apply_filters('tbg_reg_fields', $this->fields);
}
public function create_reg_form ($filter_fields){
$form_fields = implode($this->filter_fields);
?>
<h4>Register as a New Store Owner</h4>
<form method="post" class="tbg_reg_form" action="' . admin_url( 'admin-ajax.php' ) . '">
<?php echo $form_fields; ?>
<input type="hidden" name="action" value="tbg_form_submit">
<input type="submit" value="Start Selling Now">
</form>
<?php
}
}
$newForm = new RegForm;
add_action ('plugins_loaded', [$newForm, 'init']);
and in the themes functions.php file I have
// Registration Fields
function add_age_field($new_fields) {
$new_fields[] = '<label>Website.</label><br><input type="text" name="website"><br>';
return $new_fields;
}
add_filter('tbg_reg_fields', 'add_age_field');
Share
Improve this question
asked Jan 3, 2020 at 14:46
Dan SutherlandDan Sutherland
1632 gold badges2 silver badges11 bronze badges
1
|
1 Answer
Reset to default 2Your problem has nothing to do with apply_filters
, it's a basic PHP mistake:
public function init (){
$filter_fields = apply_filters('tbg_reg_fields', $this->fields);
}
Here, you create a brand new variable in the init method scope named $filter_fields
, then never use it.
$this->filter_fields
and $filter_fields
are not the same.
Additionally, because you used a filter and stored the fully formed HTML in advance, it's impossible to late escape, leading to security issues.
So instead, replace this:
<h4>Register as a New Store Owner</h4>
<form method="post" class="tbg_reg_form" action="' . admin_url( 'admin-ajax.php' ) . '">
<?php echo $form_fields; ?>
<input type="hidden" name="action" value="tbg_form_submit">
<input type="submit" value="Start Selling Now">
</form>
With a do_action
, like this:
<h4>Register as a New Store Owner</h4>
<form method="post" class="tbg_reg_form" action="' . admin_url( 'admin-ajax.php' ) . '">
<?php do_action( 'tbg_reg_fields', $this->fields ); ?>
<input type="hidden" name="action" value="tbg_form_submit">
<input type="submit" value="Start Selling Now">
</form>
That way:
- you can output the HTML directly
- the action only runs when the code is being generated, unlike the original which runs even when there are no shortcodes on the page
- You can escape the fields in the functions that output them
- The call to
init
method and the filter_fields variable can be completely eliminated
Further general code quality notes:
- You're using
array( $this, '....
use PHP 5.3+ short array syntax instead[ $this, '...
instead - It's impossible to load
class-registration-form.php
without creating that class, making it impossible to create unit tests - There's no reason for this to be a class, the entire thing could be simplified to a function named
create_reg_form
, moving the fields array into that function, and callingadd_shortcode
on theinit
hook. The class provides nothing, it isn't object oriented, and makes the code more complex, not less, and you only ever have one instance, so it's a waste of memory to create an object admin-ajax.php
is for really old AJAX handlers! Stop abusing it as a form handler! Leave theaction
blank and then check$_POST
oninit
to check if your form got submitted and handle it there. Don't abuseadmin-ajax.php
for things it was never intended for.if ( !empty( $_POST['action'] ) && $_POST['action'] === 'tbg_form_submit' )
on theinit
action is more than enough
$filter_fields
ininit()
then the new value is lost. you can add this filter in the constructor when you define the field list. – Kaperto Commented Jan 3, 2020 at 14:49