Барахтаясь в паттерне MVC. Код (Text): $controller = new Controller(); Глобальная функция (подсмотрел в CodeIgniter): Код (Text): function &get_instance() { return Controller::get_instance(); } В конструкторе контроллера: Код (Text): $this->model = new Model();[ $this->view = new View(); $this->lib = new CoolLibrary(); В модели и виде, чтобы получить доступ к «параллельным» объектам, делаю: Код (Text): $this->GlobalObj = get_instance(); Если теперь посмотреть на получившийся бутерброд Код (Text): print_r($controller); можно увидеть несколько «дублей» глобального объекта, украшенных ругательствами RECURSIVE. Собственно, вопрос. Допустимо ли использовать такое взаимное подключение объектов повсеместно — с точки зрения излишнего расхода ресурсов сервера? Или следует стараться все, что можно, подключать через статические методы и свойства? Простите за ламерский вопрос, не программист я.
Ну вообще, взаимные связи объектов - это очень плохо. Зависимость должна быть односторонней. Зачем вам из модели лезть в контроллер? Вообще не представляю. Это не из-за ресурсов сервера не рекомендуется, просто в такой программе вы сами через пару месяцев хрен разберётесь. Как же меня она бесит в нём, и необходимость к ней обращаться... Не учитесь на плохом, разберите Slim, потом Lumen и Laravel Вот мне сейчас пришлось дорабатывать систему на CodeIgniter, но достал он меня, хочу уговорить заказчика на Laravel переписать. --- Добавлено --- Модель вообще наружу в идеале смотреть не должна (конечно, это не всегда получается). Она должна быть максимально изолирована. Т.е. контроллер запустил в неё данные, они там покрутились и к нему вернулись в максимально готовом виде. Кстати, тоже на чём не стоит учиться - это Open Cart, у которого вечно идёт перегонка из пустого в порожнее (хотя по функциям движок замечательный, но код у него бесячий). Т.е. модель считала данные из базы, вернула массив. Контроллер весь этот массив прочитал, и по одному полю в другой массив перегнал. Зачастую вообще ничего не меняя...
@mkramer, спасибо за развернутый ответ. Мне не надо в контроллер, контроллер у меня тощий. Он умеет только предварительную валидацию входных данных, вызвать соответствующую модель, потом вызвать соответствующий вид. Мне потребовалось в методах вида как-то получать данные, сформированные моделью, а из модели дергать некоторые специфические методы вида. А они оба являются членами объекта контроллера. Одного уровня. Отсюда и вопрос. Мне самому это интуитивно не нравилось. В общем, уже все перекрестные связи переписал на статику. Заодно разобрался, как это вообще делается. Это слишком сложно для меня. Да и не учусь я на Codeigniter, просто подсмотрел в нем несколько моментов.
Я делаю немного не так. Контроллер получает данные только от роутера, модель выкладывает сформированные данные в свои статические свойства (из буквально два — промежуточное и окончательное), а вид их оттуда забирает. Вид про модель знает исключительно эти два места, и формат данных в них. Больше он про модель не знает ничего, а про существование контроллера даже не догадывается. Контроллер тоже в тонкостях не разбирается. В большей части его методов две строчки: Модель, подготовь данные на эту тему! Вид, нарисуй чё там модель приготовила, а где взять, сам знаешь. (Иногда проверяет массив входных параметров от роутера.) Сомнительное место в этой идиллии — потребность из модели дергать специфические методы вида для верстки сложных вставок (больших таблиц в основном), чтобы потом втыкать сверстанный сложный хтмль в составной окончательный объект для выдачи виду. Может оно идеологически неправильно, но мне так проще и понятнее на данном этапе.
Вид тоже не должен (в идеале) лезть в модель, он должен работать с данными. Другое дело, что есть паттерн ActiveRecord, когда экземпляры модели передаются в вид. Для маленьких проектов сойдёт, для большого - смерть. Это трындец, почему у вас модель что-то там верстает? Массивы передавайте, а потом один файл вида может обращаться к другим файлам вида Slim сложный? Вы это серьёзно?
Laravel. Про остальные я от вас впервые слышу. Единственное, что умеет делать с моделью вид, это типа вот: PHP: View::main(Model::$out); или PHP: View::make_table(Model::$table_data); Это означает лезть в модель? Данные как-то надо по-другому передавать? Ничего она не верстает, она этого не умеет. Модель готовит массив обработанных данных (например, для большой и сложной таблицы отчета) и вызывает специально обученный метод вида, который сверстает html-таблицу и вернет ее в виде строки: PHP: self::$table_data = $this->get_table_data(); $table = View::make_table(); Дальше (string) $table вставляется в недра итогового объекта self::$out, точно так же, как и строки, добытые непосредственно из БД. После чего модель завершает работу, возвращает контроллеру true (ну или false, если произошел облом). Получив true, контроллер вызывает вид: PHP: View::main(Model::$out); Для чего это мне понадобилось. Например, есть страница, где большую часть времени написано: Среди всякого прочего написано, это не единственный контент, там куча всякого другого. В какой-то момент — бац! появились данные, и вместо строки «Приходите завтра.» надо вставить большую и сложную таблицу. Как это сделать идеологически верно? Единственное, что придумалось, это внедрять в общий шаблон спецметки, которые вид будет парсить, вызывать специально обученный вспомогательный метод, и заменять метку на ту самую строку, которую я готовлю в процессе работы модели. Вызывая тот же самый вспомогательный метод View::make_table(). Это явно проще, чем городить парсер меток.
Ой, сплошная статика... Терпеть не могу. Модель - это что, один единственный класс? Ну вообще, традиционно контроллеры передают в вид данные от модели, но у вас тут ад какой-то, все классы друг к другу лезут в кишки, это вообще не ОО-архитектура, да и вообще не архитектура. Почитайте что-нибудь нормальное про ООП, попробуйте с каким-нибудь фреймворком плотно поработать, чтоб дисциплина была. Вообще, я часто по работе занимаюсь сопровождением чужих сайтов, и чаще всего, если это самопис без фреймворка, то значит тонна говнокода, если на фреймворке - то более-менее. Пока, из всех чужих сайтов, код которых я дорабатывал, мне только один раз попался сайт на действительно качественном сапомисном фреймворке, хоть и тоже на статических функциях. Но там прогер очень опытный, с опытом работы high load. Сам я без фреймворка пишу только совсем небольшой код, если надо что-то большее, чем отправка почты с лендинга, то обязательно беру фреймворк, в том числе ради самодисциплины. --- Добавлено --- Понимаете, глобальные данные - это очень плохо. Если кому-то нужны данные, надо их туда передать.
Похоже, ничего конкретного я уже не услышу, очень жаль. Видите ли, я не программист, и это не кокетство. Мне всего лишь нужно автоматизировать громадную кучу тупой рутины, свалившуюся на меня в последнее время. И я вовсе не собираюсь осваивать профессию программиста, слишком поздно. Если б лет двадцать назад, хотя бы... А так — нет. Но, спасибо и на этом.
Ну я же не могу книгу уместить в пост на форуме. Если вам нравится, как работает ваша программа - ОК. А так, я вам путь сказал - берёте любой приличный фреймворк, делаете на нём, так, как в руководстве описано. MVC в иделе - это когда слои друг к другу обращаются, но друг в друга не лезут. К этому надо стремиться. Вид не должен лезть в переменные внутри модели - он должен получать готовые данные от контроллера. Контроллер тоже не должен лезть в данные внутри модели, он должен получать готовые от модели (через вызов). Вас я не понимаю. Если я не хочу осваивать профессию сантехника, но мне надо прочистить засор в ванной, я вызываю сантехника.
Вот эту фразу можно перевести на простой язык? Я знаю только два способа обратиться из одного объекта к другому — прочитать свойство и вызвать метод. Что такое «лезут», я не понимаю.
Я же написал - не надо обращаться из вида к статической переменной модели. Передайте её как параметр в вид из контроллера. Как - не знаю, я ваш код не видел
<не сарказм> Ок, статическая переменная — это то, куда «лезут». Так понятнее. Т.е., кошерно действовать только так: 1. Контроллер вызывает метод модели и получает возвращаемую через return переменную. 2. Контроллер вызывает метод вида и передает ему в виде параметра данные от модели. Все иные пути являются греховными и неправославными. Так?
Ок. Тогда посоветуйте, как действовать в описанном выше случае: сначала в модели было простое получение строки из БД (преформатированный html), и вдруг потребовалась сложная обработка данных из БД с последующей сложной версткой. И выводить надо это сложное в то же самое место, где раньше было простой коротенький текст. Ок, модель обнаружила, что теперь надо вон чего, вызвала свой специально обученный метод, он сформировал многомерный массив/объект, являющийся набором данных. Как и где этот набор преобразовывать в строку? Как и где эта строка должна вставляться в выходной поток?
Вы можете во вьюхе проверить, есть ли теперь эти данные, и включить в неё другую вьюху, передав в неё эти данные. Ну я бы так сделал, только не знаю, позволяет ли это ваша архитектура. Я-то свои фреймворки не пишу, всё равно лучше Laravel-я не сделаю
Как проверить во вьюхе то, что внезапно выяснила модель? Проверить тип переменной (была строка, теперь массив) или как? Или ставить специальную метку? Как узнать (сообщить) главной вьюхе, какой из вспомогательных методов вызывать?
Я же вашу архитектуру не знаю, поэтому дальше не могу сказать, не видя всю систему. Можно и тип проверить (is_array, к примеру), можно ещё что-нибудь
Затрудняюсь пояснить, что у меня за архитектура, я в столь крутых терминах не мыслю. Максимум абстракции — парадигма, или там паттерн какой. Да и то барахтаюсь. А код могу вывалить куда-нить. Он несложен, если выкинуть кучку извращенных частных методов, вычисляющих мозголомное нечто, которое требует от нас высшее начальство.