Jump to content

Best way to load controller MVC


TrueMember

Recommended Posts

I'm using this struture to run my application, everything works fine, but i don't like how the controllers are called. If i load the model in construct it will work great again, but i think that is unnecessary.

You can see two pieces of code about controller "Post.php", the last one, works great.

If i try this: (Posts.php)

    namespace app\controllers;
    
    use app\libraries\Controller;
    use app\models\User;
    
    class Posts extends Controller {    
        public function index():void {
            //Get posts
            $user = new User();
            $posts = $user->posts();
            $data = [
                'posts' => $posts
            ];
    
            $this->view('posts/index', $data);
        }
    }

I will get an error: 

Quote

Fatal error: Uncaught Error: Class 'app\models\User' not found in C:\xampp\htdocs\shake\app\controllers\Posts.php

Structure:

Quote

    - app
        - libraries
            - Core.php
            - Controller.lphp
        - bootstrap.php
    - public
        - index.php
    - vendor
    composer.json

bootstrap.php

//include all files from libraries
require_once __DIR__ . "/../vendor/autoload.php";

index.php

use app\libraries\Core;
require_once '../app/bootstrap.php';

//Init Core Library
$init = new Core();

core.php

    public function __construct(){
        $url = $this->getUrl();
    
        //Look in controllers for first value
        if(file_exists(dirname(__FILE__, 2) . '/controllers/' . ucwords($url[0]) . '.php')){
            //if exists, set as controller
            $this->currentController = ucwords($url[0]);
            //Unset 0 index
            unset($url[0]);
        }
    
        //Require the controller
        require_once dirname(__FILE__, 2) . '/controllers/' . $this->currentController . '.php';
    
        //instantiate controller class
        $class = 'app\\controllers\\' . $this->currentController;
        $this->currentController = new $class;
    
        //check for second part of url
        if(isset($url[1])){
            //Check to see if method exists in controller
            if(method_exists($this->currentController, $url[1])){
                $this->currentMethod = $url[1];
                //Unset 1 index
                unset($url[1]);
            }
        }
        
        //Get params
        $this->params = $url ? array_values($url) : [];
    
        //Call a callback with array of params
        call_user_func_array([$this->currentController, $this->currentMethod], $this->params);
        }

Posts.php

    class Posts extends Controller {
        public function __construct() {
            $this->userModel = $this->model('User');
            $this->postModel = $this->model('Post');
        }
        
        public function index():void {
            //Get posts
            $posts = $this->userModel->posts();
            $data = [
                'posts' => $posts
            ];
    
            $this->view('posts/index', $data);
        }
    }

Controller.php

abstract class Controller {
    /**
     * Load model
     * @param $model
     * @return mixed
     */
    public function model($model) {
        //Require model file
        require_once '../app/models/' . $model . ".php";
        
        //instantiate model
        $class = 'app\models\\' . $model;
        return new $class();
    }

 

Link to comment
Share on other sites

You're barking up the wrong tree.

In the first version PHP is telling you that it doesn't know what that User class is. I see in the second version you're require_once()ing a file before trying to use its class...

Link to comment
Share on other sites

You can make whatever changes you'd like - as long as that User.php file gets included before you try to use the class.

Or better yet, learn about and implementing autoloading so you never have to care about including files manually.

Link to comment
Share on other sites

9 minutes ago, requinix said:

You can make whatever changes you'd like - as long as that User.php file gets included before you try to use the class.

Or better yet, learn about and implementing autoloading so you never have to care about including files manually.

This is what i do in bootstrap.php but only for content inside libraries folder. I should do the same for controllers? Do you have any example?

Link to comment
Share on other sites

You might as well do it for all your classes, not just this "libraries" folder.

As an example of how to do autoloading, I would point you to the place in your code where you are (apparently) already doing autoloading.

Link to comment
Share on other sites

You bootstrap requires routing.

Essentially routing is the piece that takes a url and matches it to a controller.  

Some examples to look at:

https://symfony.com/doc/current/routing.html

https://laravel.com/docs/7.x/routing

https://book.cakephp.org/3/en/development/routing.html

There's lots of Routing components/classes out there, but here is one that might make for a good model for you:  https://altorouter.com/

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.