作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.
迈克尔•霍顿
验证专家 在工程

Michael is a full-stack developer with 13+ years of experience. 他对PHP很有经验 & Vue.js.

以前在

Apple
Share

CakePHP是一个了不起的PHP框架,但它有一个陡峭的学习曲线! It requires a good amount of research and training to become an expert.

I have been fortunate to use CakePHP for over 7 years now, and in that time I’ve had the honor of working with many CakePHP社区的成员.

在这个CakePHP教程中,我想描述一些我多年来看到的糟糕实践, and propose the correct approach to avoid these mistakes. 这并不是说我的代码是完美的, 但作为一名程序员,我们总是在学习, so it is important to follow the best practices and adjust as you learn!

Content of this article is inspired by a post from CakeCoded. 如果您想了解更多关于CakePHP的信息,请访问我们的学习部分 here.

这个初学者CakePHP教程将帮助您避免用错误和错误来油炸CakePHP代码!

Common Mistake #1: Not Following CakePHP Coding Conventions

CakePHP的编码约定可以 看这里. 我将强调一些我在查看其他程序员的代码时经常注意到的事情.

控制结构. 所以你经常会看到程序员犯这个错误, and in some cases bring practices from other coding languages. CakePHP期望以下语法:

If ((expr_1) || (expr_2)) {
    / / action_1;
} elseif (!(expr_3) && (expr_4)) {
    / / action_2;
} else {
    / / default_action;
}

第一个括号前应该有1(1)个空格,最后一个括号和左括号之间应该有1(1)个空格. So this means that the following is incorrect:

if($this->request->data){

}

的空格 if and (,以及 ) and {

在控制结构中总是使用花括号,即使不需要. 它们增加了代码的可读性,并且减少了逻辑错误.

So, for example, the following is incorrect:

if ($foo)
    $bar = true

应该这样格式化:

If ($foo) {
    $bar = true
}

最后,注意括号的位置. 左括号不应该开始新的一行. 确保所有的括号对齐,使每个新括号与结束括号对齐.

下面是一些不正确的例子:

if ($foo)
{
    $bar = true;
}

This is incorrect, the opening bracket should be in the first line:

If ($foo) {    
    $bar = true;
If ($action) {
    $to = false;
}
}

缩进需要正确对齐.

I often hear programmers say, “But I am too busy to make the code neat….” My response is, “Trust me, neat code will stand the test of time”. 如果需要在几个月内进行更改,那么编写不可读的CakePHP代码将是一场噩梦.

常见错误#2:在ORM中不正确地使用可包含行为和递归级别

最近,我有幸与Facebook的一位数据库开发人员进行了一次非正式的讨论. 我们开始谈论CakePHP,他对我说,“哦,它使用ORM,不是吗? 这很可怕.我问他是什么意思, 他评论说,使用对象关系映射(ORM)很容易使SQL查询变得不必要的大.

在某种程度上他是对的. CakePHP的神奇之处在于它对ORM的使用,以及它将不同的数据库表关系组合在一起的方式. By default, CakePHP automatically selects any related ‘Belongs To’, “有一个”和“有很多”数据, 这可能导致非常大的SQL查询. 在最初开发应用程序时,这些查询可能不是一个问题, 但经过六个月的实时数据收集, you may find the application becomes very slow, and in some cases crashes if the queries aren’t optimized.

I look out for two things when auditing an existing website. Firstly, has the default recursive level been changed? 默认情况下,CakePHP将递归级别设置为1,我认为这个级别太高了. 我总是将其设置为-1,然后使用containable行为来获取任何相关模型.

这就引出了我要寻找的第二件事——是否使用了Containable行为? I often have new clients come to me and say that CakePHP is slow. The reason is almost always because Containable hasn’t been used! 一个优秀的CakePHP程序员会优化他们的SQL查询,而不管幕后做了多少“自动魔术”.

The containable behavior wasn’t added until CakePHP 1.2 .但是,男孩,这有什么不同?! 确保尽可能多地使用containable,因为这是优化SQL的有效方法. 有关如何实现和使用Containable行为的详细信息,请参见 click here.

常见错误#3:将业务逻辑保存在控制器中而不是模型中

Good CakePHP code will have the logic in the model files. 这需要一点时间来适应,但一旦掌握了就没有回头路了! 控制器文件应该用于它在MVC模式中的目的——控制! So use your controller file to handle user actions, while letting the business logic go in the model file.

A good example of this would be a simple CRUD - an everyday action! Let’s take the add posts function from a blog tutorial as an example. 默认的add函数如下:

公共函数add() {
    if ($this->request->is('post')) {
        $this->Post->create();
        if ($this->Post->save($this->request->data)) {
            $this->Session->setFlash(__('Your post has been saved.'));
            return $this->redirect(array('action' => 'index'));
        }
        $this->Session->setFlash(__('Unable to add your post.'));
    }
}

This controller action is fine for a simple add, 但是,如果您想在添加帖子时向管理员发送电子邮件等操作,会发生什么呢, or update another model association when a post was added. 这是附加的逻辑,但是这个逻辑不应该进入我们的控制器文件.

Instead we would write a function for this in our Post.php model. 也许是这样的:

public function addPost($data = array(), $emailAdmin = true) {
    $this->create();
    $this->save($data);

    //更新其他表

    //发送邮件给admin用户
    if ($emailAdmin) {
    
    }

    //如果一切成功
    返回true;
}

这将导致对控制器动作的一个小改变,如下所示:

公共函数add() {
    if ($this->request->is('post')) {
        if ($this->Post->addPost($this->request->data)) {
            $this->Session->setFlash(__('Your post has been saved.'));
            return $this->redirect(array('action' => 'index'));
        }
        $this->Session->setFlash(__('Unable to add your post.'));
    }
}

As you can see, the new action is actually one less line, because the $this->Post->create() 是否已移动到模型文件.

这是一个完美的, 在日常示例中,将逻辑移动到模型文件中是一个好主意——而且它肯定会使代码库更加清晰!

常见错误#4:给代码添加太多复杂性,而不是经常和尽早返回

这一直是一个持续的争论, 但是经常回来, and returning early certainly does make for much cleaner looking code. This applies to the model methods more than anything else.

但我到底是什么意思? 好吧,让我们看看我们在上面的CakePHP教程中添加的方法:

public function addPost($data = array(), $emailAdmin = true) {
    $this->create();
    $this->save($data);

    //更新其他表

    //发送邮件给admin用户
    if ($emailAdmin) {
    
    }

    //如果一切成功
    返回true;
}

经常回来, and return early means that as we run through our function, we check to make sure the everything is OK on a regular basis. If it isn’t, then we return false, or return a CakePHP error.

It might be easiest to show this with an example. There are two ways the above function could be written:

public function addPost($data = array(), $emailAdmin = true) {
    If ($data) {
        $this->create();
        $result = $this->save($data);

        If (结果美元){
            //更新其他表

            //发送邮件给admin用户
            if ($emailAdmin) {
                //发送admin邮件
            }
        } else {
            //保存数据有问题
            返回错误;
        }

        //如果一切成功
        返回true;
    } else {
        //没有数据提交
        返回错误;
    }
}

看看代码是如何迅速变得不可读的? There are ifs and elseS到处都是,函数很快就变成了一个大缩进. 别误会我, 我喜欢干净的凹痕, but watch how the function looks if it written with the return often, 早退原则.

public function addPost($data = array(), $emailAdmin = true) {
    if (!$data) {
        //没有数据提交
        返回错误;
    }

    $this->create();
    $result = $this->save($data);

    if (!结果美元){
        //保存数据有问题
        返回错误;
    }

    //更新其他表

    //发送邮件给admin用户
    if ($emailAdmin) {
        //发送admin邮件
    }

    //如果一切成功
    返回true;
}

马上, 在这个小例子中, 您可以看到代码只有一个缩进,可读性更强. 逻辑实际上更有意义——让逻辑逐行运行, 如果在此过程中出现任何问题, return the error and don’t proceed to the next line.

这允许CakePHP程序员用和我们阅读一样的方式来写代码——从左到右读代码, 从上到下, 而不是在不同的街区, 哪个很快就会让人困惑!

Common Mistake #5: Not Using the DRY Principle

DRY代表不要重复自己, and it is a philosophy which should be followed when coding in CakePHP. 对于面向对象的代码,没有理由重复相同的代码块两次!

Here are few CakePHP tips to ensure you don’t repeat yourself:

  • 如上所述,目标是将逻辑放入模型文件中,以便您可以共享逻辑.

  • 在视图文件中, 如果你在重复视图, 将视图代码创建为一个元素, 甚至是一个定制的助手.

  • 设置一些配置设置 应用程序/配置/引导.php 文件是一个很好的地方. 这有助于确保您没有硬编码诸如应用程序名称和主电子邮件地址之类的内容. 您最不希望做的事情就是仅仅因为客户端要求更新应用程序中的电子邮件地址而遍历数百个文件.

  • 经常问自己, “如果我在重复代码, 是否有更好的方法来编写这段代码, and am I putting this code in the right place?” Chances are, if you need to repeat code, it could be written better.

常见错误#6:不注释代码

The last point I will make is in regards to comments. 首先,文档阻塞. A doc block is when you document a method or an action. It takes only a minute to record a little about what a function is doing, but it makes such a difference in terms of readability of code.

CakePHP Doc Blocks need to go against the left margin of the page. So a simple example using the code from above.

/**
 * Adds & 保存帖子,并发送电子邮件给管理员,让他们知道帖子已添加.
 *也执行一些保存到另一个表
 *
 * @param array $data post data
 @param bool $emailAdmin如果设置为true,将发送电子邮件给网站管理员
 * @return bool如果成功返回true
 */
public function addPost($data = array(), $emailAdmin = true) {

你会看到, 编写文档块并不需要很长时间, but it makes a huge difference in terms of longevity of the code. Ultimately, it means the code can live on past you as the developer.

内联注释也是如此. Don’t be scared to explain what your code is doing and why! It makes it a lot easier in the long run to understand your code, especially if another developer is looking at it!

Wrap-up

CakePHP is an extensive, full-featured framework. Given it follows convention over configuration, CakePHP is more strict than other PHP based frameworks, 从某种意义上说,用户被“强迫”遵循某种布局代码的方式. 这是有争议的, but in my experience it leads to a code base which is more consistent, 可读性和可理解性——而不是让开发人员“选择”应该如何编写代码, 开发团队将按照Cake的约定编写一致的代码.

通过遵循本CakePHP教程并确保您的代码编写得很好, 应用程序可以经受时间的考验. 代码应该永远是为明天而写的——这样,如果另一个开发人员在几年后看到一个特定的代码块, 他会理解代码的, 并坚持预期的标准. CakePHP也不例外,希望本指南能帮助纠正一些坏习惯.

聘请Toptal这方面的专家.
Hire Now
迈克尔•霍顿

迈克尔•霍顿

验证专家 在工程

爱尔兰利默里克,

2014年4月21日成为会员

作者简介

Michael is a full-stack developer with 13+ years of experience. 他对PHP很有经验 & Vue.js.

作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.

以前在

Apple

世界级的文章,每周发一次.

By entering your email, you are agreeing to our 隐私政策.

世界级的文章,每周发一次.

By entering your email, you are agreeing to our 隐私政策.

Toptal开发者

加入总冠军® community.