...
Code Block | ||||
---|---|---|---|---|
| ||||
# Мы объявляем package с названием "*модуль*::Api". package Portal::Api; =head1 NAME Portal Api =cut use strict; use warnings FATAL => 'all'; # Импортируем сообщения для ошибок use Control::Errors; my Control::Errors $Errors; #********************************************************** =head2 new($db, $conf, $admin, $lang, $debug, $type) =cut #********************************************************** # Создаём конструктор sub new { my ($class, $db, $admin, $conf, $lang, $debug, $type) = @_; my $self = { db => $db, admin => $admin, conf => $conf, lang => $lang, debug => $debug }; bless($self, $class); $self->{routes_list} = (); # Определяем, для чего роутер вызвал наш модуль API # Соответственно, ли это USER API или ADMIN API # И записываем routes_list if ($type eq 'user') { $self->{routes_list} = $self->user_routes(); } elsif ($type eq 'admin') { $self->{routes_list} = $self->admin_routes(); } $Errors = Control::Errors->new($self->{db}, $self->{admin}, $self->{conf}, # Обязательно обозначить что это за модуль, # чтобы система могла подгрузить сообщения для ошибок со словаря модуля за потребности { lang => $lang, module => 'Portal' } ); # Сохраняем словарь ошибок в объект, он нам потом будет нужен $self->{Errors} = $Errors; return $self; } 1; |
Словарь ошибок
Документация по словарю ошибок
Важная часть - позволяет систематизировать ошибки и избежать разночтений ошибок во время написания кода.
...
Code Block | ||||
---|---|---|---|---|
| ||||
package Portal::Api::admin::AttachmentArticles; =head1 NAME Portal attachmentarticles manage # Рекомендуем в подах записывать к каким # группам эндпойнтов относится данный контроллер Endpoints: /portal/attachmentarticles/* =cut use strict; use warnings FATAL => 'all'; use Control::Errors; # Импортируем объект Portal для работы с базой # он должен находиться в /usr/abills/Abills/mysql/Portal.pm use Portal; use Portal::Misc::Attachments; my Control::Errors $Errors; my Portal $Portal; my ControlPortal::Misc::ErrorsAttachments $Errors$Attachments; #********************************************************** =head2 new($db, $admin, $conf) =cut #********************************************************** sub new { my ($class, $db, $admin, $conf, $attr) = @_; my $self = { db => $db, admin => $admin, conf => $conf, attr => $attr }; bless($self, $class); $Portal = Portal->new($db, $admin, $conf); #$Attachments Определяем словарь ошибок, который = Portal::Misc::Attachments->new($self->{db}, $self->{admin}, $self->{conf}); # Определяем словарь ошибок, который нам пришёл выше $Errors = $self->{attr}->{Errors}; return $self; } #********************************************************** =head2 get_portal_attachmentarticles($path_params, $query_params) # Всегда пишите в подах Endpoint *METHOD* *path* # Это позволит легче искать путь во время разработки. Endpoint GET /portal/attachmentarticles =cut #********************************************************** sub get_portal_attachmentarticles { my $self = shift; my ($path_params, $query_params) = @_; # Определяем системные параметры, сортировки, пагинации my %PARAMS = ( COLS_NAME => 1, PAGE_ROWS => $query_params->{PAGE_ROWS} ? $query_params->{PAGE_ROWS} : 25, SORT => ($query_params->{SORT} || 1) > 5 ? 5 : ($query_params->{SORT} ||: 1), PG => $query_params->{PG} ? $query_params->{PG} : 0, DESC => $query_params->{DESC}, ); # Даём возможность сортировки с помощью ?filename&file_size&file_type foreach my $param (keys %{$query_params}) { $query_params->{$param} = ($query_params->{$param} || "$query_params->{$param}" eq '0') ? $query_params->{$param} : '_SHOW'; } # Вызываем функцию для извлечения списка из базы, с нашими параметрами и которые определены вызовом # которые будут внутри обрабатываться search_former my $results$list = $Portal->attachment>portal_articles_list({ %$query_params, %PARAMS }); ID my @result = map { my $article_sublink = $_-> '_SHOW',{permalink} || $_->{id}; FILENAMEmy $picture_link => '_SHOW', FILE_SIZE => '_SHOW',$_->{picture} ? $self->_portal_picture_link($_->{picture}) : ''; FILE_TYPE => '_SHOW',$_->{url} = $self->_portal_news_link($article_sublink); UPLOADED_AT$_->{picture} => '_SHOW',$picture_link; %$query$_params, %PARAMS, }); #} @$list; # Рекомендация: когда вы создаёте путь, который возвращает массив, то возвращайте # его с объектом с ключём list, а в total возвращайте общее число айтемов - это позволит работать пагинации return { list => $results\@result, total => $Portal->{TOTAL} }; } |
...
Code Block | ||||
---|---|---|---|---|
| ||||
#********************************************************** =head2 user_routes() - Returns available USER API paths =cut #********************************************************** sub user_routes { my $self = shift; return [ { method => 'GET', # Для USER API ОБЯЗАТЕЛЬНО начинаем абсолютный путь с /user/*. path => '/user/portal/menu/', # Подключаем "контроллер" для API /user/portal/* controller => 'Portal::Api::user::News', # Даём ссылку на функцию-эндпойнт контроллера endpoint => \&Portal::Api::user::News::get_user_portal_menunews, credentials => [ # Определяем нужные параметры для авторизации. # USER - авторизация по header, полученном с /user/login # USERSID - авторизация по cookie (в том числе для api_call) # PUBLIC - без авторизации # Тоесть, в данном случае путь может работать как и с авторизованными пользователями, так и нет. # Внутри хэндлера можно определять какой пользователь, об этом ниже. 'USER', 'USERSID', 'PUBLIC' ] }, ] } |
...
Code Block | ||||
---|---|---|---|---|
| ||||
package Portal::Api::user::News; =head1 NAME User Portal # Рекомендуем в подах записывать к каким # группам эндпойнтов относится данный контроллер Endpoints: /user/portal/news* /user/portal/menu =cut use strict; use warnings FATAL => 'all'; use Control::Errors; # Импортируем объект Portal для работы с базой # он должен находиться в /usr/abills/Abills/mysql/Portal.pm use Portal; my Portal $Portal; my Control::Errors $Errors; #********************************************************** =head2 new($db, $admin, $conf) =cut #********************************************************** sub new { my ($class, $db, $admin, $conf, $attr) = @_; my $self = { db => $db, admin => $admin, conf => $conf, attr => $attr }; bless($self, $class); $Portal = Portal->new($db, $admin, $conf); # Определяем словарь ошибок, который нам пришёл выше $Errors = $self->{attr}->{Errors}; return $self; } #********************************************************** =head2 get_user_portal_menunews($path_params, $query_params) Endpoint GET /user/portal/menunews =cut #********************************************************** sub get_user_portal_menunews { my $self = shift; my ($path_params, $query_params) = @_; # Не обязательно писать всю логику прямо внутри эндпоинта, как в примере с ADMIN API # Вы можете ссылаться на другую функцию, для сокращения использования. # Но для простоты понимания, с самого начала лучше писать всё в эндпоинтах return return $self->_portal_menu({ # Если пользователь авторизован - в $path_params->{uid} будет UID пользователя. UID => $path_params->{uid} || '', DOMAIN_ID => $query_params->{DOMAIN_ID}, PORTAL_MENU_ID => $query_params->{PORTAL_MENU_ID}, MAIN_PAGE => $query_params->{MAIN_PAGE}, LIST => 1, }); } 1; |