您的第一种方法的问题在于它没有顺序概念。除非您只有一个图像和一个段落的特定顺序,否则无法保证正确的顺序。完成此类任务的更好方法是使用 articles 和 article_contents 之类的东西。
// 文章
id, title
// 文章内容
id, article_id, content_type, body, order
我想您也不能拥有 order 字段并依赖自动增量 ID,但我认为这些东西最好更明确。
因此,在渲染模板时,您可以执行类似的操作。 (这都是伪代码)
<h1>
<?= $article->title; ?>
</h1>
<?php
foreach($article->content as $content) {
// this would be better as a class constant
if ($content->content_type === 'image') {
// have a class to handle rendering of images
echo \Content\Image::render($content->body);
}
if ($content->content_type === 'paragraph') {
// have a class to handle rendering of content, this output will likely need to be purified (see below)
echo \Content\Paragraph::render($content->body);
}
}
?>
有很多方法可以做到。
您提到的另一个选项确实存在问题,但您可以通过以下两种方式之一来处理 XSS 问题。
- htmlentities() 但随后您会丢失所有格式 ()。
- HTML Purifier,这将允许您将某些标签(如粗体、斜体和段落)列入白名单。您可能还需要为第一个解决方案执行此操作,因为没有任何格式的文章很难阅读。
基于 cmets 的更新:
关于您的第一条评论,如果 ID 位于两个单独的表中,则您不能依赖 ID,它可能会起作用,但这是一个非常脆弱的解决方案,没有我能想到的任何好处。
至于净化 src 标签,你只需要配置 HTMLpurifier 来验证 src 标签,从外观上看你可以使用指令Core.RemoveInvalidImg 来做到这一点。 HTMLPuirifier 内置了很多这些选项,它非常强大。有关更多选项/文档,请参阅下面的链接。
https://github.com/GordonLesti/Lesti_Blog/tree/master/lib/HTMLPurifier/ConfigSchema/schema
http://htmlpurifier.org/docs/enduser-customize.html
进一步更新:
关于性能。这就是所谓的“好问题”。
选择文章时,您可以缓存生成的 HTML 并提供它,当数据不经常更改时,无需打扰数据库。
插入新文章时,您只需要等待并围绕它进行构建。您可以执行更新 UI 和异步更新数据库等操作。让用户了解情况,这是最重要的。
更新文章时不要忘记使缓存失效。
要带走的主要一点是,这不是您现在需要考虑的真正问题。现在加入一个缓存层,当你达到 SO 的大小时,你可以聘请专家来处理这种疯狂。看下面的链接,很有意思。
http://nickcraver.com/blog/2013/11/22/what-it-takes-to-run-stack-overflow/