Передача данных из MVC-контроллера для просмотра в PHP

У меня есть собственная ручная фреймворк PHP MVC для некоторых проектов, над которыми я работаю. Когда я впервые создал фреймворк, это было в контексте создания админ-CMS. Поэтому между моделью, представлением и контроллером была очень приятная взаимно-однозначная взаимосвязь. У вас есть одна строка в БД, которая сопоставляется с одной моделью. Контроллер загружает модель и передает ее в визуализируемое представление (например, в форму редактирования). Хороший, чистый и легкий.

Однако теперь, когда я работаю над интерфейсом сайта, все становится липким. Страница не всегда представляет собой представление об одной модели. Это может быть список каталогов пользователей с 20 пользователями (каждая из моделей пользователей). Кроме того, могут быть метаданные о запросе, такие как разбиение на страницы (текущая страница, общие страницы, количество результатов) и/или поисковый запрос.

Мой вопрос: какой самый чистый способ передать все эти данные в представление?

Некоторые параметры, которые я рассматриваю:

  • Попросите контроллер создать массив и передать его в виде одного параметра:

    class UserController{
    
        public function renderView(){
    
            // assume there some logic to create models, get pagination, etc.
            $data = array()
            $data['models'] = $models; 
            $data['currentPage'] = $current;
            $data['totalPages'] = $total;
            return $view->render($data);
        }
    }
    
    class UserView{
        public function render($data){
            // render the data
        }
    }
    
  • Создайте свойства в классе представления и запишите их в контроллер:

    class UserView{
        public $models;
        public $currentPage;
        public $totalPages;
    }
    
    class UserController{
    
        public function renderView(){
    
            // assume there some logic to create models, get pagination, etc.
            $view = new UserView();
            $view->models = $models; 
            $view->currentPage = $current;
            $view->totalPages = $total;
            return $view->render();
        }
    }
    
  • Дайте представлению какой-то общий объект HashMap или Collection как контейнер, который может содержать произвольное число и имя данных.

    class UserView{
        public $collection = new Collection(); // works like a Java collection
    }
    
    class UserController{
    
        public function renderView(){
    
            // assume there some logic to create models, get pagination, etc. 
            $view = new UserView();
            $view->collection->add($models,'models');
            $view->collection->add($currentPage,'currentPage');        
            return $view->render();
        }
    }
    

Я знаю, что технически любой из них мог бы работать, но я не уверен в лучшем выборе, или если есть лучший или более обычный выбор, который мне не хватает.

Ответы

Ответ 1

Я порекомендую концепцию Fat Models, Skinny Controllers (или Тонкие контроллеры толстых моделей, если вы предпочитаете...)

В других словах ваша модель слишком строгая: привязка вашей модели к представлению только чего-то вроде RowDataGateway крайне ограничена.

На самом деле, я думаю, хорошие модели скрывают тот факт, что вы вообще читаете данные из базы данных. Потому что на самом деле ваши данные могут быть в текстовых файлах или из веб-службы или что-то еще. Если вы относитесь к своей модели как к прославленному DBAL, вы обрекаете себя на то, чтобы иметь жестко связанный код в ваших контроллерах, который просто не позволит вам оторваться от "мышления" только из базы данных.

Ответ 2

Я видел оба из первых двух методов, реализованных в популярных структурах MVC/templating.

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

smarty использует второй метод, создавая объект Smarty и присваивая значения каждому из свойств в контейнере.

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

На самом деле, я думаю, я не сказал ничего, о чем вы уже не думали. В принципе, это все звуковые идеи, поэтому реализуйте все, что вы считаете наиболее комфортным.

Ответ 3

В том, что я использую, у него автоматически есть свойство вида в контроллере, которое позволяет получить доступ к методам и свойствам в представлении. Все общедоступные свойства затем доступны в представлении вида '$ this', так как представление визуализируется в контексте его собственных объектов.

В контроллере:

$this->view->myVar = 'test';

И в представлении:

$this->myVar; // 'test'

То же самое касается макета, так как оба экземпляра одного и того же объекта просмотра:

$this->layout->myVar = 'test';

И затем в макете:

$this->myVar; // 'test'

Рамка была собственностью, но должна быть выпущена для широкой публики. Я был бы рад выслать вам код, если вы думаете, что это поможет. Помните, что самый простой ответ - лучший ответ.