Посмотрел. Давно надо уже было. Несколько замечаний по ORM.
1) Почему бы не сделать так?
$user = new Us er();
$users = $user->Fields("ID", "LOGIN")->Filter("=ACTIVE=Y", "%NAME=$name")->OrderBy("LAST_NAME")->Splice(0, 10)->GroupBy();
foreach($users as $user) ....
Не всегда же нужны все эти аргументы в GetList. Это избавило бы от такого кода:
При этом статический метод вернет объект запроса, в котором дальше устанавливаются параметры с помощью методов-сеттеров, а выполняет запрос метод GetList. Каждый метод возвращает объект обратно.
Глагол самого запроса, если это итератора, это первый вызов next() интерфейса Iterator. В других случаях да нужен отдельный метод (получение массива например, что нужно довольно редко).
В вашем коде объект $user возвращает коллекцию объектов User, хотя сам является объектом User. Т.е получается "Пользователь" возвращает "Пользователей". Так было бы более понятно:
4-е строчки вместо 2-х. Лишние сущности. Зачем. Конструируется query запрос, который конкретно выражается в SQL. А может быть, например, выражен в Javasript, если это MongoDB. C этим query объектом можно делать что угодно. Самое частое употребление же будет итерация его списка объектов. В этом случае запрос автоматически превращается в то что нужно. Происходит ленивое связывание/вычисление. Как это выглядит в других языках. Фреймворках.
Python/Django:
users = User->objects->filter(name="a", active=True).order_by("last_name").fields("id", "login")
for user in users:
....
Ruby/Ruby On Rails (возможно стоит посмотреть на их названия методов where = find)
$book = BookQuery::create()->findPK(123); // retrieve a record fr om a database
$book->setName('Don\'t be Hax0red!'); // modify. Don't worry about escaping
$book->save(); // persist the modification to the database
$books = BookQuery::create() // retrieve all books...
->filterByPublishYear(2009) // ... published in 2009
->orderByTitle() // ... ordered by title
->joinWith('Book.Author') // ... with their author
->find();
foreach($books as $book) {
echo $book->getAuthor()->getFullName();
}
Все же хотелось бы следовать принципу DRY. Мне пример python и ruby в этом более симпатичен. Давайте разберем ваш пример. Если вы создали объект User, вы его создали для какой-то цели. А не для "вещи в себе" и самолюбования. В случае веб-фреймворка - получить доступ к данным этого объекта. Сразу отпадают select() и fetchAll(). Второе. Зачем нужен статический вызов User::select(). Model-Viewer-Controller явно подразумевает определения объекта в Модели. Мы же хотим нормальное ООП, не так ли? Я вный возравщаемый результат, как итератор? Собираетесь его использовать его где-то помимо цикла foreach? Нет. Да и не получится. GetList и иже с ним отпадают.
У вас $user = new Us er(); User - это в этом случае что? Что за объект? Как по вашему отличить User для доступа к данным от User - Вася пупкин с ID=50? Model-Viewer-Controller тут вообще не причем. Еще раз напомню строчку:
$user = new Us er();
$users = $user->Fields("ID", "LOGIN")->Filter("=ACTIVE=Y", "%NAME=$name")->OrderBy("LAST_NAME")->Splice(0, 10)->GroupBy();
Кто такой $user и кто такие $users?
Вот так еще более-менее понятно (с применением мапперов):
//создали объект для получения данных
$mapper = new UserMapper();
//получили коллекцию объектов User
$users = $mapper->Fields("ID", "LOGIN")->Filter("=ACTIVE=Y", "%NAME=$name")->OrderBy("LAST_NAME")->Splice(0, 10)->GroupBy();
foreach($users as $user) {
//тут $user объект типа User
}
В тот-то и вопрос кто такие User? Это такой квази-объект, который умеет все. Ну, почти все, что может описать язык, на котором он написан. Он и singleton и асtiverecord и datamapper (в какой-то степени). И объект и множество объектов. Суть же не в формальном описании, a в реальной практике. Нам ведь сайты писать. Поэтому надо и брать, что лаконичнее, короче и красивее. И постоянные используемые паттерны прятать за синтаксический сахар.
Группы на сайте создаются не только сотрудниками «1С-Битрикс», но и партнерами компании. Поэтому мнения участников групп могут не совпадать с позицией компании «1С-Битрикс».