yendrrek
yendrrek

Reputation: 331

Including model functions in controller in PHP

I'm trying to put all my PHP functions in a separate file. I'm using require to include them in the controller file but I get errors with undefined variables in the view file. For example:

A function stored in a file 'functions.php' validating my contact form (for the sake of clarity reduced here to validating only one field):

function validateContactForm()
{
    if (empty($_POST['name'])) {
        $name_error = 'Name is required.';
    } else {
        $name = ($_POST['name'];
        if (!preg_match("/^[A-Za-z .'-]+$/", $name)) {
            $name_error = 'Enter a valid name.';
        }
    }               
} 

In my controller I put this require 'functions.php';.

My view file which gives undefined variable errors. It's just an HTML file with PHP code echoing validation messages.

<form 
name="contact" 
action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>" 
method="post">

<label 
for="name" 
id="name-form">
Name:
</label>
    <span id="name-error">
    <?php echo $name_error; ?></span>
</form>

It all works great when I put the PHP code without enclosing it in a function on top of the view file. I've tried to return $name in the function, I've tried require_once and also I used $name as an argument in the function: validateContactForm($name) .

I have followed some simple tutorials where return statement is supposed to be enough but obviously I'm missing something.

Looks like my view file can't access the variables in the function validateContactForm().

Upvotes: 0

Views: 74

Answers (3)

F. M&#252;ller
F. M&#252;ller

Reputation: 4062

Problem:

The variables in your functions.php file have file-scope. You may access them with the use of global or $GLOBALS or the use keyword on anonymous functions.

I recommend, that you use classes to store your functions.
Please note, that it is not good practice to use globals in the first place.

Possible solutions:

Anyway, you could use any one of these options below*:
*This list of options may not be complete.


./lib.php

<?php

// variables have file-scope, can`t be used directly via require
$foo = 1;
$bar = 2;

// anonymous functions can use the keyword `use` to access the variable
$callFoo = function() use ($foo) {
    echo $foo;
};

// with normal functions, we use the global keyword to get the variable 
function callBar() {
    global $bar;
    echo $bar;
}

// alternative to the one above ...
function callBarAlternative() {
    echo $GLOBALS['bar'];
}

// working with classes:
class Foo {
    public $publicFoo = 3;
    private $privateFoo = 4;

    function fooMethod() {
        echo $this->privateFoo;
    }
}

./view.php

<?php

require "lib.php";

?>
<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="text/html" charset="utf-8">
</head>
<body>
    <?php
        $callFoo();
        callBar();
        callBarAlternative();
        $foo = new Foo();
        echo $foo->publicFoo;
        $foo->fooMethod();
        echo $GLOBALS['bar'];
        global $bar;
        echo $bar;
    ?>
</body>
</html>

The output for these calls will be: 1223422

Upvotes: 2

jon
jon

Reputation: 123

The most right way for me to do this looks like this (based on the general code logic):

/**
 * @param Array $POST
 */
function validateContactForm($POST){
    
    if( empty($POST['name']) ){
         throw new Exception('Name is required');
    }

    if (!preg_match("/^[A-Za-z .'-]+$/", $POST['name'])) {
        throw new Exception('Enter a valid name');
    }

}

Then in the view you can do:

try {
     validateContactForm($_POST);
}
catch (Exception $e) {
    // show the error to the user somehow..
}

By this way, you can expand the logic in the function however you wish later and not be able to change code elsewhere. You can also check & validate multiple $_POST data.

Upvotes: 0

Nicola Revelant
Nicola Revelant

Reputation: 102

The PHP variables inside a function have a local scope and so they are not visible outside. Use the "global" keyword to indicate that the variable is global.

function validateContactForm()
{
    global $name_error, $name;
    if (empty($_POST['name'])) {
        $name_error = 'Name is required.';
    } else {
        $name = ($_POST['name'];
        if (!preg_match("/^[A-Za-z .'-]+$/", $name)) {
            $name_error = 'Enter a valid name.';
        }
    }               
}

Upvotes: 1

Related Questions