0

I apologize for this being a bit lengthy but I wanted to show the code and not leave anything out.

The Goal: The user submits a registration form that submits the form to a database which adds the info plus a unique string to the database. Once the user submits an email is sent to the user that contains a link to a php page that has that unique string as a URL identifier at the end like so:

    xyz.com/activate.php?uid=292ca78b727593baad9a

When the user clicks that link they are taken that page where they will fill out another form and when they click submit it will activate their account.

The Problem: When the user goes to the link provided they receive an error from my validation page like so:

    Undefined index: variable in process.php

BUT when the user deletes the URL identifier so the URL shows as:

    xyz.com/activate.php

The user does not receive an error and the validation page (process.php) works properly. I have attempted to use the identifier with a $_GET['uid'] and checking if it exists before running the code but the result was the same. I cannot find an answer when attempting to google this issue so I apologize if this has been asked before.

The Question: Why does this work without the URL identifier but not with it? I do realize the URL identifier basically does a $_REQUEST when the page first loads which is what runs the process.php. Is there a way to prevent that?

So that you guys know the code I am working with I have posted it below.

activate.php:

<?php

    // validate the form.
    require_once('process.php');
    $validation_rules = array(
        'company_name' => array(
            'required' => true,
            'min-length' => 2
        )
    );
    $db_error = '';
    $validate = new validator();
    $validate->validate($validation_rules);
    if ($validate->validate_result()) {
        // the validation passed!
    }

?>
        <div class="bg v-100 cm-hero-activate">
            <div class="v-100">
                <div class="v-set v-mid">
                    <form class="v-mid v-bg-white <?php if(!$validate->validate_result() && $_POST || !empty($error)) { echo "shake"; } ?>" name="activation" action="" method="post">
                        <fieldset>
                            <div class="form-content">
                                <div id="content">
                                    <div class="form-inner in" data-id="1" data-name="activate">
                                        <h1>ACTIVATE YOUR ACCOUNT</h1>
                                        <div class="form-section">
                                            <h2>Personal Info</h2>
                                            <?php if (!empty($db_error)) {
                                                echo $db_error;
                                            } ?>
                                            <div class="field-group">
                                                <input type="text" id="company_name" class="field required" name="company_name" value="<?php $validate->form_value('company_name'); ?>">
                                                <label for="company_name" class="placeholder">Company Name</label>
                                                <?php $validate->error(array('field' => 'company_name', 'display_error' => 'single')); ?>
                                            </div>
                                        </div>
                                        <div class="field-bottom">
                                            <button name="submit" data-name="activate" class="bttn btn-dark btn-hover-gloss">ACTIVATE MY ACCOUNT</button>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </fieldset>
                    </form>
                </div>
            </div>
        </div>

process.php:

<?php

    class validator {

    private $validation_rules;
    private $errors = array();
    private $validate_result = array();

    public function validate($rules) {
        $this->validation_rules = $rules;
        if($this->validation_rules && $_REQUEST) {
            foreach($this->validation_rules as $field => $rules) {
                $result = $this->process_validation($field, $rules);
                if($result == false) {
                    $this->validate_result[] = 0;
                } elseif($result == true) {
                    $this->validate_result[] = 1;
                }
            }
        }
    }

    public function form_value($field_name = '') {
        if($this->validation_rules) {
            if($_REQUEST && $_REQUEST[$field_name]) {
                if(!$this->validate_result()) {
                    echo $_REQUEST[$field_name];
                }
            }
        }
    }

    public function validate_result() {
        if($this->validation_rules) {
            if($_REQUEST) {
                $final_result = true;
                $length = count($this->validate_result);
                for($i=0;$i < $length; $i++) {
                    if($this->validate_result[$i] == 0) {
                        $final_result = false;
                    }
                }
                return $final_result;
            }
        }
    }

    private function process_validation($field, $rules) {
        $result = true;
        $error = array();
        foreach($rules as $rule => $value) {
            if($rule == 'required' && $value == true) {
                if(!$this->required($field, $value)) {
                    $error[] = "$field - required";
                    $result = false;
                }
            } elseif($rule == 'min-length') {
                if(!$this->minlength($field, $value)) {
                    $error[] =  "$field - minimun length is $value";
                    $result = false;
                }
            }
        }
        $this->errors[] = array($field => $error);
        return $result;
    }

    public function error($data = '') {
        if($this->validation_rules) {
            if($_REQUEST) {
                foreach($this->errors as $err) {
                    if(isset($data['field'])) {
                        foreach($err as $field => $field_error) {
                            if($data['field'] == $field) {
                                foreach($field_error as $error_data) {
                                    if(isset($data['display_error']) == 'single') {
                                        echo '<p class="error">' . $error_data . '</p>';
                                        goto next;
                                    } else {
                                        echo '<p class="error">' . $error_data . '</p>';
                                    }
                                }
                                next:
                            }
                        }
                    } else {
                        foreach($err as $field => $field_error) {
                            foreach($field_error as $error_data) {
                                if(isset($data['display_error']) == 'single') {
                                    echo '<p class="error">' . $error_data . '</p>';
                                    goto next1;
                                } else {
                                    echo '<p class="error">' . $error_data . '</p>';
                                }
                            }
                            next1:
                        }
                    }
                }
            }
        }
    }

    private function required($field, $value) {
        if(empty($_REQUEST[$field])) {
            return false;
        } else {
            return true;
        }
    }

    private function minlength($field, $value) {
        if(strlen($_REQUEST[$field]) < $value) {
            return false;
        } else {
            return true;
        }
    }

?>

EDIT: it seems that the error is happening on the if statement in the min-length function: if(strlen($_REQUEST[$field]) < $value)

EDIT 2: This may also be of some use. The textbox is being filled with this: <br /><font size='1'><table class='xdebug-error xe-notice' dir='ltr' border='1' cellspacing='0' cellpadding='1'><tr><th align='left' bgcolor='#f57900' colspan=

and underneath that I receive this error: Notice: Undefined index: company_name in C:\...\process.php on line 25 Call Stack #TimeMemoryFunctionLocation 10.0005369632{main}( )...\activate.php:0 20.0029403928validator->form_value( )...\activate.php:80 ">

9
  • No I am not. This code is hosted on my server with wamp. (Don't know if that is relevant but I was not sure what CodeIgniter was until just now) Commented Aug 11, 2016 at 6:10
  • Am sorry that was a stupid comment. Did not read the question properly. Will remove it now Commented Aug 11, 2016 at 6:12
  • On which line did the unidentified index happend, please post the code Commented Aug 11, 2016 at 6:14
  • Sorry I have added the line where the error is happening at the bottom of the question. Commented Aug 11, 2016 at 6:21
  • 1
    @Gravy Also I was unaware of the validator package you linked. As a new php developer, I for some reason get it in my head that I want to "start from scratch" so that I can understand the code better, but it seems like in cases like validation there is absolutely no reason to "reinvent the wheel". I feel like I need to get out of that mindset. Commented Aug 11, 2016 at 13:05

2 Answers 2

2

Your $field_name doesn't exist in the $_REQUEST array which is why you are getting your undefined index error.

You are not checking if the value is set - just accessing it via $_REQUEST[$field_name] in your if statement.

Change

public function form_value($field_name = '') {
    if($this->validation_rules) {
        if($_REQUEST && $_REQUEST[$field_name]) {
            if(!$this->validate_result()) {
                echo $_REQUEST[$field_name];
            }
        }
    }
}

To

public function form_value($field_name = '') {
    if($this->validation_rules) {
        if($_REQUEST && isset($_REQUEST[$field_name])) {
            if(!$this->validate_result()) {
                echo $_REQUEST[$field_name];
            }
        }
    }
}

Unrelated Tips.

Aim for cleaner - and more concise readable code.

$input = [
    'name' => 'Matthew',
];

$rules = [
    'name' => 'required|string',
];

$v = (new Validator())->validate($input, $rules);
if ($v->fails()) {
  // Do something with $v->errors();
  return;
}

// Do something with validated input

Try and avoid using else or elseif wherever possible. This can be achieved by looking for the negative first, and exiting early. Try not to have too many levels of nesting. It makes your code extremely difficult to read and increases cyclomatic complexity.

Also - take a look at an MVC framework which should help you to structure your code. A good start would be something like Laravel https://laravel.com/ there are good tutorials on https://laracasts.com/

Sign up to request clarification or add additional context in comments.

3 Comments

Thank you!!! This worked fantastically. Changing all instances where $_REQUEST[$field_name] was in an if statement to isset($_REQUEST[$field_name]) is exactly what I needed. You're awesome @Gravy
Yeah, when I was following the tutorial for the custom validation I thought that the nesting was a bit unnecessary but I am not sure how to trim it down without basically re-writing it. I may just go with the validator package you recommended in your comment. I am constantly looking for the best practices and "right" way to do things. I will take a look into using laravel and see if I can understand it better. Is it easy to integrate into a project that has already been started or would it be better to start over? Thanks for all your help by the way. I appreciate it.
Laravel is pretty easy / straight forward. Based on your code above - You will probably want to re-write it once you start using a framework. Follow the laracasts tutorials - before you know it, you will be writing enterprise quality software.
1

You are getting this error because you have logic like

if($this->validation_rules && $_REQUEST) {

In PHP, an empty array is falsy and a non-empty one, truthy.

$_REQUEST is a combination of $_GET, $_POST and $_COOKIE.

When you add the uid query parameter, $_REQUEST will not be empty and therefore not falsy and your validator will attempt to run but without the expected POST data (such as company_name).

If you're only wanting to validate POST data, you should only be inspecting $_POST.

See Gravy's answer for safer ways to check for the existence of array keys.

1 Comment

I should have known that the $_REQUEST would act like that. Perhaps I will change all of the $_REQUEST to $_POST so that the form does not try to validate until they click the submit button. +1 for explaining why I was getting the error in a bit more detail. Thank you!

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.