Диспетчер катализаторов для произвольной древовидной структуры - PullRequest
2 голосов
/ 19 февраля 2011

Привет,

Я новичок в Catalyst и пытаюсь реализовать некоторую логику отправки.

В моей базе данных есть таблица элементов, каждый из которых имеет уникальное поле url_part,и каждый элемент имеет родителя в одной и той же таблице, образуя древовидную структуру.Если baz является дочерним по отношению к bar, который является дочерним по отношению к foo, который является дочерним по отношению к корню, я хочу, чтобы URL /foo/bar/baz отображался на этот объект.Дерево может быть любой глубины, и пользователям потребуется доступ к любому узлу, будь то ветвь или лист.

Я просматривал документацию для связанных диспетчеров, но я не уверен, что это можно сделатьчто я хочу.Кажется, что каждый шаг в цепочечном диспетчере должен иметь определенное имя для атрибута PathPart, но я хочу, чтобы мои URL-адреса определялись исключительно структурой базы данных.

Это легко реализовать с помощью существующего Catalystдиспетчер, или мне нужно написать свой собственный класс диспетчеризации?

Спасибо!:)

ETA:

Я понял, что могу использовать пустой атрибут Args для перехвата произвольного числа аргументов.Кажется, что следующий запрос успешно перехватывает каждый запрос в корне:

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

    my $path = $c->request->path;

    $c->response->status( 200 );
    $c->response->body( "Your path is $path" );
}

Оттуда я могу вручную проанализировать путь и получить то, что мне нужно, однако я не знаю, является ли это лучшим способом выполнитьчто я после.

Ответы [ 2 ]

2 голосов
/ 19 февраля 2011

Это зависит от структуры ваших данных, которая мне не совсем понятна из вашего вопроса.

Если существует фиксированное количество уровней (или, по крайней мере, ограниченный диапазон чисел уровней) с каждым уровнем, соответствующим определенному виду вещей, то Chained может делать то, что вы хотите - он действителен (и совершенно обычен) иметь связанное действие с :CaptureArgs(1) PathPart(''), которое создаст сегмент /*/ в пути, то есть он сожрет один сегмент пути, не требуя показа какой-либо определенной фиксированной строки.

Если такого нет, например, вы гоняете неограниченное количество уровней вниз по произвольному дереву, тогда, вероятно, именно то, что вам нужно, - это действие :Args, и в его использовании нет ничего грязного. Но вам не нужно самостоятельно декодировать $c->req->path - вы можете получить оставшиеся сегменты пути от $c->req->args или просто выполнить my ($self, $c, @args) = @_; в своем действии. Вы можете написать новый тип DispatchType, но это вряд ли окупится.

0 голосов
/ 24 февраля 2011

Поиграв с различными вариантами, я считаю, что нашел приемлемое решение. К сожалению, я не смог получить рекурсивную рассылку с :Chained (Catalyst жалуется, если вы пытаетесь связать обработчик с самим собой. Это не весело.)

Итак, я использовал один обработчик с большим CaptureArgs, например:

sub default : CaptureArgs(10) PathInfo('') { 
    my ( $self, $c, @args ) = @_;

    foreach my $i( 0 .. $#args ) { 
        my $sub_path = join '/', @args[ 0 .. $i ];

        if ( my $ent = $self->_lookup_entity( $c, $sub_path ) ) { 
            push @{ $c->stash->{ent_chain} }, $ent;
            next;
        }

        $c->detach( 'error_not_found' );
    }

    my $chain = join "\n", map { $_->entity_id } @{ $c->stash->{ent_chain} };
    $c->response->content_type( 'text/plain' );
    $c->response->body( $chain );
}

Если я сделаю GET на /foo/bar/baz, я получу

foo
foo/bar
foo/bar/baz

что я и хочу. Если какая-либо часть URL не соответствует объекту в БД, я получаю 404.

Это прекрасно работает для моего приложения, которое никогда не будет иметь глубину в десять уровней, но я бы хотел найти более общее решение, которое могло бы поддерживать дерево произвольной глубины.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...