从cakephp官方网站下载最 新的stable版本,解压缩到合适的目录,在httpd.conf里设置一个测试用的<VirtualHost>虚拟机,把其中的 DocumentRoot设置为/path/to/cakephp/app/webroot,并设置虚拟机的<Directory>部分,加 入:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
激活apache的方法有两种,你可以把mod_rewrite模块静态编译到apache里,也可以动态加载mod_rewrite模块,一般后 者更常见一些,如果是Windows版本的apache的话,只要在httpd.conf里去掉LoadModule rewrite_module modules/mod_rewrite.so一行的注释就可以了,如果使用的linux,方法稍复杂,不做介绍了。
有问题的地方:{cakephp官方安装文档里推荐使用的是用. htaccess文件(设置httpd.conf里AllowOverride为All)来设置重写规则,如果网站处于测试阶段的话,当然无可厚非,但是 如果网站处于产品阶段,应该尽量避免使用.htaccess(设置httpd.conf里AllowOverride为None),相应的重写规则最好直 接写在httpd.conf的<VirtualHost>部分。}
差点忘记说明一点,还要在httpd.conf文件里设置:DirectoryIndex index.php,把index.php设置为目录索引文件。
这样,服务器段配置工作基本就可以了,但是为了让cakephp跑起来,还应该配置一下数据库,把app/config目录下的database.php.default文件改名为database.php,然后在里面写上相关信息。
database.php文件的内容大致如下:
<?php
class DATABASE_CONFIG
{
var $default = array('driver' => 'mysql',
'connect' => 'mysql_connect',
'host' => 'localhost',
'login' => 'user',
'password' => 'password',
'database' => 'project_name',
'prefix' => '',
'charset' => 'gbk');
var $test = array('driver' => 'mysql',
'connect' => 'mysql_connect',
'host' => 'localhost',
'login' => 'user',
'password' => 'password',
'database' => 'project_name-test',
'prefix' => '',
'charset' => 'gbk');
}
?>
注意:charset选项是我自己添加的,为了能够设置正确的编码,后面会有例子。
有问题的地方:{database.php文件中的DATABASE_CONFIG类是个纯粹的数据容器,没有任何方法,虽然这样的方式能运行,但是我不得不说,这样的类是“弱智类”,我们应该尽量避免在编程过程中发明出这样的类来,你用数组或者其他什么结构来做数据容器都比这样要好。}
cakephp封装了mysql, mssql,...此外,还包装了peardb, adodb,并实现了事务支持。
有问题的地方:{在cakephp里封装了adodb,但是可以说封装相当的简陋,连limit方法都没处理好,adodb的数据抽象能力基本over,而且cakephp在数据库事务的处理上相当简陋,没有乐观锁,悲观锁的概念。}
不管怎么说,进行完这些设置后cakephp就能跑起来了,如果这时你浏览http://domainname/应该能看到cakephp的提示信息了。
使用cakephp编程,你的url会类似如下的样子:
http://domainname/controller/action/param1/param2
如果你按照类似上面的url去访问,就会看到cakphp友好的错误提示,告诉你应该建立某某文件等等,只要根据提示建立文件,一个应用程序的骨架基本就搭起来了。
model和controller里都存在一个名为$name的属性,model里的$name关系到数据库表的名字(表名缺省会转换成复数形式, 如果你不喜欢这样的表名,你可以通过在model里添加$useTable属性来自定义表名),controller的$name关系到所使用的 model的名字。这两个位置的$name属性你都可以不写,cakephp会按照一定的规则自己去推算相应的字符串应该是什么样子,但是最好还是显式的 写出来更明智一些。
有问题的地方:{cakephp把POST变量封装成控制器对象的一个名为$data的属性,但对于GET变量 (如上面url中的param1, param2)则未作这样的处理,而是在调用控制器方法的时候自动把他们(param1, param2)赋值给方法的形参。虽然这很不错,但是对于GET/POST变量处理的差异还是让我觉得有些别扭。}
通过修改app/config/core.php文件中的define('DEBUG', 2),我们可以在浏览页面的时候顺带看到系统帮我们生成的SQL语句。
缺省的配置文件database.php里,数据库配置有两个类型,一个是$default,另一个是$test,缺省使用的是$default设 置,通过在自定义的model文件里加入var $useDbConfig = 'test',可以让系统使用$test的数据库设置。
在配置文件app/config/routes.php中,可以修改系统的各个缺省路由,除了可以设定缺省的控制器动作名,还可以设定控制器动作方法中缺省的参数,如下:
$Route->connect('/例子', array('controller' => '模块名', 'action' => '动作名', '第一个参数', '第二个参数', ...));
此外,通过打开app/config/core.php配置文件中的define('CAKE_ADMIN', 'admin');选项,可以支持形如/admin/products/add的管理路由,也就是“/管理员/控制器/动作/参数/...”形式的管理路由。
有问题的地方:{管理路由虽然在一定程度上可以让你的逻辑更有条理,但是不得不说的是管理路由的权限相对简陋,不能实现多级别的认证处理}
cakephp编程之所以快速,就是因为框架本身已经尽可能完整的封装了CRUD操作,软件的各种用例操作我们只要通过在controller里调 用model的若干方法就可以完成了,而且,如果数据库中存在created,modified,updated这样的字段名,并且字段类型为 date/datetime,那么cakephp会自动填充他们。
有问题的地方:{虽然cakephp会自动填充名子为created,modified,updated,字段 类型为date/datetime类型的字段,但是很多开发者在编程习惯上,更喜欢使用整数时间戳来保存时间(int unsigned),而这样的字段cakephp不会自动填充}
如果使用mysql4.1以上的话,有时候需要设定数据库编码才能正常查询,否则会有乱码。
有问题的地方:{cakephp竟然没有给出一个设定编码(SET NAMES 'gbk')的地方,NND}
编码问题不能不解决,这里给出一个权宜的方案,拷贝cake目录下的app_model.php文件到app目录下,按如下方式修改文件内容:
class AppModel extends Model{
function __construct()
{
parent::__construct();
$conf = new DATABASE_CONFIG;
$data = $conf->{$this->useDbConfig};
if(strtolower($data['driver']) == 'mysql')
{
$this->execute("SET NAMES '{$data['charset']}'");
}
}
}
注意:这里又有一个需要注意的地方:为啥不直接修改cake目录下的app_model.php文件,而要拷贝到app目录下再修改呢?因为cake目录下的文件是cakephp核心库文件,无论什么情况都不应该修改,否则会给升级维护带来不必要的困难。
注意:同样的道理,我们还可以把cake目录下的app_controller.php文件复制到app目录下,这样我们就可以编辑此文件来自定义控制器了,通常在app目录下的app_controller.php文件里放入诸如权限判断的方法是不错的主意,这样在子控制器中就可以直接调用了。
cakephp中,模型和模型之间存在四种关系:hasOne, hasMany, belongsTo, hasAndBelongsToMany。
A hasOne B:相应的关联字段(A_id)建立在B的数据表里,在A里查询时,cakephp会对A,B两个模型执行一次LEFT JOIN查询。
A hasMany B:相应的关联字段(A_id)建立在B的数据表里,在A里查询时,cakephp会对A,B两个模型各自执行一次SELECT查询。
A belongsTo B:相应的关联字段(B_id)建立在A的数据表里,在A里查询时,cakephp会对A,B两个模型执行一次LEFT JOIN查询。
A hasAndBelongsToMany B:相应的关联字段(A_id, B_id)建立在一个独立的中间表里,在A里查询时,cakephp会先对A表进行一次查询,然后从查询影响行得到相关外键的信息,依次执行JOIN链接 中间表的查询。举例:如果我们要查询10个A和他们关联的B,那么我们要执行1+10次查询。
有问题的地方:{cakephp对与多对多的处理不能对三个表智能的执行两次LEFT JOIN查询,明显存在1+N问题,效率会大打折扣,本来一次查询就可以搞定的问题实际上多查询了N次}
多对多关系的中间表,一般对编程者是隐藏的,但是有些情况下,中间表也可以是一个独立的实体,比如说学生选课,会存在一个名字类似 student_class的中间表,里面可能有student_id, class_id字段,除此之外,还可能有学生选择某门课程的具体时间等额外信息,这时候的中间表就明显是一个独立的实体了。
通过研究cake/libs/model/datasources/dbo_source.php文件中的generateAssociationQuery方法,可以搞清楚cakephp是如何拼装sql语句的。
待续
更正:CakePHP是支持MySQL的SET NAMES ...的,只要在配置文件里加上encoding选项就可以了。详细看/cake/libs/model/dbo/dbo_mysql.php