1 Востаннє редагувалося Tenevyk (07.04.2016 23:43:07)

Тема: MVC. Допомога у розумінні

Всім привіт!

Мені надзвичайно потрібна ваша допомога у розумінні, як правильно має працювати сайт на MVC. Зараз намагаюся зробити одне завдання (але не прошу допомоги у вирішенні, лише у розумінні MVC), яке потрібно зробити без фреймворків (умова така).

Коротше кажучи, в мене є отака

структура

http://image.prntscr.com/image/806963062dbc47ea93bb4f586c9792a6.png

Як видно, є контролер MoviesController та модель Movie.
Я маю пошукову форму у views/index.php . Мені потрібно туди ж передати масив даних, який я можу отримати з моделі. Я викликаю цю модель у контролері.

Отже, в мене два питання:
1) До якого файлу потрібно звертатися у формі (action="")?До самого контролеру (тобто action="controllers/MoviesController"? Чи до чого?
2) Як мені передати масив даних у views/index.php з самого контролера?

Дякую.

P.S. Я знаходив багато підказок щодо роутингу, але я не розумію просто, як саме реалізувати його в такому маленькому завданні як моє. Тобто я взагалі не розумію, що писати, аби роутинг цей спрацьовував.
P.P.S. Продивився серію відео Віктора Зінченка по створенню власного магазину на основі MVC, але подивитися подивився, а суті саме роботи роутингу не зрозумів. Хочеться самому навчитися таке писати.

Подякували: leofun01, 221VOLT2

2

Re: MVC. Допомога у розумінні

Вам потрібен ще один компонент функції якого зазвичай і виконують фреймворки. Можете його і називати роутером. Зазвичай це індекс файл в паблік частині сайту. Апач повинен переадресовувати на нього усі запити. А цей файл в залежності від урл повинен шукати відповідну функцію в відповідному контролері і потрібний для нього вю файл. І передавати дані з контролеру у вю. Відповідно у фреймворках він контролює рівні доступу і загальний лейаут сайту, як ото хедери і футери, які є спільні для кожної сторінки.

Подякували: koala1

3

Re: MVC. Допомога у розумінні

Vo_Vik написав:

Вам потрібен ще один компонент функції якого зазвичай і виконують фреймворки. Можете його і називати роутером. Зазвичай це індекс файл в паблік частині сайту. Апач повинен переадресовувати на нього усі запити. А цей файл в залежності від урл повинен шукати відповідну функцію в відповідному контролері і потрібний для нього вю файл. І передавати дані з контролеру у вю. Відповідно у фреймворках він контролює рівні доступу і загальний лейаут сайту, як ото хедери і футери, які є спільні для кожної сторінки.

А можете, будь ласка, привести який-небудь приклад структури та коду? Наскільки я розумію, ви говорите про фронт контролер. Але що саме там писати?Як потім направляти всі запити туди? Наприклад, з моїми Movie та MoviesController...

4

Re: MVC. Допомога у розумінні

Доброго дня
Колись допомагав знайомому у написанні елементарного MVC тож ділюся з Вами.
Сподіваюся допоможе у розумінні. Роутер там теж є.

Post's attachments

mvc_com_v2.zip 5.64 kb, 299 downloads since 2016-04-08 

Подякували: leofun01, Tenevyk2

5 Востаннє редагувалося iovchynnikov (08.04.2016 09:15:37)

Re: MVC. Допомога у розумінні

Esforeal написав:
Vo_Vik написав:

Вам потрібен ще один компонент функції якого зазвичай і виконують фреймворки. Можете його і називати роутером. Зазвичай це індекс файл в паблік частині сайту. Апач повинен переадресовувати на нього усі запити. А цей файл в залежності від урл повинен шукати відповідну функцію в відповідному контролері і потрібний для нього вю файл. І передавати дані з контролеру у вю. Відповідно у фреймворках він контролює рівні доступу і загальний лейаут сайту, як ото хедери і футери, які є спільні для кожної сторінки.

А можете, будь ласка, привести який-небудь приклад структури та коду? Наскільки я розумію, ви говорите про фронт контролер. Але що саме там писати?Як потім направляти всі запити туди? Наприклад, з моїми Movie та MoviesController...

Роутер робиться наступним чином:
1) Усі запити до Вашого сайту перенаправляються до одного скрипку - Роутера, або файлу, що облуговує Роутер. Це можна зробити через налаштування самого http сервера. Це можна зробити, на приклад, через файл .htaccess (https://en.wikipedia.org/wiki/.htaccess), який має бути у рутовому каталозі Вашого сайту. З мого прикладу, такий файл має таку інформацію:
RewriteEngine on
RewriteRule . index.php [L]
Що дослівно означає "переписати усі запити до . (до цього місця) до index.php"

2) Далі необхідна логіка, що розбирає адресу URL і визначає який треба викликати контролер і акцію. З мого прикладу:

class Router {
    const DEFAULT_CONTROLLER = 'index';
    const DEFAULT_ACTION = 'index';

    public static function run() {
        $url = $_SERVER['REQUEST_URI']; // Читаємо URL

        $route = array('controller' => Router::DEFAULT_CONTROLLER, 'action' => Router::DEFAULT_ACTION); // Визначаємо акцію і контролер за замовчуванням 

        // Парсуємо і визначаємо акцію і контролер за такою схемою mysite.com/controller_name/action_name
        $url = explode('/', $url);
        $url = array_filter($url);

        if (count($url) > 1) {
            $route['controller'] = $url[1];
            $route['action'] = $url[2];
        } else if (count($url) > 0) $route['controller'] = $url[1];

        // Визначаємо файл де є наш контроллер
        $controllerClass = $route['controller'] . 'Controller';
        $controllerPath = APPLICATION_PATH . '/controllers/' . $controllerClass . '.php';

        if (!is_file($controllerPath)) throw new Exception("No such controller!");

        require $controllerPath;

        if (!class_exists($controllerClass)) throw new Exception("No class has been found!");

        // Створюємо об'єкт контролера 
        $controllerObject = new $controllerClass();
        $actionName = $route['action'] . 'Action'; // Визначаємо назву акції - функції у класі, за конвенцією "назваакціїїAction"

        if (!method_exists($controllerObject, $actionName)) throw new Exception("No action!");

        $controllerObject->$actionName(); // Викликаємо акцію.
    }
}

Тобто для адреси mysite.com/user/list:

$controllerClass = 'UserController';
$controllerPath = APPLICATION_PATH . '/controllers/UserController.php';
$actionName = 'listAction';

А контролер буде виглядати так

class UserController{
    public function listAction() {
        // shos
    }
}

3) З мого прикладу, так як всі запити перенаправляються до index.php, маємо там запустити цей роутер:

require LIB_PATH . '/Router.php'; // завантажуємо клас
Router::run(); // запускаємо роутер
Подякували: leofun01, Tenevyk2

6

Re: MVC. Допомога у розумінні

Відповідаючи на Ваші запитання:

Esforeal написав:

Отже, в мене два питання:
1) До якого файлу потрібно звертатися у формі (action="")?До самого контролеру (тобто action="controllers/MoviesController"? Чи до чого?
2) Як мені передати масив даних у views/index.php з самого контролера?
Дякую.

1) action - функція у MoviesController. Приклад див. вище.
2) Розповім знову ж таки на моєму прикладі:

class View {
    public $data;
    private $path;

    public function __construct($path) {
        $path = APPLICATION_PATH . '/view/' . $path . '.html';

        if (!is_file($path))
            throw new InvalidArgumentException("Np view " . $path);

        $this->path = $path;
        $this->data = new ArrayObject();
    }

    public function render() {
        include $this->path;
    }
} 

Дуже простий клас, що має лише масив для переховування даних ($this->data = new ArrayObject();) і один метод що "малює" в view - тобто робить include. Так як include всмоктує файл у цей самий клас, усі дані, що належать View також доступні у $this->path - view і можна спокійно робити щось такого:

// application\view\index.html
<h1> Hello <?= $this->data->world; ?> </h1>

Тоді у IndexController.php користуємося class View таким чином:

class IndexController {
    public function indexAction() {
        $view = new View('index');
        $view->data->world= "WORLD! AWESOME MVC!";
        $view->render();
    }
}

І на екрані у нас з'явиться:

<h1> Hello WORLD! AWESOME MVC! </h1>
Подякували: leofun01, Tenevyk2

7 Востаннє редагувалося Tenevyk (08.04.2016 12:06:04)

Re: MVC. Допомога у розумінні

Дякую. Блін, мені чомусь важко дається розуміння, сам від себе такої тупоголовості не очікував.

1) Я так зрозумів, що у мене

$view->data->var

якщо мені потрібно отримати список фільмів, має бути

$view->data->var = Movie::getMoviesList();

Якщо так, то як мені, наприклад, передати $_POST['title'] з view до контролера?
2) А якщо я створю ще якусь сторінку у view, наприклад, about.html, то мені потрібно буде робити AboutController? Чи ні?

Чи є у вас можливість у скайпі поговорити?

P.S. Ще знайшов отаке пояснення.

8 Востаннє редагувалося iovchynnikov (08.04.2016 13:20:14)

Re: MVC. Допомога у розумінні

Esforeal написав:

Дякую. Блін, мені чомусь важко дається розуміння, сам від себе такої тупоголовості не очікував.

1) Я так зрозумів, що у мене

$view->data->var

якщо мені потрібно отримати список фільмів, має бути

$view->data->var = Movie::getMoviesList();

Якщо так, то як мені, наприклад, передати $_POST['title'] з view до контролера?
2) А якщо я створю ще якусь сторінку у view, наприклад, about.html, то мені потрібно буде робити AboutController? Чи ні?

Чи є у вас можливість у скайпі поговорити?

P.S. Ще знайшов отаке пояснення.

Не треба на себе лаятися, інші ще встигнуть :) Нічого страшного не трапилося, це вже й таке все просте як 1+1 для новачків.
1)

$view->data->var = Movie::getMoviesList();

так, є гуд
Передавати з view нічого не треба, це ламає усю парадигму. Дані у моделях, а вже контролери передають дані вью. view тільки для висвітлювання даних, верства презентації. Можна спокійно зробити так:

    class IndexController {
        public function indexAction() {
            $data = $_POST['title'];
        }
    }

2) Щодо мого прикладу, то Ви можете вибирати який файл відрендерувати будь-де:

    class IndexController {
        // обслуговує такі запити: 
        //     1) mysite.com/ (бо за замовчування контролер має назву Index і акцію index)
        //     2) mysite.com/index (бо за замовчування контролер має акцію index)   
        //     3) mysite.com/index/index
        public function indexAction() {
            new View('index.html')->render(); // завантажить в'ю mainPage.html і намалює його
        }

        // обслуговує mysite.com/index/about
        public function aboutAction() {
            new View('about.html')->render(); // завантажить в'ю about.html і намалює його
        }
    }

Але так, якщо треба щоб було mysite.com/about то треба AboutController, бо перша вартість після / означає назву контролера:

    class AboutController {
        // обслуговує mysite.com/about  (без ще /index, бо за замовчування контролер має акцію index)   
        public function indexAction() {
            new View('about.html')->render(); // завантажить в'ю about.html і намалює його
        }
    }

Мій приклад досить прямий і робить жорстко так, але як правило, більш розвинуть Роутери мають можливість керувати стежками гнучкіше і додавати свої шляхи. На приклад, можна дописати мій роутер так, що у index.php можна зробити:

    require LIB_PATH . '/Router.php'; // завантажуємо клас
    Router::route('/about', array('controller' => 'index', action => 'about')); // керувати запити до /about до IndexController і aboutAction()
    Router::run(); // запускаємо роутер

Тоді можна не творити новий контролер і зробити так:

    class IndexController {
        // обслуговує такі запити: 
        //     1) mysite.com/ (бо за замовчування контролер має назву Index і акцію index)
        //     2) mysite.com/index (бо за замовчування контролер має акцію index)   
        //     3) mysite.com/index/index
        public function indexAction() {
            new View('index.html')->render(); // завантажить в'ю mainPage.html і намалює його
        }

        // обслуговує mysite.com/index/about
        public function aboutAction() {
            new View('about.html')->render(); // завантажить в'ю about.html і намалює його
        }

        // обслуговує mysite.com/about
        public function aboutAction() {
            new View('about.html')->render(); // завантажить в'ю about.html і намалює його
        }
    }

Щодо скайпу - вибачаюсь, але не маю можливості. Зараз у довгій дорозі, інет не потягне :)

Подякували: Tenevyk, leofun012

9

Re: MVC. Допомога у розумінні

iovchynnikov написав:

Тоді можна не творити новий контролер і зробити так:

    class IndexController {
        // обслуговує такі запити: 
        //     1) mysite.com/ (бо за замовчування контролер має назву Index і акцію index)
        //     2) mysite.com/index (бо за замовчування контролер має акцію index)   
        //     3) mysite.com/index/index
        public function indexAction() {
            new View('index.html')->render(); // завантажить в'ю mainPage.html і намалює його
        }

        // обслуговує mysite.com/index/about
        public function aboutAction() {
            new View('about.html')->render(); // завантажить в'ю about.html і намалює його
        }

        // обслуговує mysite.com/about
        public function indexAction() {
            new View('about.html')->render(); // завантажить в'ю about.html і намалює його
        }
    }

Це як?У одному класі два однакових методи indexAction?

Ось такий код Router-a у того ж Зінченка
class Router
{

    /**
     * Свойство для хранения массива роутов
     * @var array 
     */
    private $routes;

    /**
     * Конструктор
     */
    public function __construct()
    {
        // Путь к файлу с роутами
        $routesPath = ROOT . '/config/routes.php';

        // Получаем роуты из файла
        $this->routes = include($routesPath);
    }

    /**
     * Возвращает строку запроса
     */
    private function getURI()
    {
        if (!empty($_SERVER['REQUEST_URI'])) {
            return trim($_SERVER['REQUEST_URI'], '/');
        }
    }

    /**
     * Метод для обработки запроса
     */
    public function run()
    {
        // Получаем строку запроса
        $uri = $this->getURI();

        // Проверяем наличие такого запроса в массиве маршрутов (routes.php)
        foreach ($this->routes as $uriPattern => $path) {

            // Сравниваем $uriPattern и $uri
            if (preg_match("~$uriPattern~", $uri)) {

                // Получаем внутренний путь из внешнего согласно правилу.
                $internalRoute = preg_replace("~$uriPattern~", $path, $uri);

                // Определить контроллер, action, параметры

                $segments = explode('/', $internalRoute);

                $controllerName = array_shift($segments) . 'Controller';
                $controllerName = ucfirst($controllerName);

                $actionName = 'action' . ucfirst(array_shift($segments));

                $parameters = $segments;

                // Подключить файл класса-контроллера
                $controllerFile = ROOT . '/controllers/' .
                        $controllerName . '.php';

                if (file_exists($controllerFile)) {
                    include_once($controllerFile);
                }

                // Создать объект, вызвать метод (т.е. action)
                $controllerObject = new $controllerName;

                /* Вызываем необходимый метод ($actionName) у определенного 
                 * класса ($controllerObject) с заданными ($parameters) параметрами
                 */
                $result = call_user_func_array(array($controllerObject, $actionName), $parameters);

                // Если метод контроллера успешно вызван, завершаем работу роутера
                if ($result != null) {
                    break;
                }
            }
        }
    }

}
А це у нього роути
return array(
    // Товар:
    'product/([0-9]+)' => 'product/view/$1', // actionView в ProductController
    // Каталог:
    'catalog' => 'catalog/index', // actionIndex в CatalogController
    // Категория товаров:
    'category/([0-9]+)/page-([0-9]+)' => 'catalog/category/$1/$2', // actionCategory в CatalogController   
    'category/([0-9]+)' => 'catalog/category/$1', // actionCategory в CatalogController
    // Корзина:
    'cart/checkout' => 'cart/checkout', // actionAdd в CartController    
    'cart/delete/([0-9]+)' => 'cart/delete/$1', // actionDelete в CartController    
    'cart/add/([0-9]+)' => 'cart/add/$1', // actionAdd в CartController    
    'cart/addAjax/([0-9]+)' => 'cart/addAjax/$1', // actionAddAjax в CartController
    'cart' => 'cart/index', // actionIndex в CartController
    // Пользователь:
    'user/register' => 'user/register',
    'user/login' => 'user/login',
    'user/logout' => 'user/logout',
    'cabinet/edit' => 'cabinet/edit',
    'cabinet' => 'cabinet/index',
    // Управление товарами:    
    'admin/product/create' => 'adminProduct/create',
    'admin/product/update/([0-9]+)' => 'adminProduct/update/$1',
    'admin/product/delete/([0-9]+)' => 'adminProduct/delete/$1',
    'admin/product' => 'adminProduct/index',
    // Управление категориями:    
    'admin/category/create' => 'adminCategory/create',
    'admin/category/update/([0-9]+)' => 'adminCategory/update/$1',
    'admin/category/delete/([0-9]+)' => 'adminCategory/delete/$1',
    'admin/category' => 'adminCategory/index',
    // Управление заказами:    
    'admin/order/update/([0-9]+)' => 'adminOrder/update/$1',
    'admin/order/delete/([0-9]+)' => 'adminOrder/delete/$1',
    'admin/order/view/([0-9]+)' => 'adminOrder/view/$1',
    'admin/order' => 'adminOrder/index',
    // Админпанель:
    'admin' => 'admin/index',
    // О магазине
    'contacts' => 'site/contact',
    'about' => 'site/about',
    // Главная страница
    'index.php' => 'site/index', // actionIndex в SiteController
    '' => 'site/index', // actionIndex в SiteController
);

Я просто ще намагаюся і порівнювати, аби розуміти різницю, і як можна це все діло написати. Бо я якусь деталь залишив поза увагою, але не можу зрозуміти яку саме...Наче пазл - просто потрібно якийсь шматок вставити.

10

Re: MVC. Допомога у розумінні

Суть MVC одна, але реалізації різні.
Можете подивитись наприклад на це
http://phpmvc.ru

Подякували: leofun011

11

Re: MVC. Допомога у розумінні

Esforeal написав:
iovchynnikov написав:

Тоді можна не творити новий контролер і зробити так:

    class IndexController {
        // обслуговує такі запити: 
        //     1) mysite.com/ (бо за замовчування контролер має назву Index і акцію index)
        //     2) mysite.com/index (бо за замовчування контролер має акцію index)   
        //     3) mysite.com/index/index
        public function indexAction() {
            new View('index.html')->render(); // завантажить в'ю mainPage.html і намалює його
        }

        // обслуговує mysite.com/index/about
        public function aboutAction() {
            new View('about.html')->render(); // завантажить в'ю about.html і намалює його
        }

        // обслуговує mysite.com/about
        public function indexAction() {
            new View('about.html')->render(); // завантажить в'ю about.html і намалює його
        }
    }

Це як?У одному класі два однакових методи indexAction?

Ось такий код Router-a у того ж Зінченка
class Router
{

    /**
     * Свойство для хранения массива роутов
     * @var array 
     */
    private $routes;

    /**
     * Конструктор
     */
    public function __construct()
    {
        // Путь к файлу с роутами
        $routesPath = ROOT . '/config/routes.php';

        // Получаем роуты из файла
        $this->routes = include($routesPath);
    }

    /**
     * Возвращает строку запроса
     */
    private function getURI()
    {
        if (!empty($_SERVER['REQUEST_URI'])) {
            return trim($_SERVER['REQUEST_URI'], '/');
        }
    }

    /**
     * Метод для обработки запроса
     */
    public function run()
    {
        // Получаем строку запроса
        $uri = $this->getURI();

        // Проверяем наличие такого запроса в массиве маршрутов (routes.php)
        foreach ($this->routes as $uriPattern => $path) {

            // Сравниваем $uriPattern и $uri
            if (preg_match("~$uriPattern~", $uri)) {

                // Получаем внутренний путь из внешнего согласно правилу.
                $internalRoute = preg_replace("~$uriPattern~", $path, $uri);

                // Определить контроллер, action, параметры

                $segments = explode('/', $internalRoute);

                $controllerName = array_shift($segments) . 'Controller';
                $controllerName = ucfirst($controllerName);

                $actionName = 'action' . ucfirst(array_shift($segments));

                $parameters = $segments;

                // Подключить файл класса-контроллера
                $controllerFile = ROOT . '/controllers/' .
                        $controllerName . '.php';

                if (file_exists($controllerFile)) {
                    include_once($controllerFile);
                }

                // Создать объект, вызвать метод (т.е. action)
                $controllerObject = new $controllerName;

                /* Вызываем необходимый метод ($actionName) у определенного 
                 * класса ($controllerObject) с заданными ($parameters) параметрами
                 */
                $result = call_user_func_array(array($controllerObject, $actionName), $parameters);

                // Если метод контроллера успешно вызван, завершаем работу роутера
                if ($result != null) {
                    break;
                }
            }
        }
    }

}
А це у нього роути
return array(
    // Товар:
    'product/([0-9]+)' => 'product/view/$1', // actionView в ProductController
    // Каталог:
    'catalog' => 'catalog/index', // actionIndex в CatalogController
    // Категория товаров:
    'category/([0-9]+)/page-([0-9]+)' => 'catalog/category/$1/$2', // actionCategory в CatalogController   
    'category/([0-9]+)' => 'catalog/category/$1', // actionCategory в CatalogController
    // Корзина:
    'cart/checkout' => 'cart/checkout', // actionAdd в CartController    
    'cart/delete/([0-9]+)' => 'cart/delete/$1', // actionDelete в CartController    
    'cart/add/([0-9]+)' => 'cart/add/$1', // actionAdd в CartController    
    'cart/addAjax/([0-9]+)' => 'cart/addAjax/$1', // actionAddAjax в CartController
    'cart' => 'cart/index', // actionIndex в CartController
    // Пользователь:
    'user/register' => 'user/register',
    'user/login' => 'user/login',
    'user/logout' => 'user/logout',
    'cabinet/edit' => 'cabinet/edit',
    'cabinet' => 'cabinet/index',
    // Управление товарами:    
    'admin/product/create' => 'adminProduct/create',
    'admin/product/update/([0-9]+)' => 'adminProduct/update/$1',
    'admin/product/delete/([0-9]+)' => 'adminProduct/delete/$1',
    'admin/product' => 'adminProduct/index',
    // Управление категориями:    
    'admin/category/create' => 'adminCategory/create',
    'admin/category/update/([0-9]+)' => 'adminCategory/update/$1',
    'admin/category/delete/([0-9]+)' => 'adminCategory/delete/$1',
    'admin/category' => 'adminCategory/index',
    // Управление заказами:    
    'admin/order/update/([0-9]+)' => 'adminOrder/update/$1',
    'admin/order/delete/([0-9]+)' => 'adminOrder/delete/$1',
    'admin/order/view/([0-9]+)' => 'adminOrder/view/$1',
    'admin/order' => 'adminOrder/index',
    // Админпанель:
    'admin' => 'admin/index',
    // О магазине
    'contacts' => 'site/contact',
    'about' => 'site/about',
    // Главная страница
    'index.php' => 'site/index', // actionIndex в SiteController
    '' => 'site/index', // actionIndex в SiteController
);

Я просто ще намагаюся і порівнювати, аби розуміти різницю, і як можна це все діло написати. Бо я якусь деталь залишив поза увагою, але не можу зрозуміти яку саме...Наче пазл - просто потрібно якийсь шматок вставити.

Там, звісно, помилка. Остання акція має бути aboutAction(), звичайно. Виправив.

Як і казав, є більш круті роутери. Мій - тупий, він просто дивиться на URL і читає так: site.com/назва-контролера/назва-акції і вирішує динамічно. Натомість у того Пана, всі стежки вписані вручну і вже знані до "запускання" роутера.

Подякували: Tenevyk1

12 Востаннє редагувалося Tenevyk (08.04.2016 14:01:38)

Re: MVC. Допомога у розумінні

VTrim написав:

Суть MVC одна, але реалізації різні.
Можете подивитись наприклад на це
http://phpmvc.ru

Я так розумію, що це вже більш крутий, з namespace-ами і т.п.

iovchynnikov написав:

Як і казав, є більш круті роутери. Мій - тупий, він просто дивиться на URL і читає так: site.com/назва-контролера/назва-акції і вирішує динамічно. Натомість у того Пана, всі стежки вписані вручну і вже знані до "запускання" роутера.

Я б не називав тупим роутер, що працює - в мене взагалі зараз власноруч написаного немає, тому я навіть не порівнюю.

Просто люди пишуть оці роутери, а я не розумію логіки поетапної побудови (написання). Для уточнення:
1) Наскільки я зрозумів, завжди в роутері треба брати й використовувати

$_SERVER['REQUEST_URI']

аби знати, до якої сторінки звертається користувач (тобто яке view в нього зараз завантажено у браузері)?;
2) Потім нам потрібно перенаправити його до контролеру, який обробляє саме цю сторінку - тобто це щось типу

require ucfirst($_SERVER['REQUEST_URI']) . 'Controller'

Так?
3) В самому контролері ми викликаємо модель ucfirst($_SERVER['REQUEST_URI']), і в цей контролер же передаємо результати з моделі;
4) А оскільки контролер заінклюдений в index.php, що виступає як фронт контролер, то тому відображаються дані на сторінках. Так?

Здається, що я щось таки наплутав...

13

Re: MVC. Допомога у розумінні

Найперше, почніть із розуміння робочого потоку у MVC-фреймворках:

1. користувач робить запит типу /post/read/26;

2. початково, веб-сервер шукає відповідний каталог чи файл, "думаючи" що на сервері є каталог post, підкаталог read, а у ньому файл 26;

3. MVC-фреймворки змінюють початкові налаштування веб-серверів, щоб усі запити переадресовувались на одну сторінку, наприклад на index.php; зазвичай це робиться за допомогою відповідних конфіг-файлів, наприклад для .htaccess це:

RewriteEngine on
RewriteRule . /index.php [PT]

тепер веб-сервер абсолютно усі запити, в тому числі і наш запит /post/read/26, буде переадресовувати до однієї єдиної сторінки index.php, що знаходиться в кореневому каталозі;

4. оскільки усі запити йдуть до index.php, то із цього моменту й починається насправді робота MVC-фреймворка; це означає, що програміст в index.php отримує зокрема рядок запиту в  $_SERVER['REQUEST_URI'], на основі якого повинен написати правила, по яким фреймворк повинен реагувати на той чи інший запит, наприклад "якщо запитують /post/read/26, то вважати що запити буде обробляти контролер з іменем post, в якого є метод з іменем read, і до цього методу передавати параметр з ім’ям, скажімо, postId зі значенням 26; ось ці правила і є тією маршрутизацією (чи роутингом);

5. маршрутизатор підключає контролер, а кожен контролер заточений для роботи з певним розділом сайта, наприклад, коли запитують /post/read/26 або /comment/read/484, то як правило фреймворк має відповідні два окремі контролери Post та Comment, а також у кожному з цих контролерів є метод read;

6. контролер, як правило, робить запит до моделі;

7. модель передає дані контролеру;

8. контролер ловить дані від моделі і передає їх у вьюху.

Питання було "як передати дані із контролера у вьюху?", - та точно так само як ви передаєте дані будь-якому об’єкту. Тобто створюєте об’єкт вьюхи, у цьому об’єкті повинні бути методи, які працюють вже із "фізичними" файлами вьюхи, які в свою чергу очікують певні змінні...

Подякували: iovchynnikov, leofun01, Tenevyk3

14 Востаннє редагувалося Tenevyk (08.04.2016 22:20:57)

Re: MVC. Допомога у розумінні

Коротше кажучи, справа у часі. Я зараз на готову конструкцію накинув весь свій сайт, написав правильний контролер та метод. Зробивши це, я трохи поекспериментував, і тепер я значно краще розумію все це. Дякую усім.

15

Re: MVC. Допомога у розумінні

Ваш топік сьогодні мені пригадав, що десь у мене завалявся недороблений маленький php mvc фреймфорк, що аж захотілося його доробити :)
Можливо Вам буде у нагоді якісь клаптики з того:
https://github.com/wingsofovnia/vortex-mvc

Подякували: Tenevyk1