0

I have a page that receives POST data from a form. I also have a form validation class that attempts to access the $_POST array when a FormValidation object is created on the page. However, the FormValidation object does not seem to have access to the $_POST array. Why is this happening, and how can I fix this?

EDIT: Added code :)

This code is from register.php

if($_SERVER['REQUEST_METHOD'] == 'POST')
{
var_dump($_POST);

$errors = validate_form();

if(count($errors) > 0)
{
    display($errors);
}
else
{
    act();
}
}
else
{
display();
}

function validate_form()
{
$validator = new FormValidation('POST');

$validator->add_field('first_name', 'First Name');
$validator->add_field('last_name', 'Last Name');
$validator->add_field('email_address', 'Email Address');
$validator->add_field('password', 'Password');
$validator->add_field('password_confirmation', 'Password Confirmation');

$validator->add_rule('first_name', 'required');
$validator->add_rule('last_name', 'required');
$validator->add_rule('email_address', 'required');
$validator->add_rule('email_address', 'is_valid_scarsdaleschools_email');
$validator->add_rule('password', 'required');
$validator->add_rule('password_confirmation', 'required');
$validator->add_rule('password_confirmation', 'matches', array('password', 'Password'));


return $validator->validate();
}

The form validation code looks like this

class FormValidation
{
var $fields;
var $rules; //Associative array that maps field_name to array of rules
var $errors;

var $form_method_type;

function FormValidation($form_method_type)
{
    $this->form_method_type = strtoupper($form_method_type);

    $this->fields = array(); //maps fields to field labels
    $this->rules = array();
    $this->errors = array();
}

function validate() 
{   
    foreach(array_keys($this->fields) as $field_name)
    {
        if(!array_key_exists($field_name, $this->rules))
        {
            continue;
        }
        foreach(array_keys($this->rules[$field_name]) as $rule_name)
        {
            call_user_func_array(array($this, $rule_name), $this->rules[$field_name][$rule_name]);
        }
    }

    return $this->errors;
}

function add_field($field_name, $field_label)
{
    $this->fields[$field_name] = $field_label;
}

function add_rule($field_name, $rule_name, $parameters=array())
{                                                           
    if(!isset($this->rules[$field_name]))
    {
        $this->rules[$field_name] = array();
    }

    array_unshift($parameters, $field_name, $this->fields[$field_name]);
    $this->rules[$field_name][$rule_name] = $parameters;
}

function var_isset($field_name)
{
    global ${'$_' . $this->form_method_type};
    var_dump(${'$_' . $this->form_method_type}[$field_name]);
    return isset(${'$_' . $this->form_method_type}[$field_name]);
}

function get_value($field_name)
{
    global ${'$_' . $this->form_method_type};
    return ${'$_' . $this->form_method_type}[$field_name];
}

    ////////////////////////////////////////////////////////////
/////RULES//////////////////////////////////////////////////
////////////////////////////////////////////////////////////

function required($field_name, $field_label)
{
    if(!$this->var_isset($field_name))
    {
        $this->errors[$field_name] = "$field_label is a required field";
    }
}

function is_valid_email($field_name, $field_label)
{
    if($this->var_isset($field_name))
    {
        if(!validEmail($this->get_value($field_name)))
        {
            $this->errors[$field_name] = "$field_label requires a valid email address";
        }
    }
}

function is_alpha($field_name, $field_label)
{
    if($this->var_isset($field_name))
    {
        if(!ctype_alpha($this->get_value($field_name)))
        {
            $this->errors[$field_name] = "$field_label requires alphabetical characters only";
        }
    }
}

function is_alphanumeric($field_name, $field_label)
{
    if($this->var_isset($field_name))
    {
        if(!ctype_alnum($this->get_value($field_name)))
        {
            $this->errors[$field_name] = "$field_label requires alphanumeric characters only";
        }
    }
}

function is_integer_number($field_name, $field_label)
{
    if($this->var_isset($field_name))
    {
        if(!is_int($this->get_value($field_name)) || preg_match('[-+]?[0-9]+', $this->get_value($field_name)) == 0)
        {
            $this->errors[$field_name] = "$field_label must be an integer";
        }
    }
}

function is_float_number($field_name, $field_label)
{
    if($this->var_isset($field_name))
    {
        if(!is_float($this->get_value($field_name)) || preg_match('[-+]?[0-9]*\.?[0-9]+', $this->get_value($field_name)) == 0)
        {
            $this->errors[$field_name] = "$field_label must be a number";
        }
    }
}

function is_valid_scarsdaleschools_email($field_name, $field_label)
{
    if($this->var_isset($field_name))
    {
        if(!validEmail($this->get_value($field_name)))
        {
            $this->errors[$field_name] = "$field_label requires a valid email address";
        }

        $email = $this->get_value($field_name);

        if(!(endsWith($email, 'scarsdaleschools.org', $case=false) || endsWith($email, 'scarsdaleschools.com', $case=false) || endsWith($email, 'scarsdaleschools.k12.ny.edu', $case=false)))
        {
            $this->errors[$field_name] = "$field_label requires a Scarsdale Schools email address";
        }
    }
}

function max_length($field_name, $field_label, $max_length)
{
    if($this->var_isset($field_name))
    {
        if(strlen($this->get_value($field_name)) > $max_length)
        {
            $this->errors[$field_name] = "$field_label cannot be longer than $max_length characters";
        }
    }
}

function min_length($field_name, $field_label, $min_length)
{
    if($this->var_isset($field_name))
    {
        if(strlen($this->get_value($field_name)) > $min_length)
        {
            $this->errors[$field_name] = "$field_label must be at least $min_length characters";
        }
    }
}

function matches($field_name, $field_label, $match_field_name, $match_field_label)
{
    if($this->var_isset($field_name) && !$this->var_isset($match_field_name))
    {
        $this->errors[$field_name] = "$field_label must match $match_field_label";
    }
    elseif(!$this->var_isset($field_name) && $this->var_isset($match_field_name))
    {
        $this->errors[$field_name] = "$field_label must match $match_field_label";
    }
    if($this->var_isset($field_name) && $this->var_isset($match_field_name))
    {
        if(strcmp($this->get_value($field_name), $this->get_value($match_field_name)) != 0)
        {
            $this->errors[$field_name] = "$field_label must match $match_field_label";
        }
    }
}
}

Thanks for the help!

1
  • $_POST is a superglobal, meaning that it's available in any scope at any time. As long you are still in the same script to which the form data was posted, $_POST should be available anywhere. Commented Jun 30, 2011 at 2:24

3 Answers 3

1

There is a small error in your code. What you were writing was essentially $$_POST. You'll need to remove the extra dollar sign from the variable name (corrected methods below). In addition, you needn't worry about calling global $_POST; as $_POST is a superglobal, or automatic global.

Update: Retrieving $_POST via ${'_' . $this->form_method_type} does not seem to work. The code I sent you works OUTSIDE of the class, but not inside. I wanted to make sure you understood my findings, and the distinction. So while ${'_' . $formMethodType} works outside of the class, inside you'll have to use something like this:

const TYPE_POST = 'POST';
const TYPE_GET = 'GET';
const TYPE_SESSION = 'SESSION';
const TYPE_SERVER = 'SERVER';
const TYPE_REQUEST = 'REQUEST';

public $fields = array();
public $rules = array();
public $errors = array();

public function __construct($formMethodType)
{
    $r = new ReflectionClass($this);
    $constants = $r->getConstants();

    $formMethodType = strtoupper($formMethodType);
    if (!array_key_exists('TYPE_' . $formMethodType, $constants)) {
        throw new InvalidArgumentException('Could not find type matching $formMethodType : ' . $formMethodType);
    }
    $this->form_method_type = $formMethodType;
}

public function var_isset($field_name)
{
    $values = $this->get_values();
    var_dump($values[$field_name]);
    return isset($values[$field_name]);
}

public function get_value($field_name)
{
    $values = $this->get_values();
    return $values[$field_name];
}

public function get_values()
{
    switch ($this->form_method_type) {
        case self::TYPE_POST:
            $values = $_POST;
            break;
        case self::TYPE_GET:
            $values = $_GET;
            break;
        case self::TYPE_REQUEST:
            $values = $_REQUEST;
            break;
        case self::TYPE_SERVER:
            $values = $_SERVER;
            break;
        case self::TYPE_SESSION:
            $values = $_SESSION;
            break;
    }
    return $values;
}
Sign up to request clarification or add additional context in comments.

10 Comments

When I tried your change for var_isset I got the following error: Notice: Undefined variable: _POST in /Users/nick/Sites/CompLabSite/includes/formvalidation.php on line 58 NULLL When I return to the old code a var_dump shows Notice: Undefined variable: $_POST in /Users/nick/Sites/CompLabSite/includes/formvalidation.php on line 58 NULL This leads me to believe that the old way was at least trying to access the right variable, but it doesn't seem to be global for some reason. :-/
@nickles I am positive that this method of pulling from $_POST works. You have to trust me when I say your original code was trying to pull from $$_POST.
@nickles Can you test this code? $_POST['test'] = 'test123'; $var = 'POST'; var_dump(${'_' . $var});
Also, what version of PHP are you using? I successfully tested this code in PHP 5.3.
@webjawns.com I'm running PHP 5.3. Give me a second to run the test code there.
|
1

We haven't yet seen any code posted, but I'll make a recommendation about using dependency injection to get the $_POST data into your form validation class, rather than accessing the superglobal from inside the class.

Since you can't always rely on $_POST being populated correctly when you are testing your code, it is advisable to inject the contents of $_POST as a parameter to the constructor of a class where it will be used. This makes it easier to debug later on.

class MyClass {
  // Public property to hold post array data 
  public $postdata;

  // constructor receives $_POST as a parameter
  function __construct($param1, $param2, $postdata) {
    //
    $this->postdata  = $postdata;
  }
}

// Instantiate the class with $_POST injected
$x = new MyClass($a, $b, $_POST);

ADDENDUM after code posted

I don't see any method in your class that actually calls the get_value() method when validating. It's unclear if you are ever accessing the contents of $_POST in that class at all other than in the var_isset() and get_value() methods.

1 Comment

Hi, thanks for responding! I have a bunch of rules that use both methods. I snipped the rules out since I found that the get_value() method was not able to see the $_POST data. I'll post them all though.
0
/**
 * This should work for $_REQUEST and $_POST the mysql_real_escape_string
 * was added to escape urls. It is best not to allow URLs as parameters.
 */
foreach( $_POST as $key=> $val)
{
  ${$key} = mysql_real_escape_string($val);
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.