4

我正在使用 CakePHP 2.4

我有一个网址,例如 /sent?note=123&test=abc

我想删除note参数,同时将其余的 url 还给我。IE

/sent?test=abc

我有一段代码有效,但仅适用于查询参数。我想了解如何改进我的代码,使其适用于:

  1. 命名参数
  2. 传递的参数
  3. 井号

例如

/sent/name1:value1?note=123&test=abc#top

这是我到目前为止写的代码。https://github.com/simkimsia/UtilityComponents/blob/master/Controller/Component/RequestExtrasHandlerComponent.php#L79

更新第三部分:

让我用更多的例子来说明我所说的更通用的答案是什么意思。

更通用的答案应该假设没有关于 url 模式的先验知识。

假设给定这个 url

/sent/name1:value1?note=123&test=abc

我只想摆脱查询参数note并返回

/sent/name1:value1?test=abc

更通用的解决方案应该可以将这个 url 还给我。

另一个例子。这次要摆脱命名参数。

假设再次给出这个 url

/sent/name1:value1?note=123&test=abc

我想摆脱name1并回来:

/sent?note=123&test=abc

再一次,更通用的解决方案也应该能够做到这一点。

更新第二部分:

我正在寻找更通用的答案。假设 web 应用程序不知道该 url 被称为已发送。您也不知道查询参数是否包含单词 note 或 test。我如何仍然完成上述工作?

我希望能够对任何操作使用相同的代码。这样,我可以将它打包成一个组件,以便轻松重用。

更新第一部分:

我了解主题标签不会传递给 PHP。所以请忽略这一点。

有关如何从主题标签中获取值的线索:

4

3 回答 3

2

使用 mod_rewrite 怎么样?

您可以通过其他方式处理您的 URL:

<IfModule mod_rewrite.c>  
  RewriteEngine on  
  RewriteRule ^/sent/name:(.*)?note=(.*)&test=([az-AZ])(#(.*))$ /sent/name:$1/note:$2/test:$3$4
</IfModule>

我不确定正则表达式,但这可能会以干净的方式将变量传递给 cakePHP(但我还没有测试过)

[编辑]

但是,如果您想在不知道 url 模式的情况下工作,那么您可以使用$this->request数组 : 与类似的 URL

action/id:10/test:sample?sothertest=othersample&lorem=ipsum

我可以在我的控制器中使用它来获取所有参数:

// In your controller's method
$arguments= array_merge_recursive($this->request->named,$this->request->query);

然后,$arguments将是一个包含命名和传递参数的数组:

array(
    'id' => '10',
    'test' => 'sample',
    'sothertest' => 'othersample',
    'lorem' => 'ipsum'
)

这个会比较好吗 ?

[编辑 2] 如果您知道必须删除哪个参数,并直接重定向到新 URL,这应该有效:

action/id:10/test:sample?knownParam=value&lorem=ipsum

或与

action/id:10/knownParam:value?othertest=othersample&lorem=ipsum

在您的控制器/appController 操作中:

    // Name of the known param
    $knownParam = 'knownParam';
    // Arguments
    $arguments = array_merge_recursive($this->request->named, $this->request->query);
    if (key_exists($knownParam, $arguments)) {
        // Unset in named params:
        unset($arguments[$knownParam]);
        // Creating url:
        $url = array(
            'admin' => $this->request->params['prefix'],
            'plugin' => $this->request->params['plugin'],
            'controller' => $this->request->params['controller'],
            'action' => $this->request->params['action']
        );
        // Adding args
        foreach ($arguments as $k => $v) {
            $url[$k] = $v;
        }
        // Redirect
        $this->redirect($url);
    }

这会将两个网址重定向到

action/id:10/param1:value1/param2:value2

没有“知道参数”...

于 2013-09-04T08:19:04.557 回答
1

假设您创建了以下路线:

Router::connect('/projects/:id/quotations/:quotation_id/*', 
    array(
        'controller' => 'quotations', 
        'action' => 'get_all_by_project', "[method]" => "GET"),
    array(
        'pass' => array('id', 'quotation_id'),
        'id' => '[0-9]+',
        'quotation_id' => '[0-9]+'
    ),
    array(
        'named' => array(
            'name1',
            'name2',
            'name3'
        )
    )
);

在这条路线中:

  • 传递的参数将是强制参数id,并quotation_id服从作为第一个和第二个传递参数的顺序
  • 命名参数将是可选参数name1name2name3
  • 当然,查询参数也是可选的,并且取决于您在 url 中实际拥有的内容。
  • 您需要在末尾加上星号,以便命名参数可以通过

让我们假设以下相同动作的漂亮 url 和丑陋 url:

/projects/1/quotations/23/name2:value2/name3:value3/name1:value1?note=abc&test=123 (pretty)

/quotations/get_all_by_project/1/23/name2:value2/name3:value3/name1:value1?note=abc&test=123 (ugly)

答案的第一部分: 让我们只考虑删除查询参数note的场景。

我们应该回去

/projects/1/quotations/23/name2:value2/name3:value3/name1:value1?test=123 (pretty)

/quotations/get_all_by_project/1/23/name2:value2/name3:value3/name1:value1?test=123 (ugly)

以下Component方法将起作用。我已经在丑陋和漂亮的网址上对其进行了测试。

public function removeQueryParameters($parameters, $here = '') {
    if (empty($here)) {
        $here       = $this->controller->request->here;
    }
    $query          = $this->controller->request->query;
    $validQueryParameters   = array();

    foreach($query as $param=>$value) {
        if (!in_array($param, $parameters)) {
            $validQueryParameters[$param] = $value;
        }
    }

    $queryString = $this->_reconstructQueryString($validQueryParameters);

    return $here . $queryString;
}

protected function _reconstructQueryString($queryParameters = array()) {
    $queryString = '';
    foreach($queryParameters as $param => $value) {
        $queryString .= $param . '=' . $value . '&';
    }

    if (strlen($queryString) > 0) {
        $queryString = substr($queryString, 0, strlen($queryString) - 1);
        $queryString = '?' . $queryString;
    }
    return $queryString;
}

这就是调用 Component 方法的方式。

$newUrl = $this->RequestExtrasHandler->removeQueryParameters(array('note'));

RequestExtrasHandler是我编写的具有上述方法的组件的名称。

答案的第二部分: 让我们只考虑删除命名参数name2的场景。

我们应该回去

/projects/1/quotations/23/name3:value3/name1:value1?test=123 (pretty)

/quotations/get_all_by_project/1/23/name3:value3/name1:value1?test=123 (ugly)

以下Component方法将起作用。我已经在丑陋和漂亮的网址上对其进行了测试。

public function removeNamedParameters($parameters, $here = '') {
    if (empty($here)) {
        $here   = $this->controller->request->here;
    }
    $query      = $this->controller->request->query;
    $named      = $this->controller->request->params['named'];

    $newHere    = $here;
    foreach($named as $param=>$value) {
        if (in_array($param, $parameters)) {
            $namedString = $param . ':' . $value;
            $newHere = str_replace($namedString, "", $newHere);
        }
    }

    $queryString = $this->_reconstructQueryString($query);

    return $newHere . $queryString;
}

这就是调用 Component 方法的方式。

$newUrl = $this->RequestExtrasHandler->removeNamedParameters(array('name2'));

RequestExtrasHandler是我编写的具有上述方法的组件的名称。

答案第三部分: 当我意识到传递参数是强制性的之后,我发现没有真正的业务需要删除传递的参数。

另一个问题是,与命名参数和查询参数不同,传递的参数往往没有键存在于$this->controller->request->params['pass']

$this->controller->request->params['pass']通常采用数字索引数组的形式。

因此,取出正确传递的参数是一个巨大的挑战。

因此,我不会创建任何方法来删除传递的参数。

详细查看这里的代码:

https://github.com/simkimsia/UtilityComponents/blob/d044da690c7b83c72a50ab97bfa1843c14355507/Controller/Component/RequestExtrasHandlerComponent.php#L89

于 2013-09-06T17:09:17.410 回答
0

也许简单的 php 函数可以做你想做的事

$url =  '/sent?note=123&test=abc'; //for example
$unwanted_string = substr($url, 0,strrpos($url,'&') + 1);
$unwanted_string = str_replace('/sent?', '', $unwanted_string);
$url = str_replace($unwanted_string, '', $url);
于 2013-08-29T10:27:03.273 回答