今天早上发表了一篇文章《CSS中的em和rem尺寸单位有什么不同》,主要记叙了CSS中的em与rem尺寸单位不同之处与使用方法,发表完之后在网站前台预览时发现有一段落未换行导致这一段落与上一段落紧密挨在一起不美观(目前已经处理好了),所以在后台修改这篇文章,当我点击这篇文章的修改链接之后,看到ckeditor编辑器里的内容乱七八糟的,根本不是我编辑发布时的排版,我就很纳闷,为什么会变成这样子的呢?难道是ckeditor编辑器转换了某些字符?不想那么多,一步步排查:
首先,我打开了mysql数据库查看文章保存后的内容跟我发布时是不是一致,经过对比发现内容是一致的。继续排查,此时,我怀疑是数据在读取时被格式化,打开修改文章时调用的程序文件:/phpcms/modules/content/content.php并查看public function edit()方法里的代码,果然,导致问题就是如下第35行代码(已被我注释掉了)所示造成的:
public function edit() { //设置cookie 在附件添加处调用 param::set_cookie('module', 'content'); if(isset($_POST['dosubmit']) || isset($_POST['dosubmit_continue'])) { define('INDEX_HTML',true); $id = $_POST['info']['id'] = intval($_POST['id']); $catid = $_POST['info']['catid'] = intval($_POST['info']['catid']); if(trim($_POST['info']['title'])=='') showmessage(L('title_is_empty')); $modelid = $this->categorys[$catid]['modelid']; $this->db->set_model($modelid); $this->db->edit_content($_POST['info'],$id); if(isset($_POST['dosubmit'])) { showmessage(L('update_success').L('2s_close'),'blank','','','function set_time() {$("#secondid").html(1);}setTimeout("set_time()", 500);setTimeout("window.close()", 1200);'); } else { showmessage(L('update_success'),HTTP_REFERER); } } else { $show_header = $show_dialog = $show_validator = ''; //从数据库获取内容 $id = intval($_GET['id']); if(!isset($_GET['catid']) || !$_GET['catid']) showmessage(L('missing_part_parameters')); $catid = $_GET['catid'] = intval($_GET['catid']); $this->model = getcache('model', 'commons'); param::set_cookie('catid', $catid); $category = $this->categorys[$catid]; $modelid = $category['modelid']; $this->db->table_name = $this->db->db_tablepre.$this->model[$modelid]['tablename']; $r = $this->db->get_one(array('id'=>$id)); $this->db->table_name = $this->db->table_name.'_data'; $r2 = $this->db->get_one(array('id'=>$id)); if(!$r2) showmessage(L('subsidiary_table_datalost'),'blank'); $data = array_merge($r,$r2); // $data = array_map('htmlspecialchars_decode',$data); 就是这行代码导致编辑内容时内容显示错乱 require CACHE_MODEL_PATH.'content_form.class.php'; $content_form = new content_form($modelid,$catid,$this->categorys); $forminfos = $content_form->get($data); $formValidator = $content_form->formValidator; include $this->admin_tpl('content_edit'); } header("Cache-control: private"); }
解决办法就是像我那样注释掉这行代码就OK了,不过我们来分析下这行代码到底做了什么改动。如果知道php内置的htmlspecialchars_decode函数起什么作用的话就很容易理解原因所在了,不认识这个htmlspecialchars_decode函数的朋友也没关系,这个函数很容易理解,就是把一些预定义的HTML实体转换为字符,会被解码的HTML实体是:
& 解码成 & (和号)
" 解码成 " (双引号)
' 解码成 ' (单引号)
< 解码成 < (小于)
> 解码成 > (大于)
所以,在数据输出前内容里面的HTML实体都会被转换成字符,最终导致编辑器显示的内容错乱。