对于PHP初学者来说,一上手就学习庞大的PHP语法无疑很打击自信心。其实即便是很熟练的程序员,也未必对所有的语法非常熟悉。通常熟练的程序员比普通的程序员的优势在于对基本语法的理解非常透彻,而且常用的一些基础代码块基本上可以不用费脑筋直接写出来。再深入一点,便是借助一些著名的PHP开发框架,加上自己项目中经常用到的一些自己编写的可重用模块或者类库,从而快速而有效地开发各种系统。
因此,与其花费时间在PHP语法的学习,不如一上手便教给初学者这些实用的东西,也就是基本的技巧,项目开发的必备技能,以及总结出可重用的代码块。最后,给大家介绍一些著名的PHP开发框架。
在学习的过程中,一些初入门的读者肯定会对一些使用到的语法或者函数感到疑惑。没有关系,跟着读下去,在理解了文章之后,打开你手头边的PHP手册,查找实例中讲到的各种语法和函数,然后自己按照文章的内容做一遍,相信比枯燥的语法学习要有趣得多。不是吗,当你把所有的代码无误地键入系统,并且运行成功后,那种喜悦感会让初学者对于未来充满信心。
实例一:WEB CRM系统
1.1 系统介绍
本实例要讲解的是WEB版的CRM系统。CRM其实就是Customer Relationship
Management的缩写,翻译过来就是客户关系管理系统。现实当中,CRM的范围相当地广泛,无论公司或者工厂规模的大小,客户始终都是最重要的资
产。除了满足客户的订单和送货要求外,日常的客户拓展和关系维护都是至关重要的。有句行话说得好:平常不烧香,临时抱佛脚。
那么如何将客户的信息管理起来,并且挖掘出潜在的商机,这就是CRM系统的基本目标。当然,我们不是让大家开发一个大而全的系统,而是将其简化,做为我们一个简化而不失真的“麻雀”系统。
开发系统的第一步,便是分析系统的需求,抽象出系统中要反映的概念,以及概念间的关系,并且用计算机程序模拟出来。基本上PHP系统很难脱离开数据库而
存在,这也是为什么PHP和Mysql几乎同时出现的原因。抽象出来的概念和概念之间的复杂关系往往会映射成数据库的模型,也就是我们常说的E-R图。下
面的内容便逐步地分析和抽象这些概念,并且E-R建模工具体现出来。
CRM都是围绕着客户展开的,所以客户便是关键的因素。有人会说,客户代表的公司才是核心要素,这话没有错。但是CRM更关注的是人,人的范畴远比公司
广泛得多,所以我们抽取出了系统中的最重要元素,就是人。要维护客户关系,会经常性地拜访,也可能是打电话,这些行为便是拜访记录。有的时间,有一些与拜
访无关的重要记录,比如说客户要过生日了,你要记得去参加,我们称之为备注。最后,我们的系统是多人使用的WEB系统,那么使用者的信息也是要维护的。
所以总结来说,一个最简单的CRM系统包括如下的重要概念:
1.客户 (contacts)
2.拜访 (history)
3.备注 (notes)
4.使用者 (users)
上面的列表中,括号中的部分就是中文概念的英文表示。
有了这些东西,就可以开始干活了。最终,这些概念会变成数据库中的表,字段,外建,索引,视图等等。当在某个具体的数据库上实现时,又会变成SQL语句的集合。
许多初学者一学会PHP的Mysql编程,立马就拿着“锄头”开始干活,却不知“磨刀不误砍柴功”。一个成功的系统会有很长的生命周期,从开发,测试,交互,功能增加,系统运维。如果你是一条条SQL写在文本文件里。那么恭喜你,你还处在原始社会。
图形化的E-R图表示,能够在项目开发的早期给所有的开发人员,包括客户一个对系统中要处理的内容一个High
level的Overview。一些工具还能够帮你将E-R图转成SQL语句,甚至从现有的数据库系统当中,反向生成E-R图。所以,各位初学者,选好一
个工具,从E-R建模开始设计你的数据库吧。
因为Mysql和PHP是天生一对,所以使用Mysql自带的E-R图建模工具是最好不过了。去Mysql的网站上下载
具体的Mysql Workbench使用我就不讲了,如果大家有兴趣的话,可以在群上告诉我。如果要求讲的人多,我会专门写篇文章来介绍。
要注意的是,在下图中,每一个方块代表的便是一个数据库的表,仔细对比一下,可以看出我们所建的表和上面分析出来的概念是一一对应的。但是因为是实战教程,一些重要的细节在这里要给各位交待。
任何系统功能是第一位的,但是性能也是极为重要的。体现在E-R图建模时,便需要注意如下的原则:
1.数据库的表名要尽量地短
2.字段名尽可能地短
3.字段的长度尽可能地短
建模时,可以在表间建立外键关联,但实际的SQL脚本一定要把这些语句删除掉
1.2 数据库的表名和字段名越短越好
建好了数据库的表,以及表中的字段后,在PHP程序中是要通过SQL语句来操纵的。SQL语句的长短直接影响了SQL语句的解析和执行效率,越长的
SQL语句Mysql解析的时间越短,占用的内存空间越小。著名的SAP软件,更是将这个原则运用到了极致,很多的表名和字段都使用无意义的短名称表示,
然后通过短名称和有意义的长名称对应的字典表进行维护。所以你在被面试的时候,遵循这个原则,可以让主考官对你刮目相看哟。
1.3 消除所有的外键关联
基本上表之间都一定存在逻辑上的关联。例如,一个重点客户,你一个月之类会拜访多次。在使用系统的时候,你肯定希望选中某个客户后,能够看到其近期的拜访记录,这便是关联的现实体现。
许多的初学者学会了表关联后,高兴得不行,恨不得所有的表间都划上一条线,结果整个E-R图变得象蜘蛛网一样,无法理解。而且表关联意味着表间有外键。
任何时候在进行数据库的增、删、改时,都会默默地触发对关联表的一次完整性查询,这些于数据库的性能是致命的打击。所以切记不要建立外键。
但有人会问,没有了外键,怎么保证数据的完整性呢?奇怪了,你的程序是干吗的?如果你完全寄托完整性校验在数据库上,你的程序中的其他问题导致了数据的
错误,又靠什么来保证呢?而且,以后讲大型分布式系统的时候,我还会提到,作为最大的状态存储层,数据库的可扩展性是最差的。尽量地减少数据库的负担,才
可能设计出高可用,高性能的系统。
举个我以前项目的例子,在开发国内一个著名的ERP系统的时候,我当时做的一个最小的优化就是取消所有核心表之间的关联,立马系统的吞吐量显著提升,数据库的死锁大部分都被消除。所以,如果你设计的是商用系统,千万别告诉我你有N多的表关联。
1.4 字段的长度尽可能地短
设计好了表之后,是为了以后往里面存储和查询数据。如果你的数据类型和长度选择得不恰当,也会导致性能的下降。举了很肤浅的例子,在你的电脑上打开一个大文件的速度和打开一个几KB文件的速度,哪个快?所有人都会说几KB的速度快。
其实,任何文件的内容都会占据着你磁盘上的存储区域。要读取文件的内容,硬盘的磁头会通过机械运动定位和存取,越大的文件占据的存储区域就越多,磁头的运动距离越长,时间也相应地增加。
因此,在定义客户的电话和手机号码时,我仅选择了25个字符的长度,因为够用了,尽管实际上对系统的提升非常有限,但作为一个好的习惯,我希望各位能够牢记。
1.5 正向工程
当你对E-R图建模完成后,利用Mysql Workbench的Export,可以导出完整的SQL脚本。如果你是用手工编写的,那绝对是一件吃力不讨好的事情,必须那么多的文本,随便打错一个字,就要查半天,能用工具的时候还是用工具,才是聪明人的办法。
把生成的SQL文本文件打开,稍做编辑,删除不必要的部分后,结果如下:
[code language=sql]-- -----------------------------------------------------
-- Table `crm`.`contacts`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `crm`.`contacts` ;
CREATE TABLE IF NOT EXISTS `crm`.`contacts` (
`id` INT NOT NULL AUTO_INCREMENT ,
`first` VARCHAR(255) NULL ,
`last` VARCHAR(255) NULL ,
`title` VARCHAR(255) NULL ,
`image` VARCHAR(255) NULL ,
`profile` TEXT NULL ,
`tags` TEXT NULL ,
`company` VARCHAR(255) NULL ,
`street` VARCHAR(255) NULL ,
`city` VARCHAR(255) NULL ,
`state` VARCHAR(255) NULL ,
`zip` VARCHAR(255) NULL ,
`phone` VARCHAR(25) NULL ,
`cell` VARCHAR(25) NULL ,
`fax` VARCHAR(25) NULL ,
`email` VARCHAR(255) NULL ,
`web` VARCHAR(255) NULL ,
`updated` DATETIME NULL ,
PRIMARY KEY (`id`) )
ENGINE = MyISAM;
-- -----------------------------------------------------
-- Table `crm`.`users`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `crm`.`users` ;
CREATE
TABLE IF NOT EXISTS `crm`.`users` (
`id` INT NOT NULL AUTO_INCREMENT ,
`level` INT NULL ,
`email` VARCHAR(255) NULL ,
`password` VARCHAR(255) NULL ,
`date` DATETIME NULL ,
`home` VARCHAR(255) NULL ,
PRIMARY KEY (`id`) )
ENGINE = MyISAM;
-- -----------------------------------------------------
-- Table `crm`.`history`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `crm`.`history` ;
CREATE
TABLE IF NOT EXISTS `crm`.`history` (
`id` INT NOT NULL AUTO_INCREMENT ,
`type` INT NULL ,
`contact_id` INT NULL ,
`last_update_date` DATETIME NULL ,
`status` INT NULL ,
`user_id` INT NULL ,
PRIMARY KEY (`id`) ,
CONSTRAINT `fk_history_contacts_contact_id`
FOREIGN KEY (`contact_id` )
REFERENCES `crm`.`contacts` (`id` )
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = MyISAM;
CREATE INDEX `fk_history_contacts_contact_id` ON `crm`.`history` (`contact_id` ASC) ;
-- -----------------------------------------------------
-- Table `crm`.`notes`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `crm`.`notes` ;
CREATE
TABLE IF NOT EXISTS `crm`.`notes` (
`id` INT NOT NULL AUTO_INCREMENT ,
`contact_id` INT NULL ,
`description` TEXT NULL ,
`last_update_date` DATETIME NULL ,
PRIMARY KEY (`id`) ,
CONSTRAINT `fk_notes_contacts_contact_id`
FOREIGN KEY (`contact_id` )
REFERENCES `crm`.`contacts` (`id` )
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = MyISAM;
CREATE INDEX `fk_notes_contacts_contact_id` ON `crm`.`notes` (`contact_id` ASC) ;
[/code]
1.6 进一步修饰
到现在为止,第一堂课的内容基本上就讲完了。但是为了连接下一堂课的内容,我这里再引申一下。用过PHP的开源系统的人应该知道,PHP系统的一个好处就是基本上安装非常简单,大概几个步骤就搞定了:
1.拷贝系统到指定的目录
2.修改常见的配置文件
3.访问安装PHP页面
4.填入必要的信息
5.安装完成后,修改目录或者文件的权限
在安装过程中,一般都需要输入数据库的联接信息。验证通过后,安装程序会建立起系统中所需要的大部分表和索引,甚至会有一些初始化数据。象一般都会建立一个默认的管理员账号。
我们已经通过E-R工具得到了高质量的SQL脚本,在安装的时候如何初始化数据库呢?其实上面的内容已经足够了。但是,如果你要做数据库的升级,通常都是先导出旧数据,然后删除原来的表和索引,创建新表,往新表中导入数据,重新建立索引。
此时,上面的大杂烩SQL就不行了。所以一般的系统会将这些SQL脚本进一步分类,将DROP TABLE分为一个,CREATE
TABLE归到一个,ALTER TABLE归到一个,DROP INDEX归到一个,CREATE
INDEX放到另一个单独的脚本当中。考虑到本文的教程性质,就不再修饰,留给大家去完成。
下一堂课,我们将基于现有的SQL脚本来创建CRM的安装程序,直接进入PHP与Mysql的集成。