前言
PageKit官方的介绍是:直观,模块化,灵活。在俩年前体验下,的确是很赞一个CMS系统。
我为什么要放弃WordPress,不是因为“臃肿”,如果因为这点我完全可以转Typecho平台,但是同样Typecho并不合适我。WordPress对我来说,他的代码“很乱”,到现在为止还没有跟进新的php规范,不过这个的确没办法,毕竟有很长的历史。
此教程就是我一些针对PageKit搭建和WordPress数据转移的心得。
安装
PageKit针对主机要求比较高,无论是版本还是组件,这也保证PageKit为什么现代化!
我安装的坏境是Centos 7.2,Nginx + MariaDB + PHP7.2
和WordPress一样,直接把PageKit程序放在根目录,然后进行配置即可。
但是,理想很丰富,现实很骨感,当我进入域名发现提示"404 Not Found",域名却是"https://api.i95.me//installer"。
所以确定下来是Nginx规则问题了,搜索官方的文档:Server Configuration
得知Nginx配置如下:
server {
# Server name
server_name example.com;
# Server Port
listen 80;
# Webroot
root /var/www/;
# Index file
index index.php;
# PHP setup with query string support
location / {
try_files $uri $uri/ /index.php?$args;
}
# Deny access to sensitive folders
location ~* /(packages|storage|tmp)/.*$ {
return 403;
}
# Deny access to files with the following extensions
location ~* \.(db|json|lock|dist|md)$ {
return 403;
}
# Deny access to following files
location ~ /(config.php|pagekit|composer.lock|composer.json|LICENSE|\.htaccess) {
return 403;
}
# Leverage browser caching of media files for 30 days
location ~* \.(?:ico|css|js|gif|jpe?g|png|ttf|woff)$ {
access_log off;
expires 30d;
add_header Pragma public;
add_header Cache-Control "public, mustrevalidate, proxy-revalidate";
}
# Uncomment the lines below depending on the PHP version you are using.
# PHP-FPM settings for PHP 7 如果你的PHP版本是7+请取消下面的注释
# location ~ \.php$ {
# try_files $uri =404;
# fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
# include fastcgi_params;
# fastcgi_param HTTP_MOD_REWRITE On;
# }
# PHP-FPM settings for PHP 5 如果你的PHP版本是5+请取消下面的注释
# location ~ \.php$ {
# try_files $uri =404;
# fastcgi_pass unix:/var/run/php5-fpm.sock;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
# include fastcgi_params;
# fastcgi_param HTTP_MOD_REWRITE On;
# }
}
看了下应该是少了:
# PHP setup with query string support
location / {
try_files $uri $uri/ /index.php?$args;
}
写入正常了:
不过进去之后发现丢失一些静态资源,查看全部返回403错误,应该还是Nginx配置问题,官网实例Nginx规则很多人反馈这个问题,真的蛮坑的,既然这样删除限制访问即可:
# Deny access to following files
#location ~ /(config.php|pagekit|composer.lock|composer.json|LICENSE|\.htaccess) {
# return 403;
#}
# Deny access to sensitive folders
#location ~* /(packages|storage|tmp)/.*$ {
# return 403;
#}
寻找上面配置代码然后注释之即可。
转移数据
到目前来看,安装过程还算简单,没有很大的问题,下面就是如何从wordpress数据转过来。我Google搜索相关的文章,很幸运的发现有人在PageKit开发一个插件WordPress Import,查看使用说明很简单:
- 从PageKit应用市场搜索“WordPress”关键词的扩展插件,安装即可
- 从你的原有WordPress平台导出数据(工具-导出-所有内容)导出文件格式是xml
- 然后在PageKit启用插件导入xml即可
然而很现实,上传没反应...打开F12查看上传请求直接500报错了。
emmmmmm,怎么办?我打开debug再打开请求总看到相关的报错了:
LogicException in MimeTypeGuesser.php line 135:
Unable to guess the mime type as no guessers are available (Did you enable the php_fileinfo extension?)
in MimeTypeGuesser.php line 135
at MimeTypeGuesser->guess('/tmp/phpgvjEVn') in File.php line 79
at File->getMimeType() in File.php line 58
at File->guessExtension() in WordpressimportController.php line 63
at WordpressimportController->uploadAction()
at call_user_func_array(array(object(WordpressimportController), 'uploadAction'), array()) in ControllerListener.php line 60
at ControllerListener->executeController(object(ControllerEvent), object(Request))
at call_user_func_array(array(object(ControllerListener), 'executeController'), array(object(ControllerEvent), object(Request))) in WrappedListener.php line 63
at WrappedListener->__invoke(object(ControllerEvent), object(Request))
at call_user_func_array(object(WrappedListener), array(object(ControllerEvent), object(Request))) in EventDispatcher.php line 123
at EventDispatcher->trigger(object(ControllerEvent), array(object(ControllerEvent), object(Request))) in TraceableEventDispatcher.php line 126
at TraceableEventDispatcher->trigger('controller', array(object(Request))) in HttpKernel.php line 148
at HttpKernel->handleController() in HttpKernel.php line 77
at HttpKernel->handle(object(Request)) in Application.php line 67
at Application->run() in app.php line 24
at require_once('/data/wwwroot/api.i95.me/app/system/app.php') in index.php line 40
很好,只要是有信息都好办,根据报错好像我的没启用php_fileinfo
这个扩展,那就尝试安装该扩展吧:
查看了下php_fileinfo
是默认就有的,但是我这个PHP版本当时编译没有带这个参数,所以需要重新弄:
#我的是PHP7.2版本的
tar tar xzf php-7.2.1.tar.gz
cd php-7.2.1/ext/fileinfo/
/usr/local/php/bin/phpize
./configure --with-php-config=/usr/local/php/bin/php-config
make && make install
打开/usr/local/php/etc/php.ini
添加扩展:
extension=fileinfo.so
然后重启下php服务即可
php -m
从返回的消息看到fileinfo
安装成功了。
再回过头导入XML文件,又报另外一个错误:"Please upload a valid xml file."
然后去xml检验网站检验下文件,返回都是正确的xml格式文件,这是一个很奇怪的问题。
最后无奈向作者提交问题:Github
说到底还是自己解决吧,根据报错定位到pagekit\packages\spqr\wordpressimport\src\Controller\WordpressimportController.php
,大改第62行,大致看了下应该是判断文件逻辑出问题了,我也懒得费脑筋直接把:
if ((!empty($upload->getExtension()) && $upload->getExtension() != 'xml') || (!empty($upload->guessExtension()) && $upload->guessExtension() != 'xml')
) {
App::abort(400, __('Please upload a valid xml file.test1'));
}
if ($upload->getMimeType() != 'application/xml') {
App::abort(400, __('Please upload a valid xml file.test2'));
}
注释即可。
然而注释后的确可以导入,导入半途有出息问题(崩溃ing...)
Preparing.
Importing.
Importing blog post 7.
Importing blog post 8.
Importing blog post 9.
Importing blog post 10.
Importing blog post 11.
Importing blog post 12.
Importing blog post 13.
Importing blog post 14.
Importing blog post 15.
Importing blog post 16.
Importing blog post 17.
Importing blog post 19.
Importing blog post 21.
Importing blog post 22.
Importing blog post 23.
Importing blog post 24.
Importing blog post 25.
Importing blog post 26.
Importing blog post 27.
Importing blog post 265.
Importing blog post 28.
Importing blog post 29.
Importing blog post 30.
Importing blog post 31.
Importing blog post 34.
Importing blog post 35.
Importing blog post 36.
Importing blog post 37.
Importing blog post 38.
Importing blog post 39.
Importing blog post 40.
Importing blog post 41.
Importing blog post 42.
Importing blog post 43.
Importing blog post 44.
Importing blog post 45.
Importing blog post 46.
Importing blog post 47.
Importing blog post 48.
Importing blog post 49.
Importing blog post 50.
Importing blog post 51.
Importing blog post 52.
Importing blog post 53.
Importing blog post 54.
Importing blog post 55.
Importing blog post 56.
Importing blog post 57.
Importing blog post 58.
Importing blog post 59.
Importing blog post 60.
Importing blog post 61.
Importing blog post 62.
Importing blog post 63.
Importing blog post 64.
Importing blog post 65.
Importing blog post 66.
Importing blog post 67.
Importing blog post 68.
Importing blog post 69.
An exception occurred while executing 'INSERT INTO pk_blog_post (id, title, slug, user_id, date, content, excerpt, status, modified, comment_status, comment_count, roles, data) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)' with params [null, "\u5173\u4e8e9\u6708\u4e0b\u65ec\u7684\u4e00\u4e9b\u4e8b", "\u5173\u4e8e9\u6708\u4e0b\u65ec\u7684\u4e00\u4e9b\u4e8b", 1, "2016-09-26 20:36:47", "
\u5de5\u4f5c<\/h3>
\n
\u4e4b\u524d\u5728\u4e0a\u6d77\u5927\u91cf\u6295\u7b80\u5386\uff0c\u6536\u5230\u5927\u90e8\u5206\u90fd\u662f\u4e0a\u6d77\u5e02\u533a\u90a3\u513f\u7684\uff0c\u5de5\u4f5c\u57fa\u672c\u57288K-1.2W\u5de6\u53f3\uff0c\u6211\u8bb0\u5f97\u8fd9\u51e0\u5bb6\u90fd\u662f\u505a\u7535\u5546\u7684\uff0c\u5de5\u8d44\u5f85\u9047\u867d\u7136\u4e0d\u9519\uff0c\u4f46\u542c\u4e86\u670b\u53cb\u8bf4\uff0c\u7535\u5546\u516c\u53f8\u5f88\u5fd9\uff0c\u6bcf\u5929\u90fd\u8981\u52a0\u73ed\u5230\u5927\u534a\u591c\uff0c\u57fa\u672c\u662f996<\/code>\u90a3\u79cd\u60c5\u51b5\u5427\uff0c\u867d\u7136\u6211\u5f88\u60f3\u53bb\uff0c\u65e0\u5948\u5bb6\u91cc\u6709\u4e8b\u4e00\u65f6\u8d70\u4e0d\u5f00\uff0c\u800c\u4e14\u5e02\u4e2d\u5fc3\uff0c\u60f3\u60f3\u5c31\u86cb\u75bc\u4e86..\u4eba\u8fd9\u4e48\u591a\u2026<\/p>
\n
\u8fd9\u4e2a\u6708\u63a5\u89e6\u524d\u7aef\u5de5\u7a0b\u5e08\uff0c\u611f\u89c9\u8981\u6c42\u771f\u7684\u662f\u8d8a\u6765\u8d8a\u9ad8\u4e86\uff0c\u6216\u8bb8\u4ee5\u540e\u524d\u7aef\u5de5\u7a0b\u5e08\u5fc5\u987b\u638c\u63e1Node.js\u6280\u80fd\uff0c\u800c\u4e14\u5176\u4e2d\u7684ReactJS\u6700\u4e3a\u706b\u70ed\u2026<\/p>
\n
\u8fd8\u6709\u4e0d\u662f\u6709\u795e\u9a6c\u5fae\u4fe1\u5c0f\u7a0b\u5e8f\u90a3\u73a9\u610f\u513f\u2026\u4e0d\u60f3\u5410\u69fd\uff0c\u8fd8\u4e0d\u77e5\u9053\u662f\u4e0d\u662fTX\u8bf7\u6c34\u519b\u6765\u5ba3\u4f20\u7684\u2026\u6548\u679c\u592a\u5938\u5f20\u2026\u96be\u9053iOS Android \u540e\u7aef\u5168\u7279\u4e48\u4e0b\u5c97\u4e86\uff1f\uff1f\ud83d\ude02\ud83d\ude02<\/p>
\n
\"\"<\/p>
\n
\u73b0\u5728\u5929\u5929\u5728\u5bb6\u90fd\u4e0d\u77e5\u9053\u5e72\u5565\u2026\u4ee3\u7801\u5b8c\u5168\u770b\u4e0d\u4e0b\u53bb\u4e86..\u8868\u793a\u6c89\u8ff7\u4e8e\u68a6\u5e7b\u897f\u6e38\u624b\u6e38\ud83d\ude02\ud83d\ude02\u7b49\u6211\u73a9\u591f\u5c31\u5378\u4e86\u2026<\/p>
\n
\u9a6c\u4e0a\u5230\u6708\u5e95\uff0c\u4f30\u6478\u7740\u8981\u56de\u8001\u5bb6\u4e00\u8d9f\uff0c\u4e3b\u8981\u662f\u62ff\u8863\u670d\u548c\u529e\u70b9\u4e8b\u60c5\u3002<\/p>
\n
\u6742(\u5bb6)\u4e8b<\/h3>
\n
\u90fd\u8bf4\u5bb6\u4e11\u4e0d\u53ef\u5916\u626c\uff0c\u6211\u5df2\u7ecf\u65e0\u529b\u5410\u69fd\u5bb6\u91cc\u90a3\u4e9b\u7834\u4e8b\u4e86\uff0c\u4e0a\u4e2a\u6708\u6211\u8fd8\u4ee5\u4e3a\u5904\u4e8e\u53cc\u4eb2\u5bb6\u5ead\uff0c\u8fd9\u6837\u6211\u5988\u7a81\u7136\u62ff\u51fa\u79bb\u5a5a\u8bc1\u7ed9\u770b\uff0c\u8bb2\u771f\uff0c\u5f53\u65f6\u6211\u5c31\u8499\u903c\u4e86\u4e00\u6837\u3002\u8c08\u4e0d\u4e0a\u6709\u592a\u5927\u7684\u4f24\u611f\uff0c\u5bf9\u6211\u6765\u8bf4\u8f7b\u677e\u4e86\u70b9\uff0c\u5929\u5929\u5939\u5728\u4ed6\u4eec\u4fe9\u4e2d\u95f4\u4e5f\u662f\u591f\u96be\u53d7\u7684\u3002<\/p>
\n
\u73b0\u5728\u8ddf\u7740\u6211\u7238\u8fc7\u54af\uff0c\u4e2d\u65ec\u7684\u65f6\u5019\uff0c\u516c\u53f8\u8fc7\u6237\u7ed9\u6211\u7238\uff0c\u53c8\u63a5\u4e0b\u4e00\u6bd4\u5927\u751f\u610f\uff0c\u57fa\u672c\u6ca1\u591a\u5c11\u8d44\u91d1\u8bf7\u4eba\u4e86\uff0c\u6211\u7559\u4e0b\u505a\u6587\u5458\u517c\u5404\u79cd\u2026\u8bf6\uff0c\u771f\u4e0d\u60f3\u5e72\uff0c\u4f46\u8fd8\u6709\u4ec0\u4e48\u529e\u6cd5\u5462\uff1f\u601d\u7d22\u7740\u5230\u5341\u6708\u4efd\u62cd\u62cd\u5c41\u80a1\u8d70\u4eba\u3002<\/p>
\n
\u5176\u5b83<\/h3>
\n
\u542c\u8bf4windows 10 1607\u5f88\u4e0d\u9519\uff1f\u9664\u4e86\u5bf9\u8f6f\u4ef6\u517c\u5bb9\u6027\u5b58\u5728\u95ee\u9898\uff0c\u5176\u4ed6\u8fd8\u53ef\u4ee5\u5427\u3002\u800c\u4e14\u652f\u6301emoji\u8868\u60c5\u4e86\u3002<\/p>
\n
\"\"<\/p>
\n
\u770b\u7740\u98ce\u683c\uff0c\u6211\u90fd\u4e0d\u77e5\u9053\u90a3\u4e9b\u5de5\u7a0b\u5e08\u5ba1\u7f8e\u89c2\u662f\u4e0d\u662f\u5b58\u5728\u95ee\u9898\u2026<\/p>
\n
\u7b97\u4e86\uff0c\u51d1\u5408\u7528\u5427\ud83d\ude02\ud83d\ude02\uff0c\u770b\u5230\u8fd9\u98ce\u683c\u771f\u662f\u65e5\u4e86\u5409\u5a03\u5a03\u7684\u2026\u6bd4android\u597d\u770b\u4e00\u70b9\uff0c\u53ea\u662f\u4e00\u70b9\u70b9\u800c\u5df2\ud83d\ude02<\/p>
\n
\u8fd8\u6709\u54e6\uff0ciOS 10 Emoji\u8868\u60c5\u98ce\u683c\u4e5f\u53d8\u4e86\u2026\u7b80\u76f4\u5c31\u662f\u4e27\u5fc3\u75c5\u72c2\u2026\u662f\u4e0d\u662f\u6211\u7684\u5ba1\u7f8e\u89c2\u51fa\u95ee\u9898\u4e86\uff1f\u8981\u4e0d\u8981\u53bb\u77eb\u6b63\u4e0b\uff1f\ud83d\ude02\ud83d\ude02<\/p>
\n<\/div>", false, 2, "2018-05-01 05:41:35", 1, 0, null, null]: SQLSTATE[22007]: Invalid datetime format: 1366 Incorrect string value: '\xF0\x9F\x98\x82\xF0\x9F...' for column 'content' at row 1
很显然这是字符串编码问题...头疼。
由于硬性问题存在我只能在xml把这个id删了,从log来看是post id 69的数据插入失败。打开xml文件很显然看到emoji表情,搜索emoji表情相关资料,的确和数据库存入有关系:
普通的字符串或者表情都是占位3个字节,所以utf8足够用了,但是移动端的表情符号占位是4个字节,普通的utf8就不够用了,为了应对无线互联网的机遇和挑战、避免 emoji 表情符号带来的问题、涉及无线相关的 MySQL 数据库建议都提前采用 utf8mb4 字符集,这必须要作为移动互联网行业的一个技术选型的要点.
那么对我来说,只有俩个选择:第一个是删除xml emoji数据,第二个修改数据库类型为utf8mb4
,如果还是不行把存放文章的数据字段修改成utf8mb4_general_ci
所以我选择删除表情吧...
2018.05.01 18:00更新
和作者沟通下,现在Ver 1.0.2已经解决这个问题
XML很大,导入出现nginx 报 504 Gateway Time-out错误
解决方法:
fastcgi_buffer_size 128k;
fastcgi_buffers 8 128k;
fastcgi_busy_buffers_size 256k;
fastcgi_temp_file_write_size 256k;
将上面属性调整(翻一倍)即可。
目前来看问题都解决了。