MVC framework application concept. MVC for the web: couldn't be simpler. Creating the remaining pages

In my opinion, absolutely every developer, and not just a programmer, should know MVC in order to ensure the best extensibility of the project.

MVC is not only a software architecture, but also a development concept. I'm not saying that this article will tell you all the secrets of MVC, but you can definitely get an initial understanding. And then http://pogugli.com/?74600

The concept of MVC (Model-View-Controller) has been mentioned very often in the world of web programming in recent years. Everyone who is in any way connected with web application development has come across this acronym in one way or another. Today we will understand what the MVC concept is and why it became popular.

Ancient history

MVC is not a project pattern, it is a design pattern that describes how to build the structure of our application, the responsibilities and interaction of each of the parts in this structure.

It was first described in 1979, of course, for a different environment. There was no concept of a web application back then. Tim Berners Lee sowed the seeds of the World Wide Web (WWW) in the early nineties and changed the world forever. The template we use today is an adaptation of the original template for web development.

The wild popularity of this structure in web applications was due to its inclusion in two development environments that became very popular: Struts and Ruby on Rails. These two development environments set the path for hundreds of development environments that were created later.

MVC for web applications

The idea behind the MVC design pattern is very simple: we need to clearly separate responsibilities for the various functioning in our applications:

The application is divided into three main components, each of which is responsible for different tasks. Let's look at the components in detail using an example.

Controller

The controller manages user requests (received as HTTP GET or POST requests when the user clicks on interface elements to perform various actions). Its main function is to call and coordinate the action of the necessary resources and objects needed to perform actions specified by the user. Typically, the controller calls the appropriate model for the task and selects the appropriate view.

Model

A model is the data and rules that are used to operate on the data that represent the concept for controlling an application. In any application, the entire structure is modeled as data that is processed in a certain way. What is a user for an application - message or book? Only data that must be processed according to rules (date cannot point into the future, email must be in a certain format, name cannot be longer than X characters, and so on).

The model gives the controller a representation of the data that the user has requested (message, book page, photo album, etc.). The data model will be the same no matter how we want to present it to the user. Therefore, we select any available view to display the data.

The model contains the most important part of the logic of our application, the logic that solves the problem we are dealing with (forum, store, bank, etc.). The controller contains basically the organizational logic for the application itself (much like housekeeping).

View

A view provides different ways of representing the data that is obtained from the model. It can be a template that is filled with data. There can be several different types, and the controller chooses which one is best suited for the current situation.

A web application typically consists of a set of controllers, models, and views. The controller can be designed as a main controller that receives all requests and calls other controllers to perform actions depending on the situation.

Let's look at an example

Let's say we need to develop an online bookstore. The user can perform the following actions: view books, register, buy, add items to the current order, create or delete books (if he is an administrator). Let's see what happens when a user clicks on a category fantasy to view the titles of books that are available in our store.

We have a specific controller to handle all actions related to books (view, edit, create, etc.). Let's call it books_controller.php in our example. Also we need a model like book_model.php, which processes the data and logic associated with a store item. In conclusion, we need several views to represent the data, such as a book list, an edit page, and so on.

The following figure shows how a user's request to view a list of books on a topic is processed fantasy:

The controller (books_controller.php) receives the user request (HTTP GET or POST request). We can create a central controller, for example index.php, which receives the request and calls books_controller.php.

The controller checks the request and parameters and then calls the model(book_model.php), asking she has a list of available books on the topic fantasy.

The model receives data from the database (or another source that stores information), applies filters and the necessary logic, and then returns data that represents a list of books.

The controller uses the appropriate view to present data to the user. If the request comes from a mobile phone, the mobile phone view is used; if the user uses a certain interface design, then the corresponding view is selected, and so on.

What are the advantages?

The most obvious benefit we get from using the MVC concept is the clear separation of presentation logic (user interface) and application logic.

Supporting different types of users who use different types of devices is a common challenge these days. The interface provided should be different if the request comes from a personal computer or from a mobile phone. The model returns the same data, the only difference is that the controller chooses different views to output the data.

In addition to isolating views from application logic, the MVC concept significantly reduces the complexity of large applications. The code is much more structured, making it easier to maintain, test, and reuse solutions.

Why use the work environment?

When you use the workbench, the basic MVC structure is already prepared and all you have to do is expand the structure by placing your files in the appropriate directories to match the MVC pattern. Plus, you'll have a set of features that are already written and well tested.

Let's look at cakePHP as an example of an MVC workbench. After installation you will have three main directories:

  • cake/
  • vendors/

Folder app is where your files are located. This is the place to develop your part of the application.

In folder cake hosts cakePHP files (workbench functionality).

Folder vendors is used to store third-party PHP libraries.

Your workspace (app directory) has the following structure:

  • app/
    • config/
    • controllers/
    • locale/
    • models/
    • plugins/
    • tests/
    • vendors/
    • views/
    • webroot/

You need to place your controllers in the controllers directory, your models in the models directory, and your views in the views directory!

Once you start using the workbench, it will immediately become clear where virtually every part of your application that needs to be created or modified resides. This organization in itself greatly simplifies the process of developing and maintaining an application.

Using the workbench for our example

Since this tutorial is not intended to show the process of creating an application using cakePHP, we will only show the code for the model, controller and view with comments on the benefits of using the MVC workbench. The code is deliberately simplified and unsuitable for use in a real application.

Remember, we were looking at a bookstore and a curious user who wanted to see a complete list of books on the topic fantasy. The controller received the user's request and coordinated the necessary actions.

So, as soon as the user clicks the button, the browser requests the given url:

1 www.ourstore.com/books/list/fantasy

CakePHP formats URL using a pattern /controller/action/param1/param2, Where action is a function that is called by the controller. In the old classic form, the url will look like this:

1 www.ourstore.com/books_controller.php?action=list&category=fantasy

Controller

In the cakePHP working environment, our controller will look like this:

1
class BooksController extends AppController (

function list($category) (

$this ->set("books" , $this ->Book->findAllByCategory($category));

}

function add() ( ... ... )

function delete () ( ... ... )

... ... } ?>

Simple, isn't it? This controller will be saved as books_controller.php and posted in /app/controllers. It contains a list of functions that perform the actions for our example, as well as other functions for performing book-related operations (add a new book, delete a book, and so on).

The working environment provides us with many ready-made solutions and we only need to create a list of books. There is a base class that already defines the basic functionality of the controller, so you need to inherit the properties and functions of this class ( AppController is the heir Controller).

All you have to do in the action list is call the model to get the data and then select a view to present it to the user. Here's how it's done.

this->Book- this is our model, and part of the code:

1 $this ->Book->findAllByCategory($category)

tells the model to return a list of books on the selected topic (we'll look at the model later).

Method set in line:

1 $this ->set("books" , $this ->Book->findAllByCategory($category));

The controller passes data to the view. Variable books accepts the data returned by the model and makes it available to the view.

Now all that remains is to display the view, but this function is done automatically in cakePHP if we use the default view. If we want to use a different type, we must explicitly call the method render.

Model

The model is even simpler:

1
class Book extends AppModel (

}

?>

Why is it empty? Because it inherits from a base class that provides the required functionality and we need to use CakePHP's naming convention to have the runtime handle all other tasks automatically. For example, cakePHP knows based on its name that this model is used in BooksController, and that it has access to a database table named books.

With this definition, we will have a model that can only read, delete, or save data in the database.

Save the code as book.php in folder /app/models.

View

All we need to do now is create a view (at least one) for the action list. The view will have HTML code and a few (as few as possible) lines of PHP code to loop through the array of books that the model provides.

1














Name Author Price

As you can see, the view does not create a full page, but only a fragment of HTML (a table in this case). Because CakePHP provides another way to define a page template, and the view is inserted into that template. The workbench also provides us with some helper objects for performing common tasks while creating parts of an HTML page (inserting forms, links, Ajax or JavaScript).

Save the view as list.ctp(list is the action name and ctp means CakePHP template) in the folder /app/views/books(because it's a view for a controller action).

This is how all three components are executed using the CakePHP workbench!

MVC is a web design pattern that includes several smaller patterns. When using MVC, the application data model, user interface and interaction with the user they are divided into three separate components, thanks to which the modification of one of them has a minimal effect influence on others or does not have any effect at all.

The main goal of using MVC is to separate data and business logic from the visualization (external appearance). Due to this division, the possibility of reusing program code is increased and maintenance is simplified ( changes in appearance, for example, are not reflected in business logic).

The MVC concept separates the data, presentation and processing of user actions on someone:

  • Model(Model) - provides an object model of a certain subject area, includes data and methods of working with this data, reacts to requests from the controller, returning data and/or changing its state, while the model does not contain information as given These can be visualized, and also do not “communicate” with the user directly.
  • Performance(View) - responsible for displaying information (visualization), the same data can be presented differently With the help of, for example, a collection of objects with the help of different “views” can be presented both in tabular form and in a list .
  • Controller(Controller) - provides communication between the user and the system, uses the model and presentation to implement the need -di-my reaction to the actions of the user, as a rule, at the level of the controller, filtering of the received data and authorization (the user’s rights to perform actions or receive information are verified).

Alternate names for the MVC pattern:

  • model-view-controller
  • model-pre-becoming-le-nie-pove-de-nie
  • model-pre-becoming-le-nie-con -troller
  • model-view-con-troller
Many people start writing a project to work with a single task, not implying that it can grow into a multi-user management system, for example, content or, God forbid, production. And everything seems great and cool, everything works, until you begin to understand that the code that is written consists entirely of crutches and hard code. The code is mixed with layout, queries and crutches, sometimes even unreadable. A pressing problem arises: when adding new features, you have to tinker with this code for a very long time, remembering “what was written there?” and curse yourself in the past.

You may have even heard about design patterns and even leafed through these wonderful books:

  • E. Gamma, R. Helm, R. Johnson, J. Vlissides “Object-oriented design techniques. Design Patterns";
  • M. Fowler "Architecture of Enterprise Software Applications."
And many, undaunted by the huge manuals and documentation, tried to study any of the modern frameworks and, faced with the complexity of understanding (due to the presence of many architectural concepts cleverly linked to each other), put off the study and use of modern tools “on the back burner.”

This article will be useful primarily for beginners. In any case, I hope that in a couple of hours you will be able to get an idea of ​​the implementation of the MVC pattern, which underlies all modern web frameworks, and also get “food” for further reflection on “how to do it.” At the end of the article there is a selection of useful links that will also help you understand what web frameworks consist of (besides MVC) and how they work.

Seasoned PHP programmers are unlikely to find anything new for themselves in this article, but their comments and comments on the main text would be very helpful! Because Without theory, practice is impossible, and without practice, theory is useless, then first there will be a little theory, and then we will move on to practice. If you are already familiar with the MVC concept, you can skip the theory section and go straight to the practice.

1. Theory

The MVC pattern describes a simple way to structure an application that aims to separate business logic from the user interface. As a result, the application is easier to scale, test, maintain and, of course, implement.

Let's look at the conceptual diagram of the MVC pattern (in my opinion, this is the most successful diagram I have seen):

In MVC architecture, the model provides the data and business logic rules, the view is responsible for the user interface, and the controller provides interaction between the model and the view.

A typical flow of an MVC application can be described as follows:

  1. When a user visits a web resource, the initialization script creates an instance of the application and launches it for execution.
    This displays a view of, say, the main page of the site.
  2. The application receives a request from the user and determines the requested controller and action. In the case of the main page, the default action is performed ( index).
  3. The application instantiates the controller and runs the action method,
    which, for example, contains model calls that read information from the database.
  4. After this, the action creates a view with the data obtained from the model and displays the result to the user.
Model- contains the business logic of the application and includes methods for sampling (these can be ORM methods), processing (for example, validation rules) and providing specific data, which often makes it very thick, which is quite normal.
The model should not directly interact with the user. All variables related to the user request must be processed in the controller.
The model should not generate HTML or other display code that can change depending on the user's needs. Such code should be processed in views.
The same model, for example: the user authentication model can be used in both the user and administrative parts of the application. In this case, you can move the general code into a separate class and inherit from it, defining sub-application-specific methods in its descendants.

View- used to set the external display of data received from the controller and model.
Views contain HTML markup and small inserts of PHP code to traverse, format, and display data.
Should not directly access the database. This is what models should do.
Should not work with data obtained from a user request. This task must be performed by the controller.
Can directly access properties and methods of a controller or models to obtain output-ready data.
Views are usually divided into a common template, containing markup common to all pages (for example, a header and footer) and parts of the template that are used to display data output from the model or display data entry forms.

Controller- the glue that connects models, views, and other components into a working application. The controller is responsible for processing user requests. The controller should not contain SQL queries. It is better to keep them in models. The controller should not contain HTML or other markup. It’s worth bringing it into view.
In a well-designed MVC application, controllers are usually very thin and contain only a few dozen lines of code. The same cannot be said about Stupid Fat Controllers (SFC) in CMS Joomla. The controller logic is quite typical and most of it is transferred to base classes.
Models, on the contrary, are very thick and contain most of the code related to data processing, because the data structure and business logic contained within it are usually quite specific to a particular application.

1.1. Front Controller and Page Controller

In most cases, user interaction with a web application occurs through clicking on links. Look now at the address bar of your browser - you received this text from this link. Other links, such as those on the right side of this page, will provide you with different content. Thus, the link represents a specific command to the web application.

I hope you have already noticed that different sites can have completely different formats for constructing the address bar. Each format can display the architecture of a web application. Although this is not always the case, in most cases it is a clear fact.

Let's consider two options for the address bar, which display some text and a user profile.

First option:

  1. www.example.com/article.php?id=3
  2. www.example.com/user.php?id=4
Here, each script is responsible for executing a specific command.

Second option:

  1. www.example.com/index.php?article=3
  2. www.example.com/index.php?user=4
And here all calls occur in one scenario index.php.

You can see the multi-touchpoint approach on the phpBB forums. Browsing the forum occurs through a script viewforum.php, view topic via viewtopic.php etc. The second approach, with access through a single physical script file, can be seen in my favorite CMS MODX, where all accesses go through index.php.

These two approaches are completely different. The first is typical for the Page Controller pattern, and the second approach is implemented by the Front Controller pattern. The page controller is good for sites with fairly simple logic. In turn, the request controller consolidates all request processing activities in one place, which gives it additional capabilities that can allow you to implement more complex tasks than are usually solved by the page controller. I will not go into details of the implementation of the page controller, but will only say that in the practical part, it will be the request controller (something similar) that will be developed.

1.2. URL Routing

URL routing allows you to configure your application to accept requests from URLs that do not correspond to actual application files, and to use CNCs that are semantically meaningful to users and preferred for search engine optimization.

For example, for a regular page displaying a contact form, the URL might look like this:
http://www.example.com/contacts.php?action=feedback

Approximate processing code in this case:
switch ($_GET ["action" ]) ( case "about" : require_once ("about.php" ); // "About Us" page break ; case "contacts" : require_once ( "contacts.php" ); // page "Contacts" break ; case "feedback" : require_once("feedback.php" ); // "Feedback" page break ; default : require_once ( "page404.php" ); // page "404" break ; )
I think almost everyone has done this before.

Using a URL routing engine, you can configure your application to accept requests like this to display the same information:
http://www.example.com/contacts/feedback

Here contacts represents the controller, and feedback is the contacts controller method that displays the feedback form, etc. We will return to this issue in the practical part.

It's also worth knowing that many web frameworks' routers allow you to create custom URL routes (specify what each part of the URL means) and rules for processing them.
Now we have sufficient theoretical knowledge to move on to practice.

2. Practice

First, let's create the following file and folder structure:

Looking ahead, I will say that the core classes Model, View and Controller will be stored in the core folder.
Their children will be stored in the controllers, models and views directories. File index.php This is the entry point into the application. File bootstrap.php initiates the download of the application, connecting all the necessary modules, etc.

We will go sequentially; Let's open the index.php file and fill it with the following code:
ini_set("display_errors" , 1 ); require_once "application/bootstrap.php" ;
There shouldn't be any questions here.

Next, let's immediately move on to the halyard bootstrap.php:
require_once "core/model.php" ; require_once "core/view.php" ; require_once "core/controller.php" ; require_once "core/route.php" ; Route::start(); //start the router
The first three lines will include currently non-existent kernel files. The last lines include the file with the router class and launch it for execution by calling the static start method.

2.1. Implementing a URL Router

For now, let's deviate from the implementation of the MVC pattern and move on to routing. The first step we need to do is write the following code in .htaccess:
RewriteEngine On RewriteCond %(REQUEST_FILENAME) !-f RewriteCond %(REQUEST_FILENAME) !-d RewriteRule .* index.php [L]
This code will redirect processing of all pages to index.php, which is what we need. Remember in the first part we talked about Front Controller?!

We will place the routing in a separate file route.php to the core directory. In this file we will describe the Route class, which will run controller methods, which in turn will generate the page view.

Contents of the route.php file

class Route( static function start() ( // controller and default action$controller_name = "Main" ; $action_name = "index" ; $routes = explode("/" , $_SERVER ["REQUEST_URI" ]); // get the controller name if (!empty ($routes )) ( $controller_name = $routes ; ) // get the action name if (!empty ($routes )) ( $action_name = $routes ; ) // add prefixes$model_name = "Model_" .$controller_name ; $controller_name = "Controller_" .$controller_name ; $action_name = "action_" .$action_name ; // hook up the file with the model class (there may not be a model file)$model_file = strtolower($model_name )..php" ; $model_path = "application/models/" .$model_file ; if (file_exists($model_path )) ( include "application/models/" .$model_file ; ) // hook up the file with the controller class$controller_file = strtolower($controller_name )..php" ; $controller_path = "application/controllers/" .$controller_file ; if (file_exists($controller_path )) ( include "application/controllers/" .$controller_file ; ) else ( /* it would be correct to throw an exception here, but to simplify it, we’ll immediately redirect to the 404 page */ Route::ErrorPage404(); ) // create a controller$controller = new $controller_name ; $action = $action_name ; if (method_exists($controller , $action )) ( // call the controller action$controller ->$action(); ) else ( // it would also be wiser to throw an exception here Route::ErrorPage404(); ) ) function ErrorPage404() ($host = "http://" .$_SERVER ["HTTP_HOST" ]."/" ; header("HTTP/1.1 404 Not Found" ); header("Status: 404 Not Found" ); header("Location:" .$host ."404" ); ) )


I note that the class implements very simplified logic (despite the voluminous code) and may even have security problems. This was done intentionally, because... writing a full-fledged routing class deserves at least a separate article. Let's look at the main points...

The global array element $_SERVER["REQUEST_URI"] contains the full address to which the user contacted.
For example: example.ru/contacts/feedback

Using the function explode The address is divided into components. As a result, we get the name of the controller, for the example given, this is controller contacts and the name of the action, in our case - feedback.

Next, the model file (the model may be missing) and the controller file, if any, are connected and finally, an instance of the controller is created and the action is called, again, if it was described in the controller class.

Thus, when going to, for example, the address:
example.com/portfolio
or
example.com/portfolio/index
The router will perform the following actions:

  1. will include the model_portfolio.php file from the models folder, containing the Model_Portfolio class;
  2. will include the controller_portfolio.php file from the controllers folder, containing the Controller_Portfolio class;
  3. will create an instance of the Controller_Portfolio class and call the default action, action_index, described in it.
If the user tries to access the address of a non-existent controller, for example:
example.com/ufo
then he will be redirected to the “404” page:
example.com/404
The same thing will happen if the user accesses an action that is not described in the controller.

2.2. Let's return to the MVC implementation

Let's go to the core folder and add three more files to the route.php file: model.php, view.php and controller.php

Let me remind you that they will contain base classes, which we will now begin writing.

File contents model.php
class Model( public function get_data() ( } }
The model class contains a single empty data fetch method, which will be overridden in descendant classes. When we create descendant classes everything will become clearer.

File contents view.php
classView( //public $template_view; // here you can specify the default general view. function generate ( $content_view , $template_view , $data = null) { /* if(is_array($data)) ( // convert array elements into variables extract($data); ) */ include "application/views/" .$template_view ; ) )
It is not difficult to guess that the method generate intended to form a view. The following parameters are passed to it:

  1. $content_file - views displaying page content;
  2. $template_file — template common to all pages;
  3. $data is an array containing page content elements. Usually filled in in the model.
The include function dynamically connects a general template (view) within which the view will be embedded
to display the content of a specific page.

In our case, the general template will contain header, menu, sidebar and footer, and the page content will be contained in a separate form. Again, this is done for simplicity.

File contents controller.php
class Controller( public $model ; public $view ; function __construct() ($this ->view = new View(); ) ) )
Method action_index- this is the action called by default; we will override it when implementing descendant classes.

2.3. Implementation of descendant classes Model and Controller, creation of View's

Now the fun begins! Our business card website will consist of the following pages:
  1. home
  2. Services
  3. Portfolio
  4. Contacts
  5. And also - the “404” page
Each page has its own controller from the controllers folder and a view from the views folder. Some pages may use a model or models from the models folder.

In the previous figure, the file is highlighted separately template_view.php is a template containing markup common to all pages. In the simplest case it could look like this:
<html lang="ru" > <head > <metacharset="utf-8"> <title > hometitle > head > <body > $content_view ; ?> body > html >
To give the site a presentable look, we create a CSS template and integrate it into our site by changing the structure of the HTML markup and connecting CSS and JavaScript files:
<link rel ="stylesheet" type ="text/css" href ="/css/style.css" /> <script src="/js/jquery-1.6.2.js" type="text/javascript" >script >

At the end of the article, in the “Result” section, there is a link to a GitHub repository with a project in which steps have been taken to integrate a simple template.

2.3.1. Creating the main page

Let's start with the controller controller_main.php, here is his code:
class Controller_Main extends Controller ( function action_index() ($this ->view->generate("main_view.php" , "template_view.php" ); ) )
In method generate an instance of the View class, the names of the files of the general template and the view with the page content are passed.
In addition to the index action, the controller can of course contain other actions.

We reviewed the general view file earlier. Consider the content file main_view.php:
<h1 > Welcome!h1 > <p> <img src ="/images/office-small.jpg" align ="left" > <a href = "/" > OLOLOSHA TEAMa >- a team of first-class specialists in the field of website development with many years of experience in collecting Mexican masks, bronze and stone statues from India and Ceylon, bas-reliefs and sculptures created by masters of Equatorial Africa five or six centuries ago...p>
This contains simple markup without any PHP calls.
To display the main page, you can use one of the following addresses:

  • methods of libraries that implement data abstraction. For example, methods of the PEAR MDB2 library;
  • ORM methods;
  • methods for working with NoSQL;
  • and etc.
  • For simplicity, we will not use SQL queries or ORM statements here. Instead, we will emulate real data and immediately return an array of results.
    Model file model_portfolio.php put it in the models folder. Here are its contents:
    class Model_Portfolio extends Model ( public function get_data() ( return array (array ("Year" => "2012" , "Site" => "http://DunkelBeer.ru" , "Description" => "Promotional site for dark beer Dunkel from the German manufacturer Löwenbraü, produced in Russia by the brewing company SUN InBev."), array ("Year" => "2012" , "Site" => "http://ZopoMobile.ru" , "Description" => "Russian-language catalog of Chinese phones from Zopo based on Android OS and accessories for them."), // todo ); ) )

    The model controller class is contained in the file controller_portfolio.php, here is his code:
    class Controller_Portfolio extends Controller ( function __construct() ($this ->model = new Model_Portfolio(); $this ->view = new View(); ) function action_index() ($data = $this ->model->get_data(); $this ->view->generate("portfolio_view.php" , "template_view.php" , $data ); ) )
    To a variable data the array returned by the method is written get_data which we looked at earlier.
    This variable is then passed as a method parameter generate, which also contains: the name of the file with the general template and the name of the file containing the view with the page content.

    The view containing the page content is in the file portfolio_view.php.

    Portfolio

    All projects in the following table are fictitious, so do not even try to follow the links provided. " ; }


    GitHub link: https://github.com/vitalyswipe/tinymvc/zipball/v0.1

    But in this version I sketched out the following classes (and their corresponding types):

    • Controller_Login in which a view is generated with a form for entering login and password, after filling which the authentication procedure is performed and, if successful, the user is redirected to the admin panel.
    • Contorller_Admin with an index action that checks whether the user was previously authorized on the site as an administrator (if so, the admin panel view is displayed) and a logout action for logging out.
    Authentication and authorization is a different topic, so it is not discussed here, but only the link given above is provided so that you have something to start from.

    4. Conclusion

    The MVC pattern is used as an architectural basis in many frameworks and CMS, which were created in order to be able to develop qualitatively more complex solutions in a shorter time. This was made possible by increasing the level of abstraction, since there is a limit to the complexity of the structures that the human brain can operate with.

    But, using web frameworks such as Yii or Kohana, consisting of several hundred files, when developing simple web applications (for example, business card sites) is not always advisable. Now we can create a beautiful MVC model so as not to mix Php, Html, CSS and JavaScript code in one file.

    This article is more of a starting point for learning CMF than an example of something truly correct that you can use as the basis for your web application. Perhaps it even inspired you and you are already thinking about writing your own microframework or CMS based on MVC. But, before reinventing the next wheel with “blackjack and whores,” think again: maybe it would be more reasonable to direct your efforts to the development and helping the community of an already existing project?!

    P.S.: The article was rewritten taking into account some comments left in the comments. The criticism turned out to be very useful. Judging by the response: comments, PMs and the number of users who added the post to favorites, the idea of ​​writing this post turned out to be not so bad. Unfortunately, it is not possible to take into account all the wishes and write more and in more detail due to lack of time... but perhaps those mysterious individuals who downvoted the original version will do this. Good luck with your projects!

    5. A selection of useful links on the subject

    The article very often touches on the topic of web frameworks - this is a very broad topic, because even microframeworks consist of many components cleverly interconnected and it would take more than one article to talk about these components. However, I decided to present here a small selection of links (which I followed while writing this article) that in one way or another relate to the topic of frameworks.

    There are millions of web applications scattered throughout the internet world. There are some that are quite simple, and there are those that “the architect of the matrix himself would break his leg.” But they have one thing in common - MVC.

    The most popular architectural pattern in the world among web applications - model-view-controller (Model View Controller or simply MVC). For the first time, it was used back in the late 70s of the twentieth century, in applications in the language Smalltalk. And then the programmers took him in Java and shared it with the whole world and all programming languages. PHP was no exception. Today, only a small part of programmers who collect rare PHP code can afford not to look towards MVC.

    It became so popular for a reason. It was simply born to create flexible and scalable applications that are easy to maintain and expand.
    The purpose of our tutorial is to show with a simple example how the MVC pattern works.

    To complete the tasks, you will need the following programs:

    Notes:

    • We assume that you have basic knowledge of PHP.

    MVC pattern

    Now let's talk about everything in order. First, let's reveal the great secret of the abbreviation, which obviously reflects the fact that the application will consist of three interacting parts:

    • Model is responsible for data management, it stores and retrieves entities used by the application, typically from a database and contains the logic implemented in the application.
    • Performance is responsible for displaying the data provided by the controller. Closely related to presentation is the concept of a template, which allows you to change the appearance of the information shown. In a web application, the view is often implemented as an HTML page.
    • Controller connects the model and the view. It receives a request from the client, analyzes its parameters, and accesses the model to perform operations on the request data. Already assembled objects come from the model. They are then redirected to the view, which passes the generated page to the controller, which in turn sends it to the client.

    The data flows in this model can be schematically represented as follows:

    Entering reality

    Let's finally formulate the real problem. Let us say they ordered us to build a social networking site. There is a small subtask in this gigantic task: using the existing database of friends, provide viewing of their complete list, as well as detailed information for each friend.

    We will not now consider the architecture of the entire social network. We will take only a small subtask, imagine its seriousness and apply the MVC pattern to it.

    As soon as we start using it, we immediately think - how can we arrange the scripts of our solution so that everything is at hand? To do this, let's place each of the three sections of our MVC system in separate folders and thus get a simple directory structure in which it is easy to find what we need. In addition, we will place these three folders in the lib directory, and move it above the root www web directory:

    /lib --/controller ---- FrendCnt.php --/model ---- Frend.php ---- FrendList.php --/view ---- frendlist.php ---- frendone.php / www -- index.php -- .htaccess

    Uploading the catalog lib(containing the engine of our site) from the web directory gives us greater security, making our system inaccessible to the encroachments of the playful hands of hackers.

    Controller

    Now let's talk about everything in order. Let's start with controller, since it is the first of the three components of the pattern that encounters a client request, parses it into elements, and initializes model objects. After the model processes the data, it accepts its response and sends it to the presentation layer.

    In our simple example, the controller will be concentrated in a single FrendCnt class. We will describe it in more detail later. And now a little about the entry point into the web application - this, of course, will be a file index.php. In it, we will determine the starting point for connecting our scripts. Let's create an instance of the controller and call a method on it that will begin processing the HTTP request and determine what to do next.

    Listing No. 1 (file index.php):

    $baseDir = dirname(__FILE__) . "/.."; include_once($baseDir . "/lib/controller/FriendCnt.php"); $controller = new FriendCnt(); $controller->invoke();

    Now about the controller. For us, this is the FriendCnt class. You have already noticed that an instance of this class is created in index.php. It has only one invoke() method, which is called immediately after the instance is created. In the controller constructor, an object is created based on the model class - FrendList (list of friends) for operating with data.

    In the invoke() function, based on the incoming HTTP request, a decision is made: what data is required from the model. Then the method that retrieves the data is called. Next, templates for display are connected, to which data is transferred from the controller. Note that the controller doesn't know anything about the database or how the page is rendered.

    Listing No. 2 (controller file FriendCnt.php):

    Require_once($baseDir . "/lib/model/FriendList.php"); class FriendCnt ( public $oFriendList; public function __construct() ( $this->oFriendList = new FriendList(); ) public function invoke() ( global $baseDir; $oFriendList = $this->oFriendList; if(isset($_GET ["key"])) ( $oFriendList->setKey($_GET["key"]); $oFriend = $oFriendList->fetch(); include $baseDir . "/lib/view/friendone.php"; ) else ( $aFriend = $oFriendList->fetch(); include $baseDir . "/lib/view/friendlist.php"; ) ) )

    Model and Entities

    Model- this is an image of reality, from which only what is needed to solve the problem is taken. The model focuses on the logic of solving the main problem. Many call this business logic; it bears a great responsibility:

    • Saving, deleting, updating application data. This is implemented through database operations or through calls to external web services.
    • Encapsulation of all application logic. Absolutely all application logic, without exception, must be concentrated in the model. There is no need to move any part of the business logic into a controller or view.

    Our model includes two scripts, each of which has its own class defined. The central FriendList class and the Friend entity class. In the central class, data manipulation occurs: receiving data from the controller and processing it. The entity class serves as a container for transferring data between the model and the view, and also defines its format. In a good implementation of the MVC pattern, entity classes should not be referenced in the controller, and they should not contain any business logic. Their purpose is only to store data.
    In the FriendList class, which works with a list of friends, we created a function that models the interaction of this class with the database. The getFriendList() method returns an array of objects created from the Friend class. To ensure ease of working with data, a function was also created that indexes an array of objects. Only two methods were available to the controller: setKey() - sets the key field by which detailed data about the friend is returned; fetch() - returns either a specific object or the entire list of friends.

    Listing No. 3 (model file FriendList.php):

    Require_once($baseDir . "/lib/model/Friend.php"); class FriendList ( private $oneKey; private function getFriendList() ( return array(new Friend("Alexander", "1985", " [email protected]"), new Friend("Yuri", "1987", " [email protected]"), new Friend("Alexey", "1989", " [email protected]"),); ) private function getIndexedList() ( $list = array(); foreach($this->getFriendList() as $val) ( $list[$val->getKey()] = $val; ) return $list; ) public function setKey($key) ( $this->oneKey = $key; ) public function fetch() ( $aFriend = $this->getIndexedList(); return ($this->oneKey) ? $aFriend [$this->oneKey] : $aFriend; ) )

    Depending on the implementation of Entity objects, data about it can be formatted as an XML document or a JSON object.

    Listing #4 (Friend.php entity file):

    Class Friend ( private $key; private $name; private $yearOfBirth; private $email; public function __construct($name, $yearOfBirth, $email) ( $this->key = md5($name . $yearOfBirth . $email) ; $this->name = $name; $this->yearOfBirth = $yearOfBirth; $this->email = $email; ) public function getKey() ( return $this->key; ) public function getName() ( return $this->name; ) public function getYearOfBirth() ( return $this->yearOfBirth; ) public function getEmail() ( return $this->email; ) )

    Performance

    Now we need to present the data in the best possible light for the user.

    It's time to talk about the Presentation. Depending on the task, data can be passed to the view in different formats: simple objects, XML documents, JSON objects, etc. In our case, an object or an array of objects is passed. At the same time, we did not worry about the output of the base layer - what applies to the footer and header of the generated page, this code is repeated in both view files. But for our small example this is not important.

    The main point here is to show that the view is separate from the controller and model. In this case, the controller is responsible for transferring data from the model to the view.

    In our example, the view contains only two files: one for displaying detailed information about a friend and one for displaying a list of friends.

    Listing No. 5 (file for displaying the list of friends friendlist.php):

    My friends

    YearProjectDescription
    " .$row ["Year" ]."" .$row ["Site" ]."" .$row ["Description" ]."
    Name Year of birth
    getKey() ?>">getName() ?> getYearOfBirth() ?>

    Listing No. 6 (file for displaying the list of friends friendone.php):

    <?php echo $oFriend->getName() ?> : My friend getName() . "
    "; echo "Year of birth: " . $oFriend->getYearOfBirth() . "
    "; echo "Email: " . $oFriend->getEmail() . "
    "; ?> List

    If you transfer all this code to a web server, then as a result you will get a microsite not of two pages (judging by the number of presentation files), but of four. The first one will show a list of friends, and the other three will show detailed information for each friend.

    We could implement detail browsing using AJAX, then we would have just one page, and we would render part of the view via JSON objects directly on the clients' computers. There are a lot of options in this regard.

    This is a simplified example of a web application based on the MVC pattern. But already on it you can see a lot of possibilities. We have already included flexibility and scalability as advantages. Additional advantages will be the ability to standardize coding, ease of detecting and correcting errors, and the rapid entry of new developers into the project. In addition, you can change the way entities are stored in your application using third-party web services and cloud databases. The only downside is a slight increase in the volume of scripts. And so, continuous advantages. So, use it for your health.

    Here are the project files, download and compare:

    So how? What thoughts? Let's comment, don't be shy.

    Good afternoon, dear colleagues. In this article I would like to talk about my analytical understanding of the differences between the MVC, MVP and MVVM patterns. I was prompted to write this article by the desire to understand modern approaches to the development of large software and the corresponding architectural features. At the current stage of my career ladder, I am not a direct developer, so the article may contain errors, inaccuracies and misunderstandings. Intrigued by how analysts see what programmers and architects are doing? Then welcome to cat.

    Links
    The first thing I would like to start with are links to external materials that guided me in the process of writing this article:
    Introduction
    In a time when the sun was shining brighter and the grass was greener, a team of students like the author of this article developed software by writing hundreds of lines of code directly into the product interface. Sometimes services and managers were used to work with data, and then the solution was obtained using the Document-View pattern. Supporting such code required enormous costs, since a new developer had to be trained (told) what code was responsible for what in the product, and there was no talk of any unit testing. The development team is 4 people who sit in one room.
    Time passed, work changed. The applications being developed became larger and more complex, and from one cohesive team of developers there became many different teams of developers, architects, usability specialists, designers and PMs. Now everyone is responsible for their own area: GUI, business logic, components. A department of analysis, testing, and architecture appeared. The cost of software development has increased hundreds and even thousands of times. This approach to development requires a stable architecture that would synchronize different functional areas of the product with each other.
    Patterns
    Given the goal of reducing labor costs for developing complex software, we assume that it is necessary to use ready-made unified solutions. After all, templated actions facilitate communication between developers, allow you to refer to well-known designs, and reduce the number of errors.
    According to Wikipedia, a design pattern is a repeatable architectural design that represents a solution to a design problem within some frequently occurring context.

    Let's start with the first main thing - Model-View-Controller. MVC is a fundamental pattern that has found its way into many technologies, given rise to new technologies, and makes life easier for developers every day.

    The MVC pattern first appeared in the SmallTalk language. The developers had to come up with an architectural solution that would separate the graphical interface from the business logic, and the business logic from the data. Thus, in its classic version, MVC consists of three parts, which give it its name. Let's look at them:

    Model
    A Model is usually understood as a part containing the functional business logic of an application. The model must be completely independent from the rest of the product. The model layer doesn't need to know anything about the design elements or how it will be rendered. A result is achieved that allows you to change the presentation of data, how they are displayed, without touching the Model itself.

    The model has the following features:

    • The model is the business logic of the application;
    • The model has knowledge about itself and does not know about controllers and views;
    • For some projects, the model is simply a data layer (DAO, database, XML file);
    • For other projects, the model is a database manager, a set of objects, or simply application logic;
    View
    The responsibilities of the View include displaying the data received from the Model. However, the view cannot directly influence the model. We can say that a view has read-only access to the data.

    The representation has the following characteristics:

    • The view implements the display of data that is obtained from the model in any way;
    • In some cases, the view may have code that implements some business logic.
    Examples of presentation: HTML page, WPF form, Windows Form.
    Differences between MVC & MVVM & MVP
    The most common types of MVC pattern are:
    • Model-View-Controller
    • Model-View-Presenter
    • Model-View-View Model

    Let's consider and compare each of them.

    Model-View-Presenter

    This approach allows you to create a representation abstraction. To do this, you need to select a view interface with a specific set of properties and methods. The presenter, in turn, receives a reference to the interface implementation, subscribes to presentation events, and modifies the model upon request.

    Signs of a presenter:

    • The view interacts directly with the presenter by calling appropriate functions or events on the presenter instance;
    • The Presenter interacts with the View by using a special interface implemented by the View;
    • One presenter instance is associated with one display.

    Implementation:
    Each view must implement the corresponding interface. The presentation interface defines the set of functions and events needed to interact with the user (for example, IView.ShowErrorMessage(string msg)). The presenter must have a reference to the implementation of the corresponding interface, which is usually passed in the constructor.
    The presentation logic must have a reference to the presenter instance. All view events are passed to the presenter for processing and are almost never processed by the presentation logic (including the creation of other views).

    Usage example: Windows Forms.

    Model-View-View Model


    This approach allows you to associate view elements with properties and events of the View model. It can be argued that each layer of this pattern does not know about the existence of another layer.

    Features of the View model:

    • Two-way communication with presentation;
    • A view model is an abstraction of a view. Usually means that the properties of the view are the same as the properties of the View/Model
    • The View model does not have a reference to the view interface (IView). Changing the state of the View model automatically changes the view and vice versa, since the data binding mechanism is used (Bindings)
    • One instance of a View model is associated with one view.

    Implementation:
    When using this pattern, the view does not implement the corresponding interface (IView).
    The view must have a link to the data source (DataContex), which in this case is the View model. View elements are bound to the corresponding properties and events of the View model.
    In turn, the View model implements a special interface that is used to automatically update view elements. An example of such an interface in WPF would be INotifyPropertyChanged.

    Usage example: WPF

    Model-View-Controller

    The main idea of ​​this pattern is that both the controller and the view depend on the model, but the model does not depend on these two components.

    Controller characteristics

    • The controller determines which view should be displayed at the moment;
    • View events can only affect the controller. The controller can affect the model and define another view.
    • Multiple views are possible for just one controller;

    Implementation:
    The controller intercepts the event from the outside and, in accordance with the logic embedded in it, reacts to this event by changing the Model by calling the appropriate method. After a change, the Model uses the event that it has changed, and all the View events subscribed to this, having received it, turn to the Model for updated data, after which they are displayed.

    Usage example: MVC ASP.NET

    Summary
    The implementation of MVVM and MVP patterns, at first glance, looks quite simple and similar. However, for MVVM the binding of the view to the View-model is done automatically, but for MVP it is necessary to program
    MVC seems to have more control over the view.
    General rules for choosing a pattern
    MVVM
    • Used in a situation where data binding is possible without the need to introduce special view interfaces (i.e. there is no need to implement IView);
    • A common example is WPF technology.
    MVP
    • Used in a situation where data binding is not possible (Binding cannot be used);
    • A common example would be using Windows Forms.
    MVC
    • Used in a situation where communication between the view and other parts of the application is not possible (and you cannot use MVVM or MVP);
    • A common use case is ASP.NET MVC.
    Conclusion
    In conclusion, the author of this article would like to point out that strictly sticking to just one pattern is not always the best choice. For example, imagine that you would like to use MVVM to develop applications using Windows Forms through the Bindings property of controls. Your goal is to separate the presentation from the business logic and the logic that connects them. The application should be easy to test and support, and understandable for analysts (after all, to the question “how is the performance of a hard drive measured” there is only one correct answer - in Joules (abstract example Model -> Views)).

    Thank you very much for your time, enjoy reading!

Share with friends or save for yourself:

Loading...