72. 编辑话题
简介
在本节里,我们完成话题编辑功能。
需求分解
编辑话题的要求如下:
- 只有作者可以编辑自己创建的话题;
- 编辑表单里用户只能修改话题的标题、分类和正文这三项内容;
- 保存时自动截取正文前 200 个文字作为话题的摘要信息;
- 编辑表单提交方式必须是
PUT
请求; - 编辑保存成功后转到话题详情页。
数据模型
因为我们在 Topic 观察者类里把摘要( excerpt
)赋值写在 beforeWrite
事件里,所以编辑保存时会自动触发该事件,所以观察者类不需要更新。
另外,在创建话题时我们已经创建了验证器,编辑话题时的验证规则和创建一样,所以我们不需要创建新的验证器或修改已有验证器验证规则。
所以,我们只需要在数据模型里实现编辑需求。我们在 Topic
模型里添加两个实例方法:
canUpdate
用来判断当前用户是否有编辑topic
记录权限;updateInfo
验证提交数据是否有效,当验证通过时保存数据。
application/common/model/Topic.php
<?php
.
.
.
class Topic extends Model
{
.
.
.
/**
* 是否可以编辑记录
* @Author zhanghong(Laifuzi)
* @DateTime 2019-06-21
* @return boolean [description]
*/
public function canUpdate(){
$current_user = User::currentUser();
if(empty($current_user)){
return false;
}else if($this->user_id != $current_user->id){
return false;
}
return true;
}
/**
* 更新记录
* @Author zhanghong(Laifuzi)
* @DateTime 2019-06-21
* @param array $data 表单提交数据
* @return boolean 是否成功
*/
public function updateInfo($data)
{
$data['id'] = $this->id;
$validate = new Validate;
if(!$validate->batch(true)->check($data)){
$e = new ValidateException('数据验证失败');
$e->setData($validate->getError());
throw $e;
}
$this->allowField(true)->save($data, ['id' => $this->id]);
return $this;
}
}
控制器
接下来,完成控制器里的控制( action )方法 edit
和 update
处理逻辑:
application/index/controller/Topic.php
<?php
.
.
.
use app\common\exception\ValidateException;
class Topic extends Base
{
.
.
.
/**
* 显示编辑资源表单页.
*
* @param int $id
* @return \think\Response
*/
public function edit($id)
{
$topic = TopicModel::find($id);
$message = null;
if(empty($topic)){
$message = '编辑话题不存在';
}else if(!$topic->canUpdate()){
$message = '对不起,您没有权限编辑该话题';
}
if(!empty($message)){
$this->redirect('[topic.index]');
}
$this->assign('topic', $topic);
$categories = CategoryModel::all();
$this->assign('categories', $categories);
return $this->fetch('form');
}
/**
* 保存更新的资源
*
* @param \think\Request $request
* @param int $id
* @return \think\Response
*/
public function update(Request $request, $id)
{
if(!$request->isAjax()){
$this->redirect('[topic.create]');
}
$topic = TopicModel::find($id);
if(empty($topic)){
$this->error('编辑话题不存在', '[topic.index]');
}else if(!$topic->canUpdate()){
$this->error('对不起,您没有权限编辑该话题', '[topic.index]');
}
try{
$data = $request->post();
$topic->updateInfo($data);
}catch (ValidateException $e){
$this->error($e->getMessage(), '', ['errors' => $e->getData()]);
}catch (\Exception $e){
$this->error($e->getMessage());
}
$message = '更新成功';
Session::set('success', $message);
$this->success($message, url('[topic.read]', ['id' => $topic->id]));
}
.
.
.
}
路由
在路由文件里添加 edit
和 update
方法路由规则。
route/route.php
<?php
.
.
.
// 话题管理
Route::get('topic/create', 'topic/create')->name('topic.create');
Route::post('topic', 'topic/save')->name('topic.save');
Route::get('topic/<id>/edit', 'topic/edit')->name('topic.edit');
Route::put('topic/<id>', 'topic/update')->name('topic.update');
Route::get('topic/<id>', 'topic/read')->name('topic.read');
Route::get('topic', 'topic/index')->name('topic.index');
Route::get('category/<id>', 'category/read')->name('category.read');
视图模板
修改视图模板,使得编辑话题时的标题和创建页面不一样,另外编辑表单提交时的请求方式是 put
请求,并且编辑时默认选中话题当前分类,标题和正文输入框分别显示话题当前信息。
application/index/view/topic/form.html
.
.
.
<div class="card-body">
<h2>
<i class="far fa-edit"></i>
{if(isset($topic['id']))}
编辑话题
{else /}
新建话题
{/if}
</h1>
</div>
{if(isset($topic['id']))}
<form id="model-form" class="needs-validation" novalidate action="{:url('[topic.update]', ['id' => $topic->id])}" method="POST" accept-charset="UTF-8">
<input type="hidden" name="_method" value="PUT">
{else /}
<form id="model-form" class="needs-validation" novalidate action="{:url('[topic.save]')}" method="POST" accept-charset="UTF-8">
{/if}
<div class="form-group">
<input class="form-control" type="text" name="title" value="{$topic['title']|default=''}" placeholder="请填写标题" required />
</div>
<div class="form-group">
<select class="form-control" name="category_id" required>
<option value="" hidden disabled selected <?php if(!isset($topic['id'])){ echo('selected'); } ?>>请选择分类</option>
{volist name='categories' id='category'}
<option value="{$category->id}" <?php if(isset($topic['category_id']) && $topic['category_id']==$category->id){ echo('selected'); } ?>>
{$category->name}
</option>
{/volist}
</select>
</div>
<div class="form-group">
<textarea name="body" id="body-field" class="form-control" rows="3">{$topic['body']|default=''}</textarea>
</div>
<div class="well well-sm">
<button type="submit" class="btn btn-primary">
<i class="far fa-save mr-2" aria-hidden="true"></i> 保存
</button>
</div>
</form>
.
.
.
当用户可以编辑当前话题时,在话题详情页面添加到编辑页面入口:
application/index/view/topic/read.html
.
.
.
<div class="operate">
<hr>
<?php if($topic->canUpdate()): ?>
<a href="{:url('[topic.edit]', ['id' => $topic->id])}" class="btn btn-default btn-xs pull-left" role="button">
<i class="glyphicon glyphicon-edit"></i> 编辑
</a>
<?php endif; ?>
<a href="#" class="btn btn-default btn-xs pull-left" role="button">
<i class="glyphicon glyphicon-trash"></i> 删除
</a>
</div>
.
.
.
效果预览
Git 版本控制
下面把代码纳入到版本管理。
$ git add -A
$ git commit -m "用户可以编辑话题"
推荐文章: