У меня есть приложение, предположительно API, над которым я работаю. Приложение возвращается в формате JSON для запрошенных ресурсов. Итак, у меня есть приложение для управления проектами, структура которого аналогична приведенной ниже:
Теперь API будет звонить:
/projects List all the projects
/project List all the projects (alias)
/projects/ID/issues List all the issues of this project
/project/ID/issues List all the issues of this project (alias)
/projects/ID/issue List all the issues of this project (alias)
/project/ID/issue List all the issues of this project (alias)
И так далее. Теперь проблема для меня, я бы использовал switch ($request)
для этого и у меня сумасшедший case
заявления как ниже:
<?php
switch ($request) {
case '/projects':
case '/project':
# code...
break;
case '/projects/ID/issues':
case '/project/ID/issues':
case '/projects/ID/issue':
case '/project/ID/issue':
# code...
break;
}
Я надеюсь, что вы поняли проблему. Подумайте о количестве случаев для discussion
часть. Это было бы экспоненциально выше. Это было бы сочетанием 3
ценности, которые придут к 2
в силу 3
(23) который приходит 8
case
заявления.
Есть ли лучший способ уменьшить это? Это мой первый раз в переполнении стека. Заранее спасибо.
Вы можете уменьшить его, проверив с первой попытки. то есть, проверьте наличие формы множественного числа или единственного числа и замените ее одной единственной формой.
<?php
$request = replace(array("projects", "project"), "project", $request);
$request = replace(array("issues", "issue"), "issue", $request);
$request = replace(array("users", "user"), "user", $request);
$request = replace(array("discussions", "discussion"), "discussion", $request);
А позже проверьте в switch ()
дело только для единственного числа:
<?php
switch ($request) {
case '/project':
# code...
break;
case '/project/ID/issue':
# code...
break;
}
Я знаю, что это будет повторяющейся задачей, но я думаю, если вы не хотите использовать какие-либо методы плюрализации, это лучше. Надеюсь, этот «быстрый взлом» полезен. Поскольку у вас не более трех или четырех переменных, это лучше.
Замечания: Основная причина, по которой я дал этот ответ — простота, а не использование RegEx.
Я бы порекомендовал использовать preg_match
для такого рода вещей.
Начнем с создания массива с именами маршрутов в качестве ключей и регулярными выражениями в качестве значений:
$routes = [
'projects' => '/\/projects?$/',
'payments' => '/\/projects?\/([0-9]+)\/payments?$/',
'issues' => '/\/projects?\/([0-9]+)\/issues?$/',
'discussions' => '/\/projects?\/([0-9]+)\/issues?\/([0-9]+)\/discussions?$/',
'users' => '/\/users?$/
];
Теперь проверьте, какой маршрут соответствует вашему URL:
function getRoute($url, $routes) {
foreach ($routes as $name => $regex) {
if (preg_match($regex, $url)) {
return $name;
}
}
// return false, or throw an exception if no route has been found
}
И теперь вы можете просто перейти по названию маршрута в вашем коммутаторе:
switch (getRoute($request, $routes)) {
case 'projects':
...
case 'payments':
...
case 'issues':
...
case 'discussions':
...
case 'users':
...
}
Я считаю, что это самое элегантное решение для того, что вы пытаетесь сделать. Вы можете легко экспортировать массив маршрутов во внешнюю конфигурацию, если хотите. Вы также избегаете любых модификаций URL.
Вы могли бы расширить getRoute
Функция не только возвращает имя маршрута, но и возвращает параметры:
function getRoute($url, $routes) {
foreach ($routes as $name => $regex) {
if (preg_match($regex, $url, $matches) {
// removes the first match which is the whole url
array_shift($matches);
return ['route' => $name, 'params' => $matches];
}
}
}
Вышеприведенное вернет массив, содержащий соответствующее имя маршрута и его параметры. Вот пример:
$route = getRoute('/project/13/issues/14/discussions', $routes);
// $route = [
// 'route' => 'discussions',
// 'params' => [0 => '13', 1 => '14']
// ];
Только не забудьте изменить свой оператор switch на:
$route = getRoute($request, $routes);
switch($route['route']) {
...
}
Дайте мне знать, если вам понадобится дальнейшее объяснение.
Подобный подход к Praveen Kumars состоит в том, чтобы анализировать часть запроса по частям и обрабатывать их соответствующим образом. Вы можете разделить это, используя $requestParts = explode('/',$request);
тогда вы идете:
if (($requestParts[0]=='project')||($requestParts[0]=='projects')) {
handleProjectRequest($requestParts);
}
elseif (($requestParts[0]=='user')||($requestParts[0]=='users')) {
handleUserRequest($requestParts);
}
//...and so on...
Тогда ваши подфункции могут выглядеть так:
function handleProjectRequest(&$requestParts) {
if ($requestParts[1]=='ID') { //seems to be the only case?
if (($requestParts[2]=='issue')||($requestParts[2]=='issues')) {
//do your magic
}
}
}
Это поможет вам избавиться от этого гиганта switch
заявление, а также организовать ваш код довольно хорошо.
Продвинутым способом вы можете определить множественное и единственное число для каждого случая в массиве, например так: $projectRequests=['project,projects'];
и проверьте их позже:
if (in_array($requestParts[0],$projectRequests)) {
handleProjectRequest($requestParts);
}
Преимущество этого подхода заключается в том, что вы можете централизованно определять все возможные части каждого запроса.