如何在PHP中处理多元化

时间:2016-05-03 18:33:20

标签: php pluralize

我有一个应用程序,可能是一个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值的组合来实现23(2 3 )的力量8 } case陈述。

有减少这种情况的最佳方法吗?这是我第一次进入Stack Overflow。提前谢谢。

3 个答案:

答案 0 :(得分: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?$/
];

现在检查您的网址匹配的路线:

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':
        ...
}

我相信这是您尝试做的最优雅的解决方案。如果愿意,您可以轻松地将routes数组导出到外部配置。您也避免对网址进行任何修改。

获取参数(id&#39; s)

您可以展开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 :(得分:1)

您可以通过首次登记入住来减少它。即,检查复数或单数形式,并用一个单一的形式替换它。

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

答案 2 :(得分:-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);
}

这种方法的优点是,您可以集中定义每个请求的所有可能部分。