McLotos
9.10.2015 - 08:57
Всем привет. В общем читал последнее время много разных статей по реализации MVC, везде почему-то разный подход. Я выделил 3 самых часто встречающихся, попробую описать их тут. Помогите выбрать правильный вариант (если он тут есть конечно)
1. Когда есть 1 базовый контроллер, а все остальные контроллеры его наследники. Тогда получается что router для каждого URL вызывает свой контроллер, а тот зачем-то обращается к базовому контроллеру, хотя по сути всё может сделать сам. То же с моделями, все модели наследники базовой модели (тут как раз всё понятно, только 1 класс может общаться с БД напрямую) и вызываются контроллерами конкретной страницы (1 модель для 1 страницы). При этом базовая модель просто возвращает результат запроса в виде массива, а модели классов уже обрабатывают их так как нужно. Контроллер страницы вызывает нужную ему View
2. Когда есть 1 базовый контроллер, который вызывает нужные контроллеры. (как бы наоборот, не контроллеры вызывают базовый, а базовый контроллер подключает контроллер страницы). Много моделей, наследников базовой модели и сами модели решают в каком формате отдать уже обработанные данные контроллеру, а контроллер просто передает их в вид.
3. Когда под каждую страницу есть свой контроллер и он работает самостоятельно, со своей моделью, которая является наследником базовой модели и так же как в 2 варианте просто отдает контроллеру данные. (нет никакого базового контроллера).
И как к этому всему прикручивать класс Router (и нужен ли он вообще).
И как тут использовать класс Requests, который хранит и обрабатывает данные из всех суперглобальных массивов ($_POST, $_GET, $_SERVER, $_SESSION)
_____________
программирование - инструмент для решения конкретных задач, любая попытка спроектировать что-то универсальное приведет к провалу.©paul85
В любом случае тебе прийдётся пройти путь изобретения велосипеда, который прошли другие, только причиной твоего изобретения будет непонимание принципов работы велосипеда изобретённого другими людьми.©SlavaFr
jQuery это попытка использовать АН-225 для перевозки зубочистки
По верх стандартной MVC есть еще FrontController, он инициализирует Router, задает ему маршруты из конфига, берет URL из Request, ищет совпадение, если находит то возвращеет название контроллера и метода в нём, вьюхи. Ты берешь эти названия, в данном случае контроллера, отдаешь его фабрике, фабрика возвращает объект контроллера, у него ты вызываешь метод, который опять же получил от роута. Тоже самое делаешь и вьюшками.
_____________
Люди, имеющие низкий уровень квалификации, делают ошибочные выводы, принимают неудачные решения и при этом неспособны осознавать свои ошибки в силу низкого уровня своей квалификации
Картинку прсовокуплю.
_____________
Если вам недостаточно собственных заблуждений, можно расширить их мнениями экспертов.Нужно уважать мнение оппонета. Ведь заблуждаться - его святое право.Настаивал, настаиваю и буду настаивать на своем. На кедровых орешках.
McLotos
9.10.2015 - 11:21
chee
еще больше усложнил вопрос =))))
twin
Вызов методов контроллера из View?
А разве не контроллер рулит вьюшками и моделями?
_____________
программирование - инструмент для решения конкретных задач, любая попытка спроектировать что-то универсальное приведет к провалу.©paul85
В любом случае тебе прийдётся пройти путь изобретения велосипеда, который прошли другие, только причиной твоего изобретения будет непонимание принципов работы велосипеда изобретённого другими людьми.©SlavaFr
jQuery это попытка использовать АН-225 для перевозки зубочистки
McLotos, MVC без фронтконтроллера не жизнеспособна, это факт.
_____________
Люди, имеющие низкий уровень квалификации, делают ошибочные выводы, принимают неудачные решения и при этом неспособны осознавать свои ошибки в силу низкого уровня своей квалификации
Цитата |
Вызов методов контроллера из View? |
конечно. а как у тебя например формы обрабатываются?
у меня например если форма запрашивает
url/param1/param2/param3
то param1 - это контроллер, param2 - это метод контроллера ну и потом параметры для самого метода. так же и фреймворки работают
Bolik твой ответ вообще не как не связан с вопросом, если что.
_____________
Люди, имеющие низкий уровень квалификации, делают ошибочные выводы, принимают неудачные решения и при этом неспособны осознавать свои ошибки в силу низкого уровня своей квалификации
я написал с каким именно вопросом связан мой ответ
McLotos
9.10.2015 - 11:36
chee
не совсем понимаю как это должно работать.
Вот смотри. Есть Router, есть Request есть Controller, Model, View
И есть еще куча всяких Controller, Model, View, которые подключаются в зависимости от url.
Как они должны взаимодействовать между собой?
Я вот например думал что Router вызывает контроллер, который нужен для конкретной страницы (например ChartController), а этот контроллер в свою очередь тянет свою модель (ChartModel) и свою вью (ChartView), которые в свою очередь являются наследниками Model, View. а ChartController не является ни чьим наследником. Или не так?
А FrontController это же по идее index.php - единая точка входа в приложение, или я опять ошибаюсь?
_____________
программирование - инструмент для решения конкретных задач, любая попытка спроектировать что-то универсальное приведет к провалу.©paul85
В любом случае тебе прийдётся пройти путь изобретения велосипеда, который прошли другие, только причиной твоего изобретения будет непонимание принципов работы велосипеда изобретённого другими людьми.©SlavaFr
jQuery это попытка использовать АН-225 для перевозки зубочистки
Цитата (McLotos @ 9.10.2015 - 11:36) |
А FrontController это же по идее index.php |
Ну по идее да, но таки реализация у него объетная, он аккомулирует в себе работу по матчингу роутов, инициализации компонентов MVC.
Что касается того, что и как взаимодействует, то класическая схема таков.
Контроллер устанавливает состояние модели, выполняет с ней какие либо действия связаные с бизнесс логикой, то есть запускает например их.
Модель, вообще не в курсах кто с ней работает, она не знает что есть контроллер и представление, но у нёё есть методы доступа к данным, к установке данным, работы с данными (бизнесс логика).
Представление забирает данные из модели, не взаимодействует с бизнесс логикой
_____________
Люди, имеющие низкий уровень квалификации, делают ошибочные выводы, принимают неудачные решения и при этом неспособны осознавать свои ошибки в силу низкого уровня своей квалификации
McLotos
9.10.2015 - 12:54
Цитата (chee @ 9.10.2015 - 14:51) |
Контроллер устанавливает состояние модели, выполняет с ней какие либо действия связаные с бизнесс логикой, то есть запускает например их. Модель, вообще не в курсах кто с ней работает, она не знает что есть контроллер и представление, но у нёё есть методы доступа к данным, к установке данным, работы с данными (бизнесс логика). Представление забирает данные из модели, не взаимодействует с бизнесс логикой |
Ну это я знаю.
Так контроллер должен быть всего 1, 1 под каждый класс, или 1 но с кучей наследников?
_____________
программирование - инструмент для решения конкретных задач, любая попытка спроектировать что-то универсальное приведет к провалу.©paul85
В любом случае тебе прийдётся пройти путь изобретения велосипеда, который прошли другие, только причиной твоего изобретения будет непонимание принципов работы велосипеда изобретённого другими людьми.©SlavaFr
jQuery это попытка использовать АН-225 для перевозки зубочистки
McLotos
9.10.2015 - 13:13
Сейчас например сделано так:
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, всё только через него.
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.
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()){
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{
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();
}
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;
}
}else{
return false;
}
}else{
return false;
}
}else{
return false;
}
}
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 для перевозки зубочистки
Быстрый ответ:
Powered by dgreen
Здесь расположена полная версия этой страницы.