如何处理 PHP 中的多元化
How to handle pluralisation in PHP
我有一个正在开发的应用程序,大概是 API。应用程序 returns 以 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
语句。
有减少这种情况的最佳方法吗?这是我第一次进入 Stack Overflow。提前致谢。
定义路线
对于此类内容,我建议使用 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.
进行任何修改
正在获取参数(id)
您可以将 getRoute
函数扩展到不仅 return 路由名称,而且 return 参数:
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];
}
}
}
以上将 return 包含匹配的路由名称及其参数的数组。这是一个例子:
$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);
}
这种方法的优点是,您可以集中定义每个请求的所有可能部分。
您可以通过第一次尝试检查来减少它。即,检查复数形式或单数形式,并将其替换为一种单一形式。
<?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;
}
我知道这是一个重复性的任务,但我想如果你不想使用任何复数方法,这会更好。希望这篇 "quick hack" 对您有所帮助。由于您没有超过三个或四个变量,因此更好。
Note: The main reason I gave this answer is for Simplicity and for not using RegEx.
我有一个正在开发的应用程序,大概是 API。应用程序 returns 以 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
语句。
有减少这种情况的最佳方法吗?这是我第一次进入 Stack Overflow。提前致谢。
定义路线
对于此类内容,我建议使用 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.
进行任何修改正在获取参数(id)
您可以将 getRoute
函数扩展到不仅 return 路由名称,而且 return 参数:
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];
}
}
}
以上将 return 包含匹配的路由名称及其参数的数组。这是一个例子:
$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);
}
这种方法的优点是,您可以集中定义每个请求的所有可能部分。
您可以通过第一次尝试检查来减少它。即,检查复数形式或单数形式,并将其替换为一种单一形式。
<?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;
}
我知道这是一个重复性的任务,但我想如果你不想使用任何复数方法,这会更好。希望这篇 "quick hack" 对您有所帮助。由于您没有超过三个或四个变量,因此更好。
Note: The main reason I gave this answer is for Simplicity and for not using RegEx.