The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]

форумы  помощь  поиск  регистрация  майллист  вход/выход  слежка  RSS
"Catalyst сборка шаблона в переменную"
Вариант для распечатки  
Пред. тема | След. тема 
Форум WEB технологии (Perl)
Изначальное сообщение [ Отслеживать ]

"Catalyst сборка шаблона в переменную"  +1 +/
Сообщение от z0091 (ok) on 29-Окт-12, 14:39 
Добрый вечер!

Представим есть обертка шаблона.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <link rel="stylesheet" type="text/css" href="dbrm/root/styles/style.css"/>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
        <title>[% page.title %]</title>
    </head>
    <body>
        [% page.content %]
    </body>
</html>


Также есть контролер page.pm
В зависимости от переменной, контролер вытаскивает данные из базы.

Например страницу с id=1

my $my_content = $c->model('DBI::Content::Return')->return( '1' );


DBI::Content::Return

    foreach my $content_f (@$contents) {
            $keys_db->{ $content_f->{id}  }->{title} = $content_f->{title};
            $keys_db->{ $content_f->{id}  }->{date} = $content_f->{date};
            $keys_db->{ $content_f->{id}  }->{published} = $content_f->{published};
            $keys_db->{ $content_f->{id}  }->{autor} = $content_f->{autor};
            $keys_db->{ $content_f->{id}  }->{content} = $content_f->{content};
    }
    #print Dumper $keys_db;
    return \$keys_db;


Ни как не могу понять, как мне отправить данные хэша $my_content, в определенный шаблон. И уже подготовленный html код вставить в $c->page->content

Погуглив наткнулся на:

my $html = $c->view('TT')->render($c,'list_main.tt2', { result => $result, no_wrapper => 1 });


Но не могу понять как это работает.

Ответить | Правка | Cообщить модератору

Оглавление

Сообщения по теме [Сортировка по времени | RSS]


1. "Catalyst сборка шаблона в переменную"  +/
Сообщение от z0091 (ok) on 29-Окт-12, 14:40 
Нашел пример:


sub email_stuff : Local {
    my ($self, $c, $review_id) = @_;
    $c->stash(
        review_url    => $c->uri_for("/thingy/${review_id}"),
        status_msg => "Thank you for your feedback!",
        template      => 'view_all.tt2',
    );
    $c->email(
        header => [
            From    => $c->config->{'from'},
            To      => $c->config->{'to'},
            Subject => "Emaily stuff!",
        ],
        body => $c->view('TT')->render($c, 'review.tt2'),
    );
    return;
}

Я правильно понимаю, что линией  body => $c->view('TT')->render($c, 'review.tt2'),

Мы присваиваем в  $c->body шаблон review.tt2 с уже вставленными в него

  header => [
            From    => $c->config->{'from'},
            To      => $c->config->{'to'},
            Subject => "Emaily stuff!",
        ],


Если да, то помогите пожалуйста разобраться, где и как осуществляется эта самая вставка.  

Ответить | Правка | ^ к родителю #0 | Наверх | Cообщить модератору

2. "Catalyst сборка шаблона в переменную"  +/
Сообщение от ACCA (ok) on 31-Окт-12, 03:37 
1) внимательно прочитай Catalyst::View::TT. В разделе RENDERING VIEWS - дурацкий выбор имени функции в первом примере, он запутывает понимание остальных примеров и не имеет к ним никакого отношения.


>[оверквотинг удален]
>     <head>
>         <link rel="stylesheet" type="text/css" href="dbrm/root/styles/style.css"/>
>         <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
>         <title>[% page.title %]</title>
>     </head>
>     <body>
>         [% page.content %]
>     </body>
> </html>
> Например страницу с id=1


$c->stash->{page} = $c->model('DBI::Content::Return')->return( '1' );

Всё, больше ничего не нужно, View тебе разрисует одну страницу. Хочешь [зачем-то] больше - описывай цикл в самом шаблоне.


> Ни как не могу понять, как мне отправить данные хэша $my_content, в
> определенный шаблон. И уже подготовленный html код вставить в $c->page->content

см. 1) TT ожидает данные в $c->stash


Про Catalyst - я сначала заменил DBIx на самоделку, потом заменил TT на Xslate, потом бросил всё и ушёл на Poet::Mason. Однако Catalyst необходим, чтобы понять, как вообще писать такие прилады.

Ответить | Правка | ^ к родителю #0 | Наверх | Cообщить модератору

3. "Catalyst сборка шаблона в переменную"  +/
Сообщение от z0091 (ok) on 03-Ноя-12, 15:55 
Большое спасибо за ответ.

>

 
> $c->stash->{page} = $c->model('DBI::Content::Return')->return( '1' );
>

> Всё, больше ничего не нужно, View тебе разрисует одну страницу. Хочешь [зачем-то]
> больше - описывай цикл в самом шаблоне.

Сейчас я так делаю:


$c->stash->{content} = $c->model('DBI::Content::Return')->return( $id );
    $c->stash->{content} = $c->view('TT')->render( $c, 'content.html' );  

В итоге переменная  $c->stash->{content} содержит подготовленные html с данными контента.
После сборки, все это вставляется во враппер:

[% content %]

Ответить | Правка | ^ к родителю #2 | Наверх | Cообщить модератору

4. "Catalyst сборка шаблона в переменную"  +/
Сообщение от ACCA (ok) on 05-Ноя-12, 08:09 
>
 
> $c->stash->{content} = $c->model('DBI::Content::Return')->return( $id );
>     $c->stash->{content} = $c->view('TT')->render( $c, 'content.html' );
>

> В итоге переменная  $c->stash->{content} содержит подготовленные html с данными контента.

Это лишнее. Ты же всё равно раскатываешь для browser, пускай content.tt2 сам этим занимается.

Основная идея - насовать в хэш $c->stash объекты и значения, которые разрисует View. При этом принципиально не рендерить ничего вручную, а уж тем более в контроллере.

Водку с портвейном можно, конечно, мешать, но пронесёт.

Ответить | Правка | ^ к родителю #3 | Наверх | Cообщить модератору

5. "Catalyst сборка шаблона в переменную"  +/
Сообщение от z0091 (ok) on 17-Дек-12, 00:38 
>[оверквотинг удален]
>> $c->stash->{content} = $c->model('DBI::Content::Return')->return( $id );
>>     $c->stash->{content} = $c->view('TT')->render( $c, 'content.html' );
>>
>> В итоге переменная  $c->stash->{content} содержит подготовленные html с данными контента.
> Это лишнее. Ты же всё равно раскатываешь для browser, пускай content.tt2 сам
> этим занимается.
> Основная идея - насовать в хэш $c->stash объекты и значения, которые разрисует
> View. При этом принципиально не рендерить ничего вручную, а уж тем
> более в контроллере.
> Водку с портвейном можно, конечно, мешать, но пронесёт.

Спасибо.

Если я Вас правильно понял, то можно все сделать например так
$c->model('DBI::Content::Return')->return( $id );


В DBI::Content::Return

$keys_db->{ $content_f->{id}  }->{title} = $content_f->{title};
            $c->stash->{date} = $content_f->{date};
            $c->stash->{published} = $content_f->{published};
            $c->stash->{autor} = $content_f->{autor};
            $c->stash->{content} = $content_f->{content};

И вопрос возможно немного не по теме.

Как лучше/рациональнее реализовать бизнес логику url

Сейчас у меня так:

Root.pm
sub begin : Private  - работа с куки, чтение конфигов

Post.pm
sub index : Path :Args(1) {   -  url/post/$id  - обращение к странице. Шаблон соответственно лежит в post/index.html

    if ( $c->model('DBI::Content::Return')->return( $id_post ) == 1 ) {
        $c->stash->{template} = 'error_404';
        $c->response->status(404);

Таким костылем я осуществляю проверку параметра $id.

Но Все это тупо и не красиво.
Хочу избавиться от return.

Стоит ли отдать под контроль url в Root::begin?


И еще вопрос.

Куда писать данные(в том числе и временные системные)? чтобы они были доступны из любого места.
$c->stash ?

Ответить | Правка | ^ к родителю #4 | Наверх | Cообщить модератору

6. "Catalyst сборка шаблона в переменную"  +1 +/
Сообщение от ACCA (ok) on 17-Дек-12, 08:36 
> Если я Вас правильно понял, то можно все сделать например так
> $c->model('DBI::Content::Return')->return( $id );
> В DBI::Content::Return
> $keys_db->{ $content_f->{id}  }->{title} = $content_f->{title};
> $c->stash->{date} = $content_f->{date};
> $c->stash->{published} = $content_f->{published};
> $c->stash->{autor} = $content_f->{autor};
> $c->stash->{content} = $content_f->{content};

Это тебя в другую сторону перекосило - не дело модели лазить в stash. Избегай излишних присваиваний. Если $c->stash не содержит ничего, кроме $content_f, смело делай $c->{stash} = $content_f. Приятный побочный эффект - что добавляешь в Model, сразу становится видимым во View.


>[оверквотинг удален]
>         $c->stash->{template} = 'error_404';
>         $c->response->status(404);
> Таким костылем я осуществляю проверку параметра $id.
> Но Все это тупо и не красиво.
> Хочу избавиться от return.
> Стоит ли отдать под контроль url в Root::begin?

Вопрос сложный, следующий будет - а не нужно ли переделать URL, чтобы был вид /$id/xxx/xxx и применить Chained? То есть сначала убедиться, что $id существует, а уже потом разбираться, что следует делать.

Вся проблема - артефакт Catalyst с его Chained контроллерами. В других языках решается через наследование, где предок разбирается с ID, а потомки разбираются с более детальными инструкциями.


> И еще вопрос.
> Куда писать данные(в том числе и временные системные)? чтобы они были доступны
> из любого места.
>  $c->stash ?

В одном цикле запрос/ответ - всё равно. Хоть в $c->stash, хоть во $c->flash, хоть в глобальную переменную.

Неприятные вопросы появляются, когда один контроллер вызывает другой, то есть stash уже не годится, а session замусоривать не хочется. В Poet::Mason эта проблема решается принципиально по-другому, там нет нужды во всей банде go/visit/detach/Chained и неочевидной передачей параметров.


В Catalyst иногда приходится делать такое -


    my @path = split /\//, $c->req->path;

    $path[1] = 'double';
    $path[$#path-1] = $key;
    $path[$#path] = $last;
        
    $c->req->path(join('/', '',@path));
    
    $c->dispatcher->prepare_action($c);
    $c->detach($c->action, $c->req->args);

Что означает "вызвать другой контроллер, передав ему в URL вычисленные аргументы"

Ответить | Правка | ^ к родителю #5 | Наверх | Cообщить модератору

7. "Catalyst сборка шаблона в переменную"  +/
Сообщение от z0091 (ok) on 17-Дек-12, 17:46 
Спасибо за разъяснения. В итоге получилось так


Post.pm

sub index : Path :Args(1) {
    my ( $self, $c, @args ) = @_;

    my $id_post = $c->request->arguments->[0];

    my $error_404;
    $c->stash->{site} = undef;

    unless ( $id_post =~ /^\d+?$/ ) {
        $c->detach('/error_404');
    }

    $c->stash->{site}->{content}->{id_post} = $id_post;
    $c->model('DBI::Content::Return')->return( $c );
}

DBI::Content::Return

sub return {
    my ( $self, $c ) = @_;
    my $dbh = $self->dbh;

    my $post_id = $c->stash->{site}->{content}->{id_post};

    my $contents = $dbh->selectall_arrayref(qq{
        SELECT * FROM  `posts` WHERE `id` = $post_id },
    { Slice => {} } )
    or die "Couldn't select books: " . $dbh->errstr;


    unless ( @{$contents} ) {
        $c->detach('/error_404');
    } else {
        foreach my $content_f (@$contents) {
            $c->stash->{site}->{content} = $content_f;
        }
    }
}

Ответить | Правка | ^ к родителю #6 | Наверх | Cообщить модератору

8. "Catalyst сборка шаблона в переменную"  +/
Сообщение от ACCA (ok) on 19-Дек-12, 04:19 
> Post.pm
> sub index : Path :Args(1) {
>     my ( $self, $c, @args ) = @_;
>     my $id_post = $c->request->arguments->[0];

sub index : Path :Args(1) {
     my ( $self, $c, $id_post ) = @_;


>     $c->stash->{site}->{content}->{id_post} = $id_post;
>     $c->model('DBI::Content::Return')->return( $c );

Не показывай модели $c, разводишь бардак. Верни значение контроллеру, это его забота, что делать дальше.


> DBI::Content::Return
> sub return {
>     my ( $self, $c ) = @_;
>     my $dbh = $self->dbh;
>     my $post_id = $c->stash->{site}->{content}->{id_post};

Ты, конечно, можешь прятать лифчики в ящике с цветными карандашами, но кто их потом сможет найти?

Модель должна вернуть данные.
Контроллер может слепить stash, если хочет. У каждого есть своё дело и очередь, когда его делать.


>     my $contents = $dbh->selectall_arrayref(qq{
>         SELECT * FROM  
> `posts` WHERE `id` = $post_id },
>     { Slice => {} } )
>     or die "Couldn't select books: " . $dbh->errstr;

Не, это не пойдёт. Прочитай про DBIx и вообще про ORM, у тебя типичная задача для него.


>     unless ( @{$contents} ) {
>         $c->detach('/error_404');
>     } else {
>         foreach my $content_f (@$contents)
> {
>             $c->stash->{site}->{content} = $content_f;
>         }

Пробуй ещё, цикл здесь не нужен. Если posts.id не уникален, ты неправильно выполнил декомпозицию. В общем случае, если хочешь получить всё равно какой элемент массива, делай pop @$contents или $contents->[0]

Ответить | Правка | ^ к родителю #7 | Наверх | Cообщить модератору

Архив | Удалить

Рекомендовать для помещения в FAQ | Индекс форумов | Темы | Пред. тема | След. тема




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2025 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру