[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: Запутался в MVC
Страницы: 1, 2, 3, 4
McLotos
Всем привет. В общем читал последнее время много разных статей по реализации MVC, везде почему-то разный подход. Я выделил 3 самых часто встречающихся, попробую описать их тут. Помогите выбрать правильный вариант (если он тут есть конечно)
1. Когда есть 1 базовый контроллер, а все остальные контроллеры его наследники. Тогда получается что router для каждого URL вызывает свой контроллер, а тот зачем-то обращается к базовому контроллеру, хотя по сути всё может сделать сам. То же с моделями, все модели наследники базовой модели (тут как раз всё понятно, только 1 класс может общаться с БД напрямую) и вызываются контроллерами конкретной страницы (1 модель для 1 страницы). При этом базовая модель просто возвращает результат запроса в виде массива, а модели классов уже обрабатывают их так как нужно. Контроллер страницы вызывает нужную ему View
2. Когда есть 1 базовый контроллер, который вызывает нужные контроллеры. (как бы наоборот, не контроллеры вызывают базовый, а базовый контроллер подключает контроллер страницы). Много моделей, наследников базовой модели и сами модели решают в каком формате отдать уже обработанные данные контроллеру, а контроллер просто передает их в вид.
3. Когда под каждую страницу есть свой контроллер и он работает самостоятельно, со своей моделью, которая является наследником базовой модели и так же как в 2 варианте просто отдает контроллеру данные. (нет никакого базового контроллера).
И как к этому всему прикручивать класс Router (и нужен ли он вообще).
И как тут использовать класс Requests, который хранит и обрабатывает данные из всех суперглобальных массивов ($_POST, $_GET, $_SERVER, $_SESSION)

_____________
программирование - инструмент для решения конкретных задач, любая попытка спроектировать что-то универсальное приведет к провалу.©paul85
В любом случае тебе прийдётся пройти путь изобретения велосипеда, который прошли другие, только причиной твоего изобретения будет непонимание принципов работы велосипеда изобретённого другими людьми.©SlavaFr
jQuery это попытка использовать АН-225 для перевозки зубочистки
chee
По верх стандартной MVC есть еще FrontController, он инициализирует Router, задает ему маршруты из конфига, берет URL из Request, ищет совпадение, если находит то возвращеет название контроллера и метода в нём, вьюхи. Ты берешь эти названия, в данном случае контроллера, отдаешь его фабрике, фабрика возвращает объект контроллера, у него ты вызываешь метод, который опять же получил от роута. Тоже самое делаешь и вьюшками.


_____________
Люди, имеющие низкий уровень квалификации, делают ошибочные выводы, принимают неудачные решения и при этом неспособны осознавать свои ошибки в силу низкого уровня своей квалификации
twin
Картинку прсовокуплю. smile.gif

_____________
Если вам недостаточно собственных заблуждений, можно расширить их мнениями экспертов.

Нужно уважать мнение оппонета. Ведь заблуждаться - его святое право.

Настаивал, настаиваю и буду настаивать на своем. На кедровых орешках.

user posted image
McLotos
chee
еще больше усложнил вопрос =))))
twin
Вызов методов контроллера из View?
А разве не контроллер рулит вьюшками и моделями?

_____________
программирование - инструмент для решения конкретных задач, любая попытка спроектировать что-то универсальное приведет к провалу.©paul85
В любом случае тебе прийдётся пройти путь изобретения велосипеда, который прошли другие, только причиной твоего изобретения будет непонимание принципов работы велосипеда изобретённого другими людьми.©SlavaFr
jQuery это попытка использовать АН-225 для перевозки зубочистки
chee
McLotos, MVC без фронтконтроллера не жизнеспособна, это факт.


_____________
Люди, имеющие низкий уровень квалификации, делают ошибочные выводы, принимают неудачные решения и при этом неспособны осознавать свои ошибки в силу низкого уровня своей квалификации
Bolik
Цитата
Вызов методов контроллера из View?


конечно. а как у тебя например формы обрабатываются?

у меня например если форма запрашивает

url/param1/param2/param3

то param1 - это контроллер, param2 - это метод контроллера ну и потом параметры для самого метода. так же и фреймворки работают
chee
Bolik твой ответ вообще не как не связан с вопросом, если что.


_____________
Люди, имеющие низкий уровень квалификации, делают ошибочные выводы, принимают неудачные решения и при этом неспособны осознавать свои ошибки в силу низкого уровня своей квалификации
Bolik
я написал с каким именно вопросом связан мой ответ
McLotos
chee
не совсем понимаю как это должно работать.
Вот смотри. Есть Router, есть Request есть Controller, Model, View
И есть еще куча всяких Controller, Model, View, которые подключаются в зависимости от url.
Как они должны взаимодействовать между собой?
Я вот например думал что Router вызывает контроллер, который нужен для конкретной страницы (например ChartController), а этот контроллер в свою очередь тянет свою модель (ChartModel) и свою вью (ChartView), которые в свою очередь являются наследниками Model, View. а ChartController не является ни чьим наследником. Или не так?

А FrontController это же по идее index.php - единая точка входа в приложение, или я опять ошибаюсь?

_____________
программирование - инструмент для решения конкретных задач, любая попытка спроектировать что-то универсальное приведет к провалу.©paul85
В любом случае тебе прийдётся пройти путь изобретения велосипеда, который прошли другие, только причиной твоего изобретения будет непонимание принципов работы велосипеда изобретённого другими людьми.©SlavaFr
jQuery это попытка использовать АН-225 для перевозки зубочистки
chee
Цитата (McLotos @ 9.10.2015 - 11:36)
А FrontController это же по идее index.php

Ну по идее да, но таки реализация у него объетная, он аккомулирует в себе работу по матчингу роутов, инициализации компонентов MVC.

Что касается того, что и как взаимодействует, то класическая схема таков.

Контроллер устанавливает состояние модели, выполняет с ней какие либо действия связаные с бизнесс логикой, то есть запускает например их.
Модель, вообще не в курсах кто с ней работает, она не знает что есть контроллер и представление, но у нёё есть методы доступа к данным, к установке данным, работы с данными (бизнесс логика).
Представление забирает данные из модели, не взаимодействует с бизнесс логикой


_____________
Люди, имеющие низкий уровень квалификации, делают ошибочные выводы, принимают неудачные решения и при этом неспособны осознавать свои ошибки в силу низкого уровня своей квалификации
McLotos
Цитата (chee @ 9.10.2015 - 14:51)
Контроллер устанавливает состояние модели, выполняет с ней какие либо действия связаные с бизнесс логикой, то есть запускает например их.
Модель, вообще не в курсах кто с ней работает, она не знает что есть контроллер и представление, но у нёё есть методы доступа к данным, к установке данным, работы с данными (бизнесс логика).
Представление забирает данные из модели, не взаимодействует с бизнесс логикой

Ну это я знаю.
Так контроллер должен быть всего 1, 1 под каждый класс, или 1 но с кучей наследников?

_____________
программирование - инструмент для решения конкретных задач, любая попытка спроектировать что-то универсальное приведет к провалу.©paul85
В любом случае тебе прийдётся пройти путь изобретения велосипеда, который прошли другие, только причиной твоего изобретения будет непонимание принципов работы велосипеда изобретённого другими людьми.©SlavaFr
jQuery это попытка использовать АН-225 для перевозки зубочистки
McLotos
Сейчас например сделано так:
1.Index.php устанавливает autoload всех моделей.
подключает скрипт core.php
2. В скрипте core.php

require 'core/config.php';
require 'core/controller.php';
require 'core/model.php';
require 'core/view.php';
require 'core/request.php';
require 'core/router.php';

$configs = new Config;
$configs->setConfig('maxFilesize', 1024*20*1024); //Размер файлов, которые можно грузить на сайт
$configs->setConfig('mainPage', 'https://site.ru/');
$configs->setConfig('cookiename', 'mycookies');
******************************

$Request = new Request();
$Router = new Router($configs, $Request);


3. Request используется просто для того чтобы исключить везде в коде чтение/запись в $_GET, $_POST, $_SERVER, $_SESSION, всё только через него.
request.class
class Request{
private $get = array();
private $post = array();
private $request = array();
private $session = array();
private $server = array();
private $files = array();

public function __construct(){
$this->get = $_GET;
$this->post = $_POST;
$this->request = $_REQUEST;
$this->session = $_SESSION;
$this->files = $_FILES;
$this->server = $_SERVER;
$this->cookie = $_COOKIE;
}

public function get($key=false){
if(!$key){
return $this->get;
}else{
if(array_key_exists($key, $this->get)){
return $this->get[$key];
}
}
}


public function post($key=false){
if(!$key){
return $this->post;
}else{
if(array_key_exists($key, $this->post)){
return $this->post[$key];
}
}
}


public function request($key=false){
if(!$key){
return $this->request;
}else{
if(array_key_exists($key, $this->request)){
return $this->request[$key];
}
}
}


public function session($key=false){
if(!$key){
return $this->session;
}else{
if(array_key_exists($key, $this->session)){
return $this->session[$key];
}
}
}


public function setSession($key, $val){
$_SESSION[$key] = $val;
}

public function files($key=false){
if(!$key){
return $this->files;
}else{
if(array_key_exists($key, $this->files)){
return $this->files[$key];
}
}
}


public function server($key=false){
if(!$key){
return $this->server;
}else{
if(array_key_exists($key, $this->server)){
return $this->server[$key];
}
}
}


public function cookie($key=false){
if(!$key){
return $this->cookie;
}else{
if(array_key_exists($key, $this->cookie)){
return $this->cookie[$key];
}
}
}
}

4. Router решает какой контроллер нужно подключить именно для этой страницы основываясь на данных с Request.
Router
class Router{
private $controllerName;
private $actionName;
private $modelName;
private $model;
private $request;
private $cfg;
private $acl;
private $menuBuilder;

public function __construct($cfg, $request){
require $cfg->getConfig('dirControllers') . 'acl.controller.php';
require $cfg->getConfig('dirControllers') . 'menubuilder.controller.php';
$this->cfg = $cfg;
$this->request = $request;
$this->acl = new ACL($cfg, $request);
$this->startRoute();
}

private function startRoute(){
if(!$this->checkGetParams()){//пустой url
if(!$this->request->session('access')){ //нет уровня доступа
$controllerName = 'Auth';
if(!$this->request->post()){ //если не переданы никакие данные
$actionName = 'authForm';
}else{ //если отправлены логин и пароль
$actionName = 'login';
}
}
else{
$controllerName = 'Main';
if(!$this->request->get('action')){
$actionName = 'index';
}else{
$actionName = $this->request->get('action');
}
}
}
else{//url проверен и доступен
if(!$this->acl->getRights()){//нет доступа к этой странице
$controllerName = 'Auth';
$actionName = 'logout';
}else{

$controllerName = (!$this->request->get('module')) ? 'Main' : $this->request->get('module');
$actionName = (!$this->request->get('action')) ? 'index' : $this->request->get('action');
}
}

require_once $this->cfg->getConfig('dirControllers') . strtolower($controllerName) . '.controller.php';
$controller = new $controllerName($this->cfg, $this->request);
$menuBuilder = new MenuBuilder($controller, $this->request);
$menuBuilder->addMenu();
$controller->$actionName();

}

//нужно переделать этот метод чтобы он не подключал скрипт. разделить его на 2-3 метода
private function checkGetParams(){
if(array_key_exists('module', $this->request->get())){
if(is_file($this->cfg->getConfig('dirControllers') . $this->request->get('module') . '.controller.php')){

require $this->cfg->getConfig('dirControllers') . $this->request->get('module') . '.controller.php';
$className = ucwords($this->request->get('module'));
$obj = new $className($this->cfg, $this->request);
if(is_object($obj)){
if(array_key_exists('action',$this->request->get())){
if(method_exists($obj, $this->request->get('action'))){
return true; //у модуля найден запрашиваемый метод
}else{
return false; //у модуля нет такого метода
}
}
else{
return true; //в url не указан action
}
}
else{
return false; //не получилось создать объект запрашиваемого модуля
}
}
else{
return false; //не нашли файл запрашиваемого модуля
}
}
else{
return false; //не найден параметр module
}
}


private function ErrorPage404(){
header('HTTP/1.1 404 Not Found');
header('Status: 404 Not Found');
header('Location:http://'.$_SERVER['HTTP_HOST'].'/404');
}
}


5. Дальше Router просто вызывает нужный контроллер, где каждый контроллер является потомком Controller.
6. Каждый контроллер работает только со своей моделью и со своей вьюшкой. Модель любого контроллера потомок Model.
Но как мы вчера выяснили этот подход не подходит в случае если нужно использовать дополнительные компоненты, например добавить на страницу меню, которое является самостоятельным объектом со своим Controller, Model, View, где MenuController потомок Controller а MenuModel потомок Model

_____________
программирование - инструмент для решения конкретных задач, любая попытка спроектировать что-то универсальное приведет к провалу.©paul85
В любом случае тебе прийдётся пройти путь изобретения велосипеда, который прошли другие, только причиной твоего изобретения будет непонимание принципов работы велосипеда изобретённого другими людьми.©SlavaFr
jQuery это попытка использовать АН-225 для перевозки зубочистки
Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2024 Invision Power Services, Inc.