BO
466 10
Asked
Updated
Viewed
12.1k times

I sort of understand what MVC is in theory. Model, View and Controller and CodeIgniter, Laravel, CakePHP and those sort of libraries (would that define them?) use a form of MVC or a derivative. I've actually used Laravel (the only "library" I was able to figure out how to work) but I have no idea how it works.

Now though, I've gotten the idea that the user, when typing www.site.com (as an example) lands on the Controller which then combines the correct Model to it's View and displays the formatted results to the user. Is that the correct understanding of MVC?

For some reason, I've being unable to completely understand the concept entirely regardless of how many tutorials I've read on the topic and I've being trying for quite some time (though not consistently... haven't being coding for a few years now).

  • 0
    You generally have the right idea, however, when visiting a website you don't necessarily land on the controller, but typically most will setup routes to load a Controller's method that handles the logic. — Brian Wozeniak
  • 0
    I don't understand exactly what routes are, how they work and how they're setup. I understand the general picture but don't know the intricate details of it. — Bogey
add a comment
2

3 Answers

  • Votes
  • Oldest
  • Latest
Answered
Updated

You have already properly identified the meaning of MVC in your question, Model-View-Controller, but essentially it is a design pattern that is used in programming and web development frameworks like you mentioned. You might also say it's an architectural pattern since it sort of forms the basis of how your application generally is pieced together.

If you have heard of the SOLID principle, MVC follows the "S" principle by separating responsibilities. The Model contains the data, the view renders the elements that interact with the user, and the controller ensures that the sequence of steps occurs correctly and pieces everything together.

Does that make it all crystal clear to you now? Probably not, you might be exactly where you were before with your understanding. Maybe a better question would be, What is the point of MVC, and how will it help me?

I think where this pattern excels is when you have rather complex systems, especially systems that you might reuse in different places. A common model for instance is a model representing the User. With this model, you would probably be able to obtain all sorts of data, probably much from the database where it's stored, but you may also have other logic in the model that does calculations or has to run through logic before returning the value that is used. You can then load up this Model in a controller and send some of its data to a view that is presented to someone visiting your website. The controller itself would be rather simple, it would ask for the User Model and then would send any data obtained from this model to the view which would render the HTML and the data together.

Now imagine if you didn't use the MVC pattern, and instead, you had a single method in a class for each webpage on your website that ran through logic line-by-line. This method would have to do quite a bit of work, it would have to have logic in place to bring in the user's data (perhaps a unique database query), it would have to run any calculations, and it would need to somehow have logic in place for HTML and inserting any dynamic data in that HTML where it belongs. The old Ozzu which ran on PHPBB did exactly this sort of procedural programming, and it was often frustrating to work with. I always feared making certain changes because I was not sure how they might affect other areas. Everything was very coupled together.

So by using MVC, you will:

  1. Promote separation of responsibilities: Allows you to help make the code easier to maintain and extend since everything is decoupled.
  2. Support code reusability and scalability: Can easily change the view or model without affecting other components. Perhaps you want a view for when people visit the web page, but you also want a view for those accessing the data via an API. No problem, you can easily reuse the components.
  3. Maintain better organization of code: Always helpful, but even more so if you have a large or complex application.

Finally just a note about routing. Most MVC systems used with web applications will have some sort of routing system so that you can send (route) requests to a specific controller and method that will handle it. Laravel for instance sends everything through a routing system first so that you can do exactly this (if you want). The image below shows what the MVC model looks like with the routing portion included:

Diagram of the MVC Design Pattern

In a nutshell, it's just a way to figure out what controller/method is responsible for returning what the user asked for. From there the controller's method will get all of the data the view needs via models, get its rendered result from the view (HTML for a web page, JSON for an API response, etc), and then send it back to the user who requested it.

add a comment
2
BO
466 10
Answered
Updated

Thanks to ChatGPT, I learned how routers actually work and actually created 1 (with ChatGPT) that seems like it works.

Part of the magic is because .htaccess sends all requests to index.php and index PHP initiates the router and passes in the URI to it. Then the router class breaks the URI down into parts and matches them against the registered routes and then invokes the classes calls the actions and passes the params into the action/method.

.htaccess

<IfModule mod_rewrite.c>
    # Send Requests To Front Controller...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.php [L]
</IfModule>

index.php

<?php

include 'Router.php';
include 'UserController.php';

$router = new Router(require 'routes.php');
$router->route($_SERVER['REQUEST_URI']);

?>

UserController.php

<?php

class UserController {
    public function show($id) {
        // Logic to handle user with the specified ID
        echo "Showing user with ID: $id";
    }
    public function showPost($uid, $pid) {
        // Logic to handle user with the specified ID and post with the specified ID
        echo "Showing post with ID $pid for user with ID $uid";
    }
}

?>

router.php

<?php

class Router {
    
    private $routes;

    public function __construct(array $routes) {
        $this->routes = $routes;
    }

    public function route($url) {
        foreach ($this->routes as $route => $handler) {
            $pattern = $this->buildPattern($route);
            if (preg_match($pattern, $url, $matches)) {
                array_shift($matches); // Remove the full match
                $this->invokeControllerAction($handler, $matches);
                return;
            }
        }
        // Handle 404 - Route not found
        $this->handle404();
    }

    private function buildPattern($route) {
        return '#^' . preg_replace('/\{(\w+)\}/', '(?P<$1>[^/]+)', $route) . '$#';
    }

    private function invokeControllerAction($handler, $params) {
        list($controllerName, $action) = explode('@', $handler);
        $controller = new $controllerName();
        $this->callControllerAction($controller, $action, $params);
    }

    private function callControllerAction($controller, $action, $params) {
        $reflectionMethod = new ReflectionMethod($controller, $action);
        $methodParameters = $reflectionMethod->getParameters();

        $resolvedParams = [];
        foreach ($methodParameters as $param) {
            $paramName = $param->getName();
            $resolvedParams[] = $params[$paramName] ?? null;
        }

        $reflectionMethod->invokeArgs($controller, $resolvedParams);
    }

    private function handle404() {
        // Handle the 404 error
        echo "404 Not Found";
    }
}

?>

routes.php

<?php

return [
    '/testRouter/users/{id}'                 => 'UserController@show',
    '/testRouter/users/{uid}/posts/{pid}'    => 'UserController@showPost',
    // Other routes...
];

?>
  • 0
    From the top level that is how many of these frameworks work too, such as the Laravel Framework. All requests get routed to index.php via .htaccess rules like you did here, and from there the URI is parsed and request routed accordingly. — Brian Wozeniak
  • 1
    This single thing, the router, kept me from being able to use frameworks because I simply didn't understand how it worked. Much easier now that I do. — Bogey
add a comment
1
Answered
Updated

MVC (Model-View-Controller) is a design pattern used in software development to separate the application logic into three interconnected components. This separation helps manage complex applications by dividing responsibilities, improving modularity, and making the code easier to maintain and test. Here’s how MVC works in PHP:

1. Model

The Model represents the data and the business logic of the application. It handles data retrieval, storage, and updates, often interacting with a database.

Responsibilities:

  • Manage data and business rules.
  • Interact with the database (CRUD operations: Create, Read, Update, Delete).
  • Process data before it is displayed by the View.

Example:

class UserModel {
    private $db;

    public function __construct($database) {
        $this->db = $database;
    }

    public function getUser($id) {
        $stmt = $this->db->prepare("SELECT * FROM users WHERE id = ?");
        $stmt->execute([$id]);
        return $stmt->fetch();
    }

    public function createUser($data) {
        $stmt = $this->db->prepare("INSERT INTO users (name, email) VALUES (?, ?)");
        return $stmt->execute([$data['name'], $data['email']]);
    }

    // More CRUD operations...
}

2. View

The View is responsible for rendering the user interface and presenting data to the user. It only displays information and does not contain any business logic.

Responsibilities:

  • Display data provided by the Model.
  • Render HTML templates and handle the presentation layer.

Example:

// user_view.php
<!DOCTYPE html>
<html>
<head>
    <title>User Details</title>
</head>
<body>
    <h1>User Details</h1>
    <p>Name: <?= htmlspecialchars($user['name']) ?></p>
    <p>Email: <?= htmlspecialchars($user['email']) ?></p>
</body>
</html>

3. Controller

The Controller acts as an intermediary between the Model and the View. It handles user input, processes it, and updates the Model or View accordingly.

Responsibilities:

  • Receive input from the user.
  • Interact with the Model to retrieve or manipulate data.
  • Pass data to the View for rendering.

Example:

class UserController {
    private $model;

    public function __construct($model) {
        $this->model = $model;
    }

    public function showUser($id) {
        $user = $this->model->getUser($id);
        include 'user_view.php';
    }

    public function createUser($data) {
        $this->model->createUser($data);
        header('Location: /users');
    }

    // More actions...
}

Putting It All Together

To implement an MVC pattern in PHP, follow these steps:

  1. Set Up the Environment:

    • Create a basic file structure: models, views, controllers, and index.php.
    • Set up a database connection.
  2. Define the Model:

    • Create a model class to handle database operations.
  3. Create the Controller:

    • Develop a controller class to handle user input and interact with the model.
    • Define methods for different actions (e.g., show user, create user).
  4. Design the View:

    • Create view files to render the data provided by the controller.
    • Use basic HTML templates.
  5. Route Requests:

    • Use a basic routing mechanism in index.php to map URLs to controller actions.

Example of a Basic Routing Mechanism:

// index.php
require 'models/UserModel.php';
require 'controllers/UserController.php';

$database = new PDO('mysql:host=localhost;dbname=testdb', 'root', '');
$model = new UserModel($database);
$controller = new UserController($model);

if ($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['id'])) {
    $controller->showUser($_GET['id']);
} elseif ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $controller->createUser($_POST);
} else {
    // Default action or error handling
}

Frameworks

While you can implement MVC from scratch, using a PHP framework like Laravel, Symfony, or CodeIgniter can simplify the process and provide additional features and tools.

By following the MVC pattern, you can create organized, maintainable, and scalable PHP applications.

add a comment
0