ThinkPHP笔记

  • 作者: 溪水清澈

    类文件都是以.class.php为后缀
    在调试模式下面,即使在Windows平台也会严格检查大小写
    类名和文件名一致
    数据表和字段采用小写加下划线方式命名
    
    行为: 到底是什么?
    行为可以说是一个中间接口, 
    行为中保存了行为的名字, 和这个名字相对应的操作,
    当准备执行这个行为的时候, 举例如下: 
    class Behavior
    {
    	static $callStaticMap = array( 
    		'checkLogin' => 'CheckLoginBehavior' );
    		
    	static public function __callStatic( $name, $args )
    	{
    		if ( isset( self :: $callStaticMap [ $name ] ) )
    		{
    			$object = new self :: $callStaticMap[ $name ];
    			call_user_func_array( $object, $args );
    		}
    	}
    
    }
    
    class CheckLoginBehavior
    {
    	public function run( $args )
    	{
    		//行为要处理的事情
    	}
    }
    当执行语句
    Behavior :: checkLogin();
    时, 就会去执行CheckLoginBehavior类的run函数.
    
    
    1. //开启调试模式
    2. define('APP_DEBUG', true);
    
    
    惯例配置->项目配置->调试配置->分组配置->扩展配置->动态配置
    以上是配置文件的加载顺序,因为后面的配置会覆盖之前的同名配置
    
    配置参数不区分大小写(因为无论大小写定义都会转换成小写)
    需要注意的是,二级参数配置区分大小写,也就说读取确保和定义一致。
    
    注意在地址栏中输入控制名的时候的大小写, 
    要和文件名的大小写一致.
    
    
    'LOAD_EXT_CONFIG' => 'user,db', // 加载扩展配置文件
    C('USER_AUTH_ID');
    
    如果希望采用二级配置方式,可以设置如下: 
    	1. 'LOAD_EXT_CONFIG' => array(
    	2. 'USER' => 'user', //用户配置
    	3. 'DB' => 'db', //数据库配置
    	4. ), //加载扩展配置文件
    C('USER.USER_AUTH_ID');
    
    单字母大写方法:
    A($p)	<==> new ($p . Action) () 
    B	执行行为, 具体意思是?
    C	Config
    D	快速实例化自定义模型, 第一参数是表名, 第二参数是类后缀名, 默认为Model
    F	简单缓存
    G	记录时间标签
    L	语言变量
    M	new Model;快速实例化基础模型类, 参数是除去表前缀的表名
    N	统计数据
    R	调用模块的方法, A($p) -> 方法()
    S	缓存方法
    U	生成URL
    W	Widget, 在模板中调用 {:W('名字')}
    
    函数库: (另见下面的分组)
    系统函数库, 系统Common目录下,
    common.php  自动加载
    functions.php  一般是自动加载(什么是不一般?)
    runtime.php  调试和编译时加载, 别的时候不加载
    
    项目函数库, 项目的Common目录下,
    common.php 自动加载,并编译到缓存中
    分组名/function.php  根据分组自动加载(注意后面没有s)
    
    扩展函数库, 项目的Common目录下, 文件名随意, 不自动加载
    加载方式:
    	1. 在配置文件中设置:
    "LOAD_EXT_FILE" => "不带.php后缀的文件名,..."
    在逗号前后不能有空格
    	2. load( '@.不带.php后缀的文件名' )
    
    import导入类库
    import( 'Think.Util.Session' ) //系统类库
    import( 'ORG.Util.Page' ) //系统类库
    import( '项目名.Action.自定义Action类名' )
    import( '项目名.Model.自定义Model类名' )
    项目名可以用@来代表当前项目
    import( '@.Model.MyModel' );
    类名中有点号的话, 把点用#代替
    
    真是他喵的没事找事, 
    人家Java系统本身就是用点来分隔各个包的, 
    一味的模仿有毛用啊, 不知道结合实际.
    PHP决定用\来分割命名空间, 
    为什么不用这个来做导入类的分割符?
    
    导入第三方类库
    vendor( '类路径.路径. ... .类名' )
    实际上还是调用import了, 
    不过是把第二个参数如果是空的话 替换成VENDOR常量的值
    
    自动加载优先级, 上 => 下 高 => 低
    类名	规则	说明
    行为类 	规则1	搜索系统类库目录下面的Behavior目录 
    	规则2	搜索系统扩展目录下面的Behavior目录 
    	规则3	搜索应用类库目录下面的Behavior目录 
    	规则4	如果启用了模式扩展,则搜索模式扩展目录下面的Behavior目录 
    模型类 	规则1	如果启用分组,则搜索应用类库目录的Model/当前分组 目录 
    	规则2	搜索应用类库下面的Model目录 
    	规则3	搜索系统扩展目录下面的Model目录 
    控制器类 	规则1	如果启用分组,则搜索应用类库目录的Action/当前分组 目录 
    	规则2	搜索项目类库目录下面的Action目录 
    	规则3	搜索系统扩展目录下面的Action目录 
    
    自定义路径自动加载
    'APP_AUTOLOAD_PATH' =>'@.Common,@.Tool',
    
    分组:
    项目目录	分组(以Home和Admin分组为例)	不分组
    公共目录	Home分组:Common/Home/function.php	Common/common.php
    (Common)	Admin分组:Common/Admin/function.php
    	公共文件:Common/common.php
    配置目录	Home分组:Conf/Home/config.php	Conf/config.php
    (Conf)	Admin分组:Conf/Admin/config.php
    	公共配置:Conf/config.php
    Action目录	Home分组:Lib/Action/Home/	Lib/Action/
    	Admin分组:Lib/Action/Admin/
    	公共Action:Lib/Action/
    Model 目录	Lib/Model/	Lib/Model/
    此目录也可以分组,
    分组以后,
    优先使用分组目录中的类.
    语言包目录	Home分组:Lang/zh-cn/Home/lang.php	Lang/zh-cn/common.php
    (Lang 以zh-cn为例)	Admin分组:Lang/zh-cn/Admin/lang.php
    	公共语言包:Lang/zh-cn/common.php
    模板目录	Home分组:Tpl/Home/theme/	Tpl/theme/
    (Tpl以theme主题为例)	Admin分组:Tpl/Admin/theme/
    运行时目录(Runtime)	Home分组:Runtime/Home/	Runtime/
    	Admin分组:Runtime/Admin/
    
    伪静态后缀
    如果URL_HTML_SUFFIX为空, 
    那么任何后缀都可以使用,
    如果配置了URL_HTML_SUFFIX的值, 
    那么只能使用这些配置的值.
    'URL_HTML_SUFFIX'=>'(shtml|html|xml)'
    
    URL路由
    在项目配置文件中设置, 在分组配置文件中貌似不好使
    例如:
    'Home/Abc/:m/:a' => 'Home/:1/:2'
    :1 = :m
    :2 = :a
    正则路由比较不错的说.
    在这儿发现PHP正则的一个用法 e 模式
    
    
    URL生成
    在模板中是 {:U( 参数 )}
    域名使用:
    U( 'Blog/read@blog.thinkphp.cn?username=xxx' );
    
    URL大小写
    'URL_CASE_INSENSITIVE' =>true
    区分大小写时, 在URL中按文件名大小写来定
    
    有类为 UserType
    区分大小写时, URL为: UserType
    不区分大小写, URL为: user_type
    
    跨模块调用
    $user = A( 'Admin://Tool/User' )
    Admin项目的Tool分组的User模块
    如果启用分组, 要把分组名给写上, 
    不然, 貌似不好使啊.
    
    真是麻烦, 把文件名命名规则直接改成全小写,
    不就行了, ?还用得着这么麻烦么
    想出英文字母区分大小写的人, 
    真是脑袋被驴踢了.
    
    获得超全局变量
    $this -> _get( 名字, 过滤器 );
    这个方法的好处是能过滤数据
    过滤器不写, 会使用 DEFAULT_FILTER
    过滤器为false, 不过滤.
    
    参数绑定
    在方法中, 可以指定形参数, 
    这样在程序执行时, 会直接把浏览器传递过来的参数给方法.
    
    多层控制器, 控制器分层
    在TP中, 看着以Actoin结尾实在不爽, 
    改造, 必须改造
    在Common/common.php中,
    import( '@.Common.Controller' );
    在项目目录下面建一个Common/Controller.class.php
    内容为:
    class Controller extends Action
    {}
    
    在配置文件中写入:
    'DEFAULT_C_LAYER'       =>  'Controller',
    'ACTION_SUFFIX'         =>  'Action',
    
    模型, 三个属性
    tableName
    trueTableName
    dbName
    tablePrefix
    
    在模型中自定义表结构
    protected $fields = array(
    	..., 
    	'_pk' => '...', 
    	'_autoinc' => true/false);
    
    使用PDO
    'DB_TYPE' => 'pdo',
    'DB_DSN' => 'pdo的dsn',
    给$connection 属性赋值, 可以自定义数据库连接信息, 
    格式同配置文件
    
    创建数据
    create(), 其中有一些验证功能
    data(), 没有验证, 只是简单的赋值.
    
    字段映射
    protected $_map = array(
    	表单名 => 数据库字段,
    	假名   => 真名, 
    	);
    
    连贯操作
    $User->where('status=1')->order('create_time')->limit(10)->select();
    
    下面这样也行, 等同上面.
    $User->select(array('order'=>'create_time','where'=>'status=1','limit'=>'10'));
    连贯操作	作用	支持的参数类型
    where	用于查询或者更新条件的定义	字符串、数组和对象
    table	用于定义要操作的数据表名称(真表名)	字符串和数组
    alias	用于给当前数据表定义别名	字符串
    data	用于新增或者更新数据之前的数据对象赋值	数组和对象
    field	用于定义要查询的字段(2参为字段排除)	字符串和数组
    order	用于对结果排序	字符串和数组
    limit	用于限制查询结果数量	字符串和数字
    page	用于查询分页(内部会转换成limit)	字符串和数字
    group	用于对查询的group支持	字符串
    having	用于对查询的having支持	字符串
    join*	用于对查询的join支持	字符串和数组
    union*	用于对查询的union支持	字符串、数组和对象
    distinct	用于查询的distinct支持	布尔值
    lock	用于数据库的锁机制	布尔值
    cache	用于查询缓存	支持多个参数
    relation	用于关联查询(需要关联模型支持)	字符串
    
    getField()
    setField()
    setField( 'id', 'id + 100' ); //可以这样的哦.
    setInc(), setDec()
    getBy字段名(字段值)
    比如有个字段叫 first_name, 要查询这个字段的值为UA的记录,
    getByFirstName( 'UA' ), 或
    getByfirst_name( 'UA' ), 这样就OK了.
    
    $_validate 自动验证字段, 对表单中的数据进行验证, 不是数据哦. //TODO: 未测试成功
    array(验证字段,验证规则,错误提示,[验证条件,附加规则,验证时间])
    举例:
    protected $_validate = array(
    	array('verify','require','验证码必须!'), //默认情况下用正则进行验证
    	array('name','','帐号名称已经存在!',0,'unique',1), // 在新增的时候验证name字段是否唯一
    	array('value',array(1,2,3),'值的范围不正确!',2,'in'), // 当值不为空的时候判断是否在一个范围内
    	array('repassword','password','确认密码不正确',0,'confirm'), // 验证确认密码是否和密码一致
    	array('password','checkPwd','密码格式不正确',0,'function'), // 自定义函数验证密码格式
    );
    
    字段排除
    field( '字段1, 字段2, ...' , 排除? );
    
    只是需要一个模型类, 又不想连接数据库, 那么可以:
    class UserModel extends Model
    {
    	protected $autoCheckFields = false;
    }
    
    模型分层, 和控制器分层一个样.
    
    模板
    在模板中, 可以混用php和TP的标签,
    通过assign赋值的变量, 可以直接使用, 前面不用加$this
    因为在解析模板以前, 会将这些变量进行extract入当前空间.
    'TMPL_ENGINE_TYPE'     => 'Smarty',
    
    系统模板变量
    $Think //注意首字母大写
    
    函数
    {$var|func1=arg1,arg2,###|func2|...}
    执行函数并输出返回值:
    {:func(arg...)}  //编译以后代码是 <?php echo func(...);?>
    执行不输出:
    {~func(...)} //编译以后代码是 <?php func(...);?>
    
    默认值:
    {$def|default='这家伙真懒'}
    <?php echo (($def)?($def):'这家伙真懒'); ?>
    
    导入外部文件
    <import type='类型, 就是后缀' file='不带后缀名' />
    <load href='路径, 通过后缀判定导入什么文件' />
    
    <include file='路径' />
    include如果使用相对路径的话,是基于项目的入口文件位置。
    
    模板布局 ???//TODO: OK
    <layout name='布局文件路径, 无后缀' />
    布局文件当前目录在分组模板目录中. 
    布局文件路径是相对当前目录而言的.
    
    模板继承, OK
    <extend name='xxx' />
    <block name='yyy' >...</block>
    
    注释:
    {// ... }
    {/* ... */}
    
    缓存
    $cache = Cache :: getInstance( 'file', array( 'expire' => 60 ) );
    建立一个60秒的文件缓存, 默认是无限时间.
    $cache -> set( 'name', 'value' );
    保存name到缓存中, 值为value,
    会在runtime文件夹下面建立一个以md5( 'name' ) . '.php' 为名的文件, 
    保存的就是值 value
    
    单字母函数S也是缓存函数的简写.
    F( 'name', 'value') 是简单缓存函数,
    文件名就是 name,
    文件内容是 var_export( 'value' )输出的值.
    
    行为扩展
    执行方式:
    	1. 在tags.php中定义, 哪个标签对应哪个行为.
    	注意tags.php中, 配置是二维数据哦.
    	2. B( 不带behavior后缀的类名 )
    	3. add_tag_behavior( '标签', '不带behavior后缀的类名' )
    
    标签库扩展
    注意标签的闭合选项, close=0, 闭合(类似 <br />)
    
    Widget扩展
    定义一个public function render( $data )
    {
     //返回字符串, 这个Widget可以有自己的模板
        $content = $this -> renderFile() ;
    	// 默认是在 Widget/本类名/本类名.html
    	$content = $this -> renderFile( 'article/show' );
    	// 此文件是在 Widget/本类名/article/show.html
    	//Widget扩展需要返回才可以显示出来
    	return $content;
    }
    
    表单令牌: 默认貌似是关的
    'TOKEN_ON' => true,
    
    查询条件预处理
    $Model->where("id=%d and username='%s' and xx='%f'",array($id,$username,$xx))->select();
    
    防sql注入的一种方式, 
    使用sprintf 函数组织sql语句
    
    性能
    	1. 关闭调试模式
    	2. 开启缓存, APC/XCACHE
    	3. 合并字段缓存, 把 字段文件合进MODEL里面.
    	4. 替换入口, 把index.php替换成~runtime.php(当然, 名字是要改的)
    	5. 优化SQL, 
    	下面是一部分比较重要的建议:
    	1、选择正确的存储引擎
    	以 MySQL为例,包括有两个存储引擎 MyISAM 和 InnoDB,每个引擎都有利有弊。
    	MyISAM 适合于一些需要大量查询的应用,但其对于有大量写操作并不是很好。甚至你只是需要update一个字段,整个表都会被锁起来,而别的进程,就算是读进程都无法操作直到读操作完成。另外,MyISAM 对于 SELECT COUNT(*) 这类的计算是超快无比的。
    	InnoDB 的趋势会是一个非常复杂的存储引擎,对于一些小的应用,它会比 MyISAM 还慢。但是它支持“行锁” ,于是在写操作比较多的时候,会更优秀。并且,他还支持更多的高级应用,比如:事务。
    	2、优化字段的数据类型
    	记住一个原则,越小的列会越快。对于大多数的数据库引擎来说,硬盘操作可能是最重大的瓶颈。所以,把你的数据变得紧凑会对这种情况非常有帮助,因为这减少了对硬盘的访问。
    	如果一个表只会有几列罢了(比如说字典表,配置表),那么,我们就没有理由使用 INT 来做主键,使用 MEDIUMINT, SMALLINT 或是更小的 TINYINT 会更经济一些。如果你不需要记录时间,使用 DATE 要比 DATETIME 好得多。当然,你也需要留够足够的扩展空间。
    	3、为搜索字段添加索引
    	索引并不一定就是给主键或是唯一的字段。如果在你的表中,有某个字段你总要会经常用来做搜索,那么最好是为其建立索引,除非你要搜索的字段是大的文本字段,那应该建立全文索引。
    	4、避免使用Select *从数据库里读出越多的数据,那么查询就会变得越慢。并且,如果你的数据库服务器和WEB服务器是两台独立的服务器的话,这还会增加网络传输的负载。即使你要查询数据表的所有字段,也尽量不要用*通配符,善用内置提供的字段排除定义也许能给带来更多的便利。
    	5、使用 ENUM 而不是 VARCHAR
    	ENUM 类型是非常快和紧凑的。在实际上,其保存的是 TINYINT,但其外表上显示为字符串。这样一来,用这个字段来做一些选项列表变得相当的完美。例如,性别、民族、部门和状态之类的这些字段的取值是有限而且固定的,那么,你应该使用 ENUM 而不是 VARCHAR。
    	6、尽可能的使用 NOT NULL
    	除非你有一个很特别的原因去使用 NULL 值,你应该总是让你的字段保持 NOT NULL。 NULL其实需要额外的空间,并且,在你进行比较的时候,你的程序会更复杂。 当然,这里并不是说你就不能使用NULL了,现实情况是很复杂的,依然会有些情况下,你需要使用NULL值。
    	7、固定长度的表会更快
    	如果表中的所有字段都是“固定长度”的,整个表会被认为是 “static” 或 “fixed-length”。 例如,表中没有如下类型的字段: VARCHAR,TEXT,BLOB。只要你包括了其中一个这些字段,那么这个表就不是“固定长度静态表”了,这样,MySQL 引擎会用另一种方法来处理。
    	固定长度的表会提高性能,因为MySQL搜寻得会更快一些,因为这些固定的长度是很容易计算下一个数据的偏移量的,所以读取的自然也会很快。而如果字段不是定长的,那么,每一次要找下一条的话,需要程序找到主键。
    	并且,固定长度的表也更容易被缓存和重建。不过,唯一的副作用是,固定长度的字段会浪费一些空间,因为定长的字段无论你用不用,他都是要分配那么多的空间。
    	使用“垂直分割”技术,你可以分割你的表成为两个一个是定长的,一个则是不定长的。
    	8、垂直分割“垂直分割”是一种把数据库中的表按列变成几张表的方法,这样可以降低表的复杂度和字段的数目,从而达到优化的目的。
    	例如:在User表中有一个字段是家庭地址,这个字段是可选字段,相比起,而且你在数据库操作的时候除了个人信息外,你并不需要经常读取或是改写这个字段。那么,为什么不把他放到另外一张表中呢? 这样会让你的表有更好的性能,大家想想是不是,大量的时候,我对于用户表来说,只有用户ID,用户名,口令,用户角色等会被经常使用。小一点的表总是会有好的性能。
    	另外,你需要注意的是,这些被分出去的字段所形成的表,你不会经常性地去Join他们,不然的话,这样的性能会比不分割时还要差,而且,会是极数级的下降。
    	9、EXPLAIN 你的 SELECT 查询;
    	使用 EXPLAIN 关键字可以让你知道MySQL是如何处理你的SQL语句的。这可以帮你分析你的查询语句或是表结构的性能瓶颈。EXPLAIN 的查询结果还会告诉你你的索引主键被如何利用的,你的数据表是如何被搜索和排序的……等等,等等。
    	通常我们可以对比较复杂的尤其是涉及到多表的SELECT语句,把关键字EXPLAIN加到前面。你可以使用phpmyadmin来做这个事。
    


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值