Автор Тема: CMF на перле  (Прочитано 12611 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн Макс

  • vir magni ingenii
  • Глобальный модератор
  • Ветеран
  • *****
  • Сообщений: 3534
  • +0/-0
  • 2
    • Просмотр профиля
CMF на перле
« Ответ #15 : 10 Марта 2005, 17:39:37 »
По поводу http://2netfly.com/blog/?p=6
1. По поводу get/set - методов.
Про set - согласен. А вот get-методы ИМХО могут быть полезны. Код буду приводить на ПХП (мне он  ближе)
Возьмем типичную новость. Ее надо показать на странице юзеру, ее надо показать в админке, возможно где-нибудь еще. Например дату новости на всех этих страницах надо привести к одному формату. В тексте новости надо символы перевода строк заменить на
 а теги <> на & lt; & gt;
Если все это делать в шаблонах или ручкми после получения, то получиться избыточный код. Поэтому имхо удобнее сделать get-методы :
 function getDate() {
    return 
date(\'Y.m.d\', $this->fields[\'date\']);
}

а вшаблонах вызывать $news->getDate(); - хотя это уже зависит от уровня представления.

2. Все-таки в 95% случаев данные добавляются через POST.
 if (POST_METHOD) {
      if (
$news->add()) {
            
redirect(\'news_added.php\');       
      }  else {
             $errors = $news->errors; // получаем массив ошибок
      }
}
метод add() сам загружает данные из пост, проверяет и записывает в БД (я все таки за проверку данных внутри класса)

3. мне кажется более логичным такое разделение классов :
 - один базовый класс(DBObject) и все его наследники занимаются отображением одного объекта. В основном он занимается CRUD-операциями + по желанию (например если объектом является юзер, то занимается его авторизацией). Причем READ-операция делает только чтение одного объекта (не списка)
 
 - один базовый класс (DBObjectList)  и все его наследники занимаются работой со списком объектов. Это все выборки из БД и все что с этим связано - постраничная разбивка, определение кол-ва найденных объектов, некоторые манипуляции с полем ORDER BY.
while ($obj = &$list->getOne()) {
   
/// $obj - объект типа DBObject
}



4. и немного о проблеме модификации класса при добавлении новых связей.
Я в своем классе сделал поле $_fields, в которое помещаются все неиспользованые данные. Например объект новостей получил хеш-массив:

 $fields 
= array(
   
"id"=> 12
   
"subject"=>"...."
   
"text"=>"...."
   
"blablabla"=>"XXX",  /// <<<
   
"date"=> "...."

Допустим объект новостей ничего не знает о поле "blablabla", тогда это поле и его значение будут помещены в $_fields (на всякий случай) и к нему я всегда смогу обратиться.
Теперь если мне в готовом проекте вдруг понадобилось подключить к новостям комментарии и выводить их кол-во, то я меняю запрос :
SELECT news.*, [b]COUNT(comments.*) as comments_amount[/b] FROM ..... LEFT JOIN .....
а в шаблоне напишу <?=intval($news->_fields[\'comments_amount\']);?>
Но эта фича скорее для "грязных хаков", чем для постоянного использования :)
First learn computer science and all the theory. Next develop a programming style. Then forget all that and just hack. ( George Carrette )

Оффлайн 2NetFly

  • Модератор
  • Глобальный модератор
  • Постоялец
  • *****
  • Сообщений: 144
  • +0/-0
  • 0
    • Просмотр профиля
    • http://feotast.net
CMF на перле
« Ответ #16 : 10 Марта 2005, 18:43:38 »
Во-первых, спасибо за ответ, наконец-то появилась возможность подискутировать на интересную мне тему =) Во-вторых, если не сложно, продублируй свой ответ в блоге - его читаю пользователи других форумов, возможно они тоже захотят принять участие в дискуссии. Теперь ответы по пунктам.

1. Я довольно скептически отношусь к использованию объектов в шаблонах и, как следствие, к представлению, например, новости, как объекта. В моем понимании новость - это ассоциативный массив, ключи которого дублируют поля таблицы, и, если необходимо, некоторые дополнительные значения, которые предварительно устанавливаются доменным объектом. А список новостей - это массив таких хэшей. Может в будущем я изменю свое мнение, но сейчас мне кажется, что объектам в представлении не место (за исключением статических методов построения блоков информации).

Касательно замены определенных символов в некоторых полях, приведения даты к стандартному формату и прочего - я размышлял над этим, но пока не пришел к окончательному выводу, хотя уже вижу два пути реализации:
а) изменять данные непосредственно после выборки и хранить их в новом формате.
б) делать то же самое, но не в коде, а при помощи xml конфига. Пример подобного конфига был приведен в отчете о PHP конференции (доклад посвященный ORM).

2. У меня существует отдельный класс Request который занимается парсингом параметров и он умеет преобразовывать, например, /news/show/123/ в action=show&id=123. Использования такого класса упрощает модификацию обработки и пасинга параметров путем просто переопределения нужных методов.

3. Раньше все так и было. Все классы наследовали Object (в нем методы select, update, create, delete, getAll), зачастую в классах-наследниках указывался только путь к xml конфигурационному файлу (в нем определились короткие синонимы для полей, указывался первичный ключ, его тип и пр.), а так же был статический метод list (find) который занимался работой со списком. Однако вскоре стали появляться большие проблемы. Например, все документы я храню в одной таблице, информацию об авторах - в другой, иконку для документа - в третьей, информацию о источнике - в четвертой и т.д.. Я так и не смог придумать, как правильно реализовать метод выбора одной новости и списка новостей в этом случае и в какой класс его поместить. С одной стороны загромождать класс Document неправильно, с другой - больше эти методы и деть-то некуда.

Вот такой вот был запрос для списка (немного упрощенный =):

my $query 
"
SELECT *
FROM 
$TBL{document}{_} AS doc
LEFT JOIN 
$TBL{author}{_} AS a ON a.$TBL{author}{id} = doc.$TBL{document}{authorid}
LEFT JOIN 
$TBL{category}{_} AS cat ON cat.$TBL{category}{id} = doc.$TBL{document}{categoryid}
LEFT JOIN 
$TBL{source}{_} AS s ON s.$TBL{source}{id} = doc.$TBL{document}{sourceid}" .
(
$self->SQLOrderBy($sparam->{OrderBy})) .
$self->SQLLimit(@{$sparam->{Limit}});


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

<!-- вывод первых 3 новостей с одним шаблоном -->
[% 
News::List("tmp_1"LimitForm => 0LimitTo => 3OrderBy => ‘date’OrderType => ‘DESC’) %]
<!
—вывод новостей с 3 по 7 с другим шаблоном -->
[% 
News::List("tmp_2"LimitForm => 3LimitTo => 10) %]

tmp_1, tmp2 - это тройные шаблоны (альтернатива foreach).

Все, конечно, упрощенно. Можно обрабатывать ситуации, когда список пуст и т.д., но общая идея должна быть понятна.

Кстати,  весьма интересная реализация работы с шаблонами есть в WordPress (блоге). Я думаю что для PHP (с перлом другая история) шаблонизаторы типа смарти - это излишество.
There Is More Than One Way To Do It (c)

Оффлайн Макс

  • vir magni ingenii
  • Глобальный модератор
  • Ветеран
  • *****
  • Сообщений: 3534
  • +0/-0
  • 2
    • Просмотр профиля
CMF на перле
« Ответ #17 : 10 Марта 2005, 20:11:29 »
Цитировать
2NetFly:
Во-первых, спасибо за ответ, наконец-то появилась возможность подискутировать на интересную мне тему =)

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

По поводу блога - подними эту тему к выходным, я все тексты туда переброшу. У тебя там какой-нибудь ББ-код есть для подсветки синтаксисиа ?

 
Цитировать
2NetFly:
 1. Я довольно скептически отношусь к использованию объектов в шаблонах и

Цитировать
2NetFly:
Ну и в шаблоне это дело удобно использовать:

[% News::List("tmp_1", LimitForm => 0, LimitTo => 3, OrderBy => ‘date’, OrderType => ‘DESC’) %] [% News::List("tmp_2", LimitForm => 3, LimitTo => 10) %]

:) Или на статические вызовы методов в шаблонах ты смотришь иначе ?

3. Да я с таким тоже сталкивался и как правило все делал через Ж...
Славу богу таких случаев было не так много.
Вообще я считаю что такой фреймворк должен упрощать разработку простых скриптов и хотя бы не усложнять разработку сложных вещей. И я не вижу ничего плохого в том, чтобы иногда отказываться от ORM, когда связей слишком много и они затрудняют работу.

Что касается твоего примера, то у меня давно крутится в голове идея, но до реализации пока так и не дошло. Суть примерно такая.
Пишем класс - назовем его SQLLoader. Назначение - он получает SQL-запрос, список пустых объектов (может быть список классов, но интуитивно объекты мне нравятся больше), выполняет этот запрос и возвращает объекты. Покажу на примере :

$a_list 
= new AuthorList(); // список авторов
$c_list = new CommentList(); // список комментов
$loader = new SQLLoader();
$loader->setSQL("SELECT a.*, c.* FROM authors a, comments c WHERE c.author_id = a.author_id AND c.article_id = 12");
$loader->setObjects($a_list$c_list);
l$loader->load();

дальше в зависимости от реализации  (например если объекты были переданы по ссылке)  их можно уже использовать

Пока вижу здесь 2 проблемы
 - обеспечить ссылки между связаными объектами (именно это я пока не продумал)
 - неудобно работать, если в связанных таблицах  будут поля с одинаковыми именами полей

Кстати, в таком случае ИМХО есть преимущества в том, что "объект" и "список объектов" - это 2 разных класса.

$author 
= new Author(); // один автор
$comment = new Comment(); // один коммен
$loader = new SQLLoader();
$loader->setSQL("SELECT a.*, c.* FROM authors a, comments c WHERE c.author_id = a.author_id AND c.article_id = 12");
$loader->setObjects($a_list$c_list);
while (
l$loader->load()) {
   ....
// здесь используем объекты $author и $comment
    
....// на каждой новой итерации они будут иметь новые значения
    
.... /// в этом случае и со ссылками проблем не будет
}


Но это все вымышленный код, пока нет времени (да и потребности) реализовывать его.
« Последнее редактирование: 10 Марта 2005, 20:22:28 от Макс »
First learn computer science and all the theory. Next develop a programming style. Then forget all that and just hack. ( George Carrette )

Оффлайн 2NetFly

  • Модератор
  • Глобальный модератор
  • Постоялец
  • *****
  • Сообщений: 144
  • +0/-0
  • 0
    • Просмотр профиля
    • http://feotast.net
CMF на перле
« Ответ #18 : 10 Марта 2005, 20:54:10 »
Цитировать
Или на статические вызовы методов в шаблонах ты смотришь иначе?

У этих статических методов иное назначение, без них обойтись нельзя. Я имел в виду объекты как сущность (новость, комментарии и т.д.).

Касательно объектов и коллекций объектов в представлении - я наконец-то вспомнил, почему в свое время от них отказался. Представь себе, что тебе нужно вывести список 100 пользователей с подробной информацией о каждом (допустим, 10 полей). Тебе во-первых придется создать коллекцию из 100 объектов Пользователь, а во-вторых сделать тысячу вызовов методов! Я не думаю, что это будет очень быстро =) По крайней мере обход структуры займет в тысячи раз меньше времени. Поэтому я все больше и больше склоняюсь к мнению, что дополнительный слой нужен и он не должен быть связан с доменными классами.
There Is More Than One Way To Do It (c)

Оффлайн Макс

  • vir magni ingenii
  • Глобальный модератор
  • Ветеран
  • *****
  • Сообщений: 3534
  • +0/-0
  • 2
    • Просмотр профиля
CMF на перле
« Ответ #19 : 10 Марта 2005, 23:48:07 »
Цитировать
2NetFly:
 Касательно объектов и коллекций объектов в представлении - я наконец-то вспомнил, почему в свое время от них отказался. Представь себе, что тебе нужно вывести список 100 пользователей с подробной информацией о каждом (допустим, 10 полей). Тебе во-первых придется создать коллекцию из 100 объектов Пользователь, а во-вторых сделать тысячу вызовов методов! Я не думаю, что это будет очень быстро =) По крайней мере обход структуры займет в тысячи раз меньше времени.

1. Поскольку в большинстве случаев такие коллекции исползуются в скрипте всего один раз и почти всегда это обход коллекции в одну сторону, то не проблема реализовать их, незагружая сразу в массив (типа Lazy Load), а работая с одним объектом из коллекции.

2. такие массивы данных (как ты описал) обычно выводятся только в админках. А там вполне можно пожертвовать производительностью.

3. Всегда есть куча способов оптимизировать скрипт (компиляция шаблонов, кеширование, статика, акселераторы и т.п.) Так что это не проблема.
First learn computer science and all the theory. Next develop a programming style. Then forget all that and just hack. ( George Carrette )

Оффлайн 2NetFly

  • Модератор
  • Глобальный модератор
  • Постоялец
  • *****
  • Сообщений: 144
  • +0/-0
  • 0
    • Просмотр профиля
    • http://feotast.net
CMF на перле
« Ответ #20 : 11 Марта 2005, 00:22:15 »
1. Не совсем понял, что имеется в виду.
2. При разработке mp3 архива подобные запросы мне приходилось выводить довольно часто: список исполнителей на определенную букву, лейблов, дат выхода альбомов и т.д.
3. Я бы сказал, что всегда есть куча способов усложнить программу =) В данном случае статика и прочее - это лишь усложнение, цель которого решить проблемы, которые решаются другими более простыми способами.

И все равно мне кажется, что объектам модели в преставлении не место. Доменными объектами можно (и нужно) манипулировать в классах-обработчиках, а представление (по определению) должно манипулировать данными, а не методами доменных объектов. Процитирую одного из участников дискуссии на форуме phpclub, мнение которого я полностью разделяю: "Собственно, зачем нам необходимо полностью загружать доменные объекты, если всего лишь требуется отобразить некоторую информацию во View?".
There Is More Than One Way To Do It (c)

Оффлайн Макс

  • vir magni ingenii
  • Глобальный модератор
  • Ветеран
  • *****
  • Сообщений: 3534
  • +0/-0
  • 2
    • Просмотр профиля
CMF на перле
« Ответ #21 : 11 Марта 2005, 12:13:44 »
Цитировать
2NetFly:
1. Не совсем понял, что имеется в виду.

Обычно список сущностей нужно просто получить из базы и вывести на странице. Поэтому даже если используются коллекции объектов, не надо сразу загружать все данные коллекции.
Задача класса DBObjectList не в том, чтобы сразу загрузить в объект все данные (это можно делать, а можно не делать - по желанию разработчика), а в том, чтобы стандартизировать работу со списками:

$list 
= new NewsList();
$list->getNewsForCategory($category_id);
if (!
$list->empty) {
    while (
$news = &$list->get()) {
       
/// работаем с одной новостью
    
}
}



Насчет представления - не считаю этот вопрос принципиальным.
Я не делаю никаких ограничений на представление - все на совести разработчика.
First learn computer science and all the theory. Next develop a programming style. Then forget all that and just hack. ( George Carrette )

Оффлайн Макс

  • vir magni ingenii
  • Глобальный модератор
  • Ветеран
  • *****
  • Сообщений: 3534
  • +0/-0
  • 2
    • Просмотр профиля
CMF на перле
« Ответ #22 : 11 Марта 2005, 12:17:24 »
Цитировать
2NetFly:
манипулировать в классах-обработчиках

вообще про отдельные классы-обработчики я еще подумаю на досуге.
Идея хорошая.
First learn computer science and all the theory. Next develop a programming style. Then forget all that and just hack. ( George Carrette )

Оффлайн 2NetFly

  • Модератор
  • Глобальный модератор
  • Постоялец
  • *****
  • Сообщений: 144
  • +0/-0
  • 0
    • Просмотр профиля
    • http://feotast.net
CMF на перле
« Ответ #23 : 11 Марта 2005, 13:33:50 »
Я раньше использовал в качестве обработчиков методы классов (например, класс News метод add), но потом перешел на отдельные классы-обработчики. Преимуществ довольно много, основное из которых - возможность построения иерархии обработчиков и повторное использование кода. Т.е. создаешь common обработчики для добавления, удаления, модификации, а затем лишь указываешь на нужный доменный объект, с которыми они будут работать.
There Is More Than One Way To Do It (c)

Оффлайн 2NetFly

  • Модератор
  • Глобальный модератор
  • Постоялец
  • *****
  • Сообщений: 144
  • +0/-0
  • 0
    • Просмотр профиля
    • http://feotast.net
CMF на перле
« Ответ #24 : 15 Марта 2005, 11:24:07 »
Приобрел неплохую книгу по паттернам в J2EE. Перевод ужасный, но довольно информативно. Прокомментировал несколько паттернов на блоге. Так же связался с разработчиками LIMB, они придумали очень интересный механизм организации команд в конечный автомат.
There Is More Than One Way To Do It (c)

 

Sitemap 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28