OOP and MVC are two separate things. MVC is a design standard where it basically separates the layers of responsibilities where M represents the business logic, C represents the controller and V represents the interface. It is possible, without any problem, to structure codes in the MVC standard without using object orientation. The creator of PHP himself, Rasmus Lerdorf, 10 years ago, wrote an article from which he was misinterpreted so he rewrote another article available on the link: https://toys.lerdorf.com/archives/38-The-no-framework-PHP-MVC-framework.html
The criticisms he received were actually from haters who disliked what he commented in the original article. In the original article he literally chopped wood (made severe criticism) to the "irrational" use of OOP in PHP. Then he saw, he received a storm of haters who did not understand what he meant, as if he was saying that OOP was something useless and unnecessary.
Finally, when you think about MVC, don’t think about OOP. MVC isn’t even an object. It is merely a design standard for organizing codes and routines.
Most likely you already use some MVC unintentionally. Maybe with one violation or another, but anyway you already do it. For example, if you write PHP codes without mixing with CSS, HTML, JS, among others, you are already making a good separation between the view and the controllers. The most confusing point is knowing how to separate what the controller is and what the model is.
Part of the question you asked emphasizes the OOP, however, as this is not the focus in question, I will restrict the answer to the MVC.
The existing answers already say enough, therefore, not to repeat the obvious, we go directly to a practical and simple example, without use of classes. Something that any early PHP programmer who knows at least how to use variables and functions, can understand.
<?php
/*
Bootstrap
*/
date_default_timezone_set('Asia/Tokyo');
ini_set('error_reporting', E_ALL);
ini_set('log_errors', true);
ini_set('html_errors', false);
ini_set('display_errors', true);
define('CHARSET', 'UTF-8');
ini_set('default_charset', CHARSET);
mb_http_output(CHARSET);
mb_internal_encoding(CHARSET);
/*
Controller
*/
function Control()
{
$m = null;
if (isset($_REQUEST['m'])) {
$m = trim($_REQUEST['m']);
}
if (empty($m)) {
$m = 'Foo';
}
/*
Call the model
*/
$f = 'Model'.$m;
$data = $f();
/*
Call the view
*/
$f = 'View'.$m;
$f($data);
}
/*
Foo Model
*/
function ModelFoo()
{
return array(
'body' => array('a', 'b', 'c'),
'header_charset' => CHARSET,
'header_content_type' => 'text/html'
);
}
/*
Foo View
*/
function ViewFoo($data)
{
header('Content-Type: '.$data['header_content_type'].'; charset='.$data['header_charset']);
echo '<html>
<body>
Foo Page<br />'.
$data['body'][0].$data['body'][1].$data['body'][2].'
</body>
</html>';
}
/*
Bar Model
*/
function ModelBar()
{
return array(
'body' => array('a', 'b', 'c'),
'header_charset' => CHARSET,
'header_content_type' => 'text/html'
);
}
/*
Bar View
*/
function ViewBar($data)
{
header('Content-Type: '.$data['header_content_type'].'; charset='.$data['header_charset']);
echo '<html>
<body>
Bar Page<br />'.
$data['body'][0].$data['body'][1].$data['body'][2].'
</body>
</html>';
}
/*
Start the engine
*/
Control();
/*
Para executar, acesse pelo browser
http://localhost/mvc/?m=Bar
ou http://localhost/mvc/
e veja o resultado desse mini framework.
*/
In the example I did no validation to avoid filling with too many codes and demonstrating the MVC layers more clearly. Therefore, be aware that you need to create consistent and secure code. The above example is merely illustrative.
In this application we have 2 models and each model has 1 view, so 2 models and 2 views.
There is a single controller, which decides what to do with the input from the user. GET/POST requests. In the above example I simplified with $_REQUEST
.
A very common problem to find is the misuse of the pattern where apply parts of the business model within the controller or parts of the view within the model or even the controller.
Examples of very common errors
Violating the controller
function anti_injection_sql($str){
// Suponha que aqui tenha uma rotina para tratar injeções sql, das mais bizarras e sem sentido.
return $str;
}
function Control()
{
$m = null;
if (isset($_REQUEST['m'])) {
$m = trim($_REQUEST['m']);
}
/*
Por quê fazer filtragem contra sql injection aqui?
Não é responsabilidade do Controller, a menos que esse parâmetro seja usado pelo controller para buscar no banco de dados algo específico somente do controller.
Mas enfim, normalmente é desnecessário. Está apenas violando o MVC e corrompendo a entrada original.
Como aqui não há nenhuma consulta a banco de dados, não faz sentido.
*/
$m = anti_injection_sql($m);
if (empty($m)) {
$m = 'Foo';
}
Violating the model
function ModelFoo()
{
/*
Observe o código HTML `<b></b>` dentro do array que será enviado para a view. Ainda estamos no Model, não deveria ter nada de HTML formatando o conteúdo da view aqui.
*/
return array(
'body' => array('<b>a</b>', 'b', 'c'),
'header_charset' => CHARSET,
'header_content_type' => 'text/html'
);
}
Violating the view
/*
Bootstrap
*/
date_default_timezone_set('Asia/Tokyo');
ini_set('error_reporting', E_ALL);
/*
Aqui dispara um cabeçalho que informa o tipo do conteúdo e conjunto de caracteres.
Isso torna a aplicação inteira "engessada" pois se precisar exibir uma view com um content-type ou charset diferente?
E se precisar usar funções como session_start() que conflitarão com cabeçalhos previamente despachados?
Nesses casos, com certeza vai acabar resolvendo com mais gambiarras e, é o que acontece normalmente.
O cabeçalho faz parte da view, portanto, é responsabilidade dessa camada.
*/
header('Content-Type: text/html; charset=UTF-8);
The view is dumb?
Here we also have a little confusion, because in the example we mixed PHP with HTML in the view and at the same time stated that in MVC should not mix PHP with HTML.
The fact is, the view needs to be compiled somehow. Here, as we deal with PHP, we use PHP itself to compile. In order to make the example as simple as possible, I avoided using a complex example with a template compiler as it would make the example too complex. Basically, the view can’t be "dumb". After all, HTML is not a programming language where we can use flow control structure, loops, among others.
Alternatively we can use Javascript to control the layout of the data in the view, so the view templates would be 100% free of PHP code.
For this there are tools like jquery template, mustache, handlebars, among others.
As not everything are flowers we find a flaw, because to build a website we need to worry about SEO (search engines). Search engines do not compile Javascript making it a problem to use Javascript as a template engine. But at that point we enter into another discussion that is not the case discuss here.
In short, don’t take "don’t mix php with html" literally. This should be interpreted as "don’t mix the MVC layers".
function ViewFoo($data)
{
header('Content-Type: '.$data['header_content_type'].'; charset='.$data['header_charset']);
echo '<html>
<body>
Foo Page<br />'.
$data['body'][0].$data['body'][1].$data['body'][2].'
</body>
</html>';
}
Eventually there will be situations where it will be necessary to invoke routines within the view. It would be a violation to write routines in the view and so something was created that we know as "helpers". It’s an elegant way to rape, to sniff around the view in an acceptable way.
Helpers make it easy to mount views, such as HTML headers, mounting menus, links, etc.
Performance
You must have noticed the parameter passages in the controller:
/*
Call the model
*/
$f = 'Model'.$m;
$data = $f();
/*
Call the view
*/
$f = 'View'.$m;
$f($data);
In procedural-style programming, we wouldn’t do so many loops and save processes, memory, etc. So why should I give up the performance of simpler code to write more complex code that will consume more memory and processes?
The whole thing about the OOP concept is to intelligently reuse routines. In fact, you start writing less code. It focuses more on business logic (Model) than on control processes. In procedural programming, we practically reinvent the wheel for each new business logic. These are repetitive processes that, when you don’t have an organization, turn maintenance into a nightmare.
In the code snippet above, for example, we could eliminate the use of a new variable $data = $f();
trading it for a class property.
Thus avoiding transporting the same data in different objects.
When to use? Should I use? Where would OOP enter?
As you can see, in this ridiculous little framework we find a lot of things that need implementations making it quite complex. Imagine in an average system, how big is the complexity of writing organized and consistent code?
In structural programming, the amount of codes and concepts become unviable for maintenance even in small systems. That is why there is OOP and its various concepts and paradigms. The decision to use an X or Y concept depends on the programmer. There is no law that says how we should write the codes. What exists are recommendations of what to do and what to apply in a situation A or B.
Obviously, let’s not overreact. If you need to create a 1-page HTML site with a 3-field contact form, it’s obvious you won’t need to use OOP. A simple $_POST
, isset()
, if else
and mail()
already resolves.
MVC in PHP is for the guy to think he’s doing the right thing because he heard it in college, or in the X book he bought I don’t know where. Someone saw this in another language, and thought that in PHP it would work the same, but that not all languages work the same way. Meanwhile, the people who understand PHP do normal scripts in a good way, and the thing comes out faster and gives less maintenance. Academicism in scripting language only makes sense if there really is a need. 80% to 90% of the codes I see with MVC and OOP in PHP are horror shows. The other 10 to 20% are not for qq a.
– Bacco
What is MVC?, How to implement the MVC standard in PHP and It is advantageous to use the MVC standard in small applications?
– rray
PS: I voted for the question because it is a valid doubt. My first comment is a protest against the modinhas, and not against the question. Which, by the way, I think should be done by every programmer who invents to adopt some practice.
– Bacco
I only cited frameworks because of the use of Composer in most of the MVC tutorials I’ve seen. I completely agree with @Bacco (except about OOP, which in PHP is good for creating libraries, otherwise it was a waste of time for language developers)For me, it’s better to have a well-structured, organized code than to follow a 'rule' that gives you more work. From what I understand, then it’s kind of a waste of time. Thanks for the comments, I will wait for answers, but only for the comments I’ve made the decision not to use MCV in PHP.
– Leonardo
@Bacco, you’re absolutely right. My teacher inserted this concept in php for us, at first it seemed something "stylish", cool, but then I realized that I had no advantage, at least for small and academic jobs. It is an academic fad to insert a concept anyway without delving into it.
– user28595