EduSoho 汇集了很多开发者的心血,系统在不断发展中越来越完善。一个具有良好性能的系统取决于代码的设计和质量,在此和大家分享几个 EduSoho 开发的小技巧。
程序的性能好坏直接影响到网站的整体体验。在EduSoho开发过程中,如果能正确地使用系统默认提供的一些接口和函数,可以有效地提高代码的执行效率。
EduSoho 中的 Dao
层提供了一部分内置的查询函数,主要有 get
、search
、findByFields
。简单地按照功能区分如下:
单行数据查询:get
,性能提升的空间不大
多条数据查询:search
、findByFields
,有性能提升的空间
search($conditions, $orderBys, $start, $limit, $columns = array())
应用到一些列表展示的场景,只要控制好查询条件和分页,毫无问题。
比如仅仅想要查找课程下所有学员的id,在考虑选取具体措施的时候可以说是非常的纠结。
考虑1: 直接写个 SQL 语句去获取觉得有点多余;
考虑2: 课程的学员数量又是不可控的,课程学员数量多的时候,使用 findByFields
全部搜索出来必然会增加进程内存的消耗。
我们可以使用 search
函数的第五个参数 columns
来解决这个难点。columns
含义是限制输出的列。巧妙地使用 columns
,就可以降低内存占用率。它的优势如下:
MySQL
的查询时间; $this->getCourseDao()->search(
array(...),
array(),
0,
PHP_INT_MAX, // 在输出字段 columns 可控的时候,使用PHP_INT_MAX可以接受
array('id') // columns,按需取列,降低内存消耗,提高性能的利器
);
findByFields
只有 查询条件 一个参数。
findByFields($fields);
使用最多的场景类似于 findByIds
、findByXXXId
。$fields
有很明确的参数限制,这样可以增加代码的可读性,同时降低内存泄漏的风险。如果想要灵活设定参数值,建议使用 search
的 conditions
。
循环作为一个基本的逻辑代码块,大多出现在批量数据的处理上。而批量处理数据往往是最易消耗性能的地方。遵循以下原则,在一定程度上可以降低循环带来的时间和性能消耗。
很多代码会出现循环中嵌套多层循环的现象。其实遇到这种情况,首先该思考业务的实现思路是否合理。多层嵌套循环会使代码的可读性变差,无论是开发当时还是后续回顾都极易杀死更多脑细胞。
举个栗子,我需要将某个课程下的所有学员都进行数据处理后再更新。如果将所有学员信息直接一次性
搜索出来,在课程学员数据量较大的情况下,往往还没开始循环,内存就先炸了。需要对循环的数据进行分组, 利用 search
方法一次只取出 500
条数据进行处理,处理完一批再处理下一批,这样的好处是可以保证内存可控。
避免在循环逻辑块中执行像 MySQL
读这样的操作。这样会大大增加程序的执行时间。正确的做法是将一组数据需要的资源批量准备好。这样在一定程度上可以减小 MySQL
的压力,减少执行时间。
避免在循环中更新数据。建议先在循环中准备好要更新的数据,等到一组循环执行结束后,批量更新。AdvancedDao
提供了 batchUpdate
、batchCreate
等功能,可以配合循环使用。
数据库是一个程序宝贵的持久化资源,代码中如果使用不当,极易造成数据的丢失。
EduSoho 提供了更新、删除数据的函数 update
、 delete
AdvancedDao
提供了 batchUpdate
、batchDelete
适用于将一组数据批量更新或者批量删除同一组值。
// $identifier : int型会通过$id更新, 数组会通过$conditions更新
update($identifier, array $fields)
更新形式取决于传入 $identifier
的参数类型:
int
型会通过 $id
更新单条数据,简单明了,操作简单,一般不会出现数据安全问题;
数组会通过 $conditions
更新,可能存在数据的“越权操作”风险。
需要注意的是,根据查询条件去更新极易造成数据的“越权操作”。比如,我们本来要更新某个课程下所有课时的某个字段,正常情况下会有类似这样的操作。
update(
array(
'courseId' => 1
),
$fields
)
第一个参数是数组类型,意味着此处的查询条件会很灵活。
php
是弱类型的语言,很多情况下数据的类型不会这么敏感。
传入一个'courseId' => null
的值
恰好使用了 array_filter
函数进行筛选
surprise !!! 灾难就发生了,我将整个数据库的数据全部更新了!不要以为我在开玩笑,很多代码就是在这种无意识中被写出来了。并且常规情况不会触发,只有在某些极端情况下被触发,极其难被测试出来。
update
实现批量更新引用上文的例子,我们需要根据业务封装一个严格控制参数的函数。
public function updateByCourseId($courseId, $fields)
{
// 保证参数courseId有效
if (empty($courseId)) {
return false;
}
// 保证参数严格限定,不会有额外的参数
$conditions = array('courseId' => $courseId);
return $this->getLessonService()->update($conditions, $fields);
}
批量更新的时候,可以将要更新数据的唯一标识符取出来,然后再去更新,也不失为一个好办法。
public function updateByCourseId($courseId, $fields)
{
// 保证参数courseId有效
if (empty($courseId)) {
return false;
}
// 查找符合条件的ids
$ids = $this->getLessonService()->search(
array('courseId' => $courseId),
array(),
0,
PHP_INT_MAX,
array(id)
);
$ids = ArrayToolkit::column($ids, 'id');
if (!$ids) {
return false;
}
return $this->getLessonService()->updateByIds($ids, $fields);
}
适用于更新和删除一批数据中,并且值不同的状况。
批量更新和删除依赖于 AdvancedDao
的扩展功能具体使用很简单,不再赘述。
程序开发从来都不是一件枯燥的事情,当你乐意去思考代码的细节和实现思路,你将会爱上你的代码。
如文章中有不同的观点和建议,欢迎斧正~
我们正在寻求外包团队
EduSoho官方开发文档地址
EduSoho官网 https://www.edusoho.com/
EduSoho开源地址 https://github.com/edusoho/edusoho