最近一直在做opencart的开发,相当的时间就是在阅读其核心代码,数据库,添加需要的模块,发现其代码虽然简单,但是有很多设计上的问题,特别是许多错误,后来的版本没有去改善,反而使用另一种方法来延续这种错误,这里把所看到的设计失误的地方列举出来,也算作个简单的总结。
1. Extension的设计问题,对于extension的设计,一般的方法是通过提供Hook API和开放API,提供对于系统内部的流程的接入,Opencart没有一个Hook API系统,所以当你需要接入系统流程的时候,你只能修改系统核心的代码,使用的方式是使用vqMOD,这是一个搜索替换引擎,这样的设计会带来直接的弊端。当某一个核心代码被替换的时候,其运行的逻辑直接会影响所有共享其的代码。
2. 数据库的设计,采用了MyISM的引擎,这个引擎是没有事务处理支持的引擎。Opencart系统采用的回避的方法是,在Order的过程中,其确认了支付之后,才创建Order,似乎这样可以避免回滚的问题,但是并没有彻底解决问题,Order的添加,是通过若干个SQL语句构建的,如果其中一个发生问题,Order就是错乱的,采用事务是必要的。
3. 电子邮件,电子邮件的处理,如果不能成功,直接trigger_error(),然后exit,如果邮件没有配置好,你得到的就是空白页面,这样让用户如何理解,什么地方没有完成呢?不知道。
4. 语言系统,几乎所有的Controller都有一个语言文件,单独保存在不同的目录中,没有提供一个单词添加的自动的方法,这一点比wordpress差了些。
5. 引擎,Opencart试图使用MVC的方式,使用的是自己设计的一套相当简单(原始)的机制,使用一个单独的类Registery注入到Controller里面,来提供Controller所需要的各种Helper,比如Request,Response,但是其Request没有提供基本的过滤,甚至于对于字符串存在与否的检查也没有做,如果你使用$this->request->get("hello"),如果此时hello不存在,Opencart使用其注册的全局error handler直接把错误写入error log里面。
6. Order过程,Order在确认之后,Order的内部数据已经创建,这个时候,Opencart给了用户一个按钮,除非用户点击Confirm Order按钮,否则位于shopping cart以及被确认的产品数据不会被清除。这是不符合逻辑的,此时如果页面突然关闭,用户没有点击按钮,Order也已经成功创建,而此时用户发现自己的shopping cart里面所有的内容还没有被确认,用户可能再次Order。
7. Reorder的过程,reorder是再次购买以及购买过的产品的过程,opencart提供了这个机制,但是,其在检查一个order是否能够reorder的时候,仅仅是order_status_id > 0,就可以reorder,丝毫不管order状态有可能是失败,有可能是取消,有可能是别的原因,而不能够被再次order的逻辑。表面上看似乎没有问题,因为reorder其实是取出product的信息,然后加入当前的shopping cart让用户再order一次,但是,这样不做检查的逻辑,在实际的使用中是行不通的。
8. Filter的处理,Filter是用来过滤和检索产品的机制,Opencart的设计似乎完全出现了问题,filter本身的实现必须和category绑定在一起,如果你希望检索所有的产品,你需要修改代码,否则filer只能让你检索某一个category里面的产品,这简直是......
9. Shopping cart的处理,Opencart似乎使用了一个聪明的设计,shopping cart的内容被写入到这个用户的数据表的cart字段里面,这个设计看似相当的聪明,因为你不需要使用任何数据库表来存放Shopping cart,而每一次用户登录的时候,都可以恢复其所有的Shopping cart,确实可以解决目前的问题。但是,这带来几个问题,一个就是如果产品很多,其cart的数据量就很大,解析效率会不会有问题?另外,如果你想要访问所有用户的shopping cart以及其所有的内容,或者想要在shopping cart上扩展一些数据来作为某种自定义的标记,就非常困难。原则上Cart只支持三种数据product id, product option, profile,通常我们认为一个product id,如果再次购买,还是同一个product id,就是同一个产品,只需要添加数量就可以了,Opencart是这样做的,其实还有一种情况,就是如果这个Product是一类product的统称,但是每一个product都有可能有着不同的内容(比如设计),就出现完全的错误,因为此时应该在shopping cart里面是两个不同的项目,还好profile存在,虽然profile可以代用来表示不同的内容,不过这个并不是opencart的本意。
10. 删除一个store或者是一个customer,其余相关的数据全部都没有删除,或者任何处理,以及提示。
12. 从管理端,无法删除order。以及,如果一个产品或者是目录,只有一种语言的描述,而这种语言不是管理端的默认语言,你只有切换管理端的语言才能够看到这些产品或者是目录。更加有问题的是,如果这些产品或者目录本身兼容了所有语言,所有的store的内容都会放在一起,而没有方法可以切换管理不同的store的产品,目录等。