【问题标题】:What's the best method for detecting tags with PHP?用 PHP 检测标签的最佳方法是什么?
【发布时间】:2010-12-23 06:15:10
【问题描述】:

我希望用户能够插入如下标签:

Lorem ipsum dolor sit amet, {module_user_name, 123} consectetur adipiscing elit.

正如您在上面的示例中看到的,标签有几个参数。第一个是所需的函数,参数将取决于请求的函数。

所以我会使用正则表达式来检测 { 和 },反馈?然后我会抓取第一个参数并检查它是否存在。

如果确实存在,我会使用良好的命名约定以避免使用大量的 IF ELSE 或 switch 脚本。像 module_user_name 会触发 moduleUserName() 函数,或者类似的东西,反馈?

** 这只是我对如何解决这个问题的想法,我只是想知道是否有人可以改进它或指出速度等方面的任何问题。

【问题讨论】:

    标签: php regex performance


    【解决方案1】:

    我假设标签是指某种形式的插件标记。那么{ 语法有点太轻量了,很容易和常规文本冲突;为什么要谨慎更换。这里的一个好技巧是像这样使用preg_replace_callback()

     $html = preg_replace_callback('/\{([\w\s,\d]+)\}/', "tags_", $html);
    
     function tags_($call) {
    
         // split up
         $func = explode(",", $call[1]);
         $func = array_map("trim", $func);
    
         // test for handler existence
         if (function_exists($func[0])) {
             return call_user_func_array(array_shift($func), $func);
         } 
    
         return $call[0];   // do not replace
     }
    

    这里命名的用户函数如果存在就会被调用。如果找到了类似{wacky text 123} 的东西,那么回调只会返回它,从而保持原来的$html 不变。

    【讨论】:

    • 首先,我忘了感谢您在 12 月份的反馈。我一定是太忙了,没时间回复。其次,我不太擅长正则表达式,如果我想要多个参数,如 {module_name, 123, ABC, 1A2B}, {module_name, ABC, 1} 等。我需要将正则表达式更改为什么?
    • 那个正则表达式应该已经可以工作了。然而回调包含一个错误,它应该说if (function_exists($func[0])) {。还是您遇到了另一个错误?
    • 伙计,我很抱歉,我没有测试提供的正则表达式并根据我所看到的做出假设,一切正常!
    【解决方案2】:

    我的建议会非常接近马里奥已经给你的,但我会补充:

    • 您应该更详细地使用正则表达式,以便忽略看起来不像函数的内容(例如 {12345})

    • 如果您确实必须将“module_user_name”转换为“moduleUserName”,那么您应该将其设置为数组,而不是开关:

      $tags = 数组( /* 用户标签 => php 函数 */ 'module_user_name' => 'moduleUserName', 'module_user_id' => 'getUserId', // ETC ); if (isset($tags[$func])) { call_user_func($tags[$func], ...) }

    避免使用 switch() 的原因是因为它像一堆 if/elseif 语句一样执行,并且到达底部的情况需要更长的时间,而数组具有恒定的查找时间(我很确定是这种情况) .

      1234563并且只调用以USER_TAG_开头的函数。
    • 不要忘记为用户提供一种方法来输入 { 而不会变成其他东西(即使用 {{\{

    【讨论】:

    • 我绝对不想创建一个巨大的数组,我希望项目尽可能无缝以避免错误等。最好将标签从'module_user_name'重写为'moduleUserName'和看看这个函数是否存在,不是吗?
    【解决方案3】:

    如果确实存在,我会使用一个好的 命名约定以避免不得不 使用大量的 IF ELSE 或 switch 脚本。像 module_user_name 会 触发 moduleUserName() 函数,或者 类似的东西,反馈?

    这听起来像是自动加载器的变体,其中每个名称都映射到一个类/函数。如果您可以完全控制命名,那应该不是问题。如果您必须支持现有标签和/或命名约定不一致,则需要 switch 语句或类似语句。

    事实上,这类似于 Smarty 的函数调用方式。与编写自己的解析器相反,您可以探索那个。它的实现很完善,可能比你第一次写的要好。

    【讨论】:

      猜你喜欢
      • 2011-06-16
      • 2021-05-31
      • 1970-01-01
      • 2019-09-05
      • 1970-01-01
      • 2019-01-26
      • 1970-01-01
      相关资源
      最近更新 更多