创新实训(九) 博客的编辑
博客的编写采用富文本格式,可以设置标签方便检索,可以设置公开状态,可以对博客进行删除。
博客编辑器
该部分的代码编写在blog-editor.php文件中,定义了通用的博客编写格式
这段代码展示了一个用于编辑博客内容的表单。该表单具有标题、标签、内容输入框,以及博客的可见性选项。它还包括了相应的JavaScript代码,用于初始化博客编辑器和切换按钮。以下是每部分代码的详细解释:
-
表单的开始:
- 表单采用了
POST
方法,并支持文件上传(enctype="multipart/form-data"
)。 - 使用了一个隐藏的令牌来防止CSRF攻击。
<form method="post" class="form-horizontal" id="form-<?= $editor->name ?>" enctype="multipart/form-data"> <?= HTML::hiddenToken() ?>
- 表单采用了
-
标题和标签输入框:
- 两个输入框分别用于博客的标题和标签,采用Bootstrap网格系统进行布局。
<div class="row"> <div class="col-sm-6"> <?= HTML::div_vinput("{$editor->name}_title", 'text', $editor->label_text['title'], html_entity_decode($editor->cur_data['title'])) ?> </div> <div class="col-sm-6"> <?= HTML::div_vinput("{$editor->name}_tags", 'text', $editor->label_text['tags'], join(', ', $editor->cur_data['tags'])) ?> </div> </div>
-
内容输入框:
- 一个用于博客内容的多行文本输入框。
<?= HTML::div_vtextarea("{$editor->name}_content_md", $editor->label_text['content'], $editor->cur_data['content_md']) ?>
-
操作按钮和隐藏选项:
- 包含一个查看博客的按钮和一个用于切换博客可见性的复选框。
<div class="row mt-2"> <div class="col-sm-6"> <?php if ($editor->blog_url): ?> <a id="a-<?= $editor->name ?>_view_blog" class="btn btn-info" href="<?= HTML::escape($editor->blog_url) ?>"><?= $editor->label_text['view blog'] ?></a> <?php else: ?> <a id="a-<?= $editor->name ?>_view_blog" class="btn btn-info" style="display: none;"><?= $editor->label_text['view blog'] ?></a> <?php endif ?> </div> <div class="col-sm-6 text-right"> <?= HTML::checkbox("{$editor->name}_is_hidden", $editor->cur_data['is_hidden']) ?> </div> </div>
-
表单结束:
- 结束表单标签。
</form>
-
JavaScript部分:
- 使用
bootstrapSwitch
初始化可见性切换按钮。 - 调用
blog_editor_init
函数初始化博客编辑器。
<script type="text/javascript"> $('#<?= "input-{$editor->name}_is_hidden" ?>').bootstrapSwitch({ onText: <?= json_encode($editor->label_text['private']) ?>, onColor: 'danger', offText: <?= json_encode($editor->label_text['public']) ?>, offColor: 'primary', labelText: <?= json_encode($editor->label_text['blog visibility']) ?>, handleWidth: 100 }); blog_editor_init("<?= $editor->name ?>", <?= json_encode(array('type' => $editor->type)) ?>); </script>
- 使用
博客编写
具体的博客编写的功能实现在blog-write.php文件中
这个PHP脚本展示了一个用于撰写和编辑博客的页面。包括权限验证、博客数据处理、博客编辑器初始化等部分。以下是每段代码的详细解释:
代码详细解释
权限验证和博客获取
-
加载必要的库和权限验证:
- 加载
form
库。 - 检查当前用户是否有权限撰写博客,如果没有权限则返回403错误页面。
requirePHPLib('form'); if (!UOJContext::hasBlogPermission()) { become403Page(); }
- 加载
-
获取博客数据:
- 根据GET参数中的
id
值获取对应的博客。如果id
无效或博客不存在,返回404错误页面。 - 如果没有提供
id
,则尝试获取当前用户的草稿博客。
if (isset($_GET['id'])) { if (!validateUInt($_GET['id']) || !($blog = queryBlog($_GET['id'])) || !UOJContext::isHisBlog($blog)) { become404Page(); } } else { $blog = DB::selectFirst("select * from blogs where poster = '".UOJContext::user()['username']."' and type = 'B' and is_draft = true"); }
- 根据GET参数中的
初始化博客编辑器
-
初始化博客编辑器:
- 创建
UOJBlogEditor
实例并设置博客编辑器的名称。 - 根据获取的博客数据初始化编辑器的当前数据。如果没有博客数据,则设置默认值。
$blog_editor = new UOJBlogEditor(); $blog_editor->name = 'blog'; if ($blog) { $blog_editor->cur_data = array( 'title' => $blog['title'], 'content_md' => $blog['content_md'], 'content' => $blog['content'], 'tags' => queryBlogTags($blog['id']), 'is_hidden' => $blog['is_hidden'] ); } else { $blog_editor->cur_data = array( 'title' => '新博客', 'content_md' => '', 'content' => '', 'tags' => array(), 'is_hidden' => true ); }
- 创建
-
设置博客URL:
- 如果博客不是草稿,则设置博客的URL,否则设置为空。
if ($blog && !$blog['is_draft']) { $blog_editor->blog_url = HTML::blog_url(UOJContext::user()['username'], "/post/{$blog['id']}"); } else { $blog_editor->blog_url = null; }
数据库操作函数
-
定义更新和插入博客的函数:
updateBlog
函数更新已有博客的数据。insertBlog
函数插入新的博客数据。
function updateBlog($id, $data) { DB::update("update blogs set title = '".DB::escape($data['title'])."', content = '".DB::escape($data['content'])."', content_md = '".DB::escape($data['content_md'])."', is_hidden = {$data['is_hidden']} where id = {$id}"); } function insertBlog($data) { DB::insert("insert into blogs (title, content, content_md, poster, is_hidden, is_draft, post_time) values ('".DB::escape($data['title'])."', '".DB::escape($data['content'])."', '".DB::escape($data['content_md'])."', '".Auth::id()."', {$data['is_hidden']}, {$data['is_draft']}, now())"); }
保存博客的处理逻辑
-
定义博客编辑器的保存逻辑:
- 根据博客是否存在、是否是草稿、是否隐藏等条件进行不同的处理,包括更新博客、删除博客、插入博客,以及处理博客标签的更新。
$blog_editor->save = function($data) { global $blog; $ret = array(); if ($blog) { if ($blog['is_draft']) { if ($data['is_hidden']) { updateBlog($blog['id'], $data); } else { deleteBlog($blog['id']); insertBlog(array_merge($data, array('is_draft' => 0))); $blog = array('id' => DB::insert_id(), 'tags' => array()); $ret['blog_write_url'] = HTML::blog_url(UOJContext::user()['username'], "/post/{$blog['id']}/write"); $ret['blog_url'] = HTML::blog_url(UOJContext::user()['username'], "/post/{$blog['id']}"); } } else { updateBlog($blog['id'], $data); } } else { insertBlog(array_merge($data, array('is_draft' => $data['is_hidden'] ? 1 : 0))); $blog = array('id' => DB::insert_id(), 'tags' => array()); if (!$data['is_hidden']) { $ret['blog_write_url'] = HTML::blog_url(UOJContext::user()['username'], "/post/{$blog['id']}/write"); $ret['blog_url'] = HTML::blog_url(UOJContext::user()['username'], "/post/{$blog['id']}"); } } if ($data['tags'] !== $blog['tags']) { DB::delete("delete from blogs_tags where blog_id = {$blog['id']}"); foreach ($data['tags'] as $tag) { DB::insert("insert into blogs_tags (blog_id, tag) values ({$blog['id']}, '".DB::escape($tag)."')"); } } return $ret; };
运行博客编辑器
-
运行博客编辑器:
- 执行博客编辑器的服务器端逻辑。
$blog_editor->runAtServer();
输出页面
-
输出页面内容:
- 输出页面头部、博客编辑器HTML和页面尾部。
<?php echoUOJPageHeader('写博客') ?> <?php $blog_editor->printHTML() ?> <?php echoUOJPageFooter() ?>
博客的删除
博客删除的业务逻辑单独写在文件blog-delete.php中
该代码展示了一个博客删除确认页面,要求用户确认删除博客,并处理删除博客的操作。下面是对代码每个部分的详细解释:
引入库和权限检查
-
引入必要的库和权限检查:
- 加载
form
库。 - 检查当前用户是否有删除博客的权限,如果没有权限则返回403错误页面。
requirePHPLib('form'); if (!UOJContext::hasBlogPermission()) { become403Page(); }
- 加载
-
博客数据获取和验证:
- 检查GET参数中的
id
是否存在且有效,确保博客存在且当前用户有权限操作该博客。如果验证失败,则返回404错误页面。
if (!isset($_GET['id']) || !validateUInt($_GET['id']) || !($blog = queryBlog($_GET['id'])) || !UOJContext::isHis($blog)) { become404Page(); }
- 检查GET参数中的
删除表单处理
-
初始化删除表单:
- 创建一个新的
UOJForm
实例,用于处理博客删除操作。 - 设置表单的处理函数,删除对应的博客。
- 配置删除按钮的样式和文本。
- 设置删除成功后的重定向URL为博客存档页面。
$delete_form = new UOJForm('delete'); $delete_form->handle = function() { global $blog; deleteBlog($blog['id']); }; $delete_form->submit_button_config['class_str'] = 'btn btn-danger'; $delete_form->submit_button_config['text'] = '是的,我确定要删除'; $delete_form->succ_href = "/archive"; $delete_form->runAtServer();
- 创建一个新的
输出页面内容
-
输出页面头部和确认信息:
- 输出页面头部,并显示确认删除博客的标题。
- 使用
HTML::stripTags
函数来避免标题中的HTML标签。
<?php echoUOJPageHeader('删除博客 - ' . HTML::stripTags($blog['title'])) ?> <h3>您真的要删除博客 <?= $blog['title'] ?> 吗?该操作不可逆!</h3>
-
输出删除表单的HTML:
- 输出删除表单的HTML内容,包括提交按钮。
<?php $delete_form->printHTML(); ?>
-
输出页面尾部:
- 输出页面尾部内容。
<?php echoUOJPageFooter() ?>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!