Comments 116
Статья хороша наглядностью, но много чего конечно сыровато.

Вот это просто ужос:
$router = new Router($registry);
$registry->set ('router', $router);

Как минимум можно сделать так:
$router = new Router();
Registry::set ('router', $router);

final class Registry
{
private static $_instance;
private __construct();
public static set($key, $value) {....}
private _init()
{
if (!isset(self::$_instance)) {
self::$_instance = new Registry();
}
}
......
}
UFO landed and left these words here
а зачем вам несколько регистрЕй!? больше одной вам не надо, а чтобы быть уверенным что больше одной у вас создать не получится юзают синглетон. имхо всё логично :)
UFO landed and left these words here
при этом нужно помнить что работать с ним можно только так, и никак иначе.
а синглетон защищает от того, что по запарке кто нибудь родит кучу new Registry() и потом будет ломать себе голову почему "ничего не работает!" ;)
new Registry родить не получится, т.к. в реализации AirWorker конструктор - приватный.
Вообще делается

$ob = SignetoneClass::getInstance();

public static function getInstance() {
if(!is_object(self::$_instance)) {
$c = __CLASS__;
self::$_instance = new $c;

return self::$_instance;
} else {
return self::$_instance;
}

}

И никаких объектов.

Как-то так :)
Это для PHP4. В PHP5 можно использовать полноценные классы, что правильнее.
Кто-то из нас определенно тупит :)
в PHP4 нет ни public, ни static в данном контексте. А что вы подразумеваете под "неполноценными" и "полноценными" классами мне не понятно...

Есть такой шаблон - Singletone, это и есть его реализация.
Дело в том что есть несколько вариантов его реализации в PHP. В Википедии про это есть.

Да, кстати, Вы правы, ступил я немного. (В PHP5 действительно реализация отличается не существенно.) Извините. :-\
Варианты реализации отличаются по сути только синтаксисом, шаблоны на то и шаблоны, что условия в них жесткие :)

А извиняться вам не за что, все мы учимся :)
Странно, вот делал я проект. Там был класс, у которого всё что есть — куча статических публичных функций и методов, которые работают с внутренними переменными класса (тоже static).
Выходит, раз там не было getInstance — это был не синглетон?
Вы понимаете в чем вообще предназначение шаблонов, в чем тут суть и логика заключается? И почему собственно Singleton? :)
После рабочего дня голова не варит. Когда дома буду постараюсь ответить =)
ну во-первых как минимум так:

public static function getInstance()
{
if (!self::$_instance) {
self::$_instance = new self;
}
return self::$_instance;
}

А во-вторых приемы то разные.
В случае с Registry::set ('router', $router); ВООБЩЕ не нужно инстанционировать объект этого класса, даже статичный (через сингелтон). Единственное (и определяющее) преимущество использования класса — глобальная зона видимости. т.е. обратиться к Registry::set ('router', $router); можно из любого места.

Сингелтон нужен в случае, если класс реализуют несколько более сложную логику, нежели просто хранение объектов.
Я не пишу "как нужно", если вы заметили, я просто правильно выразил мысли человека, а правильные они или нет - пусть другие исправляют :)

А Singleton нужен в случае, когда вам нужен exactly one instance of your class :) Причем экземпляр создается, сам по себе класс несет нагрузку объекта...А Registry в данном случае - нет.
это именно то, что я и имел ввиду. в данном конкретном случае Registry не требует функциональности объекта — соответственно инстанционировать его не нужно, даже как сингелтон.
Почему вы думаете что еще один объект registry не нужен?
А если я еще один хочу сделать, скажем с какими либо отдельными настройками?
Из определения регистра для данного случая следует, что он должен быть ОДИН :)

А вообще флаг вам в руки, убирайте сингтон и делайте как хотите.
Блокирование clone с помощью magic-метода не нужно, клонировать объект такого типа все равно не получится.

Думаю, что основной недостаток любых решений с использованием registry — это потеря типа. Для PHP это означает всего лишь потерю автокомплишна в ide, но это очень серьезный аргумент для того, чтобы отказаться от registry в пользу конструкций вида

final class C
{
/**
* Объект БД
*
* @var Zend_Db_Adapter_Pdo_Mysql
*/
public static $db;


}
Про clone, спасибо, я учту

Делегирование тоже не всегда оправдано, например если большой класс использует туже БД только в одном своём методе, то делегировать БД в класс немного излишне

А создавать финальные классы со статическими свойствами это мне кажеться больше подходит для констант

final class C
{

public static $BYTE = 1;



}

>> Делегирование тоже не всегда оправдано, например если большой класс использует туже БД только в одном своём методе, то делегировать БД в класс немного излишне

я имел в виду что класс C является контейнером для общих объектов приложения, юзается в любом месте:

C::$db->select()->[и тут вываливается автокомплишн]
Есть ли у этого метода ещё какие-то плюсы перед Регистром кроме автокомплишена?

У меня например возникают вопросы, вроде: как удалить синглтон объект если он больше не нужен чтобы он не занимал память
unset(self::$instance)
так не выйдет

допустим у нас синглтон БД
мы удаляем его не из объекта а снаружи
private static мы не можем удалить снаружи по определению, и с этим поделать ничего нельзя. Максимум, что мы можем — добавить метод unsetInstance() { unset(self::$instance) } (я это имел в виду)

кстати, реализация класса БД в виде синглтона — не лучшая идея.
>> А создавать финальные классы со статическими свойствами это мне кажеться больше подходит для констант

Вот это совсем непонятно…

И почему не «const BYTE = 1;»?
final class C{
public static $BYTE = 1;
public static $KILOBYTE = 1024;
public static $MEGABYTE = 1048576;
}

я понимаю такой подход в java но видел и в пхп
это класс констант с которым потом сравнивают переменные
чтото вроде if($myFileSize < C::$MEGABYTE)
я не думаю что стоит спорить должен это быть static или const
>> я не думаю что стоит спорить должен это быть static или const

В больших проектах это важно. Про const мы знаем, что никакой «орел» не поставит заглушку, меняющую «псевдоконстанту», из-за которой возникнет ошибка в логике (например, ошибочный посчет суммы крупного заказа). Это вопрос скорее не технический, управленческий.
Отлично Саш! Спасибо что вспомнил - как раз будет над чем посидеть завтра! Пробежался глазами - радует наличие примеров, без них никак! Еще раз спасибо за перевод!

Автор, найдите, пожалуйста, в статье

$registry->['name']

и удалите в ней стрелочку.

Спасибо

Удивляют условия, где булево значение избыточно сравнивается с булевой константой. Можно проще:

if (file_exists($file) == false) → if (!file_exists($file))

А в целом пост добротный.
причем, даже сравнение if (file_exists($file) == false) правильнее было бы использовать с тремя знаками равно === :-)
Простуда - враг программиста :-) Мозг плохо соображает, пойду лечиться ;-)
file_exists($file) == false
тож не верно
для ТРУ и ФОЛС нинзя используют эквиваленты
Спасибо! Если честно, то MVC-модель трогал исключительно одним пальцем, не доходили руки никак, чтобы разобраться. Вы мне помогли своим переводом. Спасибо! =)
Очень интересно, спасибо.

создание переменных для шаблонного класса
// Загружаем переменные
foreach ($this->vars as $key => $value) {
$$key = $value;
}

можно заменить на extract($this->vars);
Вау, как раз неделю назад у меня была такая необходимость. Жаль, что теперь поздно, но, думаю, еще понадобится.
Это
$site_path = realpath(dirname(__FILE__) . DIRSEP . '..' . DIRSEP) . DIRSEP;
на вот это
$site_path = dirname(dirname(__FILE__)) . DIRSEP;
Спасибо! Теперь примерно понял что такое MVC, а то без примеров сложно было понять как это все работает.
Супер, спасибо за топик!
Единственное что не понял - где подключается файл controller_base.php?
Ой, понял, я не туда сохранил его, надо в classes, а я поместил в controllers. :) А потом оказывается функцией __autoload() он автоматически подключается при вызове контроллера.
несмотря на критику в каментах (в заключении кстати написано что методы реализации возможно не самые лучшие),
очень хорошая статья, я в качестве view прикрутил шаблонизатор smarty,
если кому интересно - могу кинуть кусок кода ))
вопрос еще кстати про модель MVC, если мне надо использовать БД, общение с ней я так понял должно происходить с контроллере, те все запросы будут тупо храниться в классе-контролере, так? или есть более интеллектуальные методы?
Нет, не совсем так. Можно, конечно, и хранить запросы, и работать с БД в контроллере. Но всё же этими вещами должна заниматься модель. А уже с ней будет работать контроллер.
а пример можно?

я сейчас создал свой DB-класс, зарегистрировал его и через него общаюсь с PDO. PDO кстати раньше не юзал, да он мне и не очень удобным показался...
значит вы еще не пользовались PEAR::DB, который переопределить у меня НУ НИКАК не получилось, а хотелось добавить кое-какой функционал и логику :)
я тут 1,5 месяца потренировался в mvc - создал небольшую системку.

к системе, которая приведена примером в этой статье прикрутил более, как мне кажется грамотную "модель" - по аналогии с контроллерами (также грузятся). через эти классы-модели уже непосредственно общаюсь с БД, сейчас есть идея ввести параметр - драйвер чтобы уже не быть привязанным к какой-то определенной бд
Драйвер нужен в любом случае для работы с БД, он никак не вписывается ни в вид, ни в контроллер, только отдаленно относится к модели представления данных.
я к модели и хочу его прикрутить естественно, в настройках прописать драйвер и чтобы автоматически грузилась модель в соотвествии с выбранным драйвером - для контролера это должно быть прозрачным.

в статье просто про модель очень мало написано - я решил поделиться как можно развить идею модели

ps а какие сложности возникли с pear::db?
Мне понадобилось изменить поведение функций quoteIdentifier и quoteSmart, решил делать стандартно через полиморфизм, у меня вообще PEAR::DB подружался через extended класс, который реализован как Singleton, чтобы не держать кучу соединений с базой. Поэтому я и решил переопределять все через DDB просто переопределив функции, но не тут то было...Создаваемый в приложении instance класса DDB на самом деле являлся экземпляром DB и никакими хаками мне это обойти не удалось, предлагали использовать Decorator pattern, по-моему, но результато это не дало никакого.

Решил, что больше PEAR штуки в проектах постараюсь не использовать :)
у меня довольно тупая модель - простые селекты, апдейты, инсерты ))

я в такие дебри не вдавался и в итоге даже от PDO отказался
Там все до ужаса просто, никаких особых features я не заметил. Нормальные вещи (те же quote*) реализованы достаточно тупо, когда в метод попадает integer оно зачем-то квотит его, ну и подобные мелочи. Смысл обеих этих функций в одном и том же, только quoteIdentifier еще в `` квотит, но в мануале ничего нормально не неписано, есть еще escapeSimple, короче, полный бред...

А еще я хотел иметь аналог mysql_last_id(), т.к. в PEAR::DB этого ПОЧЕМУ-ТО нет :) Зато там есть некие sequences, которые вместо возврата LAST_INSERT_ID позволяют создавать последовательности вставок, где будет храниться LAST_INSERT_ID, короче там вместо 1 функции приходится использовать 3 с мудреной логикой, причем для каждой sequence создается еще и своя таблица в бд...с ума сойти :)
советую посмотреть в сторону DbSimple — более удобной библиотеки абстракции БД я не встречал. Это конечно если вам не нужны сверхвозможности (работа с биндами, тригерами и т.д.). а если все таки нужны — то ADODB может вам подойдет больше чем peardb, с ней нет проблем в переназначении методов.
Сейчас я ищу нечто большее, чем простую абстракцию к интерфейсу БД, нужен целый фреймворк, который устраивал бы меня по 2/3 своих возможностей, а такого пока я не видел.

К тому же планирую чуть позже совсем уйти из php.
вы уже смотрели в сторону Zend Framwork? если нет советую хотябы ознакомиться. я использую его в своих больших, но при этом невысоконагруженных проектах. он удовлетворяет как раз эти 2/3 потребностей. в связке со смарти, дбсимпл и JsHttpReques — 3/4 :)
Зенд ОЧЕНЬ туп, там фактический тот же PEAR подход, многие вещи просто переписаны под логику этого фреймворка, куча ненужных вещей. Шаблонные движки по моему мнению вообще не нужны, особенно такие, как пресловутый смарти, язык в языке, по-другому не скажешь. Фреймворк должен оптимизировать рутину, типа обработки форм, их вывода, ошибок и т.п., с чем каждый раз приходится сталкиваться. Для асинхронных запросов я использую в данный момент prototype, но думаю перейти на mootools, т.к. функционал в разы выше и круче.
у нас различные понятия определения «фреймворк». обработка форм, их вывод, валидация и т.д. очень сильно зависят от конкретного проекта. сделать что-нибудь более менее универсальное и чтобы при этом с ним можно было нормально работать практически невозможно.

фреймворк дает базовые инструменты, кирпичики так сказать, с помощью которых легко сложить нужный вам дом. Так например в прототайпе нет реализации валидации форм, нет реализации построения таблиц с сортировкой и другой более высокоуровневой логики. этим фреймвор заниматься не должен. а вот например script.aculo.us построенный на базе прототайпа (ну или того же mootools) прекрасно реализует возложенную на него более высокоуровневую задачу.

что касается конкретно Zend Framework, то я не сказал бы что это что-то идеальное и панацея от всех бед. да многое в нем меня не устраивает тоже, но тем он и хорош, что позволяет с легкостью переписать/дописать не устраивающий тебя метод/класс/модуль. его долго можно сравнивать с cakePHP или codeInteger и прийти лишь к тому что у каждого есть свои + и -.

а вообще нужно на python переходить :))
Это уже от каждого отдельного товарища зависит.
Мне достаточно prototype, чтобы сделать

function validateLogin(login) {
new Ajax.Updater(...)
}

или сделать вообще validate, а скрипт-обработчик будет определять по пришедшему к нему значению что требуется...Всего одной оберткой.
Просто mootools мне больше понравился, это js-фреймворк, а грузить сторону пользователя глупыми вещами, вроде валиадации там - бред, юзер отключит жс и поломает вам нафиг сайт...по-другому только реализовать логику валидации 2 раза, в жс для удобства юзера и в скрипте, для спокойного сна кодера.

И никто не говорит о том, чтобы фреймворк позволял делать

$obj = new Site();

Зенд - бред, мне нафиг не нужен их Ajax реализация, нафиг не нужна их авторизация банальная, если я могу то же самое сделать в .htaccess, нафиг не нужен переписанный PEAR::DB, есть вещи, которые можно сделать ВНЕ PHP, а это значит, что в нем они совершенно не нужны, к тому же в таком количестве, к тому же такие беспомощные. Остальное я смотрел и мне не понравилось.

И питон мне не нравится :)
по порядку:
1. валидировать данные, отправляя их на сервер? хм. я так никогда не делаю.
2. поддерживаю технологию двойной валидации — на фронтенде для удобства, на бекенде для безопасности — половинчатые варианты очень не люблю.
3. мне в зенде нравиться реализация контроллеров-роутеров-диспетчеров. легкость и простота ее имплементирования и широкая возможность доработки под собственные нужды не ломая при этом идеологию и не изобретая велосипедов. Zend_Db, как впрочем и зендовскую авторизацию в чистом виде я не использую. тоже самое с Zend_View — имплементировал удовство работы, а движок для парсинга шаблонов использую смартевый. Как то передавать данные в шаблоны нужно, а смарти это делает наиболее прозрачно и понятно для верстальщиков.

3. я python настолько плохо знаю, что не могу сказать нравиться он мне или нет)). пока мнение исключительно субъективное.
а можешь показать как реализовал продгрузку разных моделей?
в startup.php5:
// если название класса Model_A[_B]
if(preg_match("/Model_([^_]*)(?:_([^_]*))?/", $class_name, $matches) ) {
array_shift($matches);
// имя будет /models/a[/b].php
$file = site_path . 'models' . DIRSEP . strtolower(join('/',$matches)).ext;
// иначе грузим из директории classes
} else {
$filename = strtolower($class_name).ext;
$file = site_path . 'classes' . DIRSEP . $filename;
}

include ($file);
Возникло желание посмотреть всю систему, если можно, вышлите на jonsne@ngs.ru
Сквозь года присоединяюсь к вопросу насчет всей системы. romansivakov@gmail.com
понравилась статья, несмотря на то, что немного смазанно понятие модели. Модель в моем понимании (воспитанном во многом рельсами) это более высокий уровень абстракции чем прослойка к БД. Модель должна представлять собой уже некоторую сущность, к примеру клиента. Получается что модель предоставляет интерфейс для работы с клиентами в контроллере.

не совсем понятна также целесообразность использования ArrayObject
код в итоге будет довольно неприятный
$this->registry['db']->query($sql)
както щетинисто выглядит

последнее время вообще тянет в сторону препроцессоров кода. Тянет создать чтото вроде надстройки на пхп. К примеру, чтобы в контроллере конструкции вида
@clients = &cleints->list();

преобразовывались в
$this->env->template->set($clients, $this->env->models->cleints->list());

Реалезуется элементарно, но до реализации хочется продемать что еще туда впихнуть.
остается только посочувствовать людям, которым возможно придется рефакторить (да и просто читать) ваш код. в любом случае удачи)
А ещё лучше почитать документацию и покопаться в коде какого-то хорошего готового фреймворка.
Я бы советовал CakePHP. Разработчики умудряются выжимать всё, что только можно из PHP.
в новой версии (которая beta) PHP4 уже не будет поддерживаться. её и нужно смотреть.
а старой уже больше года
SPL тут ни к чему, все нормально решается стандартными методами и поставкой :)
Если вы используете PHP5 и пишете, что все ТОЛЬКО для PHP5, будьте добры использовать exceptions, а не die :) И область видимости методов отмечайте, статичность и т.п. :)

$site_path можно было define('ROOT_PATH', '/var/www/localhost/htdocs'), вместо переменной, DIRSEP как-то не смотрится по сравнению с DIRECTORY_SEPARATOR, последнее хоть и длиннее, но дает четкое понимание "куда я попал" :)

Ах да, еще include...давайте уже include_once или require_once, что будет правильнее, вы же проверяете на существование файла :)

В общем все, в принципе понравилось :)
dirname(__FILE__); позволяет не думать о том, что однажды провайдер (к примеру) сменит домашнюю директорию вашего проекта.
так что define('ROOT_PATH', dirname(__FILE__));

и еще вместо использования константы DIRECTORY_SEPARATOR достаточно ВСЕГДА использовать прямой слеш /. Он в юниксе родной разделитель, а винде пофигу))
Мало ли какая ОС, да и то, что винда поддерживает - не есть стандарт.

Полностью динамическое задание path у вас не получится, у PHP с этим огромные косяки, которые никто не думает править, в любом случае вам придется либо один раз жестко дефайнить, либо постоянно держать директорию проекта в include_path.
«придется либо один раз жестко дефайнить» — именно так. вопрос лишь в том, как это делать. define('ROOT_PATH', dirname(__FILE__)); в index.php к примеру вполне для этого подойдет.

ну а держать в include_path предпочитаю директорию с контроллерами, моделями и библиотеками (т.е. все три, не подумайте что уменя все это в одной папке свалено:) ).
Ну а причем здесь index.php?
Ты каждый раз будешь его инклудить?
Есть какой-либо config.php, в котором хранятся настройки, но require_once 'config.php', в котором будет написано ваше dirname(__FILE__); повлечет за собой то, что рут патом будет считаться текущий каталог...а это конец :)

Поэтому я знаю что пишу, т.к. неоднократно сталкивался с такой фигней :)
ну во-первых константа __FILE__ не изменит своего значения в зависимости от того, где был проинклужен файл config.php.
большенство моделей построения MVC подразумевают единую точку входа (тот же самый index.php). Так работает зенд фреймворк напрмер — все обращения к серверу реврайтятся на index.php. ну а уже в нем достаточно один раз require_once 'config.php';

у меня подобный алгоритм использован во всех проектах — все прекрасно работает. при этом я могу спокойно сменить место дислокации проекта с (напрмер) /var/www/ на /home/www/ и при этом ничего править не прийдется.
"... достаточно ВСЕГДА использовать прямой слеш /. ... а винде пофигу"
вы это проверяли или просто где-то прочитали/услышали? А то прям с капслоком написано.
А на заборах пишут "хуй".

<?php
mkdir ("dir1/dir2/dir3", 0755, true);
?>

<?php
mkdir ("dir1\dir2\dir3", 0755, true);
?>
Платформа: winXP, Apache/2.2.4 (Win32), PHP/5.2.4
результаты тестирования можно увидеть на скриншоте →

Также пришлось переводить не один проект с win2003/iis/php4(php5) на linux. В процессе перехода сполна ощутил разницу в системах.
Возможно условия тестирования не вполне объективны? Мне уже самому интересно — неужели на win-платформах прямой слеш (/) не проходит когда-то.
попробуй в консоле на win-платформе начиная с ядра 5.1 написать вот такую команду cd / — и увидишь результат
Очередное изобретение велосипеда как всенда закончилось кучей комментов что и где надо дописать/исправить/заменить (ради которых такие статьи интересно читать).

советую почитать документацию по Zend Framework (если конечно вы ее уже не читали) — уж очень ваш подход мне напоминает этот фреймворк.
Для новичков это ОЧЕНЬ полезно, а то мастеров, пишущих "говнокод" сейчас достаточно, сам иногда велосипеды писал, пока к паттернам не приучили, это поможет и в планировании, конструировании будущего приложения.
согласен. статья очень полезна для изучения патернов и стандартов. но использовать приведенный в ней код я бы не советовал. Если уж заинтересовал новый подход — «погугли в яндексе» не описан ли он в википедии :)
Всё давольно просто и понятно. Спасибо!

Но вот у меня есть вопрос:
на странице есть не только основное содержание, но и повторяющиеся блоки.
Такие как навигация, анонсы новостей, ну и хидеры с футерами (причем на одних страницах новостей нет, а на других есть).

Как их вписать в архитектуру МВЦ?
В каком месте и где их вызывать?
Какова иерархия папок (структура приложения)?
Интересный вопрос. На сколько я знаю однозначного ответа на него нет.

Есть несколько подходов к решению.
Ну во-первых, если четко придерживаться MVC то все данные для формирования хедеров, меню и подобных повторяющихся блоков нужно формировать в контролерах и передавать в шаблоны в виде готовых к «употреблению» массивов.
с другой стороны, на мой взгляд, у этого подхода есть один минус — в каждом контролере придется повторять одну и туже рутинную операцию. Конечно ее можно свести к минимуму, но все же.

есть еще способ — использование так называемых плагинов (виджетов, хелперов) в шаблонах. Тогда мы немного отступаем от стандарта MVC и схема работы сайта получается такой:
запрос → контроллер → модель → контроллер → шаблон → плагин → модель → плагин → шаблон.

соответственно плагин это некий контролер, вызываемый из шаблона. он автономен, но при этом знает все о запросе и может корректировать свою работу в зависимости от параметров запроса. например если плагин отвечает за рендеринг меню он может в зависимости от запроса подсвечивать текущий раздел. и так далее.

это решение, которое использую я. Есть конечно еще варианты, например еще больше изменить архитектуру MVC, чтобы процесс выглядел примерно так:
запрос → контроллер → шаблон → плагин → модель → плагин → шаблон.
→ плагин → модель → плагин →
→ плагин → модель → плагин →
т.е. единственная роль контролера — вызов шаблона. а уже в шаблоне вызываются плагины, которые рендерят контент в вставляют его в сетку шаблона. тогда шаблон собирается как бы из кубиков, а каждый кубик автономен.

Я не открыл что-то новое, есть довольно большое количество литературы, описывающей тот или иной подход. Стоит рассмотреть несколько вариантов, а потом сделать вывод какой из них наиболее подходит для решения ваших задач. Ну или имплементировать лучшие стороны каждого и (на свой страх и риск) написать свою схему построения приложения. Выбор за вами.

ps: все сказанное является отражением моей точки зрения на проблему, и не есть руководство к действию. Всегда открыт для конструктивных замечаний :)
да и вобще. стоит взять документацию по какому-нибудь фреймворку (zend подойдет например) — возможно там вы найдете ответы на все интересующие вас вопросы (даже если потом не будете этот фреймворк использовать).
полностью поддерживаю что ZF весьма показан к хотя бы ознакомлению хотя бы за его документацию + внутрение ситили кодирования + способ реализации, которые могут послужить примером оформия framework'a. а то что он весьма тяжел никому не мещает написать некое свое подобие (кто тут еще свой framework/CMS не писал?)
дочитал до половины. Далее уже не в мочь. Статья отстойная.
1. Класс Registry не что иное как массив $_GLOBALS - т.е. заводя этот класс мало того что воспроизводится уже существующая структура, так еще и навешивается избыточное количество функций на работу с ней. К тому же подобную структуру в системе принято создавать синглтоном.
2. Именно модель должна работать с БД (то есть в ней находится представление о структуре таблиц, а не просто формирование запросов). Если различие стирается - то это уже не MVC.
3. getController(&$file, &$controller, &$action, &$args) - зачем создавался Registry если значения гоняются параметрами? При нормальном MVC - параметры у функций вообще не используются.
n. Ничего не рассказано про структуру-архитектуру приложения.
"Это был не MVC!"
А я вот не понял зачем вообще несколько контроллеров может понадобиться (
А вы не моглибы выкладывать если не трудно свои реализации и рассказывать чем они лучше?
ета статья лиш предложение идей для основ будущего приложения:)
довольно хороша (в качестве каркаса...) ... но во что перерастет приложение, построеное на етой модели - зависит только от програмиста.
http://localhost/demo/members/view вот так у меня не работает.... пишет Not Found
а вот так работает..

пос отличный может кто выложит этот MVC со всеми поправками которые были выше изложены?
UFO landed and left these words here
Очень интересно.
Объясните пожалуйста:

Вот допустим в контроллере обработал данные, получил массив($myvars) где формировать html-код?
Где из этого массива делать таблицу(<table&gt) и т.п.?

в контроллере
...
for ($i...){
$mytable.='<tr>...<td>'.$myvars[$i].'</td>...</tr>';
}
...
$this->registry['template']->set('mytable',$mytable);

или

в контроллере делать:
$this->registry['template']->set('myvars',$myvars);

а в самом Template уже обходить массив и строить html
скажите, а как получить дополнительные переменные, т.е. кроме members/view, например мне езе нужно передеть member_id, category_id как мне передать и получить эти переменные? заранее спасибо.
Тут уже надо переписывать Router.
Или как в зенде — на preg по шаблонам или как я — тупой перебор массива router с подставленями стандартных значений из конфига загруженного сайта.
а ты не знаешь как можно обрабатывать аргументы типа controllName/Method/arg1/arg2/
Вот нашел дополнительные ф-и к Роутеру
public function getArg($key) {
if (!isset($this->args[$key])) {
return null;
}
return $this->args[$key];
}
private function extractArgs($args) {
if (count($args) == 0) {
return false;
}
$this->args = $args;
}

по доступу видно что одна из них должна внутри класса обрабатываться, другая как-то доступна из вне! о_0`
а почему бы запрос не делать такого вида index.php?router=controllName/Method&args=arg1/arg2&… Другое?
Загрузился только тайтл страницы :( Если у кого-то есть возможность отзеркалить страницу — буду очень благодарен.
А есть где примерчик глянуть всё с использованием отдельных Model, отдельных Controller, отдельных View?
Спасибо за статью, начало уже интересное. Как только начал читать нашел ошибку в определении метода Registry::remove();
Пляха муха, статья обрезана и не полностью, помогите найти полную версию. Спасибо
Открыта проблема безопасности данного кода. Например, что будет если пользователь перейдет по такой ссылке, например
http://example.com/?route=../../../folder/script.php
Only those users with full accounts are able to leave comments. Log in, please.