PS - 个人博客原文:CI框架入门笔记

当前(2019-03-22)CodeIgniter 框架的最新版本是 3.1.5,于2017年6月发布,距今快两年了也没有更新,这与 Laravel 的更新速度相比差距太大了。因为确实,它是一个很古老的框架了(第一个版本在2006年发布),当初的设计原则,开发环境与现在都已经大为不同。它有自己的设计原则,有相配套的一大堆工具、库,使用这些现有的工具就已经能很好地满足日常开发所需。

虽然已经是2019年了,但是公司用的框架是CI框架,所以我也应当快速适应CI框架的开发模式。本文就针对CI框架开发中的一些重点问题进行梳理和记录。CI框架的官网文档( http://codeigniter.org.cn/user_guide/index.html )很完善,但是我觉得仍然有必要整理出自己的一套实用规则。

就一个常规PHP框架来说,我认为应当包含这几个部分:

  • (1)index.php 或全局 App 对象,一个提供统一入口,一个提供容器资源管理
  • (2)路由控制
  • (3)请求和响应对象的封装,输入数据过滤和验证,输出数据的验证和转义,各种输入输出方法
  • (4)MVC 分层,控制器,模型和视图层,以及 Service 层
  • (5)数据库操作:数据库驱动、查询构造器、通用的查询方法
  • (6)文件存储、缓存管理
  • (7)Session, Cookie管理
  • (8)安全性、配置、国际化、自动加载、第三方扩展机制
  • (9)常见的工具类(其实应当通过扩展提供)
  • (10)模板语言(这个不是必要的,因为PHP本身就能输出)

入门

了解框架

我们下载好CI框架解压之后的初始目录是下面这样的:

application/
controller/
cache/
config/
controllers/
core/
helpers/
hooks/
language/
libraries/
logs/
models/
third_party/
views/
.htaccess
index.html
system/
core/
database/
fonts/
helpers/
language/
libraries/
index.html
.gitignore
composer.json
index.php

其中,我注意到,每个目录下面都有一个index.html文件,其内容也都是一样的:403 Forbidden。这是为了防止意外访问吗?

application/ 就是是项目目录,就是我们实际的项目代码存放处,下面分了很多子目录,看名字就知道会放哪种功能的代码,这些子目录目前除了包含一个 403 index.html 文件,没有别的内容。system/ 就是框架目录,下面就是框架代码。

根目录的 index.php 是整个项目的唯一入口点。index.php 主要的功能是定义了一些系统目录,包括项目目录、视图目录、框架目录,在最后调用了框架目录下的 core/CodeIgniter.php,这个文件是CI框架的入口点和结束点,即包含了CI框架的所有生命周期。它的执行过程如下:

* 定义全局常量,加载全局函数,环境检测,PHP版本判断
* 注册错误处理函数,自动加载函数(Composer判断)
* 加载一系列类:
* Hooks,钩子函数类
* Config,配置类
* UTF-8,
* URI,(CI_URI)
* Router,路由类
* Output,输出类
* Security,安全类
* Input,输入类
* Lang,多语言类
* 加载控制器类
* 判断控制器类、方法是否存在,不存在则404
* 调用控制器前置钩子函数
* 实例化控制器
* 调用控制器后置钩子函数
* 调用控制器方法(业务逻辑)
* 输出响应
* 调用系统后置钩子函数

在实例化控制器这一部分中,注意到它定义了一个静态实例,代码如下

# core/CodeIgniter.php
# 此处定义了一个全局函数 get_instance(),返回一个静态对象。
function &get_instance()
{
return CI_Controller::get_instance();
}
// ... $CI = new $class(); # core/Controller.php
class CI_Controller {
public function __construct()
{
self::$instance =& $this;
// ...
} public static function &get_instance()
{
return self::$instance;
}
}

在之后的任意位置的代码中,只要通过 get_instance() 方法就能获取唯一的 Controller 对象,它其实就是CI框架中的“容器”。

调用控制器方法(即业务逻辑)通过这段代码调用执行:

call_user_func_array(array(&$CI, $method), $params);

业务逻辑

在调用上述代码之后,就进入到 application/ 目录下我们的实际的业务功能代码。上面的 &$CI 就是 $class 名对象,即根据URL参数解析对应到 application/controllers/ 目录下的实际控制器类文件名。具体的映射方法可以看文档( https://codeigniter.org.cn/user_guide/general/controllers.html

比如,有一个 URI 是这样的:/welcome,会解析为 application/controller/Welcome.php 文件,它应该是一个继承自 CI_Controller 的类。/welcome 相当于 /welcome/index,URI 的第一个部分是控制器,第二个部分是控制器的方法,所以这个 URI 会调用 Welcome 类的 index 方法。URI 中只有第一个部分时,那第二个部分默认是 index。在控制器方法中我们编写实际的业务功能代码。示例如下:

<?php
defined('BASEPATH') OR exit('No direct script access allowed'); class Welcome extends CI_Controller { public function index()
{
$this->load->view('welcome_message');
}
}

加载功能模块(类库)

CI框架默认提供了模型、视图、辅助函数、日志、配置、缓存等功能。这些功能模块默认是不加载的,需要在控制器中进行手动按需加载。另外,libraries 目录中的类库,也是同上的加载机制,只不过这里面的类库是开发人员自己写的功能模块。下面详细描述每种模块的加载方式。

model

首先,我们看到上节中的 $this->load,这就是CI框架中的加载类(CI_Loader),我们所有需要的类库、模块都可以通过它来加载。这个加载类实际上是“容器”的一个对象属性,从下面 model 的源码可以看到,实际上所有容器的“对象属性”都可以直接通过模型获取:

class CI_Model {
public function __get($key)
{
return get_instance()->$key;
}
}

在业务功能开发中,使用最频繁的就是模型了。CI框架提供的模型类是 core/Model.phpCI_Model 类,它其实就是一个很简单的类,没有提供任何内容,如果你需要使用模型,那就应该在 application/models 下面新建一个继承自 CI_Model 的类,然后在使用模型的地方先使用 $this->load->model() 来加载它,加载了之后,就能直接通过 $this->{模型名} 访问该模型对象:

 $this->load->model('User_model');
$result = $this->User_model->get_one($id);

model() 默认到 application/model/ 目录下寻找 user_model.php 这个文件名,然后加载 User_model 类,实例化之,并赋值作为“容器”的对象属性,属性名就是模型名。model() 方法部分源码:


public function model($model, $name = '', $db_conn = FALSE)
{
// ...
$model = new $model();
$CI->$name = $model;
}

model() 方法的第二个参数可以指定属性名,示例代码如下:

$this->load->model('User_model', 'USER');
$result = $this->USER->get_one($id);

CI框架并没有规定模型类中应当放什么,这取决于你。通常我们会写一个 Base_Model 类,用来提供各种查询方法,然后在具体的模型类中实现具体模型对应的业务方法。在控制器中直接调用模型类的业务方法获取数据。在CI框架中我们使用模型类的理由就是封装逻辑,不然所有的逻辑都写在控制器中(我看到项目中现在有一部分老代码就是这样做的!)。CI也没有提供进一步Service层,这由你自己决定。

database

一般在 Base_Model 类中,我们会加载一下默认的数据库,封装若干查询方法:

class Base_Model
{
function __construct()
{
// ...
$this->load->database();
} function save() {}
function get_one() {}
function get_all() {}
function update() {}
function delete() {}
function query() {}
...
}

调用了 database() 之后,会实际化一个 CI_DB 对象,并赋值为控制器的 $db 属性,database() 部分源码如下:

public function database($params = '', $return = FALSE, $query_builder = NULL)
{
// ...
if ($return === TRUE)
{
return DB($params, $query_builder);
}
// ...
$CI->db =& DB($params, $query_builder);
}

可以看到,当第二个参数为 TRUE 时,直接返回 DB 对象,并不会设置为控制器的属性。这一点在具体的模型类中会有用,比如我们会在具体的模型类中加载不同的数据库类:

class Article_model extends Base_Model
{
public function __construct()
{
$this->db = $this->load->database('myDb2', TRUE);
}
}

这里获取 myDb2 数据库对象,避免了污染全局的 $CI->db 对象。

最复杂的部分其实已经介绍完了,下面是一些常用的类库介绍

helper

在使用自定义的辅助函数之前,需要加载一下,语法同上。只不过它会去 application/helpers 目录下去寻找相应文件。

$this->load->helper('dt');

libraries

application/libraries 目录下的类,加载语法同上,使用其实没什么问题,值得注意的是如何写一个自己的类库。

$this->load->library('t');

config

配置文件也需要加载,然后 item 方法直接访问配置文件中的值,自定义的配置需要设置为 $config 数组的属性的形式。

# application/config/d.php
$config['ddd'] = ''; # Controller
$this->load->config('d');
$data = $this->config->item('ddd')

view

由于现在CI项目只是作为API,所以并无视图,但为了介绍,下面提供了一个示例:

# application/views/welcome.php

# Controller
$this->load->view('welcome', $data);

这个视图文件就是一个普通的PHP文件,可以直接输出。

driver

驱动其实也是类库的一种。

总结

就我入手这个CI项目的一个月经验来看,日常业务开发就是这些东西,后面也不过是在这个框架基础上不断深入和完善。所以这篇文章作为入门总结应该算是足够了。

CI框架入门笔记的更多相关文章

  1. CI框架入门1

    CI框架入门: 1.url的特点             2.目录结构/布局             3.MVC分别在哪里,如何依葫芦画瓢             4.安全性             ...

  2. CI框架入门

    本人最近在学习CI框架,网上找到一些个人觉得入门比较好的资料,记录一下: 兄弟连的CI框架入门系类: [军哥谈CI框架]之入门教程之第一讲:codeigniter的介绍和安装配置:http://bbs ...

  3. 一看就懂的Mybatis框架入门笔记

    本篇为初学Mybatis框架时的入门笔记,整理发出 Spring集成Mybatis https://www.cnblogs.com/yueshutong/p/9381590.html SpringBo ...

  4. 【转】最简单的CI框架入门示例--数据库取数据

    1.下载CI框架(自己找) 2.配置 database.php配置:    为数据库服务器设置 connection 参数: $db['default']['hostname'] = "yo ...

  5. CI框架入门教程

    1. URL常用的相关函数 url相关函数在辅助类url中第一,要使用它们必须先加载$this->load->helper('url')或者自动装载    site_url('控制器/方法 ...

  6. 最简单的CI框架入门示例--数据库取数据

    前提: 安装好MySQL,Apache,PHP. 1.下载CI框架 下载地址  http://www.codeigniter.com/ 2.配置 database.php配置:    为数据库服务器设 ...

  7. CI框架入门2

    文件目录与布局 1.user_guide    用户手册,可删 2.readme.rst    说明,可删 3.license.txt     证书,可删 4..gitignore composer. ...

  8. CI框架学习笔记

    打印SQL语句$this->dbRead->last_query(); 重映射方法正如上文所说,URI 的第二段通常决定控制器的哪个方法被调用.CodeIgniter 允许你使用 _rem ...

  9. Express NodeJs Web框架 入门笔记

    Express 是一个简洁而灵活的 node.js Web应用框架, 提供了一系列强大特性帮助你创建各种 Web 应用,和丰富的 HTTP 工具. 使用 Express 可以快速地搭建一个完整功能的网 ...

随机推荐

  1. 2018.10.27 洛谷P2915奶牛混合起来Mixed Up Cows(状压dp)

    传送门 状压dp入门题. 按照题意建一个图. 要求的就是合法的链的总数. 直接f[i][j]f[i][j]f[i][j]表示当前状态为jjj,下一位要跟iii连起来的方案数. 然后从没被选并且跟iii ...

  2. dom4j 通过 org.dom4j.DocumentFactory 设置命名空间来支持 带namespace 的 xpath

    测试文件 test.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http:/ ...

  3. Servlet Life Cycle

    Servlet Life Cycle http://docs.oracle.com/javaee/5/tutorial/doc/bnafi.html Servlet Filters and Event ...

  4. Eclipse环境下如何配置tomcat,并且把项目部署到Tomcat服务器上

    打开Eclipse,单击“Window”菜单,选择下方的“Preferences”. 单击“Server”选项,选择下方的“Runtime Environments”.  点击“Add”添加Tomca ...

  5. $.contains(a,b)

    jQuery.contains()函数用于判断指定元素内是否包含另一个元素. 简而言之,该函数用于判断另一个DOM元素是否是指定DOM元素的后代. 该函数属于全局jQuery对象. 语法 jQuery ...

  6. 属性动画和Activity、Fragment过渡动画等

    主题是关于动画的,但是不是什么动画的内容都包括.先泛泛的介绍一下,然后详细的介绍一下翻代码找见的一个好玩的动画的使用.以下的内容包括Android 3和Android 3.1等引入的API,在使用中请 ...

  7. 20145232 韩文浩 《Java程序设计》第5周学习总结

    教材学习内容总结 处理异常 教材中使用一个简单的程序,用户连续输入整数最后输入0结束后显示输入数的平均值. 但有时,用户会没有按常规出牌输入不正确的信息,例如"30"输成" ...

  8. JAVA作业之两数的加减乘除

    1.设计思路 把输入的字符转化为计算的数字问题,再以对话框的形式输入输出加减乘除的结果问题. 2.程序流程图 3.源代码 4.实验结果

  9. 第86讲:Scala中For表达式的生成器、定义和过滤器

    今天我们来看一下For表达式中的生成器,定义和过滤等内容. 让我们来看下代码 def main(args:Array[String]){     val lauren = Persons(" ...

  10. 卷积神经网络(CNN)之一维卷积、二维卷积、三维卷积详解

    作者:szx_spark 由于计算机视觉的大红大紫,二维卷积的用处范围最广.因此本文首先介绍二维卷积,之后再介绍一维卷积与三维卷积的具体流程,并描述其各自的具体应用. 1. 二维卷积 图中的输入的数据 ...