ThinkPHP-MVC什么是框架

📅 2026/7/15 3:08:47
ThinkPHP-MVC什么是框架
什么是框架框架即framework。其实就是某种应用的半成品就是一组组件供你选用完成你自己的系统MVC是一个设计模式它强制性的使应用程序的输入、处理和输出分开。使用MVC应用程序被分成三个核心部件模型、视图、控制器。Zend FrameworkYiiSymfonyCodelgniterThinkPHP……3、什么是MVCMVC是施乐帕克研究中心 (Xerox PARC)在八十年代为编程语言Smalltalk80发明的一种软件设计模式至今已被广泛使用。MModel模型VView视图CControl 控制器快速入门控制器视图模型实用项4、介绍thinkphphttp://thinkphp.cn下载thinkphp3.0直接部署到项目中php5.2thinkphp1.0 php5.0thinkphp3.0 php5.2thinkphp3.2.2 php5.3项目布署流程1解压thinkphp并进入到解压出来的文件夹2将ThinkPHP文件夹放在我们的项目中5、快速入门1开发项目入口文件2运行以上程序自动创建相应的程序文件看到以上界面说明项目创建成功在我们的项目中自动产生了一些文件夹如下图所示Common 项目公共文件目录Conf 项目配置目录Lang 项目语言包目录Lib 项目类库目录Tpl 项目模板目录Runtime 项目运行时目录~runtime.php 这个文件会自动将项目的当前配置、公共函数等程序编译到这个文件中下次程序运行时直接运行这个文件即可。以上URL中的Index会被自动处理为模块名以上URL中的index会被自动处理为动作名3开启调试模式代码运行开启调试模式之后如果发生了一些错误会有一些提示信息建议开发时开启调试模式布署时关闭调试模如果你的项目路径与本题相同可以不定义三个路径常量注意开启调试后不会产生runtime.php文件4分析项目入口文件5默认配置为什么输入地址之后,可以看到内容因为使有以上url时会自动加载Index模块控制器下的index方法在框架配置文件中复制两个配置选项将以上选项放在项目配置文件中6添加新的控制器以及方法在Lib/Action下创建新的控制器GoodsAction在GoodsAction中添加新方法add运行以上程序为add方法添加指定模板并显示一个项目对应一个数据库一个数据库中包含很多数据表一个数据表就是一个模块一个模块可以对应一个控制器在Tpl下创建Goods文件夹用于存放所有Goods模块下的模板修改控制器代码运行7配置项目的虚拟主机修改apache配置文件修改hosts文件重启apache并重新运行二、控制器1、什么是控制器控制器用于接收和处理用户的请求2、定义控制器在Lib/Action下创建控制器文件文件名模块名首字母大写Action.class.php如我们有一张数据表member会员表/Lib/Action/MemberAction.class.php控制器内容class 模块名首字母大写Action extends Action{}必须继承父类控制器Action代码3、url调度模式url的调度模式就是url的访问方式ThinkPHP支持四种URL模式可以通过设置URL_MODEL参数来定义这个配置选项的值共有四个0 普通模式1 pathinfo模式默认2 rewrite模式3 兼容模式1普通模式语法http://项目/入口文件?m模块名a动作名运行2pathinfo模式语法http://项目/入口文件/模块名/动作名运行在项目的配置文件中可以修改以下选项修改路径分隔符URL_PATHINFO_DEPR访问时3rewrite模式1修改config.php配置选项2httpd.conf配置文件中加载了mod_rewrite.so模块3AllowOverride None 将None改为 All4把下面的内容保存为.htaccess文件放到入口文件的同级目录下IfModule mod_rewrite.cRewriteEngine onRewriteCond %{REQUEST_FILENAME} !-dRewriteCond %{REQUEST_FILENAME} !-fRewriteRule ^(.*)$ index.php/$1 [QSA,PT,L]/IfModule语法http://项目/模块名/动作名运行4兼容模式语法http://项目/入口文件?s/模块名/动作名运行4、空操作空操作是指系统在找不到指定的操作方法的时候会定位到空操作_empty方法来执行利用这个机制我们可以实现错误页面和一些URL的优化。语法public function _empty($name){}1错误页面的定制访问时2优化url访问我们访问时由于没有shanghai方法所以会自动定位到_empty方法中并将shanghai做为参数传递给$name。5、空模块空模块的概念是指当系统找不到指定的模块名称的时候系统会尝试定位空模块(EmptyAction)利用这个机制我们可以用来定制错误页面和进行URL的优化。语法class EmptyAction extends Action{}MODULE_NAME请求的当前模块名称1错误页面的订制运行系统找不到abc控制器所以会自动定位到EmptyAction中。2优化url运行6、项目分组一般网站项目是由若干个小项目构成的如前台、后台、会员、博客等配置文件config.php中有两个选项用于配置项目的分组?APP_GROUP_LIST 分组列表?DEFAULT_GROUP 默认组名1修改配置文件2创建分组控制器目录3运行4对模板进行分组7、url大小写TP中的url严格区分大小写如果想不区分大小写可以修改以下选项配置文件config.php?‘URL_CASE_INSENSITIVE’true运行8、页面跳转在需要对用户的操作信息进行提示时可以使用以下两个方法?success 操作成功时所调用的方法?error 操作失败时所调用的方法配置文件config.php?TMPL_ACTION_SUCCESS success方法对应的模板?TMPL_ACTION_ERROR error方法对应的模板代码运行配置文件中可以修改以上选项实现自定义模板9、页面重定向如果想实现页面的重定向可以使用以下方法redirect语法$this-redirect(“news/show”, array(‘id’2), 5, “页面跳转中” );参数1跳转地址参数2参数数组参数3停留时间参数4提示信息三、视图1、什么是视图用户看到的并与之交互的界面在tp中视图主要包含两部份1视图类2模板2、模板定义默认的模板文件定义规则模板目录/[分组名/]模块名/操作名模板后缀TMPL_TEMPLATE_SUFFIX 模板后缀名3、分隔符?TMPL_L_DELIM{, 模板左分界符 默认{?TMPL_R_DELIM}, 模板右分界符 默认}4、模板赋值与输出模板赋值$this-assign(‘模板变量名’,’值’);模板输出$this-display(‘模板名’);5、模板字符串替换在tp的模板中默认有一些字符串表示一些路径?__PUBLIC__当前网站的公共目录?__APP__ 当前项目的URL地址?__GROUP__当前分组的URL地址?__URL__ 当前模块的URL地址?__ACTION__当前操作的URL地址?TMPL_PARSE_STRING 可以在配置文件中配置此选项用于一些常用路径的定义模板文件运行配置文件模板文件6、获取内容?$this-fetch();fetch 获取内容返回字符串display 输出字符串7、模板注释tp的模板中可以加入注释有两种方式?{/* 注释内容 */ } 多行注释?{// 注释内容 } 单行注释运行可以看出tp模板注释属于服务器端注释不会显示在客户端中8、变量输出在tp的模板中变量输出主要有三种形式1普通变量{$name}、{$email}2数组变量{$row[‘name’]}、{$row.name}3对象变量{$obj:name}、{$obj:test()}控制器代码模板代码运行结果9、系统变量在tp的模板有一个内置的对象它是$Think它可以引用很多系统内置的变量?$Think.server $_SERVER?$Think.get $_GET $Think.get.username?$Think.post $_POST?$Think.request $_REQUEST?$Think.cookie $_COOKIE?$Think.session $_SESSION?$Think.config 引入配置文件中的值运行10、使用函数语法{$name|fn1|fn2arg1,arg2,### }运行11、默认值语法{$变量|default默认值}以下情况时会自动使用default后面的内容1没有为这个变量分配数据2向这个变量分配空数据12、运算符在模板中可以直接使用算术运算符对变量进行运算? {$a$b}?- {$ab}?* {$a*$b}?/ {$a/$b}?% {$a%$b}? {$a} 或 ?{$a}?-- {$a--} ?或 {--$a}控制器模板运行13、文件包含语法include?file模板文件名?/是基于项目的入口文件位置。./Tpl/Admin/Public/header.html目录结构Public所有公共页模板在模板中include的另一种语法include file’模块:操作’ /在上题中在Index模块下的模板中可以直接使用这种语法来引用其它模块下的模板footer.html运行14、导入文件导入文件是指对资源文件css、js的导入语法import type‘type’ file‘file’ /file必须资源文件type可选资源文件类型默认为js起始路径是网站的Public目录以前的导入方式文件目录模板代码运行15、volist标签语法volist?namelist?idvo{$vo.id}{$vo.name}/volist?name必须要遍历的数组变量?id必须当前数组元素?offset 要输出数据的offset?length 输出数据的长度,需要指定offset?key 循环索引从1开始排列默认值i控制器模板运行16、foreach标签foreach用于解析数组语法‘foreach namelist?itemvo {$vo.id}{$vo.name}/foreachname要解析的数组名称item当前解析到的数组元素模板运行17、if标签语法?if?condition$name eq 1? value1? elseif?condition$name eq 2/? value2? else /? value3? /if关于condition里面的判断条件?eq或者 equal等于?neq 或者notequal不等于?gt大于?egt大于等于?lt小于?elt小于等于?heq恒等于?nheq不恒等于模板运行18、php标签在tp的模板中允许直接使用php代码语法1phpecho “hello”;/php2?php echo “think”; ?TMPL_DENY_PHP 用于配置模板中是否拒绝使用php代码模板运行修改配置文件禁用第二种php写法四、模型1、什么是模型模型表示企业数据和业务规则2、定义模型Lib/Model下文件命名规则表名首字母大写Model.class.php模型内代码class 表名首字母大写Model extends Model{}在tp中如果没有特殊的业务要求可以直接使用Model类而不需要定义子类模型但推荐使用子类模型自定义模型数据表文件代码我们尝试去实例化这个模型类对象运行说明tp中的模型被实例化的同时会自动创建与数据库连接3、配置数据库信息在配置文件config.php中添加以下信息再重新运行以上程序看到上图说明配置信息添加成功。通过上图可以看出tp模型被实例化时会自动解析当前模型对应的数据表的表结构4、实例化模型对象我们目前使用的模型主要分两种1自定义模型GoodsModelUserModel2基础模型在tp中实例化模型主要有两种形式1直接实例化$goodsnew GoodsModel();2快速实例化$goodsD(‘Goods’);tp 中实例化模型的四种方式1直接实例化用户自定义模型2快速实例化用户自定义模型3直接实例化基础模型4快速实例化基础模型5、CURD操作?创建操作Create?读取数据Read?更新数据Update?删除数据Delete1创建操作$adminnew AdminModel();$rowarray(‘name’‘zhangsan’,‘age’30 );$admin-add($row);2更改操作$adminnew AdminModel();$dataarray();$admin-save($data);3删除操作$adminnew AdminModel();$admin-delete(‘4,5,6’)4查询操作select();查询多条数据时使用结果永远是一个二维数组即使结果只有一条数据find();永远返回一条数据所以返回值是一个一维数组运行6、字段缓存当实例化模型对象时会自动将这个对应的表中的字段信息缓存下来?字段缓存保存在Runtime/Data/_fields/ 目录下面?只要是不开启调试模式都会生成字段缓存字段缓存可以单独设置关闭。?可以通过设置DB_FIELDS_CACHE 参数来关闭字段自动缓存?可以在模型类里面手动定义数据表字段的名称可以避免IO加载的效率开销在模型类里面添加fields属性即可7、字段定义在子类模型中使用以下属性定义表中所有字段信息语法?protected $fieldsarray(‘id’,‘username’,‘password’,‘_pk’‘id’,‘_autoinc’true);模型定义字段时是定义在子类模型中但如果实例化父类模型那么程序还会重新解析表结构。如果使用定义字段功能那么实例化时必须使用子类模型。8、创建数据ThinkPHP可以帮助你快速地创建数据对象最典型的应用就是自动根据表单数据创建数据对象这个优势在一个数据表的字段非常之多的情况下尤其明显。语法?从表单中创建数据$User-create();?从数组中创建数据$User-create($data);控制器当对象调用create方法时这个方法默认会从$_POST获取数据再将这个数据放在$category对象的data属性中当对象调用add方法时如果没有向函数传递参数那么会自动从这个对象data属性中读取数据并完成录入。create方法的本质是从一个数组中创建数据。如果一个表单以get形式提交数据我们也想使用创建数据的功能可以使用$category-create($_GET);创建数据功能必须依赖一个条件表单中元素的名字必须和数据表中的名字保持一致但这样一来会在客户端源文件暴露数据表结构的真实字段名如何解决9、字段映射ThinkPHP的字段映射功能可以让你在表单中隐藏真正的数据表字段而不用担心放弃自动创建表单对象的功能语法protected $_map array(‘name?? ‘username,‘pwd’ ‘userpwd’‘假名’ ‘真名’);模型字段映射原理$data $User-parseFieldsMap($data);可以看出如果type的值为1表示将真名元素转为假名元素如果type的值为0表示将假名元素转为真名元素10、表名操作在一个数据库中如果部署了多个项目那么我们可以使用表前缀解决问题‘DB_PREFIX ‘think_’tp中默认的表前缀是think_如数据库表名我们接下来需要在配置文件config.php中添加以下选项项目就可以正常工作。tableName如数据表名是sp_categorys但是这个表对应的模型是 CategoryModel那么我不想改动文件名和类的前提下还想使用这个模型。trueTableName如所有数据表的表前缀是sp但某个表没有表前缀如表名goods而不是sp_goods。在子类模型中添加trueTableName属性表示是数据库的真实表名11、事务处理在tp中模型对象使用以下三个方法实现事务处理?$User-startTrans() 开启事务?$User-commit()? 提交事务?$User-rollback()? 回滚事务什么情况下使用事务要么都成功要么都失败程序有一个文件里面保存上百个人员的信息我们需要使用php程序对文件中的人员信息入库。12、ActiveRecord简称AR模式AR模式的核心1将数据表映射到类2将字段映射到类属性3将数据映射到类对象class Goods{private $id;private $name;private $content;public function __set($name,$value){$this-$name$value;}public function __get($name){return $this-$name;}public function insert(){$sql”insert into goods values(null,‘$this-name’,’$this-content’)”;}public function fetch($id){$sql”select * from goods where id’$id’”;$row$db-query($sql);$this-id$row[‘id’];$this-name$row[‘name’];}}$goodsnew Goods();$goods-name’’;$goods-content’’;$goods-insert();--------------------------------------------------------------------$goodsnew Goods();$goods-id8;$goods-delete();$goodsnew Goods();$goods-fetch(8);echo $goods-name;TP中AR模式1增加数据?$User??M(User);??$User-name??ThinkPHP;?$User-email??ThinkPHPgmail.com;?$User-add();2修改数据?$User-find(1);??$User-name??TOPThink;??$User-save();?3删除数据?$User-delete(8);?4查询数据?$User??M(User);??$User-find(8);?echo?$User-name;?echo?$User-email;TP中AR模式的原理我们可以看到在这几个操作时直接对对象的属性赋值如$category-name’abc’但$category对象下并没有这些属性。原因魔术方法。下面我们一起看一下父类Model中的魔术方法可以看出当我们为某个对象的属性进行赋值时会自动执行__set方法这个方法将这个传递过来的属性名保存在当前对象的data属性数组中并赋值当对对象取值会自动执行__get方法首先判断当前对象data属性数组中是否有这个元素如果有返回它的值否则返回null,综上所述我们为对象赋值的属性和值都是存储在当前对象$data属性中.add方法举例可以看出如果我们之前调用add方法时没有传递参数data会首先判断data是否为空如果为空再判断当前对象下data属性是否不为空如果不为空将$this-data属性数组中的值赋值给参数data.13、联贯操作?where?order?limit?field?group语法$对象-方法1()-方法2()-方法n()-select();以上方法在使用时没有顺序上的要求但是最后的方法必须是select();14、统计查询?count 查询数据总行数?max 取最大值?min 取最小值?avg 平均值?sum 求和以上方法与select或find方法平级的方法五、实用项1、设置trace信息1开启调试模式2开启跟踪信息机制config.php配置文件2、session和cookie在tp中它又封装了一些方法用于操作session和cookie1session相关方法?session(name,value);? 添加一个新的session并赋值?$value session(name); 获取指定的session的值?session(name,null); 删除指定的session的值?session(null); 清空所有session的值?session(?name); 判断指定的session是否存在在tp中,session机制默认是开启的可以通过更改配置文件来控制2cookie的相关方法cookie(name,value);? 添加一个新的cookie并赋值cookie(name,value,3600); 添加一个新的cookie并赋值同时指定有效期$value cookie(name); 获取指定cookie的值cookie(name,null); 删除指定cookie的值session案例项目登录案例在项目中添加公共控制器CommonAction用于验证session登录以后所有需要验证的模块的控制器都继承这个公共控制器。3、文件载入1函数文件1common.phpCommon/common.php文件位置文件内容引用函数如果关闭调试模式我们发现在common.php文件中定义的函数会被写入到runtime.php文件中。下次执行时会直接从runtime.php文件中查找并执行也就是说如果函数文件common.php发生改变用户不会看到最新结果。2config.phpLOAD_EXT_FILE“user”文件位置文件内容配置文件我们在Common目录下创建其它函数文件在程序中如果直接使用发现调用了未定义函数说明Common目录下的文件除了common.php之外都不会被自动加载。我们可这样做修改配置文件添加配置选项LOAD_EXT_FILE’引用文件的列表’这样就可以程序中直接使用函数了同时我们可以看出使用这个方法加载的函数不会被写入到runtime.php文件中所以函数的内容发生改变后用户可以立即看到最新结果。Common/user.php文件位置程序这种方式的好处在于需要使用什么样的文件就去载入哪个文件而不需要每次载入多余的文件。2类文件1import(‘ORG.Util.User’);ORG/Util/User.class.php文件位置控制器运行2import(‘.Common.User’);Lib/Common/User.class.php文件位置控制器总结将自定义类文件放在tp框架中使用import(‘ORG.Util.User’);将自定义类文件放在项目中使用import (‘.Common.User’);4、验证码在tp框架程序中有一个文件如下图所示Image.class.php可以帮助我们实现验证码的输出功能Image类的使用方式1在用户控制器UserAction中添加一个动作用于显示验证码2修改模板中的验证码图片加载路径让路径指向上个控制器中的方法3运行程序并输入验证码4对用户输入的验证码进行校验注意Image类在保存session验证码时使用了md5加密所以用户输入的验证码在判断时也需要使用md5加密再进行比较同时Image类也提供了方法可以输出中文验证码1先将simhei.ttf字体库文件从fonts文件夹复制到与Image类同级目录下2创建控制器动作用于显示中文验证码3显示与验证与上题相同5、数据分页1在tp中有一个类Page.class.php可以实现数据分页功能2具体步骤?$User??D(“User”);?$count? $User-count();?$page? new Page($count,25);?$show? $Page-show();?$list $User-limit($Page-firstRow.,.$Page-listRows)-select();?$this-assign(list,$list);?$this-assign(page,$show);?$this-display();代码模板运行3可以通过分页对象的setConfig方法改变分页样式?setConfig?header?prev?next?first?last在setConfig方法中可以直接修改分页对象的config属性数组我们可以在分页对象调用show方法之前通过setConfig修改文字样式。