Search
Write a publication
Pull to refresh

Mojolicious. MVC фреймворк для Perl

Что же такое Mojolicious?


Автором сего чуда есть ни кто иной как создатель фреймворка Catalyst — Sebastian Riedel. Что же толкнуло создателя одного Perl фреймворка создать другой? Catalyst имеет очень служную архитектуру. К тому же, как и во многих существующих MVC фреймворках, Catalyst имеет единственный вариант роутинга — это
example.com///. Основное достоинство Catalyst — это повторое использование кода. Для чего же стоило заморачиваться с новым фреймворком? Что же есть такого в Mojolicious?
Mojolicious — это настоящий фреймфорк для Perl, который отвечает всем принципам языка:
«Есть больше одного способа это сделать» («There’s more than one way to do it»), известный также под аббревиатурой TMTOWTDI; «Простые вещи должны оставаться простыми, а сложные стать выполнимыми» («Easy things should be easy and hard things should be possible». Catalyst стал черновиком для Mojolicious, который выделяется следующими фичами:

* Полностью объектно ориентированое API
* Поддержка HTTP 1.1(REST), WebSocket, IPv6, SSL, IDNA
* Поддержка CGI, FastCGI, PSGI, Daemon, Prefork
* Отсутствие зависимостей (начиная с Perl 5.8.1)

Piccy.info - Free Image Hosting

Слова — вода! А где же код?


Как и в самом Perl, все плюшки можно осознать, только после рассмотрения основных модулей и примеров их использования.

Рассмотрим самые вкусные атрибуты класса Mojolicious:
* controller_class — Класс который используется в качестве контроллера по умолчанию(по умолчанию Mojolicious::Controller)
my $class = $app->controller_class;
$app = $app->controller_class('Mojolicious::Controller');

* mode — определяет режим в котором работает приложение. Вы можете добавлять код уникальный для приложения в режиме разработки или в продакшине.
my $mode = $app->mode;
$app = $app->mode('production');

sub development_mode {
my $self = shift;
}

sub production_mode {
my $self = shift;
}

* plugin — загрузчик плагинов (по умолчанию Mojolicious::Plugins)
my $plugins = $app->plugins;
$app = $app->plugins(Mojolicious::Plugins->new);

* renderer — Определяет класс, который используется для создания ответа от сервера. (по умолчанию Mojolicious::Renderer)
my $renderer = $app->renderer;
$app = $app->renderer(Mojolicious::Renderer->new);

* routes — определяет класс, который используется для роутинга запросов. (по умолчанию Mojolicious::Routes)
my $routes = $app->routes;
$app = $app->routes(Mojolicious::Routes->new);


И методы:
* hook — дает возможность прицепиться на какой-то именованый ивент. это экспериментальный метод, но на мой взгляд — самый интересный
$app->hook($event => sub { ... });
список доступных ивентов: after_build_tx, before_dispatch, after_static_dispatch, after_dispatch
* plugin — загружает плагин.

А теперь немного подробнее про использование некоторых классов
Mojolicious::Controller:
*render
render(controller=>'foo',action=>'bar');
render('foo#bar')
render('foo#bar', format=>'html');
render(template=>'foo/bar');

* render_text
render_text('Hello world!');
render(text=>'Hello world!');

* render_data
render_data('binary data');
render(data=>'binary data');

* render_json
render_json({foo=>'bar'});
render(json=>{foo=>'bar'});

* render_static
render_static('img/logo.png');
Методы render возвращают ответ клиенту в заданов формате или с использованием темплейтов. Для того чтобы иметь доступ к ответу, а не отправлять его, например для отправки его в качестве имейла, необходимо использовать параметр partial.
my $html = $self->render('mail', partial => 1);
Вы так же можете передавать статус код через параметр status
$self->render(text => 'Oops!', status => 500);
Или Content-Type и MIME тип через параметр format, что может быть полезным, если Вы генерируете какой-нибудь файл на стороне сервера или храните какие-то файлы в БД.
$self->render(text => 'Hello!', format => 'txt');
$self->types->type(txt => 'text/plain; charset=utf-8');

* render_not_found/render_excepton
* send_message/receive_message
* url_for/redirect_to
Данные в темплейты передаются через stash следующим образом:
$self->stash(author => 'Sebastian');
$self->stash(frameworks => [qw/Catalyst Mojolicious/]);
$self->stash(examples => {tweetylicious => 'a microblogging app'});

темплейт:
<% for my $framework (@$frameworks) { %>
<%= $framework %> was written by <%= $author %>.
<% } %>

<% while (my ($app, $description) = each %$examples) { %>
<%= $app %> is a <%= $description %>.
<% } %>

Mojolicious::Routes:
Итак, в большинстве фреймворков диспатчер работает по одному определенному принципу. В Mojolicious же этот процесс сделан более динамическим.
Маршруты могут быть описаны не только статической строкой, но и регулярным выражением. Так же в маршрутах данного фреймворка введено понятие placeholder.
Например хабрамаршрут к статье /blogs/social_networks/111416 может быть обобщен с помощью регулярных выражений как /blogs/(\w+)/(\d+) или с помощью placeholder'ов /blogs/:blog/:article
placeholder'ы бывают 3х типов:
1. Обычные — находят все символы, кроме / и.
/hello -> /:name/hello -> undef
/sebastian/23/hello -> /:name/hello -> undef
/sebastian.23/hello -> /:name/hello -> undef
/sebastian/hello -> /:name/hello -> {name => 'sebastian'}
/sebastian23/hello -> /:name/hello -> {name => 'sebastian23'}
/sebastian 23/hello -> /:name/hello -> {name => 'sebastian 23'}

2. «Ослабленые» — находят все символы, кроме /
/hello -> /(.name)/hello -> undef
/sebastian/23/hello -> /(.name)/hello -> undef
/sebastian.23/hello -> /(.name)/hello -> {name => 'sebastian.23'}
/sebastian/hello -> /(.name)/hello -> {name => 'sebastian'}
/sebastian23/hello -> /(.name)/hello -> {name => 'sebastian23'}
/sebastian 23/hello -> /(.name)/hello -> {name => 'sebastian 23'}

3. «Расширеные» — Находят все символы
/hello -> /(*name)/hello -> undef
/sebastian/23/hello -> /(*name)/hello -> {name => 'sebastian/23'}
/sebastian.23/hello -> /(*name)/hello -> {name => 'sebastian.23'}
/sebastian/hello -> /(*name)/hello -> {name => 'sebastian'}
/sebastian23/hello -> /(*name)/hello -> {name => 'sebastian23'}
/sebastian 23/hello -> /(*name)/hello -> {name => 'sebastian 23'}

Для определения цели маршрута используется метод to. Простой пример:
# /welcome -> {controller => 'foo', action => 'welcome'}
$r->route('/welcome')->to(controller => 'foo', action => 'welcome');

Передача данных без явного использования stash:
# /bye -> {controller => 'foo', action => 'bye', mymessage => 'Bye!'}
$r->route('/bye')
->to(controller => 'foo', action => 'bye', mymessage => 'Bye!');

обозначение controler/method в виде 'controler#method' уместно не только в рендере, но и здесь, тогда предидущий пример будет выглядеть так:
# /bye -> {controller => 'foo', action => 'bye', mymessage => 'Bye!'}
$r->route('/bye')->to('foo#bye', mymessage => 'Bye!');

В качестве цели маршрута может служить класс(namespace)
# /bye -> MyApp::Controller::Foo->bye
$r->route('/bye')->to('foo#bye', namespace => 'MyApp::Controller');

или метод:
$r->route('/bye')->to(cb => sub {
my $self = shift;
$self->render(text => 'Good bye!');
});

Так же Вы можете для большего удобства задавать имена маршрутам, например для получения полной строки запроса:
# /foo/abc -> {controller => 'foo', action => 'bar', name => 'abc'}
$r->route('/foo/:name')->name('test')
->to(controller => 'foo', action => 'bar');

# Generate URL "/foo/abc" for route "test"
$self->url_for('test');

# Generate URL "/foo/sebastian" for route "test"
$self->url_for('test', name => 'sebastian');

Так же фреймворк предоставляет возможность использовать разные маршруты для разных типов HTTP запросов
# GET /bye -> {controller => 'foo', action => 'bye'}
# POST /bye -> undef
# DELETE /bye -> undef
$r->route('/bye')->via('get')->to(controller => 'foo', action => 'bye');

# GET /bye -> {controller => 'foo', action => 'bye'}
# POST /bye -> {controller => 'foo', action => 'bye'}
# DELETE /bye -> undef
$r->route('/bye')->via(qw/get post/)
->to(controller => 'foo', action => 'bye');


В Mojolicious::Lite для этого используется более простая запись:
# GET /yada
# POST /yada
my $yada = $r->under('/yada');
$yada->get(sub {
my $self = shift;
$self->render(text => 'Hello!');
});
$yada->post(sub {
my $self = shift;
$self->render(text => 'Go away!');
});


Вместо заключения.


Mojolicious — очень гибкий и мощный фреймворк для Perl, который, ко всему прочему, вполне может потягаться с большинством современных фреймворков для модных языков программирования. Что в свою очередь показывает, что не стоит збрасывать со счетов Perl прогаммистов и пренебрегать Perlом как вариантом языка для разработки своего веб проекта. Описаное в этой статье — это всего-навсего маленькая часть возможностей.
Большая презентация с кучей примеров: тыц
Официальный сайт: http://mojolicio.us/
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.