用于表单提交的Cakephp3前缀路由不起作用

问题描述 投票:0回答:1

我正在玩路由。我要实现的是类似“ customer / customer_slug / ...”的URL,因此,它将是/ customer / test / hosts / add或/ customer / acme / networks / list。我设置了以下路线...

Router::prefix('customer', function (RouteBuilder $routes){

    $routes->connect('/',['controller' => 'Customers', 'action' => 'index']);
//    ->setMethods(['GET','POST']);

    $routes->connect('/add',['controller' => 'Customers', 'action' => 'add'])
    ->setMethods(['GET','POST']);

    $routes->connect('/:slug/edit',['controller' => 'Customers', 'action' => 'edit'])
    ->setMethods(['GET','POST'])
    ->setPatterns(['slug'=>'[a-z0-9-_]+'])
    ->setPass(['slug']);

    $routes->connect('/:slug',['controller' => 'Customers', 'action' => 'overview'])
    ->setMethods(['GET','POST'])
    ->setPatterns(['slug'=>'[a-z0-9-_]+'])
    ->setPass(['slug']);

    $routes->connect('/:slug/:controller', ['action' => 'index'],['routeClass' => DashedRoute::class])
    ->setMethods(['GET','POST'])
    ->setPatterns(['slug'=>'[a-z0-9-_]+'])
    ->setPass(['slug']);

    $routes->connect('/:slug/:controller/:action', ['param'=>'slug'],['routeClass' => DashedRoute::class])
    ->setMethods(['GET','POST'])
    ->setPatterns(['slug'=>'[a-z0-9-_]+'])
    ->setPass(['slug']);

    $routes->connect('/:slug/:controller/:action/*', [],['routeClass' => DashedRoute::class])
    ->setMethods(['GET','POST'])
    ->setPatterns(['slug'=>'[a-z0-9-_]+'])
    ->setPass(['slug']); 

    // TODO:  Understand and look to remove this 
    $routes->fallbacks(DashedRoute::class);

});

我可以在测试中转到URL,这很好。但是,当我转到/ customer / acme / edit时,我在Customer / CustomersController.php上执行了编辑操作,它显示了适当的形式。查看路由调试工具包,它说它正在使用以下路由:

customer:customers:edit /customer/:slug/edit    
{
    "controller": "Customers",
    "action": "edit",
    "prefix": "customer",
    "plugin": null,
    "_method": [
        "GET",
        "POST"
    ]
}

这是我期望的。但是,当我提交表单时,它会将路由更改为:

customer:_controller:_action    /customer/{controller}/{action}/*   
{
    "prefix": "customer",
    "plugin": null,
    "action": "index"
}

如果我从前缀部分中删除$routes->fallbacks(...,则会收到CSRF错误。

我的编辑页面很简单

<?php $this->extend('../../Layout/TwitterBootstrap/dashboard'); ?>

<?php $this->start('tb_actions'); ?>
<li><?= $this->Form->postLink(__('Delete'), ['action' => 'delete', $customer->id], ['confirm' => __('Are you sure you want to delete # {0}?', $customer->id), 'class' => 'nav-link']) ?></li>
<li><?= $this->Html->link(__('List Customers'), ['action' => 'index'], ['class' => 'nav-link']) ?></li>

<?php $this->end(); ?>
<?php $this->assign('tb_sidebar', '<ul class="nav flex-column">' . $this->fetch('tb_actions') . '</ul>'); ?>

<div class="customers form content">
    <?= $this->Form->create($customer) ?>
    <fieldset>
        <legend><?= __('Edit Customer') ?></legend>
        <?php
            echo $this->Form->control('name');
        ?>
    </fieldset>
    <?= $this->Form->button(__('Submit')) ?>
    <?= $this->Form->end() ?>
</div>

并且来自控制器的关联代码为

    public function edit($slug = null)
    {
        $customer = $this->Customers->getbySlugID($slug);

        if ($this->request->is(['patch', 'post', 'put'])) {
            $customer = $this->Customers->patchEntity($customer, $this->request->getData());
            if ($this->Customers->save($customer)) {
                $this->Flash->success(__('The customer has been saved.'));

                exit;
                return $this->redirect(['controller'=>false, 'action' => 'index', $customer->slug]);

            }
            $this->Flash->error(__('The customer could not be saved. Please, try again.'));
        }
        $this->set(compact('customer'));
    }

查看生成的URL代码

<form method="post" accept-charset="utf-8" role="form" action="/customer/customer4/edit"><div style="display:none;"><input type="hidden" name="_method" value="PUT"></div>    <fieldset>
        <legend>Edit Customer</legend>
        <div class="form-group text required"><label for="name">Name</label><input type="text" name="name" required="required" maxlength="40" id="name" class="form-control" value="Customer4"></div>    </fieldset>
    <button type="submit" class="btn btn-secondary">Submit</button>    </form>

因此看起来应该将其发布到正确的位置(customer4是记录的条目)。

问题是为什么Cake在请求编辑页面时为什么能够获得正确的路线,但是在发布时选择了另一条路线?

注意:我认为还存在其他一些路由缺陷,好像我删除了后备路由,那么我的/路由不起作用。

对于上下文,以下工作正常:

/ customer / add用于编辑和表单提交。

CakePHP版本是3.8.8

cakephp cakephp-3.0
1个回答
0
投票

默认情况下,CakePHP表单使用(模拟的)PUT进行更新(请参见生成的表单中的隐藏的_method字段。是的,是否最好是PATCH尚待商but,但实际上是这样) ,并且您将路由限制为GETPOST,因此在提交表单时它们都不匹配,而后备路由将与请求匹配,因为它们不应用任何HTTP方法限制。

长话短说,请确保您的/edit路线也至少接受PUT

$routes
    ->connect('/:slug/edit',['controller' => 'Customers', 'action' => 'edit'])
    ->setMethods(['GET', 'POST', 'PUT']) // <<<<<< there
    ->setPatterns(['slug'=>'[a-z0-9-_]+'])
    ->setPass(['slug']);

您的控制器还接受PATCH,这是Bake创建的默认设置,但是如果您实际上不使用或不想接受PATCH请求,那么您当然可以放弃它。

另请参见

© www.soinside.com 2019 - 2024. All rights reserved.