Php routing preg_match help needed(需要PHP路由PRIG_MATCH帮助)
问题描述
我有一个自定义路由类,它允许我对请求进行如下匹配:
'/[*:cat1]/[*:cat2]/?[*:cat3]/?[*:cat4]/?[p:page]/?'
该链接将与以下链接匹配:
category-one/
category-one/cat-two/
category-one/cat-two/cat-three/
category-one/cat-two/cat-three/cat-four/
正如您所看到的?After/表示该参数是可选的。
我的问题是[p:page]/?这也是可选的。
category-one/page-2/ category-one/cat-two/page-2/ category-one/cat-two/cat-three/page-2/ category-one/cat-two/cat-three/cat-four/page-2/
我的问题是当我尝试匹配此链接时
/category-one/cat-two/page-2/
它将为我提供以下参数:
cat1 => category-one
cat2 => cat-two
cat3 => page-2
而不是
cat1 => category-one
cat2 => cat-two
page => page-2
我正在使用此生成的regexp:
`^(?:/(?P<cat1>[^/.]+))(?:/(?P<cat2>[^/.]+/)?)(?:(?P<cat3>[^/.]+/)?)(?:(?P<cat4>[^/.]+/)?)(?:(?P<page>(a^)|(?:pag-)(d+)/)?)$`u
如有任何帮助,我们将不胜感激。谢谢! 亚历克斯
推荐答案
我会使用令牌词法分析器/解析器方法。我的GIT中心页面上有几个示例:
https://github.com/ArtisticPhoenix/MISC/tree/master/Lexers
这些是我用来回答有关问题的其他问题,其中一个是JSON对象解析器,而不是JSON字符串。如果没有json_decode无法处理的属性周围的",这将是格式错误的JSON。另一个是HTML缩略器(采用OOP风格,但概念相同),您可以将<textarea>标记排除在外,因为空格很重要。因此,您几乎可以使用此方法进行任何类型的文本处理。
我修改了一个,但是我真的不知道您希望如何输出,或者您想如何处理它,但是它应该可以让您开始使用它。可能您必须将其集成到您的URL路由类中,我不知道这是什么样子。但与简单的preg_match相比,这是一种更好的方法,因为它为您提供了在比赛的每一段上执行复杂逻辑的位置。
 //don't edit this part.
function parse($subject, $tokens)
{
    $types = array_keys($tokens);
    $patterns = [];
    $lexer_stream = [];
    $result = false;
    foreach ($tokens as $k=>$v){
        $patterns[] = "(?P<$k>$v)";
    }
    $pattern = "/".implode('|', $patterns)."/i";
    if (preg_match_all($pattern, $subject, $matches, PREG_OFFSET_CAPTURE)) {
        //print_r($matches);
        foreach ($matches[0] as $key => $value) {
            $match = [];
            foreach ($types as $type) {
                $match = $matches[$type][$key];
                if (is_array($match) && $match[1] != -1) {
                    break;
                }
            }
            $tok  = [
                'content' => $match[0],
                'type' => $type,
                'offset' => $match[1]
            ];
            $lexer_stream[] = $tok;
        }
        $result = parseTokens( $lexer_stream );
    }
    return $result;
}
//make changes here to how the tokens are dealt with
function parseTokens( array &$lexer_stream ){
    $result = [];
    while($current = current($lexer_stream)){
        $content = $current['content'];
        $type = $current['type'];
        switch($type){  
            case 'T_EOF': return;
            //custom code for you tokens.
            case 'T_DELIMTER': 
            case 'T_BASE': 
                //ignore these
                next($lexer_stream); //don't forget to call next
            break;
            case 'T_CAT':
                $cat = substr($content, 4);
                echo "This is Cat ".$cat."
";
                next($lexer_stream);
            break;
            case 'T_PAGE':
                $page = substr($content, 5);
                echo "This is Page".$page;
                next($lexer_stream);
            break;
            //catch all token
            case 'T_UNKNOWN':
            default:
                print_r($current);
                trigger_error("Unknown token $type value $content", E_USER_ERROR);
        }
    }
    if( !$current ) return;
    print_r($current);
    trigger_error("Unclosed item $mode for $type value $content", E_USER_ERROR);
}
/**
 * token should be "name" => "regx"
 * 
 * Order is important
 * 
 * @var array $tokens
 */
$tokens = [
    'T_EOF'             => '',
    'T_DELIMTER'        => '/',
    'T_BASE'            => 'category-one',
    'T_CAT'             => 'cat-(?:one|two|three|four)',
    'T_PAGE'            => 'page-d+',
    'T_UNKNOWN'         => '.+?',
];
$subject = '/category-one/cat-two/page-2/';
parse($subject, $tokens);
echo "
========================================
";
$subject = '/category-one/cat-two/cat-three/cat-four/page-2/';
parse($subject, $tokens);
您可以在操作中看到它here
上述代码的输出:
//$subject = '/category-one/cat-two/page-2/';
This is Cat two
This is Page2
========================================
//$subject = '/category-one/cat-two/cat-three/cat-four/page-2/';
This is Cat two
This is Cat three
This is Cat four
This is Page2
它的工作原理主要是使用preg match all,但是它被包装在一个Sensum类型的事务中,以使处理输出和构建正则表达式变得更容易。因此,您最终得到的不是单一的Regx,而是一个更小、更容易处理的Regx。乍一看,这似乎很复杂,但实际上,一旦你了解了它的作用,它就会变得容易得多。
如果需要,您甚至可以通过在parseTokens函数中添加一些逻辑来检查顺序。这应该是您必须编辑内容的唯一位置,并且主要在Token Switch语句中。
它创建的regx如下所示
/(?P<T_EOF>)|(?P<T_DELIMTER>/)|(?P<T_BASE>category-one)|(?P<T_CAT>cat-(?:one|two|three|four))|(?P<T_PAGE>page-d+)|(?P<T_UNKNOWN>.+?)/i
因此当我添加或时,您不能添加子捕获组备注cat-(?:one|two|three|four)这是一个非捕获组。但您可以稍后使用substr将其分开,这样没什么大不了的。
有点晦涩难懂,但它只匹配字符串的末尾,没有捕获任何内容。
处理部分调用如下(在parse中):
$result = parseTokens( $lexer_stream );
...
return $result;
这样您就可以将通过parse函数返回的数据返回到您调用它的位置(如果您愿意)
  $something = parse($subject,$tokens);
我现在没有时间详细解释什么是词法分析器或它是如何工作的。因此,希望这足以让您开始学习。
更新
这是一个很好的开始,但您的代码非常具体
为了反驳这一点(不要误解我或误解这一点),我觉得我需要进一步解释一下。
这是非常笼统的
$tokens = [
    'T_EOF'             => '',
    'T_DELIMTER'        => '/',
    'T_BASE'            => 'category-one',
    'T_CAT'             => 'cat-(?:one|two|three|four)',
    'T_PAGE'            => 'page-d+',
    'T_UNKNOWN'         => '.+?',
];
这是非常具体的
`^(?:/(?P<cat1>[^/.]+))(?:/(?P<cat2>[^/.]+/)?)(?:(?P<cat3>[^/.]+/)?)(?:(?P<cat4>[^/.]+/)?)(?:(?P<page>(a^)|(?:pag-)(d+)/)?)$`u
如果你必须编辑这将是一个巨大的问题,如果你想要路由到书籍或其他东西怎么办。你打算如何在此基础上进行扩展?我甚至不知道从何说起。
我给您的数组方法,您只需添加它
$tokens = [
    'T_EOF'             => '',
    'T_DELIMTER'        => '/',
    'T_BASE'            => 'category-one',
    'T_CAT'             => 'cat-(?:one|two|three|four)',
    'T_PAGE'            => 'page-d+',
    'T_BOOK'            => 'book-w+',
    'T_UNKNOWN'         => '.+?',
];
然后修改Switch语句:
  case 'T_BOOK':
       ///do something
  break;
而且,你可以用一种清晰而简洁的方式做任何你想做的事情。您可以添加任何复杂的逻辑,任何错误检查等。这是你需要的,很容易。
                        这篇关于需要PHP路由PRIG_MATCH帮助的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:需要PHP路由PRIG_MATCH帮助
				
        
 
            
        - Laravel 5:Model.php 中的 MassAssignmentException 2021-01-01
 - 覆盖 Magento 社区模块控制器的问题 2022-01-01
 - openssl_digest vs hash vs hash_hmac?盐与盐的区别HMAC? 2022-01-01
 - 如何在 Symfony2 中正确使用 webSockets 2021-01-01
 - 使用 GD 和 libjpeg 支持编译 PHP 2022-01-01
 - PHP - if 语句中的倒序 2021-01-01
 - Oracle 即时客户端 DYLD_LIBRARY_PATH 错误 2022-01-01
 - 如何从数据库中获取数据以在 laravel 中查看页面? 2022-01-01
 - 如何使用 Google API 在团队云端硬盘中创建文件夹? 2022-01-01
 - PHP foreach() 与数组中的数组? 2022-01-01
 
