Что такое MVC или с чего начать писать сайт?

Не судите строго, чтобы показать пример работы MVC, я за 20 минут набросал простой код построенный на разделении пути в ссылке. Будем разбирать все на примере локальной ссылки:

http://test1.loc/product/test-product

Наша структура проекта будет состоять из 4 папок и нескольких php файлов.

Структура папок проекта

1. .htaccess:

Это самый первый файл, который срабатывает при вхождении пользователя, еще на уровне apache.

AddDefaultCharset UTF-8
Options +FollowSymLinks
RewriteEngine on

RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php?path=$1&%{QUERY_STRING}  [L]

В апаче обязательно должен быть установлен mod_rewrite.

RewriteRule ^index\.php$ - [L] // - Гласит про то, что главный файл запуска index.php. В урле его не обязательно теперь указывать.

RewriteRule ^(.*)$ /index.php?path=$1&%{QUERY_STRING}  [L] // - весь путь (product/test-product) заходит в $_GET параметр, который мы потом будем разделять на роуты.

2. index.php:

Является запускным файлом, в котором я разместил управление ошибками и запуск следующего этапа.

<?php

if (strpos($_SERVER['REQUEST_URI'], '.php') !== false) {
    header("Location:http://" . $_SERVER['SERVER_NAME']);
    exit;
}

define('ENVIRONMENT', 'development');

switch (ENVIRONMENT) {
    case 'development':
        error_reporting(E_ALL ^ E_NOTICE ^ E_WARNING);
        ini_set('display_errors', 'on');
        break;

    case 'testing':
    case 'production':
        error_reporting(E_ALL ^ E_NOTICE ^ E_DEPRECATED ^ E_STRICT ^ E_WARNING);
        ini_set('display_errors', 'off');
        break;

    default:
        header('HTTP/1.1 503 Service Unavailable.', TRUE, 503);
        exit('The application environment is not set correctly.');
}

define('DOCUMENT_ROOT', $_SERVER['DOCUMENT_ROOT']);
define('SERVER_NAME', $_SERVER['SERVER_NAME']);

require_once DOCUMENT_ROOT.'/system/router.php';
new Router();

Здесь мы объявляем константы и запускаем класс Router();

3. system/router.php:

Главный роутер, который делит ссылку на сегменты массива, и запускает контроллер по названию первого сегмента ссылки. Первый сегмент ссылки "product". Поэтому будет подгружаться product.php

<?php

if (!defined('DOCUMENT_ROOT')) {
    exit('No direct script access allowed');
}    

class Router {
    
    private $full_path ='';
    private $array_path = array();
       
    public function __construct() {
        $this->parse_path();
    }
    
    private function parse_path() {
        $this->full_path = $_GET['path'];
        $this->array_path = explode('/', $_GET['path']);
        unset($_GET['path']);
        
        if (file_exists(DOCUMENT_ROOT . '/controller/'.$this->array_path[0] . '.php')) {
            require_once DOCUMENT_ROOT . '/controller/' . $this->array_path[0] . '.php';
            
            if (class_exists($this->array_path[0])) {
                $class = new $this->array_path[0]($this->array_path);
                $class->index();
            }
        }
    }
    
}

!defined('DOCUMENT_ROOT') - не даст запустить php файл на выполнение напрямую.

parse_path() - мы разделяем урл $_GET['path'], который приходит из htaccess, на путь к файлам и запускается index().

4. controller/product.php:

Обработчик Controller. В нем будем размещать логику обработки модели и view. Первый сегмент ссылки "product". Поэтому подгружается именно этот файл. Далее, я думаю, понятно, почему подгружается "product_model.php" и "product_view.php"

<?php

if (!defined('DOCUMENT_ROOT')) {
    exit('No direct script access allowed');
}

/**
 * Контроллер обработки расчетов и логики
 */
class product {

    private $array_path = array();

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

    public function index() {
        $dataProduct = $this->connectPhp('model');    
        
        $this->includeFile('view', ['dataProduct' => $dataProduct]);
        
    }

    private function connectPhp($folder) {

        if ($this->includeFile($folder)) {

            if (class_exists($this->array_path[0] . '_' . $folder)) {
                $name = $this->array_path[0] . '_' . $folder;
                $class = new $name($this->array_path);
                return $class->index();
            }
        }
    }

    private function includeFile($folder, $data = false) {
        if (file_exists(DOCUMENT_ROOT . '/' . $folder . '/' . $this->array_path[0]. '_' . $folder . '.php')) {

            include DOCUMENT_ROOT . '/' . $folder . '/' . $this->array_path[0]. '_' . $folder . '.php';
            return TRUE;
            
        }
        return FALSE;
        
    }

}

в index() подключаем модель и подключается view, в которой используем полученую переменную $dataProduct.

5. model/product_model.php:

Эта модель будет отвечать за обработку запросов в базу. В нее будем размещать все, что касается коннектов и запросов.

<?php

if (!defined('DOCUMENT_ROOT')) {
    exit('No direct script access allowed');
}

/**
 * Модель для манипуляций с запросами в базу
 */
class product_model {   
    
    private $array_path = array();
    
    public function __construct($path) {
        $this->array_path = $path;
    }
    
    public function index() {
        $this->dbConnect();
        
        return $this->getProduct();
    }
    
    private function dbConnect() {
        // Здесь просиходит коннект к базе
    }
    
    private function getProduct () {
        // Достаем что-то касающееся товара $this->array_path[1];
        return 'Товар тест тест';
    }
    
}

Модель пустая, не стал заполнять ее, просто вернул строку для примера структуры MVC. Здесь так же запускается index() и возвращает строку.

6.view/product_view.php:

Html вывод страницы. Формируется сама view, которая будет доступна пользователю.

<html>
    <head>
        <title>Главная страница - страница обо мне</title>
    </head>
    <body>
    <center><h1><?php echo $data['dataProduct']; ?></h1></center>
    <center><h2>Описание товара</h2></center>
</body>
</html>

Передаем строку, которая пришла с модели в массиве $data. Выводим и все круто.

В итоге у нас выйдет обычная страничка.

Итоговый вывод view

Не судите строго, ведь я не ставил задачи показать правильный код или правильную структуру классов. Нашло вдохновение растолковать про MVC.

2911 2

Комментарии

Добрый день, Файзулла.
В общем view/product_view.php это и есть подключаемая фронтовая страница.
Для каждого контроллера можно создать свой фронтовый php файл. Можно поиграться с расширением структуры на namespace.
Я привел только стркутурный пример, чтобы показать что такое MVC. Так же есть еще HMVC, но не будем углубляться)
В любом случае тема эта большая и должна исходить из задачи, которую желают видеть в проекте)
Можно разобрать какай-то индивидуальный пример для Вас, отпишите через обратную связь если есть желание)
Здравствуйте.
Немного ясно стало, но не совсем... в частности как соединять фронтенд с бакэндом
я хочу сайт сделать на РНР без шаблонизатора и фрэймворка, но в MVC/
Поможете? и вам материал на сайт будет )))
Только авторизованные пользователи могут оставлять комментарии Вход

Похожие статьи

Создать и скачать CSV на PHP

Рассмотрим возможность быстрого создания CSV файла с автоматическим скачиванием файла. Рассмотрим формирование, разделители и header для возможности скачать файл.