0

我有一个控制器和操作,它采用客户名称,然后在数据库上进行搜索以匹配客户。有些客户可能有中间名,有些则没有。

为此,我有以下两条路线:

        'full-name' => array(
            'type' => 'regex',
            'options' => array(
                'regex' => '/(?<title>Mr|Miss|Mrs|Ms)/(?<firstname>[a-zA-Z0-9_-]+)/(?<middlename>[a-zA-Z0-9_-]+)/(?<lastname>[a-zA-Z0-9_-]+)',
                'defaults' => array(
                    'controller' => 'Application\Controller\Customers',
                    'action'     => 'index',
                ),
                'spec'  => '/%firstname%/%middlename%/%lastname%'
            )
        ),
        'name' => array(
            'type' => 'regex',
            'options' => array(
                'regex' => '/(?<title>Mr|Miss|Mrs|Ms)(?<firstname>[a-zA-Z0-9_-]+)/(?<lastname>[a-zA-Z0-9_-]+)',
                'defaults' => array(
                        'controller' => 'Application\Controller\Customers',
                        'action'     => 'index',
                ),
                'spec'  => '/%firstname%/%lastname%'
            )
        ),

我想知道是否有办法将它们组合成一个正则表达式规则,但我找不到任何适用于中间名的东西。我尝试了一些方法,例如:

(?<middlename>[a-zA-Z0-9_-]?)
(?<middlename>[a-zA-Z0-9_-]+|^$)

但后来它抱怨说,当我在没有中间名的情况下尝试它时没有匹配的路由。显然,我可以保持原样,因为它可以工作,但如果可以将两条路线组合成一条路线,那就太好了。

有谁知道这样做的方法?

编辑:与我实际需要的相比,我最初简化了代码,但这导致解决方案无法回答我关于正则表达式中可选值的问题。我更改了代码以反映我为什么不能有分段路线。

作为参考,这是我的初始代码:

        'full-name' => array(
            'type' => 'regex',
            'options' => array(
                'regex' => '/Customer/(?<firstname>[a-zA-Z0-9_-]+)/(?<middlename>[a-zA-Z0-9_-]+)/(?<lastname>[a-zA-Z0-9_-]+)',
                'defaults' => array(
                    'controller' => 'Application\Controller\Customers',
                    'action'     => 'index',
                ),
                'spec'  => '/%firstname%/%middlename%/%lastname%'
            )
        ),
        'name' => array(
            'type' => 'regex',
            'options' => array(
                'regex' => '/Customer/(?<firstname>[a-zA-Z0-9_-]+)/(?<lastname>[a-zA-Z0-9_-]+)',
                'defaults' => array(
                        'controller' => 'Application\Controller\Customers',
                        'action'     => 'index',
                ),
                'spec'  => '/%firstname%/%lastname%'
            )
        ),

谢谢!

4

2 回答 2

1

我对Regex路由类不太熟悉。我知道这可以通过Segment路线来完成。

'name' => array(
    'type'    => 'Segment',
    'options' => array(
        'route'    => '/[:title[/]]:firstname[/:middlename]/:lastname',
        'constraints' => array(
            'title' => 'Mr|Miss|Mrs|Ms',
            'firstname' => '[a-zA-Z0-9_-]+',
            'middlename' => '[a-zA-Z0-9_-]+',
            'lastname' => '[a-zA-Z0-9_-]+',
        ),
        'defaults' => array(
            'controller' => 'Application\Controller\Customers',
            'action'     => 'index',
        ),
    ),
),

编辑:更新答案以反映评论。

于 2013-02-06T23:21:47.340 回答
0

当您从匹配的路由中获取参数时,您可以尝试在控制器中解决此问题:

'full-name' => array(
    'type' => 'regex',
    'options' => array(
        // look here how I changed the regex in a way that the last parameter is optional
        'regex' => '/Customer/(?<firstname>[a-zA-Z0-9_-]+)/(?<middlename>[a-zA-Z0-9_-]+)/*(?<lastname>[a-zA-Z0-9_-]*)',
        'defaults' => array(
            'controller' => 'Application\Controller\Customers',
            'action'     => 'index',
            'lastname'   => false, // add some default value to the optional parameter
        ),
        'spec'  => '/%firstname%/%middlename%/%lastname%'
    )
),

然后在控制器...

public function userAction()
{
    $firstName = $this->params()->fromRoute('firstname');

    // if lastname === false, we have just two parameters (firstname/lastname)
    if ($this->params()->fromRoute('lastname') === false) {
        $lastName = $this->params()->fromRoute('middlename');
        $middleName = NULL;
    } else {
        // if not, we have the three parameters (firstname/middlename/lastname)
        $lastName = $this->params()->fromRoute('lastname');
        $middleName = $this->params()->fromRoute('middlename');
    }
}

编写控制器动作的其他方式(实际上是同一件事):

public function userAction()
{
    $firstName = $this->params()->fromRoute('firstname');

    $lastName = $this->params()->fromRoute('lastname') === false ?
        $this->params()->fromRoute('middlename') :
        $this->params()->fromRoute('lastname');

    $middleName = $this->params()->fromRoute('lastname') === false ?
        NULL : $this->params()->fromRoute('middlename');
}

这样您就可以只使用一条路线。我想不出别的办法!

于 2013-02-07T04:50:43.710 回答