Get up to 80 % extra points for free! More info:

Lesson 3 - Three-tier architecture and other multi-tier architectures

In the previous lesson, Monolithic and two-tier architecture, we explained what the logical architecture is and why it's important for our applications to have some architecture. We mentioned the monolithic architecture and then divided it into two layers, creating a two-tier architecture. To experience the principle of controllers and models, we have created a fully functional two-tier application in PHP that provides the API to get data of cars.

Three-tier architecture

We're getting back to the topic which is asked in most job interviews. You'll definitely hear the question "What is the three-tier architecture?" Since we've already explained the two-layer architecture, there's not much more ahead. The third layer shows the result to the user, which we could omit in the two-tier application since the user was just a machine working with raw JSON.

The application layers will be:

  • Models - Logic, typically SQL queries
  • Views - Templates, typically HTML files
  • Controllers - Middle men with whom the user communicates and whom communicate with the models and views. It's the middle men what allows the full separation of logic and presentation. This is what we try to do in every application. If you should remember something, then it's that architectures usually separate logic and presentation.

Note that the initial letters of the layers form "MVC" together, which is the name of the most famous three-tier architecture. Other three-tier architectures are:

  • Model-View-ViewModel (MVVM) - The MVVM architecture comes up with another layer. We use minimalist models in templates, so-called ViewModels, to make passing data between the template and the controller, and vice versa, easier. In practice, we use bindings, which is a very sophisticated tool. It allows us to bind a ViewModel to a template so that any changes, e.g. of values ​​in a template form, immediately results in a change of the corresponding ViewModel properties and vice versa. We are able to read and write template data just by creating a ViewModel.
  • Model-View-Presenter (MVP) - The MVP architecture is promoted by some popular frameworks. It works basically just like MVC, sometimes it's understood as an MVC implementation. We can find various MVC and MVP implementations in different applications and some things can be done in a slightly different way. There are small differences between these two patterns. In MVP, we're often able to access presenters from a view. Sometimes it's even the view which takes over the control of the application itself and creates a presenter that retrieves data from the logic. But it doesn't always have to work like that. If you are lost in MVC and MVP differences, it's unfortunately normal because their specification is confusing. I recommend following the previously mentioned MVC.

Just to be sure, let's describe what the layers will do once again:

The MVC architecture

The life cycle of a request to a three-layer MVC application will be as follows:

  1. The router calls the appropriate controller by the URL
  2. The controller asks a model for data
  3. The controller stores the data
  4. The data are passed to a View
  5. The View fills an HTML template with the data
  6. The complete page is sent to the user

Let's change our two-tier application to a three-layer application so it displays results as HTML pages.


The model will stay the same.


Instead of using echo() and `json_encode() to print the data, the controller prepares variables for the template, and then loads the template:

class CarController

    private $carManager;
    private $database;

    public function __construct($database)
        $this->database = $database;
        $this->carController = new CarController($this->database);

    public function all()
        $cars = $this->carManager->getCars(); // A template variable
        require('Templates/cars.phtml'); // Loads the template

    // Other actions like one($id), remove($id), ...



The new application layer is now a view, a template. That's an HTML code with a small addition of some other language's syntax used to iterate over the data and to insert variables. We use a loop to iterate the $data variable retrieved from the controller.

<html lang="en">
        <title>Car list</title>
       <meta charset="UTF-8">

        <table border="1">
            <?php foreach ($cars as $car) : ?>
                    <td><?= htmlspecialchars($car['license_plate']) ?></td>
                    <td><?= htmlspecialchars($car['color']) ?></td>
            <?php endforeach ?>


The completed template is then sent to the user. It looks like this:

Car list

So, we improved our sample application a lot. Although we've passed the dependencies manually so far, the app is now separated as follows:

  • Models - Files with pure application/bu­siness logic
  • Views - Files with relatively clean templates
  • Controllers - Relatively small middle men

You can compare the current progress with the example when everything was in a single file. However, it's also necessary to imagine that each application part is complex enough to show the value added by separating these parts.

Form applications

And what about form applications? If the application is not a web-based but a desktop application, of course, there is some similar automatic mechanism above our code calling the right class representing a form or whatever the user is communicating with. The Controller pattern can really be applied everywhere, and we should definitely do that. You've already created a form application for sure, the class handling the form controls was a controller. For example, in JavaFX, classes are even named controllers, but, for example in C# .NET, they are called CodeBehind, even though they are controllers. Be honest, have you ever written your logic directly to this file handling the form? :) So now you know that you should have encapsulated logic into separated models. Just like we've shown it on the cars web app.

In the next lesson, Wrong ways of passing dependencies - Static members, we'll finally talk about passing dependencies. We'll show what happens if we don't pass dependencies at all but create new service instances every time. We also show antipatterns as a passing by static attributes, Singleton and ServiceLocator design patterns, and different variations.

If you are having problems with MVC or you are interested in it, take a look at our separate PHP course on this architecture - Simple object-oriented CMS in PHP (MVC).


Previous article
Monolithic and two-tier architecture
All articles in this section
Software Architectures and Dependency Injection
Skip article
(not recommended)
Wrong ways of passing dependencies - Static members
Article has been written for you by David Capka
User rating:
No one has rated this quite yet, be the first one!
The author is a programmer, who likes web technologies and being the lead/chief article writer at He shares his knowledge with the community and is always looking to improve. He believes that anyone can do what they set their mind to.
Unicorn university David learned IT at the Unicorn University - a prestigious college providing education on IT and economics.