Mojolicious (вимовляється «моджолішес») - це новий і активно розвивається веб-фреймворк. написаний на Perl. І написав його не аби хто, а Sebastian Riedel, який є одним з розробників Catalyst. Останнім часом Mojolicious став темою активного обговорення в співтоваристві Perl-програмістів, так що я просто не міг його не спробувати.
1. Що пишуть про Mojolicious?
Якщо вбити в гуглі слово Mojolicious, можна знайти такі його огляди:
Почитавши все це, я так і не зрозумів найголовнішого - чим же такий хороший Mojolicious. що все про нього говорять. Дійсно він мені потрібен, або це просто чиїсь заморочки на тему ідеальної архітектури додатку, вчиненого коду і тп? І врешті-решт цікавість узяла наді мною вгору.
2. Встановлення та налаштування
Mojolicious можна поставити з CPAN або, якщо ви користуєтеся FreeBSD, з портів. До речі, під FreeBSD тепер стандартним інтерпретатором Perl став 5.12, бо 5.10 більше не підтримується. Не забудьте оновитися!
pkg_upgrade -o perl-5.12.3 perl-5.10.1_3
pkg_add -r p5-Mojolicious
Що приємно, фреймворк не тягне за собою ніяких залежностей. Catalyst, як я чув, тягне за собою Moose. а це дуже багато пакетів. Далі я створив свій перший проект:
/ Projects / mojolicious / test_app /
cd
/ Projects / mojolicious / test_app /
mojo generate app TestApp
З'явилася така структура каталогів:
lib - тут зберігається весь код
log - сюди пишуться логи
public - статичні файли (css, js, картинки)
script - ядро Моджолішеса
t - всі тести
tempaltes - шаблони сторінок
Також було створено трохи коду, який відразу можна перевірити в дії. Наше додаток може працювати під Apache або Nginx. але під час налагодження найзручніше використовувати вбудований веб-сервер Моджолішеса:
/ Test_app / script / test_app daemon --restart
За замовчуванням сервер слухає 3000-й порт.
Якщо хочете знати мою думку, вбудований веб-сервер - це охренительно. Більше не потрібно перекручуватися, піднімаючи локальний Apache. Або займатися написанням коду в VIM через SSH-з'єднання. Ні, VIM + SSH - це теж добре. До тих пір, поки з інтернетом все в порядку. Ну або поки потрібно робити тільки невеликі правки.
У мене з вбудованим веб-сервером виникла тільки одна проблема. Під Віндою (Windows 7 + Strawberry Perl) ключ - -restart чомусь не працює. В результаті, сервер доводиться перезапускати вручну після внесення змін до коду.
Доповнення: У нових версіях Mojolicious прибрали ключик - -restart. Замість нього пропонується використовувати сервер morbo:
morbo script / test_app
Як використовувати Mojolicious в режимі CGI, FastCGI і PSGI, можна прочитати в Mojolicious :: Guides :: Cookbook. Все досить просто. Наприклад, прикручування до Apache в режимі CGI здійснюється одним рядком в httpd.conf:
ScriptAlias / test_app "/ path / to / script / test_app"
..., а команди ...
cd / usr / local / www / apache22 / data /
chown -R eax: www. / test_app
chmod -R g + rx. / test_app
... виправили ситуацію. Начебто, все працює. Однак якщо зазирнути в логи додатки, виявляється, що дещо працює не зовсім правильно:
Позбутися від цих повідомлень дуже просто - достатньо дописати в ./test_app/lib/TestApp.pm наступне:
# Цей метод викликається один раз при запуску сервера
sub startup # 123;
my $ self = shift;
# ОСЬ, ЩО дописувати:
# Secret passphrase можна отримати за допомогою pwgen -s 16
$ Self -> secret # 40; '* POpRTm; M<;5?fk
3. Рауса і обробка аргументів
Трохи покуривши документацію, я більш-менш зрозумів загальний принцип роботи фреймворка. Наприклад, щоб додати на наш сайт нову сторінку, потрібно дописати в метод TestApp :: startup () наступне:
# Для сторінки / example-page /, запитувану методом GET:
$ R -> route # 40; '/ Example-page /' # 41; -> via # 40; 'Get' # 41; -> to # 40; 'Example-page # index' # 41; ;
# Для тієї ж сторінки, запитуваної методом POST:
# -> via ( 'post') -> to ( 'example-page # result');
# Якщо метод не важливий:
# $ R-> route ( '/ example-page /') -> to ( 'example-page # result');
Далі створюємо test_app / lib / TestApp / Example / Page.pm:
package TestApp. Example. Page;
use Mojo. Base 'Mojolicious :: Controller';
# Виводимо example-page
sub index # 123;
my # 40; $ self # 41; = @_;
# Мені дуже хотілося написати про можливість вести логи,
# Але не знав, куди запхати цю одну сходинку коду :)
$ Self -> app -> log -> debug # 40; "Rendering / example-page /." # 41; ;
$ Self -> render # 40; var1 => '123'. var2 => '456' # 41; ;
# 125;
Як ви могли помітити, тут має місце зв'язок з Рауса:
$ R -> route # 40; '/ Ім'я-сторінки /' # 41; -> to # 40; 'Ім'я-класу # метод' # 41; ;
Імена сторінок при цьому, зрозуміло, можуть бути будь-якими. Якщо потрібно отримати передані користувачем аргументи, це робиться так:
# Отримати імена всіх параметрів:
my @names = $ self -> param;
# Отримати параметр по його імені:
my $ value = $ self -> param # 40; "Name" # 41; ;
# Отримати параметр, переданий методом GET:
my $ value = $ self -> req -> query_params -> param # 40; "Name" # 41; ;
# Отримати параметр, переданий методом POST:
my $ value = $ self -> req -> body_params -> param # 40; "Name" # 41; ;
Подробиці щодо обробки запитів можна подивитися тут.
4. Готуємо шаблони
Сторінка вже майже готова, залишилося тільки зробити для неї шаблон. Для цього створюємо файл templates / example / page / index.html.ep:
% Layout 'default';
% Title 'Превееед!';
Це - тестова сторінка.
Мінлива var1 = <% = $var1 %>. а var2 = <% = $var2 %> .
Перейти На головну a>. p>
Перший рядок визначає лейаут (див templates / layouts /). Далі йде визначення заголовка сторінки і власне код сторінки. Як бачите, в імені шаблону присутня ім'я класу і його методу. «Html» в назві шаблону ніби натякає на формат, в якому ми віддаємо дані. У тому ж каталозі можна створити файл index.json.ep або index.xml.ep для виведення даних у відповідних форматах.
5. Пишемо тести
Далі я написав тест для щойно створеної сторінки. Це не обов'язково, але сильно спрощує життя, коли з замовника РАПТОМ починає перти креатив. Тести дозволяють переконатися, що при зміні сайту нічого не відвалилося. І так, я в курсі, що TDD передбачає написання тестів перед написанням коду, але я ж зараз в фреймворку розбираюся, а не працюю над реальним проектом. Отже, файл t / example-page.t:
use strict;
use Test. More;
use Test. Mojo;
my $ t = Test. Mojo -> new # 40; app => 'TestApp' # 41; ; Copyright © 2024
$ T -> get_ok # 40; '/ Example-page /' # 41; ;
$ T -> status_is # 40; 200 # 41; ;
$ T -> content_type_is # 40; 'Text / html; charset = UTF-8' # 41; ;
$ T -> content_like # 40; qr #