Recently I am planning to take over and improve a project written by others using Codeigniter. Although I have used CI before, I wrote it completely according to my own wishes and did not follow some of the CI routines. For projects used by the public, it is best to follow the framework specifications, so it is better to summarize it to avoid making others laugh when they take over it in the future.
1. The first is MVC
If you don’t know MVC yet, you should learn it as soon as possible. You will quickly realize the value of data access in Model, business logic in Controller, and writing HTML code in Views. You may wrinkle your forehead if you haven't programmed using this pattern before, but you should give yourself a chance to try it.
A rule of thumb is to put less stuff into the Controller and remember the DRY principle: don’t reinvent the wheel. When writing the same code in more than one place, you should try to write a library, helper, or model depending on its type. For example, the database connection class is used frequently, so it is made into a model (provided by the system).
Once you understand the essence of MVC, this will become a habit, and you will benefit a lot from MVC's concise code.
One principle is: leave complex operations to the Model. Controller is more like an architect. Model is hard work. View is the painter. The Controller only needs to throw things into the Model, and does not need to care whether the data is abnormal, and then returns a flag and corresponding data. In this way, the MVC architecture is reflected.
Model is actually like an electrical appliance such as a microwave oven. The simpler the method of use, the more people like it. (Put the food in - press start - ok, the rice is cooked.) The advantage of having fewer interfaces is that when the Model is upgraded and the code is optimized, , the coupling degree to the outside world is not high. Even if you write poorly internally, the interface is clean and easy to use.
2. Application and System paths
It is best to place the system and application folders outside the webroot. If index.php is placed under the /public_html/ path of the FTP server, you should try to place the System in the root directory. /system , in this case, your PHP files can only be accessed through index.php.
Don’t forget to modify the values of $system_folder and $application_folder in the index.php file. The value of $system_folder should be relative to the index.php file, while the value of $application_folder should be relative to the system directory.
3. Error reporting and debugging
A common mistake is to forget to turn off PHP error and database error reporting. Doing so is risky. In any public site, error_reporting should be set to 0, and can only be set to E_ERROR at most. The database setting db_debug should be set to false. Based on other security considerations, set error information not to be displayed ini_set('display_errors', 'Off');
As you code and debug, you should set error_reporting to E_ALL and address every note and warning before releasing your application.
A simple method is to set the value of db_debug to a constant MP_DB_DEBUG in the application/config/database.php file. When the website is running, set it as follows:
ini_set('display_errors', 'Off'); error_reporting(0); define('MP_DB_DEBUG', false);
Set it to:
ini_set('display_errors', 'On'); error_reporting(E_ALL); define('MP_DB_DEBUG', true);
4 during coding and debugging . Security issues are very important
Before receiving any data to your program, whether it is POST data submitted by a form, COOKIE data, URI data, XML-RPC data, or data in the SERVER array, we recommend that you practice the following Three steps:
Filter bad data.
Validate the data to ensure it matches the correct type, length, size, etc. (Sometimes this step can also replace the first step)
Put the data before submitting it to your database Conversion.
Regarding SQL injection, XSS, and CSRF, you should first understand them before deciding whether to adopt methods to prevent them. You can refer to the security guidelines in the CI manual and the input and security categories. Perhaps the most important principle is to check all user input before submitting data to the database or file system.
SQL injection. Using Active Record that comes with CI can solve this problem.
XSS (cross-site scripting). By setting $config['global_xss_filtering'] = TRUE; to enable automatic filtering of cross-site scripting attacks in POST and COOKIE, it will consume some resources. It can also be used separately each time POST and COOKIE are processed, and the second parameter is set to TRUE, such as $this->input->post('some_data', TRUE); The form validation class also provides XSS filtering Options, such as $this->form_validation->set_rules('username', 'Username', 'trim|required|xss_clean');
CSRF (跨站请求伪造)。CI 2.0 将内置 CSRF 检查,在 Google 上搜索 "CSRF tokens" 学习更多关于在保护表单提交和 URL 链接的知识,在 Ajax 应用方面可以搜索 "double cookie submission" 或 "双提交 cookie"。
SPAM (垃圾留言和恶意注册)。通过保护你的邮件表单,评论表单,以及其他各种免费用户提交的数据来防止垃圾信息,一个简单的方法是只允许一个IP/User客户端在一分钟之内只能提交一次,一个比较好的方式是使用 Captcha ,CI2中内置了一个CAPTCHA的辅助函数。
5. 数据库 和 ORM
CodeIgniter 有一个自带的库 Active Record 能够帮助你在不使用 SQL 语句的情况下写查询语句。这在你不太精通 SQL 语句或不知道怎样防止SQL注入的情况下是一个很好的方法。
当你需要更强大的工具时,你可以考虑使用 Object Relational Mapper ,就是鼎鼎大名的 ORM 了,遗憾的是,CodeIgniter 没有自带 ORM 库,不过也有一些其他很好的选择。
6. 代码实践
编写简洁的代码,并且理解你的代码,不要只是复制粘贴别人的代码,并且不断提高编码能力。手册上的开发规范是一个能学习怎样更好编写代码的地方。
1. DRY。不要总是重复造轮子,把能重用的代码放在它应该在的地方,比如libraries, helpers 或者是 models,而不是controllers,一个经验准则:当你复制代码的时候,也许你已经第二次把它放在了错误的地方。
2. Caching (缓存)。缓存是一个提高性能的很好的方式,尤其是减少数据库的访问。可以参考网页缓存和数据库缓存,或者在论坛上搜索其他的可选方案,比如 MP_Cache 是作者自己的作品。
3. HTTP headers (HTTP头部)。在客户端你能够通过单独发送HTTP头部使浏览器缓存页面来提高性能,当你使用 AJAX 的时候你也需要了解它来禁止浏览器缓存。
一个禁止缓存的例子:
$this->output->set_header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); $this->output->set_header("Cache-Control: no-store, no-cache, must-revalidate"); $this->output->set_header("Cache-Control: post-check=0, pre-check=0", false); $this->output->set_header("Pragma: no-cache");
一个长时间保持缓存的例子(比如 css, javascript):
$this->output->set_header('Cache-Control: private, pre-check=0, post-check=0, max-age=2592000'); $this->output->set_header('Expires: ' . gmstrftime("%a, %d %b %Y %H:%M:%S GMT", time() + 2592000)); $this->output->set_header('Last-Modified: ' . gmstrftime("%a, %d %b %Y %H:%M:%S GMT", time() - 20));
7. 模板渲染不必每次都调用 header 与 footer
在 MY_Controller 头部和 __construct 函数中添加以下内容,用于设定默认的模版信息,其中 SITE_NAME 需要自己在 application/config/constants.php 里面自己定义:
class MY_Cont roller extends CI_Controller { protected $_data; // 模版传值数组 protected $_tplext; // 默认模版后缀 protected $_header; // 默认头部模版 protected $_footer; // 默认底部模版 public function __construct () { parent::__construct(); $this->_data['title'] = SITE_NAME; $this->_tplext = '.php'; $this->_header = 'templates/header'; $this->_footer = 'templates/footer'; // 开发模式下开启性能分析 if (ENVIRONMENT === 'development') { $this->output->enable_profiler(TRUE); } } }
8. 不必所有的类都继承 CI_Controller
新增的控制器不再继承 CI_Controller,而改继承 MY_Controller:
class Index extends MY_Controller { public function __construct () { parent::__construct(); } /** * 前台首页 */ public function index () { $this->_data['title'] = '首页'; // 不指定则使用默认标题 SITE_NAME $this->_view('index/index'); } }
末了,再补充两个:
9. CodeIgniter的文件结构
cache用以存储缓存文件,codeigniter文件夹包含了CI的基类CI_Base,为了兼容php4和php5,CI_Base有两个版本,其中php4版本的CI_Base继承于CI_Loader。libraries里存放了大部分常用的类库,最主要的三个类:Model,View和Cotronller,自己写的任何mvc都要继承于已有的mvc类;helpers里是一些函数(方法)集合,用以辅助其他模块的方便工作。language是一个语言包,用以支持多语言。
application文件夹用以存储您的应用程序,CI已经在内部为您增加了一些子文件,包括models、views、controllers、config、errors、hooks和libraries。其中前三个文件夹是用以创建模型、视图和控制器的。您的大部分工作都应该是创建属于自己的MVC,并可在config里加入配置文件,libraries里加入一些对象和方法,用来辅助您的模型和控制器工作。而hooks也是对CI_Hooks的扩展,具体内容见下面的章节。
10. CodeIgniter的工作过程
当有一个http请求时,如http://www.google.com/blog/,首先进入CI的引导文件index.php。接下来我们看看index.php里做了哪些事情。
index首先设置了应用程序的文件夹名称为application,系统的文件夹名称为system,然后做了一系列严格的判断并转换为unix风格的服务器绝对文件路径,具体说来定义了两个比较重要的常量,APPPATH,应用程序的文件夹路径,根据分析可知,该路径可以和system同级:htdocs/application/,也可以放到system文件夹里面,作为其子文件夹:htdocs/system/application/,但推荐采用第二种方式,这样显得比较整齐;BASEPATH,网站文档的基本文件路径,写出来大概是htdoc/system/;到最后,index引导文件引入了codeigniter/codeigniter.php里。接下来我们看看codeigniter里做了什么事情。
codeigniter.php一上来就引入了三个文件:Common.php,Compat.php和config/constants.php,其中Common里包含了一些函数,用于载入类库的load_class,记录日志的log_message,和引入错误页面的show_404是几个重要的函数;Compat主要解决了php4和php5中的函数不兼容问题,而constants则定义了一些读写文件权限的常量。
Then codeigniter loads the first class library, Benchmark. One of the simplest applications of this class library is to calculate the time it takes for a web page to start from the beginning to the end of compilation, so you put a mark at the beginning of compilation and the rendering ends. Then add a mark and you can calculate the time spent.
Then the second class library, Hooks, is loaded. Like Benchmark, this class library is under systemlibraries. The function of this class library is to provide you with an opportunity to perform other things before the program starts compiling. Hooks will tell you Approximately 8 opportunities are provided to perform other tasks, see the user guide for details. Here it imports the first hook.
Then load the Config, URI, Router, Output and other class libraries respectively. Then, check whether there is a cache_override hook. This hook allows you to schedule your own function to replace the _display_cache method of the Output class. If not, call it directly. Output's _display_cache checks whether there is cache content. If there is, the cache will be output directly and exit; if not, the execution will continue.
After that, continue to load Input and Language. Note that the class library loaded before is a reference; then there is another important load, which is the loading of the CI_Base object. First, the php version will be judged. If it is the php4 version , Loader will be loaded first, and then Base4, because CI_Base in Base4 inherits from CI_Loader, but in Base5, CI_Base and CI_Loader have no inheritance relationship.
The next step is also the really critical step. This step starts by loading a Controller class. This is an instance, not a reference; then the http address is parsed through the Router to get the names of the controller and methods, and then look at the application controllers Whether there is such a controller and method, if not, an error will be reported; if there is, the judgment will be started.