Kohana и Роут с бесконечным уровнем вложенности каталогов.

В данном посте я хочу сохранить обсуждение и решение проблемы с офф форума . Проблему обозначаю в первой цитате, решение с подсказки сообщества (использовать коллбеки) во второй, т.е. сам код. Работает для 3.2, для 3.3 надо править, чего я не сделал в виду не надобности. У меня проект на 3.2. :)

seyfer July 2013
Добрый день.

Возможно уже существует решение, но я не могу придумать его сам.

Есть структура в папке controller admin admin/settings

В admin лежат контроллеры админки. И базовые, скажем так, классы, для подразделов. В подразделе (например settings) лежат контроллеры страниц подраздела. Работает это таким образом.

Если запрашивается ссылка /admin/settings/ то отрабатывает базовый контроллер, если же /admin/settings/users, то это уже контроллер users в папке settings.

Реализуют это сейчас два роута:

//поддиректории в admin
Route::set(‘subadmin’, ‘(< directory >)/< controller >(/< action >)(/page< page >)(/< id >)(/< id2 >)’, array
(
‘controller’ => ‘[a-z]+’,
‘page’ => ‘[0-9]+’,
‘action’ => ‘[\pL]+’,
//’directory’ => ‘admin(/settings){1}’
‘directory’ => ‘admin/[\pL]+’,
‘page’ => ‘[0-9]+’,
))
->defaults(array(
‘directory’ => ‘admin’,
‘controller’ => ‘main’,
‘action’ => ‘index’,
));
// для админки
Route::set(‘admin’, ‘admin(/< controller >(/< action >(/page< page >)(/< id >)(/< id2 >)))’, array(
‘directory’ => ‘admin’,
‘page’ => ‘[0-9]+’,
))
->defaults(array(
‘directory’ => ‘admin’,
‘controller’ => ‘main’,
‘action’ => ‘index’,
));

А что мне делать, если я хочу третий ? Например по ссылке /admin/settings/users/client/ должен отработать контроллер Client который лежит в папке /admin/settings/users/. Т.е. логика та же, что со вторым уровнем, но чтобы она повторялась на любой вложенности.
Не писать же мне роуты на каждый случай? subsettings, subusers…

Меня устроит решение с бесконечным уровнем вложенности и с другой логикой.

WinterSilence July 2013
правило для проверки параметра directory подкорректировать

seyfer July 2013
@WinterSilence , как ?

WinterSilence July 2013
как-то так: ‘directory’ => ‘[\w-/]+’ только наверное имеет смысл сделать жадную проверку

seyfer July 2013
@WinterSilence, это для роута admin ? И тогда я могу удалить subadmin?

А жадная как будет выглядеть?

seyfer July 2013
У меня не получается сделать. Есть у кого-то еще идеи или готовое решение?

ButscH July 2013
Вообще по аналогии с этим: http://kerkness.ca/kowiki/doku.php?id=routing:building_routes_with_subdirectories

seyfer July 2013
@ButscH, спасибо, но не то. В данном случае интересно было только регулярное выражение..

‘directory’ => ‘.+?’

Дальше автор приводит пример двух роутов, в которых жестко задан путь

‘directory’ => ‘content/library’

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

ButscH July 2013
Вообще @seyfer ты мне кажется ты мало рассуждаешь логически, т.к. ты сам представь работу твоего роута, как роутер поймет что есть что.

Вот скажи, что будет в этой строке директорией, что контроллером, что экшеном dir1/dir2/dir3/controller и что в этой dir1/dir2/dir3/controller/action.

Если сам не догадаешься, вот тебе подстказка:

dir1/dir2/dir3/controller Directory: dir1/dir2 Controller: dir3 Action: controller (Экшен мы не указывали, роут сработал не верно)

dir1/dir2/dir3/controller/action Directory: dir1/dir2/dir3 Controller: controller Action: action

Т.е. роут всегда будет считать последний параметр урл – экшен, предпослдений – контролллер, все остальное директория.

В общем это не самый умный роут.

Тебе нужно логическое разделение на переход от директории к контроллеру, например: dir1/dir2/dir3/controller.action или dir1/dir2/dir3/controller-action, (< directory >/)< controller >(-< action >(/page< page >)(/< id >)(/< id2 >)) хотя бы так.

WinterSilence July 2013
@ButscH +1

@seyfer освой регулярные выражения http://ru.wikipedia.org/wiki/Регулярные_выражения всю жизнь за тебя другие люди проблемы решать не будут, мы скорее по части посоветовать, но знания то всё равно нужны ^^

biakaveron July 2013
Почему не рассматриваются коллбэки?

seyfer July 2013
@ButscH, я как раз таки очень много рассуждаю логически по долгу работы.

Ты видимо не понял задачу. Прочитай еще раз первый пост. Если бы не возникла проблема, я бы не писал. Я хочу именно по той логике, которую я описал в первом посте.

dir1/dir2/dir3/controller Directory: dir1/dir2 Controller: dir3 Action: controller (Экшен мы не указывали, роут сработал не верно)
Вот тебе тоже подумать. Конкретно под приведенный пример роута ссылка

Так работает. Есть папка админ, есть папка settings, так работает.

/admin/settings/seancesettings
Теперь я создаю папку seance в settings и переношу туда контроллер. Так не работает

/admin/settings/seance/settings/
И так не работает

/admin/settings/seance/settings/index
Потому, что

protected _directory => string(14) “admin/settings”
protected _controller => string(6) “seance”
protected _action => string(8) “settings”
protected _uri => string(30) “admin/settings/seance/settings”
А settings это контроллер, я не хочу указывать action. А даже если указать, то

protected _directory => string(14) “admin/settings”
protected _controller => string(6) “seance”
protected _action => string(8) “settings”
protected _uri => string(36) “admin/settings/seance/settings/index”
То же самое. И так мы видим, что проблема все таки есть.

Теперь рассмотрим пример советчика учить регулярки.

@WinterSilence сказал

‘[\w-/]+’
, ок

Ссылка /admin/settings/seance/settings/ открылась, ура. А вот ни один экшн не работает. Потому, что контроллером считается

protected _directory => string(30) “admin/settings/seance/settings”
protected _controller => string(6) “update”
protected _action => string(5) “index”
protected _uri => string(37) “admin/settings/seance/settings/update”
И последний вариант из статьи, приведенной @ButscH, которому все время что-то кажется, или он не умеет уважительно общаться с собеседником.

.+?
не открылась ссылка admin/settings/seance/settings, ведь не работает так, сказал же.

protected _directory => string(14) “admin/settings”
protected _controller => string(6) “seance”
protected _action => string(8) “settings”
protected _uri => string(30) “admin/settings/seance/settings”
Но ты конечно умнее всех.

Пока что лучший вариант от @WinterSilence –

‘[\w-/]+’
, только заставить бы работать экшены. Если бы все так просто было, я бы не создавал тему.

Как видно задача не тривиальная, регулярными выражениями ее не решить, т.к. логика так сказать кастомная. Вот решение через callback.