множественное число — как справиться с множественным числом в переполнении стека

У меня есть приложение, предположительно 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 заявления.

Есть ли лучший способ уменьшить это? Это мой первый раз в переполнении стека. Заранее спасибо.

4

Решение

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

<?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.

1

Другие решения

Определение маршрутов

Я бы порекомендовал использовать 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']) {
...
}

Дайте мне знать, если вам понадобится дальнейшее объяснение.

1

Подобный подход к 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);
}

Преимущество этого подхода заключается в том, что вы можете централизованно определять все возможные части каждого запроса.

-1
По вопросам рекламы [email protected]