OJS(Open Journal Systems)期刊管理系统,是目前主流期刊学术系统,自带期刊管理、论文投稿、专家评审、出版发行、数据库收录等多种学术功能。OJS以强大的功能和稳定的性能,广泛应用在学术出版行业。OJS系统基本的学术工作已经满足了绝大多数的期刊和出版社,但是仍有一些特殊需求的客户,需要对OJS进行深度的定制化处理,以开发出符合自身业务和特点的系统。
错误代码
在对OJS期刊系统的定制开发过程中,经常遇见的一个问题是Fatal error: Uncaught TypeError: Cannot access offset of type string on string in...具体错误信息为:
Fatal error: Uncaught TypeError: Cannot access offset of type string on string in /ojs/lib/pkp/classes/services/PKPSchemaService.php:603 Stack trace:
#0 /ojs/lib/pkp/classes/author/maps/Schema.php(109): PKP\services\PKPSchemaService->addMissingMultilingualValues()
#1 /ojs/lib/pkp/classes/author/maps/Schema.php(58): PKP\author\maps\Schema->mapByProperties()
#2 /ojs/lib/pkp/classes/author/maps/Schema.php(83): PKP\author\maps\Schema->summarize()
#3 /ojs/lib/pkp/lib/vendor/laravel/framework/src/Illuminate/Collections/LazyCollection.php(789): PKP\author\maps\Schema->PKP\author\maps\{closure}()
#4 /ojs/lib/pkp/lib/vendor/laravel/framework/src/Illuminate/Collections/LazyCollection.php(1563): Illuminate\Support\LazyCollection->Illuminate\Support\{closure}()
#5 [internal function]: Illuminate\Support\LazyCollection->Illuminate\Support\{closure}()
#6 /ojs/lib/pkp/lib/vendor/laravel/framework/src/Illuminate/Collections/LazyCollection.php(105): iterator_to_array()
#7 /ojs/lib/pkp/lib/vendor/laravel/framework/src/Illuminate/Collections/Traits/EnumeratesValues.php(867): Illuminate\Support\LazyCollection->all()
#8 [internal function]: Illuminate\Support\LazyCollection->jsonSerialize()
#9 /ojs/cache/t_compile/5bf36214e1ce24916562cc2103e2ac5661ce538a^164bd5a4f3891532cf93e9d19911fe9cb3308efd_0.app.layoutsbackend.tpl.php(289): json_encode()
#10 /ojs/lib/pkp/lib/vendor/smarty/smarty/libs/sysplugins/smarty_template_resource_base.php(123): content_6a0c00d25a0506_36418637()
#11 /ojs/lib/pkp/lib/vendor/smarty/smarty/libs/sysplugins/smarty_template_compiled.php(114): Smarty_Template_Resource_Base->getRenderedTemplateCode()
#12 /ojs/lib/pkp/lib/vendor/smarty/smarty/libs/sysplugins/smarty_internal_template.php(217): Smarty_Template_Compiled->render()
#13 /ojs/lib/pkp/lib/vendor/smarty/smarty/libs/sysplugins/smarty_internal_template.php(386): Smarty_Internal_Template->render()
#14 /ojs/lib/pkp/lib/vendor/smarty/smarty/libs/sysplugins/smarty_internal_runtime_inheritance.php(116): Smarty_Internal_Template->_subTemplateRender()
#15 /ojs/cache/t_compile/5bf36214e1ce24916562cc2103e2ac5661ce538a^c8df85e224ffffc0ed32366fedb3eb0ef9ae1255_0.app.submissionwizard.tpl.php(33): Smarty_Internal_Runtime_Inheritance->endChild()
#16 /ojs/lib/pkp/lib/vendor/smarty/smarty/libs/sysplugins/smarty_template_resource_base.php(123): content_6a0c00d2568c73_10854003()
#17 /ojs/lib/pkp/lib/vendor/smarty/smarty/libs/sysplugins/smarty_template_compiled.php(114): Smarty_Template_Resource_Base->getRenderedTemplateCode()
#18 /ojs/lib/pkp/lib/vendor/smarty/smarty/libs/sysplugins/smarty_internal_template.php(217): Smarty_Template_Compiled->render()
#19 /ojs/lib/pkp/lib/vendor/smarty/smarty/libs/sysplugins/smarty_internal_templatebase.php(238): Smarty_Internal_Template->render()
#20 /ojs/lib/pkp/lib/vendor/smarty/smarty/libs/sysplugins/smarty_internal_templatebase.php(134): Smarty_Internal_TemplateBase->_execute()
#21 /ojs/lib/pkp/classes/template/PKPTemplateManager.php(1407): Smarty_Internal_TemplateBase->display()
#22 /ojs/lib/pkp/pages/submission/PKPSubmissionHandler.php(258): PKP\template\PKPTemplateManager->display()
#23 /ojs/lib/pkp/pages/submission/PKPSubmissionHandler.php(114): PKP\pages\submission\PKPSubmissionHandler->showWizard()
#24 [internal function]: PKP\pages\submission\PKPSubmissionHandler->index()
#25 /ojs/lib/pkp/classes/core/PKPRouter.php(334): call_user_func()
#26 /ojs/lib/pkp/classes/core/PKPPageRouter.php(278): PKP\core\PKPRouter->_authorizeInitializeAndCallRequest()
#27 /ojs/lib/pkp/classes/core/Dispatcher.php(165): PKP\core\PKPPageRouter->route()
#28 /ojs/lib/pkp/classes/core/PKPApplication.php(395): PKP\core\Dispatcher->dispatch()
#29 /ojs/index.php(21): PKP\core\PKPApplication->execute()
#30 {main} thrown in /ojs/lib/pkp/classes/services/PKPSchemaService.php on line 603故障分析
这是一个看似非常复杂的问题。在这段错误代码中,涉及的相关php文件都是通用的基础类,不包含业务函数,根据错误代码并不能直接找到故障点,基本上95%的开发者,遇到这种问题是根本毫无头绪的,即使从最原始的底层架构一点一点调试,也很难找到错误原因。
从报错代码可以看出,说的是无法访问字符串类型的字符串偏移量,翻译成人话就是说,使用了一个包含下标的数组,但该数组没有这个下标,或者没有该数组,总之就是为空,找不到。其实从这个时候,就已经能基本判断出来了,这应该不是程序错误,而是数据错误,在数据库的数据出现错误时,OJS的程序没有做容错处理,导致在读取相关数据对象时,比如获取到了setting_value,但是OJS是多语言系统,如果使用$setting_value[en],但根本就没有这个键值,所以就直接报错出现故障了。
解决方法
1.检查Mysq的l数据源。出现上述错误代码时,看一下是在哪个流程,哪个环节,记住这个环节调用的函数,在该函数中,查找获取了哪些数据,对这些数据进行检查,确保数据统一规范,不会出现下标溢出的情况。
2.检查模型schemas,在对应模型的json文件中,对字段进行检查,将字段配置信息,与数据库的数据进行比对,举个例子:

比如当某个字段,他的multilingual(是否开启多语言)设置为false时,数据库的记录如果为

这种格式,那就必报错。因为在数据库中的记录,是记录locale=zh_CN,即$data['zh_CN']的值,已经定义过locale了,setting_value应该是纯字符串才对。但此处的setting_value明显又是一个序列化的对象,OJS程序在读取到值后,会把他当成序列化对象,再次格式化处理,因此就会报错。
引起这种故障的原因是,不专业的技术人员,在对OJS进行二次开发、功能定制时,只是简单的改了业务逻辑,但却根本不知道OJS的底层架构是由什么构成的,OJS数据库表、字段,都与locale多语言层层关联,不同的multilingual设置方式,对应不同的数据存储内容。随意的修改multilingual,会直接导致已存在数据的报错。
全文总结
OJS的对象由数据库、控制器、模型、schemas、service多个模块关联,构成方式异常复杂,没有七八年的技术经验,不懂OJS的底层架构,这玩意一般的技术开发者根本改不了。上述错误信息和解决方法,只是举的一个最简单的例子,在实际的开发过程中,各种故障和问题会不断涌现。
丁老师从事学术软件研发十余年,可提供OJS系统的安装、维护、升级、Bug修复、二次开发等服务。
如需专业OJS系统技术服务,可以联系丁老师,同时也欢迎学术界的各位作者、学者、同行,针对学术软件信息化进行交流和咨询。
经常有同学提问,open journal system期刊系统,可以在国产服务器和操作系统上运行吗?比如鲲鹏服务器、麒麟操作系统、统信UOS等国产系统。因为是高校的期刊出版社,软件系统现在都是部署在了国产服务器和操作系统上,不知道OJS...
有使用OJS期刊投稿管理系统的小伙伴提问,最近在给评审发送邮件通知时,经常会遇到邮件据收被退回的情况,这是怎么回事呢?如图:遇到这种情况,需要先测试OJS的发信功能是否正常,具体可以通过:1.忘记密码,找回密码,发送重置密码邮件方式。2...
有使用Open Journal System期刊管理系统的客户反映,在使用OJS的PKP PN插件时,出现“The PKP PLN does not know about this journal yet”的提示,是怎么回事呢?PKP ...
有做期刊的出版社客户咨询,OJS系统支持手机、平板等移动端吗?丁老师给你解答,OJS是支持手机移动端的,支持手机、平板,移动端是H5页面的形式,页面是响应式布局设计,可以自适应移动端显示。并且可以通过二次开发,集成到APP中、微信小程序...