在PHP中为自定义字符提供转义支持

时间:2014-08-17 13:22:30

标签: php

我想提供在PHP中转义{字符串中的字符的能力。

字符串通常如下所示:

$route = '{controller}/{action}/{id}';

(示例结果:Home / Index / 3)

我想为开发人员提供以下功能:

$route = '{controller}/{action}/\{id\}={id}';

(示例结果:主页/索引/ {id} = 3)

但是,如果有人做了以下事情,我还想提供支持:

$route = '{controller}/{action}/\\{id\\}';

(示例结果:Home / Index / \ 3 \)

我知道addslashes和stripslashes函数,但这些函数不提供我需要的功能。

我还想在我的代码的其他方面使用此功能,以便我可以保持API与PHP的工作方式一致。

首先,这可能会导致冲突,好像我使用双引号然后我猜PHP会自动将\\转义为\ \这是我需要考虑的因为我希望返回的结果是确定性的(即相同,无论是使用单引号还是双引号)。

其次,如果PHP已经提供了执行此操作的能力,我宁愿使用本机实现而不是自定义代码。

最后,如果我不得不求助于自定义代码,那么实现我想要的最佳方式是什么?

1 个答案:

答案 0 :(得分:3)

您可以在正则表达式中使用负向lookbehind来仅匹配{}的出现,而不会在其前面添加\字符。

正则表达式会是这样的(注意你必须在实际的PHP代码中将斜杠转义为\\\\

(?<!\\\\)\{(.+?)(?<!\\\\)\}

Regular expression visualization

正则表达式尸检

  • (?<!\\) - 负面的背后照明,指明下一场比赛前面不能有\\(转义的\字符)
  • \{ - 一个文字{字符。必须进行转义,因为{在正则表达式中具有实际意义
  • (.+?) - 一个懒人匹配组,尽可能少地匹配(但至少包含1个字符),直到达到下一个匹配
  • (?<!\\) - 负面的背后照明,指明下一场比赛前面不能有\\(转义的\字符)
  • \} - 一个文字}字符。必须进行转义,因为{在正则表达式中具有实际意义

在代码中使用

<?php

class Router {
    private $route;
    private $variables;

    public function __construct($route, $variables) {
        $this->route = $route;
        $this->variables = $variables;
    }

    public function getRoute() {
        // Replace variables
        $route = preg_replace_callback('/(?<!\\\\)\{(.+?)(?<!\\\\)\}/', array($this, 'replaceRoute'), $this->route);

        // Replace escaped brackets and return it
        return str_replace(array('\{', '\}'), array('{', '}'), $route);
    }

    private function replaceRoute($match) {
        // Replace variable within {} if it exists
        return isset($this->variables[$match[1]]) ? $this->variables[$match[1]] : $match[0];
    }
}

$router = new Router('{controller}/{action}/\{id\}={id}', array(
    'controller' => 'Home',
    'action' => 'Index',
    'id' => 3
));

var_dump( $router->getRoute() ); // string(17) "Home/Index/{id}=3"

DEMO