1

In my php project I use simple mvc created with this tutorial.

This is my Bootstrap.php file

<?php
class Bootstrap {

    private $_url = null;
    private $_controller = null;

    private $_controllerPath = 'controllers/';
    private $_modelPath = 'models/';
    private $_errorFile = 'error.php';
    private $_defaultFile = 'home.php';

    public function init(){
        $this->_getUrl();

        if(empty($this->_url[0])){
            $this->_loadDefaultController();
            return false;
        }   

        $this->_loadExistingController();
        $this->_callControllerMethod(); 
    }

    private function _getUrl(){
        $url = isset($_GET['url']) ? $_GET['url'] : null;
        $url = rtrim($url, '/');
        $url = filter_var($url, FILTER_SANITIZE_URL);
        $this->_url = explode('/', $url);
    }

    private function _loadDefaultController() {
        require $this->_controllerPath . $this->_defaultFile;
        $this->_controller = new Home();
        $this->_controller->index();    
    }

    private function _loadExistingController() {
        $file = $this->_controllerPath . $this->_url[0] . '.php';

        if(file_exists($file)) {
            require $file;
            $this->_controller = new $this->_url[0];
            $this->_controller->loadModel($this->_url[0], $this->_modelPath);   
        } else {
            $this->_error();
            return false;
        }           
    }

    private function _callControllerMethod() {
        if(isset($this->_url[2])) {
            if(method_exists($this->_controller, $this->_url[1])) {
                $this->_controller->{$this->_url[1]}($this->_url[2]);
            } else {
                $this->_error();
            }
        } else {
            if(isset($this->_url[1])) {
                if(method_exists($this->_controller, $this->_url[1])) {
                    $this->_controller->{$this->_url[1]}();
                } else {
                    $this->_error();
                }
            } else {
                $this->_controller->index();
            }
        }
    }

    private function _error() {
        require $this->_controllerPath . $this->_errorFile;
        $this->_controller = new Error();
        $this->_controller->index();
        exit;
    }
}

Controller

<?php
class Controller {
    function __construct() {
        $this->view = new View();           
    }

    public function loadModel($name, $modelPath = 'models/') {
        $path = $modelPath . $name .'_model.php';

        if(file_exists($path)) {
            require $modelPath . $name .'_model.php';

            $modelName = $name . '_Model';
            $this->model = new $modelName();
        }
    }
}

and user controller

<?php
class User extends Controller {
    function __construct(){
        parent::__construct();          
    }

    public function registration() {
        $this->view->render('user/registration');
    }

    public function enter() {
        $this->view->render('user/enter');
    }

    public function create() {
        $data = array();
        $data['name'] = $_POST['name'];
        $data['password'] = $_POST['password'];
        $data['role'] = 2;

        $this->model->create($data);            
        header('location: ' . URL);
    }

}

I added client-side validation (name and password fields must not be empty) but I also would like to add server-side validation, but I don't understand how here return data if errors would be found back to view? I guess, I need to return errors and data from right filled fields.

2
  • Have you thought about using query parameters and $_GET? Not sure what you've tried so far. Commented Feb 1, 2016 at 18:55
  • No, I didn't try this. Could you give me an example or idea how to use it, please? Commented Feb 1, 2016 at 18:59

2 Answers 2

2

Use sessions to pass the validation errors. Here is an example...

$_SESSION['error'] = array(
    'message' => 'Invalid username/password combination',
    'for' => 'login-form',
    'variables' => array(
        'username' => $_POST['username'],
    ),
);

Then on the front end you can check to see if the session contains and error variable or whatever you choose to name it. If it does you can then go ahead and print the errors.

I actually made a similar lightweight framework for a University class that I was taking and looking through some of the code may help you. Check it out.

To further explain this in the context of your application...

class User extends Controller {

    ...

    public function create() {
        $data = array();
        $data['name'] = $_POST['name'];
        $data['password'] = $_POST['password'];
        $data['role'] = 2;

        // lets assume that the create method on the model will return true when it is successfully created,
        // and then false in the event that there was an error when creating/inserting it.  I am assuming that
        // the session has already been created.
        if (!$this->model->create($data)) {
            // there was an error so lets set the error message
            $_SESSION['errors'] = [
                'form' => 'user-create',
                'message' => 'There was an error creating the user',
            ];
        }

        header('location: ' . URL);
    }

}

I am assuming that you have already started a session. If a session does not exist you can't set a variable on the session. To get around this use session_start() in your bootstrapping/index file.

Then in your view, you can check for errors using something like this code...

if (isset($_SESSION['error']) && count($_SESSION['error']) > 0) {
    echo '<ul>';
    foreach ($_SESSION['error'] as $error) {
        echo '<li>' . $error['messsage'] . '</li>';
    }
    echo '</ul>';
}

This will check if their is an error set (there are several ways to do this, but I always just count the errors). Then we can iterate through each error and print it as an HTML unordered list for the user to view.

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

7 Comments

Where should I add this code? In controller? Could you explain me, please?
You would add it where ever you want to perform the validation, this could be in the controller, in the model, or in a custom validation class. Then in your view you would check for the 'error' key in the session. If it exists you can then print the error. In my specific example from my github repo, I set the session error variable of the UserController in the postLogin method in the case of a failed login attempt.
@Heidel I expanded my answer to better answer your question. In this context you will want to use sessions. It doesn't seem like your application currently has sessions set up but you will more than likely have to implement them in the future. Sessions can be used to track the currently authenticated user and other information about the application state.
thanks a lot for the explanation. I'm just learning php and trying to understand mvc, so I guess it would be better to use a some validation class. but I don't undestand how to use it, how to pass data to it and get some response. And I'm going to use Session for user authentication, yes.
I would put the validation in the controller in that instance then. Take a look at how some frameworks handle the validation. I particularly really like Laravel and it heavily influenced my development of the micro framework I linked to. With the controller that I wrote above, the session allows for you to 'transfer' the error to the view without writing any additional logic.
|
1

To expand on my comment, you can try using query parameters and the $_GET superglobal. For example, in your controller:

<?php
class User extends Controller {
    function __construct(){
        parent::__construct(); //This isn't needed as it's redundant           
    }

    public function registration() {
        $this->view->render('user/registration');
    }

    public function enter() {
        $this->view->render('user/enter');
    }

    public function create() {
        $name = isset($_POST['name']) ? $_POST['name'] : "";
        $password = isset($_POST['password']) ? $_POST['password'] : "";
        if(empty($name) || empty($password)){
            //Redirect to your login form with the query parameter
            //errorMessage which will be used with $_GET
            header('Location: loginPage.php?errorMessage=Username and password cannot be empty!');
            exit();
        }
        $data = array();
        $data['name'] = $_POST['name'];
        $data['password'] = $_POST['password'];
        $data['role'] = 2;

        $this->model->create($data);            
        header('location: ' . URL);
    }

}

Then on your page that has your form, you can do something similar to:

<?php
//This is loginPage.php from the controller example
//Other code up here if you have it

if(isset($_GET['errorMessage'])){
    //If there is a query parameter with the key 'errorMessage'
    //it will echo this out
    echo '<span class="error">' . $_GET['errorMessage'] . '</span>';
}
?>
<form>
    <input type="text" name="password" />
    <input type="password" name="name" />
</form>

More information on $_GET here

2 Comments

Can I use $_POST to return errors to view? I see your idea, but I don't like an idea have all errors in url, it looks a bit ugly, in my opinion.
You cannot use $_POST to return errors to the view without actually POSTing back to your view (which would be ugly). If you don't like having the error message in your URL, you can use @kyle 's example from above or pass the variables back into your view a different way, such as stackoverflow.com/questions/17279230/… or stackoverflow.com/questions/6633849/… .

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.