Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: разработка для Web > [Catalys] Кодировка


Автор: DEER 8.10.2009, 12:59
Добрый день.
Столкнулся с такой проблемой.
Начну сначала.
Изначально проект был на windows-1251 (и классы и шаблоны, и бд)
все работало, но приходилось в каждом action контролеров явно указывать 
Код

    $c->res->content_type( "text/html; charset=windows-1251" );
    $c->stash->{template}    = 'site/record/edit.tt';

то есть явно указывать, что content_type должен быть windows-1251. Это все работало, но именно это явное указание не понтравилось "заказчику".
В связи с этим вопрос №1: Можно ли как то, где то указать, что content_type должен быть windows-1251? К конфиге каком нибудь? Все облазил - не нашел.
Далее решил, что раз Catalyst работает с utf8, то пусть и проект будет на utf8
Изменил кодироку в БД у таблиц, изменил кодировку у классов проекта и шаблонов.
В модели сделал такой конфиг
Код

__PACKAGE__->config(
    schema_class => 'PhoneBook::DBClass',
    connect_info => [
        'dbi:mysql:phonebook',
        'root',
    '',
        { 
        AutoCommit => 1,
        mysql_enable_utf8   => 1,
            on_connect_do => [
                'SET character_set_client = utf8',
                'SET character_set_connection = utf8',
                'SET character_set_results = utf8',
            ],
        },
    ],
);


все. у меня все работает и отображается.
Отослал проверить. Но у "заказчика" вылетает ошибка. Он ввел в поле русские символы и теперь
Код

[info] *** Request 35 (0.443/s) [2476] [Thu Oct  8 13:33:49 2009] *** [debug] "GET" request for "person" from "10.10.6.2"
[debug] Path is "person"
[debug] Rendering template "person/index.tt"
[error] Caught exception in engine "Wide character in syswrite at /usr/local/lib/perl5/site_perl/5.10.0/Catalyst/Engine.pm line 635."

почитал на счет этой ошибки. Даже тут на форуме есть тема про это. Что получается? Я должен каждый парамерт из запросов и БД изменять
Код

$string = Encode::decode('utf-8', $some_utf8_octets);

Не за что не поверю smile Может как то можно бороться с этой проблемой?
в сети нашел Catalyst::Plugin::Unicode, может он поможет? проблема в том, что у меня не воспроизводиться такая ошибка.

Автор: gcc 8.10.2009, 14:18
я держу всегда везде в utf8

Код

sub end : Private {
    my ( $self, $c ) = @_;
 $c->res->content_type( "text/html; charset=windows-1251" );
    $c->forward('MyApp::View::HTML::Template');
}


или
Код

sub begin : Private {
 $c->res->content_type( "text/html; charset=windows-1251" );
}


скорее всего begin

Добавлено через 6 минут и 40 секунд
а зачем вы его перевли на utf8?

может быть стоит все таблицы перевести в utf8?

Автор: DEER 8.10.2009, 14:33
да в том и прикол, что все таблицы тоже в utf8 и шаблоны в utf8 и классы в utf8


первый вопрос сам разобрал.
переопределил метод process и View и там поставил нужный content_type. Странно, что пол года назад это не получилось сделать...

Автор: DaemonSuw 9.10.2009, 23:58
В перле бы хорошо врубить магическую переменную $ENV{PERL_UNICODE} где нибудь "в начале" (не знаю где начало в каталисте - не работал) в блоке BEGIN {} но 100% уверенности нету(

Автор: kapany3 4.11.2009, 19:00
Цитата(DEER @  8.10.2009,  12:59 Найти цитируемый пост)
№1: Можно ли как то, где то указать, что content_type должен быть windows-1251? К конфиге каком нибудь?


Я решил данную проблему изменив подпрограмму в контроллере Root.pm 
Код

sub end : ActionClass('RenderView') {
my ( $self, $c ) = @_;
$c->res->content_type( "text/html; charset=windows-1251" );
}
 
Т.е. достаточно указать эту строчку только один раз, а не впихивать в каждую подпрограмму.

Кстати говоря, проблема возникла из-за невозможности поиска case insensitive в кодировке utf-8 в MySQL, хоть на конце кодировке в базе и красуется ci  (т.е. case insensitive). Поиск ci в этой кодировке происходит только с буржуйским алфавитом. Так что подумай, прежде чем переходить на utf-8. 

Автор: sir_nuf_nuf 4.11.2009, 20:32
Кстати знатоки каталиста, напишите плиз в каком порядке выполняются действия контроллеров.
Помнится было какое - то действие, которое дергалось вперед всего в любом случае. Вот в нем то можно выставлять content-type

Автор: kapany3 5.11.2009, 09:51
Цитата(sir_nuf_nuf @  4.11.2009,  20:32 Найти цитируемый пост)
Кстати знатоки каталиста, напишите плиз в каком порядке выполняются действия контроллеров.
Помнится было какое - то действие, которое дергалось вперед всего в любом случае. Вот в нем то можно выставлять content-type 


Я каталист юзаю недавно, и на сколько мне известно, то нет такого действия. При создании нового проекта  у вас в контроллере Root есть две подпрограммы: index и end. index можно переназвать или удалить вовсе, и ничего страшного не произойдёт. А вот end - действие, которое выполняется в обязательном порядке самым последним, его удалять нельзя. В доках сказано, что даже если вы ничего не собираетесь делать в этой подпрограмме, то она всё равно должна быть, хоть и пустая. Т.е. первого действия нет обязательного, последнее есть в которое можно и вставить content-type и оно отработает как раз перед передачей параметров шаблону.

Автор: sir_nuf_nuf 5.11.2009, 16:37
Да это вообщем пофигу первое оно или последнее.
Главное что бы оно выпонлнялось при любом запросе.

Т.е. Root::end() - вызывается в любом случае ? - тогда нужно переопределять его.

Автор: DEER 5.11.2009, 17:28
а все описал в View
Код

sub process {
    my ( $self, $c ) = @_;
    $c->res->content_type( "text/html; charset=windows-1251" );
    $self->SUPER::process( $c, @_ );
}

"заказчику" (www.reg.ru) подошел такой подход.
То есть так можно делать получается

Автор: kapany3 5.11.2009, 22:14
Цитата(sir_nuf_nuf @  5.11.2009,  16:37 Найти цитируемый пост)
Да это вообщем пофигу первое оно или последнее.
Главное что бы оно выпонлнялось при любом запросе.

Т.е. Root::end() - вызывается в любом случае ? - тогда нужно переопределять его. 


у меня этот способ работает, я поправил 
Код

sub end : ActionClass('RenderView')
 в контроллере Root.pm
Судя по докам он отрабатывает при каждом запросе, когда все действия в контроллере выполнены (если этого метода нет в контроллере к которому произошёл запрос, то он ищется дальше, т.е. в родителе Root.pm). Кстати, как оказалось есть подобный метод, который отрабатывает в самом начале запроса, зовётся begin.


Цитата(DEER @  5.11.2009,  17:28 Найти цитируемый пост)
а все описал в View
Выделить всёкод Perl
sub process {
    my ( $self, $c ) = @_;
    $c->res->content_type( "text/html; charset=windows-1251" );
    $self->SUPER::process( $c, @_ );
}


Это по-моему более логичный вариант чем указывать кодировку в sub end : ActionClass('RenderView'). Буду его использовать. Спасибо за идею! smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)