我做了一个安静的控制器,如果我发送id,get方法会收到它。但是当我更新表单时,我希望更新方法可以处理,但是我无法找到正确的配置,在这个问题的1天之后我决定将它放在这里。
这里涉及的代码 模块配置中的路由:
'activities' => array(
'type' => 'segment',
'options' => array(
'route' => '/activities[/:id][/:action][.:formatter]',
'defaults' => array(
'controller' => 'activities'
),
'constraints' => array(
'formatter' => '[a-zA-Z0-9_-]*',
'id' => '[0-9_-]*'
),
),
),
管制员负责人:
namespace Clock\Controller;
use Zend\Mvc\Controller\AbstractRestfulController;
use Zend\Mvc\MvcEvent;
use Zend\View\Model\ViewModel;
use Zend\Form\Annotation\AnnotationBuilder;
use Zend\Form;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\EntityRepository;
use Clock\Entity\Activity;
use \Clock\Entity\Project;
Wich contains the get method:
public function get($id)
{
$entity = $this->getRepository()->find($id);
$form = $this->buildForm(new Activity());
#$form->setAttribute('action', $this->url()->fromRoute("activities", array('action' => 'update')));
$form->setAttribute('action', "/activities/$id/update");
$form->bind($entity);
return array(
"activities" => $entity,
"form" => $form
);
}
这提供了这个观点:
<h3>Edit activity</h3>
<div>
<?php echo $this->form()->openTag($form);?>
<?php echo $this->formSelect($form->get("project"));?><br>
<?php echo $this->formInput($form->get("duration"));?><br>
<?php echo $this->formInput($form->get("description"));?><br>
<input type="submit" value="save changes" />
<?php echo $this->form()->closeTag($form);?>
</div>
发送后,我希望活动中的更新方法能够控制,但我得到:
A 404 error occurred
Page not found.
The requested controller was unable to dispatch the request.
Controller:
activities
编辑:@DrBeza 这就是我得到的,我认为(不是路线中的主人)是对的:
Zend\Mvc\Router\Http\RouteMatch Object
(
[length:protected] => 21
[params:protected] => Array
(
[controller] => activities
[id] => 30
[action] => update
)
[matchedRouteName:protected] => activities
)
-
那就是它。 有什么帮助吗?
答案 0 :(得分:3)
RouteMatch对象尝试调度ActivitiesController::updateAction
,但您已定义ActivitiesController::update
这是因为你使用了Restful Controller。 Controller::update
- 方法专门与PUT
- 请求相关联。您需要定义一个额外的方法来通过POST
- 请求来处理更新。
我建议您定义ActivitiesController::updateAction
,在docblock中明确说明它是为了处理POST更新请求并重构::updateAction
和::update
以共享尽可能多的常见帮助方法可以快速解决。
作为开始开发RESTful应用程序/ API时的一个很好的信息: ruby社区为您的资源建议以下url结构:
# These are restful
/resource GET (lists) | POST (creates)
/resource/:id PUT (updates) | DELETE (deletes)
# these are just helpers, not restful, and may accept POST too.
/resource/new GET (shows the create-form), POST
/resource/:id/edit GET (shows the update-form), POST
消费者将通过PUT
发送详细更新,但发送HTML表单的浏览器只能发送GET
或POST
个请求。你永远不应该使用GET
创建一些东西。因此,您必须在表单上下文中使用POST
。
从架构的角度来看问题,根据您的应用程序的大小,会出现多种可能性。
作为一个教育范例,我原则上提出了an gist to show how such a controller could look like。该控制器是a)未经测试的b)未生产就绪且c)仅可轻微配置。
为了您的特殊兴趣,这里有两个关于更新的摘录:
/* the restful method, defined in AbstractRestfulController */
public function update($id, $data)
{
$response = $this->getResponse();
if ( ! $this->getService()->has($id) )
{
return $this->notFoundAction();
}
$form = $this->getEditForm();
$form->setData($data);
if ( ! $form->isValid() )
{
$response->setStatusCode(self::FORM_INVALID_STATUSCODE);
return [ 'errors' => $form->getMessages() ];
}
$data = $form->getData(); // you want the filtered & validated data from the form, not the raw data from the request.
$status = $this->getService()->update($id, $data);
if ( ! $status )
{
$response->setStatusCode(self::SERVERSIDE_ERROR_STATUSCODE);
return [ 'errors' => [self::SERVERSIDE_ERROR_MESSAGE] ];
}
// if everything went smooth, we just return the new representation of the entity.
return $this->get($id);
}
以及满足浏览器请求的editAction
:
public function editAction()
{
/*
* basically the same as the newAction
* differences:
* - first fetch the data from the service
* - prepopulate the form
*/
$id = $this->params('id', false);
$dataExists = $this->getService()->has($id);
if ( ! $dataExists )
{
$this->flashMessenger()->addErrorMessage("No entity with {$id} is known");
return $this->notFoundAction();
}
$request = $this->getRequest();
$form = $this->getEditForm();
$data = $this->getService()->get($id);
if ( ! $request->isPost() )
{
$form->populateValues($data);
return ['form' => $form];
}
$this->update($id, $request->getPost()->toArray());
$response = $this->getResponse();
if ( ! $response->isSuccess() )
{
return [ 'form' => $form ];
}
$this->flashMessenger()->addSuccessMessage('Entity changed successfully');
return $this->redirect()->toRoute($this->routeIdentifiers['entity-changed']);
}
答案 1 :(得分:1)
该错误消息表明调度进程无法找到请求的控制器操作,因此使用notFoundAction()
。
我会检查匹配的路线,并确保值符合预期。您可以通过在模块的onBootstrap()
方法中添加以下内容来完成此操作:
$e->getApplication()->getEventManager()->attach('route', function($event) {
var_dump($event->getRouteMatch());
exit;
});